Aby obsługiwać realizację lokalną, musisz utworzyć aplikację, która będzie obsługiwać te intencje dotyczące inteligentnego domu:
IDENTIFY
: obsługa wykrywania inteligentnych urządzeń, którymi można sterować lokalnie. Obsługa intencji wyodrębnia dane, które Twoje urządzenie inteligentne zwraca podczas wykrywania, i wysyła je w odpowiedzi do Google.EXECUTE
: obsługa wykonywania poleceń.QUERY
: obsługa zapytań o stan urządzenia.REACHABLE_DEVICES
: (opcjonalnie) obsługa wykrywania urządzeń końcowych z możliwością sterowania lokalnie za pomocą centrali (lub mostu).
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ą TypeScript (preferowana opcja) lub JavaScriptu.
Zalecamy TypeScript, ponieważ możesz korzystać z wiązań, aby zapewnić statycznie, że dane zwracane przez aplikację są zgodne z typami wymaganymi przez platformę.
Więcej informacji o tym interfejsie API znajdziesz w artykule Referencje interfejsu Local Home SDK API.
Poniższe fragmenty kodu pokazują, jak zainicjować aplikację do obsługi lokalnie dostępnej usługi i dołączyć swoje 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 obsługi lokalnego zamówienia, musisz utworzyć pakiet JavaScriptu dla kodu i wszystkich jego zależności.
Użyj inicjatora projektu aplikacji do obsługi lokalnej, aby uruchomić odpowiednią strukturę projektu z preferowaną konfiguracją pakietu.
Szablony projektów
Aby wybrać konfigurację pakietu, uruchom polecenie npm init
w ten sposób:
TypeScript bez konfiguracji pakietu:
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 obsługi lokalnej.
TypeScript z konfiguracją z użyciem 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 aplikacji do obsługi lokalnej.
TypeScript z konfiguracją 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 obsługi lokalnej.
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 aplikacji do obsługi lokalnej.
Wykonywanie typowych zadań na poziomie projektu
Wygenerowany projekt obsługuje te skrypty npm:
cd project-directory/ npm run build
Ten skrypt kompiluje kod źródłowy TypeScript i tworzy pakiet aplikacji z jej zależnościami dla środowiska wykonawczego Chrome w podkatalogu dist/web
i środowiska wykonawczego Node.js w podkatalogu dist/web
.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 testy automatyczne z katalogu test.ts
.
cd project-directory/ npm run start
Podczas tworzenia skrypt ten lokalnie udostępnia pakiety aplikacji dla środowisk wykonawczych Chrome i Node.js.
Zaimplementuj moduł obsługi IDENTIFY
Obsługa IDENTIFY
zostanie uruchomiona, 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 centralą). Platforma Local Home przeskanuje lokalne urządzenia, korzystając z podanych wcześniej informacji o konfiguracji skanowania, i wywołuje moduł obsługi IDENTIFY
z wynikami skanowania.
Plik IdentifyRequest
z platformy Local Home zawiera dane skanowania instancji LocalIdentifiedDevice
. Na podstawie konfiguracji skanowania, która wykryła urządzenie, wypełniana jest tylko 1 instancja device
.
Jeśli wyniki skanowania pasują do Twojego urządzenia, element obsługi IDENTIFY
powinien zwrócić obiekt IdentifyResponsePayload
, który zawiera obiekt device
z metadanymi inteligentnego domu (np. typami, cechami i stanem raportu).
Google tworzy powiązanie urządzenia, jeśli verificationId
z odpowiedzi IDENTIFY
pasuje do jednej z wartości otherDeviceIds
zwróconych przez odpowiedź SYNC
.
Przykład
Poniższe fragmenty kodu pokazują, jak utworzyć IDENTIFY
dla samodzielnego urządzenia i integracji z 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ń podłączonych do koncentratora
Jeśli Google wykryje urządzenie koncentratora, będzie je traktować jako przewód do urządzeń końcowych z połączonymi urządzeniami końcowymi i będzie próbować je zweryfikować.
Aby umożliwić Google potwierdzenie obecności urządzenia sterującego, wykonaj te instrukcje dotyczące IDENTIFY
:
- Jeśli odpowiedź
SYNC
zawiera identyfikatory lokalnych urządzeń końcowych połączonych z hubem, ustawisProxy
jakotrue
wIdentifyResponsePayload
. - Jeśli odpowiedź
SYNC
nie zawiera informacji o urządzeniu hub, ustawisLocalOnly
jakotrue
wIdentifyResponsePayload
. - Pole
device.id
zawiera lokalny identyfikator urządzenia dla samego urządzenia koncentratora.
Zaimplementuj moduł obsługi REACHABLE_DEVICES (tylko integracje z hubem)
Intencją REACHABLE_DEVICES
jest przesłanie przez Google potwierdzenia, które urządzenia końcowe mogą być kontrolowane lokalnie. Ta intencja jest wywoływana za każdym razem, gdy Google przeprowadza skanowanie w celu wykrywania (około raz na minutę), o ile hub jest online.
Obsługę REACHABLE_DEVICES
wdrażasz podobnie jak obsługę IDENTIFY
, z tym że Twój handler musi zbierać dodatkowe identyfikatory urządzeń dostępne dla lokalnego serwera proxy (czyli urządzenia koncentratora). Pole device.verificationId
zawiera identyfikator lokalnego urządzenia końcowego, które jest połączone z hubem.
Element ReachableDevicesRequest
z platformy Local Home zawiera instancję elementu LocalIdentifiedDevice
.
Dzięki temu możesz uzyskać identyfikator urządzenia proxy oraz dane z wyników skanowania.
Twój handler REACHABLE_DEVICES
powinien zwracać obiekt ReachableDevicesPayload
, który zawiera obiekt devices
zawierający tablicę wartości verificationId
reprezentujących urządzenia końcowe kontrolowane przez hub. Wartości verificationId
muszą być zgodne z wartością otherDeviceIds
w odpowiedzi SYNC
.
W tym fragmencie kodu pokazujemy, jak utworzyć element 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; };
Implementacja modułu obsługi EXECUTTE
Obsługa EXECUTE
w aplikacji przetwarza polecenia użytkownika i korzysta z pakietu SDK Local Home, aby uzyskać dostęp do Twoich urządzeń inteligentnych za pomocą istniejącego protokołu.
Platforma Local Home przekazuje funkcji obsługi EXECUTE
te same dane wejściowe, co w przypadku intencji EXECUTE
do przetwarzania w chmurze. Podobnie, EXECUTE
zwraca dane wyjściowe w tym samym formacie co po przetworzeniu inencji 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
do tworzenia poleceń na podstawie jednego z tych protokołów: UDP, TCP lub HTTP. Następnie wywołaj funkcję deviceManager.send()
, aby wysłać polecenia.
Aby kierować polecenia na urządzenia, użyj identyfikatora urządzenia (oraz parametrów z pola customData
, jeśli jest dostępne) z odpowiedzi SYNC
do komunikacji z urządzeniem.
Przykład
Poniższy fragment kodu pokazuje, jak utworzyć element 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()); };
Zaimplementuj moduł obsługi zapytania.
Handler QUERY
w aplikacji przetwarza żądania użytkownika i korzysta z pakietu Local Home SDK, aby zgłaszać stan urządzeń inteligentnych.
Platforma Local Home przekazuje ten sam ładunek żądania do funkcji obsługi „QUERY” jak w przypadku intencji QUERY
do realizacji w chmurze. Podobnie, QUERY
zwraca dane w tym samym formacie co podczas przetwarzania QUERY
.
Wysyłanie poleceń do urządzeń podłączonych do koncentratora
Aby sterować urządzeniami końcowymi za pomocą koncentratora, konieczne może być podanie dodatkowych informacji w danych ładunku poleceń związanych z danym protokołem, które są wysyłane do koncentratora, aby ten mógł zidentyfikować urządzenie docelowe. W niektórych przypadkach można to określić bezpośrednio na podstawie wartości device.id
, ale jeśli nie jest to możliwe, należy podać te dodatkowe dane w polu customData
.
Jeśli aplikacja została utworzona za pomocą TypeScript, pamiętaj, aby skompilować ją na JavaScript. Do pisania kodu możesz użyć dowolnego systemu modułów. Upewnij się, że przeglądarka Chrome obsługuje docelowy system operacyjny.