Wydarzenia

Zdarzenia są asynchroniczne i zarządzane przez Google Cloud Pub/Sub w 1 temacie na Project. Zdarzenia zapewniają aktualizacje dla wszystkich urządzeń i struktur. Otrzymywanie zdarzeń jest gwarantowane, o ile token dostępu nie zostanie unieważniony przez użytkownika, a wiadomości o zdarzeniach nie wygasły.

Włącz wydarzenia

Zdarzenia to opcjonalna funkcja interfejsu SDM API. Przeczytaj Włączanie zdarzeń , aby dowiedzieć się, jak je włączyć w domenie Project.

Google Cloud Pub/Sub

Więcej informacji o tym, jak działa Pub/Sub, znajdziesz w dokumentacji Google Cloud Pub/Sub. W szczególności:

Subskrypcja zdarzenia

Po włączeniu zdarzeń w przypadku usługi Projectzobaczysz temat związany z tym identyfikatorem Project w postaci:

projects/sdm-prod/topics/enterprise-project-id

Aby odbierać zdarzenia, utwórz subskrypcję pull lub push do tego tematu, w zależności od przypadku użycia. Obsługiwane jest wiele subskrypcji tematu SDM. Więcej informacji znajdziesz w artykule Zarządzanie subskrypcjami.

Inicjowanie zdarzeń

Aby zainicjować zdarzenia po raz pierwszy po utworzeniu subskrypcji Pub/Sub, wykonaj jednorazowe wywołanie interfejsu API devices.list. Zdarzenia dotyczące wszystkich struktur i urządzeń zostaną opublikowane po zakończeniu tego wywołania.

Zobacz przykład na stronie Autoryzuj w krótkim przewodniku.

Kolejność wydarzeń

Pub/Sub nie gwarantuje uporządkowanego dostarczania zdarzeń, a kolejność ich odbierania może nie odpowiadać kolejności, w której zdarzenia wystąpiły. Pole timestamp ułatwia uzgadnianie kolejności zdarzeń. Zdarzenia mogą też pojawiać się pojedynczo lub być łączone w jedną wiadomość o wydarzeniu.

Więcej informacji znajdziesz w artykule o kolejności wiadomości.

Identyfikatory użytkowników

Jeśli Twoja implementacja opiera się na użytkownikach (a nie na strukturze czy urządzeniu), użyj pola userID z ładunku zdarzenia, aby skorelować zasoby i zdarzenia. To pole to zaciemniony identyfikator reprezentujący konkretnego użytkownika.

Identyfikator userID jest też dostępny w nagłówku odpowiedzi HTTP każdego wywołania interfejsu API.

Zdarzenia związane z relacją

Zdarzenia relacji reprezentują relacyjną aktualizację zasobu. Na przykład gdy urządzenie zostanie dodane do domu lub gdy urządzenie zostanie usunięte z domu.

Wyróżniamy 3 typy zdarzeń relacji:

  • UTWORZONO
  • USUNIĘTY
  • ZAKTUALIZOWANO

Ładunek zdarzenia relacji wygląda tak:

Ładunek

{
  "eventId" : "b121cb59-a477-48ea-a1a9-3e8f4072b34d",
  "timestamp" : "2019-01-01T00:00:01Z",
  "relationUpdate" : {
    "type" : "CREATED",
    "subject" : "enterprises/project-id/structures/structure-id",
    "object" : "enterprises/project-id/devices/device-id"
  },
  "userId": "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi"
}

W przypadku zdarzenia relacji object to zasób, który wywołał zdarzenie, a subject to zasób, z którym interfejs object ma teraz powiązanie. W powyższym przykładzie użytkownik user przyznał dostęp do tego konkretnego urządzenia urządzeniu developer, a autoryzowane urządzenie użytkownika userjest teraz powiązane z autoryzowaną strukturą, która wywołuje zdarzenie.

subject może być tylko pomieszczeniem lub domem. Jeśli a developer nie ma uprawnień do wyświetlania struktury user, subject jest zawsze pusty.

Pola

Pole Opis Typ danych
eventId Unikalny identyfikator zdarzenia. string
Przykład: „101cb31c-e4a8-48c8-b203-d693f5be7d76”
timestamp Czas wystąpienia zdarzenia. string
Przykład: „2019-01-01T00:00:01Z”
relationUpdate Obiekt ze szczegółowymi informacjami o aktualizacji relacji. object
userId Unikalny, zaciemniony identyfikator reprezentujący użytkownika. string
Przykład: „AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi”

