Внедрите приложение для местного выполнения заказов

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

  • IDENTIFY : поддерживает обнаружение локально управляемых интеллектуальных устройств. Обработчик намерений извлекает данные, которые ваше интеллектуальное устройство возвращает во время обнаружения, и отправляет их в ответ в Google.
  • EXECUTE : поддерживает выполнение команд.
  • QUERY : поддерживает запрос состояния устройства.
  • REACHABLE_DEVICES : (Необязательно) Поддерживает обнаружение локально управляемых конечных устройств за устройством-концентратором (или мостом).

Это приложение работает на устройствах Google Home или Google Nest пользователя и подключает ваше интеллектуальное устройство к Ассистенту. Вы можете создать приложение, используя TypeScript (предпочтительно) или JavaScript.

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

Дополнительные сведения об API см. в справочнике по API Local Home SDK .

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

Автономный
import App = smarthome.App;
const localHomeApp: App = new App("1.0.0");
localHomeApp
  .onIdentify(identifyHandler)
  .onExecute(executeHandler)
  .listen()
  .then(() => {
    console.log("Ready");
  });
Центр
import App = smarthome.App;
const localHomeApp: App = new App("1.0.0");
localHomeApp
  .onIdentify(identifyHandler)
  .onReachableDevices(reachableDevicesHandler)
  .onExecute(executeHandler)
  .listen()
  .then(() => {
    console.log("Ready");
  });

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

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

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

Шаблоны проектов

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

Никто

TypeScript без конфигурации упаковщика:

npm init @google/local-home-app project-directory/ --bundler none

Структура проекта:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
└── serve.js

Замените project-directory новым каталогом, который будет содержать проект локального приложения для выполнения.

Веб-пакет

TypeScript с конфигурацией упаковщика веб-пакетов :

npm init @google/local-home-app project-directory/ --bundler webpack

Структура проекта:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
├── webpack.config.web.js
├── webpack.config.node.js
└── serve.js

Замените project-directory новым каталогом, который будет содержать проект локального приложения для выполнения.

Свернуть

TypeScript с конфигурацией упаковщика Rollup :

npm init @google/local-home-app project-directory/ --bundler rollup

Структура проекта:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
├── rollup.config.js
└── serve.js

Замените project-directory новым каталогом, который будет содержать проект локального приложения для выполнения.

Посылка

TypeScript с конфигурацией упаковщика посылок :

npm init @google/local-home-app project-directory/ --bundler parcel

Структура проекта:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
└── serve.js

Замените project-directory новым каталогом, который будет содержать проект локального приложения для выполнения.

Выполнение общих задач на уровне проекта

Сгенерированный проект поддерживает следующие сценарии npm :

Пучок
cd project-directory/
npm run build

Этот скрипт компилирует исходный код TypeScript и связывает ваше приложение с его зависимостями для среды выполнения Chrome в подкаталоге dist/web и среды выполнения Node.js в подкаталоге dist/node .

Проверять
cd project-directory/
npm run lint
npm run compile
npm test

Этот сценарий проверяет синтаксис вашего кода TypeScript, компилирует его, не создавая никаких результатов в подкаталоге dist/ , и запускает автоматические тесты из test.ts

Служить
cd project-directory/
npm run start

Во время разработки этот скрипт локально обслуживает ваши пакеты приложений для сред выполнения Chrome и Node.js.

Реализуйте обработчик IDENTIFY

Обработчик IDENTIFY сработает, когда устройство Google Home или Google Nest перезагружается и обнаруживает непроверенные локальные устройства (включая конечные устройства, подключенные к концентратору). Платформа Local Home выполнит поиск локальных устройств, используя информацию о конфигурации сканирования, указанную вами ранее, и вызовет обработчик IDENTIFY с результатами сканирования.

IdentifyRequest с платформы Local Home содержит данные сканирования экземпляра LocalIdentifiedDevice . Заполняется только один экземпляр device на основе конфигурации сканирования, обнаружившей устройство.

Если результаты сканирования соответствуют вашему устройству, ваш обработчик IDENTIFY должен вернуть объект IdentifyResponsePayload , который включает в себя объект device с метаданными умного дома (такими как типы, характеристики и состояние отчета).

Google устанавливает ассоциацию устройства, verificationId из ответа IDENTIFY соответствует одному из otherDeviceIds , возвращенных ответом SYNC .

Пример

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

Автономный
const identifyHandler = (request: IntentFlow.IdentifyRequest):
  IntentFlow.IdentifyResponse => {

    // Obtain scan data from protocol defined in your scan config
    const device = request.inputs[0].payload.device;
    if (device.udpScanData === undefined) {
      throw Error("Missing discovery response");
    }
    const scanData = device.udpScanData.data;

    // Decode scan data to obtain metadata about local device
    const verificationId = "local-device-id";

    // Return a response
    const response: IntentFlow.IdentifyResponse = {
      intent: Intents.IDENTIFY,
      requestId: request.requestId,
      payload: {
        device: {
          id: device.id || "",
          verificationId, // Must match otherDeviceIds in SYNC response
        },
      },
    };
    return response;
  };
Центр
const identifyHandler = (request: IntentFlow.IdentifyRequest):
  IntentFlow.IdentifyResponse => {

    // Obtain scan data from protocol defined in your scan config
    const device = request.inputs[0].payload.device;
    if (device.udpScanData === undefined) {
      throw Error("Missing discovery response");
    }
    const scanData = device.udpScanData.data;

    // Decode scan data to obtain metadata about local device
    const proxyDeviceId = "local-hub-id";

    // Return a response
    const response: IntentFlow.IdentifyResponse = {
      intent: Intents.IDENTIFY,
      requestId: request.requestId,
      payload: {
        device: {
          id: proxyDeviceId,
          isProxy: true,     // Device can control other local devices
          isLocalOnly: true, // Device not present in `SYNC` response
        },
      },
    };
    return response;
  };

Определите устройства за концентратором

