通过智能家居集成,Google 助理可以控制用户住宅中已连接的设备。如要构建智能家居 Action,您需要提供一个能够处理智能家居 intent 的云网络钩子端点。例如,当用户说“Ok Google,打开灯”时,Google 助理会将这条指令发给您的云执行方式,以更新设备状态。
Local Home SDK 可以增强智能家居集成。它添加了一条本地路径,能直接将智能家居 intent 传递给 Google Home 设备,从而提高可靠性并缩短处理用户指令时的延迟时间。借助此 SDK,您可以用 TypeScript 或 JavaScript 编写和部署本地执行方式应用,以识别设备并在任意一个 Google Home 智能音箱或 Google Nest 智能显示屏上执行指令。然后,您的应用使用现有的标准协议,通过局域网直接与用户的现有智能设备进行通信,以便执行指令。
前提条件
- 创建智能家居 Action 开发者指南
- 智能家居洗衣机 Codelab
- 本地执行方式开发者指南
构建内容
在此 Codelab 中,您将利用 Firebase 部署一个以前构建的智能家居集成,然后在 Actions 控制台中应用一个扫描配置,并使用 TypeScript 构建一个本地应用,用于将以 Node.js 编写的命令发送到虚拟洗衣机设备。
学习内容
- 如何在 Actions 控制台中启用和配置本地执行方式。
- 如何使用 Local Home SDK 编写本地执行方式应用。
- 如何调试在 Google Home 音箱或 Google Nest 智能显示屏上加载的本地执行方式应用。
所需条件
- 最新版本的 Google Chrome
- 安装了 Google Home 应用的 iOS 或 Android 设备
- Google Home 智能音箱或 Google Nest 智能显示屏
- Node.js 10.16 或更高版本
- Google 帐号
- Google Cloud 结算帐号
启用活动控件
在您计划与 Google 助理搭配使用的 Google 帐号中启用以下活动控件:
- 网络与应用活动记录
- 设备信息
- 语音和音频活动记录
创建 Actions 项目
- 转到 Actions on Google 开发者控制台。
- 点击 New Project,输入项目名称,然后点击 CREATE PROJECT。
选择智能家居应用
在 Actions 控制台的“Overview”屏幕中,选择 Smart home。
选择 Smart home 体验卡片,然后系统会将您转到项目控制台。
安装 Firebase CLI
借助 Firebase 命令行界面 (CLI),您可以在本地提供 Web 应用,并将您的 Web 应用部署到 Firebase Hosting。
如需安装 CLI,请从终端运行以下 npm 命令:
npm install -g firebase-tools
如需验证 CLI 是否已正确安装,请运行以下命令:
firebase --version
运行以下命令,授权您的 Google 帐号使用 Firebase CLI:
firebase login
启用 HomeGraph API
借助 HomeGraph API,您可以在用户 Home Graph 中存储并查询设备及其状态。如需使用此 API,您必须先打开 Google Cloud Console,然后启用 HomeGraph API。
在 Google Cloud Console 中,请务必选择与您的 Actions <project-id>.
相匹配的项目。然后,在 HomeGraph API 的 API 库屏幕中,点击启用。
开发环境设置完毕后,您可以部署入门级项目以验证所有设置是否已配置正确。
获取源代码
点击以下链接,将此 Codelab 的示例下载到您的开发机器上:
…或者,您也可以通过命令行克隆 GitHub 代码库:
git clone https://github.com/googlecodelabs/smarthome-local.git
项目简介
入门级项目包含以下子目录:
public
- 可控制和监控智能洗衣机的前端网络界面functions
- 为智能家居 Action 实现云执行方式的 Cloud Functions 函数local
- 框架本地执行方式应用项目,包含在index.ts
中打桩的 intent 处理程序
提供的云执行方式在 index.js
中包括以下函数:
fakeauth
- 用于帐号关联的授权端点faketoken
- 用于帐号关联的令牌端点smarthome
- 智能家居 intent 执行方式端点reportstate
- 在设备状态改变时调用 HomeGraph APIupdateDevice
- 虚拟设备用来触发报告状态的端点
关联到 Firebase
转到 app-start
目录,然后使用您的 Actions 项目设置 Firebase CLI:
cd app-start firebase use <project-id>
部署到 Firebase
转到 functions
文件夹,然后使用 npm.
安装所有必要的依赖项
cd functions npm install
依赖性安装完毕且配置好项目后,您就可以首次运行此应用了。
firebase deploy
您应该会看到以下控制台输出:
... ✔ Deploy complete! Project Console: https://console.firebase.google.cn/project/<project-id>/overview Hosting URL: https://<project-id>.firebaseapp.com
此命令会部署一个 Web 应用以及几个 Cloud Functions for Firebase。
在浏览器 (https://<project-id>.firebaseapp.com
) 中打开托管网址以查看此 Web 应用。您会看到以下界面:
此网络界面表示用于查看或修改设备状态的第三方平台。如需使用设备信息填充数据库,请点击 UPDATE。此页面不会显示任何更改,但洗衣机的当前状态会存储在数据库中。
现在,您可以通过 Actions 控制台将您部署的云服务关联到 Google 助理。
配置您的 Actions 控制台项目
在 Overview > Build your Action 下,选择 Add Action(s)。输入为智能家居 intent 提供执行方式的 Cloud Functions 函数的网址,然后点击 Save。
https://us-central1-<project-id>.cloudfunctions.net/smarthome
在 Develop > Invocation 标签页中,在 Display name 中为您的 Action 添加显示名,然后点击 Save。此名称会显示在 Google Home 应用中。
如需启用帐号关联,请在左侧导航栏中依次选择 Develop > Account linking 选项。使用以下帐号关联设置:
客户端 ID |
|
客户端密钥 |
|
授权网址 |
|
令牌网址 |
|
点击 Save 保存您的帐号关联配置,然后点击 Test 针对您的项目启用测试。
系统会将您重定向到 Simulator。将鼠标指针悬停在“Testing on Device”() 图标上,以便验证是否已针对您的项目启用测试。
关联到 Google 助理
为了测试您的智能家居 Action,您需要将项目与 Google 帐号相关联。这样一来,您就可以使用登录同一帐号的 Google 助理界面和 Google Home 应用来进行测试。
- 在手机上打开 Google 助理设置。请注意,您登录的帐号应该与控制台所用的帐号相同。
- 依次转到 Google 助理 > 设置 > 家居控制(位于“Google 助理”下方)。
- 点击右下角的加号 (+) 图标。
- 您应该会看到带有 [test] 前缀及您设置的显示名的测试应用。
- 选择此项目。然后,Google 助理会通过您的服务进行身份验证并发送
SYNC
请求,以要求您的服务提供用户设备列表。
打开 Google Home 应用,然后验证您能否看到相应洗衣机设备。
验证您是否可以在 Google Home 应用中通过语音指令控制洗衣机。您还应该会在云执行方式的前端网络界面中看到设备状态更改情况。
现在,可以开始为您的 Action 添加本地执行方式了。
为了支持本地执行方式,您需要将一个新的设备专用字段(名为 otherDeviceIds
)添加到包含设备唯一本地标识符的云 SYNC
响应中。此字段还表示在本地控制该设备的功能。
将 otherDeviceIds
字段添加到 SYNC
响应中,如以下代码段所示:
functions/index.js
app.onSync((body) => {
return {
requestId: body.requestId,
payload: {
agentUserId: '123',
devices: [{
id: 'washer',
type: 'action.devices.types.WASHER',
traits: [ ... ],
name: { ... },
deviceInfo: { ... },
willReportState: true,
attributes: {
pausable: true,
},
otherDeviceIds: [{
deviceId: 'deviceid123',
}],
}],
},
};
});
将更新后的项目部署到 Firebase:
firebase deploy --only functions
部署完成后,转到网络界面,然后点击工具栏中的 Refresh 按钮。这会触发请求同步操作,以便 Google 助理接收更新后的 SYNC
响应数据。
在本部分中,您会将本地执行方式所必需的配置选项添加到您的智能家居 Action。在开发过程中,您可以将本地执行方式应用发布到 Firebase Hosting,Google Home 设备可以从这里访问并下载该应用。
在 Actions 控制台中,依次选择 Develop > Actions,然后找到 Configure local home SDK 部分。在测试网址字段中输入以下网址,插入您的项目 ID,然后点击 Save:
https://<project-id>.firebaseapp.com/local-home/index.html
接下来,需要定义 Google Home 设备应如何发现本地智能设备。Local Home 平台支持多种设备发现协议,包括 mDNS、UPnP 和 UDP 广播。您将使用 UDP 广播来发现智能洗衣机。
点击 Device scan configuration 下的 New scan config,添加新的扫描配置。选择 UDP 作为协议,并填写以下属性:
字段 | 说明 | 建议值 |
Broadcast address | UDP 广播地址 |
|
Broadcast port | Google Home 用于发送 UDP 广播的端口 |
|
Listen port | Google Home 用于监听响应的端口 |
|
Discovery packet | UDP 广播数据载荷 |
|
最后,点击窗口顶部的 Save 以发布所作更改。
您将借助 Local Home SDK typings 软件包,使用 TypeScript 开发本地执行方式应用。查看入门级项目中提供的框架:
local/index.ts
/// <reference types="@google/local-home-sdk" />
import App = smarthome.App;
import Constants = smarthome.Constants;
import DataFlow = smarthome.DataFlow;
import Execute = smarthome.Execute;
import Intents = smarthome.Intents;
import IntentFlow = smarthome.IntentFlow;
...
class LocalExecutionApp {
constructor(private readonly app: App) { }
identifyHandler(request: IntentFlow.IdentifyRequest):
Promise<IntentFlow.IdentifyResponse> {
// TODO: Implement device identification
}
executeHandler(request: IntentFlow.ExecuteRequest):
Promise<IntentFlow.ExecuteResponse> {
// TODO: Implement local fulfillment
}
...
}
const localHomeSdk = new App('1.0.0');
const localApp = new LocalExecutionApp(localHomeSdk);
localHomeSdk
.onIdentify(localApp.identifyHandler.bind(localApp))
.onExecute(localApp.executeHandler.bind(localApp))
.listen()
.then(() => console.log('Ready'))
.catch((e: Error) => console.error(e));
本地执行方式的核心组件是 smarthome.App
类。入门级项目附加针对 IDENTIFY
和 EXECUTE
两个 intent 的处理程序,然后调用 listen()
方法来通知 Local Home SDK 此应用已准备就绪。
添加 IDENTIFY 处理程序
当 Google Home 设备根据 Actions 控制台提供的扫描配置发现本地网络中有未经验证的设备时,Local Home SDK 就会触发 IDENTIFY
处理程序。
与此同时,当 Google 发现匹配的设备时,此平台会使用生成的扫描数据调用 identifyHandler
。在您的应用中,使用 UDP 广播执行扫描,而提供给 IDENTIFY
处理程序的扫描数据包括本地设备发送的响应载荷。
处理程序会返回一个包含本地设备唯一标识符的 IdentifyResponse
实例。将以下代码添加到您的 identifyHandler
方法中,以处理来自本地设备的 UDP 响应并确定合适的本地设备 ID:
local/index .ts
identifyHandler(request: IntentFlow.IdentifyRequest):
Promise<IntentFlow.IdentifyResponse> {
console.log("IDENTIFY intent: " + JSON.stringify(request, null, 2));
const scanData = request.inputs[0].payload.device.udpScanData;
if (!scanData) {
const err = new IntentFlow.HandlerError(request.requestId,
'invalid_request', 'Invalid scan data');
return Promise.reject(err);
}
// In this codelab, the scan data contains only local device id.
const localDeviceId = Buffer.from(scanData.data, 'hex');
const response: IntentFlow.IdentifyResponse = {
intent: Intents.IDENTIFY,
requestId: request.requestId,
payload: {
device: {
id: 'washer',
verificationId: localDeviceId.toString(),
}
}
};
console.log("IDENTIFY response: " + JSON.stringify(response, null, 2));
return Promise.resolve(response);
}
请注意,verificationId
字段必须与您的 SYNC
响应中的某个 otherDeviceIds
值相匹配,这会在用户的 Home Graph 中将相应设备标记为可用于本地执行方式。Google 找到匹配项之后,相应设备就会被视为已通过验证,并可随时用于本地执行方式。
添加 EXECUTE 处理程序
当支持本地执行方式的设备收到命令时,Local Home SDK 会触发您的 EXECUTE
处理程序。本地 intent 的内容等同于发送到您的云执行方式的 EXECUTE
intent,因此本地处理 intent 的逻辑与您在云中的处理方式相似。
该应用可使用 TCP/UDP 套接字或 HTTP(S) 请求与本地设备通信。在本 Codelab 中,HTTP 充当用于控制虚拟设备的协议。端口号在 index.ts
中被定义为 SERVER_PORT
变量。
将以下代码添加到您的 executeHandler
方法,以处理传入的命令,并通过 HTTP 将命令发送到本地设备:
local/index.ts
executeHandler(request: IntentFlow.ExecuteRequest):
Promise<IntentFlow.ExecuteResponse> {
console.log("EXECUTE intent: " + JSON.stringify(request, null, 2));
const command = request.inputs[0].payload.commands[0];
const execution = command.execution[0];
const response = new Execute.Response.Builder()
.setRequestId(request.requestId);
const promises: Array<Promise<void>> = command.devices.map((device) => {
console.log("Handling EXECUTE intent for device: " + JSON.stringify(device));
// Convert execution params to a string for the local device
const params = execution.params as IWasherParams;
const payload = this.getDataForCommand(execution.command, params);
// Create a command to send over the local network
const radioCommand = new DataFlow.HttpRequestData();
radioCommand.requestId = request.requestId;
radioCommand.deviceId = device.id;
radioCommand.data = JSON.stringify(payload);
radioCommand.dataType = 'application/json';
radioCommand.port = SERVER_PORT;
radioCommand.method = Constants.HttpOperation.POST;
radioCommand.isSecure = false;
console.log("Sending request to the smart home device:", payload);
return this.app.getDeviceManager()
.send(radioCommand)
.then(() => {
const state = {online: true};
response.setSuccessState(device.id, Object.assign(state, params));
console.log(`Command successfully sent to ${device.id}`);
})
.catch((e: IntentFlow.HandlerError) => {
e.errorCode = e.errorCode || 'invalid_request';
response.setErrorState(device.id, e.errorCode);
console.error('An error occurred sending the command', e.errorCode);
});
});
return Promise.all(promises)
.then(() => {
return response.build();
})
.catch((e) => {
const err = new IntentFlow.HandlerError(request.requestId,
'invalid_request', e.message);
return Promise.reject(err);
});
}
编译 TypeScript 应用
转到 local/
目录并运行以下命令,以下载 TypeScript 编译器并编译应用:
cd local npm install npm run build
这会编译 index.ts
(TypeScript) 源代码,并将以下内容放入 public/local-home/
目录:
bundle.js
- 已编译的 JavaScript 输出,包含本地应用和依赖项。index.html
- 用于提供应用以在设备上进行测试的本地托管网页。
部署测试项目
将更新后的项目文件部署到 Firebase Hosting,以便您可以从 Google Home 设备访问这些文件。
firebase deploy --only hosting
现在,您可以测试本地执行方式应用与智能洗衣机之间的通信了!该 Codelab 入门级项目包括一个使用 Node.js 编写的虚拟智能洗衣机,它用于模拟一个用户可在本地控制的智能洗衣机。
配置设备
您需要配置该虚拟设备,以使用您在 Actions 控制台中为设备发现扫描配置应用的相同 UDP 参数。此外,您还需要告知虚拟设备要报告的本地设备 ID,以及当设备状态更改时用于报告状态事件的 Actions 项目 ID。
参数 | 建议值 |
deviceId |
|
discoveryPortOut |
|
discoveryPacket |
|
projectId | 您的 Actions 项目 ID |
启动设备
转到 virtual-device/
目录并运行设备脚本,以将配置参数作为实际参数进行传递:
cd virtual-device npm install npm start -- \ --deviceId=deviceid123 --projectId=<project-id> \ --discoveryPortOut=3311 --discoveryPacket=HelloLocalHomeSDK
验证设备脚本是否以预期参数运行:
(...): UDP Server listening on 3311 (...): Device listening on port 3388 (...): Report State successful
在下一部分中,您将验证 Google Home 设备是否可以通过本地网络正确扫描、识别虚拟智能洗衣机以及向其发出命令。使用 Google Chrome 开发者工具,您可以连接到 Google Home 设备、查看控制台日志,并调试 TypeScript 应用。
关联 Chrome 开发者工具
如需将调试程序关联到您的本地执行方式应用,请按照以下步骤操作:
- 确保您已将 Google Home 设备与有权访问 Actions 控制台项目的用户相关联。
- 重新启动 Google Home 设备,使其能够获取您的 HTML 的网址,以及您在 Actions 控制台中添加的扫描配置。
- 在开发机器上启动 Chrome。
- 打开新的 Chrome 标签页,然后在地址字段中输入
chrome://inspect
以启动检查器。
您应该会在页面上看到设备列表,并且您的应用网址应该会出现在您的 Google Home 设备名称下方。
启动检查器
点击应用网址下方的 Inspect,以启动 Chrome 开发者工具。选择 Console 标签页,并验证您是否可以看到您的 TypeScript 应用输出的 IDENTIFY
intent 内容。
此输出意味着您的本地执行方式应用已成功发现和标识虚拟设备。
测试本地执行方式
使用 Google Home 应用的触控功能向您的设备发送指令,或向 Google Home 设备下达语音指令,例如:
“Ok Google,启动洗衣机。”
“Ok Google,运行洗衣机。”
“Ok Google,让洗衣机停止运行。”
这会触发平台将 EXECUTE
intent 传递给您的 TypeScript 应用的操作。
验证您能否看到每个指令引起的本地智能洗衣机状态更改。
... ***** The washer is RUNNING ***** ... ***** The washer is STOPPED *****
恭喜!您使用 Local Home SDK 将本地执行方式集成到了智能家居 Action 中。
了解详情
您还可以尝试下面这些操作:
- 更改扫描配置并让其正常运行。例如,尝试使用其他的 UDP 端口或发现数据包。
- 修改虚拟智能设备代码库,以在嵌入式设备(例如 Raspberry Pi)上运行,并使用 LED 或显示屏呈现当前状态。