Ereignisse

Ereignisse sind asynchron und werden von Google Cloud Pub/Sub in einem einzigen Thema pro Projectverwaltet. Ereignisse liefern Aktualisierungen für alle Geräte und Strukturen. Der Empfang von Ereignissen wird gewährleistet, solange das Zugriffstoken nicht vom Nutzer widerrufen wird und die Ereignisnachrichten nicht abgelaufen sind.

Veranstaltungen aktivieren

Ereignisse sind eine optionale Funktion der SDM API. Unter Ereignisse aktivieren erfahren Sie, wie Sie sie für Ihr Projectaktivieren.

Google Cloud Pub/Sub

Weitere Informationen zur Funktionsweise von Pub/Sub finden Sie in der Google Cloud Pub/Sub-Dokumentation. Wichtig ist insbesondere:

Abo für Veranstaltung

Wenn Ereignisse für Projectaktiviert sind, erhalten Sie ein für diese Project -ID spezifisches Thema im folgenden Format:

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

Erstellen Sie je nach Anwendungsfall ein pull oder ein push für dieses Thema, um Ereignisse zu empfangen. Es werden mehrere Abos für das SDM-Thema unterstützt. Weitere Informationen finden Sie unter Abos verwalten.

Ereignisse initiieren

Wenn du Ereignisse zum ersten Mal auslösen möchtest, nachdem das Pub/Sub-Abo erstellt wurde, führe einmalig einen devices.list-API-Aufruf aus. Nach diesem Aufruf werden Ereignisse für alle Gebäude und Geräte veröffentlicht.

Ein entsprechendes Beispiel finden Sie in der Kurzanleitung auf der Seite Autorisieren.

Ereignisreihenfolge

Pub/Sub garantiert keine geordnete Zustellung von Ereignissen. Außerdem entspricht die Empfangsreihenfolge der Ereignisse möglicherweise nicht der Reihenfolge, in der die Ereignisse tatsächlich aufgetreten sind. Verwenden Sie das Feld timestamp, um den Abgleich der Ereignisreihenfolge zu vereinfachen. Ereignisse können auch einzeln oder in einer einzelnen Ereignisnachricht eingehen.

Weitere Informationen finden Sie unter Nachrichten sortieren.

Nutzer-IDs

Wenn Ihre Implementierung auf Nutzer und nicht auf Struktur oder Gerät basiert, verwenden Sie das Feld userID aus der Ereignisnutzlast, um Ressourcen und Ereignisse zu korrelieren. Dieses Feld ist eine verschleierte ID, die einen bestimmten Nutzer darstellt.

userID ist auch im HTTP-Antwortheader jedes API-Aufrufs verfügbar.

Beziehungsereignisse

Relationsereignisse stellen eine relationale Aktualisierung für eine Ressource dar. Das ist beispielsweise der Fall, wenn ein Gerät einem Gebäude hinzugefügt oder aus einem Gebäude gelöscht wird.

Es gibt drei Arten von Beziehungsereignissen:

  • ERSTELLT
  • GELÖSCHT
  • AKTUALISIERT

Die Nutzlast für ein Relationsereignis sieht so aus:

Nutzlast

{
  "eventId" : "eed9763a-8735-45d9-81d9-e0621c130eb1",
  "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"
}

Bei einem Beziehungsereignis ist object die Ressource, die das Ereignis ausgelöst hat, und subject die Ressource, mit der object jetzt eine Beziehung hat. Im Beispiel oben hat ein user einem developerZugriff auf dieses bestimmte Gerät gewährt und das autorisierte Gerät des userist jetzt mit seiner autorisierten Struktur verknüpft, wodurch das Ereignis ausgelöst wird.

Ein subject kann nur ein Raum oder ein Gebäude sein. Wenn a developer keine Berechtigung zum Ansehen der Struktur von userhat, ist subject immer leer.

Felder

Field Beschreibung Datentyp
eventId Die eindeutige Kennung des Ereignisses. string
Beispiel: „1362476b-4ac4-4608-a8be-4c8cf4101426“
timestamp Der Zeitpunkt, zu dem das Ereignis aufgetreten ist. string
Beispiel: „2019-01-01T00:00:01Z“
relationUpdate Ein Objekt, das Informationen zur Aktualisierung der Beziehung enthält. object
userId Eine eindeutige, verschleierte Kennung, die den Nutzer repräsentiert. string
Beispiel: „AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi“