Если Google идентифицирует устройство-концентратор, он будет рассматривать концентратор как канал для подключенных к нему конечных устройств и попытается проверить эти конечные устройства.

Чтобы Google мог подтвердить наличие устройства-концентратора, следуйте этим инструкциям для вашего обработчика IDENTIFY :

  • Если ваш ответ SYNC сообщает идентификаторы локальных конечных устройств, подключенных к концентратору, установите для isProxy значение true в IdentifyResponsePayload .
  • Если ваш ответ SYNC не сообщает о вашем устройстве-концентраторе, установите isLocalOnly значение true в IdentifyResponsePayload .
  • Поле device.id содержит идентификатор локального устройства для самого устройства-концентратора.

Реализуйте обработчик REACHABLE_DEVICES (только для интеграции с хабом)

Намерение REACHABLE_DEVICES отправляется Google, чтобы подтвердить, какие конечные устройства могут управляться локально. Это намерение срабатывает каждый раз, когда Google запускает сканирование обнаружения (примерно раз в минуту), пока хаб обнаруживается в сети.

Вы реализуете обработчик REACHABLE_DEVICES аналогично обработчику IDENTIFY , за исключением того, что вашему обработчику необходимо собирать дополнительные идентификаторы устройств, доступные локальному прокси-устройству (то есть концентратору). Поле device.verificationId содержит идентификатор локального устройства для конечного устройства, подключенного к концентратору.

ReachableDevicesRequest с платформы Local Home содержит экземпляр LocalIdentifiedDevice . С помощью этого экземпляра вы можете получить идентификатор прокси-устройства, а также данные из результатов сканирования.

Ваш обработчик REACHABLE_DEVICES должен возвращать объект ReachableDevicesPayload , который включает в себя объект devices , содержащий массив значений verificationId , представляющих конечные устройства, которыми управляет концентратор. verificationId должны совпадать с одним из otherDeviceIds из ответа SYNC .

В следующем фрагменте показано, как можно создать обработчик REACHABLE_DEVICES .

Центр
const reachableDevicesHandler = (request: IntentFlow.ReachableDevicesRequest):
  IntentFlow.ReachableDevicesResponse => {

    // Reference to the local proxy device
    const proxyDeviceId = request.inputs[0].payload.device.id;

    // Gather additional device ids reachable by local proxy device
    // ...

    const reachableDevices = [
      // Each verificationId must match one of the otherDeviceIds
      // in the SYNC response
      { verificationId: "local-device-id-1" },
      { verificationId: "local-device-id-2" },
    ];

    // Return a response
    const response: IntentFlow.ReachableDevicesResponse = {
      intent: Intents.REACHABLE_DEVICES,
      requestId: request.requestId,
      payload: {
        devices: reachableDevices,
      },
    };
    return response;
  };

Реализуйте обработчик EXECUTE

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

Платформа Local Home передает в функцию обработчика EXECUTE ту же входную полезную нагрузку, что и для намерения EXECUTE для выполнения вашего облака. Аналогично, ваш обработчик EXECUTE возвращает выходные данные в том же формате, что и при обработке намерения EXECUTE . Чтобы упростить создание ответа, вы можете использовать класс Execute.Response.Builder , предоставляемый Local Home SDK.

Ваше приложение не имеет прямого доступа к IP-адресу устройства. Вместо этого используйте интерфейс CommandRequest для создания команд на основе одного из этих протоколов: UDP, TCP или HTTP. Затем вызовите функцию deviceManager.send() для отправки команд.

При нацеливании команд на устройства используйте идентификатор устройства (и параметры из поля customData , если оно включено) из ответа SYNC для связи с устройством.

Пример

В следующем фрагменте кода показано, как можно создать обработчик EXECUTE .

Автономный/Хаб
const executeHandler = (request: IntentFlow.ExecuteRequest):
  Promise<IntentFlow.ExecuteResponse> => {

    // Extract command(s) and device target(s) from request
    const command = request.inputs[0].payload.commands[0];
    const execution = command.execution[0];

    const response = new Execute.Response.Builder()
      .setRequestId(request.requestId);

    const result = command.devices.map((device) => {
      // Target id of the device provided in the SYNC response
      const deviceId = device.id;
      // Metadata for the device provided in the SYNC response
      // Use customData to provide additional required execution parameters
      const customData: any = device.customData;

      // Convert execution command into payload for local device
      let devicePayload: string;
      // ...

      // Construct a local device command over TCP
      const deviceCommand = new DataFlow.TcpRequestData();
      deviceCommand.requestId = request.requestId;
      deviceCommand.deviceId = deviceId;
      deviceCommand.data = devicePayload;
      deviceCommand.port = customData.port;
      deviceCommand.operation = Constants.TcpOperation.WRITE;

      // Send command to the local device
      return localHomeApp.getDeviceManager()
        .send(deviceCommand)
        .then((result) => {
          response.setSuccessState(result.deviceId, state);
        })
        .catch((err: IntentFlow.HandlerError) => {
          err.errorCode = err.errorCode || IntentFlow.ErrorCode.INVALID_REQUEST;
          response.setErrorState(device.id, err.errorCode);
        });
    });

    // Respond once all commands complete
    return Promise.all(result)
      .then(() => response.build());
  };

Реализуйте обработчик QUERY

Ваш обработчик QUERY в приложении обрабатывает запросы пользователей и использует Local Home SDK для сообщения о состоянии ваших интеллектуальных устройств.

Платформа Local Home передает ту же полезную нагрузку запроса функции-обработчику QUERY, что и намерение QUERY для выполнения вашего облака. Аналогично, ваш обработчик QUERY возвращает данные в том же формате, что и при обработке намерения QUERY .

Отправка команд на устройства за хабом

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

Если вы создали свое приложение с использованием TypeScript, не забудьте скомпилировать его в JavaScript. Для написания кода вы можете использовать систему модулей по вашему выбору. Убедитесь, что ваша цель поддерживается браузером Chrome.

