Aby obsługiwać realizację lokalną, musisz utworzyć aplikację do obsługi tych intencji inteligentnego domu:
IDENTIFY
: obsługuje wykrywanie urządzeń, którymi można sterować lokalnie. Moduł obsługi intencji wyodrębnia dane, które urządzenie zwraca podczas wykrywania, i wysyła je w odpowiedzi do Google.EXECUTE
: obsługuje wykonywanie poleceń.QUERY
: obsługuje wysyłanie zapytań o stan urządzenia.REACHABLE_DEVICES
: (opcjonalnie) obsługuje wykrywanie kontrolowanych lokalnie urządzeń końcowych za urządzeniem centralnym (lub mostkiem).
Ta aplikacja działa na urządzeniach Google Home lub Google Nest użytkownika i łączy Twoje urządzenie z Asystentem. Aplikację możesz utworzyć przy użyciu języka TypeScript (preferowany sposób) lub JavaScriptu.
Zalecamy korzystanie z TypeScriptu, ponieważ możesz wykorzystać powiązania, by statycznie mieć pewność, że dane zwracane przez aplikację są zgodne z typami, których oczekuje platforma.
Więcej informacji o tym interfejsie znajdziesz w dokumentacji interfejsu Local Home SDK API.
Poniższe fragmenty kodu pokazują, jak zainicjować lokalną aplikację do realizacji zamówień i dołączyć moduły obsługi.
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"); });
Tworzenie projektu
Aby wdrożyć lokalną aplikację do realizacji zamówień, musisz utworzyć pakiet JavaScript dla swojego kodu i wszystkich jego zależności.
Użyj inicjatora projektu w lokalnej aplikacji do realizacji zamówień, aby uruchomić odpowiednią strukturę projektu z preferowaną konfiguracją pakietu.
Szablony projektu
Aby wybrać konfigurację usługi tworzenia pakietów, uruchom polecenie npm init
w sposób pokazany poniżej:
TypeScript bez konfiguracji programu pakowania:
npm init @google/local-home-app project-directory/ --bundler none
Struktura projektu:
project-directory/ ├── node_modules/ ├── package.json ├── .gitignore ├── index.ts ├── test.ts ├── tsconfig.json ├── tslint.json └── serve.js
Zastąp project-directory nowym katalogiem, który będzie zawierał projekt lokalnej aplikacji do realizacji zamówień.
TypeScript z konfiguracją pakietu webpack:
npm init @google/local-home-app project-directory/ --bundler webpack
Struktura projektu:
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
Zastąp project-directory nowym katalogiem, który będzie zawierał projekt lokalnej aplikacji do realizacji zamówień.
TypeScript z konfiguracją pakietu Rollup:
npm init @google/local-home-app project-directory/ --bundler rollup
Struktura projektu:
project-directory/ ├── node_modules/ ├── package.json ├── .gitignore ├── index.ts ├── test.ts ├── tsconfig.json ├── tslint.json ├── rollup.config.js └── serve.js
Zastąp project-directory nowym katalogiem, który będzie zawierał projekt lokalnej aplikacji do realizacji zamówień.
TypeScript z konfiguracją pakietu Parcel:
npm init @google/local-home-app project-directory/ --bundler parcel
Struktura projektu:
project-directory/ ├── node_modules/ ├── package.json ├── .gitignore ├── index.ts ├── test.ts ├── tsconfig.json ├── tslint.json └── serve.js
Zastąp project-directory nowym katalogiem, który będzie zawierał projekt lokalnej aplikacji do realizacji zamówień.
Wykonywanie typowych zadań na poziomie projektu
Wygenerowany projekt obsługuje te skrypty npm:
cd project-directory/ npm run build
Ten skrypt kompiluje źródło TypeScript i łączy Twoją aplikację z zależnościami środowiska wykonawczego Chrome w podkatalogu dist/web
i środowisku wykonawczym Node.js w podkatalogu dist/node
.
cd project-directory/ npm run lint npm run compile npm test
Ten skrypt weryfikuje składnię kodu TypeScript, kompiluje go bez generowania żadnych danych wyjściowych w podkatalogu dist/
i uruchamia automatyczne testy w test.ts
.
cd project-directory/ npm run start
W trakcie programowania skrypt ten udostępnia pakiety aplikacji lokalnie w środowiskach wykonawczych Chrome i Node.js.
Implementowanie modułu obsługi IDENTIFY
Moduł obsługi IDENTIFY
uruchomi się po ponownym uruchomieniu urządzenia Google Home lub Google Nest i zobaczy niezweryfikowane urządzenia lokalne (w tym urządzenia połączone z koncentratorem). Platforma Local Home będzie szukać urządzeń lokalnych przy użyciu podanych wcześniej informacji o konfiguracji skanowania, a następnie wywoła moduł obsługi IDENTIFY
z wynikami skanowania.
IdentifyRequest
z platformy Lokalna strona główna zawiera dane skanowania instancji LocalIdentifiedDevice
. Zapełniona jest tylko 1 instancja device
na podstawie konfiguracji skanowania, która wykryła urządzenie.
Jeśli wyniki skanowania są zgodne z Twoim urządzeniem, moduł obsługi IDENTIFY
powinien zwrócić obiekt IdentifyResponsePayload
, który zawiera obiekt device
z metadanymi inteligentnego domu (np. typy, cechy i stan raportu).
Google ustanawia powiązanie urządzenia, jeśli verificationId
z odpowiedzi IDENTIFY
odpowiada jednej z wartości otherDeviceIds
zwróconych przez odpowiedź SYNC
.
Przykład
Poniższe fragmenty kodu pokazują, jak możesz utworzyć moduły obsługi IDENTIFY
odpowiednio na potrzeby integracji samodzielnych urządzeń i centrum.
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; };
Identyfikowanie urządzeń za koncentratorem
Jeśli Google zidentyfikuje urządzenie centralne, potraktuje je jako kanał do podłączonych do niego urządzeń końcowych i spróbuje zweryfikować te urządzenia.
Aby umożliwić Google potwierdzenie obecności urządzenia centralnego, postępuj zgodnie z tymi instrukcjami dotyczącymi modułu obsługi IDENTIFY
:
- Jeśli odpowiedź
SYNC
zawiera identyfikatory lokalnych urządzeń końcowych połączonych z centrum, ustawisProxy
jakotrue
wIdentifyResponsePayload
. - Jeśli odpowiedź
SYNC
nie zgłasza urządzenia centralnego, ustawisLocalOnly
jakotrue
wIdentifyResponsePayload
. - Pole
device.id
zawiera lokalny identyfikator samego urządzenia centralnego.
Wdróż moduł obsługi REACHABLE_DEVICES (tylko integracje z centrum)
Google wysyła intencję REACHABLE_DEVICES
do sprawdzania, które urządzenia końcowe mogą być sterowane lokalnie. Ta intencja jest wywoływana za każdym razem, gdy Google przeprowadza skanowanie wykrywania (mniej więcej raz na minutę), o ile urządzenie działa online.
Moduł obsługi REACHABLE_DEVICES
implementujesz podobnie jak moduł obsługi IDENTIFY
, z tym że musi on zbierać dodatkowe identyfikatory urządzeń dostępne dla lokalnego serwera proxy (czyli urządzenia centralnego). Pole device.verificationId
zawiera lokalny identyfikator urządzenia końcowego połączonego z centrum.
ReachableDevicesRequest
z platformy Lokalna strona główna zawiera instancję LocalIdentifiedDevice
.
Dzięki tej instancji możesz uzyskać identyfikator urządzenia proxy, a także dane z wyników skanowania.
Moduł obsługi REACHABLE_DEVICES
powinien zwracać obiekt ReachableDevicesPayload
zawierający obiekt devices
zawierający tablicę verificationId
wartości reprezentujących urządzenia końcowe kontrolowane przez centrum. Wartości verificationId
muszą pasować do jednej z wartości otherDeviceIds
w odpowiedzi SYNC
.
Poniższy fragment kodu pokazuje, jak możesz utworzyć moduł obsługi 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; };
Implementowanie modułu obsługi wykonywania poleceń EXECUTE
Moduł obsługi EXECUTE
w aplikacji przetwarza polecenia użytkownika i używa pakietu SDK Local Home do uzyskiwania dostępu do urządzeń za pomocą dotychczasowego protokołu.
Platforma lokalna strona główna przekazuje ten sam ładunek wejściowy do funkcji obsługi EXECUTE
co w przypadku intencji EXECUTE
w ramach realizacji w chmurze. Podobnie moduł obsługi EXECUTE
zwraca dane wyjściowe w tym samym formacie co podczas przetwarzania intencji EXECUTE
.
Aby uprościć tworzenie odpowiedzi, możesz użyć klasy Execute.Response.Builder
dostępnej w pakiecie Local Home SDK.
Aplikacja nie ma bezpośredniego dostępu do adresu IP urządzenia. Zamiast tego użyj interfejsu CommandRequest
do tworzenia poleceń opartych na jednym z tych protokołów: UDP, TCP lub HTTP. Następnie wywołaj funkcję deviceManager.send()
, aby wysłać polecenia.
Podczas kierowania poleceń na urządzenia używaj identyfikatora urządzenia (i parametrów z pola customData
, jeśli są uwzględnione) z odpowiedzi SYNC
, aby komunikować się z urządzeniem.
Przykład
Poniższy fragment kodu pokazuje, jak możesz utworzyć moduł obsługi 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()); };
Implementacja modułu obsługi zapytania QUERY
Moduł obsługi QUERY
w aplikacji przetwarza żądania użytkowników i używa pakietu SDK Local Home do raportowania stanu urządzeń.
Platforma lokalna strona główna przekazuje ten sam ładunek żądania do funkcji obsługi „QUERY” jak w przypadku intencji QUERY
w realizacji w chmurze. Podobnie moduł obsługi QUERY
zwraca dane w tym samym formacie co podczas przetwarzania intencji QUERY
.
Wysyłanie poleceń do urządzeń za koncentratorem
W przypadku sterowania urządzeniami końcowymi za koncentratorem konieczne może być podanie dodatkowych informacji w ładunku poleceń protokołu wysyłanym do centrum, aby centrum mogło rozpoznać, do jakiego urządzenia jest przeznaczone to polecenie. W niektórych przypadkach można to wywnioskować bezpośrednio na podstawie wartości device.id
, ale gdy tak nie jest, należy uwzględnić te dodatkowe dane w polu customData
.
Jeśli Twoja aplikacja została utworzona za pomocą TypeScriptu, pamiętaj o jej skompilowaniu pod kątem JavaScriptu. Do pisania kodu możesz użyć wybranego systemu modułów. Upewnij się, że wartość docelowa jest obsługiwana przez przeglądarkę Chrome.