1. Прежде чем начать
Интеграция с умным домом позволяет Google Assistant управлять подключенными устройствами в домах пользователей. Чтобы построить интеграцию между облаками, вам необходимо предоставить конечную точку облачного веб-перехватчика, способную обрабатывать намерения умного дома . Например, когда пользователь говорит: «Эй, Google, включи свет», Ассистент отправляет команду вашему облачному сервису, чтобы обновить состояние устройства.
Local Home SDK улучшает интеграцию вашего умного дома, добавляя локальный путь для маршрутизации намерений умного дома непосредственно на устройство Google Home, что повышает надежность и уменьшает задержку при обработке команд пользователей. Он позволяет вам написать и развернуть локальное приложение для выполнения заказов на TypeScript или JavaScript, которое идентифицирует устройства и выполняет команды на любом интеллектуальном динамике Google Home или интеллектуальном дисплее Google Nest. Затем ваше приложение напрямую взаимодействует с существующими интеллектуальными устройствами пользователей через локальную сеть, используя существующие стандартные протоколы для выполнения команд.
Отладка межоблачных интеграций — это важнейший шаг для создания качественной интеграции, однако это сложная задача и отнимает много времени без информативных и простых в использовании инструментов устранения неполадок и тестирования. Чтобы облегчить отладку межоблачной интеграции, доступны метрики Google Cloud Platform (GCP) и набор средств ведения журналов и тестов для умного дома, которые помогут вам выявлять и решать проблемы вашей интеграции.
Предварительные условия
- Создание руководства для разработчиков интеграции облако-облако
- Запустите лабораторию разработки кода «Включить локальное выполнение для интеграции облаков в облако».
Что ты построишь
В этой лаборатории кода вы создадите локальную реализацию для межоблачной интеграции и подключите ее к Ассистенту, а затем отладите приложение Local Home с помощью набора тестов для умного дома и показателей и ведения журнала Google Cloud Platform (GCP).
Что вы узнаете
- Как использовать метрики и журналы GCP для выявления и решения производственных проблем.
- Как использовать Test Suite для выявления функциональных проблем и проблем API.
- Как использовать инструменты разработчика Chrome при разработке приложения Local Home.
Что вам понадобится
- Последняя версия Google Chrome
- Устройство iOS или Android с приложением Google Home.
- Умная колонка Google Home или умный дисплей Google Nest.
- Node.js версии 10.16 или новее
- Аккаунт Google
- Платежный аккаунт Google Cloud
2. Запустите приложение стиральной машины.
Получить исходный код
Щелкните следующую ссылку, чтобы загрузить образец этой лаборатории кода на свою машину разработки:
…или вы можете клонировать репозиторий GitHub из командной строки:
$ git clone https://github.com/google-home/smarthome-debug-local.git
О проекте
Начальное приложение содержит те же подкаталоги и облачные функции, что и лаборатория кода «Включить локальное выполнение для интеграции облаков» . Но вместо app-start
у нас здесь app-faulty
. Мы начнем с локального домашнего приложения, которое работает, но не очень хорошо.
Подключиться к Firebase
Мы будем использовать тот же проект, который вы создали в лаборатории кода «Включить локальное выполнение для межоблачной интеграции» , но развернем файлы, загруженные в этой лаборатории кода.
Перейдите в каталог app-faulty
, затем настройте Firebase CLI с вашим проектом интеграции, созданным в лаборатории кода «Включить локальное выполнение для интеграции между облаком» :
$ cd app-faulty $ firebase use <project-id>
Развертывание в Firebase
Перейдите в папку app-faulty/functions
и установите все необходимые зависимости с помощью npm
:
$ cd functions $ npm install
Примечание. Если вы видите сообщение ниже, вы можете проигнорировать его и продолжить. Предупреждение связано с некоторыми более старыми зависимостями, более подробную информацию можно найти здесь .
found 5 high severity vulnerabilities run `npm audit fix` to fix them, or `npm audit` for details
Перейдите в каталог app-faulty/local/
и выполните следующие команды, чтобы загрузить компилятор TypeScript и скомпилировать приложение:
$ cd ../local $ npm install $ npm run build
При этом исходный код index.ts
(TypeScript) компилируется и следующее содержимое помещается в каталог app-faulty/public/local-home/
:
-
bundle.js
— скомпилированный вывод JavaScript, содержащий локальное приложение и зависимости. -
index.html
— страница локального хостинга, используемая для обслуживания приложения для тестирования на устройстве.
Теперь, когда вы установили зависимости и настроили свой проект, вы готовы запустить приложение в первый раз.
$ firebase deploy
Это вывод консоли, который вы должны увидеть:
... ✔ Deploy complete! Project Console: https://console.firebase.google.com/project/<project-id>/overview Hosting URL: https://<projectcd -id>.web.app
Эта команда развертывает веб-приложение вместе с несколькими облачными функциями для Firebase .
Обновить домашний график
Откройте URL-адрес хостинга в своем браузере ( https://<project-id>.web.app
), чтобы просмотреть веб-приложение. В веб-интерфейсе нажмите кнопку «Обновить». Кнопка для обновления HomeGraph через Request Sync с использованием последних метаданных устройства из неисправного приложения стиральной машины:
Откройте приложение Google Home и убедитесь, что вы видите стиральную машину с новым именем «Неисправная стиральная машина». Не забудьте назначить устройство комнате, в которой есть устройство Nest.
3. Запустите умную стиральную машину.
Если вы запустили лабораторную работу «Включить локальное выполнение для интеграции между облаками» , вы уже должны были запустить виртуальную интеллектуальную стиральную машину. Если он остановлен, не забудьте перезагрузить виртуальное устройство.
Запустите устройство
Перейдите в каталог virtual-device/
и запустите сценарий устройства, передав параметры конфигурации в качестве аргументов:
$ cd ../../virtual-device $ npm install $ npm start -- \ --deviceId=deviceid123 --projectId=<project-id> \ --discoveryPortOut=3311 --discoveryPacket=HelloLocalHomeSDK
Убедитесь, что сценарий устройства выполняется с ожидаемыми параметрами:
(...): UDP Server listening on 3311 (...): Device listening on port 3388 (...): Report State successful
4. Проверьте приложение Local Home.
Отправляйте команды на свое устройство с помощью голосовых команд на устройство Google Home, например:
«Эй, Google, включи мою стиральную машину».
«Окей, Google, включи мою стиральную машину».
«Эй, Google, принудительно локальный».
«Эй, Google, останови мою стиральную машину».
Вы заметите, что Google Assistant отвечает: «Извините, похоже, неисправная стиральная машина сейчас недоступна», когда вы попытаетесь управлять стиральной машиной после «принудительного локального управления».
Это означает, что устройство недоступно по локальному пути. Это работало до выдачи «Эй, Google, принудительно локальный», потому что мы вернемся к использованию облачного пути, когда устройство недоступно по локальному пути. Однако после «принудительного локального» возможность возврата к облачному пути отключена.
Чтобы выяснить, в чем проблема, давайте воспользуемся имеющимися у нас инструментами: метриками и ведением журнала Google Cloud Platform (GCP) и инструментами разработчика Chrome.
5. Отладка приложения Local Home
В следующем разделе вы воспользуетесь инструментами Google, чтобы выяснить, почему устройство недоступно по локальному пути. Вы можете использовать инструменты разработчика Google Chrome для подключения к устройству Google Home, просмотра журналов консоли и отладки приложения Local Home. Вы также можете отправлять собственные журналы в Cloud Logging , чтобы быть в курсе основных ошибок, которые ваши пользователи находят в вашем приложении Local Home.
Подключите инструменты разработчика Chrome
Чтобы подключить отладчик к местному приложению выполнения, выполните следующие действия:
- Убедитесь, что вы связали свое устройство Google Home с пользователем, имеющим разрешение на доступ к проекту Developer Console .
- Перезагрузите устройство Google Home, что позволит ему получить URL-адрес вашего HTML-кода, а также конфигурацию сканирования, которую вы разместили в консоли разработчика.
- Запустите Chrome на своей машине разработки.
- Откройте новую вкладку Chrome и введите
chrome://inspect
в поле адреса, чтобы запустить инспектор.
Вы должны увидеть список устройств на странице, а URL-адрес вашего приложения должен появиться под именем вашего устройства Google Home.
Запустить инспектор
Нажмите «Проверить» под URL-адресом вашего приложения, чтобы запустить инструменты разработчика Chrome. Выберите вкладку «Консоль» и убедитесь, что вы видите содержимое намерения IDENTIFY
напечатанное вашим приложением TypeScript.
Этот вывод означает, что обработчик IDENTIFY был запущен успешно, но verificationId
, возвращенный в IdentifyResponse
не соответствует ни одному из устройств в вашем HomeGraph. Давайте добавим несколько пользовательских журналов, чтобы выяснить, почему.
Добавить пользовательские журналы
Хотя Local Home SDK выводит ошибку DEVICE_VERIFICATION_FAILED
, она не очень помогает в поиске основной причины. Давайте добавим несколько пользовательских журналов, чтобы убедиться, что мы правильно читаем и обрабатываем данные сканирования, и обратите внимание, что, если мы отклоняем обещание с ошибкой, сообщение об ошибке фактически также отправляется в Cloud Logging .
локальный/index.ts
identifyHandler(request: IntentFlow.IdentifyRequest):
Promise<IntentFlow.IdentifyResponse> {
console.log("IDENTIFY intent: " + JSON.stringify(request, null, 2));
const scanData = request.inputs[0].payload.device.udpScanData;
if (!scanData) {
const err = new IntentFlow.HandlerError(request.requestId,
'invalid_request', 'Invalid scan data');
return Promise.reject(err);
}
// In this codelab, the scan data contains only local device id.
// Is there something wrong here?
const localDeviceId = Buffer.from(scanData.data);
console.log(`IDENTIFY handler: received local device id
${localDeviceId}`);
// Add custom logs
if (!localDeviceId.toString().match(/^deviceid[0-9]{3}$/gi)) {
const err = new IntentFlow.HandlerError(request.requestId,
'invalid_device', 'Invalid device id from scan data ' +
localDeviceId);
return Promise.reject(err);
}
const response: IntentFlow.IdentifyResponse = {
intent: Intents.IDENTIFY,
requestId: request.requestId,
payload: {
device: {
id: 'washer',
verificationId: localDeviceId.toString(),
}
}
};
console.log("IDENTIFY response: " + JSON.stringify(response, null, 2));
return Promise.resolve(response);
}
Кроме того, измените версию локального домашнего приложения, чтобы мы могли определить, используем ли мы правильную версию.
локальный/index.ts
const localHomeSdk = new App('1.0.1');
После добавления пользовательских журналов вам необходимо снова скомпилировать приложение и повторно развернуть его в Firebase.
$ cd ../app-faulty/local $ npm run build $ firebase deploy --only hosting
Теперь перезагрузите устройство Google Home, чтобы оно могло загрузить обновленное локальное домашнее приложение. Вы можете узнать, использует ли устройство Google Home ожидаемую версию, просмотрев журналы консоли в Инструментах разработчика Chrome.
Доступ к облачной регистрации
Давайте посмотрим, как использовать Cloud Logging для поиска ошибок. Чтобы получить доступ к облачной регистрации вашего проекта:
- В консоли Cloud Platform перейдите на страницу «Проекты» .
- Выберите проект умного дома.
- В разделе «Операции» выберите «Ведение журнала» > «Обозреватель журналов» .
Доступ к данным журналов управляется с помощью управления идентификацией и доступом (IAM) для пользователей вашего проекта интеграции. Дополнительные сведения о ролях и разрешениях для регистрации данных см. в разделе Управление доступом к облачным журналам.
Используйте расширенные фильтры
Мы знаем, что в намерении IDENTIFY
возникают ошибки, поскольку локальный путь не работает, поскольку локальное устройство не идентифицируется. Однако мы хотим точно знать, в чем проблема, поэтому давайте сначала отфильтруем ошибки, возникающие в обработчике IDENTIFY
.
Нажмите переключатель «Показать запрос» , он должен превратиться в окно «Конструктор запросов» . Введите jsonPayload.intent="IDENTIFY"
в поле «Конструктор запросов» и нажмите кнопку «Выполнить запрос» .
В результате вы получаете все журналы ошибок, создаваемые обработчиком IDENTIFY
. Далее разверните последнюю ошибку. В обработчике IDENTIFY
вы найдете errorCode
и debugString
, которые вы только что установили при отклонении обещания.
Из debugString
мы можем сказать, что идентификатор локального устройства не в ожидаемом формате. Приложение Local Home ожидает получить идентификатор локального устройства в виде строки, начинающейся с deviceid
за которой следуют 3 цифры, но идентификатор локального устройства здесь представляет собой шестнадцатеричную строку.
Исправьте ошибку
Возвращаясь к исходному коду, где мы анализируем идентификатор локального устройства из данных сканирования, мы замечаем, что не указали кодировку при преобразовании строки в байты. Данные сканирования принимаются в виде шестнадцатеричной строки, поэтому передайте hex
в качестве кодировки символов при вызове Buffer.from()
.
локальный/index.ts
identifyHandler(request: IntentFlow.IdentifyRequest):
Promise<IntentFlow.IdentifyResponse> {
console.log("IDENTIFY intent: " + JSON.stringify(request, null, 2));
const scanData = request.inputs[0].payload.device.udpScanData;
if (!scanData) {
const err = new IntentFlow.HandlerError(request.requestId,
'invalid_request', 'Invalid scan data');
return Promise.reject(err);
}
// In this codelab, the scan data contains only local device id.
const localDeviceId = Buffer.from(scanData.data, 'hex');
console.log(`IDENTIFY handler: received local device id
${localDeviceId}`);
if (!localDeviceId.toString().match(/^deviceid[0-9]{3}$/gi)) {
const err = new IntentFlow.HandlerError(request.requestId,
'invalid_device', 'Invalid device id from scan data ' +
localDeviceId);
return Promise.reject(err);
}
const response: IntentFlow.IdentifyResponse = {
intent: Intents.IDENTIFY,
requestId: request.requestId,
payload: {
device: {
id: 'washer',
verificationId: localDeviceId.toString(),
}
}
};
console.log("IDENTIFY response: " + JSON.stringify(response, null, 2));
return Promise.resolve(response);
}
Кроме того, измените версию локального домашнего приложения, чтобы мы могли определить, используем ли мы правильную версию.
локальный/index.ts
const localHomeSdk = new App('1.0.2');
После исправления ошибки скомпилируйте приложение и повторно разверните его в Firebase. В app-faulty/local
запустите:
$ npm run build $ firebase deploy --only hosting
Проверьте свое исправление
После развертывания перезагрузите устройство Google Home, чтобы оно могло загрузить обновленное локальное домашнее приложение. Убедитесь, что версия локального домашнего приложения — 1.0.2, и на этот раз вы не должны увидеть ошибок в консоли инструментов разработчика Chrome.
Теперь вы можете снова попробовать отправить команды на ваше устройство.
«Эй, Google, принудительно локальный».
«Эй, Google, останови мою стиральную машину».
«Эй, Google, включи мою стиральную машину».
...
«Окей, Google, принудительно установи настройки по умолчанию».
6. Запустите набор тестов для умного дома.
После проверки вашего устройства с помощью сенсорного управления в приложении Google Home или с помощью голосовых команд вы можете использовать автоматизированный набор тестов для умного дома , чтобы проверить варианты использования на основе типов устройств и характеристик, связанных с вашей интеграцией. Test Suite запускает серию тестов для обнаружения проблем в вашей интеграции и отображает информационные сообщения о неудачных тестовых случаях, чтобы ускорить отладку перед погружением в журналы событий.
Запустите Test Suite для умного дома
Следуйте этим инструкциям, чтобы протестировать интеграцию облака в облако с помощью Test Suite:
- В веб-браузере откройте Test Suite для умного дома .
- Войдите в Google, используя кнопку в правом верхнем углу. Это позволяет Test Suite отправлять команды непосредственно в Google Assistant.
- В поле «Идентификатор проекта » введите идентификатор проекта вашей облачной интеграции. Затем нажмите «ДАЛЕЕ» , чтобы продолжить.
- На этапе «Настройки проверки» вы должны увидеть неисправную стиральную машину в разделе «Устройства и лотки» .
- Отключите параметр «Синхронизация тестового запроса» , поскольку в примере приложения стиральной машины нет пользовательского интерфейса для добавления, удаления или переименования стиральной машины. В производственной системе вы должны запускать Request Sync каждый раз, когда пользователь добавляет, удаляет или переименовывает устройства.
- Оставьте параметр Local Home SDK включенным, поскольку мы собираемся протестировать как локальные, так и облачные пути.
- Нажмите «Далее: тестовая среда» , чтобы начать выполнение теста.
После завершения тестов вы заметите, что тесты приостановки/возобновления в локальном пути завершаются неудачно, в то время как тесты приостановки/возобновления в облачном пути проходят успешно.
Анализ сообщения об ошибке
Присмотритесь к сообщениям об ошибках в неудачных тестовых случаях. Они сообщают вам, каково ожидаемое состояние этого теста и каково было фактическое состояние. В данном случае для «Приостановить стиральную машину» ожидаемое состояние — isPaused: true
, но в фактическом состоянии мы получили isPaused: false
. Аналогично, для «Приостановить стиральную машину» ожидаемое состояние — isPaused: true
, но в фактическом состоянии мы получили isPaused: false
.
Судя по сообщениям об ошибках, в локальном пути мы устанавливаем состояние isPaused
в обратном порядке.
Определить и исправить ошибку
Давайте найдем исходный код, в котором приложение Local Home отправляет команду выполнения на устройство. getDataCommand()
— это функция, вызываемая функцией executeHandler()
для установки payload
в команде выполнения, отправленной на устройство.
локальный/index.ts
getDataForCommand(command: string, params: IWasherParams): unknown {
switch (command) {
case 'action.devices.commands.OnOff':
return {
on: params.on ? true : false
};
case 'action.devices.commands.StartStop':
return {
isRunning: params.start ? true : false
};
case 'action.devices.commands.PauseUnpause':
return {
// Is there something wrong here?
isPaused: params.pause ? false : true
};
default:
console.error('Unknown command', command);
return {};
}
}
Мы действительно устанавливаем isPause
в обратное состояние: для него должно быть установлено значение true
если params.pause
имеет true
, и false
в противном случае. Итак, давайте это исправим.
локальный/index.ts
getDataForCommand(command: string, params: IWasherParams): unknown {
switch (command) {
case 'action.devices.commands.OnOff':
return {
on: params.on ? true : false
};
case 'action.devices.commands.StartStop':
return {
isRunning: params.start ? true : false
};
case 'action.devices.commands.PauseUnpause':
return {
isPaused: params.pause ? true : false
};
default:
console.error('Unknown command', command);
return {};
}
}
Измените версию локального домашнего приложения, чтобы мы могли определить, используем ли мы правильную версию.
локальный/index.ts
const localHomeSdk = new App('1.0.3');
Не забудьте снова скомпилировать приложение и повторно развернуть его в Firebase. В app-faulty/local
запустите:
$ npm run build $ firebase deploy --only hosting
Теперь перезагрузите устройство Google Home, чтобы оно могло загрузить обновленное локальное домашнее приложение. Убедитесь, что версия локального домашнего приложения — 1.0.3.
Проверьте свое исправление
Теперь повторно запустите набор тестов для умного дома с теми же конфигурациями, и вы обнаружите, что все тестовые примеры пройдены.
7. Поздравления
Поздравляем! Вы успешно научились устранять неполадки в приложении Local Home с помощью набора тестов для умного дома и облачного ведения журналов.
Узнать больше
Вот еще несколько вещей, которые вы можете попробовать:
- Добавьте на свое устройство больше поддерживаемых функций и протестируйте с помощью Test Suite.
- Добавьте дополнительные пользовательские журналы в каждый из обработчиков намерений и просматривайте их в Cloud Logging.
- Создавайте информационные панели , настраивайте оповещения и программно получайте доступ к данным метрик, чтобы получать полезные показатели использования для вашей интеграции.
Вы также можете узнать больше о тестировании и отправке интеграции на рассмотрение, включая процесс сертификации для публикации вашей интеграции для пользователей.