存取裝置和裝置中繼資料

裝置 API 可透過 Home API 存取。將這些套件匯入應用程式:

import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.Id

如要使用特定裝置類型或特徵搭配 Device API,必須個別匯入。

舉例來說,如要使用 Matter 開/關特徵和開/關外掛元件裝置類型,請將下列套件匯入應用程式:

import com.google.home.matter.standard.OnOff
import com.google.home.matter.standard.OnOffPluginUnitDevice

詳情請參閱「資料模型」。

處理錯誤

Home API 中的任何方法都可能擲回 HomeException,因此建議您使用 try-catch 區塊,在所有呼叫中擷取 HomeException

處理 HomeException 時,請檢查其 codemessage 欄位,瞭解錯誤所在。

任何未處理的例外狀況都會導致應用程式停止運作。

詳情請參閱「錯誤處理」。

如需範例,請參閱「向裝置傳送指令」。

呼叫範例

取得裝置清單

當結構體可用時,devices() 呼叫會傳回可透過該結構體存取的裝置流程:

// Get a flow of all devices accessible to the user
val allDevicesFlow: HomeObjectsFlow<HomeDevice> = home.devices()

// Calling list() on a HomeObjectsFlow returns the first Set of elements.
val allDevices: Set<HomeDevice> = allDevicesFlow.list()

從這裡,您可以存取每部裝置的狀態,並將支援的指令傳送至裝置。

讀取裝置狀態

讓我們來看看如何檢查裝置的開/關特徵中的 OnOff 屬性。使用 Home API 特徵資料模型,其中特徵識別為 OnOff,您可以透過裝置類型的 standardTraits 類別擷取特徵資料:

// Assuming we have a device.
val deviceFlow = home.devices().itemFlow(myDeviceId)

val device = deviceFlow.first()

// Get a flow of a standard trait on the type. distinctUntilChanged() is needed to only trigger
// on the specific trait changes and not the whole type.
val onOffTraitFlow: Flow<OnOff?> =
  device.type(DimmableLightDevice).map { it.standardTraits.onOff }.distinctUntilChanged()

val onOffTrait: OnOff = onOffTraitFlow.first()!!

請參閱 distinctUntilChanged,進一步瞭解 Kotlin 流程函式。

在特徵訂閱中使狀態失效

在狀態未正確回報的情況下,TraitStateInvalidation 介面可讓您將透過訂閱從目標裝置擷取的狀態設為無效。狀態可能無法正確回報的情況包括:在 Matter 特徵中使用「C」品質的屬性,或是由於裝置實作意外導致問題。

這個 API 會強制讀取目前特徵狀態,並透過現有特徵流程傳回結果。

取得特徵,然後對特徵執行 forceRead

val generalDiagnosticsTrait = device.trait(GeneralDiagnostics).first()
generalDiagnosticsTrait.forceRead()

取得裝置類型特徵清單

裝置類型應用於讀取特徵的進入點,因為它們會將裝置分解為功能性部分 (例如 Matter 中的端點)。

當裝置具有兩種裝置類型,且兩者都可能具有相同特徵時,這些特徵也會考量特徵衝突。舉例來說,如果裝置同時是喇叭和可調光燈,就會有兩個開/關和兩個 Level Control 特徵。

如要取得可調光燈具裝置類型的可用特徵清單,請按照下列步驟操作:

// Get all types available on this device. Requires the types to be part of the registry during
// SDK initialization.
val typesFlow: Flow<Set<DeviceType>> = device.types()

// Get a snapshot of all types.
val types: Set<DeviceType> = typesFlow.first()

// Get the DimmableLightDevice instance from the set of types.
val dimmableLightDevice = types.filterIsInstance<DimmableLightDevice>().firstOrNull()

// Get all traits in the type + traits registered
val allTraits: Set<Trait> = dimmableLightDevice!!.traits()

如果裝置有兩個同名的特徵,就可能發生另一種特徵衝突。舉例來說,onOff 可以參照標準 OnOff 特徵的例項,也可以參照製造商定義的 OnOff 特徵例項。為避免特徵的用途產生任何模糊不清的情況,透過裝置參照的 Trait 例項應在前方加上限定命名空間。如為標準特徵 (即類似於 Matter 標準叢集的那些特徵),請使用 standardTraits。如果是 Google 特徵,請使用 googleTraits

