1. 准备工作
作为一名物联网 (IoT) 开发者,您可以构建云到云集成,让用户能够通过 Google Home 应用中的触控功能和 Google 助理的语音指令来控制设备。

学习云到云集成调试工具是构建与 Google 助理的生产质量集成的重要一步。为了便于监控和调试,我们提供了 Google Cloud Platform (GCP) 指标和日志记录以及智能家居测试套件,可帮助您识别和解决集成方面的问题。
前提条件
- 阅读创建云到云集成开发者指南
- 运行将智能家居设备关联到 Google 助理 Codelab
构建内容
在此 Codelab 中,您将部署一个包含 2 个缺陷的云到云集成,并将其关联到 Google 助理,然后通过智能家居测试套件和 Google Cloud Platform (GCP) 指标与日志记录来调试集成的缺陷。
学习内容
- 如何使用 GCP 指标和日志记录来识别和解决生产问题
- 如何使用智能家居测试套件来识别功能和 API 问题
所需条件
- 网络浏览器,例如 Google Chrome
- 安装了 Google Home 应用的 iOS 或 Android 设备
- Node.js 10.16 或更高版本
- Google Cloud 结算账号
2. 运行有缺陷的应用
获取源代码
点击以下链接,将此 Codelab 的示例下载到您的开发机器上:
...或者,您也可以通过命令行克隆 GitHub 代码库:
$ git clone https://github.com/google-home/smarthome-debug.git
项目简介
洗衣机应用包含以下子目录:
public:一种前端界面,可轻松地控制和监控智能洗衣机的状态。functions:一种已全面实现的云服务,可使用 Cloud Functions for Firebase 和 Firebase Realtime Database 来管理智能洗衣机
连接到 Firebase
在开发机器上打开终端。前往 washer-faulty 目录,然后使用在将智能家居设备连接到 Google 助理 Codelab 中构建的集成项目设置 Firebase CLI:
$ cd washer-faulty $ firebase use <firebase-project-id>
部署到 Firebase
前往 functions 文件夹,然后使用 npm. 安装所有必要的依赖项
$ cd functions $ npm install
注意:如果您看到以下消息,可以忽略并继续操作。出现此警告是因为存在一些旧版依赖项,如需了解详情,请点击此处。
found 5 high severity vulnerabilities run `npm audit fix` to fix them, or `npm audit` for details
依赖性安装完毕且配置好项目后,您就可以部署故障洗衣机应用了。
$ firebase deploy
您应该会看到以下控制台输出:
... ✔ Deploy complete! Project Console: https://console.firebase.google.com/project/<Firebase-project-id>/overview Hosting URL: https://<Firebase-project-id>.firebaseapp.com
更新 HomeGraph
在浏览器 (https://<firebase-project-id>.firebaseapp.com) 中打开托管网址以查看此 Web 应用。在 Web 界面上,点击刷新
按钮,使用 Request Sync 通过有故障的洗衣机应用更新 HomeGraph 中的最新设备元数据。

打开 Google Home 应用,然后验证您能否看到名为 Faulty Washer 的洗衣机设备。

3. 测试集成
部署项目后,测试集成是否能够控制洗衣机。
测试洗衣机
如果您通过手机尝试下达以下任意一条语音指令,就会看到值发生变化:
“Ok Google,启动洗衣机。”
“Ok Google,运行洗衣机。”
“Hey Google,暂停洗衣机。”
“Hey Google,继续运行洗衣机。”
“Ok Google,让洗衣机停止运行。”
当您暂停 / 恢复洗衣机时,您会注意到 Google 助理通过语音回应说出了“出了点问题”:
“抱歉,我无法访问<项目显示名>。”
如需调试此问题,您首先需要详细了解该错误,以便缩小范围并找出根本原因。
智能家居分析信息中心
智能家居分析信息中心是检查错误的好去处,其中汇总了云端执行的使用情况和健康状况指标图表:
- 使用情况指标反映了云到云集成的使用趋势,包括每日活跃用户数和对履行的总请求数。
- 借助健康状况指标,您可以监控云到云集成中的异常情况,包括请求延迟时间、成功百分比和错误细分。
如需缩小错误原因的范围,请按以下步骤操作以访问项目信息中心。
- 在开发者控制台中,前往“项目”页面。
- 选择你的智能家居项目。
- 点击左侧菜单中的分析标签页。

- 这会将您引导至 Google Cloud 上项目的仪表板列表。选择 Google Home Analytics - Cloud Integration 信息中心。

- 向下滚动到 Cloud Fulfillment Errors - Status Breakdown 图表,查看所选时间范围内的错误代码。

PARTNER_RESPONSE_MISSING_DEVICE 错误代码会提示根本原因。接下来,根据错误代码检索事件日志,以了解更多详情。
访问事件日志
如需详细了解错误,请使用 Cloud Logging 访问云到云集成的事件日志。
在 Google Cloud Platform 中打开导航菜单,然后在运维下,依次选择日志记录 > 日志浏览器,以访问项目的事件日志。或者,您也可以在搜索框中搜索日志浏览器。
在搜索所有字段输入字段中,输入查询 PARTNER_RESPONSE_MISSING_DEVICE,然后点击运行查询。与查询匹配的日志会显示在结果部分中。

错误日志显示了智能家居事件,其中包含的错误详细信息表明:
- 用户采取的操作是“继续洗衣机”(
actionType:“STARTSTOP_UNPAUSE”),这与最近失败的语音指令相对应。 - 关联的调试消息为“
JSON response does not include device.”
根据调试消息,您应检查洗衣机应用为何未在 EXECUTE 响应中包含正确的设备。
确定错误的根本原因
在 functions/index.js 中,找到 EXECUTE 处理程序(位于 onExecute 数组中),该处理程序会返回每个命令的状态以及新的设备状态。将设备 ID 插入 EXECUTE 响应取决于 updateDevice 函数的解析:
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)));
}
}
}
进一步检查 updateDevice 函数如何处理洗衣机上的暂停 / 恢复操作,您会发现要匹配的暂停 / 恢复命令字符串不正确:
index.js
const updateDevice = async (execution, deviceId) => {
const {params, command} = execution;
let state; let ref;
switch (command) {
...
case 'action.devices.commands.PauseUnpausePause':
const data = await queryDevice(deviceId);
state = (data.isPaused === false && data.isRunning === false)
? {isRunning: false, isPaused: false}
: {isRunning: !params.pause, isPaused: params.pause};
ref = getFirebaseRef().child(deviceId).child('StartStop');
break;
}
return ref.update(state)
.then(() => state);
};
修正错误
既然您已确定错误的根本原因,现在可以更正暂停 / 恢复命令的字符串:
index.js
const updateDevice = async (execution, deviceId) => {
const {params, command} = execution;
let state; let ref;
switch (command) {
...
case 'action.devices.commands.PauseUnpause':
const data = await queryDevice(deviceId);
state = (data.isPaused === false && data.isRunning === false)
? {isRunning: false, isPaused: false}
: {isRunning: !params.pause, isPaused: params.pause};
ref = getFirebaseRef().child(deviceId).child('StartStop');
break;
}
return ref.update(state)
.then(() => state);
};
测试修复效果
使用 Firebase CLI 部署更新后的代码:
firebase deploy --only functions
重试以下语音指令,您会发现,当您暂停 / 恢复洗衣机时,Google 助理现在可以正确响应。
“Ok Google,让洗衣机暂停运行。”
=>
“好的,正在暂停洗衣机。”
“Ok Google,让洗衣机继续运行。”
=>
“知道了,正在恢复洗衣机运行。”
您还可以通过提问来测试洗衣机的当前状态。
“Ok Google,我的洗衣机启动了吗?”
“Ok Google,我的洗衣机在运行吗?”
“Ok Google,我的洗衣机洗到哪一步了?”
4. 使用测试套件测试集成
除了手动测试之外,您还可以使用自动化的智能家居测试套件,以根据与您的集成关联的设备类型和特征来验证用例。测试套件会运行一系列测试来检测集成中的问题,并针对失败的测试用例显示信息性消息,以便您在深入研究事件日志之前快速进行调试。
运行智能家居测试套件
请按照以下说明使用测试套件测试云到云集成:
- 在网络浏览器中,打开智能家居测试套件。
- 使用右上角的按钮登录 Google。这样一来,测试套件便可直接向 Google 助理发送命令。
- 在项目 ID 字段中,输入云到云集成的项目 ID。然后,点击下一步继续。
- 在测试设置步骤中,您会看到测试套件列出了洗衣机的设备类型和特征。

