事件

事件是非同步的,由 Google Cloud Pub/Sub 管理,每個 Project的單一主題都包含在一個主題中。事件會提供所有裝置和結構的更新,而且您可以確保收到事件,前提是使用者並未撤銷存取權杖,且事件訊息尚未過期。

啟用活動功能

「事件」是 SDM API 的選用功能。請參閱 啟用事件 ,瞭解如何為 Project啟用事件。

Google Cloud Pub/Sub

如要進一步瞭解 Pub/Sub 的運作方式,請參閱 Google Cloud Pub/Sub 說明文件。請特別注意以下幾點:

事件訂閱

為 Project啟用事件後,您必須提供該 Project ID 專屬的主題,格式為:

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

如要接收事件,請根據您的用途為該主題建立pullpush訂閱項目。系統支援多個 SDM 主題訂閱。詳情請參閱「管理訂閱項目」一文。

啟動事件

如要在建立 Pub/Sub 訂閱項目後首次啟動事件,請將 devices.list API 呼叫視為一次性觸發條件。所有結構和裝置的事件會在這次呼叫後發布。

如需範例,請參閱快速入門指南中的「授權」頁面。

事件順序

Pub/Sub 無法保證事件的傳送順序,事件的接收順序也不一定能對應至事件實際發生的順序。使用 timestamp 欄位協助協調事件順序。此外,事件也可以個別抵達或合併為單一事件訊息。

詳情請參閱「排序訊息」。

使用者 ID

如果您實作的是使用者 (而非結構或裝置),請使用事件酬載中的 userID 欄位,將資源和事件建立關聯。這個欄位是代表特定使用者的經模糊處理 ID。

每個 API 呼叫的 HTTP 回應標頭中也提供 userID

關聯事件

關聯事件代表資源的關聯更新。例如裝置在結構中新增,或裝置從結構中刪除時。

關係事件分為三種類型:

  • 已建立
  • 已刪除
  • 已更新

關係事件的酬載如下:

酬載

{
  "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"
}

在關係事件中,object 是觸發事件的資源,subject 則是 object 目前具有關係的資源。在上述範例中, user 已授予 developer這個特定裝置的存取權,而 user的授權裝置現在會與其授權結構相關,因而觸發事件。

subject 只能是會議室或結構。如果 a developer 沒有查看 user結構的權限,則 subject 一律為空白。

欄位

欄位 說明 資料類型
eventId 事件的專屬 ID。 string
範例:「1362476b-4ac4-4608-a8be-4c8cf4101426」
timestamp 事件發生的時間。 string
範例:「2019-01-01T00:00:01Z」
relationUpdate 詳細提供關係更新相關資訊的物件。 object
userId 代表使用者的不重複 ID (經過模糊處理)。 string
範例:「AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi」

如要進一步瞭解不同的事件類型及其運作方式,請參閱事件

示例

每種關係事件的事件酬載都不同:

已建立

已建立結構

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

已建立裝置

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

已建立裝置

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

已更新

已移動裝置

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

已刪除

已刪除結構

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

已刪除裝置

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

已刪除裝置

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

在下列情況下,系統不會傳送關聯事件:

  • 已刪除聊天室

資源事件

資源事件代表特定資源的更新。這種模式可因應特徵欄位的值變動,例如變更溫度控制器的模式。 也可以代表不會變更特徵欄位的裝置動作,例如按下裝置按鈕。

為回應 trait 欄位值的變更而產生的事件會包含 traits 物件,類似裝置的 GET 呼叫:

酬載

{
  "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"
  ]
}

請參閱個別特徵說明文件,瞭解任何特徵欄位變更資源事件的酬載格式。

如果事件因裝置動作未變更特徵欄位而產生,而產生的事件也包含包含 resourceUpdate 物件的酬載,而是包含 events 物件,而非 traits 物件:

酬載

{
  "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" ] }

這些類型的資源事件是以特定特徵定義。例如,動作事件是在 CameraMotion 特徵中定義。請參閱各特徵的說明文件,瞭解這些資源事件的酬載格式。

欄位

欄位 說明 資料類型
eventId 事件的專屬 ID。 string
範例:「3426d266-406b-48f3-9595-5192229a39a0」
timestamp 事件發生的時間。 string
範例:「2019-01-01T00:00:01Z」
resourceUpdate 提供資源更新詳細資訊的物件。 object
userId 代表使用者的不重複 ID (經過模糊處理)。 string
範例:「AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi」
eventThreadId 事件執行緒的專屬 ID。 string
範例:「d67cd3f7-86a7-425e-8bb3-462f92ec9f59」
eventThreadState 事件執行緒的狀態。 string
值:「STARTED」、「UPDATED」、「ENDED」
resourceGroup 表示資源可能會與此事件更新類似的資源。事件本身的資源 (來自 resourceUpdate 物件) 一律會出現在這個物件中。 object

如要進一步瞭解不同的事件類型及其運作方式,請參閱事件

可更新的通知

