Debugowanie lokalnego domu

1. Zanim zaczniesz

Integracja z inteligentnym domem umożliwia Asystentowi Google sterowanie połączonymi urządzeniami w domach użytkowników. Aby stworzyć integrację między chmurami, musisz podać punkt końcowy webhooka w chmurze, który może obsługiwać intencje inteligentnego domu. Gdy na przykład użytkownik powie „OK Google, włącz światła”, Asystent wysyła polecenie do przetwarzania w chmurze, aby zaktualizować stan urządzenia.

Pakiet SDK Local Home zwiększa niezawodność integracji inteligentnego domu, dodając lokalną ścieżkę, po której intencje inteligentnego domu są kierowane bezpośrednio do urządzenia Google Home. Dzięki temu zwiększa się niezawodność i zmniejsza opóźnienie w przetwarzaniu poleceń użytkowników. Umożliwia ona pisanie i wdrażanie aplikacji do lokalnego przetwarzania w języku TypeScript lub JavaScript, która identyfikuje urządzenia i wykonuje polecenia na dowolnym głośniku Google Home lub inteligentnym ekranie Google Nest. Aplikacja komunikuje się bezpośrednio z dotychczasowymi inteligentnymi urządzeniami użytkowników przez sieć lokalną, używając do wykonywania poleceń istniejących standardowych protokołów.

72ffb320986092c.png

Debugowanie integracji między chmurami jest kluczowym krokiem w procesie tworzenia integracji o jakości produkcyjnej, ale bez przydatnych, łatwych w użyciu narzędzi do rozwiązywania problemów i testowania może być trudne i czasochłonne. Aby ułatwić debugowanie integracji między chmurami, Google Cloud Platform (GCP) udostępnia Dane i Dziennikowanie oraz Test Suite dla inteligentnego domu, które ułatwiają identyfikowanie i rozwiązywanie problemów z integracją.

Wymagania wstępne

Co utworzysz

W tym ćwiczeniu z programowania utworzysz lokalną usługę realizacji dla integracji między chmurami i połączysz ją z Asystentem. Następnie przeprowadzisz debugowanie aplikacji Local Home za pomocą zestawu testów dla inteligentnego domu oraz funkcji raportowania i rejestrowania Google Cloud Platform (GCP).

Czego się nauczysz

  • Jak używać danych i rejestru GCP do wykrywania i rozwiązywania problemów w produkcji
  • Jak za pomocą pakietu testów zidentyfikować problemy z funkcjonalnością i interfejsem API.
  • Jak korzystać z Narzędzi deweloperskich w Chrome podczas tworzenia aplikacji Local Home.

Czego potrzebujesz

2. Uruchamianie aplikacji pralki

Pobieranie kodu źródłowego

Aby pobrać na maszynę programistyczną przykładowy projekt tego ćwiczenia, kliknij ten link:

...lub możesz sklonować repozytorium GitHub z poziomu wiersza poleceń:

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

Informacje o projekcie

Aplikacja startowa zawiera podobne podkatalogi i funkcje w chmurze co Włączanie lokalnego przetwarzania w ramach integracji między chmurami. Zamiast app-start mamy tu app-faulty. Zaczniemy od lokalnej aplikacji domowej, która działa, ale niezbyt dobrze.

Połącz się z Firebase

Użyjemy tego samego projektu, który został utworzony w ramach ćwiczenia Włączanie lokalnego przetwarzania w ramach integracji między usługami w chmurze, ale wdrożony zostanie plik pobrany w tym ćwiczeniu.

Przejdź do katalogu app-faulty, a potem skonfiguruj interfejs wiersza poleceń Firebase za pomocą projektu integracji utworzonego w ramach ćwiczenia Włączanie lokalnego przetwarzania w ramach integracji między chmurami:

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

Wdrażanie w Firebase

Otwórz folder app-faulty/functions i zainstaluj wszystkie niezbędne zależności za pomocą npm:

$ cd functions
$ npm install

Uwaga: jeśli zobaczysz ten komunikat, możesz go zignorować i kontynuować. Ostrzeżenie jest spowodowane niektórymi 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

Aby pobrać kompilator TypeScript i skompilować aplikację, otwórz katalog app-faulty/local/ i uruchom te polecenia:

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