Weitere Informationen zu den verschiedenen Ereignistypen und ihrer Funktionsweise finden Sie unter Ereignisse.

Beispiele

Die Ereignisnutzlasten unterscheiden sich je nach Beziehungsereignistyp:

ERSTELLT

Gebäude erstellt

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

Gerät erstellt

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

Gerät erstellt

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

AKTUALISIERT

Gerät verschoben

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

GELÖSCHT

Gebäude gelöscht

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

Gerät gelöscht

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

Gerät gelöscht

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

Beziehungsereignisse werden in folgenden Fällen nicht gesendet:

  • Ein Raum wurde gelöscht

Ressourcenereignisse

Ein Ressourcenereignis stellt eine ressourcenspezifische Aktualisierung dar. Er kann als Reaktion auf eine Änderung des Werts eines Eigenschaftsfelds erfolgen, z. B. eine Änderung des Modus eines Thermostats. Es kann auch eine Geräteaktion darstellen, durch die kein Eigenschaftsfeld geändert wird, wie das Drücken einer Gerätetaste.

Ein Ereignis, das als Reaktion auf eine Änderung des Werts des Trait-Felds generiert wird, enthält ein traits-Objekt, ähnlich einem GET-Aufruf auf einem Gerät:

Nutzlast

{
  "eventId" : "5b98a768-6771-4d4d-836d-58cce3a62cca",
  "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"
  ]
}

In der Dokumentation zu einzelnen Traits findest du Informationen zum Nutzlastformat von Trait-Feldänderungs-Ressourcenereignissen.

Ein Ereignis, das als Reaktion auf eine Geräteaktion generiert wird, durch die kein Trait-Feld geändert wird, hat auch eine Nutzlast mit einem resourceUpdate-Objekt, aber mit einem events-Objekt anstelle eines traits-Objekts:

Nutzlast

{
  "eventId" : "3426d266-406b-48f3-9595-5192229a39a0",
"timestamp" : "2019-01-01T00:00:01Z",
"resourceUpdate" : { "name" : "enterprises/project-id/devices/device-id", "events" : { "sdm.devices.events.CameraMotion.Motion" : { "eventSessionId" : "CjY5Y3VKaTZwR3o4Y19YbTVfMF...", "eventId" : "8XZ1cQ76Becovj551YfM9ZnuwB...", } } } "userId" : "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi",
"eventThreadId" : "d67cd3f7-86a7-425e-8bb3-462f92ec9f59",
"eventThreadState" : "STARTED",
"resourceGroup" : [ "enterprises/project-id/devices/device-id" ] }

Diese Arten von Ressourcenereignissen sind in bestimmten Eigenschaften definiert. Beispielsweise ist das Motion-Ereignis in der Eigenschaft CameraMotion definiert. Informationen zum Nutzlastformat für diese Arten von Ressourcenereignissen finden Sie in der Dokumentation der einzelnen Traits.

Felder

Field Beschreibung Datentyp
eventId Die eindeutige Kennung des Ereignisses. string
Beispiel: „3426d266-406b-48f3-9595-5192229a39a0“
timestamp Der Zeitpunkt, zu dem das Ereignis aufgetreten ist. string
Beispiel: „2019-01-01T00:00:01Z“
resourceUpdate Ein Objekt, das Informationen zum Ressourcenupdate enthält. object
userId Eine eindeutige, verschleierte Kennung, die den Nutzer repräsentiert. string
Beispiel: „AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi“
eventThreadId Die eindeutige ID für den Ereignis-Thread. string
Beispiel: „d67cd3f7-86a7-425e-8bb3-462f92ec9f59“
eventThreadState Der Status des Ereignis-Threads. string
Werte: „STARTED“, „UPDATED“, „ENDED“
resourceGroup Ein Objekt, das Ressourcen angibt, die ähnliche Aktualisierungen wie dieses Ereignis haben könnten. Die Ressource des Ereignisses selbst (aus dem resourceUpdate-Objekt) ist immer in diesem Objekt vorhanden. object

