Aby obsługiwać realizację lokalną, musisz utworzyć aplikację, która będzie obsługiwać te intencje inteligentnego domu:
IDENTIFY: umożliwia wykrywanie inteligentnych urządzeń, którymi można sterować lokalnie. Moduł obsługi intencji wyodrębnia dane zwracane przez urządzenie podczas wykrywania i wysyła je w odpowiedzi do Google.EXECUTE: obsługuje wykonywanie poleceń.QUERY: obsługuje sprawdzanie stanu urządzenia.REACHABLE_DEVICES: (opcjonalnie) obsługuje wykrywanie urządzeń końcowych sterowanych lokalnie, które znajdują się za urządzeniem centralnym (lub mostkiem).
Ta aplikacja działa na urządzeniach Google Home lub urządzeniach Google Nest użytkownika i łączy Twoje urządzenie inteligentne z Asystentem. Aplikację możesz utworzyć za pomocą TypeScript (preferowane) lub JavaScriptu.
Zalecamy TypeScript, ponieważ możesz wykorzystać powiązania, aby statycznie zapewnić, że dane zwracane przez aplikację są zgodne z typami oczekiwanymi przez platformę.
Więcej informacji o interfejsie API znajdziesz w dokumentacji interfejsu Local Home SDK API.
Poniższe fragmenty kodu pokazują, jak zainicjować aplikację do realizacji lokalnej 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ć aplikację do realizacji lokalnej, musisz utworzyć pakiet JavaScript dla kodu i wszystkich jego zależności.
Użyj inicjatora projektu aplikacji do realizacji lokalnej, aby utworzyć odpowiednią strukturę projektu z preferowaną konfiguracją bundlera.
Szablony projektów
Aby wybrać konfigurację bundlera, uruchom polecenie npm init, jak pokazano w tych przykładach:
TypeScript bez konfiguracji bundlera:
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 lokalnej.
Konfiguracja TypeScript z pakietem 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 lokalnej.
TypeScript z konfiguracją bundlera 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 lokalnej.
Konfiguracja bundlera TypeScript z 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 lokalnej.
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 aplikację z jej zależnościami dla środowiska wykonawczego Chrome w podkatalogu dist/web i ś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 żadnych 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.
Implementowanie modułu obsługi IDENTIFY
Moduł obsługi IDENTIFY zostanie aktywowany, gdy urządzenie Google Home lub Google Nest uruchomi się ponownie i wykryje niezweryfikowane urządzenia lokalne (w tym urządzenia końcowe połączone z koncentratorem). Platforma Local Home wyszuka urządzenia lokalne, korzystając z podanych wcześniej informacji o konfiguracji skanowania, i wywoła moduł obsługi IDENTIFY z wynikami skanowania.
IdentifyRequest z platformy Local Home zawiera dane skanowania instancji LocalIdentifiedDevice. Wypełniona jest tylko jedna instancja device, na podstawie konfiguracji skanowania, która wykryła urządzenie.
Jeśli wyniki skanowania pasują do Twojego 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 ustanawia powiązanie urządzenia, jeśli wartość verificationId z odpowiedzi IDENTIFY jest zgodna z jedną z wartości otherDeviceIds zwróconych przez odpowiedź SYNC.
Przykład
Poniższe fragmenty kodu pokazują, jak utworzyć moduły obsługi IDENTIFY odpowiednio dla integracji samodzielnych urządzeń i centrów.
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 połączonych z nim urządzeń końcowych i spróbuje je zweryfikować.
Aby umożliwić Google potwierdzenie obecności urządzenia centralnego, wykonaj te instrukcje dotyczące modułu obsługi IDENTIFY:
- Jeśli odpowiedź
SYNCzawiera identyfikatory lokalnych urządzeń końcowych połączonych z koncentratorem, ustawisProxynatruewIdentifyResponsePayload. - Jeśli odpowiedź
SYNCnie zawiera informacji o urządzeniu hub, ustawisLocalOnlyjakotruewIdentifyResponsePayload. - Pole
device.idzawiera identyfikator urządzenia lokalnego dla samego urządzenia centralnego.
Implementowanie modułu obsługi REACHABLE_DEVICES (tylko integracje z koncentratorem)
Google wysyła intencję REACHABLE_DEVICES, aby potwierdzić, którymi urządzeniami końcowymi można sterować lokalnie. Ta intencja jest wywoływana za każdym razem, gdy Google przeprowadza skanowanie wykrywania (mniej więcej raz na minutę), o ile koncentrator jest wykrywany jako online.
Moduł obsługi REACHABLE_DEVICES implementuje się podobnie jak moduł obsługi IDENTIFY, z tą różnicą, że moduł obsługi musi zebrać dodatkowe identyfikatory urządzeń, do których lokalny serwer proxy (czyli centrum) może dotrzeć. Pole device.verificationId zawiera lokalny identyfikator urządzenia końcowego, które jest połączone z koncentratorem.
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.
Twój moduł obsługi REACHABLE_DEVICES powinien zwracać obiekt ReachableDevicesPayload, który zawiera obiekt devices z tablicą wartości verificationId reprezentujących urządzenia końcowe, którymi steruje hub. Wartości verificationId muszą być zgodne z jedną z wartości otherDeviceIds z odpowiedzi SYNC.
Poniższy fragment kodu pokazuje, jak 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 EXECUTE
Moduł obsługi EXECUTE w aplikacji przetwarza polecenia użytkownika i używa pakietu Local Home SDK, aby uzyskiwać dostęp do inteligentnych urządzeń za pomocą istniejącego protokołu.
Platforma Local Home przekazuje do funkcji obsługi EXECUTE te same dane wejściowe co w przypadku zamiaru EXECUTE do realizacji w chmurze. Podobnie moduł 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 SDK Local Home.
Aplikacja nie ma bezpośredniego dostępu do adresu IP urządzenia. Zamiast tego użyj interfejsu CommandRequest, aby utworzyć 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 (oraz 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 zapytania QUERY
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 modułu obsługi „QUERY” te same dane żądania co w przypadku zamiaru QUERY do realizacji w chmurze. Podobnie moduł obsługi QUERY zwraca dane w tym samym formacie co w przypadku przetwarzania intencji QUERY.
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 związanego z protokołem wysyłanego do koncentratora, aby koncentrator mógł zidentyfikować, do którego urządzenia jest skierowane polecenie. W niektórych przypadkach można to wywnioskować bezpośrednio z wartości device.id, ale jeśli nie jest to możliwe, należy dołączyć te dodatkowe dane w polu customData.
Jeśli aplikacja została utworzona za pomocą TypeScript, pamiętaj o jej skompilowaniu do JavaScriptu. Do pisania kodu możesz użyć wybranego systemu modułów. Upewnij się, że cel jest obsługiwany przez przeglądarkę Chrome.