Więcej informacji o różnych typach zdarzeń i sposobie ich działania znajdziesz w sekcji Zdarzenia.

Przykłady

Ładunki zdarzeń różnią się w zależności od typu zdarzenia relacji:

UTWORZONO

Utworzono strukturę

"relationUpdate" : {
  "type" : "CREATED",
  "subject" : "",
  "object" : "enterprises/project-id/structures/structure-id"
}

Urządzenie zostało utworzone

"relationUpdate" : {
  "type" : "CREATED",
  "subject" : "enterprises/project-id/structures/structure-id",
  "object" : "enterprises/project-id/devices/device-id"
}

Urządzenie zostało utworzone

"relationUpdate" : {
  "type" : "CREATED",
  "subject" : "enterprises/project-id/structures/structure-id/rooms/room-id",
  "object" : "enterprises/project-id/devices/device-id"
}

ZAKTUALIZOWANO

Urządzenie zostało przeniesione

"relationUpdate" : {
  "type" : "UPDATED",
  "subject" : "enterprises/project-id/structures/structure-id/rooms/room-id",
  "object" : "enterprises/project-id/devices/device-id"
}

USUNIĘTY

Usunięto strukturę

"relationUpdate" : {
  "type" : "DELETED",
  "subject" : "",
  "object" : "enterprises/project-id/structures/structure-id"
}

Urządzenie zostało usunięte

"relationUpdate" : {
  "type" : "DELETED",
  "subject" : "enterprises/project-id/structures/structure-id",
  "object" : "enterprises/project-id/devices/device-id"
}

Urządzenie zostało usunięte

"relationUpdate" : {
  "type" : "DELETED",
  "subject" : "enterprises/project-id/structures/structure-id/rooms/room-id",
  "object" : "enterprises/project-id/devices/device-id"
}

Zdarzenia związane z relacjami nie są wysyłane, gdy:

  • Pokój został usunięty

Zdarzenia związane z zasobami

Zdarzenie zasobu reprezentuje aktualizację związaną z danym zasobem. Może to być reakcja na zmianę wartości w polu cech, np. zmianę trybu termostatu. Może również reprezentować działanie urządzenia, które nie zmienia pola cech, np. naciśnięcie przycisku na urządzeniu.

Zdarzenie wygenerowane w odpowiedzi na zmianę wartości w polu trait zawiera obiekt traits, podobny do wywołania GET na urządzeniu:

Ładunek

{
  "eventId" : "059c87fa-f63c-43d3-a9f0-bf47cedafd41",
  "timestamp" : "2019-01-01T00:00:01Z",
  "resourceUpdate" : {
    "name" : "enterprises/project-id/devices/device-id",
    "traits" : {
      "sdm.devices.traits.ThermostatMode" : {
        "mode" : "COOL"
      }
    }
  },
  "userId": "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi",
  "resourceGroup" : [
    "enterprises/project-id/devices/device-id"
  ]
}

Z dokumentacji dotyczącej poszczególnych cech dowiesz się, jaki format ładunku ma każdy zdarzenie zmiany pola trait.

Zdarzenie wygenerowane w odpowiedzi na działanie urządzenia, które nie zmienia pola trait, zawiera też ładunek z obiektem resourceUpdate, ale z obiektem events zamiast obiektu traits:

Ładunek

{
  "eventId" : "f0371697-212a-4059-9dfe-d63fdeb52169",
"timestamp" : "2019-01-01T00:00:01Z",
"resourceUpdate" : { "name" : "enterprises/project-id/devices/device-id", "events" : { "sdm.devices.events.CameraMotion.Motion" : { "eventSessionId" : "CjY5Y3VKaTZwR3o4Y19YbTVfMF...", "eventId" : "4iHHfz9K41MzI-4osu1WzJZive...", } } } "userId" : "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi",
"eventThreadId" : "d67cd3f7-86a7-425e-8bb3-462f92ec9f59",
"eventThreadState" : "STARTED",
"resourceGroup" : [ "enterprises/project-id/devices/device-id" ] }

Te typy zdarzeń dotyczących zasobów są zdefiniowane w określonych cechach. Na przykład zdarzenie Ruch jest zdefiniowane w właściwości CameraMotion . Format ładunku dla tych typów zdarzeń zasobów znajdziesz w dokumentacji poszczególnych cech.

Pola

