xiaodu_bridge 是一个 Home Assistant 自定义集成。它把 HA 里已经接好的设备重新组织成 DuerOS 语义设备,再交给小度音箱和小度 App 发现、查询和控制。商店里的名字是 xiaodu bridge,集成 domain 是 xiaodu_bridge。
它不是把 HA 实体一对一转成小度设备,而是有一个桥接层:一台浴霸可以把照明、取暖、换气等多个 HA 实体聚合成一台浴霸;一个房间也能从 HA 区域同步成小度房间分组。小度发来的控制请求先进入这个桥接层,再由它调用 HA 的实体服务。
整体链路是:
flowchart TB
subgraph home["家里"]
direction TB
devices["米家 / Zigbee / 蓝牙 / Matter"]
ha["Home Assistant<br/>实体 + 区域 + 能力"]
bridge["xiaodu bridge<br/>DuerOS 语义设备模型"]
entry["公网入口<br/>域名 / DDNS / NGINX"]
end
cloud["小度云端"]
speaker["小度音箱"]
app["小度 App"]
devices -->|"标准化实体"| ha
ha -->|"选中设备"| bridge
cloud -->|"OAuth / 控制请求"| entry
entry --> bridge
bridge -->|"发现 / 控制 / 查询"| ha
bridge -->|"Change Report"| cloud
cloud --> speaker
cloud --> app
整套配置从 HA 侧往小度侧推,一次走完大致是:
flowchart TD
a["设备接进 HA<br/>改名字 / 分区域"]
b["安装 xiaodu bridge<br/>HACS 或手动"]
c["配置公网 HTTPS 入口<br/>DDNS + 证书 + 反向代理"]
d["小度后台创建智能家居技能"]
e["HA 里配置 Client / botId / Callback"]
f["选择暴露设备和能力<br/>开启 sync_areas"]
g["小度发现设备<br/>模拟测试 + 语音测试"]
a --> b --> c --> d --> e --> f --> g
仓库地址:https://github.com/Jackroyal/xiaodu-bridge
准备设备
装桥接之前,先把设备名字和房间理好。
小度侧的设备名就是 HA 实体名,房间就是 HA 区域。switch.switch_1 这种名字说不出来,小度也就没法控制了。改名字只做两件事:
1. 名字改成适合说话的:客厅吸顶灯、卧室空调、书房插座。
2. 房间分对:客厅就是客厅,卧室就是卧室。
改名字最省事的位置是源头:小米的设备名和房间从米家 App 直接同步到 HA,HA 再同步给小度,一路下来不用重复修改,源头设置好后续链路可以自动同步。
米家、蓝牙、美的空调 等设备都有各自的接入方式,Xiaomi Home、Sonoff、Midea Smart Home 这些集成我都在用,大家根据各自设备按需选择自己对应的集成,善用大模型或搜索。
安装集成
要求 Home Assistant 2025.1.0 或更高版本。本文按 xiaodu bridge v0.9.17 写。
HACS 安装(推荐)
xiaodu bridge 已经进了 HACS 默认商店,不用再加自定义仓库:
- HACS → Integrations,搜索 xiaodu bridge,下载。
- 重启 Home Assistant。
HACS 下载只是把文件装到位。重启后还要去 设置 → 设备与服务 → 添加集成,搜 xiaodu bridge 添加一次——填 OAuth 凭证、botId、公网地址就在这一步。只下载不添加,集成不会生效。
手动安装
不想用 HACS 就手动复制:
git clone https://github.com/Jackroyal/xiaodu-bridge.git
cp -R xiaodu-bridge/custom_components/xiaodu_bridge /config/custom_components/
复制完检查路径,别多套一层:
正确:/config/custom_components/xiaodu_bridge/manifest.json
错误:/config/custom_components/xiaodu_bridge/xiaodu_bridge/manifest.json
确认没套错后重启:
ha core restart
手动和 HACS 两条路到这里都只是「文件装好了」,最后一步是一样的:去 设置 → 设备与服务 → 添加集成里搜 xiaodu bridge 添加。
添加完成后,集成列表里就能看到它:

点进详情页,会看到版本号、一个「小度中枢」设备,以及右上角的齿轮(配置)和三个点(菜单)按钮(截图停在 0.9.13,之后的版本界面没变):