,

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

  • IDENTIFY : поддерживает обнаружение локально управляемых интеллектуальных устройств. Обработчик намерений извлекает данные, которые ваше интеллектуальное устройство возвращает во время обнаружения, и отправляет их в ответ в Google.
  • EXECUTE : поддерживает выполнение команд.
  • QUERY : поддерживает запрос состояния устройства.
  • REACHABLE_DEVICES : (Необязательно) Поддерживает обнаружение локально управляемых конечных устройств за устройством-концентратором (или мостом).

Это приложение работает на устройствах Google Home или Google Nest пользователя и подключает ваше интеллектуальное устройство к Ассистенту. Вы можете создать приложение, используя TypeScript (предпочтительно) или JavaScript.

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

Дополнительные сведения об API см. в справочнике по API Local Home SDK .

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

Автономный
import App = smarthome.App;
const localHomeApp: App = new App("1.0.0");
localHomeApp
  .onIdentify(identifyHandler)
  .onExecute(executeHandler)
  .listen()
  .then(() => {
    console.log("Ready");
  });
Центр
import App = smarthome.App;
const localHomeApp: App = new App("1.0.0");
localHomeApp
  .onIdentify(identifyHandler)
  .onReachableDevices(reachableDevicesHandler)
  .onExecute(executeHandler)
  .listen()
  .then(() => {
    console.log("Ready");
  });

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

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

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

Шаблоны проектов

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

Никто

TypeScript без конфигурации упаковщика:

npm init @google/local-home-app project-directory/ --bundler none

Структура проекта:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
└── serve.js

Замените project-directory новым каталогом, который будет содержать проект локального приложения для выполнения.

Веб-пакет

TypeScript с конфигурацией упаковщика веб-пакетов :

npm init @google/local-home-app project-directory/ --bundler webpack

Структура проекта:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
├── webpack.config.web.js
├── webpack.config.node.js
└── serve.js

Замените project-directory новым каталогом, который будет содержать проект локального приложения для выполнения.

Свернуть

TypeScript с конфигурацией упаковщика Rollup :

npm init @google/local-home-app project-directory/ --bundler rollup

Структура проекта:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
├── rollup.config.js
└── serve.js

Замените project-directory новым каталогом, который будет содержать проект локального приложения для выполнения.

Посылка

TypeScript с конфигурацией упаковщика посылок :

npm init @google/local-home-app project-directory/ --bundler parcel

Структура проекта:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
└── serve.js

Замените project-directory новым каталогом, который будет содержать проект локального приложения для выполнения.

Выполнение общих задач на уровне проекта

Сгенерированный проект поддерживает следующие сценарии npm :

Пучок
cd project-directory/
npm run build

Этот скрипт компилирует исходный код TypeScript и связывает ваше приложение с его зависимостями для среды выполнения Chrome в подкаталоге dist/web и среды выполнения Node.js в подкаталоге dist/node .

Проверять
cd project-directory/
npm run lint
npm run compile
npm test

Этот сценарий проверяет синтаксис вашего кода TypeScript, компилирует его, не создавая никаких результатов в подкаталоге dist/ , и запускает автоматические тесты из test.ts

Служить
cd project-directory/
npm run start

Во время разработки этот скрипт локально обслуживает ваши пакеты приложений для сред выполнения Chrome и Node.js.

Реализуйте обработчик IDENTIFY

Обработчик IDENTIFY сработает, когда устройство Google Home или Google Nest перезагружается и обнаруживает непроверенные локальные устройства (включая конечные устройства, подключенные к концентратору). Платформа Local Home выполнит поиск локальных устройств, используя информацию о конфигурации сканирования, указанную вами ранее, и вызовет обработчик IDENTIFY с результатами сканирования.

IdentifyRequest с платформы Local Home содержит данные сканирования экземпляра LocalIdentifiedDevice . Заполняется только один экземпляр device на основе конфигурации сканирования, обнаружившей устройство.

Если результаты сканирования соответствуют вашему устройству, ваш обработчик IDENTIFY должен вернуть объект IdentifyResponsePayload , который включает в себя объект device с метаданными умного дома (такими как типы, характеристики и состояние отчета).

Google устанавливает ассоциацию устройства, verificationId из ответа IDENTIFY соответствует одному из otherDeviceIds , возвращенных ответом SYNC .

Пример

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

Автономный
const identifyHandler = (request: IntentFlow.IdentifyRequest):
  IntentFlow.IdentifyResponse => {

    // Obtain scan data from protocol defined in your scan config
    const device = request.inputs[0].payload.device;
    if (device.udpScanData === undefined) {
      throw Error("Missing discovery response");
    }
    const scanData = device.udpScanData.data;

    // Decode scan data to obtain metadata about local device
    const verificationId = "local-device-id";

    // Return a response
    const response: IntentFlow.IdentifyResponse = {
      intent: Intents.IDENTIFY,
      requestId: request.requestId,
      payload: {
        device: {
          id: device.id || "",
          verificationId, // Must match otherDeviceIds in SYNC response
        },
      },
    };
    return response;
  };
Центр
const identifyHandler = (request: IntentFlow.IdentifyRequest):
  IntentFlow.IdentifyResponse => {

    // Obtain scan data from protocol defined in your scan config
    const device = request.inputs[0].payload.device;
    if (device.udpScanData === undefined) {
      throw Error("Missing discovery response");
    }
    const scanData = device.udpScanData.data;

    // Decode scan data to obtain metadata about local device
    const proxyDeviceId = "local-hub-id";

    // Return a response
    const response: IntentFlow.IdentifyResponse = {
      intent: Intents.IDENTIFY,
      requestId: request.requestId,
      payload: {
        device: {
          id: proxyDeviceId,
          isProxy: true,     // Device can control other local devices
          isLocalOnly: true, // Device not present in `SYNC` response
        },
      },
    };
    return response;
  };

Определите устройства за концентратором

