Многокомпонентные устройства на Android

Некоторые устройства Matter состоят из нескольких конечных точек одного типа. Другие устройства Matter имеют иерархическую структуру, где конечные точки вложены друг в друга. В API Home оба типа устройств называются многокомпонентными устройствами .

Плоское изображение

До выпуска версии 1.8 API Home многокомпонентные устройства представлялись API Home как набор отдельных, не связанных между собой устройств. Это называется плоским представлением.

Например, одно настенное панельное устройство с четырьмя выключателями отображается в API Home как четыре отдельных и не связанных между собой устройства. А иерархическое устройство Matter , такое как холодильник, может быть представлено в API Home как набор устройств, каждое из которых соответствует одной из конечных точек.

  • Пример настенной панели с несколькими переключателями, демонстрирующий стандартное представление Matter и плоскую отрисовку Home API.

    Плоское изображение настенной панели с четырьмя выключателями.

  • Пример холодильника, демонстрирующий нативное представление Matter и плоскую отрисовку Home API.

    Плоское изображение холодильника

Рисунок 1 : Примеры плоской визуализации

Многокомпонентное представление

Начиная с версии 1.8 API Home, многокомпонентное устройство может быть представлено в API как одно устройство. Чтобы включить это поведение, вызовите метод devices() для Structure , Room или HomeManager и установите параметр 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 влияет на представление многокомпонентного устройства в API Home:

  • Пример настенной панели с несколькими переключателями, демонстрирующий стандартное представление Matter и многокомпонентную отрисовку Home API.

    Многокомпонентное изображение стеновой панели.

  • Пример холодильника, демонстрирующий нативное представление Matter и многокомпонентную отрисовку Home API.

    Многокомпонентное изображение холодильника.

Рисунок 2 : Примеры многокомпонентного рендеринга

У вас всегда есть возможность получить плоское представление, либо опустив параметр enableMultipartDevices , либо установив его значение равным false .

В многокомпонентном устройстве каждый экземпляр компонента определенного типа называется частью .

Доступ к компонентам может осуществляться непосредственно либо на родительском устройстве, либо в иерархическом порядке с использованием типов устройств или семантических тегов Matter . Семантические теги реализованы в API Home с помощью 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()