Weitere Informationen zu den verschiedenen Ereignistypen und ihrer Funktionsweise finden Sie unter Ereignisse.

Benachrichtigungen, die aktualisiert werden können

Benachrichtigungen auf Basis von Ressourcenereignissen können in einer App implementiert werden, z. B. für Android oder iOS. Um die Anzahl der gesendeten Benachrichtigungen zu reduzieren, kann eine Funktion namens Benachrichtigungen, die aktualisiert werden kann implementiert werden. Dabei werden vorhandene Benachrichtigungen anhand von nachfolgenden Ereignissen im selben Ereignis-Thread mit neuen Informationen aktualisiert.

Wählen Sie die Unterstützung für Ereignisfeatures für aktualisierbare Benachrichtigungen aus. Diese werden in der Dokumentation als Aktualisierbar  gekennzeichnet. In den Nutzlasten dieser Ereignisse ist das zusätzliche Feld eventThreadId enthalten. Verwenden Sie dieses Feld, um einzelne Ereignisse miteinander zu verknüpfen, um eine vorhandene Benachrichtigung zu aktualisieren, die einem Nutzer angezeigt wurde.

Ein Ereignis-Thread ist nicht dasselbe wie eine Ereignissitzung. Der Ereignis-Thread identifiziert den aktualisierten Status für ein vorheriges Ereignis im selben Thread. Die Ereignissitzung identifiziert separate Ereignisse, die miteinander in Beziehung stehen. Für eine bestimmte Ereignissitzung kann es mehrere Ereignisthreads geben.

Zu Benachrichtigungszwecken werden verschiedene Ereignistypen in verschiedene Threads gruppiert.

Diese Threadgruppierung und Timing-Logik wird von Google verwaltet und kann sich jederzeit ändern. A developer sollte Benachrichtigungen anhand der von der SDM API bereitgestellten Ereignisthreads und -sitzungen aktualisieren.

Threadstatus

Ereignisse, die aktualisierbare Benachrichtigungen unterstützen, haben außerdem das Feld eventThreadState, das den Status des Ereignisthreads zu diesem Zeitpunkt angibt. Dieses Feld enthält die folgenden Werte:

  • Gestartet: Das erste Ereignis in einem Ereignis-Thread.
  • UPDATED: Ein Ereignis in einem laufenden Ereignis-Thread. Ein einzelner Thread kann keine oder mehr Ereignisse mit diesem Status enthalten.
  • ENDED: Das letzte Ereignis in einem Ereignis-Thread, das je nach Thread-Typ ein Duplikat des letzten UPDATED-Ereignisses sein kann.

Mit diesem Feld können Sie den Fortschritt eines Ereignisthreads und dessen Ende verfolgen.

Ereignisfilterung

In einigen Fällen können von einem Gerät erkannte Ereignisse aus der Veröffentlichung in einem SDM-Pub/Sub-Thema herausgefiltert werden. Dieses Verhalten wird als Ereignisfilterung bezeichnet. Der Zweck der Ereignisfilterung besteht darin, zu verhindern, dass zu viele ähnliche Ereignisnachrichten in kurzer Zeit veröffentlicht werden.

Beispielsweise kann eine Nachricht für ein erstes Bewegungsereignis in einem SDM-Thema veröffentlicht werden. Andere Nachrichten für Motion werden nach Ablauf eines festgelegten Zeitraums für die Veröffentlichung herausgefiltert. Nach Ablauf dieses Zeitraums kann eine Ereignisnachricht für diesen Ereignistyp wieder veröffentlicht werden.

Gefilterte Ereignisse in der Google Home App (GHA) werden weiterhin im Ereignisverlauf des userangezeigt. Durch solche Ereignisse wird jedoch keine App-Benachrichtigung generiert, selbst wenn der Benachrichtigungstyp aktiviert ist.

Jeder Ereignistyp hat eine eigene Ereignisfilterlogik, die von Google definiert wird und jederzeit geändert werden kann. Diese Ereignisfilterungslogik ist unabhängig vom Ereignis-Thread und der Sitzungslogik.

Dienstkonten

Dienstkonten werden für die Verwaltung von SDM API-Abos und Ereignisnachrichten empfohlen. Ein Dienstkonto wird nicht von einer Person, sondern von einer Anwendung oder virtuellen Maschine verwendet, und hat einen eigenen eindeutigen Kontoschlüssel.