Skompiluje to źródło index.ts (TypeScript) i umieści w katalogu app-faulty/public/local-home/ te pliki:

  • bundle.js – skompilowany kod JavaScript zawierający lokalną aplikację i zależne komponenty.
  • index.html – strona hostingu lokalnego używana do obsługi aplikacji na potrzeby testowania na urządzeniu.

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

$ firebase deploy

Dane wyjściowe konsoli powinny wyglądać tak:

...

✔ 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ą wraz z kilkoma funkcjami Cloud Functions dla Firebase.

Aktualizowanie HomeGraph

Otwórz adres URL hostingu w przeglądarce (https://<project-id>.web.app), aby wyświetlić aplikację internetową. W interfejsie internetowym kliknij przycisk Odświeżae8d3b25777a5e30.png, aby zaktualizować HomeGraph za pomocą żądania synchronizacji z najnowszymi metadanymi urządzenia z wadliwej aplikacji do prania:

fa3c47f293cfe0b7.png

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

2a082ee11d47ad1a.png

3. Uruchomić inteligentną pralkę

Jeśli masz już ukończone ćwiczenie Włączanie lokalnego wypełniania w przypadku integracji chmura–chmura, powinna być już uruchomiona wirtualna inteligentna pralka. Jeśli się zatrzyma, uruchom ponownie urządzenie wirtualne.

Uruchomienie urządzenia

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 lokalnej aplikacji Home

Wysyłanie poleceń do urządzenia za pomocą poleceń głosowych do urządzenia Google Home, takich jak:

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

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

„OK Google, włącz lokalnie”

„OK Google, zatrzymaj pralkę”.

Gdy spróbujesz sterować pralką po „wymuszeniu lokalnego”, Asystent Google odpowie: „Wygląda na to, że pralka Faulty nie jest obecnie dostępna”.

Oznacza to, że nie można połączyć się z urządzeniem przez lokalną ścieżkę. Działo się tak przed wydaniem polecenia „Hej Google, wymuś lokalny tryb”, ponieważ w przypadku braku dostępu do urządzenia przez lokalny tryb użyjemy ścieżki w chmurze. Jednak po wybraniu opcji „Wymuś lokalnie” opcja korzystania z ścieżki w chmurze jest wyłączona.

Aby dowiedzieć się, na czym polega problem, użyjmy dostępnych narzędzi: DaneLogowanie Google Cloud Platform (GCP) oraz Narzędzia deweloperskie w Chrome.

5. Debugowanie aplikacji Home na urządzeniu

W tej sekcji użyjesz narzędzi udostępnionych przez Google, aby dowiedzieć się, dlaczego nie można połączyć się z urządzeniem przez lokalną ścieżkę. Możesz użyć Narzędzi programistycznych Google Chrome, aby połączyć się z urządzeniem Google Home, wyświetlić dzienniki konsoli i przeprowadzić debugowanie aplikacji Local Home. Możesz też wysłać dzienniki niestandardowe do Cloud Logging, aby dowiedzieć się, jakie błędy najczęściej znajdują użytkownicy w aplikacji Local Home.

Łączenie z Narzędziami deweloperskimi w Chrome

Aby połączyć debuger z aplikacją do obsługi lokalnej, wykonaj te czynności:

  1. Upewnij się, że urządzenie Google Home jest połączone z użytkownikiem, który ma uprawnienia do dostępu do projektu Konsoli programisty.
  2. Zrestartuj urządzenie Google Home, aby umożliwić mu pobranie adresu URL pliku HTML oraz konfiguracji skanowania z konsoli dla deweloperów.
  3. Uruchom Chrome na komputerze programisty.
  4. Otwórz nową kartę w Chrome i w polu adresu wpisz chrome://inspect, aby uruchomić inspekcję.

Na stronie powinna wyświetlić się lista urządzeń, a adres URL aplikacji powinien być widoczny pod nazwą urządzenia Google Home.

567f97789a7d8846.png

Uruchamianie inspektora

Aby otworzyć narzędzia Chrome dla programistów, kliknij Sprawdź pod adresem URL aplikacji. Kliknij kartę Konsola i sprawdź, czy widzisz treść intencji IDENTIFY wydrukowanej przez aplikację TypeScript.

774c460c59f9f84a.png

Ten wynik oznacza, że został wywołany odpowiedni moduł obsługi IDENTIFY, ale wartość verificationId zwracana w IdentifyResponse nie pasuje do żadnego z urządzeń w Twoim HomeGraph. Aby się tego dowiedzieć, dodajmy kilka niestandardowych dzienników.

Dodawanie niestandardowych logów

Pakiet SDK Local Home zwraca błąd DEVICE_VERIFICATION_FAILED, który nie pomaga w znalezieniu głównej przyczyny problemu. Dodajmy kilka dzienników niestandardowych, aby mieć pewność, że prawidłowo odczytujemy i przetwarzamy dane skanowania. Pamiętaj, że jeśli odrzucimy obietnicę z błędem, komunikat o błędzie zostanie również 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 Home, abyśmy mogli sprawdzić, czy używasz prawidłowej wersji.

local/index.ts

const localHomeSdk = new App('1.0.1');

Po dodaniu niestandardowych dzienników musisz ponownie skompilować aplikację i ponownie ją wdrożyć w Firebase.

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

Teraz uruchom ponownie urządzenie Google Home, aby załadować zaktualizowaną lokalną aplikację domową. Aby sprawdzić, czy urządzenie Google Home używa oczekiwanej wersji, sprawdź dzienniki Konsoli w narzędziach dla programistów Chrome.

ecc56508ebcf9ab.png

Dostęp do Cloud Logging

Zobacz, jak używać Cloud Logging do znajdowania błędów. Aby uzyskać dostęp do Cloud Logging w 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 logowania w przypadku użytkowników projektu integracji zarządza usługa Identity and Access Management (IAM). Więcej informacji o rolach i uprawnieniach dotyczących logowania danych znajdziesz w artykule o kontroli dostępu w Logowaniu w chmurze.

Korzystanie z filtrów zaawansowanych

Wiemy, że występują błędy w intencji IDENTIFY, ponieważ ścieżka lokalna nie działa, ponieważ nie można zidentyfikować lokalnego urządzenia. Chcemy jednak wiedzieć, na czym dokładnie polega problem, więc najpierw odfiltrujmy błędy występujące w obiekcie IDENTIFY.

Kliknij przełącznik Pokaż zapytanie, aby przełączyć go w pole Konstruktor zapytań. Wpisz jsonPayload.intent="IDENTIFY" w polu Konstruktor zapytań i kliknij przycisk Uruchom zapytanie.

4c0b9d2828ee2447.png

W efekcie otrzymujesz wszystkie dzienniki błędów wygenerowane w obiekcie IDENTIFY. Następnie rozwiń ostatni błąd. W modułach obsługi IDENTIFY znajdziesz parametry errorCodedebugString, które zostały ustawione podczas odrzucania obietnicy.

71f2f156c6887496.png

debugString wynika, że identyfikator lokalnego urządzenia ma nieprawidłowy format. Aplikacja Local Home oczekuje, że identyfikator lokalnego urządzenia będzie ciągiem znaków zaczynającym się od deviceid, po którym następują 3 cyfry, ale identyfikator lokalnego urządzenia jest tu ciągiem szesnastkowym.

Naprawianie błędu

Wracając do kodu źródłowego, w którym analizujemy identyfikator lokalnego urządzenia na podstawie danych ze skanowania, zauważamy, że podczas konwertowania ciągu na bajty nie podano kodowania. Dane skanowania są odbierane jako ciąg szesnastkowy, dlatego podczas wywoływania funkcji Buffer.from() należy podać kodowanie znaków hex.

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 Home, abyśmy mogli sprawdzić, czy używasz prawidłowej wersji.

local/index.ts

const localHomeSdk = new App('1.0.2');

Po naprawieniu błędu skompiluj aplikację i ponownie wdroń ją na Firebase. W app-faulty/local uruchom:

$ npm run build
$ firebase deploy --only hosting

Testowanie poprawki

Po wdrożeniu zrestartuj urządzenie Google Home, aby załadować zaktualizowaną lokalną aplikację domową. Upewnij się, że wersja lokalnej aplikacji domowej to 1.0.2. Tym razem w konsoli Chrome DevTools nie powinno być żadnych błędów.

c8456f7b5f77f894.png

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

„OK Google, włącz tryb lokalny”.

„OK Google, zatrzymaj pralkę”.

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

„OK Google, ustaw domyślnie”.

6. Uruchomienie zestawu testów urządzeń inteligentnego domu

Po zweryfikowaniu urządzenia za pomocą elementów sterujących w aplikacji Google Home lub poleceń głosowych możesz użyć automatycznego pakietu testów dla domu inteligentnego, aby zweryfikować przypadki użycia na podstawie typów urządzeń i właściwości powiązanych z integracją. Pakiet testów przeprowadza serię testów w celu wykrycia problemów z integracją i wyświetla komunikaty informacyjne o nieudanych testach, aby przyspieszyć debugowanie przed zapoznaniem się z dziennikami zdarzeń.

Uruchamianie pakietu testów inteligentnego domu

Aby przetestować integrację między chmurami za pomocą Test Suite, wykonaj te czynności:

  1. W przeglądarce otwórz Test Suite for smart home (Zestaw testów dla inteligentnych urządzeń domowych).
  2. Zaloguj się w Google, klikając przycisk w prawym górnym rogu. Dzięki temu pakiet testów może wysyłać polecenia bezpośrednio do Asystenta Google.
  3. W polu Identyfikator projektu wpisz identyfikator projektu integracji między chmurami. Aby kontynuować, kliknij DALEJ.
  4. Na etapie Ustawienia testu w sekcji Urządzenia i ślady powinieneś zobaczyć pralkę Faulty Washer.
  5. Wyłącz opcję Testuj synchronizację żądań, ponieważ przykładowa aplikacja do prania nie ma interfejsu użytkownika umożliwiającego dodawanie, usuwanie ani zmianę nazwy pralki. W systemie produkcyjnym musisz wywołać Request Sync (Wyślij żądanie synchronizacji) za każdym razem, gdy użytkownik dodaje, usuwa lub zmienia nazwę urządzenia.
  6. Pozostaw włączoną opcję Local Home SDK, ponieważ będziemy testować ścieżki lokalne i w chmurze.
  7. Aby rozpocząć testowanie, kliknij Dalej: środowisko testowe.

67433d9190fa770e.png

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

d1ebd5cfae2a2a47.png

Analizowanie komunikatu o błędzie

Sprawdź komunikaty o błędach w nieudanych przypadkach testowych. Podają one oczekiwany stan testu i jego rzeczywisty stan. W tym przypadku stan oczekiwany dla „Wstrzymaj pranie” to isPaused: true, ale rzeczywisty stan to isPaused: false. Podobnie w przypadku „Wstrzymaj pranie” oczekiwany stan to isPaused: true, ale uzyskaliśmy stan isPaused: false.

6bfd3acef9c16b84.png

Z komunikatów o błędach wynika, że na ścieżce lokalnej odwrotnie ustawiamy stan isPaused.

Identyfikowanie i naprawianie błędu

Znajdź kod źródłowy, w którym aplikacja Local Home wysyła polecenie wykonania do urządzenia. getDataCommand() to funkcja wywoływana przez executeHandler() w celu ustawienia wartości payload w poleceniu wykonania wysłanym do urządzenia.

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 {};
    }
}

