# Kafka 推送格式与数据拆分规范

本文档定义了上游服务向 Kafka 推送消息的标准 JSON 格式。

**核心变更**：上游服务负责将原始报文解析为结构化的 JSON 对象。对于包含多个设备状态或故障信息的命令（如 `0x36`），上游必须将其转换为 **JSON 数组**，后端服务直接遍历这些数组进行入库，不再依赖对 `udp_raw` 的二次解析。

## 1. Kafka 基础信息
*   **Topic**: `blwlog4Nodejs-rcu-action-topic`
*   **分区数**: 6
*   **消息格式**: JSON String

## 2. 消息结构定义 (Schema)

JSON 消息由 **Header 信息** 和 **业务列表数据** 组成。

### 2.1 顶层字段 (Header & 统计)

| 字段名 | 类型 | 必填 | 说明 |
| :--- | :--- | :--- | :--- |
| **ts_ms** | Number | **是** | 日志产生时间戳 (Key1) |
| **hotel_id** | Number | **是** | 酒店 ID |
| **room_id** | String | **是** | 房间 ID |
| **device_id** | String | **是** | 设备 ID |
| **direction** | String | **是** | "上报" 或 "下发" |
| **cmd_word** | String | **是** | 命令字 (如 "0x36", "0x0F") |
| **frame_id** | Number | **是** | 通讯帧号 |
| **udp_raw** | String | **是** | UDP 原始报文备份；推荐上游直接发送base64字符串；当前若上游仍发送十六进制字符串，后端会在入库前临时将其转换为base64，后续会取消该自动转换机制 |
| **sys_lock_status** | Number | 否 | 系统锁状态 (0:未锁, 1:锁定) |
| **report_count** | Number | 否 | 上报设备数量 (对应 device_list 长度) |
| **fault_count** | Number | 否 | 故障设备数量 (对应 fault_list 长度) |
| **action_type** | String | 否 | 行为类型 (建议上游预填，或后端默认处理) |
| **device_list** | Array | 否 | **设备状态列表** (结构见 2.2) |
| **fault_list** | Array | 否 | **设备故障列表** (结构见 2.3) |
| **control_list** | Array | 否 | **控制参数列表** (用于 0x0F) |

### 2.2 设备状态对象 (Item in `device_list`)
对应 `0x36` 命令中的 P8~P13。

| JSON 字段名 | DB 映射字段 | 类型 | 说明 |
| :--- | :--- | :--- | :--- |
| **dev_type** | `dev_type` | Number | 设备类型 |
| **dev_addr** | `dev_addr` | Number | 设备地址 |
| **dev_loop** | `dev_loop` | Number | 设备回路 |
| **dev_data** | `dev_data` | Number | 设备状态 |

### 2.3 设备故障对象 (Item in `fault_list`)
对应 `0x36` 命令中的 P15~P20。

| JSON 字段名 | DB 映射字段 | 类型 | 说明 |
| :--- | :--- | :--- | :--- |
| **dev_type** | `dev_type` | Number | 故障设备类型 (复用 dev_type) |
| **dev_addr** | `dev_addr` | Number | 故障设备地址 (复用 dev_addr) |
| **dev_loop** | `dev_loop` | Number | 故障设备回路 (复用 dev_loop) |
| **error_type** | `error_type` | Number | 故障类型 |
| **error_data** | `error_data` | Number | 故障内容 |

### 2.4 控制参数对象 (Item in `control_list`)
对应 `0x0F` 下发命令。

| JSON 字段名 | DB 映射字段 | 类型 | 说明 |
| :--- | :--- | :--- | :--- |
| **dev_type** | `dev_type` | Number | 控制设备类型 |
| **dev_addr** | `dev_addr` | Number | 控制设备地址 |
| **loop** | `dev_loop` | Number | 控制设备的回路地址 (复用 dev_loop) |
| **type_l** | `type_l` | Number | 执行方式 |
| **type_h** | `type_h` | Number | 执行内容 |

---

## 3. 后端入库逻辑

后端服务接收到 JSON 后，逻辑简化为：
1.  **遍历 `device_list`**: 为数组中每个对象生成一条 DB 记录。
    *   映射：`dev_type` -> `dev_type`, `dev_addr` -> `dev_addr`, `dev_loop` -> `dev_loop`, `dev_data` -> `dev_data`。
    *   `action_type`: "36上报"。
2.  **遍历 `fault_list`**: 为数组中每个对象生成一条 DB 记录。
    *   映射：`dev_type` -> `dev_type`, `dev_addr` -> `dev_addr`, `dev_loop` -> `dev_loop`, `error_type` -> `error_type`, `error_data` -> `error_data`。
    *   `action_type`: "36上报"。
3.  **遍历 `control_list`**: 为数组中每个对象生成一条 DB 记录。
    *   映射：`dev_type` -> `dev_type`, `dev_addr` -> `dev_addr`, `loop` -> `dev_loop`, `type_l` -> `type_l`, `type_h` -> `type_h`。
    *   `action_type`: "0F下发"。

---

## 4. 参考 JSON 示例

### 4.1 0x36 混合上报 (2个设备状态 + 1个故障)

```json
{
  "ts_ms": 1706428800123,
  "hotel_id": 1001,
  "room_id": "8001",
  "device_id": "dev_001",
  "direction": "上报",
  "cmd_word": "0x36",
  "frame_id": 1001,
  "udp_raw": "3601...",
  "sys_lock_status": 1,
  "report_count": 2,
  "fault_count": 1,
  "device_list": [
    {
      "dev_type": 1,
      "dev_addr": 10,
      "dev_loop": 1,
      "dev_data": 100
    },
    {
      "dev_type": 1,
      "dev_addr": 11,
      "dev_loop": 2,
      "dev_data": 0
    }
  ],
  "fault_list": [
    {
      "dev_type": 1,
      "dev_addr": 10,
      "dev_loop": 1,
      "error_type": 1,
      "error_data": 1
    }
  ]
}
```

### 4.2 0x0F 下发控制 (包含多个控制指令)

```json
{
  "ts_ms": 1706428805000,
  "hotel_id": 1001,
  "room_id": "8001",
  "direction": "下发",
  "cmd_word": "0x0F",
  "frame_id": 1002,
  "udp_raw": "0F...",
  "action_type": 2,
  "control_list": [
    {
      "dev_type": 1,
      "dev_addr": 10,
      "loop": 1,
      "type_l": 0,
      "type_h": 1
    }
  ],
  "details": {
    "full_control_data": "..." 
  }
}
```
