Debugowanie lokalnego domu

1. Zanim zaczniesz

Integracja inteligentnego domu pozwala Asystentowi Google sterować połączonymi urządzeniami w domach użytkowników. Aby utworzyć akcję inteligentnego domu, musisz udostępnić punkt końcowy webhooka w chmurze umożliwiający obsługę intencji inteligentnego domu. Jeśli na przykład użytkownik powie „OK Google, włącz światło”, Asystent wyśle polecenie do realizacji w chmurze, aby zaktualizować stan urządzenia.

Pakiet SDK Local Home usprawnia integrację inteligentnego domu przez dodanie lokalnej ścieżki kierującej intencje inteligentnego domu bezpośrednio do urządzenia Google Home. Zwiększa to niezawodność i zmniejsza opóźnienia w przetwarzaniu poleceń użytkownika. Pozwala napisać i wdrożyć w języku TypeScript lub JavaScript aplikację do realizacji lokalnych zamówień, która identyfikuje urządzenia i wykonuje polecenia na dowolnym inteligentnym głośniku Google Home lub inteligentnym ekranie Google Nest. Aplikacja komunikuje się bezpośrednio z dotychczasowymi urządzeniami użytkowników przez sieć lokalną, wykorzystując istniejące standardowe protokoły do wykonywania poleceń.

72ffb320986092c.png

Debugowanie działań w inteligentnym domu jest kluczowym etapem tworzenia akcji o wysokiej jakości produkcyjnej. Jest jednak czasochłonne i trudne, gdy nie ma przydatnych, łatwych w użyciu narzędzi do rozwiązywania problemów i testowania. Aby ułatwić debugowanie akcji w inteligentnym domu, przygotowaliśmy Wskaźniki, Logowanie i Pakiet testowy dla inteligentnego domu w Google Cloud Platform (GCP), które pomogą Ci zidentyfikować i rozwiązać problemy z działaniami.

Wymagania wstępne

Co utworzysz

W ramach tego ćwiczenia w programie utworzysz lokalną realizację działań w inteligentnym domu i połączysz ją z Asystentem, a następnie zdebugujesz aplikację Lokalna dom za pomocą pakietu testowego do zarządzania inteligentnym domem i statystykami oraz logowania w Google Cloud Platform (GCP).

Czego się nauczysz

  • Jak korzystać ze wskaźników GCP i logowania GCP do identyfikowania i rozwiązywania problemów produkcyjnych.
  • Jak za pomocą pakietu Test Suite zidentyfikować problemy z działaniem i interfejsem API.
  • Jak korzystać z narzędzi deweloperskich w Chrome podczas tworzenia aplikacji Lokalny dom.

Czego potrzebujesz

2. Uruchamianie aplikacji pralki

Pobieranie kodu źródłowego

Kliknij poniższy link, aby pobrać na komputerze przykładowy program do przykładowego ćwiczenia:

Możesz też sklonować repozytorium GitHub z wiersza poleceń:

$ git clone https://github.com/google-home/smarthome-debug-local.git

Informacje o projekcie

Aplikacja startowa zawiera podobne podkatalogi i funkcje Cloud jak w przypadku ćwiczeń z programowania Włączanie realizacji lokalnej dla działań inteligentnego domu. Ale zamiast app-start mamy tutaj app-faulty. Zaczniemy od lokalnej aplikacji ekranu głównego, która działa, ale niezbyt dobrze.

Łączenie z Firebase

Wykorzystamy ten sam projekt, który został przez Ciebie utworzony w ramach ćwiczenia z programowania Enable local fulfillment for smart home Actions, ale wdrożymy pliki pobrane w ramach tego ćwiczenia z programowania.

Przejdź do katalogu app-faulty, a następnie skonfiguruj interfejs wiersza poleceń Firebase w projekcie Actions utworzonym w ramach ćwiczenia z programowania Enable local fulfillment for smart home Actions:

$ cd app-faulty
$ firebase use <project-id>