Если Google идентифицирует устройство-концентратор, он будет рассматривать концентратор как канал для подключенных к нему конечных устройств и попытается проверить эти конечные устройства.

Чтобы Google мог подтвердить наличие устройства-концентратора, следуйте этим инструкциям для вашего обработчика IDENTIFY :

  • Если ваш ответ SYNC сообщает идентификаторы локальных конечных устройств, подключенных к концентратору, установите для isProxy значение true в IdentifyResponsePayload .
  • Если ваш ответ SYNC не сообщает о вашем устройстве-концентраторе, установите isLocalOnly значение true в IdentifyResponsePayload .
  • Поле device.id содержит идентификатор локального устройства для самого устройства-концентратора.

Реализуйте обработчик REACHABLE_DEVICES (только для интеграции с хабом)

Намерение REACHABLE_DEVICES отправляется Google, чтобы подтвердить, какие конечные устройства могут управляться локально. Это намерение срабатывает каждый раз, когда Google запускает сканирование обнаружения (примерно раз в минуту), пока хаб обнаруживается в сети.

Вы реализуете обработчик REACHABLE_DEVICES аналогично обработчику IDENTIFY , за исключением того, что вашему обработчику необходимо собирать дополнительные идентификаторы устройств, доступные локальному прокси-устройству (то есть концентратору). Поле device.verificationId содержит идентификатор локального устройства для конечного устройства, подключенного к концентратору.

ReachableDevicesRequest с платформы Local Home содержит экземпляр LocalIdentifiedDevice . С помощью этого экземпляра вы можете получить идентификатор прокси-устройства, а также данные из результатов сканирования.

Ваш обработчик REACHABLE_DEVICES должен возвращать объект ReachableDevicesPayload , который включает в себя объект devices , содержащий массив значений verificationId , представляющих конечные устройства, которыми управляет концентратор. verificationId должны совпадать с одним из otherDeviceIds из ответа SYNC .

В следующем фрагменте показано, как можно создать обработчик REACHABLE_DEVICES .

Центр
const reachableDevicesHandler = (request: IntentFlow.ReachableDevicesRequest):
  IntentFlow.ReachableDevicesResponse => {

    // Reference to the local proxy device
    const proxyDeviceId = request.inputs[0].payload.device.id;

    // Gather additional device ids reachable by local proxy device
    // ...

    const reachableDevices = [
      // Each verificationId must match one of the otherDeviceIds
      // in the SYNC response
      { verificationId: "local-device-id-1" },
      { verificationId: "local-device-id-2" },
    ];

    // Return a response
    const response: IntentFlow.ReachableDevicesResponse = {
      intent: Intents.REACHABLE_DEVICES,
      requestId: request.requestId,
      payload: {
        devices: reachableDevices,
      },
    };
    return response;
  };

Реализуйте обработчик EXECUTE

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

Платформа Local Home передает в функцию обработчика EXECUTE ту же входную полезную нагрузку, что и для намерения EXECUTE для выполнения вашего облака. Аналогично, ваш обработчик EXECUTE возвращает выходные данные в том же формате, что и при обработке намерения EXECUTE . Чтобы упростить создание ответа, вы можете использовать класс Execute.Response.Builder , предоставляемый Local Home SDK.

Ваше приложение не имеет прямого доступа к IP-адресу устройства. Вместо этого используйте интерфейс CommandRequest для создания команд на основе одного из этих протоколов: UDP, TCP или HTTP. Затем вызовите функцию deviceManager.send() для отправки команд.

При нацеливании команд на устройства используйте идентификатор устройства (и параметры из поля customData , если оно включено) из ответа SYNC для связи с устройством.

Пример

В следующем фрагменте кода показано, как можно создать обработчик EXECUTE .

Автономный/Хаб
const executeHandler = (request: IntentFlow.ExecuteRequest):
  Promise<IntentFlow.ExecuteResponse> => {

    // Extract command(s) and device target(s) from request
    const command = request.inputs[0].payload.commands[0];
    const execution = command.execution[0];

    const response = new Execute.Response.Builder()
      .setRequestId(request.requestId);

    const result = command.devices.map((device) => {
      // Target id of the device provided in the SYNC response
      const deviceId = device.id;
      // Metadata for the device provided in the SYNC response
      // Use customData to provide additional required execution parameters
      const customData: any = device.customData;

      // Convert execution command into payload for local device
      let devicePayload: string;
      // ...

      // Construct a local device command over TCP
      const deviceCommand = new DataFlow.TcpRequestData();
      deviceCommand.requestId = request.requestId;
      deviceCommand.deviceId = deviceId;
      deviceCommand.data = devicePayload;
      deviceCommand.port = customData.port;
      deviceCommand.operation = Constants.TcpOperation.WRITE;

      // Send command to the local device
      return localHomeApp.getDeviceManager()
        .send(deviceCommand)
        .then((result) => {
          response.setSuccessState(result.deviceId, state);
        })
        .catch((err: IntentFlow.HandlerError) => {
          err.errorCode = err.errorCode || IntentFlow.ErrorCode.INVALID_REQUEST;
          response.setErrorState(device.id, err.errorCode);
        });
    });

    // Respond once all commands complete
    return Promise.all(result)
      .then(() => response.build());
  };

Реализуйте обработчик QUERY

Ваш обработчик QUERY в приложении обрабатывает запросы пользователей и использует Local Home SDK для сообщения о состоянии ваших интеллектуальных устройств.

Платформа Local Home передает ту же полезную нагрузку запроса функции обработчика QUERY, что и намерение QUERY для выполнения вашего облака. Аналогично, ваш обработчик QUERY возвращает данные в том же формате, что и при обработке намерения QUERY .

Отправка команд на устройства за хабом

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

Если вы создали свое приложение с использованием TypeScript, не забудьте скомпилировать его в JavaScript. Для написания кода вы можете использовать систему модулей по вашему выбору. Убедитесь, что ваша цель поддерживается браузером Chrome.

