Niektóre urządzenia Matter składają się z wielu punktów końcowych tego samego typu. Inne urządzenia Matter mają strukturę hierarchiczną, a punkty końcowe są zagnieżdżone w innych punktach końcowych. W interfejsach Home API oba rodzaje urządzeń są nazywane urządzeniami wieloczęściowymi.
Płaska reprezentacja
Przed wersją 1.8 interfejsów Home API urządzenia wieloczęściowe były reprezentowane przez te interfejsy jako zestaw oddzielnych, niezwiązanych ze sobą urządzeń. Nazywa się to reprezentacją płaską.
Na przykład pojedynczy panel ścienny z 4 przełącznikami jest widoczny w interfejsach Home API jako 4 oddzielne i niepowiązane urządzenia. Urządzenie hierarchiczne, takie jak lodówka, może być reprezentowane w interfejsach Home API jako zestaw urządzeń, z których każde odpowiada jednemu z punktów końcowych.Matter
Płaska reprezentacja 4-przyciskowego panelu ściennego.
Płaska ilustracja lodówki
Reprezentacja wieloczęściowa
Od wersji 1.8 interfejsów Home API urządzenie wieloczęściowe może być reprezentowane w interfejsie API jako jedno urządzenie. Aby włączyć to zachowanie, wywołaj metodę devices() w przypadku Structure, Room lub HomeManager i ustaw parametr enableMultipartDevices na 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)
Poniższe diagramy pokazują, jak opcja enableMultipartDevices wpływa na reprezentację urządzenia wieloczęściowego w interfejsach Home API:
Wieloczęściowa reprezentacja panelu ściennego.
Wieloczęściowa reprezentacja lodówki.
Zawsze możesz uzyskać płaską reprezentację, pomijając parametr enableMultipartDevices lub ustawiając go na false.
Poruszanie się po urządzeniu wieloczęściowym
W przypadku urządzenia wieloczęściowego każde wystąpienie komponentu danego typu urządzenia jest nazywane częścią.
Dostęp do części można uzyskać bezpośrednio na urządzeniu nadrzędnym lub w sposób hierarchiczny, korzystając z typów urządzeń lub Mattertagów semantycznych. Tagi semantyczne są zaimplementowane w interfejsach Home API za pomocą elementu DescriptorTrait.SemanticTagStruct.
Klasa abstrakcyjna DeviceType implementuje interfejs HasParts, dzięki czemu programiści mogą poruszać się po drzewie urządzeń za pomocą właściwości parts i metody part(). Każda instancja części implementuje też interfejs HasParts, dzięki czemu wywołanie parts() na części zwraca listę zawierającą 0 lub więcej podczęści.
Poniższy przykład pokazuje, jak uzyskać dostęp do części urządzenia wielofunkcyjnego:
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()
W kolejnym przykładzie pokazujemy, jak uzyskać dostęp do części lodówki:
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()