// Accessing standard traits on the type.
val onOffTrait: OnOff? = dimmableLightDevice.standardTraits.onOff
val levelControlTrait: LevelControl? = dimmableLightDevice.standardTraits.levelControl

如要存取特定製造商特徵,請直接參照該特徵:

// Accessing a custom trait on the type.
val customTrait = dimmableLightDevice.trait(MyCustomTrait)

取得具有特定特徵的裝置清單

您可以使用 Kotlin 中的 filter 函式進一步精進 API 呼叫。舉例來說,如要取得家中所有裝置的開/關特徵清單:

// Get all devices that support OnOff
val onOffDevices: Flow<List<HomeDevice>> =
  home.devices().map { devices -> devices.filter { it.has(OnOff) } }

如需 Home API 中可用的特徵完整清單,請參閱 Trait 介面

取得類似裝置類型的裝置清單

如要取得代表住家所有燈的裝置清單,請按照下列步驟操作:

// Get a list of devices with similar device types (lights)
val lightDevices =
  home.devices().map { devices ->
    devices.filter {
      it.has(DimmableLightDevice) ||
        it.has(OnOffLightDevice) ||
        it.has(ColorTemperatureLightDevice) ||
        it.has(ExtendedColorLightDevice)
    }
  }

Home API 中有多種裝置類型可代表核心裝置類型。例如,沒有「燈」裝置類型。相反地,有四種不同的裝置類型可代表燈具,如上述範例所示。因此,如要全面掌握住家中較高層級的裝置類型,篩選流程中必須納入多種裝置類型。

如需 Home API 中可用的裝置類型完整清單,請參閱 DeviceType 介面

取得裝置的廠商 ID 或產品 ID

BasicInformation 特徵包含供應商 ID、產品 ID、產品名稱和裝置序號等資訊:

// Get device basic information. All general information traits are on the RootNodeDevice type.
val basicInformation = device.type(RootNodeDevice).first().standardTraits.basicInformation!!
println("vendorName ${basicInformation.vendorName}")
println("vendorId ${basicInformation.vendorId}")
println("productId ${basicInformation.productId}")

找出雲端到雲端裝置

如果您是裝置製造商,並建構 Cloud-to-cloud 裝置,為了透過 BasicInformation 特徵識別 Cloud-to-cloud 裝置,您可以在 SYNC 回應中加入下列字串欄位:

  • Connectivity Standards Alliance (CSA) 核發的供應商 ID: "matterOriginalVendorId": "0xfff1",

  • 產品 ID:用於唯一識別供應商產品的 ID: "matterOriginalProductId": "0x1234",

  • 裝置的專屬 ID,以製造商專屬方式建構:"matterUniqueId": "matter-device-id",

輸入這些字串欄位時,請使用您的 Matter 供應商和產品 ID (如有)。如果您不是 CSA 成員,且未指派這些 ID,可以將 matterOriginalVendorIdmatterOriginalProductId 欄位留空,並提供 matterUniqueId 做為 ID。

以下 SYNC 回應範例說明這些欄位的用法:

{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "agentUserId": "1836.15267389",
    "devices": [
      {
        "id": "456",
        "type": "action.devices.types.LIGHT",
        "traits": [
          "action.devices.traits.OnOff",
          "action.devices.traits.Brightness",
          "action.devices.traits.ColorSetting",
        ],
        "willReportState": true,
        "deviceInfo": { ... },
        "matterOriginalVendorId": "0xfff1",
        "matterOriginalProductId": "0x1234",
        "matterUniqueId": "matter-device-id",
        "otherDeviceIds": [
          {
            "deviceId": "local-device-id",
          }
        ]
      }
    ]
  }
}

詳情請參閱 Cloud-to-cloud SYNC 說明文件

裝置和特徵中繼資料

Home API 中的裝置和特徵會附帶相關聯的結構描述,有助於管理應用程式中的使用者體驗。