,

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

  • IDENTIFY : поддерживает обнаружение локально управляемых интеллектуальных устройств. Обработчик намерений извлекает данные, которые ваше интеллектуальное устройство возвращает во время обнаружения, и отправляет их в ответ в Google.
  • EXECUTE : поддерживает выполнение команд.
  • QUERY : поддерживает запрос состояния устройства.
  • REACHABLE_DEVICES : (Необязательно) Поддерживает обнаружение локально управляемых конечных устройств за устройством-концентратором (или мостом).

Это приложение работает на устройствах Google Home или Google Nest пользователя и подключает ваше интеллектуальное устройство к Ассистенту. Вы можете создать приложение, используя TypeScript (предпочтительно) или JavaScript.

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

Дополнительные сведения об API см. в справочнике по API Local Home SDK .

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

Автономный
import App = smarthome.App;
const localHomeApp: App = new App("1.0.0");
localHomeApp
  .onIdentify(identifyHandler)
  .onExecute(executeHandler)
  .listen()
  .then(() => {
    console.log("Ready");
  });
Центр
import App = smarthome.App;
const localHomeApp: App = new App("1.0.0");
localHomeApp
  .onIdentify(identifyHandler)
  .onReachableDevices(reachableDevicesHandler)
  .onExecute(executeHandler)
  .listen()
  .then(() => {
    console.log("Ready");
  });

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

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

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

Шаблоны проектов

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

Никто

TypeScript без конфигурации упаковщика:

npm init @google/local-home-app project-directory/ --bundler none

Структура проекта:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
└── serve.js

Замените project-directory новым каталогом, который будет содержать проект локального приложения для выполнения.

Веб-пакет

TypeScript с конфигурацией упаковщика веб-пакетов :

npm init @google/local-home-app project-directory/ --bundler webpack

Структура проекта:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
├── webpack.config.web.js
├── webpack.config.node.js
└── serve.js

Замените project-directory новым каталогом, который будет содержать проект локального приложения для выполнения.

Свернуть

TypeScript с конфигурацией упаковщика Rollup :

npm init @google/local-home-app project-directory/ --bundler rollup

Структура проекта:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
├── rollup.config.js
└── serve.js

Замените project-directory новым каталогом, который будет содержать проект локального приложения для выполнения.

Посылка

TypeScript с конфигурацией упаковщика посылок :

npm init @google/local-home-app project-directory/ --bundler parcel

Структура проекта:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
└── serve.js

Замените project-directory новым каталогом, который будет содержать проект локального приложения для выполнения.

Выполнение общих задач на уровне проекта

Сгенерированный проект поддерживает следующие сценарии npm :

Пучок
cd project-directory/
npm run build

Этот скрипт компилирует исходный код TypeScript и связывает ваше приложение с его зависимостями для среды выполнения Chrome в подкаталоге dist/web и среды выполнения Node.js в подкаталоге dist/node .

Проверять
cd project-directory/
npm run lint
npm run compile
npm test

Этот сценарий проверяет синтаксис вашего кода TypeScript, компилирует его, не создавая никаких результатов в подкаталоге dist/ , и запускает автоматические тесты из test.ts

Служить
cd project-directory/
npm run start

Во время разработки этот скрипт обслуживает ваши пакеты приложений для сред выполнения Chrome и Node.js локально.

Реализуйте обработчик IDENTIFY

Обработчик IDENTIFY сработает, когда устройство Google Home или Google Nest перезагружается и обнаруживает непроверенные локальные устройства (включая конечные устройства, подключенные к концентратору). Платформа Local Home выполнит поиск локальных устройств, используя информацию о конфигурации сканирования, указанную вами ранее, и вызовет обработчик IDENTIFY с результатами сканирования.

IdentifyRequest с платформы Local Home содержит данные сканирования экземпляра LocalIdentifiedDevice . Заполняется только один экземпляр device на основе конфигурации сканирования, обнаружившей устройство.

Если результаты сканирования соответствуют вашему устройству, ваш обработчик IDENTIFY должен вернуть объект IdentifyResponsePayload , который включает в себя объект device с метаданными умного дома (такими как типы, характеристики и состояние отчета).

Google устанавливает ассоциацию устройства, verificationId из ответа IDENTIFY соответствует одному из otherDeviceIds , возвращенных ответом SYNC .

Пример

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

Автономный
const identifyHandler = (request: IntentFlow.IdentifyRequest):
  IntentFlow.IdentifyResponse => {

    // Obtain scan data from protocol defined in your scan config
    const device = request.inputs[0].payload.device;
    if (device.udpScanData === undefined) {
      throw Error("Missing discovery response");
    }
    const scanData = device.udpScanData.data;

    // Decode scan data to obtain metadata about local device
    const verificationId = "local-device-id";

    // Return a response
    const response: IntentFlow.IdentifyResponse = {
      intent: Intents.IDENTIFY,
      requestId: request.requestId,
      payload: {
        device: {
          id: device.id || "",
          verificationId, // Must match otherDeviceIds in SYNC response
        },
      },
    };
    return response;
  };
Центр
const identifyHandler = (request: IntentFlow.IdentifyRequest):
  IntentFlow.IdentifyResponse => {

    // Obtain scan data from protocol defined in your scan config
    const device = request.inputs[0].payload.device;
    if (device.udpScanData === undefined) {
      throw Error("Missing discovery response");
    }
    const scanData = device.udpScanData.data;

    // Decode scan data to obtain metadata about local device
    const proxyDeviceId = "local-hub-id";

    // Return a response
    const response: IntentFlow.IdentifyResponse = {
      intent: Intents.IDENTIFY,
      requestId: request.requestId,
      payload: {
        device: {
          id: proxyDeviceId,
          isProxy: true,     // Device can control other local devices
          isLocalOnly: true, // Device not present in `SYNC` response
        },
      },
    };
    return response;
  };

Определите устройства за концентратором

