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

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

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

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

72ffb320986092c.png

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

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

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

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

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

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

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

2. Запустите приложение стиральной машины.

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

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

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

$ git clone https://github.com/google-home/smarthome-debug-local.git

О проекте

Начальное приложение содержит те же подкаталоги и облачные функции, что и лаборатория кода «Включить локальное выполнение для действий умного дома» . Но вместо app-start у нас здесь app-faulty . Мы начнем с локального домашнего приложения, которое работает, но не очень хорошо.

Подключиться к Firebase

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

Перейдите в каталог app-faulty , затем настройте интерфейс командной строки Firebase с помощью проекта Actions, созданного в разделе «Включить локальное выполнение для умного дома», кодовой лаборатории 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 Assistant отвечает: «Извините, похоже, неисправная стиральная машина сейчас недоступна», когда вы попытаетесь управлять стиральной машиной после «принудительного локального управления».

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

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

5. Отладка приложения Local Home

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

Подключите инструменты разработчика Chrome

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

  1. Убедитесь, что вы связали свое устройство Google Home с пользователем, у которого есть разрешение на доступ к проекту консоли Actions .
  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 для поиска ошибок. Чтобы получить доступ к облачной регистрации вашего проекта:

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

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

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

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

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

4c0b9d2828ee2447.png

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

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.

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. Нажмите «ДАЛЕЕ» , чтобы начать выполнение теста.

67433d9190fa770e.png

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

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 с помощью набора тестов для умного дома и облачного ведения журналов.

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

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

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