# BLS RCU Action Server 开发文档 ## 1. 项目概述 本项目旨在构建一个后端服务,负责从 Kafka 接收 RCU(客房控制单元)的通讯日志,解析数据结构,并将其持久化存储到 PostgreSQL 数据库中。 核心目标是将不同类型的通讯协议数据(0x36 上报、0x0F 下发、ACK)统一存储,并针对不定长数据结构采用 JSON 格式进行灵活保存。 ## 2. 系统架构 **数据流向**: `MCU/Server` (产生数据) -> `Kafka` (消息队列) -> `Action Server` (消费 & 解析) -> `PostgreSQL` (存储) - **Kafka Topic**: `blwlog4Nodejs-rcu-action-topic` (分区数: 6) - **数据库**: PostgreSQL ## 3. 数据库设计 数据库名:`bls_rcu_action` 模式名: `rcu_action` ### 3.1 表结构设计 表名: `rcu_action_events` | 字段名 | 类型 | 说明 | 备注 | | :--- | :--- | :--- | :--- | | **guid** | VARCHAR(32) | 主键 (Key2) | 32位无符号UUID | | **ts_ms** | BIGINT | 日志产生时间 (Key1) | **必填** (L49) | | **write_ts_ms** | BIGINT | 入库时间 | **必填** (L50) | | **hotel_id** | INTEGER | 酒店ID | **必填** (L51) Index | | **room_id** | VARCHAR(32) | 房间ID | **必填** (L52) Index | | **device_id** | VARCHAR(32) | 设备ID | **必填** (新增) Index | | **direction** | VARCHAR(10) | 数据方向 | **必填** (L53) "上报"/"下发" Index | | **cmd_word** | VARCHAR(10) | 命令字 | **必填** (L54) 如 "0x36", "0x0F" Index | | **frame_id** | INTEGER | 通讯帧号 | **必填** (L55) 用于串联命令与状态 | | **udp_raw** | TEXT | UDP消息原文 | **必填** (L56) base64字符串;当前若上游仍发送十六进制字符串,则后端会在入库前临时转换为base64,后续会取消该自动转换机制 | | **action_type** | VARCHAR(20) | 记录行为类型 | **必填** (L57) Index | | **sys_lock_status** | SMALLINT | 系统锁状态 | (L59) 可空 | | **report_count** | SMALLINT | 本次上报数量 | (L60) 可空 | | **dev_type** | SMALLINT | 设备类型 | (L61) 可空 (统一字段) | | **dev_addr** | SMALLINT | 设备地址 | (L62) 可空 (统一字段) | | **dev_loop** | INTEGER | 设备回路 | (L63) 可空 (统一字段) | | **dev_data** | INTEGER | 设备状态 | (L64) 可空 (0x36状态) | | **fault_count** | SMALLINT | 本次故障数量 | (L65) 可空 | | **error_type** | SMALLINT | 故障类型 | (L69) 可空 (0x36故障) | | **error_data** | SMALLINT | 故障内容 | (L70) 可空 (0x36故障) | | **type_l** | SMALLINT | 执行方式 | 可空 (0x0F下发) | | **type_h** | SMALLINT | 执行内容 | 可空 (0x0F下发) | | **details** | JSONB | 业务详情数据 | 存储不定长设备列表、故障信息等 | | **extra** | JSONB | 扩展信息 | 存储上游传入的extra扩展字段;如未提供则为空对象 | **主键定义**: `(ts_ms, guid)` **索引定义**: 备注带index的字段为需要索引的字段,用于提高查询效率。 ### 3.2 字典定义 **Action Type (记录行为类型)**: - 枚举值:(ACK和下发控制是0x0F的特殊情况,用户操作和设备回路状态是0x36的枚举值) - ACK:ACK是0x0F的上报独有的,所以如果0F且Direction为上报,就标记为ACK - 下发控制:0x0F的Direction为下发指令,记录为下发控制 - 用户操作:0x36上报 的开关、温控器等客户操作设备产生的,属于用户操作 - 设备回路状态:0x36上报 的灯光、继电器回路等变化等受控设备,属于设备回路状态 - 用户操作和设备回路状态的具体区分表(根据本行数据的dev_type来区分),注意,这张表是根据dev_type来区分的,所以dev_type不能改变,否则会导致数据错误,另外这个表要写入env配置文件,以数组形式保存,随时可以更改: |dev_type|名称|描述|Action Type| |---|---|---|---| |0|Dev_Host_Invalid|无效设备(也可以被认为是场景)|无效| |1|Dev_Host_HVout|强电继电器(输出状态)|设备回路状态| |2|Dev_Host_LVinput|弱电输入(输入状态)|用户操作| |3|Dev_Host_LVoutput|弱电输出(输出状态)|设备回路状态| |4|Dev_Host_Service|服务信息|设备回路状态| |5|Dev_NodeCurtain|干节点窗帘|设备回路状态| |6|DEV_RS485_SWT|开关|用户操作| |7|DEV_RS485_TEMP|空调|用户操作| |8|DEV_RS485_INFRARED|红外感应|用户操作| |9|DEV_RS485_AirDetect|空气质量检测设备|设备回路状态| |10|DEV_RS485_CARD|插卡取电|用户操作| |11|DEV_RS485_HEATER|地暖|用户操作| |12|Dev_RCU_NET|RCU 设备网络 - 没使用|| |13|DEV_RS485_CURTAIN|窗帘|设备回路状态| |14|DEV_RS485_RELAY|继电器|设备回路状态| |15|DEV_RS485_IR_SEND|红外发送|设备回路状态| |16|DEV_RS485_DIMMING|调光驱动|设备回路状态| |17|DEV_RS485_TRAIC|可控硅调光(可控硅状态)|设备回路状态| |18|DEV_RS485_STRIP|灯带(灯带状态) --2025-11-24 取消|无效| |19|DEV_RS485_CoreCtrl|中控|无效| |20|DEV_RS485_WxLock|微信锁 (福 瑞狗的蓝牙锁 默认 0 地址)|无效| |21|DEV_RS485_MUSIC|背景音乐(背景音乐状态)|设备回路状态| |22|DEV_NET_ROOMSTATE|房态下发|无效| |23|Dev_Host_PWMLight|主机本地 调光|无效| |24|DEV_RS485_PWM|485PWM 调光( PWM 调光状态)|无效| |25|DEV_PB_LED|总线调光( PBLED 调光状态) - 没使用 -|无效| |26|DEV_RCU_POWER|RCU 电源|无效| |27|DEV_RS485_A9_IO_SWT|A9IO 开关|用户操作| |28|DEV_RS485_A9_IO_EXP|A9IO 扩展|设备回路状态| |29|DEV_RS485_A9_IO_POWER|A9IO 电源|设备回路状态| |30|DEV_RS485_RFGatewayCycle|无线网关轮询(用于轮询控制轮询设备;给无线网关下发配置和询问网关状态)|无效| |31|DEV_RS485_RFGatewayHost|无线网关主动(用于主动控制主动设备)|无效| |32|DEV_RS485_RFGatewayDoor|无线门磁|用户操作| |33|DEV_RS485_AirReveal|空气参数显示设备|设备回路状态| |34|DEV_RS485_RFGatewayRelayPir|无线继电器红外|设备回路状态| |35|Dev_Host_TimeCtrl|时间同步|设备回路状态| |36|Dev_Rs458_MonitorCtrl|监控控制|无效| |37|Dev_Rs458_RotaryCtrl|旋钮开关控制|用户操作| |38|Dev_BUS_C5IO|CSIO - 类型|设备回路状态| |39|Dev_RS485_CardState|插卡状态虚拟设备|设备回路状态| |40|DEV_RS485_FreshAir|485 新风设备|用户操作| |41|DEV_RS485_FaceMach|485 人脸机|用户操作| |42|DEV_Center_Control|中控|无效| |43|DEV_Domain_Control|域控|无效| |44|DEV_RS485_LCD|LCD|设备回路状态| |45|DEV_Virtual_NoCard|无卡断电 --2025-11-24 取消|无效| |46|DEV_Virtual_Card|无卡取电 2|用户操作| |47|DEV_Virtual_Time|虚拟时间设备|设备回路状态| |48|Dev_Rs485_PB20|PLC 总控|设备回路状态| |49|Dev_Rs485_PB20_LD|PLC 设备 - 恒流调光设备|设备回路状态| |50|Dev_Rs485_PB20_LS|PLC 设备 - 恒压调光设备|设备回路状态| |51|Dev_Rs485_PB20_Relay|PLC 设备 - 继电器设备|设备回路状态| |52|DEV_Virtual_ColorTemp|色温调节功能|设备回路状态| |53|Dev_485_BLE_Music|蓝牙音频|设备回路状态| |54|DEV_Carbon_Saved|碳达人|用户操作| |55|Dev_Scene_Restore|场景还原|用户操作| |56|Dev_Virtual_GlobalSet|全局设置|设备回路状态| |57|Dev_Energy_Monitor|能耗检测|设备回路状态| |241|Dev_BUS_C5IO|CSIO - 类型|设备回路状态| **Direction (方向)**: - `"上报"`: Upload - `"下发"`: Download ## 4. 数据解析与存储映射 ### 4.1 0x36 上报数据 (设备状态/故障) * **命令字**: "0x36" * **拆分逻辑**: 根据 `project.md` 说明,一条 UDP 可能包含多个设备状态,需拆分为多条记录入库,每条记录填充 `dev_type` 等字段。同时将完整的不定长列表存入 `details` 以便追溯。 * **Action Type**: 4 (设备回路状态) **Mapping**: - `sys_lock_status` -> P0 - `report_count` -> P7 - `dev_type`, `dev_addr`... -> 从 P8~P13 循环解析,每组生成一条 DB 记录 - `details`: `{ "all_devices": [...], "all_faults": [...] }` - `extra`: `{ "raw_hex": "..." }` ### 4.2 0x0F 下发数据 (控制指令) * **命令字**: "0x0F" * **Action Type**: 2 (下发控制) * **存储逻辑**: 主要是控制指令,通常作为单条记录存储。若包含多个设备控制,可选择存第一条到字段,或仅存入 JSON。根据 "0x0F不定长存为JSON" 的需求,主要依赖 `details` 字段。 **Mapping**: - `details`: `{ "control_params": [ ... ] }` - `extra`: `{ "raw_hex": "..." }` ### 4.3 0x0F 上报数据 (ACK) * **命令字**: "0x0F" * **Action Type**: "0FACK" (ACK) **Mapping**: - `details`: `{ "ack_code": "0x00" }` - `extra`: `{ "raw_hex": "..." }`