ローカル フルフィルメントをサポートするには、次のスマートホーム インテントを処理するアプリを作成する必要があります。
IDENTIFY
: ローカルで制御可能なスマート デバイスの検出をサポートします。インテント ハンドラは、スマート デバイスが検出の際に返したデータを抽出し、レスポンスで Google に送信します。EXECUTE
: コマンドの実行をサポートします。QUERY
: デバイスの状態のクエリをサポートします。REACHABLE_DEVICES
: (省略可)ハブ(またはブリッジ)デバイスにローカル接続され、ローカルで制御可能なエンドデバイスの検出をサポートします。
このアプリは、ユーザーの Google Home または Google Nest デバイスで動作し、スマート デバイスをアシスタントに接続します。アプリは 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 を、ファイルを格納する新しいディレクトリに置き換えます。 ローカル フルフィルメント アプリ プロジェクト。
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 と Rollup 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 と Parcel 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 デバイスが再起動して、未確認のローカル デバイス(ハブに接続されたエンドデバイスを含む)を検出したときにトリガーされます。ローカルホーム プラットフォームは、以前に指定されたスキャン設定情報を使用してローカル デバイスをスキャンし、スキャン結果を使用して IDENTIFY
ハンドラを呼び出します。
「
IdentifyRequest
スキャンデータが格納されています。
LocalIdentifiedDevice
作成します。デバイスを検出したスキャン設定に基づいて作成される device
インスタンスは 1 つのみです。
スキャン結果がデバイスと一致する場合、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 が確認できるようにするには、IDENTIFY
ハンドラに対し次の手順を行います。
SYNC
レスポンスで、接続されているローカル エンドデバイスの ID がレポートされる場合、 で、isProxy
をtrue
として設定IdentifyResponsePayload
。SYNC
のレスポンスでハブデバイスが報告されない場合は、次のように設定します。isLocalOnly
(true
)IdentifyResponsePayload
。device.id
フィールドには、ハブデバイス自体のローカル デバイス ID が含まれます。
REACHABLE_DEVICES ハンドラを実装する(ハブ統合のみ)
ローカルで制御できるエンドデバイスを確認するため、REACHABLE_DEVICES
インテントが Google から送信されます。Google が検出スキャンを実行するたびに(毎分約 1 回)、ハブがオンラインであることが検出されると、このインテントがトリガーされます。
IDENTIFY
ハンドラと同様に REACHABLE_DEVICES
ハンドラを実装します。ただし、このハンドラでは、ローカル プロキシ(つまりハブ自体)のデバイスがアクセスできる追加のデバイス ID を収集する必要があります。device.verificationId
フィールドには、ハブに接続されているエンドデバイスのローカル デバイス ID が含まれます。
「
ReachableDevicesRequest
出力には、ローカル ホーム プラットフォームに
LocalIdentifiedDevice
。
このインスタンスを介し、スキャン結果のデータとともに、プロキシ デバイス 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 を使用して既存のプロトコルを介してスマート デバイスにアクセスします。
ローカルホーム プラットフォームは、クラウド フルフィルメントへの EXECUTE
インテントと同じ入力ペイロードを EXECUTE
ハンドラ関数に渡します。同様に、EXECUTE
ハンドラは、EXECUTE
インテントの処理と同じ形式で出力データを返します。回答の作成を簡単にするために、
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 を使用してスマート デバイスの状態を報告します。
ローカルホーム プラットフォームは、クラウド フルフィルメントへの QUERY
インテントと同じリクエスト ペイロードを QUERY ハンドラ関数に渡します。同様に、QUERY
ハンドラは、QUERY
インテントの処理と同じ形式でデータを返します。
ハブに接続されたデバイスにコマンドを送信する
ハブに接続されたエンドデバイスを制御するには、ハブがコマンド対象のデバイスを識別できるよう、ハブに送信されるプロトコル固有のコマンドのペイロードに、追加情報を提供する必要があります。これは device.id
値から直接推定できる場合もありますが、推定できない場合は、この追加データを customData
フィールドの一部として含める必要があります。
TypeScript を使用してアプリを作成した場合は、必ずアプリを JavaScript にコンパイルしてください。任意のモジュール システムを使用してコードを作成できます。 ターゲットが Chrome ブラウザでサポートされていることをご確認ください。