Некоторые устройства Matter состоят из нескольких конечных точек одного типа. Другие устройства Matter имеют иерархическую структуру, в которой конечные точки вложены в другие конечные точки. В Home API оба типа устройств называются составными.
Плоское представление
До выпуска 1.8 Home API составные устройства представлялись в Home API как набор отдельных, не связанных между собой устройств. Это называется плоским представлением.
Например, одно устройство настенной панели с четырьмя переключателями отображается в Home API как четыре отдельных и несвязанных устройства. А иерархическое Matter устройство, например холодильник, может быть представлено в Home API как набор устройств, каждое из которых соответствует одной из конечных точек.
Плоское изображение настенной панели с четырьмя переключателями.
Плоское изображение холодильника
Составное представление
Начиная с версии 1.8 Home API, составное устройство может быть представлено в API как одно устройство. Чтобы включить эту функцию, вызовите метод devices() для Structure, Room или HomeManager и задайте для параметра enableMultipartDevices значение true:
var multipartDevice = structure.devices(enableMultipartDevices = multipartEnabled) var multipartDevice = multipartDevices.list().filter{ device -> device.has(PowerStrip)}
На следующих схемах показано, как параметр enableMultipartDevices влияет на представление составного устройства в Home API:
Составное представление настенной панели.
Составное представление холодильника.
Вы всегда можете получить плоское представление, опустив параметр enableMultipartDevices или задав для него значение false.
Как управлять устройством с несколькими частями
Каждый экземпляр компонента в составном устройстве называется частью.
Доступ к частям можно получить непосредственно на родительском устройстве или на части иерархическим образом, используя типы устройств или семантические теги Matter. Семантические теги реализованы в 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()