1. Прежде чем начать
Интеграция с умным домом позволяет Google Assistant управлять подключенными устройствами в домах пользователей. Чтобы создать действие умного дома, вам необходимо предоставить конечную точку облачного веб-перехватчика, способную обрабатывать намерения умного дома . Например, когда пользователь говорит: «Окей, Google, включи свет», помощник отправляет команду в ваше облачное хранилище, чтобы обновить состояние устройства.
Local Home SDK улучшает интеграцию вашего умного дома, добавляя локальный путь для маршрутизации намерений умного дома непосредственно на устройство Google Home, что повышает надежность и уменьшает задержку при обработке команд пользователей. Это позволяет вам написать и развернуть локальное приложение для выполнения на TypeScript или JavaScript, которое идентифицирует устройства и выполняет команды на любом интеллектуальном динамике Google Home или интеллектуальном дисплее Google Nest. Затем ваше приложение связывается напрямую с существующими интеллектуальными устройствами пользователей по локальной сети, используя существующие стандартные протоколы для выполнения команд.
Отладка действий «умный дом» — это важный шаг для создания ваших действий с качеством производства, но это сложно и требует много времени без информативных, простых в использовании инструментов для устранения неполадок и тестирования. Чтобы облегчить отладку действий умного дома, Google Cloud Platform (GCP) Metrics и Logging and Test Suite для умного дома доступны, чтобы помочь вам выявить и устранить проблемы с вашими действиями.
Предпосылки
- Создание умного дома Руководство разработчика действий
- Запустите лабораторию кода «Включить локальное выполнение для действий умного дома».
Что вы будете строить
В этой лаборатории кода вы создадите локальное выполнение для действий умного дома и подключите его к помощнику, а затем отладите приложение Local Home с помощью набора тестов для метрик и ведения журнала умного дома и Google Cloud Platform (GCP).
Что вы узнаете
- Как использовать метрики и ведение журнала GCP для выявления и решения производственных проблем.
- Как использовать Test Suite для выявления функциональных проблем и проблем с API.
- Как использовать Chrome Dev Tools при разработке приложения 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 с вашим проектом Actions, созданным в лаборатории кода «Включить локальное выполнение для Smart Home Actions »:
$ 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 отвечает: «Извините, похоже, что неисправная стиральная машина сейчас недоступна», когда вы пытаетесь управлять стиральной машиной после «принудительно локально».
Это означает, что устройство недоступно по локальному пути. Это работало до выдачи «Эй, Google, принудительно локально», потому что мы вернемся к использованию облачного пути, когда устройство недоступно через локальный путь. Однако после «force local» возможность возврата к облачному пути отключается.
Чтобы выяснить, в чем проблема, давайте воспользуемся имеющимися у нас инструментами: Google Cloud Platform (GCP) Metrics and Logging и Chrome Developer Tools.
5. Отладка приложения Local Home
В следующем разделе вы будете использовать инструменты, предоставляемые Google, чтобы выяснить, почему устройство недоступно по локальному пути. Вы можете использовать инструменты разработчика Google Chrome для подключения к устройству Google Home, просмотра журналов консоли и отладки приложения Local Home. Вы также можете отправлять пользовательские журналы в Cloud Logging , чтобы быть в курсе основных ошибок, которые ваши пользователи находят в вашем локальном домашнем приложении.
Подключить инструменты разработчика Chrome
Чтобы подключить отладчик к локальному приложению выполнения, выполните следующие действия.
- Убедитесь, что вы связали свое устройство Google Home с пользователем, имеющим разрешение на доступ к проекту консоли действий .
- Перезагрузите устройство 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 Logging для вашего проекта:
- В консоли Cloud Platform перейдите на страницу Projects .
- Выберите свой проект умного дома.
- В разделе «Операции» выберите «Ведение журнала» > «Проводник журналов» .
Доступ к данным журнала управляется с помощью управления идентификацией и доступом (IAM) для пользователей вашего проекта Actions. Дополнительные сведения о ролях и разрешениях для регистрации данных см. в разделе Управление доступом к облачным журналам.
Используйте расширенные фильтры
Мы знаем, что в намерении IDENTIFY
происходят ошибки, поскольку локальный путь не работает, потому что локальное устройство не может быть идентифицировано. Однако мы хотим точно знать, в чем проблема, поэтому давайте сначала отфильтруем ошибки, возникающие в обработчике IDENTIFY
.
Разверните окно предварительного просмотра запроса , оно должно превратиться в окно построителя запросов . Введите jsonPayload.intent="IDENTIFY"
в поле "Конструктор запросов" и нажмите кнопку " Выполнить запрос" .
В результате вы получаете все логи ошибок, которые выбрасываются в обработчике IDENTIFY
. Затем разверните последнюю ошибку. Вы найдете errorCode
и debugString
, которые вы только что установили при отклонении промиса в обработчике IDENTIFY
.
Из 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 Developers Tools.
Теперь вы можете снова попробовать отправить команды на ваше устройство.
«Окей, Google, локальная настройка».
«Окей, Google, останови мою стиральную машину».
«Окей, Google, включи мою стиральную машину».
...
«Окей, Google, включи значение по умолчанию».
6. Запустите тестовый набор для умного дома
После проверки вашего устройства с помощью сенсорного управления в приложении Google Home или с помощью голосовых команд вы можете использовать автоматизированный набор тестов для умного дома , чтобы проверить варианты использования на основе типов устройств и характеристик, связанных с вашим действием. Test Suite запускает серию тестов для обнаружения проблем в вашем действии и показывает информационные сообщения для неудачных тестовых случаев, чтобы ускорить отладку, прежде чем углубляться в журналы событий.
Запустите Test Suite для умного дома
Следуйте этим инструкциям, чтобы протестировать свой умный дом Action by Test Suite:
- В веб-браузере откройте Test Suite для умного дома .
- Войдите в Google с помощью кнопки в правом верхнем углу. Это позволяет Test Suite отправлять команды непосредственно в Google Assistant.
- В поле «Идентификатор проекта» введите идентификатор проекта вашего действия «Умный дом». Затем нажмите «ДАЛЕЕ» , чтобы продолжить.
- На этапе «Настройки теста » вы должны увидеть неисправную стиральную машину в разделе «Устройства и каналы» .
- Отключите параметр «Синхронизация тестового запроса» , поскольку в образце приложения для стиральной машины нет пользовательского интерфейса для добавления/удаления/переименования стиральной машины. В производственной системе вы должны запускать Request Sync всякий раз, когда пользователь добавляет/удаляет/переименовывает устройства.
- Оставьте параметр Local Home SDK включенным, поскольку мы собираемся протестировать как локальные, так и облачные пути.
- Нажмите NEXT , чтобы начать выполнение теста.
Когда тесты будут завершены, вы заметите, что тесты Pause/Resume в локальном пути завершаются сбоем, в то время как тесты Pause/Resume в облачном пути проходят.
Проанализируйте сообщение об ошибке
Присмотритесь к сообщениям об ошибках в неудачных тестах. Они говорят вам, каково ожидаемое состояние для этого теста и каково было фактическое состояние. В данном случае для «Приостановить работу стиральной машины» ожидаемое состояние 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.
- Создавайте информационные панели , настраивайте оповещения и программно получайте доступ к данным метрик , чтобы получать полезные метрики использования для вашего Действия.
Вы также можете узнать больше о тестировании и отправке действия на проверку, включая процесс сертификации для публикации вашего действия для пользователей.