Ereignisse

Ereignisse sind asynchron und werden von Google Cloud Pub/Sub in einem einzelnen Thema pro Projectverwaltet. Ereignisse liefern Updates für alle Geräte und Gebäude. Der Empfang von Ereignissen ist sichergestellt, solange das Zugriffstoken nicht vom Nutzer widerrufen wurde und die Ereignisnachrichten nicht abgelaufen sind.

Ereignisse aktivieren

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

Google Cloud Pub/Sub

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

Ereignisabo

Vor Januar 2025 wurde Ihnen, wenn Ereignisse für Ihr Projectaktiviert waren, ein Thema speziell für diese Project ID zur Verfügung gestellt, und zwar in folgendem Format:

projects/gcp-project-name/subscriptions/topic-id
Projekte, die nach Januar 2025 erstellt wurden, müssen ihre Pub/Sub-Themen selbst hosten. Sie müssen Ihre eigene Themen-ID angeben. Weitere Informationen finden Sie unter Thema erstellen.

Wenn Sie Ereignisse empfangen möchten, erstellen Sie je nach Anwendungsfall ein Pull- oder Push-Abo für dieses Thema. Es werden mehrere Abos für das SDM-Thema unterstützt. Weitere Informationen finden Sie unter Abos verwalten.

Ereignisse initiieren

Wenn Sie Ereignisse zum ersten Mal initiieren möchten, nachdem das Pub/Sub-Abo erstellt wurde, führen Sie einen devices.list API-Aufruf als einmaligen Trigger aus. Nach diesem Aufruf werden Ereignisse für alle Gebäude und Geräte veröffentlicht.

Ein Beispiel finden Sie auf der SeiteAutorisieren im Schnellstart leitfaden.

Ereignisreihenfolge

Pub/Sub garantiert keine geordnete Zustellung von Ereignissen. Die Reihenfolge, in der Ereignisse empfangen werden, entspricht möglicherweise nicht der Reihenfolge, in der die Ereignisse tatsächlich aufgetreten sind. Verwenden Sie das Feld timestamp , um die Reihenfolge der Ereignisse abzugleichen. Ereignisse können auch einzeln oder kombiniert in einer einzigen Ereignisnachricht eintreffen.

Weitere Informationen finden Sie unter Nachrichten sortieren.

Nutzer-IDs

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

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

Beziehungsereignisse

Beziehungsereignisse stellen eine relationale Aktualisierung für eine Ressource dar. Beispielsweise wenn ein Gerät einem Gebäude hinzugefügt oder daraus gelöscht wird.

Es gibt drei Arten von Beziehungsereignissen:

  • ERSTELLT
  • GELÖSCHT
  • AKTUALISIERT

Die Nutzlast für ein Beziehungsereignis sieht so aus:

Nutzlast

