Zdarzenia są asynchroniczne i zarządzane przez Google Cloud Pub/Sub w jednym temacie na Project. Zdarzenia dostarczają aktualizacji dla wszystkich urządzeń i struktur. Odbieranie zdarzeń jest zapewnione, o ile użytkownik nie cofnie tokenu dostępu, a wiadomości zdarzeń nie wygasną.
Włącz wydarzenia
Zdarzenia są opcjonalną funkcją interfejsu SDM API. Aby dowiedzieć się, jak włączyć te funkcje w przypadku usługi Project, przejdź do: Włączanie zdarzeń .
Google Cloud Pub/Sub
Więcej informacji o działaniu usługi Pub/Sub znajdziesz w dokumentacji Google Cloud Pub/Sub. W szczególności:
- opanujesz podstawy Pub/Sub, korzystając z instrukcji.
- Dowiedz się, jak działa Uwierzytelnianie.
- Wybierz udostępnioną bibliotekę klienta lub napisz własną i użyj interfejsów REST/HTTP lub gRPC API.
Subskrypcja zdarzeń
Gdy zdarzenia są włączone w przypadku Twojej domeny ( Project), otrzymasz temat dotyczący tego identyfikatora ( Project ) w postaci:
projects/sdm-prod/topics/enterprise-project-id
Aby otrzymywać zdarzenia, utwórz subskrypcję pull lub push tego tematu, w zależności od przypadku użycia. Obsługiwane są liczne subskrypcje tematu SDM. Więcej informacji znajdziesz w artykule Zarządzanie subskrypcjami.
Inicjowanie zdarzeń
Aby po raz pierwszy wywołać zdarzenia po utworzeniu subskrypcji Pub/Sub, wykonaj wywołanie interfejsu API
devices.list
jako jednorazowe zdarzenie. Po tym wywołaniu zostaną opublikowane zdarzenia dotyczące wszystkich struktur i urządzeń.
Przykładem jest strona Autoryzuj w Krótkim przewodniku.
kolejność zdarzeń,
Pub/Sub nie gwarantuje uporządkowanej dostawy zdarzeń, a kolejność ich odbioru może nie odpowiadać kolejności, w jakiej zdarzenia faktycznie miały miejsce. Użyj pola timestamp
do ułatwienia uzgadniania kolejności zdarzeń. Wydarzenia mogą być wysyłane pojedynczo lub połączone w jedną wiadomość.
Więcej informacji znajdziesz w artykule Ustalanie kolejności wiadomości.
Identyfikatory użytkowników
Jeśli Twoja implementacja opiera się na użytkownikach (a nie na strukturze ani urządzeniu), użyj pola userID
z ładunku zdarzenia, aby powiązać zasoby i zdarzenia. To pole to zniekształcony identyfikator reprezentujący konkretnego użytkownika.
Wartość userID
jest też dostępna w nagłówku odpowiedzi HTTP każdego wywołania interfejsu API.
Zdarzenia związane z relacją
Zdarzenia dotyczące relacji to aktualizacje relacyjne zasobu. Na przykład gdy urządzenie zostanie dodane do struktury lub usunięte z niej.
Istnieją 3 rodzaje zdarzeń dotyczących relacji:
- CREATED
- USUNIĘTY
- ZAKTUALIZOWANO
Ładunek zdarzenia relacji:
Ładunek
{ "eventId" : "d5c0f0bd-de65-44fd-ac60-686c302e56eb", "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 zdarzeniu relacji object
to zasób, który wywołał zdarzenie, a subject
to zasób, z którym object
ma teraz relację. W tym przykładzie user przyznał dostęp do tego konkretnego urządzenia developer, a urządzenie userjest teraz powiązane z autoryzowaną strukturą, która powoduje wystąpienie zdarzenia.
subject
może być tylko pomieszczeniem lub strukturą. Jeśli a developer nie ma uprawnień do wyświetlania struktury user, subject
jest zawsze pusta.
Pola
Pole | Opis | Typ danych |
---|---|---|
eventId |
Unikalny identyfikator zdarzenia. | string Przykład: „64b87b46-1aec-42a4-8c01-997a407814df” |
timestamp |
Czas wystąpienia zdarzenia. | string Przykład: „2019-01-01T00:00:01Z” |
relationUpdate |
Obiekt zawierający szczegółowe informacje o zmianie relacji. | object |
userId |
Unikalny, zanonimizowany identyfikator reprezentujący użytkownika. | string Przykład: „AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi”. |
Więcej informacji o różnych typach zdarzeń i ich działaniu znajdziesz w sekcji Zdarzenia.
Przykłady
Dane ładunku zdarzenia różnią się w zależności od typu zdarzenia relacji:
UTWORZONO
Struktura została utworzona
"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
Przeniesienie urządzenia
"relationUpdate" : { "type" : "UPDATED", "subject" : "enterprises/project-id/structures/structure-id/rooms/room-id", "object" : "enterprises/project-id/devices/device-id" }
USUNIĘTY
Struktura została usunięta
"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 dotyczące relacji nie są wysyłane, gdy:
- Pokój został usunięty
Zdarzenia związane z zasobami
Zdarzenie dotyczące zasobu reprezentuje aktualizację dotyczącą konkretnego zasobu. Może to być reakcja na zmianę wartości pola cechy, np. zmianę trybu termostatu. Może też reprezentować działanie urządzenia, które nie zmienia pola atrybutu, takie jak naciśnięcie przycisku urządzenia.
Zdarzenie wygenerowane w odpowiedzi na zmianę wartości pola cechy zawiera obiekt traits
, podobnie jak wywołanie GET urządzenia:
Ładunek
{
"eventId" : "a88bc884-d2b8-42d6-adba-b7be92c232a3",
"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"
]
}
Aby poznać format danych dla zdarzenia zmiany zasobu pola cechy, zapoznaj się z dokumentacją dotyczącą poszczególnych cech.
Zdarzenie wygenerowane w odpowiedzi na działanie urządzenia, które nie zmienia pola cechy, ma też ładunek z obiektem resourceUpdate
, ale z obiektem events
zamiast traits
:
Ładunek
{ "eventId" : "4f80de08-1b77-42a4-b33e-40876a2a1865",
"timestamp" : "2019-01-01T00:00:01Z",
"resourceUpdate" : { "name" : "enterprises/project-id/devices/device-id", "events" : { "sdm.devices.events.CameraMotion.Motion
" : { "eventSessionId" : "CjY5Y3VKaTZwR3o4Y19YbTVfMF...", "eventId" : "MWJ253hZMPAsJZJWbrGM4ThsKM...", } } } "userId" : "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi",
"eventThreadId" : "d67cd3f7-86a7-425e-8bb3-462f92ec9f59",
"eventThreadState" : "STARTED",
"resourceGroup" : [ "enterprises/project-id/devices/device-id" ] }
Te typy zdarzeń związanych z zasobami są definiowane w konkretnych cechach. Na przykład zdarzenie Ruch jest zdefiniowane w profilu CameraMotion . Aby poznać format danych payload w przypadku tych typów zdarzeń związanych ze zbiorem zasobów, zapoznaj się z dokumentacją poszczególnych atrybutów.
Pola
Pole | Opis | Typ danych |
---|---|---|
eventId |
Unikalny identyfikator zdarzenia. | string Przykład: „4f80de08-1b77-42a4-b33e-40876a2a1865”. |
timestamp |
Czas wystąpienia zdarzenia. | string Przykład: „2019-01-01T00:00:01Z” |
resourceUpdate |
Obiekt zawierający szczegółowe informacje o aktualizacji zasobu. | object |
userId |
Unikalny, zanonimizowany identyfikator reprezentujący użytkownika. | string Przykład: „AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi”. |
eventThreadId |
Unikalny identyfikator wątku zdarzenia. | string Przykład: „d67cd3f7-86a7-425e-8bb3-462f92ec9f59” |
eventThreadState |
Stan wątku zdarzenia. | string Wartości: „STARTED” (rozpoczęto), „UPDATED” (zaktualizowano) i „ENDED” (zakończono). |
resourceGroup |
Obiekt wskazujący zasoby, które mogą mieć podobne aktualizacje do tego zdarzenia. Zasoby samego zdarzenia (z obiektu resourceUpdate ) będą zawsze obecne w tym obiekcie. |
object |
Więcej informacji o różnych typach zdarzeń i ich działaniu znajdziesz w sekcji Zdarzenia.
Powiadomienia z możliwością aktualizacji
Powiadomienia oparte na zdarzeniach dotyczących zasobów można implementować w aplikacji, np. na Androida lub iOS. Aby zmniejszyć liczbę wysyłanych powiadomień, możesz wdrożyć funkcję powiadomień z możliwością aktualizacji, w ramach której istniejące powiadomienia są aktualizowane o nowe informacje na podstawie kolejnych zdarzeń w tym samym wątku zdarzeń.Wybrane zdarzenia obsługują powiadomienia z możliwością aktualizacji i są oznaczone w dokumentacji jako z możliwością aktualizacji eventThreadId
. Użyj tego pola, aby powiązać poszczególne zdarzenia w celu zaktualizowania istniejącego powiadomienia wyświetlanego użytkownikowi.
Nić zdarzeń to nie to samo co sesja zdarzeń. Wątek zdarzenia wskazuje zaktualizowany stan poprzedniego zdarzenia w tym samym wątku. Sesja zdarzenia identyfikuje oddzielne zdarzenia, które są ze sobą powiązane. W przypadku danej sesji zdarzenia może być wiele wątków zdarzeń.
W celu wysyłania powiadomień różne typy zdarzeń są grupowane w różne wątki.
Za logikę grupowania wątków i określanie ich czasu odpowiada Google i może ona ulec zmianie w dowolnym momencie. A developer powinien aktualizować powiadomienia na podstawie wątków zdarzeń i sesji udostępnianych przez interfejs SDM API.
Stan wątku
Wydarzenia, które obsługują powiadomienia z możliwością aktualizacji, mają też pole eventThreadState
, które wskazuje stan wątku wydarzenia w danym momencie. To pole może mieć te wartości:
- STARTED (rozpoczęto) – pierwsze zdarzenie w wątku zdarzenia.
- UPDATED – zdarzenie w bieżącym wątku zdarzenia. W ramach jednego wątku może wystąpić 0 lub więcej zdarzeń o tym stanie.
- ENDED (Zakończono) – ostatnie zdarzenie w wątku zdarzenia, które może być duplikatem ostatniego zdarzenia UPDATED (Zaktualizowano) w zależności od typu wątku.
Tego pola można używać do śledzenia postępów w rozwijaniu wątku zdarzenia i jego zakończenia.
Filtrowanie zdarzeń
W niektórych przypadkach zdarzenia wykryte przez urządzenie mogą zostać odfiltrowane z publikowania w temacie SDM Pub/Sub. Takie działanie nazywamy filtrowaniem zdarzeń. Filtrowanie zdarzeń ma na celu unikanie publikowania zbyt wielu podobnych komunikatów o zdarzeniach w krótkim czasie.
Na przykład wiadomość może zostać opublikowana w temacie SDM dla początkowego zdarzenia Motion. Inne wiadomości dotyczące Motion po tym czasie zostaną odfiltrowane i nie będą publikowane do czasu upłynięcia określonego czasu. Po upływie tego czasu wiadomość o danym typie zdarzenia może zostać opublikowana ponownie.
W aplikacji Google Home (GHA) odfiltrowane zdarzenia będą nadal widoczne w historii zdarzeń user. Jednak takie zdarzenia nie generują powiadomienia z aplikacji (nawet jeśli ten typ powiadomienia jest włączony).
Każdy typ zdarzenia ma własną logikę filtrowania, którą definiuje Google i która może ulec zmianie w dowolnym momencie. Ta logika filtrowania zdarzeń jest niezależna od wątku zdarzenia 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 procesie autoryzacji 2 FA:
- developer wysyła żądanie tokenu dostępu za pomocą klucza usługi.
- developer używa tokena dostępu w wywołaniach interfejsu API.
Więcej informacji o Google 2LO i o tym, jak go skonfigurować, znajdziesz w artykule Używanie OAuth 2.0 w aplikacjach serwer-serwer.
Autoryzacja
Konto usługi powinno być autoryzowane do korzystania z interfejsu Pub/Sub API:
- Włącz interfejs API Cloud Pub/Sub w Google Cloud.
- Utwórz konto usługi i klucz konta usługi zgodnie z opisem w artykule Tworzenie konta usługi. Zalecamy przypisanie tylko roli subskrybenta Pub/Sub. Pamiętaj, aby pobrać klucz konta usługi na maszynę, która będzie używać interfejsu Pub/Sub API.
- Aby szybko przetestować dostęp do interfejsu API, podaj swoje poświadczenia logowania (klucz konta usługi) w kodzie aplikacji, postępując zgodnie z instrukcjami na stronie z poprzedniego kroku, lub ręcznie pobierz token dostępu za pomocą funkcji
oauth2l
. - Użyj danych logowania konta usługi lub tokenu dostępu w interfejsie Pub/Sub
project.subscriptions
API, aby pobierać i potwierdzać wiadomości.
oauth2l
Google oauth2l
to narzędzie wiersza poleceń do obsługi OAuth napisane w języku Go. Zainstaluj je na Macu lub Linuxie za pomocą Go.
- Jeśli nie masz jeszcze Go, pobierz i zainstaluj ją.
- Po zainstalowaniu Google Go zainstaluj
oauth2l
i dodaj jego lokalizację do zmiennej środowiskowejPATH
:go install github.com/google/oauth2l@latest
export PATH=$PATH:~/go/bin
- Użyj
oauth2l
, aby uzyskać token dostępu do interfejsu API, używając odpowiedniego zakresu OAuth:
Na przykład, jeśli klucz usługi znajduje się woauth2l fetch --credentials path-to-service-key.json --scope https://www.googleapis.com/auth/pubsub https://www.googleapis.com/auth/cloud-platform
~/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 z tego narzędzia znajdziesz w pliku oauth2l
README.
Biblioteki klienta Google API
Do interfejsów API Google, które korzystają z protokołu OAuth 2.0, dostępnych jest kilka bibliotek klienta. Więcej informacji o konkretnym języku znajdziesz w bibliotekach klienta interfejsu API Google.
Podczas korzystania z tych bibliotek z Pub/Sub APIużyj tych ciągó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 te kody błędów:
Komunikat o błędzie | RPC | Rozwiązywanie problemów |
---|---|---|
Obraz z aparatu nie jest już dostępny do pobrania. | DEADLINE_EXCEEDED |
Obrazy wydarzeń wygasają 30 sekund po opublikowaniu wydarzenia. Pamiętaj, aby pobrać obraz przed wygaśnięciem. |
Identyfikator zdarzenia nie należy do kamery. | FAILED_PRECONDITION |
Użyj prawidłowej wartości eventID zwróconej przez zdarzenie związane z kamerą. |
Pełną listę kodów błędów interfejsu API znajdziesz w przewodniku po kodach błędów interfejsu API.