Улучшите и защитите интеграцию между облаками

1. Прежде чем начать

Интеграция между облачными сервисами использует типы устройств , чтобы сообщить Google Ассистенту, какую грамматику следует использовать с данным устройством. Характеристики устройства определяют возможности типа устройства. Устройство наследует состояния каждой характеристики устройства, добавленной в интеграцию.

dc8dce0dea87cd5c.png

Вы можете связать любые поддерживаемые характеристики с выбранным типом устройства, чтобы настроить функциональность устройств ваших пользователей. Если вы хотите реализовать в своих действиях пользовательские характеристики, которые в настоящее время недоступны в схеме устройства, то характеристики «Режимы» и «Переключатели» позволяют управлять определенными настройками с помощью заданного вами пользовательского имени.

Помимо базовых возможностей управления, предоставляемых типами и характеристиками, API Smart Home имеет дополнительные функции для улучшения пользовательского опыта. Ответы об ошибках предоставляют подробную обратную связь пользователю, когда намерения не выполняются. Дополнительная проверка пользователя расширяет эти ответы и добавляет дополнительную безопасность к выбранной вами характеристике устройства. Отправляя конкретные ответы об ошибках на блоки проверки, выдаваемые Google Ассистентом, ваша интеграция «облако-облако» может потребовать дополнительной авторизации для выполнения команды.

Предварительные требования

Что вы построите

В этом практическом занятии вы развернете готовую интеграцию умного дома с Firebase, а затем научитесь добавлять нестандартные характеристики к стиральной машине, такие как размер загрузки и турбо-режим. Вы также реализуете отчеты об ошибках и исключениях и научитесь требовать голосового подтверждения для включения стиральной машины с помощью дополнительной проверки пользователя.

Что вы узнаете

  • Как добавить свойства «Режимы» и «Переключатели» в вашу интеграцию
  • How to report errors and exceptions
  • Как применить дополнительную проверку пользователя

Что вам понадобится

2. Начало работы

Включить элементы управления активностью

Для использования Google Ассистента необходимо передавать Google определенные данные о действиях. Google Ассистент нуждается в этих данных для корректной работы; однако требование о передаче данных не является специфическим для SDK. Чтобы передать эти данные, создайте учетную запись Google , если у вас ее еще нет. Вы можете использовать любую учетную запись Google — это не обязательно должна быть ваша учетная запись разработчика.

Откройте страницу «Управление действиями» для учетной записи Google, которую вы хотите использовать с Ассистентом.

Убедитесь, что следующие переключатели включены:

  • Активность в Интернете и приложениях — Кроме того, обязательно установите флажок « Включать историю и активность Chrome с сайтов, приложений и устройств, использующих сервисы Google» .
  • Информация об устройстве
  • Голосовая и аудиоактивность

Создайте проект интеграции между облачными сервисами.

  1. Перейдите в консоль разработчика .
  2. Нажмите «Создать проект» , введите название проекта и нажмите «Создать проект» .

Название проекта

Выберите интеграцию «облако-облако».

На главной странице проекта в консоли разработчика выберите пункт «Добавить интеграцию между облаками» в разделе «Интеграция между облаками» .

Добавьте интеграцию между облачными сервисами.

Установите Firebase CLI.

Интерфейс командной строки Firebase (CLI) позволит вам запускать веб-приложения локально и развертывать их на хостинге Firebase.

Для установки CLI выполните следующую команду npm в терминале:

npm install -g firebase-tools

Чтобы убедиться в правильности установки интерфейса командной строки, выполните следующую команду:

firebase --version

Для авторизации Firebase CLI используйте свою учетную запись Google, выполнив следующую команду:

firebase login

Добавьте Firebase в свой проект в консоли разработчика Google Home.

Способ 1: Через консоль Firebase

  1. Перейдите на сайт Firebase .
  2. Нажмите «Создать проект Firebase» .
    Создать проект Firebase
  3. На экране «Создать проект» нажмите «Добавить проект Firebase в Google Cloud» .
    Добавить Firebase в проект Google Cloud
  4. На экране «Начало работы» выберите проект Google Cloud, который вы только что создали в консоли разработчика Google Home, а затем нажмите «Продолжить» .
    Выберите проект Google Cloud

