# SigMesh Gateway HACS 集成 - PRD 产品需求文档 **版本号**: 1.0.0 **创建日期**: 2026-04-15 **最后更新**: 2026-04-15 **状态**: 草稿 → 评审中 --- ## 目录 1. [文档概述](#1-文档概述) 2. [产品背景](#2-产品背景) 3. [需求范围](#3-需求范围) 4. [技术规格](#4-技术规格) 5. [功能需求](#5-功能需求) 6. [非功能需求](#6-非功能需求) 7. [数据模型](#7-数据模型) 8. [接口定义](#8-接口定义) 9. [配置参数](#9-配置参数) 10. [错误处理](#10-错误处理) 11. [日志规范](#11-日志规范) 12. [测试计划](#12-测试计划) 13. [调试指南](#13-调试指南) 14. [版本历史](#14-版本历史) --- ## 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 集成项目,实现: 1. 通过串口读取 SigMesh 网关数据 2. 解析 Bluetooth Mesh 协议消息 3. 在 Home Assistant 中创建和管理实体 4. 支持最多 200 个 Mesh 设备接入 ### 2.2 使用场景 | 场景 | 描述 | |------|------| | 智能家居 | 接入蓝牙 Mesh 开关、灯光、传感器 | | 商业照明 | 大规模 Mesh 灯光控制 | | 环境监测 | 温湿度、光照等传感器数据采集 | ### 2.3 硬件规格 **SigMesh 网关 (E104-BT12USP)**: - 芯片:Nordic nRF52840 - 协议:Bluetooth 5.4 Mesh - 接口:USB 直连(内置 USB 转 UART) - 串口参数:115200, 8N1 **网关配置工具**: - 软件:亿佰特 danglo 组网工具 - 配网方式:PROV 配网 - 组网管理:支持设备扫描、配网、分组 - 设备控制:支持 ON/OFF、亮度、色温控制 **重要配置说明**: 1. 首次使用需通过 danglo 工具配置 USB dongle 参数 2. 设备配网:SCAN 扫描 → 双击设备 → PROV 配网 → 绑定 APP Key 3. 分组管理:通过 GROUP 设置将设备分配到组地址 4. 手机 APP 默认订阅:0x1307 (SIG_MD_LIGHT_HSL_S) 5. 天猫精灵默认订阅:0x10 (SIG_MD_G_ONOFF_S) 6. 低功耗节点组传输:需将 Lightness Model 和 Vendor Model 分配到同一组 --- ## 3. 需求范围 ### 3.1 功能边界 **包含的功能**: - ✅ 串口异步数据读取 - ✅ Mesh 协议解析 - ✅ 设备自动发现 - ✅ 多平台实体创建 - ✅ UI 配置界面 **不包含的功能**: - ❌ Mesh 配网功能(网关已完成) - ❌ 设备固件升级 - ❌ 网络拓扑展示 - ❌ 离线缓存 ### 3.2 依赖关系 ``` SigMesh Gateway 集成 ├── 依赖:Home Assistant ≥ 2024.1.0 ├── 依赖:HACS ≥ 1.34.0 └── 依赖:pyserial-asyncio-fast ≥ 0.6 ``` --- ## 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,,,,\r\n 设备加入: +EVENT=PROV,device_joined,,\r\n 设备离开: +EVENT=PROV,device_left,\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 字符 | 元素数量 | **协议帧格式 (基于亿佰特文档)**: ``` 通用帧结构: [Cmd 头] [固定字段] [目标地址] [操作码] [元素地址] [组地址/参数] [ModelID] [校验/结束] 命令头:e8 ff (所有命令以此开头) ``` **常见操作码**: | 操作码 | 功能 | |--------|------| | 80 1b | 加入组/设置 | | 80 1d | 删除组 | **组网配置要点**: - 组地址:使用 0xC000 以上的地址作为组地址 - 手机 APP 默认订阅:0x1307 (SIG_MD_LIGHT_HSL_S) - 天猫精灵默认订阅:0x0010 (SIG_MD_G_ONOFF_S) - 低功耗节点:需将 Lightness Model 和 Vendor Model 分配到同一组才能接收组地址传输 ### 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 | **描述**: 管理串口的连接、读取、断开和重连 **详细需求**: 1. 支持配置串口设备和波特率 2. 异步非阻塞读取 3. 自动处理粘包和断包 4. 断线后自动重连(间隔 5 秒,最多 3 次) 5. 支持写入 AT 命令 **参数配置**: ```python 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 协议消息 **详细需求**: 1. 解析事件前缀 `+EVENT=` 2. 按行分割处理(`\r\n` 分隔) 3. 识别消息类型(MESH/PROV) 4. 提取并验证字段 5. 将 16 进制 payload 转为 bytes **调试要点**: - 启用 debug 日志查看原始数据 - 检查 opcode 是否在支持列表中 - 验证 payload 长度是否符合预期 --- ### 5.3 FR-003: 设备管理 | 属性 | 值 | |------|-----| | ID | FR-003 | | 优先级 | P1 | | 模块 | protocol_parser.py | **描述**: 管理已发现的 Mesh 设备状态 **详细需求**: 1. 设备加入时创建记录 2. 设备离开时移除记录 3. 维护设备状态缓存 4. 支持设备查询接口 **数据结构**: ```python 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 | **描述**: 协调数据更新和实体刷新 **详细需求**: 1. 使用 HA DataUpdateCoordinator 2. 支持定时轮询(可配置间隔) 3. 支持事件驱动刷新 4. 防抖处理(1 秒冷却) **参数配置**: ```python 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_ # 主传感器 sensor.sigmesh_battery_ # 电池传感器 ``` --- ### 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 | **描述**: 创建开关控制实体 **详细需求**: 1. 显示当前开关状态 2. 支持开/关操作(TODO) 3. 状态同步刷新 --- ### 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 | **描述**: 提供图形化配置界面 **配置步骤**: 1. 选择串口设备(下拉列表) 2. 输入波特率(默认 115200) 3. 验证连接 4. 完成配置 --- ## 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 设备状态模型 ```python { "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 对外接口 ```python 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) ```yaml # 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 调试参数 ```yaml # 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 日志格式 ```python _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 调试准备 ```yaml # 1. 启用调试日志 logger: default: warning logs: custom_components.sigmesh_gateway: debug ``` ### 13.2 常见问题排查 #### 问题 1: 串口无法连接 ```bash # 检查串口设备 ls -l /dev/ttyUSB* # 检查权限 groups homeassistant # 添加权限 sudo usermod -a -G dialout homeassistant # 确认串口通信 screen /dev/ttyUSB0 115200 # 发送 AT 测试 AT ``` #### 问题 2: 收不到数据 ```bash # 查看日志 tail -f ~/.homeassistant/home-assistant.log | grep sigmesh # 检查网关状态 # 确认网关已上电并正常工作 ``` #### 问题 3: 实体不显示 ```bash # 检查集成状态 # 设置 → 设备与服务 → 查看 SigMesh Gateway # 重新加载集成 # 设置 → 设备与服务 → SigMesh Gateway → 重新加载 ``` ### 13.3 数据抓取 ```python # 在 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: 配置文件模板 ```yaml # 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,,,, │ │ │ │ 调试命令: │ │ ls -l /dev/ttyUSB* # 检查串口 │ │ screen /dev/ttyUSB0 115200 # 手动测试 │ │ tail -f home-assistant.log | grep sigmesh # 查看日志 │ │ │ │ 实体命名: │ │ sensor.sigmesh_sensor_ │ │ switch.sigmesh_switch_ │ │ light.sigmesh_light_ │ └────────────────────────────────────────────────────────────┘ ``` --- **文档结束**