impress_sig_mesh_hacs/custom_components/sigmesh_gateway/const.py
impressionyang 4c3eb62dfb feat: 实现完整的 Web UI 配网管理功能
新增 Web UI 组件:
- web_ui.py: RESTful API 端点(状态、扫描、配网、分组、设备)
- sigmesh-gateway-panel.js: Lovelace Dashboard 自定义卡片
  - 设备扫描和发现
- 配网操作(开始/停止/绑定 App Key)
  - 分组管理(添加/移除)
  - 实时状态监控

配置更新:
- __init__.py: 集成 Web UI 和服务注册
- const.py: 添加服务常量定义
- services.py: 保留服务调用用于向后兼容
- README.md: 添加 Web UI 配置说明
- docs/UI 使用指南.md: 详细的 UI 使用文档

使用方式:
1. 配置 frontend.extra_module_url 加载 JS 面板
2. 在 Lovelace Dashboard 添加 custom:sigmesh-gateway-panel 卡片
3. 通过 UI 完成所有配网和分组操作

API 端点:
- GET /api/sigmesh_gateway/status - 获取配网状态
- POST /api/sigmesh_gateway/scan - 开始扫描
- POST /api/sigmesh_gateway/provisioning - 配网操作
- POST /api/sigmesh_gateway/group - 分组管理
- GET /api/sigmesh_gateway/devices - 设备列表
2026-04-16 13:41:28 +08:00

