一部の Matter デバイスは、同じデバイスタイプの複数のエンドポイントで構成されています。他の Matter デバイスは 階層型で、エンドポイントが他のエンドポイント内にネストされています。Google Home API では、どちらの種類のデバイスも マルチパート デバイスと呼ばれます。
フラット表現
Google Home API のリリース 1.8 より前では、マルチパート デバイスは、別個の関連性のないデバイスのセットとして Google Home API で表されます。これは、フラット表現と呼ばれます。
たとえば、4 つのスイッチを備えた 1 つのウォールパネル デバイスは、Google Home API では 4 つの別個の関連性のないデバイスとして表示されます。冷蔵庫などの階層型 Matterデバイスは、 Google Home API では、エンドポイントの 1 つに対応するデバイスのセットとして表される場合があります。
4 スイッチ ウォールパネルのフラット表現。
冷蔵庫のフラット表現
マルチパート表現
Google Home API のリリース 1.8 以降では、マルチパート デバイスを 1 つのデバイスとして API
で表すことができます。この動作を有効にするには、Structure、Room、または HomeManager で
devices() メソッドを呼び出し、enableMultipartDevices パラメータを true に設定します。
let devices = try await self.home.devices(enableMultipartDevices: true).list() let device = try XCTUnwrap(devices.first { $0.id == powerstripID }) let outlets = try await device.types.getAll(of: OnOffPluginUnitDeviceType.self)
次の図は、enableMultipartDevices オプションが Google Home API でのマルチパート
デバイスの表現にどのように影響するかを示しています。
ウォールパネルのマルチパート表現。
冷蔵庫のマルチパート表現。
enableMultipartDevices パラメータを省略するか、false に設定することで、常にフラット表現を取得できます。
マルチパート デバイスを操作する
マルチパート デバイス内では、デバイスタイプの各コンポーネント インスタンスはパーツと呼ばれます。
パーツには、デバイスタイプまたは Matter セマンティック
タグを使用して、親デバイスまたはパーツから
階層的に直接アクセスできます。セマンティック タグは、Google Home API で
DescriptorTrait.SemanticTagStructを使用して実装されます。
DeviceType 抽象クラスは HasParts インターフェースを実装しているため、デベロッパーは parts プロパティと part() メソッドを使用してデバイスツリーを操作できます。各パーツ インスタンスも HasParts インターフェースを実装しているため、パーツで parts() を呼び出すと、ゼロ以上のサブパーツのリストが生成されます。
次の例は、マルチスイッチ デバイスのパーツにアクセスする方法を示しています。
val device = homeManager .devices(enableMultipartDevices = true) .itemFlow(Id(MULTI_SWITCH_DEVICE)) .first() // Here at top-level, we are using the homeDevice.parts() API to access flow of // all the switches. Then we get the part ids. val partIds = device .parts() .map { parts -> parts.filter { it.has(Switch) }.mapNotNull { it.metadata.partId } } .first() .toSet()
次の例は、冷蔵庫デバイスのパーツにアクセスする方法を示しています。
val rootDevice = homeManager.devices(true).itemFlow(Id("device@uuid1")) // On the top level, HomeDevice provides both plural (parts) // and singular (part) APIs. // The parts() API returns all the parts accessible from the top level, // including Endpoint 0 and its children. val childParts = rootDevice.parts().first() // childParts contain (EP0 as RootNode, EP1 as Refrigerator) // The singular part() API accepts DeviceType and tags (optional). val refrigerator = rootDevice.part(Refrigerator).first() // Get the refrigerator device which in this case is just device@uuid1 val refrigeratorDevice = homeManager.devices(false).itemFlow(refrigerator.metadata.partId.deviceId) // DeviceType uses a synchronous API for providing access to parts val cabinets = refrigerator.parts // [EP2, EP3] // Get the HomeDevice for these cabinets (device@uuid2 and device@uuid3) val cabinetDeviceIds = cabinets.map { it.metadata.partId } // Now use the devices API with enableMultipartDevices = false. val cabinetDevices = homeManager.devices(false) .map { devices -> devices.filter { it.id in cabinetDeviceIds } }.first()