Device APIs may be accessed through the Home APIs. 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 the Matter On/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
For more information, see Data model.
Error handling
Any method in the Home APIs can throw a
HomeException
, so we recommend that you use a try-catch
block to catch
HomeException
on all calls.
When handling HomeException
, check its code
and message
fields to learn what went wrong.
Any unhandled exceptions will result in your app crashing.
For more information, see Error handling.
See Send a command to a device for an example.
Sample calls
Get a list of devices
With structure available, a devices()
call returns a Flow of devices
accessible to you from that structure:
// 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:
// 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
to learn more about the Kotlin flow function.
Invalidate state in a trait subscription
The TraitStateInvalidation
interface
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 in Matter traits 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 generalDiagnosticsTrait = device.trait(GeneralDiagnostics).first()
generalDiagnosticsTrait.forceRead()
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 in Matter).
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:
// 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 to
Matter standard clusters, use standardTraits
. For Google
traits, use googleTraits
:
// 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:
// Accessing a custom trait on the type. val customTrait = dimmableLightDevice.trait(MyCustomTrait)
Get a list of devices with a specific trait
The
filter
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:
// Get all devices that support OnOff val onOffDevices: Flow<List<HomeDevice>> = home.devices().map { devices -> devices.filter { it.has(OnOff) } }
See the Trait
interface 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:
// 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
for a full list of device types available in the Home APIs.
Get the Vendor ID or Product ID for a device
The BasicInformation
trait includes information like Vendor ID, Product ID, Product Name and the
Serial Number for a device:
// 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}")
Identify Cloud-to-cloud devices
If you are a device maker and build Cloud-to-cloud devices,
in order to identify your
Cloud-to-cloud 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 your Matter
Vendor 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.
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
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.
First, get the type(s) of the device using
type()
,
then determine which is the primary type:
val types = device.types().first() val primaryType = types.first { it.metadata.isPrimaryType }
Check if a trait is online
Use the connectivityState()
method to check a trait's connectivity:
val onOffConnectivity = onOffTrait?.metadata?.sourceConnectivity?.connectivityState
Some traits, typically Google smart home traits, may show offline if the device doesn't have internet connectivity. This is because these traits are cloud-based and do not 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.
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. Matter standard
traits may still be online due to local routing, but cloud-based traits
will be offline.
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.
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.
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.
API list
Once an instance of
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 that provides further retrieval and filtering options. |
Once you have a HomeDevice
,
the following APIs are accessible through it:
API | Description |
---|---|
allCandidates() |
Returns all automation candidates for the device and its children. |
candidates() |
Returns all automation candidates 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. |
isInRoom |
If the device is in a room. |
isInStructure |
If the device is in a structure. |
isMatterDevice |
If the device is backed by Matter. |
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. |