Wdrażanie w Firebase

Przejdź do folderu app-faulty/functions i zainstaluj wszystkie wymagane zależności za pomocą npm:

$ cd functions
$ npm install

Uwaga: jeśli zobaczysz komunikat poniżej, możesz zignorować ten komunikat i kontynuować. Ostrzeżenie jest związane ze starszymi zależnościami. Więcej informacji znajdziesz tutaj.

found 5 high severity vulnerabilities
  run `npm audit fix` to fix them, or `npm audit` for details

Przejdź do katalogu app-faulty/local/ i uruchom te polecenia, aby pobrać kompilator TypeScript i skompilować aplikację:

$ cd ../local
$ npm install
$ npm run build

Spowoduje to skompilowanie źródła index.ts (TypeScript) i umieszczenie tej treści w katalogu app-faulty/public/local-home/:

  • bundle.js – skompilowane dane wyjściowe JavaScriptu zawierające aplikację lokalną i zależności.
  • index.html – lokalna strona hostująca służąca do wyświetlania aplikacji na potrzeby testowania na urządzeniu.

Po zainstalowaniu zależności i skonfigurowaniu projektu możesz po raz pierwszy uruchomić aplikację.

$ firebase deploy

Powinny pojawić się te dane wyjściowe konsoli:

...

✔ Deploy complete!

Project Console: https://console.firebase.google.com/project/<project-id>/overview
Hosting URL: https://<projectcd -id>.web.app

To polecenie wdraża aplikację internetową i kilka funkcji Cloud Functions dla Firebase.

Zaktualizuj wykres domowy