配置公网访问
正式接入时,小度云端会回调 xiaodu bridge 提供的三个 HTTPS 接口(必须按这个填写,写死的path):
/api/xiaodu/oauth/authorize
/api/xiaodu/oauth/token
/api/xiaodu/service
所以纯内网地址完成不了正式接入,小度云端必须能从外面访问到 HA 的这几个路径。推荐结构:
小度云端
→ 公网域名
→ 路由器端口转发
→ HAOS 反向代理
→ HA Core 8123
→ xiaodu bridge
我家里是电信光纤,有公网 IPv4,主路由是华硕路由器。华硕自带 DDNS,但它内置的服务商里只有花生壳这类要实名的,我常用的 cloudflare / dnspod 都不在里面。
所以我在局域网的软路由上装了 iStoreOS,用它来做域名解析更新:软路由是长期开机的,在上面跑一个 ddns 插件,公网 IP 一变就调 cloudflare / dnspod 的 API 把 A 记录改掉。华硕路由器该干嘛干嘛,DDNS 这件事交给软路由,和 HAOS 在哪台机器上没关系。
1. 确认真的有公网 IPv4
路由器 WAN IP 和手机流量看到的出口 IP 一致才算数。WAN IP 是 100.x.x.x、10.x.x.x、172.16.x.x、192.168.x.x 这些,就是运营商套了一层,说明你没有公网ip,别折腾端口转发了。
2. 域名和 DDNS
先准备一个域名,比如 ha.example.com,在你使用的域名解析后台(cloudflare/dnspod/aliyun之类的)加一条 A 记录指向公网 IP。IP 会变就配 DDNS,公网 IP 一变,域名跟着变。
我用的是 ddns-go。在 iStoreOS 的应用商店里搜「ddns-go」装上,装完它会起一个 Web 配置页,浏览器打开 软路由IP:9876 就能看到面板,填完配置它会以服务形式常驻,公网 IP 一变就自动更新解析。
面板上要填的就几项:
| 配置项 | 填什么 |
|---|---|
DNS服务商 |
顶部单选,支持阿里云 / DnsPod / Cloudflare / 华为云 等二十来家 |
Token |
对应服务商的 API 凭据(截图里 Cloudflare 就一个 Token 输入框,面板上还带生成令牌的指引链接) |
TTL |
域名解析的缓存时间,默认「自动」即可;测试阶段可以设短一点,便于改动快速生效 |
域名 |
要更新的那条记录,比如 ha.example.com |
IP 获取方式 |
默认「通过接口获取」就行——软路由自己不持有公网 IP 时,靠本地网卡读不到真实出口地址,让它去外部接口查更准 |

配完在面板上点「测试」或等一个更新周期,然后在电脑上用 nslookup ha.example.com 或 dig 看一眼解析结果对不对。DNS 记录用“仅 DNS”模式。
平常用多个服务商的话,面板顶部有「配置切换」,可以建多套配置(比如一套 cloudflare、一套 dnspod),点「添加」新建、切换下拉选择,互不影响。 大致的原理,其实就是起个脚本监听ip变化,如果发生变化则调用cloudflare或者dnspod等的api接口更新一下域名对应的ip,变更肯定会有一定延迟,但够用了。
这里的 API Token 后面配证书还要用——HAOS 的 Let’s Encrypt add-on 走 DNS 校验,连的就是同一个 provider。
3. 端口转发
家宽对 80 和 443 的入站管控挺常见,可以用 8443 这种非标端口:
外部协议:TCP
外部端口:8443
内部目标:HAOS 主机 IP,例如 192.168.1.10
内部端口:443
里面的 443 给 HAOS 反向代理监听。HA 的 8123 端口不要直接暴露,公网统一走 HTTPS,由反向代理转 8123。
为了安全起见不建议使用DMZ开放过多内容,使用端口转发只开放一个端口,相对更安全。
华硕路由器自身远程控制用的是8443(使用华硕的子域名,我要使用自定义域名,所以不复用8443),所以我使用的是8663端口。
4. 证书和反向代理
HAOS 可以直接用 Let’s Encrypt 和 NGINX SSL proxy 这两个 add-on。跑 Docker / Core 或其他安装方式的,这两个 add-on 用不了,需要在宿主机或容器旁边准备等价方案(Caddy、NGINX 或带 DNS 模块的 Caddy)。
HAOS 上这两个 add-on 的证书走 DNS 校验,不依赖 80 端口,证书目录和文件名默认就是配套的,装完不用手动挪证书。
Cloudflare DNS 的例子:
challenge: dns
dns:
provider: dns-cloudflare
cloudflare_api_token: <你的Cloudflare API Token>
domains:
- ha.example.com
email: <你的邮箱>
NGINX SSL proxy 只需要配域名和其他选项:
domain: ha.example.com
hsts: max-age=31536000; includeSubDomains
client_max_body_size_megabytes: 1
cloudflare: false
反向代理只放行小度需要的那三个路径(前面列过),其他公网请求返回 404。
别为了省事把整个 HA 管理页面开放到公网。
然后到 HA 的 设置 → 系统 → 网络,外部地址填:
https://ha.example.com:8443
外网请求返回 400、日志里出现 forwarded 或 trusted proxy 相关内容,多半是反向代理网段没进 trusted_proxies。把 NGINX 所在网段加进去,并开启 use_x_forwarded_for。

