存取 Android 裝置和裝置中繼資料

裝置 API 可透過 Android 版 Google 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

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

處理錯誤

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

處理 HomeException 時,請檢查 codemessage 欄位,瞭解發生錯誤的原因。

任何未處理的例外狀況都會導致應用程式當機。

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

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

呼叫範例

取得裝置清單

有了可用結構,devices() 呼叫就會傳回您可從該結構存取的裝置 Flow:

// 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 屬性為例,瞭解如何使用 On/Off 特徵。使用 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 Flow 函式。

使特徵訂閱中的狀態失效

TraitStateInvalidation 介面可讓您在狀態回報不正確時,使透過訂閱項目擷取的目標裝置狀態失效。舉例來說,如果是在「C」品質的 Matter 特徵中使用屬性,或是裝置實作方式導致問題,狀態可能就無法正確回報。

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

取得特徵,然後在特徵上執行 forceRead

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

取得裝置類型特徵清單

裝置類型應做為讀取特徵的進入點,因為這類類型會將裝置分解為功能片段 (例如 Matter 中的端點)。

如果裝置有兩種裝置類型,且兩者可能具有相同特徵,系統也會將特徵衝突納入考量。舉例來說,如果裝置同時是音箱和可調光燈具,就會有兩項開/關和兩項等級控制特徵。

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

// 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: "matterOriginalProductId": "0x1234",

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

輸入這些字串欄位時,請使用供應商和產品 ID (如有)。Matter如果不是 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 說明文件

裝置和特徵中繼資料

Google Home API 中的裝置和特徵會與中繼資料建立關聯,有助於管理應用程式中的使用者體驗。

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

取得裝置的主要類型

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

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

val types = device.types().first()
val primaryTypes = types.filter { 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

在類似的案例中,您可能會觀察到 MIXED 狀態,如同 PARTIALLY_ONLINE 連線狀態:某些特徵是雲端特徵,其他則是本機特徵。

變更裝置名稱

呼叫 setName() 方法來變更裝置名稱:

mixerDevice.setName("Grendel")

如果名稱超過 60 個 Unicode 碼點 (字元) 的限制,系統會截斷名稱,且不會擲回錯誤。開發人員有責任處理長名稱,例如決定是否要通知使用者名稱會遭到截斷。

API 清單

建立 Home 執行個體後,即可透過該執行個體存取下列裝置 API:

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

取得 HomeDevice 後,即可透過該物件存取下列 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() 取得裝置上所有可用類型的清單。