Улучшите и защитите свой умный дом Действия

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

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

dc8dce0dea87cd5c.png

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

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

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

Что ты построишь

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

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

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

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

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

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

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

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

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

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

Создать проект действий

  1. Перейдите в Действия в консоли разработчика Google .
  2. Нажмите «Новый проект» , введите имя проекта и нажмите «СОЗДАТЬ ПРОЕКТ» .

3d6b68ca79afd54c.png

Выберите приложение «Умный дом».

На экране «Обзор» в консоли «Действия» выберите «Умный дом» .

2fa4988f44f8914b.png

Выберите карточку «Умный дом» , нажмите «Начать сборку» , и вы будете перенаправлены на консоль вашего проекта.

Установите интерфейс командной строки Firebase

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

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

npm install -g firebase-tools

Чтобы убедиться, что CLI установлен правильно, запустите:

firebase --version

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

firebase login

Включите API HomeGraph

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

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

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 для вашего проекта Actions:

cd washer-start
firebase use <project-id>

Настроить проект Firebase

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

firebase init

Выберите функции CLI, базу данных реального времени , функции и функцию хостинга , включающую хостинг Firebase.

? Which Firebase CLI features do you want to set up for this directory? Press Space to select features, then
 Enter to confirm your choices.
❯◉ Realtime Database: Configure a security rules file for Realtime Database and (optionally) provision default instance
 ◯ Firestore: Configure security rules and indexes files for Firestore
 ◉ Functions: Configure a Cloud Functions directory and its files
 ◉ Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys
 ◯ Hosting: 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

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

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

? 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

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

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

Наконец, настройте хостинг для использования public каталога в коде проекта и используйте существующий файл index.html . Выберите Нет , когда вас попросят использовать ESLint.

? What do you want to use as your public directory?
public

? Configure as a single-page app (rewrite all urls to /index.html)?
Yes

? Set up automatic builds and deploys with GitHub?
No

? File public/index.html already exists. Overwrite?
 No

Если 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://<project-id>.web.app ), чтобы просмотреть веб-приложение. Вы увидите следующий интерфейс:

5845443e94705557.png

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

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

Настройте проект консоли Actions

В разделе «Обзор» > «Создайте свое действие» выберите «Добавить действия» . Введите URL-адрес своей облачной функции, обеспечивающей реализацию намерений умного дома, и нажмите «Сохранить» .

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

9d7b223427f587ca.png

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

774d0c40c351c7da.png

a8c4673eb11d76ee.png

Чтобы включить привязку учетной записи, выберите параметр «Разработка» > «Привязка учетной записи» на левой панели навигации. Используйте следующие настройки привязки учетной записи:

ID клиента

ABC123

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

DEF456

URL-адрес авторизации

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

URL-адрес токена

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

9730d20b90bcc038.png

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

ee0547f05b5efd98.png

Вы будете перенаправлены в Симулятор . Если вы не видите сообщение « Тест теперь включен », нажмите «Сбросить тест» , чтобы убедиться, что тестирование включено.

d0495810dbadf059.png

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

  1. На телефоне откройте настройки Google Assistant. Обратите внимание, что вы должны войти в систему под той же учетной записью, что и в консоли.
  2. Перейдите в «Google Ассистент» > «Настройки» > «Управление домом» (в разделе «Ассистент»).
  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 , как показано в следующем фрагменте кода.

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.

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

index.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

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

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

index.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.

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

Обновить ответ 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.

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

index.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

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

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

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

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( ... )
          //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 и добавьте определение класса ошибки, которое возвращает код ошибки и тип проблемы, как показано в следующем фрагменте кода:

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( ... )
          .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 = 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 .