Otwórz w przeglądarce URL hostowania (https://<project-id>.web.app), aby wyświetlić aplikację internetową. W interfejsie internetowym kliknij przycisk Odświeżae8d3b25777a5e30.png, aby zaktualizować HomeGraph za pomocą Poproś o synchronizację o najnowsze metadane urządzenia z nieprawidłowej aplikacji pralki:

fa3c47f293cfe0b7.png

Otwórz aplikację Google Home i sprawdź, czy widzisz pralkę z nową nazwą „Wadliwa pralka”. Pamiętaj, aby przypisać urządzenie do pomieszczenia, w którym znajduje się urządzenie Nest.

2a082ee11d47ad1a.png

3. Uruchom inteligentną pralkę

Jeśli udało Ci się uruchomić zadanie z programowania Włączanie realizacji lokalnej dla działań inteligentnego domu, powinno być już uruchomione wirtualna pralka. Jeśli urządzenie wirtualne zostanie zatrzymane, pamiętaj o uruchomieniu go ponownie.

Uruchom urządzenie

Przejdź do katalogu virtual-device/ i uruchom skrypt urządzenia, przekazując parametry konfiguracji jako argumenty:

$ cd ../../virtual-device
$ npm install
$ npm start -- \
  --deviceId=deviceid123 --projectId=<project-id> \
  --discoveryPortOut=3311 --discoveryPacket=HelloLocalHomeSDK

Sprawdź, czy skrypt urządzenia działa z oczekiwanymi parametrami:

(...): UDP Server listening on 3311
(...): Device listening on port 3388
(...): Report State successful

4. Testowanie aplikacji Lokalny dom

Wysyłaj polecenia głosowe na urządzenie Google Home, na przykład:

„OK Google, włącz moją pralkę”.

„OK Google, włącz pralkę”.

„OK Google, wymuszaj lokalnie”.

„OK Google, zatrzymaj moją pralkę”.

Gdy spróbujesz sterować pralką po użyciu opcji „Wymuszanie lokalnej lokalizacji”, Asystent Google zareaguje tak: „Wygląda na to, że wadliwa pralka jest w tej chwili niedostępna”.

Oznacza to, że urządzenie jest nieosiągalne drogą lokalną. Przed wysłaniem polecenia „OK Google, wymuś działanie lokalne” zadziałało, ponieważ jeśli urządzenie nie jest osiągalne lokalną ścieżką, użyjemy ścieżki w chmurze. Jednak po ustawieniu opcji „Wymuś lokalną” opcja powrotu do ścieżki chmury jest wyłączona.

Aby dowiedzieć się, na czym polega problem, skorzystajmy z naszych narzędzi: Wskaźników i Logowania w Google Cloud Platform (GCP) oraz Narzędzi deweloperskich w Chrome.

5. Debugowanie aplikacji Local Home

W tej sekcji skorzystasz z narzędzi dostarczonych przez Google, aby dowiedzieć się, dlaczego urządzenie jest nieosiągalne drogą lokalną. Za pomocą narzędzi dla deweloperów w Google Chrome możesz połączyć się z urządzeniem Google Home, wyświetlać dzienniki konsoli i debugować aplikację Local Home. Możesz też wysyłać dzienniki niestandardowe do usługi Cloud Logging, aby otrzymywać informacje o najczęstszych błędach występujących w aplikacji Local Home.

Łączenie Narzędzi deweloperskich w Chrome

Aby połączyć debuger z lokalną aplikacją do realizacji zamówień, wykonaj te czynności:

  1. Sprawdź, czy Twoje urządzenie Google Home zostało połączone z użytkownikiem mającym uprawnienia dostępu do projektu w Konsoli Actions.
  2. Zrestartuj urządzenie Google Home, aby uzyskać adres URL Twojego kodu HTML oraz konfigurację skanowania umieszczoną w Konsoli Actions.
  3. Uruchom Chrome na komputerze, na którym pracujesz.
  4. Otwórz nową kartę Chrome i wpisz chrome://inspect w polu adresu, aby uruchomić inspektora.

Na stronie powinna być widoczna lista urządzeń, a adres URL aplikacji powinien pojawić się pod nazwą Twojego urządzenia Google Home.

567f97789a7d8846.png

Uruchom inspektora

Kliknij Zbadaj pod adresem URL aplikacji, aby uruchomić Narzędzia dla programistów w Chrome. Wybierz kartę Console (Konsola) i sprawdź, czy widać treść intencji IDENTIFY drukowaną przez Twoją aplikację TypeScript.

774c460c59f9f84a.png

Te dane oznaczają, że moduł obsługi IDENTYFIKACJI został aktywowany, ale wartość verificationId zwrócona w funkcji IdentifyResponse nie pasuje do żadnego z urządzeń w Home Graph. Dodajmy logi niestandardowe, żeby dowiedzieć się, dlaczego.

Dodaj logi niestandardowe

Pakiet SDK aplikacji Local Home wyświetla błąd DEVICE_VERIFICATION_FAILED, ale nie pomaga w znalezieniu głównej przyczyny. Dodajmy logi niestandardowe, aby mieć pewność, że poprawnie odczytują i przetwarzają dane skanowania. Pamiętaj, że jeśli odrzucimy obietnicę z błędem, komunikat o błędzie też zostanie wysłany do Cloud Logging.

local/index.ts

identifyHandler(request: IntentFlow.IdentifyRequest):
    Promise<IntentFlow.IdentifyResponse> {
  console.log("IDENTIFY intent: " + JSON.stringify(request, null, 2));

  const scanData = request.inputs[0].payload.device.udpScanData;
  if (!scanData) {
    const err = new IntentFlow.HandlerError(request.requestId,
        'invalid_request', 'Invalid scan data');
    return Promise.reject(err);
  }

  // In this codelab, the scan data contains only local device id.
  // Is there something wrong here?
  const localDeviceId = Buffer.from(scanData.data);
  console.log(`IDENTIFY handler: received local device id
      ${localDeviceId}`);

  // Add custom logs
  if (!localDeviceId.toString().match(/^deviceid[0-9]{3}$/gi)) {
    const err = new IntentFlow.HandlerError(request.requestId,
        'invalid_device', 'Invalid device id from scan data ' +
        localDeviceId);
    return Promise.reject(err);
  }

  const response: IntentFlow.IdentifyResponse = {
    intent: Intents.IDENTIFY,
    requestId: request.requestId,
    payload: {
      device: {
        id: 'washer',
        verificationId: localDeviceId.toString(),
      }
    }
  };
  console.log("IDENTIFY response: " + JSON.stringify(response, null, 2));

  return Promise.resolve(response);
}

Zmień też lokalną wersję aplikacji Google Home, żebyśmy mogli określić, czy używamy właściwej wersji.

local/index.ts

const localHomeSdk = new App('1.0.1');

Po dodaniu logów niestandardowych musisz jeszcze raz skompilować aplikację i wdrożyć ją w Firebase.

$ cd ../app-faulty/local
$ npm run build
$ firebase deploy --only hosting

Teraz zrestartuj urządzenie Google Home, by mogło wczytać zaktualizowaną lokalną aplikację Google Home. Aby sprawdzić, czy urządzenie Google Home używa oczekiwanej wersji, przejrzyj dzienniki konsoli w Narzędziach deweloperskich w Chrome.

ecc56508ebcf9ab.png

Dostęp do Cloud Logging

Zobaczmy, jak za pomocą Cloud Logging znajdować błędy. Aby uzyskać dostęp do Cloud Logging w swoim projekcie:

  1. W konsoli Cloud Platform otwórz stronę Projekty.
  2. Wybierz projekt inteligentnego domu.
  3. W sekcji Operacje wybierz Logowanie > Eksplorator logów.

Dostępem do danych logów zarządza się za pomocą Identity and Access Management (IAM) dla użytkowników projektu Actions. Więcej informacji o rolach i uprawnieniach do logowania danych znajdziesz w artykule o kontroli dostępu w Cloud Logging.

Użyj filtrów zaawansowanych

Wiemy, że w intencji IDENTIFY występują błędy, ponieważ ścieżka lokalna nie działa, ponieważ nie udało się zidentyfikować urządzenia lokalnego. Chcemy jednak dowiedzieć się, na czym polega problem, więc najpierw odfiltrujmy błędy występujące w module obsługi IDENTIFY.

Rozwiń pole Podgląd zapytań. Powinno ono zmienić się w pole Konstruktor zapytań. W polu Konstruktor zapytań wpisz jsonPayload.intent="IDENTIFY" i kliknij przycisk Uruchom zapytanie.

4c0b9d2828ee2447.png

W rezultacie otrzymujesz wszystkie logi błędów zgłaszane w module obsługi IDENTIFY. Następnie rozwiń ostatni błąd. Wartości errorCode i debugString ustawione podczas odrzucania obietnicy znajdziesz w module obsługi IDENTIFY.

71f2f156c6887496.png

Na podstawie informacji z debugString widzimy, że lokalny identyfikator urządzenia nie ma oczekiwanego formatu. Aplikacja Local Home oczekuje identyfikatora urządzenia lokalnego w postaci ciągu znaków zaczynającego się od deviceid, po którym następują 3 cyfry, ale lokalny identyfikator urządzenia jest w tym przypadku ciągiem szesnastkowym.

Naprawianie błędu

Wracając do kodu źródłowego, w którym analizujemy lokalny identyfikator urządzenia z danych skanowania, zauważyliśmy, że podczas konwertowania ciągu znaków na bajty nie podano kodowania. Dane skanowania są odbierane w postaci ciągu szesnastkowego, dlatego podczas wywoływania metody Buffer.from() przekazuj hex jako kodowanie znaków.

local/index.ts

identifyHandler(request: IntentFlow.IdentifyRequest):
    Promise<IntentFlow.IdentifyResponse> {
  console.log("IDENTIFY intent: " + JSON.stringify(request, null, 2));

  const scanData = request.inputs[0].payload.device.udpScanData;
  if (!scanData) {
    const err = new IntentFlow.HandlerError(request.requestId,
        'invalid_request', 'Invalid scan data');
    return Promise.reject(err);
  }

  // In this codelab, the scan data contains only local device id.
  const localDeviceId = Buffer.from(scanData.data, 'hex');
  console.log(`IDENTIFY handler: received local device id
      ${localDeviceId}`);

  if (!localDeviceId.toString().match(/^deviceid[0-9]{3}$/gi)) {
    const err = new IntentFlow.HandlerError(request.requestId,
      'invalid_device', 'Invalid device id from scan data ' +
      localDeviceId);
    return Promise.reject(err);
  }

  const response: IntentFlow.IdentifyResponse = {
    intent: Intents.IDENTIFY,
    requestId: request.requestId,
    payload: {
      device: {
        id: 'washer',
        verificationId: localDeviceId.toString(),
      }
    }
  };
  console.log("IDENTIFY response: " + JSON.stringify(response, null, 2));

  return Promise.resolve(response);
}

Zmień też lokalną wersję aplikacji Google Home, żebyśmy mogli określić, czy używamy właściwej wersji.

local/index.ts

const localHomeSdk = new App('1.0.2');

Po naprawieniu błędu skompiluj aplikację i wdróż ją ponownie w Firebase. W app-faulty/local uruchom:

$ npm run build
$ firebase deploy --only hosting

Przetestuj poprawkę

Po wdrożeniu zrestartuj urządzenie Google Home, aby mogło wczytać zaktualizowaną lokalną aplikację Home. Upewnij się, że wersja aplikacji lokalnej to 1.0.2 i tym razem w konsoli narzędzi Chrome Developers Console nie powinny się wyświetlać żadne błędy.

c8456f7b5f77f894.png

Teraz możesz ponownie spróbować wysyłać polecenia do urządzenia.

„OK Google, wymuszaj lokalnie”.

„OK Google, zatrzymaj moją pralkę”.

„OK Google, włącz moją pralkę”.

...

„OK Google, wymuś ustawienie domyślne”.

6. Uruchom Test Suite dla inteligentnego domu

Po zweryfikowaniu urządzenia przy użyciu sterowania dotykowego w aplikacji Google Home lub poleceń głosowych możesz skorzystać z automatycznego pakietu Test Suite dla inteligentnego domu, który pozwala zweryfikować przypadki użycia na podstawie typów urządzeń i cech powiązanych z Twoją akcją. Pakiet testowy przeprowadza serię testów, aby wykryć problemy w akcji, i wyświetla komunikaty dotyczące nieudanych testów, aby przyspieszyć debugowanie przed zagłębieniem się w dzienniki zdarzeń.

Uruchom Test Suite dla inteligentnego domu

Aby przetestować działanie inteligentnego domu Action by Test Suite, wykonaj te czynności:

  1. W przeglądarce otwórz pakiet testowy do inteligentnego domu.
  2. Zaloguj się w Google za pomocą przycisku w prawym górnym rogu. Dzięki temu pakiet Test Suite będzie mógł wysyłać polecenia bezpośrednio do Asystenta Google.
  3. W polu Identyfikator projektu wpisz identyfikator akcji inteligentnego domu. Następnie kliknij DALEJ, aby kontynuować.
  4. W kroku Ustawienia testu w sekcji Urządzenia i procesy powinna być widoczna wadliwa pralka.
  5. Wyłącz opcję Testuj synchronizację żądań, ponieważ przykładowa aplikacja pralki nie ma interfejsu umożliwiającego dodanie, usunięcie lub zmianę nazwy pralki. W systemie produkcyjnym musisz aktywować żądanie synchronizacji za każdym razem, gdy użytkownik dodaje urządzenia, usuwa je lub zmienia ich nazwy.
  6. Pozostaw włączoną opcję Pakiet SDK do lokalnej strony głównej, ponieważ będziemy testować ścieżki lokalne i ścieżki w chmurze.
  7. Aby rozpocząć test, kliknij DALEJ.

67433d9190fa770e.png

Po zakończeniu testów zauważysz, że testy wstrzymywania i wznawiania w ścieżce lokalnej kończą się niepowodzeniem, a testy wstrzymywania i wznawiania w ścieżce chmury nie zakończą się powodzeniem.

d1ebd5cfae2a2a47.png

Analiza komunikatu o błędzie

Przyjrzyj się bliżej komunikatom o błędach, które występują w przypadku nieudanych testów. Dowiesz się z nich, jaki jest oczekiwany stan testu i jego rzeczywisty stan. W tym przypadku oczekiwany stan funkcji „Wstrzymaj pralkę” to isPaused: true, a w rzeczywistości: isPaused: false. I podobnie w przypadku opcji „Wstrzymaj pralkę” oczekiwany stan to isPaused: true, a w rzeczywistości: isPaused: false.

6bfd3acef9c16b84.png

Komunikaty o błędach wskazują na odwrotne ustawienie stanu isPaused w ścieżce lokalnej.

Zidentyfikuj i napraw błąd

Znajdźmy kod źródłowy, w którym aplikacja Local Home wysyła polecenie wykonania na urządzenie. getDataCommand() to funkcja, która wywołuje metodę executeHandler(), aby ustawić payload w poleceniu wykonania przesłanym na urządzenie.

local/index.ts

getDataForCommand(command: string, params: IWasherParams): unknown {
    switch (command) {
        case 'action.devices.commands.OnOff':
            return {
                on: params.on ? true : false
            };
        case 'action.devices.commands.StartStop':
            return {
                isRunning: params.start ? true : false
            };
        case 'action.devices.commands.PauseUnpause':
            return {
                // Is there something wrong here?
                isPaused: params.pause ? false : true
            };
        default:
            console.error('Unknown command', command);
            return {};
    }
}

Rzeczywiście ustawiamy stan isPause w odwrotnym stanie. Powinien on mieć wartość true, gdy params.pause ma wartość true. W przeciwnym razie powinna być ustawiona na false. Zajmijmy się tym.

local/index.ts

getDataForCommand(command: string, params: IWasherParams): unknown {
    switch (command) {
        case 'action.devices.commands.OnOff':
            return {
                on: params.on ? true : false
            };
        case 'action.devices.commands.StartStop':
            return {
                isRunning: params.start ? true : false
            };
        case 'action.devices.commands.PauseUnpause':
            return {
                isPaused: params.pause ? true : false
            };
        default:
            console.error('Unknown command', command);
            return {};
    }
}

Zmień wersję lokalnej aplikacji ekranu głównego, żebyśmy mogli określić, czy używamy właściwej wersji.

local/index.ts

const localHomeSdk = new App('1.0.3');

Pamiętaj, aby ponownie skompilować aplikację i wdrożyć ją w Firebase. W app-faulty/local uruchom:

$ npm run build
$ firebase deploy --only hosting

Teraz zrestartuj urządzenie Google Home, by mogło załadować zaktualizowaną lokalną aplikację Google Home. Upewnij się, że aplikacja Google Home jest w wersji 1.0.3.

Przetestuj poprawkę

Teraz ponownie uruchom pakiet testowy inteligentnego domu z tymi samymi konfiguracjami – okazuje się, że wszystkie przypadki testowe zostały zaliczone.

b7fc8c5d3c727d8d.png

7. Gratulacje

764dbc83b95782a.png

Gratulacje! Wiesz już, jak rozwiązywać problemy z aplikacją Lokalny dom, korzystając z pakietu Test Suite dotyczącego inteligentnego domu i z usługi Cloud Logging.

Więcej informacji

Oto kilka dodatkowych czynności, które możesz wypróbować:

Możesz też dowiedzieć się więcej o testowaniu i przesyłaniu akcji do sprawdzenia, w tym o procesie certyfikacji w celu publikowania go użytkownikom.