Если Google идентифицирует устройство-концентратор, он будет рассматривать концентратор как канал для подключенных к нему конечных устройств и попытается проверить эти конечные устройства.

Чтобы Google мог подтвердить наличие устройства-концентратора, следуйте этим инструкциям для вашего обработчика IDENTIFY :

  • Если ваш ответ SYNC сообщает идентификаторы локальных конечных устройств, подключенных к концентратору, установите для isProxy значение true в IdentifyResponsePayload .
  • Если ваш ответ SYNC не сообщает о вашем устройстве-концентраторе, установите isLocalOnly значение true в IdentifyResponsePayload .
  • Поле device.id содержит идентификатор локального устройства для самого устройства-концентратора.

Реализуйте обработчик REACHABLE_DEVICES (только для интеграции с хабом)

Намерение REACHABLE_DEVICES отправляется Google для подтверждения того, какие конечные устройства могут управляться локально. Это намерение срабатывает каждый раз, когда Google запускает сканирование обнаружения (примерно раз в минуту), пока хаб обнаруживается в сети.

Вы реализуете обработчик REACHABLE_DEVICES аналогично обработчику IDENTIFY , за исключением того, что вашему обработчику необходимо собирать дополнительные идентификаторы устройств, доступные локальному прокси-устройству (то есть концентратору). Поле device.verificationId содержит идентификатор локального устройства для конечного устройства, подключенного к концентратору.

ReachableDevicesRequest с платформы Local Home содержит экземпляр LocalIdentifiedDevice . С помощью этого экземпляра вы можете получить идентификатор прокси-устройства, а также данные из результатов сканирования.

Ваш обработчик REACHABLE_DEVICES должен возвращать объект ReachableDevicesPayload , который включает в себя объект devices , содержащий массив значений verificationId , представляющих конечные устройства, которыми управляет концентратор. verificationId должны совпадать с одним из otherDeviceIds из ответа SYNC .

В следующем фрагменте показано, как можно создать обработчик REACHABLE_DEVICES .

Центр
const reachableDevicesHandler = (request: IntentFlow.ReachableDevicesRequest):
  IntentFlow.ReachableDevicesResponse => {

    // Reference to the local proxy device
    const proxyDeviceId = request.inputs[0].payload.device.id;

    // Gather additional device ids reachable by local proxy device
    // ...

    const reachableDevices = [
      // Each verificationId must match one of the otherDeviceIds
      // in the SYNC response
      { verificationId: "local-device-id-1" },
      { verificationId: "local-device-id-2" },
    ];

    // Return a response
    const response: IntentFlow.ReachableDevicesResponse = {
      intent: Intents.REACHABLE_DEVICES,
      requestId: request.requestId,
      payload: {
        devices: reachableDevices,
      },
    };
    return response;
  };

Реализуйте обработчик EXECUTE

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

Платформа Local Home передает в функцию обработчика EXECUTE ту же входную полезную нагрузку, что и для намерения EXECUTE для выполнения вашего облака. Аналогично, ваш обработчик EXECUTE возвращает выходные данные в том же формате, что и при обработке намерения EXECUTE . Чтобы упростить создание ответа, вы можете использовать класс Execute.Response.Builder , предоставляемый Local Home SDK.

Ваше приложение не имеет прямого доступа к IP-адресу устройства. Вместо этого используйте интерфейс CommandRequest для создания команд на основе одного из этих протоколов: UDP, TCP или HTTP. Затем вызовите функцию deviceManager.send() для отправки команд.

При нацеливании команд на устройства используйте идентификатор устройства (и параметры из поля customData , если оно включено) из ответа SYNC для связи с устройством.

Пример

В следующем фрагменте кода показано, как можно создать обработчик EXECUTE .

Автономный/Хаб
const executeHandler = (request: IntentFlow.ExecuteRequest):
  Promise<IntentFlow.ExecuteResponse> => {

    // Extract command(s) and device target(s) from request
    const command = request.inputs[0].payload.commands[0];
    const execution = command.execution[0];

    const response = new Execute.Response.Builder()
      .setRequestId(request.requestId);

    const result = command.devices.map((device) => {
      // Target id of the device provided in the SYNC response
      const deviceId = device.id;
      // Metadata for the device provided in the SYNC response
      // Use customData to provide additional required execution parameters
      const customData: any = device.customData;

      // Convert execution command into payload for local device
      let devicePayload: string;
      // ...

      // Construct a local device command over TCP
      const deviceCommand = new DataFlow.TcpRequestData();
      deviceCommand.requestId = request.requestId;
      deviceCommand.deviceId = deviceId;
      deviceCommand.data = devicePayload;
      deviceCommand.port = customData.port;
      deviceCommand.operation = Constants.TcpOperation.WRITE;

      // Send command to the local device
      return localHomeApp.getDeviceManager()
        .send(deviceCommand)
        .then((result) => {
          response.setSuccessState(result.deviceId, state);
        })
        .catch((err: IntentFlow.HandlerError) => {
          err.errorCode = err.errorCode || IntentFlow.ErrorCode.INVALID_REQUEST;
          response.setErrorState(device.id, err.errorCode);
        });
    });

    // Respond once all commands complete
    return Promise.all(result)
      .then(() => response.build());
  };

Реализуйте обработчик QUERY

Ваш обработчик QUERY в приложении обрабатывает запросы пользователей и использует Local Home SDK для сообщения о состоянии ваших интеллектуальных устройств.

Платформа Local Home передает ту же полезную нагрузку запроса функции-обработчику QUERY, что и намерение QUERY для выполнения вашего облака. Аналогично, ваш обработчик QUERY возвращает данные в том же формате, что и при обработке намерения QUERY .

Отправка команд на устройства за хабом

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

Если вы создали свое приложение с использованием TypeScript, не забудьте скомпилировать его в JavaScript. Для написания кода вы можете использовать систему модулей по вашему выбору. Убедитесь, что ваша цель поддерживается браузером Chrome.

