调试智能家居

1. 准备工作

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

a4657871181b5ad2.gif

了解云到云集成的调试工具是构建与 Google 助理的生产质量集成的重要一步。为了便于轻松监控和调试,Google Cloud Platform (GCP) 指标日志记录以及智能家居测试套件可帮助您识别和解决集成问题。

前提条件

构建内容

在此 Codelab 中,您将部署一个包含 2 个缺陷的云到云集成并将其关联到 Google 助理,然后通过智能家居测试套件和 Google Cloud Platform (GCP) 指标和日志记录调试集成的缺陷。

学习内容

  • 如何使用 GCP 指标和日志记录来识别和解决生产问题
  • 如何使用智能家居测试套件来识别功能和 API 问题

所需条件

2. 运行有缺陷的应用

获取源代码

点击以下链接,将此 Codelab 的示例下载到您的开发机器上:

...或者,您也可以通过命令行克隆 GitHub 代码库:

$ git clone https://github.com/google-home/smarthome-debug.git

项目简介

洗衣机应用包含以下子目录:

连接到 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 界面上,点击Refreshae8d3b25777a5e30.png按钮,以使用请求同步功能通过有缺陷的洗衣机应用中的最新设备元数据更新 HomeGraph。

6f2b1344179977cf.png

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

e357de6a7faff925.png

3. 测试集成

部署项目后,测试集成是否可以控制洗衣机。

测试洗衣机

如果您通过手机尝试下达以下任意一条语音指令,请检查值是否发生变化:

“Hey Google,启动洗衣机。”

“Hey Google,运行洗衣机。”

“Hey Google,让洗衣机暂停运行。”

“Hey Google,让洗衣机继续运行。”

“Hey Google,让洗衣机停止运行。”

您会注意到,当您暂停 / 继续运行洗衣机时,Google 助理会通过语音回复,指出出了问题:

“抱歉,我无法访问 <project display name>。”

如需调试此问题,您首先需要了解有关错误的更多信息,以便缩小范围并找出根本原因。

Smarthome Analytics 信息中心

检查错误的好去处是 Smarthome Analytics 信息中心,该信息中心汇总了云执行方式的 使用情况和运行状况指标 图表:

  • 使用情况 指标反映了云到云集成的使用趋势,包括每日活跃用户数和对执行方式的总请求数。
  • 运行状况 指标可帮助您监控云到云集成中异常情况的发生,涵盖请求延迟时间、成功率和错误明细。

如需缩小错误原因的范围,请按照以下步骤访问项目信息中心。

  1. 开发者控制台中,转到“项目”页面。
  2. 选择您的智能家居项目。
  3. 点击左侧菜单中的 Analytics 标签页。

b1735bbe11a7aff8.png

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

5edd3751323176dd.png

  1. 向下滚动到 Cloud Fulfillment Errors - Status Breakdown 图表,以查看突出显示的时间范围内的错误代码。

c468743c20a11c15.png

PARTNER_RESPONSE_MISSING_DEVICE 错误代码提供了有关根本原因的提示。接下来,根据错误代码检索事件日志,以了解更多详细信息。

访问事件日志

为了详细了解错误,请使用 Cloud Logging 访问云到云集成的事件日志。

在 Google Cloud Platform 中打开导航菜单,然后在运维下,选择日志记录 > 日志浏览器,以访问项目的事件日志。或者,您也可以在搜索框中搜索 Logs Explorer

搜索所有字段 输入字段中,输入查询 PARTNER_RESPONSE_MISSING_DEVICE,然后点击运行查询 。与查询匹配的日志会显示在结果 部分中。

747cca0f1249a5a.png

错误日志显示了一个智能家居事件,其中包含错误详细信息,表明:

  • 用户执行的操作是“继续运行洗衣机”(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 助理现在会正确响应。

“Hey Google,让洗衣机暂停运行。”

=>

“好的,正在暂停洗衣机。”

“Hey Google,让洗衣机继续运行。”

=>

“知道了,正在继续运行洗衣机。”

您还可以通过提问来测试洗衣机的当前状态。

“Hey Google,我的洗衣机启动了吗?”

“Ok Google,我的洗衣机在运行吗?”

“Hey Google,我的洗衣机洗到哪一步了?”

4. 使用测试套件测试集成

除了手动测试之外,您还可以使用自动化的智能家居测试套件,以根据与集成关联的设备类型和特征来验证用例。测试套件会运行一系列测试来检测集成中的问题,并针对失败的测试用例显示信息性消息,以便您在深入了解事件日志之前加快调试速度。

运行智能家居测试套件

按照以下说明使用测试套件测试云到云集成:

  1. 在网络浏览器中,打开智能家居测试套件
  2. 使用右上角的按钮登录 Google。这样,测试套件就可以直接向 Google 助理发送指令。
  3. Project ID 字段中,输入云到云集成的项目 ID。然后点击 NEXT 继续。
  4. Test Settings 步骤中,您会看到测试套件列出洗衣机的设备类型和特征。

78ed6a1ebdb581bf.png

  1. 停用 Test Request Sync 选项,因为示例洗衣机应用没有用于添加 / 移除 / 重命名洗衣机的界面。在生产系统中,每当用户添加 / 移除 / 重命名设备时,您都必须触发请求同步
  2. 点击 NEXT 开始运行测试。

测试套件运行完毕后,查看测试用例的结果。您会注意到,有两个失败的测试用例被捕获,并显示了相应的错误消息:

5838d10631c98ed2.png

如需调试云到云集成以解决失败问题,您需要先分析错误消息,找出错误的根本原因。

分析错误消息

为了帮助开发者找出根本原因,测试套件会针对每个失败的测试用例显示错误消息,指明失败的原因。

对于上面的第一个失败的测试用例,

99e4e5d06965a8a7.png

其错误消息表明,测试套件预计从云到云集成报告的状态中包含 "isPause": true,但实际状态仅包含 "isPause": false

此外,第二个失败的测试用例的错误消息表明,云到云集成中的 QUERY 响应中的状态包含 "isPause": true,这与云到云集成报告的状态中的 "isPause": false 不同:

fdb5124102e3a37.png

根据这两条错误消息,您应检查集成是否报告了具有正确值的状态 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

重新运行智能家居测试套件,您会发现所有测试用例都已通过。

148837f85d377dd6.png

5. 恭喜

17d485868a6771bc.png

恭喜!您已成功学习如何使用智能家居测试套件和 GCP 指标和日志记录来排查云到云集成问题。

了解详情

在此 Codelab 的基础上,尝试做以下练习并浏览其他资源:

您还可以详细了解如何测试和提交集成以供审核,包括用于向用户发布集成的认证流程。