如要支援店面取貨,您必須建構應用程式來處理下列智慧住宅意圖:
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 套件。
使用本機出貨應用程式專案初始化程式,透過偏好的打包工具設定,啟動適當的專案結構。
專案範本
如要選取套件組合工具設定,請執行 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 替換為新的目錄,其中會包含本機履行應用程式專案。
使用 webpack 封裝工具設定的 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 替換為新的目錄,其中會包含本機履行應用程式專案。
使用 Rollup 的 TypeScript 套件組合工具設定:
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 替換為新的目錄,其中會包含本機履行應用程式專案。
使用 Parcel 的 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 來源,並將應用程式及其依附元件分別封裝至 dist/web
子目錄和 dist/node
子目錄,供 Chrome 執行階段環境和 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 處理常式
當 Google Home 或 Google Nest 裝置重新啟動,並發現未經驗證的本機裝置 (包括連線至中樞的終端裝置) 時,系統就會觸發 IDENTIFY
處理常式。Local Home 平台會使用您先前指定的掃描設定資訊掃描本機裝置,並透過掃描結果呼叫 IDENTIFY
處理常式。
本機住家平台中的
IdentifyRequest
包含 LocalIdentifiedDevice
執行個體的掃描資料。系統只會根據發現裝置的掃描設定,填入一個 device
執行個體。
如果掃描結果與裝置相符,IDENTIFY
處理常式應傳回 IdentifyResponsePayload
物件,其中包含 device
物件和智慧住宅中繼資料 (例如類型、特徵和回報狀態)。
如果 IDENTIFY
回應中的 verificationId
與 SYNC
回應傳回的其中一個 otherDeviceIds
值相符,Google 就會建立裝置關聯。
範例
下列程式碼片段分別說明如何為獨立裝置和中樞整合建立 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
回應會回報連線至中樞的本機終端裝置 ID,請在IdentifyResponsePayload
中將isProxy
設為true
。 - 如果
SYNC
回應未回報中樞裝置,請在IdentifyResponsePayload
中將isLocalOnly
設為true
。 device.id
欄位包含中樞裝置本身的本機裝置 ID。
實作 REACHABLE_DEVICES 處理常式 (僅限中樞裝置整合)
Google 會傳送 REACHABLE_DEVICES
意圖,確認哪些終端裝置可在本機控制。只要系統偵測到中樞裝置處於連線狀態,Google 每次執行探索掃描 (大約每分鐘一次) 時,就會觸發這項意圖。
實作 REACHABLE_DEVICES
處理常式的方式與 IDENTIFY
處理常式類似,但處理常式必須收集可透過本機 Proxy (即中樞裝置) 存取的其他裝置 ID。device.verificationId
欄位包含連線至中樞裝置的終端裝置本機 ID。
來自 Local Home 平台的 ReachableDevicesRequest
包含 LocalIdentifiedDevice
的例項。透過這個執行個體,您可以取得 Proxy 裝置 ID,以及掃描結果中的資料。
REACHABLE_DEVICES
處理常式應傳回 ReachableDevicesPayload
物件,其中包含 devices
物件,該物件包含代表中樞控制終端裝置的 verificationId
值陣列。verificationId
值必須與 SYNC
回應中的其中一個 otherDeviceIds
相符。
下列程式碼片段說明如何建立 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
意圖時相同的格式,傳回輸出資料。為簡化回應建立作業,您可以使用 Local Home SDK 提供的 Execute.Response.Builder
類別。
您的應用程式無法直接存取裝置的 IP 位址。請改用 CommandRequest
介面,根據下列其中一種通訊協定建立指令:UDP、TCP 或 HTTP。然後呼叫 deviceManager.send()
函式來傳送指令。
將指令傳送至裝置時,請使用 SYNC
回應中的裝置 ID (以及 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
處理常式會處理使用者要求,並使用 Local Home SDK 回報智慧型裝置的狀態。
Local Home 平台會將與 QUERY
「QUERY」意圖相同的要求酬載,傳遞至雲端服務的「QUERY」處理常式函式。同樣地,QUERY
處理常式會以與處理 QUERY
意圖時相同的格式傳回資料。
將指令傳送至中樞裝置後方的裝置
如要控制中樞控制器後方的終端裝置,您可能需要在傳送至中樞控制器的通訊協定專屬指令酬載中提供額外資訊,中樞控制器才能識別指令的目標裝置。在某些情況下,這可直接從 device.id
值推斷,但如果不是這樣,您應將這項額外資料納入 customData
欄位。
如果您使用 TypeScript 建立應用程式,請記得將應用程式編譯為 JavaScript。您可以選擇使用模組系統來編寫程式碼。確認 Chrome 瀏覽器支援目標裝置。