Aby obsługiwać realizację zamówień lokalnych, musisz utworzyć aplikację, która będzie obsługiwać te intencje dotyczące inteligentnego domu:
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 interfejsu 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ń w sklepie stacjonarnym project initializer, aby zainicjować odpowiednią strukturę projektu z preferowaną konfiguracją narzędzia do łączenia plikó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 połączone z hubem). 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 IDENTIFY
obsługi:
- 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 koncentratora, ustawisLocalOnly
jakotrue
wIdentifyResponsePayload
. - Pole
device.id
zawiera lokalny identyfikator urządzenia dla samego huba.
Zaimplementuj moduł obsługi REACHABLE_DEVICES (tylko integracje z hubem)
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ępnych 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, a także 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
z odpowiedzi SYNC
.
Poniższy fragment kodu pokazuje, jak utworzyć REACHABLE_DEVICES
handler.
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 EXECUTE
handler
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 QUERY
funkcja obsługi zwraca daneQUERY
w tym samym formacie co w przypadku przetwarzania QUERY
intencjiQUERY
.
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 wywnioskować bezpośrednio 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.