Aby umożliwić realizację zamówień lokalnych, musisz utworzyć aplikację, która będzie obsługiwać te inteligentne zamiary związane z domem:
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 w odpowiedzi do Google.EXECUTE
: obsługuje wykonywanie poleceń.QUERY
: obsługuje zapytania dotyczące stanu urządzenia.REACHABLE_DEVICES
: (opcjonalnie) obsługuje wykrywanie urządzeń dostępnych lokalnie, które można kontrolować za pomocą hubu (lub mostka).
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 TypeScript (preferowanego) lub JavaScriptu.
Zalecamy używanie TypeScript, ponieważ można użyć powiązań, aby statycznie mieć pewność, że zwracane dane są zgodne z oczekiwanymi przez platformę.
Więcej informacji o interfejsie API znajdziesz w dokumentacji API pakietu Home Home SDK.
Poniższe fragmenty kodu pokazują, jak zainicjować lokalną aplikację do realizacji zamówień i dołączać 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 lokalnej aplikacji do realizacji zamówień, aby pobrać odpowiednią strukturę projektu z preferowaną konfiguracją pakietu.
Szablony projektów
Aby wybrać konfigurację pakietu, uruchom polecenie npm init
zgodnie z tymi przykładami:
Skrypt 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ł lokalny projekt realizacji zamówień.
Skrypt 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ł lokalny projekt realizacji zamówień.
Skrypt Type Script z konfiguracją o pełnym zakresie:
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ł lokalny projekt realizacji zamówień.
Skrypt Type Script 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ł lokalny projekt 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 aplikację z zależnościami środowiska wykonawczego Chrome w podkatalogu dist/web
oraz środowiska wykonawczego Node.js w podkatalogu dist/node
.
cd project-directory/ npm run lint npm run compile npm test
Skrypt weryfikuje składnię kodu TypeScript, kompiluje go bez generowania danych wyjściowych w podkatalogu dist/
i uruchamia automatyczne testy aplikacji test.ts
.
cd project-directory/ npm run start
Podczas programowania ten skrypt lokalnie udostępnia pakiety aplikacji na środowiska wykonawcze Chrome i Node.js.
Zaimplementuj moduł obsługi IDENTIFY
Moduł obsługi IDENTIFY
zostanie aktywowany, gdy urządzenie Google Home lub Google Nest uruchomi się ponownie i zauważy niezweryfikowane urządzenia lokalne (w tym urządzenia końcowe połączone z koncentratorem). Platforma lokalna skanuje urządzenia lokalne na podstawie podanych wcześniej informacji o konfiguracji skanowania i wywołuje Twój moduł obsługi IDENTIFY
wraz z wynikami skanowania.
IdentifyRequest
z platformy lokalnej strony głównej zawiera dane skanowania instancji LocalIdentifiedDevice
. Na podstawie konfiguracji skanowania, która wykryła urządzenie, zostało wypełnione tylko jedno wystąpienie device
.
Jeśli wyniki skanowania pasują do urządzenia, moduł obsługi IDENTIFY
powinien zwracać obiekt IdentifyResponsePayload
, który zawiera obiekt device
z inteligentnymi metadanymi domu (takimi jak typ, cechy i stan raportu).
Google tworzy powiązanie urządzenia, jeśli verificationId
w 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
na potrzeby samodzielnych urządzeń i integracji hubu.
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ń w centrum
Jeśli Google wykryje urządzenie hubu, potraktuje je jak kanał zasilający połączone z nim urządzenia końcowe i spróbuje je zweryfikować.
Aby umożliwić Google sprawdzenie, czy urządzenie Hub jest dostępne, wykonaj te czynności dotyczące modułu obsługi IDENTIFY
:
- Jeśli odpowiedź
SYNC
zawiera identyfikatory lokalnych urządzeń końcowych połączonych z centrum, ustawisProxy
natrue
wIdentifyResponsePayload
. - Jeśli odpowiedź
SYNC
nie zgłasza urządzenia Hub, ustawisLocalOnly
jakotrue
wIdentifyResponsePayload
. - Pole
device.id
zawiera identyfikator lokalnego urządzenia centralnego.
Zaimplementuj moduł obsługi REACHABLE_DEVICES (tylko integracja z centrum)
Intencja REACHABLE_DEVICES
jest wysyłana przez Google w celu potwierdzenia, które urządzenia można kontrolować lokalnie. Ta intencja jest wywoływana za każdym razem, gdy Google uruchomi skanowanie wykrywające (mniej więcej raz na minutę), o ile system wykryje, że centrum jest online.
Stosujesz moduł obsługi REACHABLE_DEVICES
w podobny sposób jak w przypadku modułu obsługi IDENTIFY
. Różnica polega na tym, że Twój moduł obsługi musi zbierać dodatkowe identyfikatory urządzeń, do których może uzyskać dostęp lokalny serwer proxy (czyli centrum). Pole device.verificationId
zawiera lokalny identyfikator urządzenia podłączonego do centrum.
ReachableDevicesRequest
z platformy lokalnej strony głównej zawiera instancję LocalIdentifiedDevice
.
W ten sposób możesz uzyskać identyfikator urządzenia proxy i dane z wyników skanowania.
Twój moduł obsługi REACHABLE_DEVICES
powinien zwracać obiekt ReachableDevicesPayload
zawierający obiekt devices
z tablicą wartości verificationId
reprezentujących urządzenia końcowe, które kontroluje centrum. Wartości verificationId
muszą odpowiadać jednej z wartości otherDeviceIds
w odpowiedzi SYNC
.
Fragment kodu poniżej pokazuje, jak utworzyć obsługę modułu 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; };
Wdrażanie modułu obsługi funkcji EXECUTE
Twój moduł obsługi EXECUTE
w aplikacji przetwarza polecenia użytkowników i używa pakietu SDK Home Home, aby uzyskiwać dostęp do urządzeń w ramach istniejącego protokołu.
Platforma lokalna przekazuje ten sam ładunek wejściowy do funkcji obsługi EXECUTE
, co w przypadku EXECUTE
intencji do realizacji chmury. Analogicznie moduł obsługi EXECUTE
zwraca dane wyjściowe w tym samym formacie co przetwarzanie intencji EXECUTE
.
Aby uprościć tworzenie odpowiedzi, możesz użyć klasy Execute.Response.Builder
udostępnianej przez pakiet SDK pakietu Home Home.
Twoja aplikacja nie ma bezpośredniego dostępu do adresu IP urządzenia. Zamiast tego użyj interfejsu CommandRequest
, aby utworzyć polecenia na podstawie jednego 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 (wraz z parametrami z pola customData
, jeśli jest podany) w odpowiedzi SYNC
, aby komunikować się z urządzeniem.
Przykład
Fragment kodu poniżej pokazuje, jak możesz utworzyć moduł obsługi żądania 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()); };
Wdrażanie modułu obsługi QUERY
Twój moduł obsługi QUERY
w aplikacji przetwarza żądania użytkowników i za pomocą SDK lokalnego domu zgłasza stan Twoich urządzeń.
Platforma lokalna przekazuje ten sam ładunek żądania do funkcji obsługi zapytania „QUERY”, co w przypadku intencji QUERY
w celu realizacji chmury. Analogicznie moduł obsługi QUERY
zwraca dane w tym samym formacie co przetwarzanie intencji QUERY
.
Wysyłanie poleceń do urządzeń za centrum
Aby sterować urządzeniami końcowymi za koncentratorem, może być konieczne podanie dodatkowych informacji w ładunku poleceń powiązanym z protokołem wysłanym do centrum w celu określenia, na które urządzenie jest przeznaczone polecenie. W niektórych przypadkach można to bezpośrednio wywnioskować z wartości device.id
, ale gdy tak się nie dzieje, warto uwzględnić te dodatkowe dane w polu customData
.
Jeśli Twoja aplikacja została utworzona za pomocą TypeScriptu, musisz skompilować ją w JavaScript. Do pisania kodu możesz użyć wybranego przez siebie systemu modułów. Upewnij się, że przeglądarka Chrome obsługuje docelowe wartości.