Отладка локального дома

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

Интеграция с умным домом позволяет Google Assistant управлять подключенными устройствами в домах пользователей. Чтобы создать действие умного дома, вам необходимо предоставить конечную точку облачного веб-перехватчика, способную обрабатывать намерения умного дома . Например, когда пользователь говорит: «Окей, Google, включи свет», помощник отправляет команду в ваше облачное хранилище, чтобы обновить состояние устройства.

Local Home SDK улучшает интеграцию вашего умного дома, добавляя локальный путь для маршрутизации намерений умного дома непосредственно на устройство Google Home, что повышает надежность и уменьшает задержку при обработке команд пользователей. Это позволяет вам написать и развернуть локальное приложение для выполнения на TypeScript или JavaScript, которое идентифицирует устройства и выполняет команды на любом интеллектуальном динамике Google Home или интеллектуальном дисплее Google Nest. Затем ваше приложение связывается напрямую с существующими интеллектуальными устройствами пользователей по локальной сети, используя существующие стандартные протоколы для выполнения команд.

72ffb320986092c.png

Отладка действий «умный дом» — это важный шаг для создания ваших действий с качеством производства, но это сложно и требует много времени без информативных, простых в использовании инструментов для устранения неполадок и тестирования. Чтобы облегчить отладку действий умного дома, Google Cloud Platform (GCP) Metrics и Logging and Test Suite для умного дома доступны, чтобы помочь вам выявить и устранить проблемы с вашими действиями.

Предпосылки

Что вы будете строить

В этой лаборатории кода вы создадите локальное выполнение для действий умного дома и подключите его к помощнику, а затем отладите приложение Local Home с помощью набора тестов для метрик и ведения журнала умного дома и Google Cloud Platform (GCP).

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

  • Как использовать метрики и ведение журнала GCP для выявления и решения производственных проблем.
  • Как использовать Test Suite для выявления функциональных проблем и проблем с API.
  • Как использовать Chrome Dev Tools при разработке приложения Local Home.

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

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 ), чтобы просмотреть веб-приложение. В веб-интерфейсе щелкните Обновить ae8d3b25777a5e30.png кнопку, чтобы обновить HomeGraph через Request Sync с последними метаданными устройства из неисправного приложения для стиральной машины:

fa3c47f293cfe0b7.png

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

2a082ee11d47ad1a.png

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

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

  1. Убедитесь, что вы связали свое устройство Google Home с пользователем, имеющим разрешение на доступ к проекту консоли действий .
  2. Перезагрузите устройство Google Home, что позволит ему получить URL-адрес вашего HTML, а также конфигурацию сканирования, которую вы указали в консоли действий.
  3. Запустите Chrome на своем компьютере для разработки.
  4. Откройте новую вкладку Chrome и введите chrome://inspect в поле адреса, чтобы запустить инспектор.

Вы должны увидеть список устройств на странице, а URL-адрес вашего приложения должен появиться под именем вашего устройства Google Home.

567f97789a7d8846.png

Запустите инспектор

Нажмите «Проверить» под URL-адресом вашего приложения, чтобы запустить инструменты разработчика Chrome. Выберите вкладку «Консоль» и убедитесь, что вы видите содержимое намерения IDENTIFY , напечатанное вашим приложением TypeScript.

774c460c59f9f84a.png

Эти выходные данные означают, что обработчик 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.

ecc56508ebcf9ab.png

Доступ к облачному журналу

Давайте посмотрим, как использовать Cloud Logging для поиска ошибок. Чтобы получить доступ к Cloud Logging для вашего проекта:

  1. В консоли Cloud Platform перейдите на страницу Projects .
  2. Выберите свой проект умного дома.
  3. В разделе «Операции» выберите «Ведение журнала» > «Проводник журналов» .

Доступ к данным журнала управляется с помощью управления идентификацией и доступом (IAM) для пользователей вашего проекта Actions. Дополнительные сведения о ролях и разрешениях для регистрации данных см. в разделе Управление доступом к облачным журналам.

Используйте расширенные фильтры

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

Разверните окно предварительного просмотра запроса , оно должно превратиться в окно построителя запросов . Введите jsonPayload.intent="IDENTIFY" в поле "Конструктор запросов" и нажмите кнопку " Выполнить запрос" .

4c0b9d2828ee2447.png

В результате вы получаете все логи ошибок, которые выбрасываются в обработчике IDENTIFY . Затем разверните последнюю ошибку. Вы найдете errorCode и debugString , которые вы только что установили при отклонении промиса в обработчике IDENTIFY .

71f2f156c6887496.png

Из 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.

c8456f7b5f77f894.png

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

«Окей, Google, локальная настройка».

«Окей, Google, останови мою стиральную машину».

«Окей, Google, включи мою стиральную машину».

...

«Окей, Google, включи значение по умолчанию».

6. Запустите тестовый набор для умного дома

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

Запустите Test Suite для умного дома

Следуйте этим инструкциям, чтобы протестировать свой умный дом Action by Test Suite:

  1. В веб-браузере откройте Test Suite для умного дома .
  2. Войдите в Google с помощью кнопки в правом верхнем углу. Это позволяет Test Suite отправлять команды непосредственно в Google Assistant.
  3. В поле «Идентификатор проекта» введите идентификатор проекта вашего действия «Умный дом». Затем нажмите «ДАЛЕЕ» , чтобы продолжить.
  4. На этапе «Настройки теста » вы должны увидеть неисправную стиральную машину в разделе «Устройства и каналы» .
  5. Отключите параметр «Синхронизация тестового запроса» , поскольку в образце приложения для стиральной машины нет пользовательского интерфейса для добавления/удаления/переименования стиральной машины. В производственной системе вы должны запускать Request Sync всякий раз, когда пользователь добавляет/удаляет/переименовывает устройства.
  6. Оставьте параметр Local Home SDK включенным, поскольку мы собираемся протестировать как локальные, так и облачные пути.
  7. Нажмите NEXT , чтобы начать выполнение теста.

67433d9190fa770e.png

Когда тесты будут завершены, вы заметите, что тесты Pause/Resume в локальном пути завершаются сбоем, в то время как тесты Pause/Resume в облачном пути проходят.

d1ebd5cfae2a2a47.png

Проанализируйте сообщение об ошибке

Присмотритесь к сообщениям об ошибках в неудачных тестах. Они говорят вам, каково ожидаемое состояние для этого теста и каково было фактическое состояние. В данном случае для «Приостановить работу стиральной машины» ожидаемое состояние isPaused: true , но в фактическом состоянии мы получили isPaused: false . Точно так же для «Пауза в стиральной машине» ожидаемое состояние isPaused: true , но в фактическом состоянии мы получили isPaused: false .

6bfd3acef9c16b84.png

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

Проверьте свое исправление

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

b7fc8c5d3c727d8d.png

7. Поздравления

764dbc83b95782a.png

Поздравляем! Вы успешно научились устранять неполадки в приложении Local Home с помощью набора тестов для умного дома и ведения журнала в облаке.

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

Вот некоторые дополнительные вещи, которые вы можете попробовать:

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