跳转到内容

Google Home

Google Home 桥走的是 cloud-to-cloud:手机上点一下开灯,链路是 手机 → Google 服务器 → 你家的公网端点 → rha → 设备。全程过公网,与局域网内直连的 HomeKit 桥是两条独立的路,可以并存。

与 HomeKit 桥一样默认编进二进制,但编进去不等于跑起来 —— 要不要监听端口全看 bridges.toml 里有没有一条 enabled 的 [[bridge]]。

Matter 是本地的、不过云,听上去更好,但 Google 官方要求:把 Matter 设备加进 Google Home 之前,家里的无线网络上必须先有一台 Google 自家的中枢 —— Nest 音箱、 Nest Hub 显示屏、Google TV Streamer 或 Nest Wifi Pro。别家的中枢(比如 HomePod mini) 对 Google 的 fabric 无效。

没有这类硬件时 Matter 连「添加设备」都点不下去,而 cloud-to-cloud 明确覆盖无硬件的 情况。家里有 Google 音箱的话,Matter 才值得重新考虑。

[[bridge]]
name = "google"
type = "google"
export = [
"plug_bedroom.switch_s2_on_p1",
"sensor_living.temperature",
"sensor_living.humidity",
]
api_token = "${RHA_API_TOKEN}"
client_secret = "${RHA_GOOGLE_CLIENT_SECRET}"

name / export / exclude / enabled 是所有 bridge 共有的字段,说明在 bridges.toml;本页只讲 type = "google" 的私有参数。

绑定 Google 账号还要在 Google 那边建一个集成、填三条 URL,并把端点经隧道暴露到公网。 完整步骤见仓库里的 docs/google-home-setup.md。

api_token 是你在授权页上手动粘贴的口令(直接复用 [api].token);client_secret 是要填进 Google 控制台的那一个。

它们不许相同,rha check 会当场拦下来。理由不是洁癖:混用等于把 rha 的 API 令牌交给 Google 的控制台保管。

默认 127.0.0.1:8421,紧邻 API 的 8420,但是两个独立的监听。

这是刻意的。这个端点要经隧道挂到公网上,如果和内核 API 共用端口,隧道那边的路径规则 写错一条就等于把整个 API 暴露出去。分开之后这件事在物理上做不到 —— API 根本不在这个 端口上。

隧道只需要放行三条路径:

/oauth/authorize 授权页
/oauth/token 换令牌
/fulfillment Google 的请求入口
语义类 Google 侧
power(瞬时功率) 没有对应物 —— Google 的传感器清单是封闭的,不含电功率
weight(体重) 没有对应物(HomeKit 也没有)
button(按钮) Google 没有第三方无状态按钮这个概念

导出它们不会静默消失:rha check 会当场点名说「这几个出不去」,好过运行时发现少了东西。

另外 swing(摆头)与 lock(童锁)在 Google 里没有标准语义,会显示成两个自定义 命名开关,而不是专门的控件。

不配的话也能用,只是 App 里的状态要下拉刷新才更新。想要实时,补上:

project_id = "你的-google-cloud-项目-id"
service_account_file = "/etc/rha/google-sa.json"

这两个必须成对出现,只配一个 rha check 会拦。只配 project_id 会让 rha 向 Google 声明「我会主动报状态」却永远报不出去 —— 那是最难查的一类故障。

字段类型默认说明
api_token*string—

绑定 Google 账号时, 授权页上要输入的口令。

rha 没有用户体系, 这里直接复用 [api].token —— 不为一次性的账号绑定 发明第二套身份。至少 16 个字符: 它是公网授权页上唯一的一道门。

client_idstringrha

账号绑定用的 client id, 要与 Google Home Developer Console 里填的一致。

不是秘密, 只是个标识, 所以有默认值。

client_secret*string—

账号绑定用的 client secret, 要与 Google 控制台里填的一致。

必须与 GoogleParams::api_token 不同: 这一个要填进 Google 的控制台, 而 api_token 是你自己在授权页上敲的。混用等于把 rha 的 API 令牌交给 Google 的控制台保管。

生成方式与 [api].token 一样, 例如 openssl rand -hex 16。

listenstring127.0.0.1:8421

本桥的监听地址。默认 127.0.0.1:8421。

不与 [api].listen 共用端口: 这个端点要经 Cloudflare Tunnel 暴露给公网, 共用端口意味着"隧道路径规则写错一条"就等于把整个内核 API 暴露出去。独立端口 让这件事在物理上不可能发生。

project_idstring可省略

Google 云项目 id, 主动上报状态时用。不填则只有下行控制, App 里的状态要靠 下拉刷新。

service_account_filestring可省略

Google 服务账号的 JSON 密钥文件路径, 与 project_id 一同使用。

speedarray可省略

字符串档位的顺序。

Google 的 FanSpeed 需要知道档位顺序, 而实体自带的取值域是 Vec<i64>, 索引不了字符串。空调伴侣 lumi.acpartner.mcn02 的 fan_level 真机回的是 "small_fan"/"medium_fan"/"large_fan", 就是这种情况。

与 HomeKit 桥的 steps 各配一份, 不共享。 语义上档位顺序是设备的客观 事实、更该放 devices.toml 里两边共用, 但那要改 HomeKit 桥已经在真机上 跑通的读取路径。代价是同一件事配两遍, 且两边写不一致不会有任何报错 —— 这是明知的取舍。

字符串档位的顺序。Google 的风速控件需要知道哪一档更高,而实体自带的取值域是整数列表, 索引不了字符串 —— 空调伴侣 lumi.acpartner.mcn02 的 fan_level 真机回的是 "small_fan" / "medium_fan" / "large_fan",就是这种情况。

整数档位不用配这个:有取值域就够了(枚举域产出命名档位,区间域产出百分比滑条)。

字段类型默认说明
entity*string—

实体 id, 形如 设备名.能力名。必须同时列进 export。

steps*array—

从最低档到最高档的设备原值。至少两项。

引用的实体必须同时列进 export,否则是加载期错误 —— 配了不生效是静默缺口, 必须当场报出来。