- 停用测试请求同步选项,因为示例洗衣机应用没有用于添加 / 移除 / 重命名洗衣机的界面。在正式版系统中,每当用户添加 / 移除 / 重命名设备时,您都必须触发请求同步。
- 点击下一步,开始运行测试。
测试套件运行完毕后,查看测试用例的结果。您会注意到,系统捕获了两个失败的测试用例,并显示了相应的错误消息:

如需调试云到云集成失败问题,您需要先分析错误消息,找出错误的根本原因。
分析错误消息
为了帮助开发者找出根本原因,Test Suite 会针对每个失败的测试用例显示错误消息,指明失败原因。
对于上述第一个失败的测试用例,

其错误消息表明,测试套件预期从云到云集成报告的状态中获得 "isPause": true,但实际状态仅包含 "isPause": false。
此外,第二个失败的测试用例的错误消息表明,从云到云集成收到的 QUERY 响应中的状态包含 "isPause": true,这与从云到云集成报告的状态 "isPause": false 不同:

根据这两条错误消息,您应检查集成是否报告了状态 isPaused,且该状态的值是否正确。
确定错误的根本原因
打开 functions/index.js,其中包含使用状态报告将状态变更发布到 Home Graph 的 reportstate 函数。检查“报告状态”载荷,您会发现该载荷缺少 isPaused 状态,而这正是测试套件在失败的测试用例中检查的内容。
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: snapshot.online,
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,
});
...
});
修正错误
现在您已确定错误的根本原因,请通过向“报告状态”载荷添加 isPaused 状态来修订 functions/index.js:
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: snapshot.online,
on: snapshot.OnOff.on,
isPaused: snapshot.StartStop.isPaused,
isRunning: snapshot.StartStop.isRunning,
currentRunCycle: [{
currentCycle: 'rinse',
nextCycle: 'spin',
lang: 'en',
}],
currentTotalRemainingTime: 1212,
currentCycleRemainingTime: 301,
},
},
},
},
};
...
});
测试修复效果
使用 Firebase CLI 部署更新后的代码:
$ firebase deploy --only functions
重新运行智能家居测试套件,您会发现所有测试用例都已通过。

5. 恭喜

恭喜!您已成功学习如何使用智能家居测试套件和 GCP 指标与日志记录来排查云到云集成问题。
了解详情
在此 Codelab 的基础上,尝试做以下练习并浏览其他资源:
- 向您的设备添加更多支持的特征,并使用测试套件对其进行测试。
- 创建信息中心、设置提醒,并以编程方式访问指标数据,以获取有关集成情况的实用使用情况指标。
- 探索智能家居的本地执行方式。
- 如需进一步探索,请查看我们的 GitHub 示例。
您还可以详细了解如何测试和提交集成以供审核,包括用于向用户发布集成的认证流程。