以資源事件為基礎的通知可在應用程式中實作,例如 Android 或 iOS。為了減少傳送的通知數量,您可以實作名為「可更新的通知」的功能,讓現有通知會根據相同事件執行緒中的後續事件,根據新資訊進行更新。

選取事件功能支援可更新的通知,並在說明文件中標記「可更新。這些事件的酬載中會有名為 eventThreadId 的額外欄位。使用這個欄位將個別事件連結在一起,以更新向使用者顯示的現有通知。

事件執行緒與事件工作階段不同。事件執行緒可辨識相同執行緒中前一個事件的更新狀態。事件工作階段可識別彼此相關的不同事件,而且特定事件時段可能會有多個事件執行緒。

基於通知目的,系統會將不同類型的事件歸為不同的執行緒。

這個執行緒分組和時間邏輯是由 Google 處理,且隨時可能變更。 developer 應根據 SDM API 提供的事件執行緒和工作階段更新通知。

執行緒狀態

支援可更新通知的事件也會有 eventThreadState 欄位,指出該時間點的事件執行緒狀態。這個欄位的值如下:

  • STARTED:事件串中的第一個事件。
  • 已更新 - 持續性事件討論串中的事件。單一執行緒中可能有零或多個包含此狀態的事件。
  • 已結束 — 事件執行緒中的最後一個事件,視討論串類型而定,可能會與最近 UPDATED 事件重複。

這個欄位可用來追蹤事件執行緒的進度和結束時間。

事件篩選

在某些情況下,系統可能會篩除裝置偵測到的事件,而不發布至 SDM Pub/Sub 主題。這種行為稱為事件篩選。事件篩選功能的用意是避免在短時間內發布太多類似的事件訊息。

舉例來說,系統可能會將初始動作事件的訊息發布至 SDM 主題。之後的其他 Motion 訊息則會過濾掉,直到一定的發布時間為止。這段期間過後,系統可能會再次發布該事件類型的事件訊息。

在 Google Home 應用程式 (GHA) 中,篩除的事件仍會顯示在 user的事件記錄中。不過,即使已啟用該通知類型,這類事件也不會產生應用程式通知。

每種事件類型都有專屬的事件篩選邏輯,由 Google 定義,隨時可能有所變動。這個事件篩選邏輯與事件執行緒和工作階段邏輯無關。

服務帳戶

建議您使用服務帳戶來管理 SDM API 訂閱和事件訊息。服務帳戶是由應用程式或虛擬機器 (而非人員) 使用,並且具有專屬的帳戶金鑰。

Pub/Sub API 的服務帳戶授權使用雙足式 OAuth (2LO),

在 2LO 授權流程中:

  • 「 developer 」會使用服務金鑰要求存取權杖。
  • developer 會將存取權杖與對 API 的呼叫搭配使用。

如要進一步瞭解 Google 2LO 以及如何設定,請參閱「針對伺服器對伺服器應用程式使用 OAuth 2.0」一文。

授權

服務帳戶應獲得授權,可與 Pub/Sub API 搭配使用:

  1. 在 Google Cloud 中啟用 Cloud Pub/Sub API
  2. 按照「建立服務帳戶」一文的說明建立服務帳戶和服務帳戶金鑰。建議您只授予「Pub/Sub 訂閱者」角色。請務必將服務帳戶金鑰下載至要使用 Pub/Sub API 的機器。
  3. 按照先前步驟頁面中的操作說明,將驗證憑證 (服務帳戶金鑰) 提供給應用程式程式碼;如果想要快速測試 API 存取權,也可以利用 oauth2l 手動取得存取權杖。
  4. 使用服務帳戶憑證或存取權杖搭配 Pub/Sub project.subscriptions API 來提取及確認訊息。

OAuth2l

Google oauth2l 是以 Go 編寫 OAuth 的指令列工具,可透過 Go 安裝在 Mac 或 Linux 上。

  1. 如果您的系統尚未安裝 Go,請先下載並安裝 Go
  2. 安裝 Go 後,請安裝 oauth2l,並將其位置新增至 PATH 環境變數:
    go install github.com/google/oauth2l@latest
    export PATH=$PATH:~/go/bin
  3. 使用 oauth2l 取得適當的 OAuth 範圍,取得 API 的存取權杖:
    oauth2l 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...

如要進一步瞭解使用資訊,請參閱 oauth2l README

Google API 用戶端程式庫

使用 OAuth 2.0 的 Google API 有多種用戶端程式庫。如要進一步瞭解您選擇的語言,請參閱 Google API 用戶端程式庫

將這些程式庫與 Pub/Sub API搭配使用時,請使用下列範圍字串:

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

錯誤

系統可能根據本指南傳回以下錯誤代碼:

錯誤訊息 RPC 疑難排解
系統不再開放下載相機圖片。 DEADLINE_EXCEEDED 活動圖片會在活動發布的 30 秒後過期。請務必在到期前下載圖片。
事件 ID 不屬於攝影機。 FAILED_PRECONDITION 使用攝影機事件傳回的正確 eventID

如需 API 錯誤代碼的完整清單,請參閱 API 錯誤代碼參考資料