Aby obsługiwać realizację zamówień lokalnych, musisz utworzyć aplikację, która będzie obsługiwać te intencje związane z inteligentnym domem:
IDENTIFY: obsługuje wykrywanie inteligentnych urządzeń, którymi można sterować lokalnie. Obsługa intencji wyodrębnia dane, które inteligentne urządzenie zwraca podczas wykrywania, i wysyła je w odpowiedzi do Google.EXECUTE: obsługuje wykonywanie poleceń.QUERY: umożliwia wysyłanie zapytań o stan urządzenia.REACHABLE_DEVICES: (Opcjonalnie) obsługuje wykrywanie urządzeń końcowych, którymi można sterować lokalnie, znajdujących się za centralą (lub mostkiem).
Ta aplikacja działa na urządzeniach Google Home lub Google Nest użytkownika i łączy inteligentne urządzenie z Asystentem. Aplikację możesz utworzyć za pomocą TypeScriptu (zalecane) lub JavaScriptu.
Zalecamy używanie TypeScriptu, ponieważ możesz korzystać z powiązań, aby statycznie sprawdzać, czy dane zwracane przez aplikację są zgodne z typami oczekiwanymi przez platformę.
Więcej informacji o interfejsie API znajdziesz w dokumentacji Local Home SDK API.
Poniższe fragmenty kodu pokazują, jak zainicjować aplikację do realizacji zamówień lokalnych i dołączyć do niej 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ć aplikację do realizacji zamówień lokalnych, musisz utworzyć pakiet JavaScript dla swojego kodu i wszystkich jego zależności.
Użyj aplikacji do realizacji zamówień lokalnych project initializer, aby zainicjować odpowiednią strukturę projektu z preferowaną konfiguracją narzędzia do łączenia modułów.
Szablony projektów
Aby wybrać konfigurację narzędzia do łączenia, uruchom polecenie npm init, jak pokazano w tych przykładach:
TypeScript bez konfiguracji narzędzia do łączenia:
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 aplikacji do realizacji zamówień lokalnych.
TypeScript z konfiguracją narzędzia do łączenia 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 aplikacji do realizacji zamówień lokalnych.
TypeScript z konfiguracją narzędzia do łączenia plików 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 aplikacji do realizacji zamówień lokalnych.
TypeScript z konfiguracją narzędzia do łączenia plików 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 aplikacji do realizacji zamówień lokalnych.
Wykonywanie typowych czynności na poziomie projektu
Wygenerowany projekt obsługuje te skrypty npm:
cd project-directory/ npm run build
Ten skrypt kompiluje źródło TypeScript i pakuje aplikację wraz z zależnościami dla środowiska wykonawczego Chrome w podkatalogu dist/web oraz dla środowiska wykonawczego 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 danych wyjściowych w podkatalogu dist/ i uruchamia automatyczne testy z test.ts.
cd project-directory/ npm run start
Podczas programowania ten skrypt lokalnie udostępnia pakiety aplikacji dla środowisk wykonawczych Chrome i Node.js.
Zaimplementuj moduł obsługi IDENTIFY
Procedura obsługi IDENTIFY zostanie uruchomiona, gdy urządzenie Google Home lub Google Nest zostanie ponownie uruchomione i wykryje niezweryfikowane urządzenia lokalne (w tym urządzenia końcowe podłączone do centrali). Platforma Local Home przeskanuje urządzenia lokalne, korzystając z informacji o konfiguracji skanowania podanych wcześniej, i wywoła Twój moduł obsługi IDENTIFY z wynikami skanowania.
IdentifyRequest
z platformy Local Home zawiera dane skanowania instancji LocalIdentifiedDevice. Wypełniana jest tylko jedna instancja device na podstawie konfiguracji skanowania, która wykryła urządzenie.
Jeśli wyniki skanowania pasują do urządzenia, moduł obsługi IDENTIFY powinien zwrócić obiekt IdentifyResponsePayload, który zawiera obiekt device z metadanymi inteligentnego domu (takimi jak typy, cechy i stan raportu).
Google tworzy powiązanie urządzenia, jeśli wartość verificationId z odpowiedzi IDENTIFY jest zgodna z jedną z wartości otherDeviceIds zwróconych w odpowiedzi SYNC.
Przykład
Poniższe fragmenty kodu pokazują, jak utworzyć moduły obsługi IDENTIFY w przypadku integracji z samodzielnym urządzeniem i hubem.
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 będące hubem, będzie traktować je jako kanał komunikacji z podłączonymi do niego urządzeniami końcowymi i spróbuje je zweryfikować.
Aby umożliwić Google potwierdzenie obecności urządzenia hub, wykonaj te instrukcje dla IDENTIFYobsługi:
- Jeśli odpowiedź
SYNCzawiera identyfikatory lokalnych urządzeń końcowych połączonych z hubem, ustawisProxyjakotruewIdentifyResponsePayload. - Jeśli odpowiedź
SYNCnie zawiera informacji o urządzeniu hub, ustawisLocalOnlyjakotruewIdentifyResponsePayload. - Pole
device.idzawiera lokalny identyfikator urządzenia dla samego huba.
Zaimplementuj moduł obsługi REACHABLE_DEVICES (tylko integracje z centralą)
Intencja REACHABLE_DEVICES jest wysyłana przez Google w celu potwierdzenia, które urządzenia końcowe mogą być sterowane lokalnie. Ten zamiar jest wywoływany za każdym razem, gdy Google przeprowadza skanowanie wykrywające (mniej więcej raz na minutę), o ile wykryje, że hub jest online.
Implementacja modułu obsługi REACHABLE_DEVICES jest podobna do modułu obsługi IDENTIFY, z tym że moduł obsługi musi zbierać dodatkowe identyfikatory urządzeń dostępne za pomocą lokalnego serwera proxy (czyli huba). Pole
device.verificationId zawiera lokalny identyfikator urządzenia końcowego
połączonego z hubem.
ReachableDevicesRequest
z platformy Local Home zawiera instancję
LocalIdentifiedDevice.
Za pomocą tej instancji możesz uzyskać identyfikator urządzenia proxy oraz dane z wyników skanowania.
Obsługa REACHABLE_DEVICES powinna zwracać obiekt ReachableDevicesPayload, który zawiera obiekt devices z tablicą wartości verificationId reprezentujących urządzenia końcowe sterowane przez koncentrator. Wartości verificationId muszą być zgodne z jedną z wartości otherDeviceIds w odpowiedzi SYNC.
Poniższy fragment kodu pokazuje, jak utworzyć REACHABLE_DEVICEShandler.
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 EXECUTE
Twój moduł obsługi EXECUTE w aplikacji przetwarza polecenia użytkownika i używa pakietu Local Home SDK, aby uzyskać dostęp do inteligentnych urządzeń za pomocą istniejącego protokołu.
Platforma Local Home przekazuje ten sam ładunek wejściowy do funkcji EXECUTEhandler
co w przypadku intencji EXECUTE
do realizacji w chmurze. Podobnie funkcja obsługi EXECUTE zwraca dane wyjściowe w tym samym formacie co w przypadku przetwarzania intencji EXECUTE.
Aby uprościć tworzenie odpowiedzi, możesz użyć klasy Execute.Response.Builder, którą udostępnia pakiet Local Home SDK.
Aplikacja nie ma bezpośredniego dostępu do adresu IP urządzenia. Zamiast tego użyj interfejsu CommandRequest, aby tworzyć polecenia oparte 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 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()); };
Implementowanie modułu obsługi QUERY
Twój moduł obsługi QUERY w aplikacji przetwarza żądania użytkowników i używa pakietu Local Home SDK do raportowania stanu urządzeń inteligentnych.
Platforma Local Home przekazuje do funkcji obsługi „QUERY” ten sam ładunek żądania co w przypadku intencji QUERY do realizacji w chmurze. Podobnie QUERYfunkcja obsługi zwraca daneQUERY w tym samym formacie co w przypadku przetwarzania QUERYintencji.
Wysyłanie poleceń do urządzeń za koncentratorem
Aby sterować urządzeniami końcowymi za koncentratorem, może być konieczne podanie dodatkowych informacji w ładunku polecenia specyficznego dla protokołu wysyłanego do koncentratora. Dzięki temu koncentrator będzie mógł określić, do którego urządzenia jest kierowane polecenie. W niektórych przypadkach można to bezpośrednio wywnioskować z wartości device.id, ale jeśli tak nie jest, należy uwzględnić te dodatkowe dane w polu customData.
Jeśli aplikacja została utworzona przy użyciu TypeScriptu, pamiętaj o skompilowaniu jej do JavaScriptu. Do pisania kodu możesz używać wybranego systemu modułów. Sprawdź, czy miejsce docelowe jest obsługiwane przez przeglądarkę Chrome.