Метод 2: Через интерфейс командной строки Firebase

firebase projects:addfirebase

Выберите проект Google Home Developer Console, который вы только что создали, чтобы добавить Firebase.

После добавления Firebase в ваш проект в консоли разработчика Google Home, он отобразится в консоли Firebase. Идентификатор проекта Firebase будет совпадать с идентификатором вашего проекта в консоли разработчика Google Home.

Добавлен облачный проект.

Включите API HomeGraph

API HomeGraph позволяет хранить и запрашивать информацию об устройствах и их состояниях в рамках пользовательского HomeGraph. Для использования этого API необходимо сначала открыть консоль Google Cloud и включить API HomeGraph .

В консоли Google Cloud убедитесь, что выбран проект, соответствующий вашему Actions <firebase-project-id>. Затем на экране библиотеки API для HomeGraph API нажмите «Включить» .

ee198858a6eac112.png

3. Запустите стартовое приложение.

Теперь, когда вы настроили среду разработки, вы можете развернуть стартовый проект, чтобы убедиться в правильности всех настроек.

Получите исходный код

Чтобы загрузить пример этого практического задания на свой компьютер, перейдите по следующей ссылке:

...или вы можете клонировать репозиторий GitHub из командной строки:

git clone https://github.com/google-home/smarthome-traits.git

Распакуйте загруженный zip-файл.

О проекте

Стартовый проект содержит следующие подкаталоги:

  • public: Пользовательский интерфейс для удобного управления и мониторинга состояния умной стиральной машины.
  • functions: Полностью реализованный облачный сервис, управляющий интеллектуальной стиральной машиной с помощью Cloud Functions for Firebase и Firebase Realtime Database.

Предоставляемое облачное решение включает следующие функции в index.js :

  • fakeauth : Конечная точка авторизации для привязки учетных записей
  • faketoken : Конечная точка для ввода токена при привязке учетной записи
  • smarthome : Конечная точка выполнения намерений в системе умного дома
  • reportstate : Вызывает API Home Graph при изменении состояния устройства.
  • requestsync : Позволяет обновлять устройства пользователей без необходимости повторной привязки учетной записи.

Подключитесь к Firebase

Перейдите в каталог washer-start , затем настройте Firebase CLI для вашего проекта интеграции:

cd washer-start
firebase use <project-id>

Настройка проекта Firebase

Инициализируйте проект Firebase.

firebase init

Выберите функции командной строки, базу данных реального времени и функцию «Функции» .

? Which Firebase features do you want to set up for this directory? Press Space to select features, then Enter
 to confirm your choices. (Press <space> to select, <a> to toggle all, <i> to invert selection, and <enter> to
 proceed)
>( ) Data Connect: Set up a Firebase Data Connect service
 ( ) Firestore: Configure security rules and indexes files for Firestore
 ( ) Genkit: Setup a new Genkit project with Firebase
 (*) Functions: Configure a Cloud Functions directory and its files
 ( ) App Hosting: Configure an apphosting.yaml file for App Hosting
 ( ) Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys
 ( ) Storage: Configure a security rules file for Cloud Storage
 ( ) Emulators: Set up local emulators for Firebase products
 ( ) Remote Config: Configure a template file for Remote Config
 ( ) Extensions: Set up an empty Extensions manifest
 (*) Realtime Database: Configure a security rules file for Realtime Database and (optionally) provision
default instance
 ( ) Data Connect: Set up a Firebase Data Connect service
 ( ) Firestore: Configure security rules and indexes files for Firestore

Это инициализирует необходимые API и функции для вашего проекта.

При появлении запроса инициализируйте базу данных Realtime Database. Вы можете использовать местоположение экземпляра базы данных по умолчанию.

? It seems like you haven't initialized Realtime Database in your project yet. Do you want to set it up?
Yes

? Please choose the location for your default Realtime Database instance:
us-central1

Поскольку вы используете код стартового проекта, выберите файл правил безопасности по умолчанию и убедитесь, что вы не перезаписываете существующий файл правил базы данных.

? File database.rules.json already exists. Do you want to overwrite it with the Realtime Database Security Rules for <project-ID>-default-rtdb from the Firebase Console?
No

При повторной инициализации проекта выберите «Перезаписать» , когда появится запрос о том, хотите ли вы инициализировать или перезаписать код.

