實作本機執行要求應用程式

如要支援本機執行要求,您必須建構應用程式來處理這些要求 智慧型住宅意圖:

  • IDENTIFY:支援探索本機可控制的智慧型裝置。 意圖處理常式會擷取智慧型裝置在探索期間傳回的資料 並傳送給 Google
  • EXECUTE:支援執行指令。
  • QUERY:支援查詢裝置狀態。
  • REACHABLE_DEVICES:(選用) 支援本機可控制的探索 或橋接器裝置後方。

這個應用程式會在使用者的 Google Home 或 Google Nest 裝置上執行,並將你的智慧型裝置連結至 「Google 助理」。您可以使用 TypeScript (建議做法) 或 JavaScript 建立應用程式。

建議使用 TypeScript 繫結 以靜態方式確保應用程式傳回的資料 以及平台的預期

如要進一步瞭解這個 API,請參閱 Local Home SDK API 參考資料

下列程式碼片段說明如何初始化本機執行要求應用程式,並 連結處理常式

獨立
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 套件。 可用於程式碼及其所有依附元件

使用本機執行要求應用程式專案 初始化工具 使用偏好的搭售工具啟動適當的專案結構 此外還會從 0 自動調整資源配置 您完全不必調整資源調度設定

專案範本

如要選取 Bundler 設定,請執行 npm init 指令,如下所示: 範例:

不含 Bundler 設定的 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 換成包含 本機執行要求應用程式專案

,瞭解如何調查及移除這項存取權。
Webpack

TypeScript: webpack 套裝組合 設定:

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 Bundler 設定:

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 Bundler 設定:

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 來源,並將您的應用程式及其依附元件封裝在 dist/web 子目錄中的 Chrome 執行階段環境,以及 dist/node 子目錄中的 Node.js 執行階段環境。

,瞭解如何調查及移除這項存取權。
驗證
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 裝置重新啟動,並 查看未經驗證的本機裝置 (包括連結至中樞裝置的最終裝置)。 本機 Google Home 平台會使用掃描設定資訊掃描本機裝置 並使用掃描結果呼叫 IDENTIFY 處理常式。

IdentifyRequest敬上 Local Home 平台的掃描資料, LocalIdentifiedDevice 執行個體。依據掃描設定,系統只會填入一個 device 執行個體 發現裝置。

如果掃描結果與裝置相符,IDENTIFY 處理常式應會傳回 IdentifyResponsePayload 物件,其中包含 device 物件,以及 智慧型住宅中繼資料 (例如類型、特徵和報告狀態)。

如果發生以下情況,Google 會建立裝置關聯: IDENTIFY 回應中的 verificationId 與下列其中一個項目相符: SYNC 回應傳回的 otherDeviceIds 值。

範例

下列程式碼片段示範如何為 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 識別出 Hub 裝置,就會將 Hub 視為導線。 登入中樞裝置,並嘗試驗證這些終端裝置。

如要讓 Google 確認是否有中樞裝置,請按照下列步驟操作: IDENTIFY 處理常式的操作說明:

  • 如果您的 SYNC 回應回報了連線 中樞,將 isProxy 設為 true IdentifyResponsePayload
  • 如果「SYNC」回應沒有回報中樞裝置,請設定 「isLocalOnly」是 true IdentifyResponsePayload
  • device.id 欄位包含中樞裝置本身的本機裝置 ID。

實作 REACHABLE_devices 處理常式 (僅限中樞整合)

Google 會傳送 REACHABLE_DEVICES 意圖來確認哪部裝置 可以由本機控制每當 Google 執行 只要系統偵測到中樞裝置,就會掃描掃描結果 (大約每分鐘一次) 連上網路。

您實作 REACHABLE_DEVICES 處理常式的方式與 IDENTIFY 類似 做為處理常式,但處理常式需要收集其他裝置 ID 可透過本機 Proxy (即中樞裝置) 連線。 device.verificationId 欄位包含最終裝置的本機裝置 ID 每個連結中樞

ReachableDevicesRequest敬上 包含來自「Local Home」平台的例項 LocalIdentifiedDevice。 透過這個執行個體,您可以取得 Proxy 裝置 ID 和以下來源的資料: 例如掃描結果

您的 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 可透過現有通訊協定存取您的智慧型裝置。

本機首頁平台會將相同的輸入酬載傳遞至 EXECUTE 處理常式 做為 EXECUTE 的函式 傳送至雲端執行要求同樣地,EXECUTE 處理常式會傳回 且輸出資料的格式與處理 EXECUTE 意圖相同。 如要簡化回應建立程序,您可以使用 Execute.Response.Builder敬上 Local Home SDK 提供的類別。

您的應用程式無法直接存取裝置的 IP 位址。 請使用 CommandRequest敬上 介面,根據以下其中一種通訊協定建立指令:UDP、TCP 或 HTTP。接著,呼叫 deviceManager.send()敬上 函式來傳送指令。

將指令指定裝置時,請使用裝置 ID (以及 SYNC 回應中的 customData 欄位 (如有提供) 以通訊 與使用者保持連線

範例

下列程式碼片段說明如何建立 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 處理常式會處理使用者要求,並使用 本機 Home SDK 可回報智慧型裝置的狀態。

本地首頁平台會將同一個要求酬載傳送至「QUERY」處理常式 作為 QUERY 的函式 傳送至雲端執行要求同樣地,QUERY 處理常式會傳回資料 格式與處理 QUERY 意圖相同。

向中樞裝置傳送指令

如要控制中樞裝置,可能需要提供額外資訊 並傳送至中樞,以便為中樞裝置執行要求,才會將通訊協定專屬指令酬載中 ,找出指令的目標裝置在某些情況下 直接從 device.id 值推斷而來,但若非如此, 您應該將這項額外資料納入 customData 欄位。

如果您使用 TypeScript 建立應用程式,請記得將應用程式編譯為 JavaScript。您可以使用您選擇的模組系統來編寫程式碼。 確認 Chrome 瀏覽器支援您的目標。