在小度后台建技能
登录小度开发者平台,创建智能家居技能。技能的「配置服务」里要填的东西,来自两个地方:
小度后台基础信息页:
botId 技能 ID,后面要填回 HA 集成里
HA 集成确认页给出的三个地址(这里用它们):
授权地址 Authorize,HA 公网地址 + /api/xiaodu/oauth/authorize
Token地址 HA 公网地址 + /api/xiaodu/oauth/token
WebService HA 公网地址 + /api/xiaodu/service
自己定义、两边配一致:
Client_Id
ClientSecret
假设公网地址是 https://ha.example.com:8443,三个地址就是把上面的路径拼在它后面,比如 https://ha.example.com:8443/api/xiaodu/oauth/authorize。
后台「配置服务」页填起来就长这样(授权地址 / Client_Id / 回调地址 / Token 地址 / ClientSecret / WebService):

授权和设备发现的过程是:
sequenceDiagram
autonumber
participant U as 用户 / 浏览器
participant D as 小度云端
participant X as 公网入口 / xiaodu bridge
participant H as Home Assistant
U->>D: 开始绑定账号
D->>U: 打开 Authorize URL
U->>X: 访问授权页并同意
X-->>D: 返回到小度 Callback
D->>X: 请求 Token URL
X-->>D: 下发私有 Access / Refresh Token
D->>X: 调用 WebService 发现设备
X->>H: 读取已选实体、区域和能力
H-->>X: 返回实体状态
X-->>D: 返回 DuerOS 语义设备
D-->>U: 展示可控制设备
两个容易搞混的点:
1. Client_Id 和 ClientSecret 是自己定义的,不是百度分配的,两边配一致就行。
Secret 用长随机串,别用 123456 这种。
2. 回调地址不是你的 HA 地址,是小度平台生成的那个,填回 HA 集成里时要原样照抄。
填写 OAuth 配置
重启 HA 后打开:
设置 → 设备与服务 → 添加集成 → xiaodu bridge
按下面填(界面是中文标签,括号里是它的含义):
| 界面字段 | 填什么 | 示例 |
|---|---|---|
Client_Id |
自定义客户端 ID | dueros_xxx |
ClientSecret |
自定义随机密钥 | 一段长随机串 |
小度技能ID(botId) |
小度后台技能 ID | 12345678 |
回调地址 |
小度平台生成的地址,不可修改 | https://xiaodu.baidu.com/... |
公网访问地址(HTTPS) |
HA 公网基础地址 | https://ha.example.com:8443 |
保存后确认页会把授权地址、Token地址、WebService 三个地址直接列出来,照着填到小度后台就行,不用自己拼。Client_Id / ClientSecret 两边保持一致即可——它们是你自己定义的,不是百度分配的。
回调地址不用操心调试环境:集成自动兼容小度的正式环境(xiaodu.baidu.com)与调试环境(xiaodu-dbp.baidu.com),后台只用填平台生成的那一个。
填错了想改,打开集成条目右上角 ⋮ →「重新配置」(OAuth 配置)就能重填,不用删掉集成。

OAuth token 这块集成自己管:Access Token 有效期 7 天,Refresh Token 30 天,到期用 refresh_token 续。这个 token 是桥接层自己的私有不透明串,只能打小度桥接的接口,碰不到 HA 的 API。
选择要暴露给小度的设备
添加成功后,打开集成条目 →「配置」,进入「小度中枢」页:

注意:从 v0.9.15 起,设备暴露改成按需选择。全新安装、或者从没保存过设备选项的实例,默认不会向小度发送任何设备,必须在这里选好并保存。
建议别一次全选,先拿两三台练手:
- 点「添加 / 移除设备」。
- 选择要暴露的 HA 设备(列表按「房间 · 设备名」展示,重名的实体也能分清)。

- 点进某台设备,先选「设备能力」勾选能力;需要时再进「高级配置」限制能力、隐藏实体、绑定语义角色或改小度侧的展示名。
- 保存后让小度重新发现。
已选设备可以在「已选设备」列表里逐台检查:

