Zdarzenia są asynchroniczne i zarządzane przez Google Cloud Pub/Sub w jednym temacie na Project. Zdarzenia zapewniają aktualizacje na wszystkich urządzeniach i w strukturach, a ich odbiór jest gwarantowany, dopóki token dostępu nie zostanie unieważniony przez użytkownika i nie wygasną wiadomości o zdarzeniach.
Włącz wydarzenia
Zdarzenia są opcjonalną funkcją interfejsu SDM API. Więcej informacji o tym, jak włączyć zdarzenia w przypadku Twojego urządzenia, znajdziesz w artykule Włączanie zdarzeń . Project
Google Cloud Pub/Sub
Więcej informacji o działaniu Pub/Sub znajdziesz w dokumentacji Google Cloud Pub/Sub. W szczególności:
- opanujesz podstawy Pub/Sub, korzystając z ich przewodników.
- dowiesz się, jak działa uwierzytelnianie;
- wybierzesz udostępnioną bibliotekę klienta lub napiszesz własną i użyjesz interfejsu API REST/HTTP lub gRPC.
Subskrypcja zdarzeń
Jeśli przed styczniem 2025 r. zdarzenia były włączone w przypadku Twojego Project, otrzymasz temat dotyczący tego Project identyfikatora w postaci:
projects/gcp-project-name/subscriptions/topic-id
Aby otrzymywać zdarzenia, utwórz subskrypcję pull lub push tego tematu w zależności od przypadku użycia. Obsługiwanych jest wiele subskrypcji tematu SDM. Więcej informacji znajdziesz w artykule Zarządzanie subskrypcjami.
Inicjowanie zdarzeń
Aby po raz pierwszy zainicjować zdarzenia po utworzeniu subskrypcji Pub/Sub, wywołaj interfejs API
devices.list
jako jednorazowy wyzwalacz. Po tym wywołaniu będą publikowane zdarzenia dotyczące wszystkich struktur i urządzeń.
Przykład znajdziesz na stronie Autoryzacja w krótkim przewodniku.
Kolejność zdarzeń
Pub/Sub nie gwarantuje dostarczania zdarzeń w określonej kolejności, a kolejność ich otrzymywania może nie
odpowiadać kolejności, w jakiej faktycznie wystąpiły. Aby ułatwić uzgadnianie kolejności zdarzeń, użyj pola timestamp. Zdarzenia mogą też docierać pojedynczo lub w postaci jednej wiadomości o zdarzeniu.
Więcej informacji znajdziesz w artykule Kolejność wiadomości.
Identyfikatory użytkowników
Jeśli implementacja opiera się na użytkownikach (a nie na strukturze lub urządzeniu), użyj pola
userID z ładunku zdarzenia, aby skorelować zasoby i zdarzenia. To pole jest
zniekształconym identyfikatorem reprezentującym konkretnego użytkownika.
Pole userID jest też dostępne w nagłówku odpowiedzi HTTP każdego wywołania interfejsu API.
Zdarzenia relacji
Zdarzenia relacji reprezentują aktualizację relacji zasobu. Na przykład gdy urządzenie zostanie dodane do struktury lub gdy zostanie z niej usunięte.
Istnieją 3 rodzaje zdarzeń relacji:
- CREATED
- USUNIĘTY
- ZAKTUALIZOWANO
Ładunek zdarzenia relacji wygląda tak:
Ładunek
{
"eventId" : "afe33940-1627-4d94-923c-58397027474e",
"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
powyższym przykładzie przyznał dostęp do tego konkretnego urządzenia użytkownikowi
developer, a autoryzowane urządzenie użytkownika jest teraz powiązane z jego autoryzowaną
strukturą, co wywołuje zdarzenie. user user
subject może być tylko pokojem lub strukturą. Jeśli a developer nie ma
uprawnień do wyświetlania struktury użytkownika user, pole subject jest zawsze
puste.
Pola
| Pole | Opis | Typ danych |
|---|---|---|
eventId |
Unikalny identyfikator zdarzenia. | stringPrzykład: „e2d072c8-3e00-4329-ad1a-de29bb5b21b5” |
timestamp |
Czas wystąpienia zdarzenia. | stringPrzykład: „2019-01-01T00:00:01Z” |
relationUpdate |
Obiekt zawierający szczegółowe informacje o aktualizacji relacji. | object |
userId |
Unikalny, celowo zniekształcony identyfikator reprezentujący użytkownika. | stringPrzykład: „AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi” |
Więcej informacji o różnych rodzajach zdarzeń i ich działaniu znajdziesz w artykule Zdarzenia.
Przykłady
Ładunki zdarzeń różnią się w zależności od rodzaju zdarzenia relacji:
UTWORZONO
Utworzono strukturę
"relationUpdate" : {
"type" : "CREATED",
"subject" : "",
"object" : "enterprises/project-id/structures/structure-id"
}Utworzono urządzenie
"relationUpdate" : {
"type" : "CREATED",
"subject" : "enterprises/project-id/structures/structure-id",
"object" : "enterprises/project-id/devices/device-id"
}Utworzono urządzenie
"relationUpdate" : {
"type" : "CREATED",
"subject" : "enterprises/project-id/structures/structure-id/rooms/room-id",
"object" : "enterprises/project-id/devices/device-id"
}ZAKTUALIZOWANO
Przeniesiono urządzenie
"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"
}Usunięto urządzenie
"relationUpdate" : {
"type" : "DELETED",
"subject" : "enterprises/project-id/structures/structure-id",
"object" : "enterprises/project-id/devices/device-id"
}Usunięto urządzenie
"relationUpdate" : {
"type" : "DELETED",
"subject" : "enterprises/project-id/structures/structure-id/rooms/room-id",
"object" : "enterprises/project-id/devices/device-id"
}Zdarzenia relacji nie są wysyłane, gdy:
- pokój zostanie usunięty.
Zdarzenia związane z zasobami
Zdarzenie związane z zasobem reprezentuje aktualizację dotyczącą konkretnego zasobu. Może to być odpowiedź na zmianę wartości pola cechy, np. zmianę trybu termostatu. Może też reprezentować działanie urządzenia, które nie zmienia pola cechy, np. naciśnięcie przycisku urządzenia.
Zdarzenie wygenerowane w odpowiedzi na zmianę wartości pola cechy zawiera obiekt
traits podobny do wywołania GET urządzenia:
Ładunek
{
"eventId" : "adb76f6f-4bd3-4704-8735-faa6e94471c3",
"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 ładunku zdarzenia związanego z zasobem, które jest wywoływane przez zmianę pola cechy, zapoznaj się z dokumentacją 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 zamiast obiektu traits zawiera obiekt events:
Ładunek
{
"eventId" : "73d758a1-7d19-4e45-8a19-6506399af5a7",
"timestamp" : "2019-01-01T00:00:01Z",
"resourceUpdate" : {
"name" : "enterprises/project-id/devices/device-id",
"events" : {
"sdm.devices.events.CameraMotion.Motion" : {
"eventSessionId" : "CjY5Y3VKaTZwR3o4Y19YbTVfMF...",
"eventId" : "MkhXoQ0QFEcU9at0j380_gUlJA...",
}
}
}
"userId" : "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi",
"eventThreadId" : "d67cd3f7-86a7-425e-8bb3-462f92ec9f59",
"eventThreadState" : "STARTED",
"resourceGroup" : [
"enterprises/project-id/devices/device-id"
]
}Te rodzaje zdarzeń związanych z zasobami są zdefiniowane w konkretnych cechach. Na przykład zdarzenie ruchu Motion jest zdefiniowane w cechach CameraMotion . Aby poznać format ładunku tych rodzajów zdarzeń związanych z zasobami, zapoznaj się z dokumentacją każdej cechy.
Pola
| Pole | Opis | Typ danych |
|---|---|---|
eventId |
Unikalny identyfikator zdarzenia. | stringPrzykład: „73d758a1-7d19-4e45-8a19-6506399af5a7” |
timestamp |
Czas wystąpienia zdarzenia. | stringPrzykład: „2019-01-01T00:00:01Z” |
resourceUpdate |
Obiekt zawierający szczegółowe informacje o aktualizacji zasobu. | object |
userId |
Unikalny, celowo zniekształcony identyfikator reprezentujący użytkownika. | stringPrzykład: „AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi” |
eventThreadId |
Unikalny identyfikator wątku zdarzenia. | stringPrzykład: „d67cd3f7-86a7-425e-8bb3-462f92ec9f59” |
eventThreadState |
Stan wątku zdarzenia. | stringWartości: „STARTED”, „UPDATED”, „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 rodzajach zdarzeń i ich działaniu znajdziesz w artykule Zdarzenia.
Powiadomienia, które można aktualizować
Powiadomienia oparte na zdarzeniach związanych z zasobami można zaimplementować w aplikacji, np. na Androida lub iOS. Aby zmniejszyć liczbę wysyłanych powiadomień, można zaimplementować funkcję powiadomień, które można aktualizować. W takim przypadku istniejące powiadomienia są aktualizowane o nowe informacje na podstawie kolejnych zdarzeń w tym samym wątku zdarzenia.Funkcja zdarzeń obsługuje powiadomienia, które można aktualizować, i jest oznaczona w dokumentacji jako
Możliwość aktualizacji eventThreadId. Użyj tego pola, aby połączyć poszczególne zdarzenia w celu zaktualizowania istniejącego powiadomienia, które zostało wyświetlone użytkownikowi.
Wątek zdarzenia nie jest tym samym co sesja zdarzenia. Wątek zdarzenia wskazuje zaktualizowany stan poprzedniego zdarzenia w tym samym wątku. Sesja zdarzenia wskazuje oddzielne zdarzenia, które są ze sobą powiązane. W przypadku danej sesji zdarzenia może występować wiele wątków zdarzeń.
Na potrzeby powiadomień różne rodzaje zdarzeń są grupowane w różne wątki.
Ta logika grupowania wątków i synchronizacji jest obsługiwana przez Google i może się w każdej chwili zmienić. A developer powinien aktualizować powiadomienia na podstawie wątków i sesji zdarzeń udostępnianych przez interfejs SDM API.
Stan wątku
Zdarzenia, które obsługują powiadomienia, które można aktualizować, mają też pole eventThreadState wskazujące stan wątku zdarzenia w danym momencie. To pole może przyjmować te wartości:
- STARTED – pierwsze zdarzenie w wątku zdarzenia.
- UPDATED – zdarzenie w trwającym wątku zdarzenia. W jednym wątku może występować zero lub więcej zdarzeń w tym stanie.
- ENDED – ostatnie zdarzenie w wątku zdarzenia, które w zależności od typu wątku może być duplikatem ostatniego zdarzenia UPDATED.
To pole może służyć do śledzenia postępu 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 nazywa się filtrowaniem zdarzeń. Filtrowanie zdarzeń ma na celu uniknięcie publikowania zbyt wielu podobnych wiadomości o zdarzeniach w krótkim czasie.
Na przykład wiadomość może zostać opublikowana w temacie SDM w przypadku początkowego zdarzenia ruchu. Inne wiadomości dotyczące zdarzenia Motion będą odfiltrowywane z publikowania do momentu upłynięcia określonego czasu. Po upływie tego czasu wiadomość o zdarzeniu tego typu może zostać ponownie opublikowana.
W aplikacji Google Home odfiltrowane zdarzenia będą nadal widoczne w historii zdarzeń użytkownika. userTakie zdarzenia nie generują jednak powiadomienia w aplikacji (nawet jeśli ten typ powiadomień jest włączony).
Każdy rodzaj zdarzenia ma własną logikę filtrowania zdarzeń, która jest zdefiniowana przez Google i może się w każdej chwili zmienić. Ta logika filtrowania zdarzeń jest niezależna od logiki wątku i sesji zdarzenia.
Konta usługi
Do zarządzania subskrypcjami interfejsu SDM API i wiadomościami o zdarzeniach zalecamy używanie kont usługi. 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 interfejsie Pub/Sub API korzysta z dwuetapowej autoryzacji OAuth (2LO).
W procesie autoryzacji 2LO:
- wysyła żądanie tokena dostępu za pomocą klucza usługi. developer
- używa tokena dostępu do wywoływania interfejsu API. developer
Więcej informacji o dwuetapowej autoryzacji OAuth Google i jej konfiguracji znajdziesz w artykule Używanie OAuth 2.0 w aplikacjach serwer-serwer.
Autoryzacja
Konto usługi powinno być autoryzowane do używania interfejsu Pub/Sub API:
- Włącz interfejs Cloud Pub/Sub API w Google Cloud.
- Utwórz konto usługi i klucz konta usługi zgodnie z opisem w artykule Tworzenie konta usługi. Zalecamy przyznanie mu tylko roli Subskrybent Pub/Sub. Pamiętaj, aby pobrać klucz konta usługi na maszynę, która będzie używać interfejsu Pub/Sub API.
- Podaj dane logowania (klucz konta usługi) w kodzie aplikacji, postępując zgodnie z instrukcjami na stronie z poprzedniego
kroku, lub ręcznie uzyskaj token dostępu za pomocą narzędzia
oauth2l, jeśli chcesz szybko przetestować dostęp do interfejsu API. - Użyj danych logowania konta usługi lub tokena dostępu w interfejsie
Pub/Sub
project.subscriptionsAPI aby pobierać i potwierdzać wiadomości.
oauth2l
Narzędzie oauth2l Google to narzędzie wiersza poleceń do obsługi OAuth napisane w języku Go. Zainstaluj je na komputerze z systemem Mac lub Linux za pomocą Go.
- Jeśli nie masz w systemie języka Go, najpierw go pobierz i zainstaluj.
- Po zainstalowaniu języka Go zainstaluj narzędzie
oauth2li dodaj jego lokalizację do zmiennej środowiskowejPATH:go install github.com/google/oauth2l@latestexport PATH=$PATH:~/go/bin - Użyj narzędzia
oauth2l, aby uzyskać token dostępu do interfejsu API, używając odpowiednich zakresów OAuth: Jeśli na przykład klucz usługi znajduje się w lokalizacjioauth2l 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-platformya29.c.Elo4BmHXK5...
Więcej informacji o użyciu znajdziesz w pliku oauth2l README narzędzia.
Biblioteki klienta Google API
Dostępnych jest kilka bibliotek klienta interfejsów API Google, które korzystają z protokołu OAuth 2.0. Więcej informacji o wybranym języku znajdziesz w artykule Biblioteki klienta Google API.
Gdy używasz tych bibliotek z Pub/Sub API, użyj tych ciągów zakresów:
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 kamery nie jest już dostępny do pobrania. | DEADLINE_EXCEEDED |
Obrazy zdarzeń wygasają 30 sekund po opublikowaniu zdarzenia. Pamiętaj, aby pobrać obraz przed wygaśnięciem. |
| Identyfikator zdarzenia nie należy do kamery. | FAILED_PRECONDITION |
Użyj prawidłowego identyfikatora eventID zwróconego przez zdarzenie zarejestrowane przez kamerę. |
Pełną listę kodów błędów interfejsu API znajdziesz w dokumentacji Kody błędów interfejsu API dla.