事件

事件為非同步資料,由 Google Cloud Pub/Sub 管理,每個 Project都有一個主題。只要使用者未撤銷存取權杖,且事件訊息未過期,事件就會為所有裝置和結構提供更新,並確保收到事件。

啟用活動功能

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

Google Cloud Pub/Sub

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

事件訂閱項目

在 2025 年 1 月前,如果已為 Project啟用事件,系統會以以下形式提供該 Project ID 的專屬主題:

projects/gcp-project-name/subscriptions/topic-id
2025 年 1 月後建立的專案必須自行代管 Pub/Sub 主題,且您需要提供自己的主題 ID。詳情請參閱「建立主題」。

如要接收事件,請視用途建立該主題的「提取」或「推送」訂閱項目。系統支援訂閱多個 SDM 主題。詳情請參閱「管理訂閱項目」。

啟動事件

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

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

活動順序

Pub/Sub 不保證事件的傳送順序,且事件的接收順序可能與事件實際發生的順序不符。使用 timestamp 欄位協助協調事件順序。事件也可能個別傳送,或合併為單一事件訊息。

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

使用者 ID

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

您也可以在每次 API 呼叫的 HTTP 回應標頭中找到 userID

關係事件

關係事件代表資源的關係更新。舉例來說,當裝置新增至結構或從結構中刪除時,就會觸發事件。

關係事件分為三種:

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

關係事件的酬載如下:

酬載

{
  "eventId" : "d77afadd-034a-47cc-bd8e-0fc3054232e6",
  "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 是觸發事件的資源,而 subjectobject 現在有關係的資源。在上述範例中, user 已將這部特定裝置的存取權授予 developer,而 user的授權裝置現在與授權結構相關聯,因此觸發了事件。

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

欄位

欄位 說明 資料類型
eventId 事件的專屬 ID。 string
範例:「e212670b-2601-4951-af7f-da19b5d3f831」
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"
}

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

  • 聊天室已刪除

資源事件

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

因特徵欄位值變更而產生的事件會包含 traits 物件,類似於裝置 GET 呼叫:

酬載

{
  "eventId" : "f3810501-5adb-4553-a3c3-2974f191748c",
  "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" : "650137d7-c980-42b7-9d22-4e612ef0383b",
"timestamp" : "2019-01-01T00:00:01Z",
"resourceUpdate" : { "name" : "enterprises/project-id/devices/device-id", "events" : { "sdm.devices.events.CameraMotion.Motion" : { "eventSessionId" : "CjY5Y3VKaTZwR3o4Y19YbTVfMF...", "eventId" : "njgR22s0yatvMlyCoJ-HlMOTSc...", } } } "userId" : "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi",
"eventThreadId" : "d67cd3f7-86a7-425e-8bb3-462f92ec9f59",
"eventThreadState" : "STARTED",
"resourceGroup" : [ "enterprises/project-id/devices/device-id" ] }

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

欄位

欄位 說明 資料類型
eventId 事件的專屬 ID。 string
示例:「650137d7-c980-42b7-9d22-4e612ef0383b」
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 處理,隨時可能變更。A developer 應根據 SDM API 提供的事件執行緒和工作階段,更新通知。

執行緒狀態

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

  • STARTED:事件串中的第一個事件。
  • UPDATED:持續進行的事件串中的事件。單一執行緒中可能會有零或多個處於這個狀態的事件。
  • ENDED:事件執行緒中的最後一個事件,視執行緒類型而定,可能與最後一個 UPDATED 事件重複。

這個欄位可用來追蹤事件執行緒的進度,以及執行緒何時結束。

事件篩選

在某些情況下,裝置偵測到的事件可能會遭到篩除,無法發布至 SDM Pub/Sub 主題。這種行為稱為事件篩選。事件篩選的目的是避免在短時間內發布過多類似的事件訊息。

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

在 Google Home 應用程式中,已篩選的事件仍會顯示在 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. 按照上一個步驟頁面中的操作說明,將驗證憑證 (服務帳戶金鑰) 提供給應用程式碼,或使用 oauth2l 手動取得存取權杖,以便快速測試 API 存取權。
  4. 使用服務帳戶憑證或存取權杖搭配 Pub/Sub project.subscriptions API,即可提取及確認訊息。

oauth2l

Google oauth2l 是以 Go 語言編寫的 OAuth 指令列工具。請使用 Go 安裝 Mac 或 Linux 版。

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

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

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

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

錯誤

本指南可能會傳回下列錯誤代碼:

錯誤訊息 單次點擊收益 疑難排解
攝影機影像已無法下載。 DEADLINE_EXCEEDED 活動圖片會在活動發布後 30 秒失效。請務必在期限前下載圖片。
事件 ID 不屬於攝影機。 FAILED_PRECONDITION 使用相機事件傳回的正確 eventID

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