126 lines
5.1 KiB
Markdown
126 lines
5.1 KiB
Markdown
# Open-XiaoAI x Home Assistant Assist
|
||||
|
|
|
|||
|
|
该示例用于将小爱音箱接入 Home Assistant 的对话/语音助手能力,支持文本对话与上下文会话,并提供可选的语音输入管线对接能力。
|
|||
|
|
|
|||
|
|
## 功能说明
|
|||
|
|
|
|||
|
|
- 文本对话:对接 Home Assistant `conversation.process` API,支持自然语言控制设备/查询信息
|
|||
|
|
- 实时打断:接收到新用户消息时先中断当前播报,再处理新输入,避免并发播报
|
|||
|
|
- 连续对话会话管理:默认开启连续对话;当命中结束词或语音静默超时时自动结束并重建 `conversation_id`
|
|||
|
|
- 区域上下文注入:支持客户端 IP 到 Home Assistant 区域映射,命中后在每次请求前注入区域前置提示词
|
|||
|
|
- 小爱音箱 I/O:从小爱音箱事件中提取最终识别文本(ASR),将回复通过小爱本机 TTS 播放
|
|||
|
|
- 可选音频能力(扩展点):支持接收小爱录音流 `record`,用于后续对接 Assist pipeline(STT→Intent→TTS)
|
|||
|
|
|
|||
|
|
## 使用场景
|
|||
|
|
|
|||
|
|
- 用中文/英文自然语言控制 Home Assistant:开灯、关灯、调亮度、问温度/天气、查询传感器状态
|
|||
|
|
- 把小爱音箱作为 Home Assistant 的“外置麦克风 + 扬声器”(局域网内运行)
|
|||
|
|
## 架构概览
|
|||
|
|
|
|||
|
|
- 小爱音箱 →(WebSocket 4399)→ Rust 网关(`open_xiaoai_server`)→ Python 回调
|
|||
|
|
- 文本链路(默认,低延迟):
|
|||
|
|
- 设备事件 `instruction/NewLine` → 抽取 `SpeechRecognizer.RecognizeResult` 文本
|
|||
|
|
- 调用 HA `/api/conversation/process`
|
|||
|
|
- 把返回的 `response.speech.plain.speech` 交给小爱 TTS 播报
|
|||
|
|
|
|||
|
|
## 目录结构
|
|||
|
|
|
|||
|
|
本目录包含:
|
|||
|
|
|
|||
|
|
- `hass_assistant.py`:主入口
|
|||
|
|
- `config.example.json`:配置模板
|
|||
|
|
- `requirements.txt`:Python 依赖
|
|||
|
|
- `src/`:Rust(PyO3) 扩展模块(小爱音箱 I/O 网关)
|
|||
|
|
- `hass/`:Python 实现(HA 客户端、对话编排、上下文记忆)
|
|||
|
|
- `tests/`:单元测试
|
|||
|
|
- `scripts/`:集成测试脚本
|
|||
|
|
|
|||
|
|
## 安装与运行
|
|||
|
|
|
|||
|
|
### 前置条件
|
|||
|
|
|
|||
|
|
- 你的小爱音箱已刷机并运行 Rust 客户端补丁(否则服务端收不到事件/音频流)
|
|||
|
|
- Home Assistant 已启用 `conversation`(默认配置一般已启用)并生成 Long-Lived Access Token
|
|||
|
|
- 本机具备 Python(建议 3.10+)与 Rust 工具链(用于编译 PyO3 扩展)
|
|||
|
|
- 可选:如果你希望使用 webrtcvad(更好的语音端点检测),Windows 需要安装 MSVC Build Tools
|
|||
|
|
|
|||
|
|
### 1) 准备配置
|
|||
|
|
|
|||
|
|
复制配置模板:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd examples/hass
|
|||
|
|
cp config.example.json config.json
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
编辑 `config.json`:
|
|||
|
|
|
|||
|
|
- `homeassistant.url`:HA 地址(例如 `http://192.168.1.10:8123`)
|
|||
|
|
- `homeassistant.access_token`:HA Long-Lived Access Token
|
|||
|
|
- `homeassistant.assistant_entity_id`:对话助理 ID(对应 `agent_id`,默认 `home_assistant`)
|
|||
|
|
|
|||
|
|
### 配置新增项说明
|
|||
|
|
|
|||
|
|
`xiaoai` 段新增以下关键配置:
|
|||
|
|
|
|||
|
|
- `interrupt_on_new_input`:是否在收到新消息时立即执行打断,默认 `true`
|
|||
|
|
- `interrupt_command`:打断命令,默认使用 `ubus call mibrain ai_service` 触发中断
|
|||
|
|
- `continuous_conversation_enabled`:是否开启连续会话,默认 `true`
|
|||
|
|
- `session_idle_timeout_seconds`:连续会话静默超时秒数,默认 `15`
|
|||
|
|
- `session_end_keywords`:结束词列表,默认包含 `再见` `拜拜` `滚` `退下`,按包含匹配
|
|||
|
|
- `client_ip_area_mapping`:客户端 IP 到区域名称映射,仅在命中时注入区域提示词
|
|||
|
|
|
|||
|
|
区域提示词注入内容为:
|
|||
|
|
|
|||
|
|
`当前用户对话所在区域:<区域名称>,如后续对话未明确指定区域,则默认为此区域`
|
|||
|
|
|
|||
|
|
### 2) 安装依赖
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
pip install -r requirements.txt
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3) 编译 Rust 扩展(open_xiaoai_server)
|
|||
|
|
|
|||
|
|
推荐使用 maturin:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
pip install maturin
|
|||
|
|
maturin develop --release
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4) 运行
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
python hass_assistant.py
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## API 调用示例
|
|||
|
|
|
|||
|
|
### Home Assistant conversation.process(curl)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
curl -X POST \
|
|||
|
|
-H "Authorization: Bearer YOUR_LONG_LIVED_ACCESS_TOKEN" \
|
|||
|
|
-H "Content-Type: application/json" \
|
|||
|
|
http://HOME_ASSISTANT:8123/api/conversation/process \
|
|||
|
|
-d '{"text":"打开客厅灯","language":"zh-cn","agent_id":"home_assistant"}'
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Python 调用(不连接小爱,仅验证 HA)
|
|||
|
|
|
|||
|
|
可参考 `scripts/integration_text.py`。
|
|||
|
|
## 故障排除
|
|||
|
|
|
|||
|
|
- 401/403:检查 `access_token` 是否正确、是否完整复制
|
|||
|
|
- 连接超时:检查 `homeassistant.url` 是否可达、是否被防火墙/反代阻断
|
|||
|
|
- 无语音输入:确认小爱已运行客户端补丁且能连到本机 4399 端口
|
|||
|
|
- 无语音输出:确认小爱系统 `ubus`/`mibrain` 可用(或改用 `play_url` 播放 URL)
|
|||
|
|
- 对话不连贯:确认 `state.json` 能写入(用于持久化 `conversation_id`),或删除它重置会话
|
|||
|
|
- 打断不生效:检查 `xiaoai.interrupt_command` 是否可在设备上执行,以及日志中是否出现 `xiaoai_interrupt_failed`
|
|||
|
|
- 区域提示词未注入:检查 `client_ip_area_mapping` 是否包含当前客户端 IP,并查看 `area_mapping_hit/area_mapping_miss` 日志
|
|||
|
|
## 部署说明
|
|||
|
|
|
|||
|
|
- 建议仅在局域网内部署运行,避免将 4399 暴露到公网
|
|||
|
|
- 如果 HA 与运行本示例的机器不在同一网段,确保 HA 的 URL 在设备侧可访问(尤其是播放 URL 时)
|