189 lines
5.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""SigMesh Gateway 常量定义."""
from enum import IntEnum, StrEnum
from typing import Final
# 集成配置
DOMAIN = "sigmesh_gateway"
DEFAULT_NAME = "SigMesh Gateway"
DEFAULT_BAUDRATE = 115200
DEFAULT_BYTESIZE = 8
DEFAULT_PARITY = "N"
DEFAULT_STOPBITS = 1
DEFAULT_TIMEOUT = 5
# 串口配置常量
CONF_SERIAL_DEVICE = "serial_device"
CONF_BAUDRATE = "baudrate"
# 配网配置USB dongle 首次使用需要)
CONF_NETWORK_KEY = "network_key" # 16 字节网络密钥
CONF_APP_KEY = "app_key" # 16 字节应用密钥
CONF_NETWORK_ID = "network_id" # 2 字节网络 ID
CONF_IV_INDEX = "iv_index" # 4 字节 IV Index
# 默认配网参数
DEFAULT_NETWORK_KEY = "00000000000000000000000000000000" # 32 字符十六进制
DEFAULT_APP_KEY = "00000000000000000000000000000000"
DEFAULT_NETWORK_ID = "0000"
DEFAULT_IV_INDEX = 0
# 配网超时
PROV_TIMEOUT = 180 # 配网超时时间(秒)
PROV_POLL_INTERVAL = 2 # 配网轮询间隔(秒)
# 组地址配置
CONF_GROUP_ADDRESS = "group_address"
DEFAULT_GROUP_ADDRESS_START = 0xC000 # 组地址起始值
DEFAULT_GROUP_ADDRESS_END = 0xCFFF # 组地址结束值
class MeshModelId(IntEnum):
"""蓝牙 Mesh 模型 ID."""
# 开关模型
ONOFF_SERVER = 0x1000
ONOFF_CLIENT = 0x1001
# 灯模型
LIGHT_LIGHTNESS_SERVER = 0x1300
LIGHT_HSL_SERVER = 0x1307
LIGHT_COLOR_SERVER = 0x130C
LIGHT_CTL_SERVER = 0x130D
# 传感器模型
SENSOR_SERVER = 0x1100
SENSOR_SETUP_SERVER = 0x1101
# 二进制传感器
SENSOR_ONOFF_SERVER = 0x1104
class MeshOpcode(IntEnum):
"""蓝牙 Mesh Opcode."""
# 开关相关
ONOFF_GET = 0x8201
ONOFF_SET = 0x8202
ONOFF_SET_UNACK = 0x8203
ONOFF_STATUS = 0x8204
# 灯泡相关
LIGHT_LIGHTNESS_GET = 0x8229
LIGHT_LIGHTNESS_SET = 0x822B
LIGHT_LIGHTNESS_STATUS = 0x822C
LIGHT_HSL_SET = 0x8231
LIGHT_HSL_STATUS = 0x8232
LIGHT_CTL_SET = 0x825D
LIGHT_CTL_STATUS = 0x825E
LIGHT_COLOR_SET = 0x8200
LIGHT_COLOR_STATUS = 0x8201
# 传感器相关
SENSOR_GET = 0x8230
SENSOR_STATUS = 0x8231
SENSOR_CADENCE = 0x8237
SENSOR_SETTINGS = 0x8238
SENSOR_SETTING_GET = 0x8239
SENSOR_SETTING_STATUS = 0x823A
SENSOR_SERIES_GET = 0x823B
SENSOR_SERIES_STATUS = 0x823C
# 时间相关
TIME_GET = 0x1200
TIME_STATUS = 0x1201
TIME_SET = 0x1202
# 电池
BATTERY_STATUS = 0x820C
# 配网相关
PROV_LINK_OPEN = 0x00
PROV_LINK_CLOSE = 0x01
PROV_INVITE = 0x02
PROV_START = 0x03
PROV_AUTH_START = 0x04
PROV_COMPLETE = 0x05
PROV_FAILED = 0x06
# 配置相关
CFG_NETKEY_ADD = 0x8000
CFG_NETKEY_UPDATE = 0x8001
CFG_APPKEY_ADD = 0x8003
CFG_APPKEY_UPDATE = 0x8004
CFG_MODEL_APP_BIND = 0x8006
CFG_MODEL_SUBSCRIBE = 0x8007
CFG_MODEL_PUBLISH = 0x8008
class MeshSigOp(IntEnum):
"""SIG 操作码(用于分组等)。"""
# 组管理
SIG_GROUP_ADD = 0x801B # 加入组
SIG_GROUP_DELETE = 0x801D # 删除组
SIG_GROUP_STATUS = 0x801C # 组状态(预留)
class MeshPropertyId(IntEnum):
"""Mesh 属性 ID - 用于解析传感器数据."""
PRESENCE_DETECTED = 0x0050 # 存在检测
MOTION_DETECTED = 0x0051 # 运动检测
AMBIENT_TEMPERATURE = 0x0059 # 环境温度
AMBIENT_HUMIDITY = 0x005A # 环境湿度
LIGHT_INTENSITY = 0x005D # 光照强度
BATTERY_LEVEL = 0x0075 # 电池电量
CO2_CONCENTRATION = 0x0092 # CO2 浓度
PM2_5_CONCENTRATION = 0x00B4 # PM2.5 浓度
TVOC_CONCENTRATION = 0x00B9 # TVOC 浓度
class SensorUnit(StrEnum):
"""传感器单位."""
NONE = ""
CELSIUS = "°C"
PERCENTAGE = "%"
LUX = "lx"
PPM = "ppm"
UG_M3 = "μg/m³"
PPB = "ppb"
MV = "mV"
VOLTAGE = "V"
# Mesh 属性 ID 到单位的映射
PROPERTY_UNIT_MAP: Final[dict[int, SensorUnit]] = {
MeshPropertyId.AMBIENT_TEMPERATURE: SensorUnit.CELSIUS,
MeshPropertyId.AMBIENT_HUMIDITY: SensorUnit.PERCENTAGE,
MeshPropertyId.LIGHT_INTENSITY: SensorUnit.LUX,
MeshPropertyId.BATTERY_LEVEL: SensorUnit.PERCENTAGE,
MeshPropertyId.CO2_CONCENTRATION: SensorUnit.PPM,
MeshPropertyId.PM2_5_CONCENTRATION: SensorUnit.UG_M3,
MeshPropertyId.TVOC_CONCENTRATION: SensorUnit.PPB,
MeshPropertyId.PRESENCE_DETECTED: SensorUnit.NONE,
MeshPropertyId.MOTION_DETECTED: SensorUnit.NONE,
}
# 事件类型
EVENT_SERIAL_DATA: Final = f"{DOMAIN}_serial_data"
EVENT_MESH_MESSAGE: Final = f"{DOMAIN}_mesh_message"
EVENT_DEVICE_JOINED: Final = f"{DOMAIN}_device_joined"
EVENT_DEVICE_LEFT: Final = f"{DOMAIN}_device_left"
# 串口通信
SERIAL_EVENT_PREFIX = "+EVENT="
SERIAL_MESH_RECV = "+EVENT=MESH,recv"
SERIAL_PROV_DEVICE_JOINED = "+EVENT=PROV,device_joined"
SERIAL_PROV_DEVICE_LEFT = "+EVENT=PROV,device_left"
# 服务名称
SERVICE_START_SCAN = "start_scan"
SERVICE_STOP_PROVISIONING = "stop_provisioning"
SERVICE_START_PROVISIONING = "start_provisioning"
SERVICE_BIND_APPKEY = "bind_appkey"
SERVICE_ADD_TO_GROUP = "add_to_group"
SERVICE_REMOVE_FROM_GROUP = "remove_from_group"
SERVICE_SEND_VENDOR_COMMAND = "send_vendor_command"