设备默认暴露全部可用能力,想省事可以直接用默认;想精细控制再一台台进能力编辑。控制类设备的开关能力是强制的,温湿度这种只读能力按需勾。底部那个「同步 HA 房间到小度」开关打开后,HA 的区域会同步成小度的房间分组。
暴露得越精准,后面误触发越少,不需要把 HA 里每个实体都丢给小度。
测试
按这个顺序来:
- 小度开发者后台触发设备发现。
- 看设备有没有出现在小度侧。
- 查询一个温湿度传感器。
- 打开一个灯或插座,再关掉。
- 手动动一下设备状态,看小度 App 是否同步。
- 用音箱和 App 试真实语音。
HAOS 上看日志:
ha core logs -f | grep --line-buffered "Xiaodu access"
成功的发现请求里能看到这样一段(实际是一行):
kind=dueros namespace=DuerOS.ConnectedHome.Discovery \
name=DiscoverAppliancesRequest result=DiscoverAppliancesResponse status=200
这里连请求都没有,就别急着改 HA 配置,先查域名、端口转发、证书和反向代理。
语音可以试这些:
小度小度,打开客厅灯。
小度小度,把卧室空调调到 26 度。
小度小度,客厅温度是多少?
小度小度,明天早上八点打开书房插座。
几个值得说的特性
这几个特性单独拎出来说。
主动状态上报
可控设备状态一变,集成会主动推 Change Report 给小度,小度 App 里的状态会跟着刷新。纯只读传感器不上报,这类本来也没有“被控制”的状态可推。小度云端偶尔会拒绝一次(开机那波最常见),集成会在 60 秒窗口后补发一次,不会无限重试。
房间分组
HA 区域同步成小度房间分组后,“打开客厅的灯”这类指令小度能自己圈范围,不用每台设备都指名道姓。前提还是第一步:房间得分对。
定时开关
支持小度侧的 timingTurnOn 和 timingTurnOff。定时信息存在 HA Storage 里,HA 重启后任务仍然保留。
语义设备模型
这是桥接层最核心的设计。它不是把 HA 实体一对一递给小度,而是先在桥接层把设备组装成 DuerOS 语义设备:浴霸就是一台浴霸,照明取暖换气都在它身上;洗衣机、晾衣杆、扫地机同理。小度协议定义了六十多种设备类型,这个集成实现了常用的十几种:灯、开关、插座、空调、窗帘、风扇、传感器、媒体播放器,外加浴霸、晾衣杆、扫地机、洗衣机四个专用档案。
晾衣杆的语义按小度的实际模型处理:开关控制的是照明,升降走上升 / 下降动作;没有灯实体的机型回退为控制杆子本身。
常见排查
集成搜索不到
先看目录有没有多套一层,再看 manifest.json 是否存在,然后重启 HA。HACS 里搜不到的话,先把 HACS 更新到最新版并刷新商店列表;还是没有就改用手动安装。
HA 里正常,小度发现不到
按顺序查:
1. 小度后台 WebService 地址对不对。
2. 地址里的端口有没有少。
3. 公网能不能访问 HA。
4. 反向代理有没有放行 /api/xiaodu。
5. HA 集成里有没有选中设备。
6. HA 日志里有没有 Xiaodu access。
如果小度云端访问不到 HA,音箱和后台都会持续失败,先把公网链路查完。
授权页打不开也是同一类问题,从外面测一下入口通不通:
curl -I https://ha.example.com:8443/api/xiaodu/service
能拿到 HTTP 状态码说明入口至少通了;TLS 都失败的话,先解决证书、DNS 和端口转发。
米家设备状态不准
问题多半不在桥接层。先回 Xiaomi Home 或米家集成里看:HA 页面能不能控制,状态会不会变,实体有没有被禁用。HA 侧不稳,桥接写得再好也没办法。
控制失败但发现成功
能力没勾全,或设备类型映射不对。空调要有温度、模式、风速这些能力;窗帘要有打开、关闭能力。回集成选项里改完,再让小度重新发现。
状态不同步
先确认这台设备是可控设备,只读传感器本来就不主动上报。再手动动一下设备,看日志里有没有状态推送的记录。
最后
这套方案的核心是让 HA 当统一中间层。桥接层把 HA 设备按 DuerOS 的语义组装好交给小度,状态变化也主动往小度推。小度 App 能拿到较新的状态,浴霸这类多实体设备也能当成一台设备控制。
设备命名和房间分好,语音体验会顺很多。先暴露少量设备测试,稳定后再慢慢加。