일부 Matter 기기는 동일한 기기 유형의 여러 엔드포인트로 구성됩니다. 다른 Matter 기기는 계층적이며 엔드포인트가 다른 엔드포인트 내에 중첩되어 있습니다. Home API에서 두 가지 유형의 기기를 모두 멀티파트 기기 라고 합니다.
플랫 표현
Home API 버전 1.8 이전에는 멀티파트 기기가 Home API에 별도의 관련 없는 기기 집합으로 표시됩니다. 이를 플랫 표현이라고 합니다.
예를 들어 스위치가 4개 있는 단일 벽면 패널 기기는 Home API에 4개의 개별적이고 관련 없는 기기로 표시됩니다. 냉장고와 같은 계층적 Matter 기기는 Home API에서 엔드포인트 중 하나에 해당하는 기기 집합으로 표시될 수 있습니다.
4-스위치 벽면 패널의 플랫 표현
냉장고의 플랫 표현
멀티파트 표현
Home API 버전 1.8부터 멀티파트 기기를 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 옵션이 Home API에서 멀티파트 기기의 표현에 미치는 영향을 보여줍니다.
벽면 패널의 멀티파트 표현
냉장고의 멀티파트 표현
enableMultipartDevices 매개변수를 생략하거나 false로 설정하여 언제든지 플랫 표현을 가져올 수 있습니다.
멀티파트 기기 탐색
멀티파트 기기 내에서 기기 유형의 각 구성요소 인스턴스를 파트 라고 합니다.
파트에는 기기 유형 또는 Matter 시맨틱
태그를 사용하여 상위 기기 또는 파트에서 계층적 방식으로 직접 액세스할 수 있습니다. 시맨틱 태그는 Home API에서
DescriptorTrait.SemanticTagStruct를 사용하여 구현됩니다.
DeviceType 추상 클래스는 HasParts 인터페이스를 구현하여 개발자가 parts 속성 및 part() 메서드를 통해 기기 트리를 탐색할 수 있도록 합니다. 각 파트 인스턴스는 HasParts 인터페이스도 구현하므로 파트에서 parts()를 호출하면 0개 이상의 하위 파트 목록이 생성됩니다.
다음 예에서는 멀티 스위치 기기의 파트에 액세스하는 방법을 보여줍니다.
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()