Google Developers
Published in

Google Developers

Implementing Report State for your smart home service

If you want to integrate your smart home devices with the Google Assistant, you will need to set up a webhook that handles four types of intents: SYNC, QUERY, EXECUTE, DISCONNECT.

When the user first links their Google account to the service, you receive a SYNC intent. When the user asks a question like “What is the temperature in the house?”, you receive a QUERY intent. When the user gives a command like “Set the house to 75”, you receive an EXECUTE intent with thermostatTemperatureSetpoint having a value of 75. If the user unlinks their account from the Google Assistant, you will receive a DISCONNECT intent.

For relative commands, like “Turn down the temperature”, the Google Assistant needs to know the current temperature of your thermostat before it can change the value. To do this, it can send a QUERY intent to your service, decrement the setpoint, and then send a second EXECUTE intent.

This can result in longer delays for the user, as there are now two calls. This delay can result in a poor user experience when giving voice commands.

The new user interface for smart home devices.

Now that Smart Displays are available with the Google Assistant built-in, you can visually view the states of your devices and control them with a graphical user interface. Having a responsive user interface is important, which means that delays should be minimized. Waiting for a QUERY request to get the current set point will result in a noticeable visual delay.

Developers can now use the Report State API to report the state of their devices to the home graph proactively, meaning the Google Assistant will not need to QUERY the device for the current state.

Setting up a service account

To securely make a connection between your service and the home graph, you first need to enable the HomeGraph API for your Google Cloud project.

Next, create a service account using the Google Cloud Console. Select Create Credentials > Service account key.

Create a new service account with a particular name with the role Service Accounts > Service Account Token Creator. Create and download the JSON file to your computer. Now you’re set to start making API calls to the home graph.

Making API calls

You can make API calls using gRPC or HTTP POST. The protos are available on GitHub if you want to compile them. You can visit the gRPC homepage to learn more about it.

Below is an example of authenticating with your service account key and then sending a request with a payload:

private HomeGraphApiServiceGrpc.HomeGraphApiServiceBlockingStub blockingStub;
public void reportStateWithGrpc(String agentUserId) {
GoogleCredentials creds;
try {
FileInputStream stream = new FileInputStream("key.json");
creds = GoogleCredentials.fromStream(stream);
ManagedChannel channel = ManagedChannelBuilder.forTarget("homegraph.googleapis.com").build();

blockingStub = HomeGraphApiServiceGrpc.newBlockingStub(channel)
.withCallCredentials(MoreCallCredentials.from(creds));
ReportStateAndNotificationRequest request =
ReportStateAndNotificationRequest.newBuilder()
.setRequestId(requestId)
.setAgentUserId(agentUserId)
.setPayload(getPayload())
.build();
blockingStub.reportStateAndNotification(request);
} catch (IOException e) {
e.printStackTrace();
}
}

When making an HTTP POST request, you can use your service account key to obtain a JSON Web Token (JWT), a standard for allowing two services to securely transfer data as each payload is signed by the sender.

The payload format includes a map with states for each device that you want to report:

{
"requestId": "ff36a3cc-ec34–11e6-b1a0–64510650abcf",
"agent_user_id": "1234",
"payload": {
"devices": {
"states": {
"1458765": {
"on": true
},
"4578964": {
"brightness": 50,
}
}
}
}
}

The home graph expects the state data to include all of the values for a particular trait, although it does not require all of the state data from the device. For example, if you are reporting the state for a device with the StartStop trait, you must send the values for both isRunning and isPaused.

Here’s an example of using report state in the Actions on Google client library for Node.js. As shown, you provide your service account key in the smarthome constructor, and then the reportState method will automatically make signed requests:

const app = smarthome({
jwt: require('./jwt.json');
});
const reportState = () => {
app.reportState({
requestId: '123ABC',
agentUserId: 'user-123',
payload: {
devices: {
states: {
"light-123": {
on: true
}
}
}
}
})
.then((res) => {
// Report state was successful
})
.catch((res) => {
// Report state failed
})
};

Testing Report State

Now that you know how to implement report state, you will want to make sure that your API calls work. To do this, you can set up and deploy the Smart Home Dashboard, which will allow you to make requests to the home graph and read back the values that you have sent:

You can find all of the devices from a particular user and view the current states that the home graph has of each. When you report a new state, you can use this tool to verify that the state has changed as expected.

Learning More

If you want to learn more about integrating report state with your smart home service, you can watch the YouTube video above or read the documentation on the feature.

To try it out for yourself, you can get started with this smart home codelab.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Nick Felker

Nick Felker

Social Media Expert -- Rowan University 2017 -- IoT & Assistant @ Google