Pole Opis Typ danych
eventId Unikalny identyfikator zdarzenia. string
Przykład: „f0371697-212a-4059-9dfe-d63fdeb52169”
timestamp Czas wystąpienia zdarzenia. string
Przykład: „2019-01-01T00:00:01Z”
resourceUpdate Obiekt ze szczegółowymi informacjami o aktualizacji zasobu. object
userId Unikalny, zaciemniony identyfikator reprezentujący użytkownika. string
Przykład: „AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi”
eventThreadId Unikalny identyfikator wątku wydarzenia. string
Przykład: „d67cd3f7-86a7-425e-8bb3-462f92ec9f59”
eventThreadState Stan wątku wydarzenia. string
Wartości: „ROZPOCZĘTO”, „ZAKTUALIZOWANE”, „ENDED”
resourceGroup Obiekt wskazujący zasoby, które mogą mieć podobne aktualizacje do tego zdarzenia. Zasób samego zdarzenia (z obiektu resourceUpdate) będzie zawsze obecny w tym obiekcie. object

Więcej informacji o różnych typach zdarzeń i sposobie ich działania znajdziesz w sekcji Zdarzenia.

Powiadomienia, które można zaktualizować

Powiadomienia na podstawie zdarzeń dotyczących zasobów można zaimplementować w aplikacji, np. na Androida lub iOS. Aby zmniejszyć liczbę wysyłanych powiadomień, można wdrożyć funkcję o nazwie powiadomienia z możliwością aktualizacji, w której istniejące powiadomienia są uzupełniane o nowe informacje na podstawie kolejnych zdarzeń w tym samym wątku.

Wybrane zdarzenia obsługują powiadomienia z możliwością aktualizacji i są oznaczone w dokumentacji jako Dostępne do aktualizacji . Te zdarzenia mają w ładunkach dodatkowe pole o nazwie eventThreadId. W tym polu możesz łączyć poszczególne zdarzenia na potrzeby aktualizowania istniejącego powiadomienia wyświetlonego dla użytkownika.

Wątek zdarzenia to nie to samo co sesja zdarzenia. Wątek zdarzenia wskazuje zaktualizowany stan poprzedniego zdarzenia w tym samym wątku. Sesja zdarzenia określa osobne zdarzenia, które są ze sobą powiązane. W przypadku danej sesji zdarzenia może być wiele wątków.

Aby wyświetlać powiadomienia, różne typy zdarzeń są grupowane w osobne wątki.

Logika grupowania wątków i określania czasu jest obsługiwana przez Google i może w każdej chwili ulec zmianie. Aplikacja developer powinna aktualizować powiadomienia na podstawie wątków i sesji zdarzeń dostarczonych przez interfejs SDM API.

Stan wątku

Zdarzenia, które obsługują powiadomienia z możliwością aktualizacji, mają też pole eventThreadState, które wskazuje stan wątku zdarzenia w danym momencie. To pole zawiera następujące wartości:

  • STARTED – pierwsze wydarzenie w wątku wydarzenia.
  • ZAKTUALIZOWANE – wydarzenie w trwającym wątku wydarzenia. W 1 wątku może być 0 lub więcej zdarzeń o tym stanie.
  • ZAKOŃCZONE – ostatnie wydarzenie w wątku wydarzenia, które może być duplikatem ostatniego ZAKTUALIZOWANEGO wydarzenia w zależności od typu wątku.

W tym polu możesz śledzić postęp wątku zdarzenia i czas jego zakończenia.

Filtrowanie zdarzeń

W niektórych przypadkach zdarzenia wykryte przez urządzenie mogą zostać odfiltrowane i nie będą mogły zostać opublikowane w temacie SDM Pub/Sub. Nazywamy to filtrowaniem zdarzeń. Filtrowanie zdarzeń ma na celu uniknięcie opublikowania zbyt wielu podobnych wiadomości o zdarzeniach w krótkim czasie.

Wiadomość może na przykład zostać opublikowana w temacie SDM w przypadku początkowego zdarzenia Motion. Pozostałe wiadomości w usłudze Motion będą odfiltrowywane z publikacji przez określony czas. Po upływie tego czasu wiadomość o zdarzeniu tego typu może zostać opublikowana ponownie.

W aplikacji Google Home (GHA) odfiltrowane zdarzenia będą nadal widoczne w historii zdarzeń urządzenia user. Takie zdarzenia nie generują jednak powiadomień aplikacji (nawet jeśli ten typ powiadomień jest włączony).

