Device APIs may be accessed through the Home APIs for Android. Import these packages into your app:  

    import com.google.home.Home
    import com.google.home.HomeDevice
    import com.google.home.Id

To use specific device types or traits with the Device APIs, they must be imported individually.

For example, to use theMatterOn/Off trait and On/Off Plug-in Unit device type, import the following packages into your application:  

    import com.google.home.matter.standard.OnOff
    import com.google.home.matter.standard.OnOffPluginUnitDevice

| **Note:** Android Studio's auto-complete feature should automatically list all available trait and device type packages when adding`import`lines to your files.

For more information, see[Data model on Android](https://developers.home.google.com/apis/android/data-model).

## Error handling

<br />

Any method in the Home APIs can throw a[`HomeException`](https://developers.home.google.com/reference/kotlin/com/google/home/HomeException), so we recommend that you use a`try-catch`block to catch`HomeException`on all calls.

When handling`HomeException`, check its[`error.code`](https://developers.home.google.com/apis/android/device/reference/kotlin/com/google/home/HomeError#code())and[`error.message`](https://developers.home.google.com/apis/android/device/reference/kotlin/com/google/home/HomeError#message())fields to learn what went wrong. There may be sub-error codes as well, so call the[`getSubErrorCodes()`](https://developers.home.google.com/reference/kotlin/com/google/home/HomeException#getSubErrorCodes())method and check the result.

Any unhandled exceptions will result in your app crashing.

For more information, see[Error handling](https://developers.home.google.com/apis/android/error-handling).

<br />

See[Send a command to a device](https://developers.home.google.com/apis/android/device/control#send-command)for an example.

## Sample calls

<br />

| **Caution:**Code examples shown here may be implemented differently than those of any sample apps, in order to illustrate basic API calls.

<br />

### Get a list of devices

With structure available, a`devices()`call returns a Flow of devices accessible to you from that structure:  

```kotlin
// Get a flow of all devices accessible to the user
val allDevicesFlow: HomeObjectsFlow<HomeDevice> = home.devices()

// Calling list() on a HomeObjectsFlow returns the first Set of elements.
val allDevices: Set<HomeDevice> = allDevicesFlow.list()
```

From there, states for each device are accessible, and supported commands can be sent to the device.

### Read a device state

Let's look at an example of checking the`OnOff`attribute from the device's On/Off trait. Using the Home APIs trait data model, where this trait is identified as`OnOff`, you can retrieve trait data through the device type's`standardTraits`class:  

```kotlin
// Assuming we have a device.
val deviceFlow = home.devices().itemFlow(myDeviceId)

val device = deviceFlow.first()

// Get a flow of a standard trait on the type. distinctUntilChanged() is needed to only trigger
// on the specific trait changes and not the whole type.
val onOffTraitFlow: Flow<OnOff?> =
  device.type(DimmableLightDevice).map { it.standardTraits.onOff }.distinctUntilChanged()

val onOffTrait: OnOff = onOffTraitFlow.first()!!
```

See[`distinctUntilChanged`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/distinct-until-changed.html)to learn more about the Kotlin flow function.

### Invalidate state in a trait subscription

The[`TraitStateInvalidation`interface](https://developers.home.google.com/reference/kotlin/com/google/home/TraitStateInvalidation)provides the ability to invalidate a state retrieved through subscriptions to the target device in cases where the state is not being reported correctly. Examples of when the state may not be reported correctly include using attributes inMattertraits with the "C" quality or due to a device implementation that unexpectedly causes the issue.

This API issues a forced read of the current trait state and returns the result through existing trait flows.

Get the trait, then run a`forceRead`on the trait:  

    val onOffTrait = device.?type(DimmableLightDevice)?.map{it.trait(OnOff)}.first()
    onOffTrait.forceRead()

| **Important:** This API should be used sparingly because it can impact the performance and battery life of the target device.

### Get a list of device type traits

Device types should be used as an entry point for reading traits, as they decompose a device into its functional pieces (like endpoints inMatter).

They also account for trait collisions in the event that a device features two device types, both of which might have the same trait. For example, if a device is both a Speaker and Dimmable Light, it would have two On/Off and two Level Control traits.

To get the list of available traits for the Dimmable Light device type:  

```kotlin
// Get all types available on this device. Requires the types to be part of the registry during
// SDK initialization.
val typesFlow: Flow<Set<DeviceType>> = device.types()

// Get a snapshot of all types.
val types: Set<DeviceType> = typesFlow.first()

// Get the DimmableLightDevice instance from the set of types.
val dimmableLightDevice = types.filterIsInstance<DimmableLightDevice>().firstOrNull()

// Get all traits in the type + traits registered
val allTraits: Set<Trait> = dimmableLightDevice!!.traits()
```

Another kind of trait collision can occur when a device has two traits with the same name. For example,`onOff`could refer to an instance of the standard`OnOff`trait, or it could refer to an instance of a manufacturer-defined`OnOff`trait. To eliminate any potential ambiguity as to which trait is intended, a`Trait`instance referenced through a device should be preceded by a qualifying namespace. For standard traits, that is, those that are analogous toMatterstandard clusters, use`standardTraits`. For Google traits, use`googleTraits`:  

```kotlin
// Accessing standard traits on the type.
val onOffTrait: OnOff? = dimmableLightDevice.standardTraits.onOff
val levelControlTrait: LevelControl? = dimmableLightDevice.standardTraits.levelControl
```

To access a manufacturer-specific trait, reference it directly:  

```kotlin
// Accessing a custom trait on the type.
val customTrait = dimmableLightDevice.trait(MyCustomTrait)
```

### Get a list of devices with a specific trait

The[`filter`](https://kotlinlang.org/docs/collection-filtering.html)function in Kotlin can be used to further refine API calls. For example, to get a list of devices in the home that all have the On/Off trait:  

```kotlin
// Get all devices that support OnOff
val onOffDevices: Flow<List<HomeDevice>> =
  home.devices().map { devices -> devices.filter { it.has(OnOff) } }
```

See the[`Trait`interface](https://developers.home.google.com/reference/kotlin/com/google/home/Trait)for a full list of traits available in the Home APIs.

### Get a list of devices with similar device types

To get a list of devices that represent all the lights in a home:  

```kotlin
// Get a list of devices with similar device types (lights)
val lightDevices =
  home.devices().map { devices ->
    devices.filter {
      it.has(DimmableLightDevice) ||
        it.has(OnOffLightDevice) ||
        it.has(ColorTemperatureLightDevice) ||
        it.has(ExtendedColorLightDevice)
    }
  }
```

There are multiple device types in the Home APIs that could represent a core device type. For example, there is no "Light" device type. Instead, there are four different device types that could represent a light, as shown in the preceding example. As such, to get a comprehensive view of higher-level type of device in a home, multiple device types must be included in filtered flows.

See the[`DeviceType`interface](https://developers.home.google.com/reference/kotlin/com/google/home/DeviceType)for a full list of device types available in the Home APIs.

### Get the Vendor ID or Product ID for a device

The[`BasicInformation`](https://developers.home.google.com/reference/kotlin/com/google/home/matter/standard/BasicInformation)trait includes information like Vendor ID, Product ID, Product Name and the Serial Number for a device:  

```kotlin
// Get device basic information. All general information traits are on the RootNodeDevice type.
val basicInformation = device.type(RootNodeDevice).first().standardTraits.basicInformation!!
println("vendorName ${basicInformation.vendorName}")
println("vendorId ${basicInformation.vendorId}")
println("productId ${basicInformation.productId}")
```

#### Cloud-to-cloud device identification for device manufacturers

If you are a device maker and buildCloud-to-clouddevices, in order to identify your[Cloud-to-cloud](https://developers.home.google.com/cloud-to-cloud/get-started)devices through the`BasicInformation`trait, you can include these string fields in their`SYNC`response:

- The Connectivity Standards Alliance (CSA) issued vendor ID:`"matterOriginalVendorId": "0xfff1",`

- A Product Identifier that uniquely identifies a product of a vendor:`"matterOriginalProductId": "0x1234",`

- A unique identifier for the device, which is constructed in a manufacturer-specific manner:`"matterUniqueId": "matter-device-id",`

When entering these string fields, use yourMatterVendor and Product IDs if you have them. If you are not a CSA member and have not been assigned these IDs, you can leave the`matterOriginalVendorId`and`matterOriginalProductId`fields blank and provide the`matterUniqueId`as the identifier.

The example SYNC response shows the use of these fields:  

    {
      "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
      "payload": {
        "agentUserId": "1836.15267389",
        "devices": [
          {
            "id": "456",
            "type": "action.devices.types.LIGHT",
            "traits": [
              "action.devices.traits.OnOff",
              "action.devices.traits.Brightness",
              "action.devices.traits.ColorSetting",
            ],
            "willReportState": true,
            "deviceInfo": { ... },
            "matterOriginalVendorId": "0xfff1",
            "matterOriginalProductId": "0x1234",
            "matterUniqueId": "matter-device-id",
            "otherDeviceIds": [
              {
                "deviceId": "local-device-id",
              }
            ]
          }
        ]
      }
    }

For more information, see[Cloud-to-cloud`SYNC`documentation](https://developers.home.google.com/cloud-to-cloud/integration/sync#sync-request).

## Device and trait metadata

Devices and traits in the Home APIs have metadata associated with them, which can help in managing the user experience in an app.

Each trait in the Home APIs contains a[`sourceConnectivity`](https://developers.home.google.com/reference/kotlin/com/google/home/SourceConnectivity)property, which has information about a trait's online status and locality (local or remote routing).

### Get the primary type of a device

Some devices may present multiple device types through the Home APIs. To ensure users are presented with the appropriate options in an app (such as device control and suggested automations) for their devices, it's useful to check what the primary device type for a device is.
| **Important:** A device can have more than one primary type.
|
| - All types belonging to the primary endpoint are considered primary types.
| - If one member of aMattersuperset type, such as a light, is primary, all other members of that superset type that are present in the device are also primary. For example, if a device supports`OnOffLightDevice`,`DimmableLightDevice`,`ColorTemperatureLightDevice`and`ExtendedColorLightDevice`, and one of them is primary, they are all primary. For more information on superset device types, see theMatter*Application Cluster Specification* , section 9.2.5,*Superset Device Types*.

First, get the type(s) of the device using[`type()`](https://developers.home.google.com/reference/kotlin/com/google/home/HasDeviceTypes#type(com.google.home.DeviceTypeFactory)), then determine the primary type(s):  

```kotlin
val types = device.types().first()
val primaryTypes = types.filter { it.metadata.isPrimaryType }
```

### Check if a trait is online

Use the`connectivityState()`method to check a trait's connectivity:  

```kotlin
val onOffConnectivity = onOffTrait?.metadata?.sourceConnectivity?.connectivityState
```

Some traits, typically Googlesmart hometraits, may show offline if the device doesn't have internet connectivity. This is because these traits are cloud-based and don't have local routing.

### Check connectivity for a device

Connectivity for a device is actually checked at the device type level because some devices support multiple device types. The state returned is a combination of the connectivity states for all traits on that device.  

```kotlin
val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState
```

A state of`PARTIALLY_ONLINE`may be observed in the case of mixed device types when there is no internet connectivity.Matterstandard traits may still be online due to local routing, but cloud-based traits will be offline.
| **Important:** A device that has a`connectivityState`of[`PARTIALLY_ONLINE`](https://developers.home.google.com/reference/kotlin/com/google/home/ConnectivityState#PARTIALLY_ONLINE)should be represented to the user as "Online."

### Check the network routing of a trait

The locality for a trait is also available in the Home APIs. The`dataSourceLocality`indicates whether the trait is routed remotely (through the cloud), locally (through a local hub), or peer-to-peer (direct from device to device, no hub).

The unknown locality value`UNSPECIFIED`is possible, for example, while an app is booting and hasn't yet reached a hub or server for device connectivity. These devices aren't reachable and will fail interaction requests from commands or events. It is up to the client to determine how to handle such devices.  

```kotlin
val onOffLocality = onOffTrait?.metadata?.sourceConnectivity?.dataSourceLocality
```

### Check the network routing for a device

Like connectivity, locality is checked at a device type level. The state returned is a combination of the locality for all traits on that device.  

```kotlin
val lightLocality = dimmableLightDevice.metadata.sourceConnectivity.dataSourceLocality
```

A state of`MIXED`may be observed in a similar scenario as that of`PARTIALLY_ONLINE`connectivity: some traits are cloud-based while others are local.

### Change the name of a device

Call the[`setName()`](https://developers.home.google.com/reference/kotlin/com/google/home/HomeDevice#setName(kotlin.String))method to change the name of a device:  

```kotlin
mixerDevice.setName("Grendel")
```

Names will be truncated if over the 60 Unicode code point (character) limit and no errors will be thrown. Developers are responsible for handling long names and, for example, can decide if they want to inform users names will be truncated.

## API list

Once an instance of[`Home`](https://developers.home.google.com/reference/kotlin/com/google/home/Home)is created, the following Device APIs are accessible through it:

|     API     |                                                                                                             Description                                                                                                              |
|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `devices()` | Get all the devices in all structures on the Google Account. Returns a[`HomeObjectsFlow`](https://developers.home.google.com/reference/kotlin/com/google/home/HomeObjectsFlow)that provides further retrieval and filtering options. |

Once you have a[`HomeDevice`](https://developers.home.google.com/reference/kotlin/com/google/home/HomeDevice), the following APIs are accessible through it:

|              API               |                                                                Description                                                                 |
|--------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
| `allCandidates()`              | Returns all[automation candidates](https://developers.home.google.com/apis/android/automation/discovery)for the device and its children.   |
| `candidates()`                 | Returns all[automation candidates](https://developers.home.google.com/apis/android/automation/discovery)for the device.                    |
| `connectivityStateChanged`     | The most recent time the state of the device changed.                                                                                      |
| `events(event)`                | Gets a flow of a specific Event.                                                                                                           |
| `events(trait)`                | Gets a flow of all Events by this Trait.                                                                                                   |
| `events(traits)`               | Gets a flow of all Events by these Traits.                                                                                                 |
| `getSourceConnectivity(trait)` | Get metadata for a particular trait. Returns a`SourceConnectivity`.                                                                        |
| `has(trait)`                   | Check if the current requested trait is supported by the device.                                                                           |
| `has(type)`                    | If the device supports the type provided.                                                                                                  |
| `id`                           | The unique system ID of the device.                                                                                                        |
| `isMatterDevice`               | If the device is backed byMatter.                                                                                                          |
| `name`                         | The user-provided name of the device.                                                                                                      |
| `room()`                       | The room the device is assigned to. Returns a`Room`.                                                                                       |
| `roomId`                       | The ID of the room the device is assigned to. Returns an`Id`.                                                                              |
| `sourceConnectivity`           | The source connectivity of the device, representing aggregated connectivity states and network locality of the device's traits.            |
| `structure()`                  | The structure the device is assigned to. Returns a`Structure`.                                                                             |
| `structureId`                  | The ID of the structure the device is assigned to. Returns an`Id`.                                                                         |
| `type(type)`                   | Get the type definition with the traits populated (when available) for direct access. Always returns an up-to-date snapshot of the traits. |
| `types()`                      | Get a list of all types available on the device.                                                                                           |