项目结构: - custom_components/sigmesh_gateway/ - Home Assistant 集成 - serial_reader.py - 串口读取器 - protocol_parser.py - 协议解析器 - coordinator.py - 数据协调器 - platforms/ - 传感器/开关/灯光/设备追踪实体 文档: - PRD.md - 产品需求文档 - README.md - 用户使用指南 - 可行性分析.md - 技术可行性分析 - 参数配置表.md - 配置参数记录 - 调试检查清单.md - 问题排查指南 功能特性: - 串口通信 (115200 波特率) - Bluetooth Mesh 协议解析 - 支持 200+ 设备接入 - UI 配置界面 - 多平台实体支持 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
20 KiB
20 KiB
SigMesh Gateway HACS 集成 - PRD 产品需求文档
版本号: 1.0.0 创建日期: 2026-04-15 最后更新: 2026-04-15 状态: 草稿 → 评审中
目录
1. 文档概述
1.1 文档目的
本文档定义 SigMesh Gateway HACS 集成的完整产品需求,用于:
- 指导开发人员进行参数配置和问题调试
- 作为功能实现的基准参考
- 提供测试和验证标准
- 记录设计决策和接口规范
1.2 适用对象
| 角色 | 使用场景 |
|---|---|
| 开发工程师 | 参数调整、功能开发、问题排查 |
| 测试工程师 | 编写测试用例、验证功能 |
| 运维人员 | 部署配置、故障诊断 |
| 用户 | 了解功能、配置参数 |
1.3 术语定义
| 术语 | 定义 |
|---|---|
| HACS | Home Assistant Community Store |
| SigMesh | Bluetooth SIG Mesh 协议 |
| HAOS | Home Assistant OS |
| Gateway | SigMesh 网关 (E104-BT12NSP 模块) |
| Opcode | Mesh 消息操作码 |
| Entity | Home Assistant 实体 |
| Coordinator | 数据更新协调器 |
2. 产品背景
2.1 项目目标
创建 HACS 集成项目,实现:
- 通过串口读取 SigMesh 网关数据
- 解析 Bluetooth Mesh 协议消息
- 在 Home Assistant 中创建和管理实体
- 支持最多 200 个 Mesh 设备接入
2.2 使用场景
| 场景 | 描述 |
|---|---|
| 智能家居 | 接入蓝牙 Mesh 开关、灯光、传感器 |
| 商业照明 | 大规模 Mesh 灯光控制 |
| 环境监测 | 温湿度、光照等传感器数据采集 |
2.3 硬件规格
SigMesh 网关 (E104-BT12NSP):
- 芯片:Nordic nRF52840
- 协议:Bluetooth 5.4 Mesh
- 接口:UART (USB 转 TTL)
- 串口参数:115200, 8N1
3. 需求范围
3.1 功能边界
包含的功能:
- ✅ 串口异步数据读取
- ✅ Mesh 协议解析
- ✅ 设备自动发现
- ✅ 多平台实体创建
- ✅ UI 配置界面
不包含的功能:
- ❌ Mesh 配网功能(网关已完成)
- ❌ 设备固件升级
- ❌ 网络拓扑展示
- ❌ 离线缓存
3.2 依赖关系
SigMesh Gateway 集成
├── 依赖:Home Assistant ≥ 2024.1.0
├── 依赖:HACS ≥ 1.34.0
├── 依赖:pyserial-asyncio ≥ 0.6
└── 依赖:bleak-mesh ≥ 0.2.0
4. 技术规格
4.1 串口通信规格
| 参数 | 值 | 可调范围 | 默认值 |
|---|---|---|---|
| 设备路径 | /dev/ttyUSB0 | 系统决定 | /dev/ttyUSB0 |
| 波特率 | 115200 | 9600-921600 | 115200 |
| 数据位 | 8 | 5-8 | 8 |
| 停止位 | 1 | 1, 1.5, 2 | 1 |
| 校验位 | None | None, E, O, M, S | N |
| 超时 | 0.1s | 0.01-10s | 0.1 |
| 读取间隔 | 10ms | 1-100ms | 10 |
4.2 协议规格
串口消息格式:
事件前缀:+EVENT=
行结束符:\r\n
Mesh 消息:
+EVENT=MESH,recv,<src_addr>,<dst_addr>,<opcode>,<hex_payload>\r\n
设备加入:
+EVENT=PROV,device_joined,<mac>,<element_count>\r\n
设备离开:
+EVENT=PROV,device_left,<mac>\r\n
字段定义:
| 字段 | 类型 | 长度 | 说明 |
|---|---|---|---|
| src_addr | string | 4-6 字符 | 源地址 (16 进制) |
| dst_addr | string | 4-6 字符 | 目标地址 (16 进制) |
| opcode | int | 1-4 字符 | 操作码 (16 进制) |
| hex_payload | bytes | 变长 | 数据负载 (16 进制字符串) |
| mac | string | 12 字符 | MAC 地址 |
| element_count | int | 1-2 字符 | 元素数量 |
4.3 支持的 Opcode 列表
| Opcode | 名称 | 模型 ID | 数据长度 | 解析状态 |
|---|---|---|---|---|
| 0x8201 | ONOFF_GET | 0x1000 | 0 | ✅ |
| 0x8202 | ONOFF_SET | 0x1000 | 1 | ✅ |
| 0x8203 | ONOFF_SET_UNACK | 0x1000 | 1 | ✅ |
| 0x8204 | ONOFF_STATUS | 0x1000 | 1 | ✅ |
| 0x8229 | LIGHT_LIGHTNESS_GET | 0x1300 | 0 | ✅ |
| 0x822B | LIGHT_LIGHTNESS_SET | 0x1300 | 2-3 | ✅ |
| 0x822C | LIGHT_LIGHTNESS_STATUS | 0x1300 | 2-3 | ✅ |
| 0x8231 | LIGHT_HSL_SET | 0x1307 | 6-7 | ✅ |
| 0x8232 | LIGHT_HSL_STATUS | 0x1307 | 6-7 | ✅ |
| 0x825D | LIGHT_CTL_SET | 0x130D | 4-5 | ✅ |
| 0x825E | LIGHT_CTL_STATUS | 0x130D | 4-5 | ✅ |
| 0x8200 | LIGHT_COLOR_SET | 0x130C | 8-9 | ✅ |
| 0x8201 | LIGHT_COLOR_STATUS | 0x130C | 8-9 | ✅ |
| 0x8230 | SENSOR_GET | 0x1100 | 2 | ✅ |
| 0x8231 | SENSOR_STATUS | 0x1100 | 2-6 | ✅ |
| 0x820C | BATTERY_STATUS | 0x1000 | 1-4 | ✅ |
4.4 传感器属性 ID 映射
| Property ID | 名称 | 单位 | 缩放 | 范围 |
|---|---|---|---|---|
| 0x0050 | PRESENCE_DETECTED | 布尔 | ×1 | 0/1 |
| 0x0051 | MOTION_DETECTED | 布尔 | ×1 | 0/1 |
| 0x0059 | AMBIENT_TEMPERATURE | °C | ÷100 | -2732~32767 |
| 0x005A | AMBIENT_HUMIDITY | % | ÷100 | 0~10000 |
| 0x005D | LIGHT_INTENSITY | lx | ×1 | 0~65535 |
| 0x0075 | BATTERY_LEVEL | % | ×1 | 0~100 |
| 0x0092 | CO2_CONCENTRATION | ppm | ×1 | 0~65535 |
| 0x00B4 | PM2_5_CONCENTRATION | μg/m³ | ×1 | 0~65535 |
| 0x00B9 | TVOC_CONCENTRATION | ppb | ×1 | 0~65535 |
5. 功能需求
5.1 FR-001: 串口连接管理
| 属性 | 值 |
|---|---|
| ID | FR-001 |
| 优先级 | P0 |
| 模块 | serial_reader.py |
描述: 管理串口的连接、读取、断开和重连
详细需求:
- 支持配置串口设备和波特率
- 异步非阻塞读取
- 自动处理粘包和断包
- 断线后自动重连(间隔 5 秒,最多 3 次)
- 支持写入 AT 命令
参数配置:
SERIAL_CONFIG = {
"device": "/dev/ttyUSB0", # 可配置
"baudrate": 115200, # 可配置
"bytesize": 8, # 固定
"parity": "N", # 固定
"stopbits": 1, # 固定
"timeout": 0.1, # 固定
"reconnect_interval": 5, # 固定
"reconnect_attempts": 3, # 固定
}
调试要点:
- 检查
dmesg | grep tty确认串口设备名 - 使用
ls -l /dev/ttyUSB*检查权限 - 使用
screen /dev/ttyUSB0 115200手动测试
5.2 FR-002: 协议解析
| 属性 | 值 |
|---|---|
| ID | FR-002 |
| 优先级 | P0 |
| 模块 | protocol_parser.py |
描述: 解析串口接收到的 Mesh 协议消息
详细需求:
- 解析事件前缀
+EVENT= - 按行分割处理(
\r\n分隔) - 识别消息类型(MESH/PROV)
- 提取并验证字段
- 将 16 进制 payload 转为 bytes
调试要点:
- 启用 debug 日志查看原始数据
- 检查 opcode 是否在支持列表中
- 验证 payload 长度是否符合预期
5.3 FR-003: 设备管理
| 属性 | 值 |
|---|---|
| ID | FR-003 |
| 优先级 | P1 |
| 模块 | protocol_parser.py |
描述: 管理已发现的 Mesh 设备状态
详细需求:
- 设备加入时创建记录
- 设备离开时移除记录
- 维护设备状态缓存
- 支持设备查询接口
数据结构:
class DeviceState:
mac_address: str # MAC 地址
element_index: int # 元素索引
model_id: int | None # 模型 ID
states: dict[str, Any] # 状态字典
last_update: float # 最后更新时间戳
5.4 FR-004: 数据协调器
| 属性 | 值 |
|---|---|
| ID | FR-004 |
| 优先级 | P0 |
| 模块 | coordinator.py |
描述: 协调数据更新和实体刷新
详细需求:
- 使用 HA DataUpdateCoordinator
- 支持定时轮询(可配置间隔)
- 支持事件驱动刷新
- 防抖处理(1 秒冷却)
参数配置:
COORDINATOR_CONFIG = {
"poll_interval": 30, # 轮询间隔 (秒),可配置
"debounce_cooldown": 1, # 防抖冷却 (秒),固定
"update_timeout": 10, # 更新超时 (秒),固定
}
5.5 FR-005: 传感器实体
| 属性 | 值 |
|---|---|
| ID | FR-005 |
| 优先级 | P0 |
| 模块 | platforms/sensor.py |
描述: 创建和管理传感器实体
支持的设备类别:
| Device Class | 单位 | 状态类 |
|---|---|---|
| temperature | °C | measurement |
| humidity | % | measurement |
| illuminance | lx | measurement |
| co2 | ppm | measurement |
| pm25 | μg/m³ | measurement |
| battery | % | measurement |
实体命名规范:
sensor.sigmesh_sensor_<mac> # 主传感器
sensor.sigmesh_battery_<mac> # 电池传感器
5.6 FR-006: 二进制传感器
| 属性 | 值 |
|---|---|
| ID | FR-006 |
| 优先级 | P1 |
| 模块 | platforms/binary_sensor.py |
描述: 创建二进制传感器(人体感应、门窗传感器)
支持的 Device Class:
| Device Class | 说明 |
|---|---|
| motion | 运动检测 |
| door | 门窗传感器 |
| presence | 存在检测 |
5.7 FR-007: 开关实体
| 属性 | 值 |
|---|---|
| ID | FR-007 |
| 优先级 | P1 |
| 模块 | platforms/switch.py |
描述: 创建开关控制实体
详细需求:
- 显示当前开关状态
- 支持开/关操作(TODO)
- 状态同步刷新
5.8 FR-008: 灯光实体
| 属性 | 值 |
|---|---|
| ID | FR-008 |
| 优先级 | P1 |
| 模块 | platforms/light.py |
描述: 创建灯光控制实体
支持的功能:
| 功能 | 支持状态 |
|---|---|
| 开关 | ✅ |
| 亮度调节 | ✅ |
| 色温调节 | ⏳ TODO |
| RGB 调色 | ⏳ TODO |
5.9 FR-009: 设备追踪
| 属性 | 值 |
|---|---|
| ID | FR-009 |
| 优先级 | P2 |
| 模块 | platforms/device_tracker.py |
描述: 创建设备追踪实体
源类型: bluetooth_le
5.10 FR-010: UI 配置界面
| 属性 | 值 |
|---|---|
| ID | FR-010 |
| 优先级 | P0 |
| 模块 | config_flow.py |
描述: 提供图形化配置界面
配置步骤:
- 选择串口设备(下拉列表)
- 输入波特率(默认 115200)
- 验证连接
- 完成配置
6. 非功能需求
6.1 性能要求
| 指标 | 要求 | 测量方法 |
|---|---|---|
| 支持设备数 | ≥200 | 模拟测试 |
| 消息延迟 | <100ms | 时间戳对比 |
| 内存占用 | <50MB | HA 监控 |
| CPU 占用 | <5% | HA 监控 |
| 启动时间 | <10s | 日志计时 |
6.2 可靠性要求
| 场景 | 要求 |
|---|---|
| 串口断开 | 自动重连,最多 3 次 |
| 数据异常 | 跳过异常数据,记录日志 |
| HA 重启 | 自动恢复连接 |
| 网关重启 | 自动重新发现设备 |
6.3 兼容性要求
| 项目 | 要求 |
|---|---|
| HA 版本 | ≥ 2024.1.0 |
| HACS 版本 | ≥ 1.34.0 |
| Python 版本 | ≥ 3.11 |
| 操作系统 | Linux (HAOS) |
6.4 安全要求
| 项目 | 要求 |
|---|---|
| 权限 | 最小权限原则 |
| 数据 | 无敏感数据传输 |
| 日志 | 不记录敏感信息 |
7. 数据模型
7.1 实体关系图
┌─────────────────┐
│ ConfigEntry │
│ (配置入口) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Coordinator │
│ (协调器) │
└────────┬────────┘
│
┌────┼────┬──────────┬────────────┐
▼ ▼ ▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐ ┌──────────┐ ┌──────────┐
│ Sensor │ │Binary │ │ Switch │ │ Light │ │ Tracker │
│ │ │Sensor │ │ │ │ │ │ │
└────────┘ └────────┘ └────────┘ └──────────┘ └──────────┘
7.2 设备状态模型
{
"mac_address": "AA:BB:CC:DD:EE:FF",
"element_index": 0,
"model_id": 4352, # 0x1100
"states": {
"property_id": 89, # 0x0059 温度
"property_name": "AMBIENT_TEMPERATURE",
"value": 2350, # 23.5°C
"unit": "°C",
"formatted": "23.5°C"
},
"last_update": 1713187200.0
}
8. 接口定义
8.1 Coordinator 对外接口
class SigMeshGatewayCoordinator:
# 获取设备
def get_device(mac_address: str) -> DeviceState | None
# 按类型获取设备
def get_devices_by_type(model_id: int) -> list[DeviceState]
# 启动/停止
async def start() -> None
async def stop() -> None
# 刷新数据
async def async_request_refresh() -> None
8.2 服务调用接口(TODO)
# service.yaml
sigmesh_gateway.send_command:
fields:
device_id:
description: 设备 ID
example: "AA:BB:CC:DD:EE:FF"
opcode:
description: 操作码
example: "0x8202"
payload:
description: 数据负载
example: "01"
9. 配置参数
9.1 配置入口参数
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| serial_device | string | 是 | /dev/ttyUSB0 | 串口设备路径 |
| baudrate | int | 否 | 115200 | 波特率 |
9.2 选项参数
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| poll_interval | int | 否 | 30 | 轮询间隔 (秒) |
9.3 调试参数
# configuration.yaml
logger:
logs:
custom_components.sigmesh_gateway: debug
custom_components.sigmesh_gateway.serial_reader: debug
custom_components.sigmesh_gateway.protocol_parser: debug
custom_components.sigmesh_gateway.coordinator: debug
10. 错误处理
10.1 错误码定义
| 错误码 | 名称 | 说明 | 处理 |
|---|---|---|---|
| E001 | SERIAL_OPEN_FAILED | 串口打开失败 | 检查设备路径和权限 |
| E002 | SERIAL_READ_ERROR | 串口读取错误 | 重连或提示用户 |
| E003 | PARSE_ERROR | 解析错误 | 跳过并记录日志 |
| E004 | DEVICE_NOT_FOUND | 设备未找到 | 返回 None |
| E005 | TIMEOUT | 超时 | 重试或报错 |
10.2 异常处理流程
串口读取异常
↓
记录错误日志
↓
尝试重连 (最多 3 次)
↓
失败 → 标记集成不可用
成功 → 恢复正常工作
11. 日志规范
11.1 日志级别
| 级别 | 使用场景 |
|---|---|
| DEBUG | 详细调试信息(原始数据、解析过程) |
| INFO | 正常流程信息(启动、停止、设备加入) |
| WARNING | 警告信息(重连、数据异常) |
| ERROR | 错误信息(解析失败、连接失败) |
| CRITICAL | 严重错误(集成无法运行) |
11.2 日志格式
_LOGGER.info("串口已连接:%s, 波特率:%d", device, baudrate)
_LOGGER.debug("串口接收:%s", line)
_LOGGER.error("解析 Mesh 消息失败:%s, 错误:%s", line, e)
11.3 关键日志点
| 模块 | 日志内容 | 级别 |
|---|---|---|
| serial_reader | 串口连接成功/失败 | INFO/ERROR |
| serial_reader | 接收原始数据 | DEBUG |
| protocol_parser | 解析结果 | DEBUG |
| coordinator | 设备加入/离开 | INFO |
| coordinator | 数据刷新 | DEBUG |
12. 测试计划
12.1 单元测试
| 模块 | 测试内容 | 方法 |
|---|---|---|
| serial_reader | 串口连接 | Mock serial |
| protocol_parser | 消息解析 | 构造测试数据 |
| coordinator | 数据协调 | Mock HA |
12.2 集成测试
| 测试项 | 步骤 | 预期结果 |
|---|---|---|
| 串口连接 | 配置正确串口 | 连接成功 |
| 设备发现 | 网关上报设备 | 实体创建 |
| 状态更新 | 发送状态消息 | 实体状态变化 |
| 断线重连 | 断开串口 | 自动重连 |
12.3 压力测试
| 测试项 | 方法 | 通过标准 |
|---|---|---|
| 200 设备 | 模拟 200 设备数据 | 无崩溃,内存<50MB |
| 高频数据 | 100 条/秒 | 无丢失,延迟<100ms |
13. 调试指南
13.1 调试准备
# 1. 启用调试日志
logger:
default: warning
logs:
custom_components.sigmesh_gateway: debug
13.2 常见问题排查
问题 1: 串口无法连接
# 检查串口设备
ls -l /dev/ttyUSB*
# 检查权限
groups homeassistant
# 添加权限
sudo usermod -a -G dialout homeassistant
# 确认串口通信
screen /dev/ttyUSB0 115200
# 发送 AT 测试
AT
问题 2: 收不到数据
# 查看日志
tail -f ~/.homeassistant/home-assistant.log | grep sigmesh
# 检查网关状态
# 确认网关已上电并正常工作
问题 3: 实体不显示
# 检查集成状态
# 设置 → 设备与服务 → 查看 SigMesh Gateway
# 重新加载集成
# 设置 → 设备与服务 → SigMesh Gateway → 重新加载
13.3 数据抓取
# 在 serial_reader.py 中添加调试输出
async def _read_loop(self) -> None:
while self._running:
if self._serial and self._serial.in_waiting:
data = self._serial.read(self._serial.in_waiting)
print(f"[DEBUG] 原始数据:{data}") # 添加此行
14. 版本历史
| 版本 | 日期 | 作者 | 变更内容 |
|---|---|---|---|
| 1.0.0 | 2026-04-15 | 开发团队 | 初始版本 |
附录 A: 配置文件模板
# configuration.yaml
# 集成配置(如使用 YAML)
sigmesh_gateway:
serial_device: /dev/ttyUSB0
baudrate: 115200
# 日志配置
logger:
default: warning
logs:
custom_components.sigmesh_gateway: debug
# 自动化示例
automation:
- alias: "温度过高告警"
trigger:
platform: numeric_state
entity_id: sensor.sigmesh_sensor_AA_BB_CC_DD_EE_FF
above: 30
action:
- service: notify.notify
data:
message: "温度过高!"
附录 B: 快速参考卡
┌────────────────────────────────────────────────────────────┐
│ SigMesh Gateway 快速参考 │
├────────────────────────────────────────────────────────────┤
│ 串口:/dev/ttyUSB0 │
│ 波特率:115200 │
│ 协议:+EVENT=MESH,recv,<src>,<dst>,<opcode>,<payload> │
│ │
│ 调试命令: │
│ ls -l /dev/ttyUSB* # 检查串口 │
│ screen /dev/ttyUSB0 115200 # 手动测试 │
│ tail -f home-assistant.log | grep sigmesh # 查看日志 │
│ │
│ 实体命名: │
│ sensor.sigmesh_sensor_<mac> │
│ switch.sigmesh_switch_<mac> │
│ light.sigmesh_light_<mac> │
└────────────────────────────────────────────────────────────┘
文档结束