? Would you like to initialize a new codebase, or overwrite an existing one?
Overwrite

При настройке функций следует использовать файлы по умолчанию и убедиться, что вы не перезаписываете существующие файлы index.js и package.json в примере проекта.

? What language would you like to use to write Cloud Functions?
JavaScript

? Do you want to use ESLint to catch probable bugs and enforce style?
No

? File functions/package.json already exists. Overwrite?
No

? File functions/index.js already exists. Overwrite?
No

Если вы выполняете повторную инициализацию проекта, выберите «Нет», когда вас спросят, хотите ли вы инициализировать или перезаписать файл functions/.gitignore.

? File functions/.gitignore already exists. Overwrite?
No
? Do you want to install dependencies with npm now?
Yes

Если ESLint был случайно включен, есть два способа его отключить:

  1. С помощью графического интерфейса перейдите в папку ../functions внутри проекта, выберите скрытый файл .eslintrc.js и удалите его. Не путайте его с файлом .eslintrc.json имеющим аналогичное имя.
  2. Использование командной строки:
    cd functions
    rm .eslintrc.js
    

Развернуть в Firebase

Теперь, когда вы установили зависимости и настроили свой проект, вы готовы запустить приложение в первый раз.

firebase deploy

Вот что вы должны увидеть в консоли:

...

✔ Deploy complete!

Project Console: https://console.firebase.google.com/project/<project-id>/overview
Hosting URL: https://<project-id>.web.app

Эта команда развертывает веб-приложение, а также несколько облачных функций для Firebase .