,

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

  • IDENTIFY : поддерживает обнаружение локально управляемых интеллектуальных устройств. Обработчик намерений извлекает данные, которые ваше интеллектуальное устройство возвращает во время обнаружения, и отправляет их в ответ в Google.
  • EXECUTE : поддерживает выполнение команд.
  • QUERY : поддерживает запрос состояния устройства.
  • REACHABLE_DEVICES : (Необязательно) Поддерживает обнаружение локально управляемых конечных устройств за устройством-концентратором (или мостом).

Это приложение работает на устройствах Google Home или Google Nest пользователя и подключает ваше интеллектуальное устройство к Ассистенту. Вы можете создать приложение, используя TypeScript (предпочтительно) или JavaScript.

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

Дополнительные сведения об API см. в справочнике по API Local Home SDK .

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

Автономный
import App = smarthome.App;
const localHomeApp: App = new App("1.0.0");
localHomeApp
  .onIdentify(identifyHandler)
  .onExecute(executeHandler)
  .listen()
  .then(() => {
    console.log("Ready");
  });
Центр
import App = smarthome.App;
const localHomeApp: App = new App("1.0.0");
localHomeApp
  .onIdentify(identifyHandler)
  .onReachableDevices(reachableDevicesHandler)
  .onExecute(executeHandler)
  .listen()
  .then(() => {
    console.log("Ready");
  });

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

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

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

Шаблоны проектов

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

Никто

TypeScript без конфигурации упаковщика:

npm init @google/local-home-app project-directory/ --bundler none

Структура проекта:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
└── serve.js

Замените project-directory новым каталогом, который будет содержать проект локального приложения для выполнения.

Веб-пакет

TypeScript с конфигурацией упаковщика веб-пакетов :

npm init @google/local-home-app project-directory/ --bundler webpack

Структура проекта:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
├── webpack.config.web.js
├── webpack.config.node.js
└── serve.js

Замените project-directory новым каталогом, который будет содержать проект локального приложения для выполнения.

Свернуть

TypeScript с конфигурацией упаковщика Rollup :

npm init @google/local-home-app project-directory/ --bundler rollup

Структура проекта:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
├── rollup.config.js
└── serve.js

Замените project-directory новым каталогом, который будет содержать проект локального приложения для выполнения.

Посылка

TypeScript с конфигурацией упаковщика посылок :

npm init @google/local-home-app project-directory/ --bundler parcel

Структура проекта:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
└── serve.js

Замените project-directory новым каталогом, который будет содержать проект локального приложения для выполнения.

Выполнение общих задач на уровне проекта

Сгенерированный проект поддерживает следующие сценарии npm :

Пучок
cd project-directory/
npm run build

Этот скрипт компилирует исходный код TypeScript и связывает ваше приложение с его зависимостями для среды выполнения Chrome в подкаталоге dist/web и среды выполнения Node.js в подкаталоге dist/node .

Проверять
cd project-directory/
npm run lint
npm run compile
npm test

Этот сценарий проверяет синтаксис вашего кода TypeScript, компилирует его, не создавая никаких результатов в подкаталоге dist/ , и запускает автоматические тесты из test.ts

Служить
cd project-directory/
npm run start

Во время разработки этот скрипт локально обслуживает ваши пакеты приложений для сред выполнения Chrome и Node.js.

Реализуйте обработчик IDENTIFY

Обработчик IDENTIFY будет запущен, когда устройство Google Home или Google Nest перезагружается и обнаруживает непроверенные локальные устройства (включая конечные устройства, подключенные к концентратору). Платформа Local Home выполнит поиск локальных устройств, используя информацию о конфигурации сканирования, указанную вами ранее, и вызовет обработчик IDENTIFY с результатами сканирования.

IdentifyRequest с платформы Local Home содержит данные сканирования экземпляра LocalIdentifiedDevice . Заполняется только один экземпляр device на основе конфигурации сканирования, обнаружившей устройство.

Если результаты сканирования соответствуют вашему устройству, ваш обработчик IDENTIFY должен вернуть объект IdentifyResponsePayload , который включает в себя объект device с метаданными умного дома (такими как типы, характеристики и состояние отчета).

Google устанавливает ассоциацию устройства, verificationId из ответа IDENTIFY соответствует одному из otherDeviceIds , возвращенных ответом SYNC .

Пример

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

Автономный
const identifyHandler = (request: IntentFlow.IdentifyRequest):
  IntentFlow.IdentifyResponse => {

    // Obtain scan data from protocol defined in your scan config
    const device = request.inputs[0].payload.device;
    if (device.udpScanData === undefined) {
      throw Error("Missing discovery response");
    }
    const scanData = device.udpScanData.data;

    // Decode scan data to obtain metadata about local device
    const verificationId = "local-device-id";

    // Return a response
    const response: IntentFlow.IdentifyResponse = {
      intent: Intents.IDENTIFY,
      requestId: request.requestId,
      payload: {
        device: {
          id: device.id || "",
          verificationId, // Must match otherDeviceIds in SYNC response
        },
      },
    };
    return response;
  };
Центр
const identifyHandler = (request: IntentFlow.IdentifyRequest):
  IntentFlow.IdentifyResponse => {

    // Obtain scan data from protocol defined in your scan config
    const device = request.inputs[0].payload.device;
    if (device.udpScanData === undefined) {
      throw Error("Missing discovery response");
    }
    const scanData = device.udpScanData.data;

    // Decode scan data to obtain metadata about local device
    const proxyDeviceId = "local-hub-id";

    // Return a response
    const response: IntentFlow.IdentifyResponse = {
      intent: Intents.IDENTIFY,
      requestId: request.requestId,
      payload: {
        device: {
          id: proxyDeviceId,
          isProxy: true,     // Device can control other local devices
          isLocalOnly: true, // Device not present in `SYNC` response
        },
      },
    };
    return response;
  };

Определите устройства за концентратором