Home API 中的每個特徵都包含 sourceConnectivity 屬性,其中包含特徵的線上狀態和位置資訊 (本機或遠端路由)。

取得裝置的主要類型

部分裝置可能會透過 Google Home API 呈現多種裝置類型。為了確保使用者在應用程式中看到適合其裝置的選項 (例如裝置控制和建議的自動化動作),建議您檢查裝置的主要裝置類型。

首先,請使用 type() 取得裝置類型,然後判斷哪個類型為主要類型:

val types = device.types().first()
val primaryType = types.first { it.metadata.isPrimaryType }

檢查特徵是否已上線

使用 connectivityState() 方法檢查特徵的連線能力:

val onOffConnectivity = onOffTrait?.metadata?.sourceConnectivity?.connectivityState

如果裝置未連上網際網路,部分特徵 (通常是 Google smart home 特徵) 可能會顯示為離線。這是因為這些特徵是雲端式,且沒有本機路由。

檢查裝置的連線

裝置的連線能力實際上是在裝置類型層級檢查,因為某些裝置支援多種裝置類型。傳回的狀態是該裝置上所有特徵的連線狀態組合。

val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState

在沒有網際網路連線的情況下,如果裝置類型混合,可能會觀察到 PARTIALLY_ONLINE 狀態。由於本機路由,Matter 標準特徵可能仍會上線,但雲端特徵會離線。

檢查特徵的網路路由

特徵的地區資訊也可以在 Home API 中使用。dataSourceLocality 會指出特徵是透過雲端遠端路由、透過本機中樞路由,還是點對點路由 (直接從裝置傳送至裝置,不經過中樞)。

例如,當應用程式正在啟動,但尚未連上裝置連線的中心或伺服器時,就可能會出現不明的區域值 UNSPECIFIED。這些裝置無法連線,因此無法回應指令或事件的互動要求。客戶端必須自行決定如何處理這類裝置。

val onOffLocality = onOffTrait?.metadata?.sourceConnectivity?.dataSourceLocality

檢查裝置的網路路由

與連線一樣,系統會在裝置類型層級檢查區域性。系統會傳回該裝置上所有特徵的區域組合。

val lightLocality = dimmableLightDevice.metadata.sourceConnectivity.dataSourceLocality

PARTIALLY_ONLINE 連線類似的情況下,可能會觀察到 MIXED 狀態:部分特徵是雲端式,其他則是本機式。

API 清單

建立 Home 的例項後,即可透過該例項存取下列 Device API:

API 說明
devices() 取得 Google 帳戶中所有結構體的所有裝置。傳回 HomeObjectsFlow,提供進一步的擷取和篩選選項。

取得 HomeDevice 後,您可以透過該 API 存取下列 API:

API 說明
allCandidates() 傳回裝置及其子項的所有自動化候選項目
candidates() 傳回裝置的所有自動化候選項目
connectivityStateChanged 裝置狀態最近一次變更的時間。
events(event) 取得特定事件的流程。
events(trait) 根據此特徵,取得所有事件的資料流。
events(traits) 根據這些特徵取得所有事件的資料流。
getSourceConnectivity(trait) 取得特定特徵的中繼資料。傳回 SourceConnectivity
has(trait) 檢查裝置是否支援目前要求的特徵。
has(type) 裝置是否支援所提供的類型。
id 裝置的專屬系統 ID。
isInRoom 裝置是否位於某個房間。
isInStructure 裝置是否位於建築物內。
isMatterDevice 如果裝置由 Matter 備份。
name 使用者提供的裝置名稱。
room() 裝置所屬房間。傳回 Room
roomId 裝置指派到的房間 ID。傳回 Id
sourceConnectivity 裝置的來源連線,代表裝置特徵的匯總連線狀態和網路位置。
structure() 裝置指派的結構體。傳回 Structure
structureId 裝置所屬結構體的 ID。傳回 Id
type(type) 取得型別定義,並填入特徵 (如有) 以便直接存取。一律傳回特徵的最新快照。
types() 取得裝置上可用的所有類型清單。