Każdy typ zdarzenia ma własną logikę filtrowania zdarzeń, która została zdefiniowana przez Google i może się w każdej chwili zmienić. Ta logika filtrowania zdarzeń zależy od wątku i logiki sesji.

Konta usługi

Konta usługi są zalecane do zarządzania subskrypcjami interfejsu SDM API i wiadomościami o zdarzeniach. Konto usługi jest używane przez aplikację lub maszynę wirtualną, a nie przez osobę, i ma własny unikalny klucz konta.

Autoryzacja konta usługi w przypadku interfejsu Pub/Sub API korzysta z dwuetapowej autoryzacji OAuth (2LO).

W ramach procesu autoryzacji dwuetapowej:

  • developer żąda tokena dostępu za pomocą klucza usługi.
  • developer używa tokena dostępu w wywołaniach interfejsu API.

Aby dowiedzieć się więcej o 2LO Google i sposobie konfiguracji, przeczytaj artykuł o używaniu OAuth 2.0 w aplikacjach między serwerami.

Upoważnienie

Konto usługi powinno być autoryzowane do używania z interfejsem Pub/Sub API:

  1. Włącz Cloud Pub/Sub API w Google Cloud.
  2. Utwórz konto usługi i klucz konta usługi zgodnie z opisem w sekcji Tworzenie konta usługi. Zalecamy przypisanie mu tylko roli Subskrybent w Pub/Sub. Pamiętaj, aby pobrać klucz konta usługi na maszynę, która będzie używać interfejsu Pub/Sub API.
  3. Jeśli chcesz szybko przetestować dostęp przez interfejs API, wpisz dane uwierzytelniające (klucz konta usługi) do kodu aplikacji, postępując zgodnie z instrukcjami na stronie w poprzednim kroku. Możesz też ręcznie uzyskać token dostępu, korzystając z oauth2l.
  4. Do pobierania i potwierdzania wiadomości używaj danych logowania konta usługi lub tokena dostępu z interfejsem API Pub/Sub project.subscriptions.

OAuth2l

Google oauth2l to narzędzie wiersza poleceń do obsługi protokołu OAuth napisanego w języku Go. Zainstaluj je na komputerze z systemem macOS lub Linux za pomocą języka Go.

  1. Jeśli nie masz aplikacji Go, najpierw ją pobierz i zainstaluj.
  2. Po zainstalowaniu języka Go zainstaluj oauth2l i dodaj jego lokalizację do zmiennej środowiskowej PATH:
    go install github.com/google/oauth2l@latest
    export PATH=$PATH:~/go/bin
  3. Użyj oauth2l, aby uzyskać token dostępu dla interfejsu API za pomocą odpowiednich zakresów protokołu OAuth:
    oauth2l fetch --credentials path-to-service-key.json --scope https://www.googleapis.com/auth/pubsub
    https://www.googleapis.com/auth/cloud-platform
    Jeśli na przykład Twój klucz usługi znajduje się pod adresem ~/myServiceKey-eb0a5f900ee3.json:
    oauth2l fetch --credentials ~/myServiceKey-eb0a5f900ee3.json --scope https://www.googleapis.com/auth/pubsub
    https://www.googleapis.com/auth/cloud-platform
    ya29.c.Elo4BmHXK5...

Więcej informacji o korzystaniu znajdziesz w czytniku README oauth2l.

Biblioteki klienta interfejsów API Google

Dostępnych jest kilka bibliotek klienta dla interfejsów API Google, które korzystają z protokołu OAuth 2.0. Więcej informacji o wybranym języku znajdziesz w sekcji Biblioteki klienta interfejsów API Google.

Jeśli używasz tych bibliotek z parametrem Pub/Sub API, użyj tych ciągów znaków zakresu:

https://www.googleapis.com/auth/pubsub
https://www.googleapis.com/auth/cloud-platform

Błędy

W związku z tym przewodnikiem mogą zostać zwrócone następujące kody błędów:

Komunikat o błędzie RPC Rozwiązywanie problemów
Zdjęcie z aparatu nie jest już dostępne do pobrania. DEADLINE_EXCEEDED Obrazy zdarzeń wygasają po 30 sekundach od opublikowania zdarzenia. Pamiętaj, aby pobrać obraz przed wygaśnięciem ważności.
Identyfikator zdarzenia nie należy do kamery. FAILED_PRECONDITION Użyj prawidłowej wartości eventID zwróconej przez zdarzenie kamery.

Pełną listę kodów błędów interfejsu API znajdziesz w dokumentacji kodu błędu interfejsu API.