Если Google идентифицирует устройство-концентратор, он будет рассматривать концентратор как канал для подключенных к нему конечных устройств и попытается проверить эти конечные устройства.

Чтобы Google мог подтвердить наличие устройства-концентратора, следуйте этим инструкциям для вашего обработчика IDENTIFY :

  • Если ваш ответ SYNC сообщает идентификаторы локальных конечных устройств, подключенных к концентратору, установите для isProxy значение true в IdentifyResponsePayload .
  • Если ваш ответ SYNC не сообщает о вашем устройстве-концентраторе, установите isLocalOnly значение true в IdentifyResponsePayload .
  • Поле device.id содержит идентификатор локального устройства для самого устройства-концентратора.

Реализуйте обработчик REACHABLE_DEVICES (только для интеграции с хабом)

Намерение REACHABLE_DEVICES отправляется Google, чтобы подтвердить, какие конечные устройства могут управляться локально. Это намерение срабатывает каждый раз, когда Google запускает сканирование обнаружения (примерно раз в минуту), пока хаб обнаруживается в сети.

Вы реализуете обработчик REACHABLE_DEVICES аналогично обработчику IDENTIFY , за исключением того, что вашему обработчику необходимо собирать дополнительные идентификаторы устройств, доступные локальному прокси-устройству (то есть концентратору). Поле device.verificationId содержит идентификатор локального устройства для конечного устройства, подключенного к концентратору.

ReachableDevicesRequest с платформы Local Home содержит экземпляр LocalIdentifiedDevice . С помощью этого экземпляра вы можете получить идентификатор прокси-устройства, а также данные из результатов сканирования.

Ваш обработчик REACHABLE_DEVICES должен возвращать объект ReachableDevicesPayload , который включает в себя объект devices , содержащий массив значений verificationId , представляющих конечные устройства, которыми управляет концентратор. verificationId должны совпадать с одним из otherDeviceIds из ответа SYNC .

В следующем фрагменте показано, как можно создать обработчик REACHABLE_DEVICES .

Центр
const reachableDevicesHandler = (request: IntentFlow.ReachableDevicesRequest):
  IntentFlow.ReachableDevicesResponse => {

    // Reference to the local proxy device
    const proxyDeviceId = request.inputs[0].payload.device.id;

    // Gather additional device ids reachable by local proxy device
    // ...

    const reachableDevices = [
      // Each verificationId must match one of the otherDeviceIds
      // in the SYNC response
      { verificationId: "local-device-id-1" },
      { verificationId: "local-device-id-2" },
    ];

    // Return a response
    const response: IntentFlow.ReachableDevicesResponse = {
      intent: Intents.REACHABLE_DEVICES,
      requestId: request.requestId,
      payload: {
        devices: reachableDevices,
      },
    };
    return response;
  };

Реализуйте обработчик EXECUTE

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

Платформа Local Home передает в функцию обработчика EXECUTE ту же входную полезную нагрузку, что и для намерения EXECUTE для выполнения вашего облака. Аналогично, ваш обработчик EXECUTE возвращает выходные данные в том же формате, что и при обработке намерения EXECUTE . Чтобы упростить создание ответа, вы можете использовать класс Execute.Response.Builder , предоставляемый Local Home SDK.

Ваше приложение не имеет прямого доступа к IP-адресу устройства. Вместо этого используйте интерфейс CommandRequest для создания команд на основе одного из этих протоколов: UDP, TCP или HTTP. Затем вызовите функцию deviceManager.send() для отправки команд.

При нацеливании команд на устройства используйте идентификатор устройства (и параметры из поля customData , если оно включено) из ответа SYNC для связи с устройством.

Пример

В следующем фрагменте кода показано, как можно создать обработчик EXECUTE .

Автономный/Хаб
const executeHandler = (request: IntentFlow.ExecuteRequest):
  Promise<IntentFlow.ExecuteResponse> => {

    // Extract command(s) and device target(s) from request
    const command = request.inputs[0].payload.commands[0];
    const execution = command.execution[0];

    const response = new Execute.Response.Builder()
      .setRequestId(request.requestId);

    const result = command.devices.map((device) => {
      // Target id of the device provided in the SYNC response
      const deviceId = device.id;
      // Metadata for the device provided in the SYNC response
      // Use customData to provide additional required execution parameters
      const customData: any = device.customData;

      // Convert execution command into payload for local device
      let devicePayload: string;
      // ...

      // Construct a local device command over TCP
      const deviceCommand = new DataFlow.TcpRequestData();
      deviceCommand.requestId = request.requestId;
      deviceCommand.deviceId = deviceId;
      deviceCommand.data = devicePayload;
      deviceCommand.port = customData.port;
      deviceCommand.operation = Constants.TcpOperation.WRITE;

      // Send command to the local device
      return localHomeApp.getDeviceManager()
        .send(deviceCommand)
        .then((result) => {
          response.setSuccessState(result.deviceId, state);
        })
        .catch((err: IntentFlow.HandlerError) => {
          err.errorCode = err.errorCode || IntentFlow.ErrorCode.INVALID_REQUEST;
          response.setErrorState(device.id, err.errorCode);
        });
    });

    // Respond once all commands complete
    return Promise.all(result)
      .then(() => response.build());
  };

Реализуйте обработчик QUERY

Ваш обработчик QUERY в приложении обрабатывает запросы пользователей и использует Local Home SDK для сообщения о состоянии ваших интеллектуальных устройств.

Платформа Local Home передает ту же полезную нагрузку запроса функции-обработчику QUERY, что и намерение QUERY для выполнения вашего облака. Аналогично, ваш обработчик QUERY возвращает данные в том же формате, что и при обработке намерения QUERY .

Отправка команд на устройства за хабом

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

Если вы создали свое приложение с использованием TypeScript, не забудьте скомпилировать его в JavaScript. Для написания кода вы можете использовать систему модулей по вашему выбору. Убедитесь, что ваша цель поддерживается браузером Chrome.