Die Dienstkontoautorisierung für die Pub/Sub API verwendet das zweibeinige OAuth (2LO).

Im 2LO-Autorisierungsablauf:

  • developer fordert mithilfe eines Dienstschlüssels ein Zugriffstoken an.
  • developer verwendet das Zugriffstoken mit Aufrufen der API.

Weitere Informationen zu Google 2LO und dessen Einrichtung finden Sie unter OAuth 2.0 für Server-zu-Server-Anwendungen verwenden.

Autorisierung

Das Dienstkonto muss für die Verwendung mit der Pub/Sub API autorisiert sein:

  1. Aktivieren Sie die Cloud Pub/Sub API in Google Cloud.
  2. Erstellen Sie ein Dienstkonto und einen Dienstkontoschlüssel, wie unter Dienstkonto erstellen beschrieben. Wir empfehlen, ihm nur die Rolle Pub/Sub-Abonnent zuzuweisen. Laden Sie den Dienstkontoschlüssel auf den Computer herunter, auf dem die Pub/Sub API verwendet werden soll.
  3. Geben Sie die Anmeldedaten zur Authentifizierung (Dienstkontoschlüssel) für Ihren Anwendungscode an. Folgen Sie dazu der Anleitung auf der Seite im vorherigen Schritt. Sie können auch manuell ein Zugriffstoken mit oauth2l anfordern, wenn Sie den API-Zugriff schnell testen möchten.
  4. Verwenden Sie die Anmeldedaten des Dienstkontos oder das Zugriffstoken mit der Pub/Sub project.subscriptions API, um Nachrichten abzurufen und zu bestätigen.

OAuth2L

Google oauth2l ist ein Befehlszeilentool für OAuth, das in Go geschrieben wurde. Du kannst es für Mac oder Linux mit Go installieren.

  1. Wenn Sie Go nicht auf Ihrem System haben, laden Sie es zuerst herunter und installieren Sie es.
  2. Nach der Installation von Go installieren Sie oauth2l und fügen den Speicherort in der Umgebungsvariablen PATH hinzu:
    go install github.com/google/oauth2l@latest
    export PATH=$PATH:~/go/bin
  3. Verwenden Sie oauth2l, um ein Zugriffstoken für die API mit den entsprechenden OAuth-Bereichen abzurufen:
    oauth2l fetch --credentials path-to-service-key.json --scope https://www.googleapis.com/auth/pubsub
    https://www.googleapis.com/auth/cloud-platform
    Beispiel, wenn sich Ihr Dienstschlüssel in ~/myServiceKey-eb0a5f900ee3.json befindet:
    oauth2l fetch --credentials ~/myServiceKey-eb0a5f900ee3.json --scope https://www.googleapis.com/auth/pubsub
    https://www.googleapis.com/auth/cloud-platform
    ya29.c.Elo4BmHXK5...

Weitere Informationen zur Verwendung finden Sie in der Readme-Datei oauth2l.

Google API-Clientbibliotheken

Es gibt mehrere Clientbibliotheken für Google APIs, die OAuth 2.0 verwenden. Weitere Informationen zur Programmiersprache Ihrer Wahl finden Sie unter Google API-Clientbibliotheken.

Wenn Sie diese Bibliotheken mit dem Pub/Sub APIverwenden, verwenden Sie die folgenden Bereichsstrings:

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

Fehler

Die folgenden Fehlercodes können im Zusammenhang mit diesem Leitfaden zurückgegeben werden:

Fehlermeldung RPC Fehlerbehebung
Das Kamerabild kann nicht mehr heruntergeladen werden. DEADLINE_EXCEEDED Ereignisbilder laufen 30 Sekunden nach der Veröffentlichung des Ereignisses ab. Achten Sie darauf, das Bild vor dem Ablaufdatum herunterzuladen.
Ereignis-ID gehört nicht zur Kamera. FAILED_PRECONDITION Verwenden Sie den korrekten eventID, der vom Kamera-Ereignis zurückgegeben wurde.

Eine vollständige Liste der API-Fehlercodes finden Sie in der API-Fehlercode-Referenz.