{
  "eventId" : "84527b4c-13ed-479c-a756-21b9bb4111b5",
  "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 das object die Ressource, die das Ereignis ausgelöst hat, und das subject ist die Ressource, mit der das object jetzt eine Beziehung hat. Im obigen Beispiel hat ein user einem Zugriff auf dieses bestimmte Gerät gewährt, und das user's autorisierte Gerät des developerist jetzt mit seinem autorisierten Gebäude verknüpft, wodurch das Ereignis ausgelöst wird.

Ein subject kann nur ein Raum oder ein Gebäude sein. Wenn a developer keine Berechtigung hat, das userGebäude des' anzusehen, ist das subject immer leer.

Felder

Feld Beschreibung Datentyp
eventId Die eindeutige Kennung für das Ereignis. string
Beispiel: „d3c2bcb3-6588-4747-a65c-07c7f50a482d“
timestamp Die Zeit, in der das Ereignis aufgetreten ist. string
Beispiel: „2019-01-01T00:00:01Z“
relationUpdate Ein Objekt mit Details zur Aktualisierung der Beziehung. object
userId Eine eindeutige, verschleierte Kennung, die den Nutzer darstellt. string
Beispiel: „AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi“

Weitere Informationen zu den verschiedenen Arten von Ereignissen und ihrer Funktionsweise finden Sie unter Ereignisse.

Beispiele

Die Ereignisnutzlasten unterscheiden sich für die einzelnen Arten von Beziehungsereignissen:

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 nicht gesendet, wenn:

  • Ein Raum gelöscht wird

Ressourcenereignisse

Ein Ressourcenereignis stellt eine Aktualisierung dar, die sich auf eine bestimmte Ressource bezieht. Es kann als Reaktion auf eine Änderung des Werts eines Merkmalsfelds erfolgen, z. B. wenn der Modus eines Thermostats geändert wird. Es kann auch eine Geräteaktion darstellen, die kein Merkmalsfeld ändert, z. B. wenn eine Gerätetaste gedrückt wird.

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

Nutzlast

{
  "eventId" : "be30516f-e855-49fb-b50d-cbf031c81c30",
  "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 den einzelnen Merkmalen finden Sie Informationen zum Nutzlastformat für Ressourcenereignisse, die durch Änderungen von Merkmalsfeldern ausgelöst werden.

Ein Ereignis, das als Reaktion auf eine Geräteaktion generiert wird, die kein Merkmalsfeld ändert, hat ebenfalls eine Nutzlast mit einem resourceUpdate Objekt, aber mit einem events Objekt anstelle eines traits Objekts:

Nutzlast

{
  "eventId" : "8e70e14f-bf37-4be0-bc85-8fd56b93b412",
"timestamp" : "2019-01-01T00:00:01Z",
"resourceUpdate" : { "name" : "enterprises/project-id/devices/device-id", "events" : { "sdm.devices.events.CameraMotion.Motion" : { "eventSessionId" : "CjY5Y3VKaTZwR3o4Y19YbTVfMF...", "eventId" : "Qah4OySZOSvtiUbdpFWafiRTfI...", } } } "userId" : "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi",
"eventThreadId" : "d67cd3f7-86a7-425e-8bb3-462f92ec9f59",
"eventThreadState" : "STARTED",
"resourceGroup" : [ "enterprises/project-id/devices/device-id" ] }

Diese Arten von Ressourcenereignissen werden in bestimmten Merkmalen definiert. Das Ereignis „Bewegung“ wird beispielsweise im Merkmal CameraMotion definiert. In der Dokumentation zu den einzelnen Merkmalen finden Sie Informationen zum Nutzlastformat für diese Arten von Ressourcenereignissen.

Felder

Feld Beschreibung Datentyp
eventId Die eindeutige Kennung für das Ereignis. string
Beispiel: „8e70e14f-bf37-4be0-bc85-8fd56b93b412“
timestamp Die Zeit, in der das Ereignis aufgetreten ist. string
Beispiel: „2019-01-01T00:00:01Z“
resourceUpdate Ein Objekt mit Details zur Aktualisierung der Ressource. object
userId Eine eindeutige, verschleierte Kennung, die den Nutzer darstellt. string
Beispiel: „AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi“
eventThreadId Die eindeutige Kennung 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 Arten von Ereignissen und ihrer Funktionsweise finden Sie unter Ereignisse.

Aktualisierbare Benachrichtigungen

Benachrichtigungen, die auf Ressourcenereignissen basieren, 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 Aktualisierbare Benachrichtigungen implementiert werden. Dabei werden vorhandene Benachrichtigungen mit neuen Informationen aktualisiert, die auf nachfolgenden Ereignissen im selben Ereignis-Thread basieren.

Ereignisse, die aktualisierbare Benachrichtigungen unterstützen, sind in der Dokumentation als Aktualisierbar  gekennzeichnet. Diese Ereignisse haben in ihren Nutzlasten ein zusätzliches Feld namens eventThreadId. Mit diesem Feld können einzelne Ereignisse verknüpft werden, um eine vorhandene Benachrichtigung zu aktualisieren, die für einen Nutzer angezeigt wurde.

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

Für Benachrichtigungen werden verschiedene Arten von Ereignissen in verschiedenen Threads gruppiert.

Diese Threadgruppierung und Timinglogik wird von Google verwaltet und kann jederzeit geändert werden. A developer sollte Benachrichtigungen basierend auf den Ereignis-Threads und ‑Sitzungen aktualisieren, die von der SDM API bereitgestellt werden.

Thread-Status

Ereignisse, die aktualisierbare Benachrichtigungen unterstützen, haben auch ein Feld eventThreadState, das den Status des Ereignis-Threads zu diesem Zeitpunkt angibt. Dieses Feld hat die folgenden Werte:

  • STARTED – Das erste Ereignis in einem Ereignis-Thread.
  • UPDATED – Ein Ereignis in einem laufenden Ereignis-Thread. In einem einzelnen Thread kann es null oder mehr Ereignisse mit diesem Status geben.
  • ENDED – Das letzte Ereignis in einem Ereignis-Thread. Je nach Threadtyp kann es sich um ein Duplikat des letzten UPDATED-Ereignisses handeln.

Mit diesem Feld lässt sich der Fortschritt eines Ereignis-Threads verfolgen und feststellen, wann er beendet wurde.

Ereignisfilterung

In einigen Fällen werden Ereignisse, die von einem Gerät erkannt wurden, möglicherweise herausgefiltert, sodass sie nicht in einem SDM Pub/Sub-Thema veröffentlicht werden. Dieses Verhalten wird als Ereignisfilterung bezeichnet. Der Zweck der Ereignisfilterung besteht darin, zu vermeiden, dass in kurzer Zeit zu viele ähnliche Ereignisnachrichten veröffentlicht werden.

Beispielsweise kann eine Nachricht für ein anfängliches Bewegungsereignis in einem SDM-Thema veröffentlicht werden. Andere Nachrichten für Bewegungen werden danach so lange herausgefiltert, bis ein bestimmter Zeitraum verstrichen ist. Nach Ablauf dieses Zeitraums kann wieder eine Ereignisnachricht für diesen Ereignistyp veröffentlicht werden.

In der Google Home App werden gefilterte Ereignisse weiterhin im userEreignisverlauf des angezeigt. Solche Ereignisse lösen jedoch keine App-Benachrichtigung aus, auch wenn dieser Benachrichtigungstyp aktiviert ist.

Jeder Ereignistyp hat seine eigene Ereignisfilterlogik, die von Google definiert wird und jederzeit geändert werden kann. Diese Ereignisfilterlogik ist unabhängig von der Logik für Ereignis-Threads und ‑Sitzungen.

Dienstkonten

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

Die Dienstkontoautorisierung für die Pub/Sub API verwendet OAuth mit zwei Beinen (2LO).

Im 2LO-Autorisierungsablauf gilt Folgendes:

  • fordert mit einem Dienstkontoschlüssel ein Zugriffstoken an. developer
  • verwendet das Zugriffstoken für Aufrufe der API. developer

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

Autorisierung

Das Dienstkonto sollte 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, der die Pub/Sub API verwenden soll.
  3. Geben Sie Ihre Anmeldedaten (Dienstkontoschlüssel) in Ihrem Anwendungscode an. Folgen Sie dazu der Anleitung auf der Seite im vorherigen Schritt. Wenn Sie den API-Zugriff schnell testen möchten, können Sie auch manuell ein Zugriffstoken mit oauth2l abrufen, 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

oauth2l von Google ist ein Befehlszeilentool für OAuth, das in Go geschrieben wurde. Installieren Sie es für Mac oder Linux mit Go.

  1. Wenn Sie Go nicht auf Ihrem System haben, laden Sie es herunter und installieren Sie es zuerst.
  2. Installieren Sie nach der Installation von Go oauth2l und fügen Sie den Speicherort der Umgebungsvariable 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
    Wenn sich Ihr Dienstkontoschlüssel beispielsweise unter ~/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 oauth2l READMEDatei.

Google API-Clientbibliotheken

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

Wenn Sie diese Bibliotheken mit der 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. Laden Sie das Bild vor Ablauf herunter.
Die Ereignis-ID gehört nicht zur Kamera. FAILED_PRECONDITION Verwenden Sie die richtige eventID, die vom Kameraereignis zurückgegeben wurde.

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