Ustawienie isPause jest odwrotne, powinno być true, gdy params.pause ma wartość true, a w przeciwnym razie – false. Naprawmy to.

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ń lokalną wersję aplikacji domowej, abyśmy mogli sprawdzić, czy używamy prawidłowej wersji.

local/index.ts

const localHomeSdk = new App('1.0.3');

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

$ npm run build
$ firebase deploy --only hosting

Teraz uruchom ponownie urządzenie Google Home, aby załadować zaktualizowaną lokalną aplikację domową. Upewnij się, że wersja lokalnej aplikacji domowej to 1.0.3.

Testowanie poprawki

Teraz ponownie uruchom zestaw testów dla inteligentnego domu z tymi samymi konfiguracjami. Zobaczysz, że wszystkie przypadki testowe zostały zaliczone.

b7fc8c5d3c727d8d.png

7. Gratulacje

764dbc83b95782a.png

Gratulacje! Wiesz już, jak rozwiązywać problemy z aplikacją Google Home na urządzeniu lokalnym za pomocą pakietu testów dla inteligentnych urządzeń domowych i zapisów w chmurze.

Więcej informacji

Oto kilka dodatkowych rozwiązań, które możesz wypróbować:

Możesz też dowiedzieć się więcej o testowaniu i przesyłaniu integracji do sprawdzenia, w tym o procesie certyfikacji w celu opublikowania integracji dla użytkowników.