1. Before you begin
As an Internet of Things (IoT) developer, you can build Cloud-to-cloud integrations that give your users the ability to control their devices through touch controls in the Google Home app and voice commands with the Google Assistant.
Learning the debugging tools for Cloud-to-cloud integrations is an important step to build production quality integration with Google Assistant. To facilitate easy monitoring and debugging, Google Cloud Platform (GCP) Metrics and Logging and Test Suite for smart home are available to help you identify and resolve issues for your integrations.
Prerequisites
- Read Create a Cloud-to-cloud integration developer guide
- Run Connect smart home devices to the Google Assistant codelab
What you'll build
In this codelab, you'll deploy a Cloud-to-cloud integration with 2 defects and connect it to the Assistant, then debug the integration's defects via Test Suite for smart home & Google Cloud Platform (GCP) Metrics and Logging.
What you'll learn
- How to use GCP Metrics and Logging to identify and resolve production issues
- How to use Test Suite for smart home to identify functional and API issues
What you'll need
- A web browser, such as Google Chrome
- An iOS or Android device with the Google Home app installed
- Node.js version 10.16 or later
- A Google Cloud billing account
2. Run the faulty app
Get the source code
Click the following link to download the sample for this codelab on your development machine:
...or you can clone the GitHub repository from the command line:
$ git clone https://github.com/google-home/smarthome-debug.git
About the project
The washer app contains the following subdirectories:
public
: A frontend UI to easily control and monitor the state of the smart washer.functions
: A fully implemented cloud service that manages the smart washer with Cloud Functions for Firebase and Firebase Realtime Database.
Connect to Firebase
Open terminal on your development machine. Navigate to the washer-faulty
directory, then set up the Firebase CLI with your integration project built in the Connect smart home devices to the Google Assistant codelab:
$ cd washer-faulty $ firebase use <firebase-project-id>
Deploy to Firebase
Navigate to the functions
folder and install all the necessary dependencies using npm.
$ cd functions $ npm install
Note: If you see the message below, you can ignore and proceed. The warning is due to some older dependencies and you can find more details here.
found 5 high severity vulnerabilities run `npm audit fix` to fix them, or `npm audit` for details
Now that you have installed the dependencies and configured your project, you are ready to deploy the faulty washer app.
$ firebase deploy
This is the console output you should see:
... ✔ Deploy complete! Project Console: https://console.firebase.google.com/project/<Firebase-project-id>/overview Hosting URL: https://<Firebase-project-id>.firebaseapp.com
Update HomeGraph
Open the Hosting URL in your browser (https://<firebase-project-id>.firebaseapp.com
) to view the web app. On the web UI, click the Refresh button to update HomeGraph via Request Sync with the latest device metadata from the faulty washer app:
Open the Google Home app and verify that you can see the washer device named Faulty Washer.
3. Test your Integration
After you deploy your project, test that your integration controls the washer.
Test the washer
Check the value change when you try any of the following voice commands through your phone:
"Hey Google, turn on my washer."
"Hey Google, start my washer."
"Hey Google, pause my washer."
"Hey Google, resume my washer."
"Hey Google, stop my washer."
You will notice Assistant responds that something is wrong via voice when you pause / resume the washer:
"Sorry, I couldn't reach <project display name>."
To debug this issue, you first need more information on the error to narrow down and identify the root cause.
Smarthome Analytics dashboard
A good place to inspect errors is Smarthome Analytics dashboard, which aggregates charts of Usage and Health metrics for your cloud fulfillment:
- The Usage metrics reflects the usage trend of your Cloud-to-cloud integration, including the number of daily active users and total request count to your fulfillment.
- The Health metrics helps you monitor anomaly occurrence on your Cloud-to-cloud integration, covering request latency, success percentage, and error breakdown.
To narrow down the cause of the error, follow the steps below to access the project dashboard.
- In the Developer Console, go to the Projects page.
- Select your smart home project.
- Click the Analytics tab on the left menu.
- This will lead you to a list of dashboards for your project on Google Cloud. Select the Google Home Analytics - Cloud Integration dashboard.
- Scroll down to Cloud Fulfillment Errors - Status Breakdown chart to view the error codes for the highlighted time range.
The PARTNER_RESPONSE_MISSING_DEVICE
error code provides a hint to the root cause. Next, retrieve event logs based on the error code for more details.
Access event logs
In order to gain more details on the error, access event logs for your Cloud-to-cloud integration via Cloud Logging.
Open the Navigation Menu in Google Cloud Platform, and under Operations, select Logging > Logs Explorer to access the event logs for your project. Alternatively, you can search for Logs Explorer in the search box.
In the Search all fields input field, enter the query PARTNER_RESPONSE_MISSING_DEVICE
and click Run Query. The logs matching the query are displayed in the Results section.
The error log shows a smart home event with error details indicating:
- The user action taken is "resuming washer" (
actionType:
"STARTSTOP_UNPAUSE
"), corresponding to the recent failed voice command. - The associated debugging message is "
JSON response does not include device.
"
Based on the debugging message, you should check why the washer app doesn't include the correct device in EXECUTE
response.
Identify the root cause of the error
In functions/index.js
, find the EXECUTE
handler (in the onExecute
array) that returns the status of each command and the new device state. The insertion of device IDs into an EXECUTE
response depends on the resolving of updateDevice
function:
index.js
app.onExecute(async (body) => {
...
for (const command of intent.payload.commands) {
for (const device of command.devices) {
for (const execution of command.execution) {
executePromises.push(
updateDevice(execution, device.id)
.then((data) => {
result.ids.push(device.id);
Object.assign(result.states, data);
})
.catch((e) =>
functions.logger.error('EXECUTE',
device.id, e.message)));
}
}
}
Further check how the updateDevice
function handles pause / resume on the washer, and you will find the string to match for the pause / resume command is incorrect:
index.js
const updateDevice = async (execution, deviceId) => {
const {params, command} = execution;
let state; let ref;
switch (command) {
...
case 'action.devices.commands.PauseUnpausePause':
state = {isPaused: params.pause};
if (params.pause) state.isRunning = false;
ref = firebaseRef.child(deviceId).child('StartStop');
break;
}
return ref.update(state)
.then(() => state);
};
Fix the error
Now that you have identified the root cause of the error, you can correct the string for the pause / resume command:
index.js
const updateDevice = async (execution, deviceId) => {
const {params, command} = execution;
let state; let ref;
switch (command) {
...
case 'action.devices.commands.PauseUnpause':
state = {isPaused: params.pause};
if (params.pause) state.isRunning = false;
ref = firebaseRef.child(deviceId).child('StartStop');
break;
}
return ref.update(state)
.then(() => state);
};
Test your fix
Deploy the updated code using the Firebase CLI:
firebase deploy --only functions
Retry the following voice commands, and you will find Assistant responds correctly now when you pause / resume the washer.
"Hey Google, pause my washer."
=>
"Sure, pausing the washer."
"Hey Google, resume my washer."
=>
"Got it, resuming the washer."
You can also test the current state of your washer by asking questions.
"Hey Google, is my washer on?"
"Hey Google, is my washer running?"
"Hey Google, what cycle is my washer on?"
4. Test your integration with Test Suite
In addition to testing manually, you can use the automated Test Suite for smart home to validate use cases based on the device types and traits associated with your integration. The Test Suite runs a series of tests to detect issues in your integration, and shows informative messages for failed test cases to expedite your debugging before diving into event logs.
Run Test Suite for smart home
Follow these instructions to test your Cloud-to-cloud integration by Test Suite:
- In your web browser, open the Test Suite for smart home.
- Sign in to Google using the button in the top-right corner. This allows the Test Suite to send the commands directly to Google Assistant.
- In the Project ID field, enter the project ID of your Cloud-to-cloud integration. And then click NEXT to proceed.
- In the Test Settings step, you will see Test Suite list the device type and traits of the washer.
- Disable the Test Request Sync option since the sample washer app has no UI to add / remove / rename the washer. In a production system, you must trigger Request Sync whenever the user adds / removes / renames devices.
- Click NEXT to start running the test.
After Test Suite completes running, view the results of test cases. You will notice two failed test cases caught with respective error message:
To debug your Cloud-to-cloud integration for the failure, you will need to identify the root cause of the error by first analyzing the error message.
Analyze error message
In order to help developers identify the root cause, Test Suite shows error messages for each failed test case that indicate the reason for the failure.
For the first failed test case above,
its error message indicates Test Suite expects "isPause": true
in the states reported from your Cloud-to-cloud integration, but the actual states include only "isPause": false
.
In addition, the second failed test case's error message indicates the states in QUERY
response from your Cloud-to-cloud integration include "isPause": true
, which differs from "isPause": false
in the states reported from your Cloud-to-cloud integration:
According to both error messages, you should then check whether your integration reports state isPaused
with the correct value.
Identify the root cause of the error
Open functions/index.js
, which contains the reportstate
function that posts state changes to Home Graph via Report State. Inspect the Report State payload, and you will find the payload is missing the isPaused
state, which is exactly what the Test Suite checked for in the failed test cases.
index.js
exports.reportstate = functions.database.ref('{deviceId}').onWrite(
async (change, context) => {
...
const requestBody = {
requestId: 'ff36a3cc', /* Any unique ID */
agentUserId: USER_ID,
payload: {
devices: {
states: {
/* Report the current state of our washer */
[context.params.deviceId]: {
online: true,
on: snapshot.OnOff.on,
isRunning: snapshot.StartStop.isRunning,
currentRunCycle: [{
currentCycle: 'rinse',
nextCycle: 'spin',
lang: 'en',
}],
currentTotalRemainingTime: 1212,
currentCycleRemainingTime: 301,
},
},
},
},
};
const res = await homegraph.devices.reportStateAndNotification({
requestBody,
});
...
});
Fix the error
Now that you have identified the root cause of the error, revise functions/index.js
by adding the isPaused
state to the Report State payload:
index.js
exports.reportstate = functions.database.ref('{deviceId}').onWrite(
async (change, context) => {
...
const requestBody = {
requestId: 'ff36a3cc', /* Any unique ID */
agentUserId: USER_ID,
payload: {
devices: {
states: {
/* Report the current state of our washer */
[context.params.deviceId]: {
online: true,
on: snapshot.OnOff.on,
isPaused: snapshot.StartStop.isPaused,
isRunning: snapshot.StartStop.isRunning,
currentRunCycle: [{
currentCycle: 'rinse',
nextCycle: 'spin',
lang: 'en',
}],
currentTotalRemainingTime: 1212,
currentCycleRemainingTime: 301,
},
},
},
},
};
...
});
Test your fix
Deploy the updated code using the Firebase CLI:
$ firebase deploy --only functions
Re-run the Test Suite for smart home, and you will find that all test cases have passed.
5. Congratulations
Congratulations! You successfully learned how to troubleshoot Cloud-to-cloud integration issues via Test Suite for smart home & GCP Metrics and Logging.
Learn more
Building off this Codelab, try the following exercises and explore additional resources:
- Add more supported traits to your device and test them with the Test Suite.
- Create dashboards, set up alerts, and access metrics data programmatically to get helpful usage metrics about your integration.
- Explore local fulfillment for smart home.
- Check out our GitHub sample to explore more.
You can also learn more about testing and submitting an integration for review, including the certification process to publish your integration to users.