> [!WARNING]
> **Experimental:** This feature is experimental and is subject to change without notice.

Some Matter devices are made up of multiple endpoints with
the same device type. Other Matter devices are
hierarchical, with endpoints nested within other endpoints. In the Home APIs,
both kinds of devices are referred to as *multipart devices*.

## Flat representation

Prior to release 1.8 of the Home APIs, multipart devices are represented
by the Home APIs as a set of separate, unrelated devices. This is referred to
as the *flat* representation.

For example, a single wall panel device with four switches appears in the Home
APIs as four distinct and unrelated devices. And a hierarchical
Matter device such as a refrigerator may be represented in
the Home APIs as a set of devices, each corresponding to one of the endpoints.
- ![Wall panel with multiple switches example showing the native Matter
  representation and Home API's flat rendering](https://developers.home.google.com/static/apis/images/4-switch-wall-panel-flat.png)

  Flat representation of a 4-switch wall panel.
  ![](https://developers.home.google.com/static/apis/images/4-switch-wall-panel-flat.png)
- ![Refrigerator example showing the native Matter representation and
  Home API's flat rendering](https://developers.home.google.com/static/apis/images/refrigerator-flat.png)

  Flat representation of a refrigerator
  ![](https://developers.home.google.com/static/apis/images/refrigerator-flat.png)
**Figure 1**: Flat rendering examples

## Multipart representation

Starting with release 1.8 of the Home APIs, a multipart device can be
represented in the API as a single device. To enable this behavior, call the
`devices()` method on
`Structure`, `Room`, or `HomeManager`
and set the `enableMultipartDevices` parameter to `true`:

```kotlin
var multipartDevice = structure.devices(enableMultipartDevices = multipartEnabled)
var multipartDevice = multipartDevices.list().filter{ device ->  device.has(PowerStrip)}
```


The following diagrams illustrate how the `enableMultipartDevices` option
affects the representation of a multipart device in the Home APIs:
- ![Wall panel with multiple switches example showing the native Matter
  representation and Home API's multipart rendering](https://developers.home.google.com/static/apis/images/4-switch-wall-panel-multipart.png)

  Multipart representation of a wall panel.
  ![](https://developers.home.google.com/static/apis/images/4-switch-wall-panel-multipart.png)
- ![Refrigerator example showing the native Matter representation and Home
  API's multipart rendering](https://developers.home.google.com/static/apis/images/refrigerator-multipart.png)

  Multipart representation of a refrigerator.
  ![](https://developers.home.google.com/static/apis/images/refrigerator-multipart.png)
**Figure 2**: Multipart rendering examples

You always have the option to get the flat representation by either omitting
the `enableMultipartDevices` parameter, or by setting it to `false`.

> [!NOTE]
> **Note:** All devices are returned, whether `enableMultipartDevices` is `true` or `false`. For example, when a basic OnOffLight device is represented as a multipart device, it has just a single part.

## Navigate a multipart device

Within a multipart device, each component instance of a device type is called a
*part*.

Parts may be accessed directly on either the parent device or a part in a
hierarchical manner, using device types or Matter semantic
tags. Semantic tags are implemented in the Home APIs with
[`DescriptorTrait.SemanticTagStruct`](https://developers.home.google.com/reference/kotlin/com/google/home/matter/standard/DescriptorTrait.SemanticTagStruct.md.txt).

The [`DeviceType`](https://developers.home.google.com/reference/kotlin/com/google/home/DeviceType.md.txt) abstract class
implements the
[`HasParts`](https://developers.home.google.com/reference/kotlin/com/google/home/HasParts.md.txt) interface,
allowing developers to navigate the device tree through the
[`parts`](https://developers.home.google.com/reference/kotlin/com/google/home/HasParts.md.txt#parts()) property and
[`part()`](https://developers.home.google.com/reference/kotlin/com/google/home/HasParts.md.txt#part(com.google.home.DeviceTypeFactory,kotlin.Array))
method. Each part instance also implements the `HasParts` interface, so that
calling `parts()` on a part produces a list of zero or more sub-parts.

The following example shows how to access the parts of the multi-switch device:

```kotlin
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()
```

> [!IMPORTANT]
> **Important:** If you attempt to access part using an unrecognized tag, you'll get a [`HomeException`](https://developers.home.google.com/reference/kotlin/com/google/home/HomeException.md.txt).

The next example shows how to access the parts of a refrigerator device:

```kotlin
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()
```