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

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

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

dc8dce0dea87cd5c.png

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

Помимо основных возможностей управления, предоставляемых типами и признаками, API Smart Home имеет дополнительные функции для улучшения пользовательского опыта. Ответы об ошибках предоставляют подробную обратную связь для пользователя, когда намерения не удаются. Вторичная проверка пользователя расширяет эти ответы и добавляет дополнительную безопасность признаку устройства по вашему выбору. Отправляя определенные ответы об ошибках в блоки вызовов, выпущенные Assistant, ваша интеграция Cloud-to-cloud может потребовать дополнительной авторизации для выполнения команды.

Предпосылки

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

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

Чему вы научитесь

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

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

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

Включить контроль активности

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

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

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

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

Создайте проект интеграции облака в облако

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

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

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

На главной странице проекта в консоли разработчика выберите Добавить интеграцию «облако-облако» в разделе «Облако-облако» .

Добавить интеграцию облако-облако

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

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

Чтобы установить CLI, выполните следующую команду npm из терминала:

npm install -g firebase-tools

Чтобы проверить правильность установки CLI, выполните:

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 CLI

firebase projects:addfirebase

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

Когда Firebase будет добавлен в ваш проект Google Home Developer Console, он появится в Firebase Console. Идентификатор проекта Firebase будет соответствовать идентификатору вашего проекта Google Home Developer Console.

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

Включить API HomeGraph

API HomeGraph позволяет хранить и запрашивать устройства и их состояния в Home Graph пользователя. Чтобы использовать этот API, сначала нужно открыть консоль Google Cloud и включить API HomeGraph .

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

ee198858a6eac112.png

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

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

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

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

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

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

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

О проекте

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

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

Предоставленное облачное исполнение включает в себя следующие функции в 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

Выберите функции CLI, Realtime Database и функцию Functions .

? 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. Используя GUI, перейдите в папку ../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 Assistant с помощью консоли разработчика .

Настройте свой проект Developer Console

На вкладке «Разработка» добавьте Отображаемое имя для вашего взаимодействия. Это имя будет отображаться в приложении 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-адрес облачной функции

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

Проверьте свою интеграцию облако-облако

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

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

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

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

ae252220753726f6.png

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

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

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

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

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

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

индекс.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

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

индекс.js

const updateDevice = async (execution,deviceId) => {
  const {params,command} = execution;
  let state, ref;
  switch (command) {
    case 'action.devices.commands.OnOff':
      state = {on: params.on};
      ref = firebaseRef.child(deviceId).child('OnOff');
      break;
    case 'action.devices.commands.StartStop':
      state = {isRunning: params.start};
      ref = firebaseRef.child(deviceId).child('StartStop');
      break;
    case 'action.devices.commands.PauseUnpause':
      state = {isPaused: params.pause};
      ref = firebaseRef.child(deviceId).child('StartStop');
      Break;
    // Add SetModes command
    case 'action.devices.commands.SetModes':
      state = {load: params.updateModeSettings.load};
      ref = firebaseRef.child(deviceId).child('Modes');
      break;
  }
};

Обновить ответ на ЗАПРОС

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

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

индекс.js

const queryFirebase = async (deviceId) => {
  const snapshot = await firebaseRef.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.

индекс.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 представляет именованные аспекты устройства, которые имеют истинное или ложное состояние, например, находится ли стиральная машина в турборежиме.

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

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

индекс.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

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

индекс.js

const updateDevice = async (execution,deviceId) => {
  const {params,command} = execution;
  let state, ref;
  switch (command) {
    case 'action.devices.commands.OnOff':
      state = {on: params.on};
      ref = firebaseRef.child(deviceId).child('OnOff');
      break;
    case 'action.devices.commands.StartStop':
      state = {isRunning: params.start};
      ref = firebaseRef.child(deviceId).child('StartStop');
      break;
    case 'action.devices.commands.PauseUnpause':
      state = {isPaused: params.pause};
      ref = firebaseRef.child(deviceId).child('StartStop');
      break;
    case 'action.devices.commands.SetModes':
      state = {load: params.updateModeSettings.load};
      ref = firebaseRef.child(deviceId).child('Modes');
      break;
    // Add SetToggles command
    case 'action.devices.commands.SetToggles':
      state = {Turbo: params.updateToggleSettings.Turbo};
      ref = firebaseRef.child(deviceId).child('Toggles');
      break;
  }

Обновить ответ на ЗАПРОС

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

индекс.js

const queryFirebase = async (deviceId) => {
  const snapshot = await firebaseRef.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, установлена ​​ли стиральная машина в режим турбо.

индекс.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. Сообщение об ошибках и исключениях

Обработка ошибок в вашей интеграции Cloud-to-cloud позволяет вам сообщать пользователям, когда проблемы приводят к сбою ответов 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 и добавьте определение класса ошибок, как показано в следующем фрагменте кода:

индекс.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;
  }
}

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

индекс.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 — вторичная проверка пользователя, требующая персонального идентификационного номера (ПИН-кода)

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

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

индекс.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 следующим образом:

индекс.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 так, чтобы для включения или выключения стиральной машины требовалось явное подтверждение.

индекс.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 = firebaseRef.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 для динамического обновления.
  • Изучите этот пример GitHub .