Откройте URL-адрес хостинга в браузере ( https://<firebase-project-id>.web.app ), чтобы просмотреть веб-приложение. Вы увидите следующий интерфейс:

5845443e94705557.png

Этот веб-интерфейс представляет собой стороннюю платформу для просмотра или изменения состояния устройства. Чтобы начать заполнение базы данных информацией об устройстве, нажмите кнопку ОБНОВИТЬ . На странице не будет никаких изменений, но текущее состояние вашей стиральной машины будет сохранено в базе данных.

Теперь пришло время подключить развернутый вами облачный сервис к Google Ассистенту с помощью консоли разработчика .

Настройте свой проект в консоли разработчика.

На вкладке «Разработка» добавьте отображаемое имя для вашего взаимодействия. Это имя будет отображаться в приложении Google Home.

Добавить отображаемое имя

В разделе «Брендинг приложения» загрузите файл png для значка приложения размером 144 x 144 пикселя и назовите его соответствующим образом. .png .

Добавить значок приложения

Для включения функции привязки учетных записей используйте следующие настройки привязки учетных записей:

Идентификатор клиента

ABC123

Секрет клиента

DEF456

URL авторизации

https://us-central1-<project-id>.cloudfunctions.net/fakeauth

URL токена

https://us-central1-<project-id>.cloudfunctions.net/faketoken

Обновите URL-адреса для привязки учетных записей.

В поле «URL-адрес облачного сервиса» введите URL-адрес вашей облачной функции, которая обеспечивает выполнение запросов для функций умного дома.

https://us-central1-<project-id>.cloudfunctions.net/smarthome

Добавить URL-адрес облачной функции

Нажмите «Сохранить» , чтобы сохранить конфигурацию проекта, затем нажмите «Далее: Тестирование» , чтобы включить тестирование в вашем проекте.

Протестируйте интеграцию между облачными сервисами.

Теперь вы можете приступить к реализации веб-хуков, необходимых для связи состояния устройства с Ассистентом.

Для тестирования интеграции между облачными сервисами необходимо связать ваш проект с учетной записью Google. Это позволит проводить тестирование через интерфейсы Google Assistant и приложение Google Home, которые подключены к одной и той же учетной записи.

  1. На телефоне откройте настройки Google Ассистента. Обратите внимание, что вы должны войти в систему под той же учетной записью, что и в консоли.
  2. Перейдите в Google Ассистент > Настройки > Управление домом (в разделе Ассистент).
  3. Нажмите на значок поиска в правом верхнем углу.
  4. Чтобы найти ваше тестовое приложение, используйте префикс [test] .
  5. Выберите этот пункт. Затем Google Ассистент пройдет аутентификацию в вашем сервисе и отправит запрос SYNC , попросив ваш сервис предоставить пользователю список устройств.

Откройте приложение Google Home и убедитесь, что вы видите свою стиральную машину.

ae252220753726f6.png

Убедитесь, что вы можете управлять стиральной машиной с помощью голосовых команд в приложении Google Home. Вы также должны увидеть изменение состояния устройства в веб-интерфейсе вашей облачной службы доставки.

Теперь, когда у вас установлена ​​базовая стиральная машина, вы можете настроить доступные режимы работы вашего устройства.

4. Добавить режимы

Трейт action.devices.traits.Modes позволяет устройству иметь произвольное количество настроек для режима, из которых одновременно можно установить только одну. Вы добавляете режим к стиральной машине, чтобы определить размер загрузки белья: маленький, средний или большой.

Обновить ответ SYNC

Вам необходимо добавить информацию о новом трейте в ответ SYNC в functions/index.js . Эти данные отображаются в массиве traits и объекте attributes , как показано в следующем фрагменте кода.

index.js

app.onSync(body => {
  return {
    requestId: 'ff36a3cc-ec34-11e6-b1a0-64510650abcf',
    payload: {
      agentUserId: USER_ID,
      devices: [{
        id: 'washer',
        type: 'action.devices.types.WASHER',
        traits: [
          'action.devices.traits.OnOff',
          'action.devices.traits.StartStop',
          'action.devices.traits.RunCycle',
          // Add Modes trait
          'action.devices.traits.Modes',
        ],
        name: { ... },
        deviceInfo: { ... },
        attributes: {
          pausable: true,
          //Add availableModes
          availableModes: [{
            name: 'load',
            name_values: [{
              name_synonym: ['load'],
              lang: 'en',
            }],
            settings: [{
              setting_name: 'small',
              setting_values: [{
                setting_synonym: ['small'],
                lang: 'en',
              }]
            }, {
              setting_name: 'medium',
              setting_values: [{
                setting_synonym: ['medium'],
                lang: 'en',
              }]
            }, {
              setting_name: 'large',
              setting_values: [{
                setting_synonym: ['large'],
                lang: 'en',
              }]
            }],
            ordered: true,
          }],
        },
      }],
    },
  };
});

Добавить новые команды выполнения намерений

В вашем интенте EXECUTE добавьте команду action.devices.commands.SetModes , как показано в следующем фрагменте кода.

index.js

const updateDevice = async (execution,deviceId) => {
  ...
  switch (command) {
    ...
    // Add SetModes command
    case 'action.devices.commands.SetModes':
      state = {load: params.updateModeSettings.load};
      ref = getFirebaseRef().child(deviceId).child('Modes');
      break;
}

Обновить ответ на запрос

Далее обновите ответ QUERY , чтобы он сообщал о текущем состоянии стиральной машины.

Внесите обновленные изменения в функции queryFirebase и queryDevice , чтобы получить состояние, хранящееся в базе данных Realtime Database.

index.js

const queryFirebase = async (deviceId) => {
  const snapshot = await getFirebaseRef().child(deviceId).once('value');
  const snapshotVal = snapshot.val();
  return {
    on: snapshotVal.OnOff.on,
    isPaused: snapshotVal.StartStop.isPaused,
    isRunning: snapshotVal.StartStop.isRunning,
    // Add Modes snapshot
    load: snapshotVal.Modes.load,
  };
};

const queryDevice = async (deviceId) => {
  const data = await queryFirebase(deviceId);
  return {
    on: data.on,
    isPaused: data.isPaused,
    isRunning: data.isRunning,
    currentRunCycle: [{ ... }],
    currentTotalRemainingTime: 1212,
    currentCycleRemainingTime: 301,
    // Add currentModeSettings
    currentModeSettings: {
      load: data.load,
    },
  };
};

Обновить отчет о состоянии

Наконец, обновите функцию reportstate , чтобы она передавала в Home Graph текущую загрузку стиральной машины.

index.js

const requestBody = {
  requestId: 'ff36a3cc', /* Any unique ID */
  agentUserId: USER_ID,
  payload: {
    devices: {
      states: {
        /* Report the current state of your washer */
        [context.params.deviceId]: {
          on: snapshot.OnOff.on,
          isPaused: snapshot.StartStop.isPaused,
          isRunning: snapshot.StartStop.isRunning,
          // Add currentModeSettings
          currentModeSettings: {
            load: snapshot.Modes.load,
          },
        },
      },
    },
  },
};

Развернуть в Firebase

Выполните следующую команду, чтобы развернуть обновленную интеграцию:

firebase deploy --only functions

После завершения развертывания перейдите в веб-интерфейс и нажмите кнопку «Обновить». ae8d3b25777a5e30.png Кнопка на панели инструментов. Она запускает запрос на синхронизацию, чтобы помощник получил обновленные данные ответа SYNC .

bf4f6a866160a982.png

Теперь вы можете отдать команду для установки режима работы стиральной машины, например:

«Привет, Google, выбери режим загрузки стиральной машины «Большой».»

Кроме того, вы можете задать вопросы о своей стиральной машине, например:

"Эй, Google, какая загрузка стиральной машины?"

5. Добавить переключатели

Трейт action.devices.traits.Toggles представляет собой именованные аспекты устройства, имеющие состояние true или false, например, находится ли стиральная машина в турбо-режиме.

Обновить ответ SYNC

В ответе SYNC необходимо добавить информацию о новой характеристике устройства. Она появится в массиве traits и объекте attributes , как показано в следующем фрагменте кода.

index.js

app.onSync(body => {
  return {
    requestId: 'ff36a3cc-ec34-11e6-b1a0-64510650abcf',
    payload: {
      agentUserId: USER_ID,
      devices: [{
        id: 'washer',
        type: 'action.devices.types.WASHER',
        traits: [
          'action.devices.traits.OnOff',
          'action.devices.traits.StartStop',
          'action.devices.traits.RunCycle',
          'action.devices.traits.Modes',
          // Add Toggles trait
          'action.devices.traits.Toggles',
        ],
        name: { ... },
        deviceInfo: { ... },
        attributes: {
          pausable: true,
          availableModes: [{
            name: 'load',
            name_values: [{
              name_synonym: ['load'],
              lang: 'en'
            }],
            settings: [{ ... }],
            ordered: true,
          }],
          //Add availableToggles
          availableToggles: [{
            name: 'Turbo',
            name_values: [{
              name_synonym: ['turbo'],
              lang: 'en',
            }],
          }],
        },
      }],
    },
  };
});

Добавить новые команды выполнения намерений

В вашем интенте EXECUTE добавьте команду action.devices.commands.SetToggles , как показано в следующем фрагменте кода.

index.js

const updateDevice = async (execution,deviceId) => {
  ...
  switch (command) {
\   ...
    // Add SetToggles command
    case 'action.devices.commands.SetToggles':
      state = {Turbo: params.updateToggleSettings.Turbo};
      ref = firebaseRef.child(deviceId).child('Toggles');
      break;
  }

Обновить ответ на запрос

Наконец, вам необходимо обновить ответ QUERY , чтобы он сообщал о турбо-режиме стиральной машины. Добавьте обновленные изменения в функции queryFirebase и queryDevice , чтобы получить состояние переключения, хранящееся в базе данных Realtime Database.

index.js

const queryFirebase = async (deviceId) => {
  const snapshot = await getFirebaseRef().child(deviceId).once('value');
  const snapshotVal = snapshot.val();
  return {
    on: snapshotVal.OnOff.on,
    isPaused: snapshotVal.StartStop.isPaused,
    isRunning: snapshotVal.StartStop.isRunning,
    load: snapshotVal.Modes.load,
    // Add Toggles snapshot
    Turbo: snapshotVal.Toggles.Turbo,
  };
}

const queryDevice = async (deviceId) => {
  const data = queryFirebase(deviceId);
  return {
    on: data.on,
    isPaused: data.isPaused,
    isRunning: data.isRunning,
    currentRunCycle: [{ ... }],
    currentTotalRemainingTime: 1212,
    currentCycleRemainingTime: 301,
    currentModeSettings: {
      load: data.load,
    },
    // Add currentToggleSettings
    currentToggleSettings: {
      Turbo: data.Turbo,
    },
  };
};

Обновить отчет о состоянии

Наконец, обновите функцию reportstate , чтобы она сообщала Home Graph, включен ли турбо-режим стиральной машины.

index.js

const requestBody = {
  requestId: 'ff36a3cc', /* Any unique ID */
  agentUserId: USER_ID,
  payload: {
    devices: {
      states: {
        /* Report the current state of your washer */
        [context.params.deviceId]: {
          on: snapshot.OnOff.on,
          isPaused: snapshot.StartStop.isPaused,
          isRunning: snapshot.StartStop.isRunning,
          currentModeSettings: {
            load: snapshot.Modes.load,
          },
          // Add currentToggleSettings
          currentToggleSettings: {
            Turbo: snapshot.Toggles.Turbo,
          },
        },
      },
    },
  },
};

Развернуть в Firebase

Для развертывания обновленных функций выполните следующую команду:

firebase deploy --only functions

Нажмите кнопку « Обновить» . ae8d3b25777a5e30.png Кнопка в веб-интерфейсе для запуска запроса на синхронизацию после завершения развертывания.

Теперь вы можете отдать команду на перевод стиральной машины в турбо-режим, произнеся:

«Эй, Google, переведи стиральную машину в турбо-режим».

Вы также можете проверить, находится ли ваша стиральная машина уже в турбо-режиме, задав следующий вопрос:

«Эй, Google, моя стиральная машина в турбо-режиме?»

6. Сообщение об ошибках и исключениях

Обработка ошибок в вашей облачной интеграции позволяет сообщать пользователям о проблемах, приводящих к сбоям в ответах на запросы EXECUTE и QUERY . Уведомления улучшают пользовательский опыт при взаимодействии с вашим смарт-устройством и интеграцией.

Всякий раз, когда запрос EXECUTE или QUERY завершается неудачей, ваша интеграция должна возвращать код ошибки. Например, если вы хотите выдать ошибку, когда пользователь пытается запустить стиральную машину с открытой крышкой, то ваш ответ EXECUTE будет выглядеть следующим образом:

{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [
      {
        "ids": [
          "456"
        ],
        "status": "ERROR",
        "errorCode": "deviceLidOpen"
      }
    ]
  }
}

Теперь, когда пользователь просит запустить стиральную машину, Ассистент отвечает следующим образом:

«Крышка стиральной машины открыта. Пожалуйста, закройте её и попробуйте снова».

Исключения похожи на ошибки, но указывают на то, когда с командой связано оповещение, которое может блокировать или не блокировать успешное выполнение. Исключение может предоставлять связанную информацию с помощью трейта StatusReport , например, уровень заряда батареи или недавнее изменение состояния. Коды неблокирующих исключений возвращаются вместе со статусом SUCCESS , а коды блокирующих исключений — со статусом EXCEPTIONS .

Пример ответа с исключением приведен в следующем фрагменте кода:

{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [{
      "ids": ["123"],
      "status": "SUCCESS",
      "states": {
        "online": true,
        "isPaused": false,
        "isRunning": false,
        "exceptionCode": "runCycleFinished"
      }
    }]
  }
}

Ассистент отвечает:

«Стиральная машина закончила работу».

Чтобы добавить функцию отправки сообщений об ошибках для вашей стиральной машины, откройте functions/index.js и добавьте определение класса error, как показано в следующем фрагменте кода:

index.js

app.onQuery(async (body) => {...});

// Add SmartHome error handling
class SmartHomeError extends Error {
  constructor(errorCode, message) {
    super(message);
    this.name = this.constructor.name;
    this.errorCode = errorCode;
  }
}

Обновите ответ на запрос выполнения, чтобы он возвращал код ошибки и статус ошибки:

index.js

const executePromises = [];
const intent = body.inputs[0];
for (const command of intent.payload.commands) {
  for (const device of command.devices) {
    for (const execution of command.execution) {
      executePromises.push(
        updateDevice(execution, device.id)
        .then((data) => {
          ...
        })
        //Add error response handling
        .catch((error) => {
          functions.logger.error('EXECUTE', device.id, error);
          result.ids.push(device.id);
          if (error instanceof SmartHomeError) {
            result.status = 'ERROR';
            result.errorCode = error.errorCode;
          }
        })
      );
    }
  }
}

Теперь помощник может сообщать вашим пользователям о любом коде ошибки , который вы выдаете. Конкретный пример вы увидите в следующем разделе.

7. Добавить дополнительную проверку пользователя.

Если ваше устройство имеет режимы, требующие защиты или ограниченные для определенной группы авторизованных пользователей, например, при обновлении программного обеспечения или снятии блокировки, вам следует включить дополнительную проверку пользователей в вашу интеграцию.

Вы можете внедрить вторичную проверку пользователя для всех типов и характеристик устройств, настроив параметры проверки безопасности: будет ли она выполняться каждый раз или необходимо соблюдение определенных критериев.

Поддерживаются три типа заданий :

  • No challenge — Запрос и ответ, в которых не используется запрос аутентификации (это поведение по умолчанию).
  • ackNeeded — Дополнительная проверка пользователя, требующая явного подтверждения (да или нет).
  • pinNeeded — Дополнительная проверка пользователя, требующая ввода персонального идентификационного номера (PIN-кода).

Для выполнения этого практического задания добавьте проверку ackNeeded к команде включения стиральной машины и функцию, которая будет возвращать ошибку, если дополнительная проверка не пройдена.

Откройте functions/index.js и добавьте определение класса error, который возвращает код ошибки и тип запроса, как показано в следующем фрагменте кода:

index.js

class SmartHomeError extends Error { ... }

// Add secondary user verification error handling
class ChallengeNeededError extends SmartHomeError {
  /**
   * Create a new ChallengeNeededError
   * @param {string} suvType secondary user verification challenge type
   */
  constructor(suvType) {
    super('challengeNeeded', suvType);
    this.suvType = suvType;
  }
}

Также необходимо обновить ответ на запрос выполнения, чтобы он возвращал ошибку challengeNeeded следующим образом:

index.js

const executePromises = [];
const intent = body.inputs[0];
for (const command of intent.payload.commands) {
  for (const device of command.devices) {
    for (const execution of command.execution) {
      executePromises.push(

        updateDevice(execution, device.id)
        .then((data) => {
          ...
        })
        .catch((error) => {
          functions.logger.error('EXECUTE', device.id, error);
          result.ids.push(device.id);
          if (error instanceof SmartHomeError) {
            result.status = 'ERROR';
            result.errorCode = error.errorCode;
            //Add error response handling
            if (error instanceof ChallengeNeededError) {
              result.challengeNeeded = {
                type: error.suvType
              };
            }
          }
        })
      );
    }
  }
}

Наконец, измените updateDevice таким образом, чтобы для включения или выключения стиральной машины требовалось явное подтверждение.

index.js

const updateDevice = async (execution,deviceId) => {
  const {challenge,params,command} = execution; //Add secondary user challenge
  let state, ref;
  switch (command) {
    case 'action.devices.commands.OnOff':
      //Add secondary user verification challenge
      if (!challenge || !challenge.ack) {
        throw new ChallengeNeededError('ackNeeded');
      }
      state = {on: params.on};
      ref = getFirebaseRef().child(deviceId).child('OnOff');
      break;
    ...
  }

  return ref.update(state)
      .then(() => state);
};

Развернуть в Firebase

Для развертывания обновленной функции выполните следующую команду:

firebase deploy --only functions

После установки обновленного кода необходимо подтвердить действие устно, когда вы просите Ассистента включить или выключить стиральную машину, например, так:

Вы: "Эй, Google, включи стиральную машину."

Ассистент: «Вы уверены, что хотите включить стиральную машину?»

Вы: "Да."

Подробный ответ на каждом этапе процесса вторичной проверки пользователя можно также увидеть, открыв журналы Firebase .

289dbe48f4bb8106.png

8. Поздравляем!

674c4f4392e98c1.png

Поздравляем! Вы расширили возможности интеграции между облачными сервисами с помощью параметров Modes и Toggles , а также обеспечили их безопасное выполнение посредством вторичной проверки пользователей.

Узнать больше

Вот несколько идей, которые вы можете использовать, чтобы углубиться в тему:

  • Добавьте возможности локального выполнения на ваши устройства.
  • Для изменения состояния устройства используйте другой тип дополнительной проверки подлинности пользователя.
  • Обновите ответ QUERY трейта RunCycle , чтобы он обновлялся динамически.
  • Explore this GitHub sample .