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:
- Poznaj podstawy Pub/Sub z tych instrukcji.
- Dowiedz się, jak działa Uwierzytelnianie.
- Wybierz udostępnianą bibliotekę klienta albo utwórz własną bibliotekę i użyj platform interfejsu API REST/HTTP lub gRPC.
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 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:
- Włącz Cloud Pub/Sub API w Google Cloud.
- 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.
- 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
. - 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.
- Jeśli nie masz aplikacji Go, najpierw ją pobierz i zainstaluj.
- Po zainstalowaniu języka 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 dla interfejsu API za pomocą odpowiednich zakresów protokołu OAuth:
Jeśli na przykład Twój klucz usługi znajduje się pod adresemoauth2l 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 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.