事件為非同步資料,由 Google Cloud Pub/Sub 管理,每個 Project都有一個主題。只要使用者未撤銷存取權杖,且事件訊息未過期,事件就會為所有裝置和結構提供更新,並確保收到事件。
啟用活動功能
事件是 SDM API 的選用功能。請參閱 啟用事件 一文,瞭解如何為 Project啟用事件。
Google Cloud Pub/Sub
如要進一步瞭解 Pub/Sub 的運作方式,請參閱 Google Cloud Pub/Sub 說明文件。請特別注意以下幾點:
- 透過操作指南瞭解 Pub/Sub 的基本知識。
- 瞭解驗證的運作方式。
- 選擇我們提供的用戶端程式庫,或自行撰寫程式碼並使用 REST/HTTP 或 gRPC API 介面。
事件訂閱項目
在 2025 年 1 月前,如果已為 Project啟用事件,系統會以以下形式提供該 Project ID 的專屬主題:
projects/gcp-project-name/subscriptions/topic-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
是觸發事件的資源,而 subject
是 object
現在有關係的資源。在上述範例中, 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 使用:
- 在 Google Cloud 中啟用 Cloud Pub/Sub API。
- 按照「建立服務帳戶」一文中的說明,建立服務帳戶和服務帳戶金鑰。建議只授予「Pub/Sub 訂閱者」角色。請務必將服務帳戶金鑰下載到要使用 Pub/Sub API 的機器。
- 按照上一個步驟頁面中的操作說明,將驗證憑證 (服務帳戶金鑰) 提供給應用程式碼,或使用
oauth2l
手動取得存取權杖,以便快速測試 API 存取權。 - 使用服務帳戶憑證或存取權杖搭配 Pub/Sub
project.subscriptions
API,即可提取及確認訊息。
oauth2l
Google oauth2l
是以 Go 語言編寫的 OAuth 指令列工具。請使用 Go 安裝 Mac 或 Linux 版。
- 如果系統沒有 Go,請先下載並安裝。
- 安裝 Go 後,請安裝
oauth2l
,並將其位置新增至PATH
環境變數:go install github.com/google/oauth2l@latest
export PATH=$PATH:~/go/bin
- 使用
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 錯誤代碼參考資料。