# PRD 需求优化文档 — 中控设备多类型主题上报

> **文档类型**: PRD 需求优化文档
> **创建日期**: 2026-08-06
> **作者**: czj
> **优先级**: P1
> **状态**: 待评审
> **关联文档**: `_PRD_需求文档_设备模拟模块.md`、`_执行计划_中控设备多类型主题上报.md`

---

## 一、需求背景

### 1.1 当前问题

中控设备模拟器当前仅实现一种主题上报格式（会议室环境监测），但在实际 IoT 场景中，中控设备需要根据不同的业务场景上报不同类型的主题消息。当前实现存在以下问题：

#### 问题一：主题类型单一

当前 `central_simulator.py` 仅支持一种主题上报：
- **订阅主题**：`/maintain/room/master/{会议室编号}/`
- **发布主题**：`/maintain/room/master/client/`
- **消息体**：固定的环境监测数据格式

无法满足中控设备在不同场景下的多种上报需求。

#### 问题二：参数绑定不灵活

当前会议室编号、设备编号通过 Excel 导入固定绑定到 `topic_params`，但不同主题类型的消息体中 `client_udid` 来源不同：
- **会议室在线**、**设备在线**：使用会议室编号
- **音频/视频/控制/网络/电源系统**：使用设备编号

#### 问题三：无法切换上报类型

用户无法在运行时切换中控设备的上报主题类型，必须重新创建设备才能更改。

**相关文件：**

| 文件 | 行号 | 问题 |
|------|------|------|
| `backend/app/simulators/central_simulator.py` | L130-166 | 仅支持一种消息体格式 |
| `backend/app/simulators/topic_templates.py` | L179-195 | 仅定义一种中控主题 |
| `backend/app/services/device_sim_service.py` | L575-584 | Excel 导入不支持设备类型参数 |
| `backend/app/routers/device_sim.py` | L274-285 | Excel 模板不支持设备类型列 |

### 1.2 目标用户

| 用户角色 | 使用场景 | 核心需求 |
|---------|---------|---------|
| 测试工程师 | 批量导入中控设备 | 通过 Excel 快速配置中控设备类型，无需逐个手动创建 |
| 测试工程师 | 验证不同主题上报 | 随时切换中控设备上报主题类型，测试不同业务场景 |
| 开发工程师 | 调试中控接入逻辑 | 查看不同主题类型的消息体格式是否符合预期 |

### 1.3 需求目标

1. **多主题类型支持**：中控设备支持 7 种主题类型上报，覆盖会议室在线、设备在线、音频/视频/控制/网络/电源系统
2. **Excel 批量配置**：通过 Excel 导入时指定设备类型，一次性完成批量配置
3. **界面动态切换**：设备启动后可在界面上切换上报类型，实时生效
4. **消息体格式规范**：每种类型有独立的消息体格式，自动填充模拟数据

---

## 二、功能需求

### 2.1 中控设备主题类型定义

#### 2.1.1 主题类型列表

| 类型编号 | 类型名称 | 订阅主题 | 发布主题 | action | client_udid 来源 |
|---------|---------|---------|---------|--------|------------------|
| 1 | 会议室在线 | `/maintain/room/master/{会议室编号}/` | `/maintain/room/online/{会议室编号}/` | `online` | -（使用 udid） |
| 2 | 设备在线 | `/maintain/room/master/{会议室编号}/` | `/maintain/room/master/client/` | `_updatestatus` | 会议室编号 |
| 3 | 音频系统 | `/maintain/room/master/{会议室编号}/` | `/maintain/room/master/client/` | `_updateaudio` | 设备编号 |
| 4 | 视频系统 | `/maintain/room/master/{会议室编号}/` | `/maintain/room/master/client/` | `_updatevideo` | 设备编号 |
| 5 | 控制系统 | `/maintain/room/master/{会议室编号}/` | `/maintain/room/master/client/` | `_updatecontrol` | 设备编号 |
| 6 | 网络系统 | `/maintain/room/master/{会议室编号}/` | `/maintain/room/master/client/` | `_updatenetwork` | 设备编号 |
| 7 | 电源系统 | `/maintain/room/master/{会议室编号}/` | `/maintain/room/master/client/` | `_updatepower` | 设备编号 |

#### 2.1.2 消息体格式定义

**类型 1：会议室在线**
```json
{
  "udid": "76db1b46-8baa-51e5-8a42-0b6f78df8c46",
  "action": "online",
  "value": 1
}
```

**类型 2：设备在线**
```json
{
  "action": "_updatestatus",
  "client_udid": "{会议室编号}",
  "data": [
    {"device_udid": "{设备编号}", "power": 1, "online": 1, "watt": 10000, "run": "在线"},
    {"device_udid": "{设备编号}", "power": 1, "online": 1, "watt": 1000, "run": "在线"}
  ]
}
```

**类型 3：音频系统**
```json
{
  "action": "_updateaudio",
  "client_udid": "{设备编号}",
  "data": [
    {
      "address": 1,
      "data_all": {"volume": 30, "mute": 0},
      "data_channel": [
        {"lineType": 1, "num": 1, "status": 1, "volume": 60, "mute": 0},
        {"lineType": 1, "num": 2, "status": 1, "volume": 60, "mute": 0}
      ],
      "data_meter": [{"lineType": 1, "num": 1, "dbvalue": 70}]
    }
  ]
}
```

**类型 4：视频系统**
```json
{
  "action": "_updatevideo",
  "client_udid": "{设备编号}",
  "data": [
    {
      "address": 1,
      "data_channel": [
        {"lineType": 1, "num": 1, "status": 0},
        {"lineType": 1, "num": 2, "status": 0}
      ]
    }
  ]
}
```

**类型 5：控制系统**
```json
{
  "action": "_updatecontrol",
  "client_udid": "{设备编号}",
  "data": [
    {
      "address": 1,
      "data_com": [{"lineType": 0, "num": 1, "status": 1, "run": "run sucess"}],
      "data_ir": [{"lineType": 1, "num": 1, "status": 1, "run": "run sucess"}],
      "data_io": [{"lineType": 2, "num": 1, "status": 1, "run": "run sucess"}],
      "data_rel": [{"lineType": 3, "num": 1, "status": 1, "run": "run sucess"}],
      "data_bus": [{"lineType": 4, "num": 1, "status": 1, "run": "run sucess"}],
      "data_net": [{"lineType": 5, "num": 1, "status": 1, "run": "run sucess"}]
    }
  ]
}
```

**类型 6：网络系统**
```json
{
  "action": "_updatenetwork",
  "client_udid": "{设备编号}",
  "data": [
    {
      "address": 1,
      "data_channel": [
        {"innum": 1, "status": 1, "run": "Good network"},
        {"innum": 2, "status": 1, "run": "Good network"}
      ]
    }
  ]
}
```

**类型 7：电源系统**
```json
{
  "action": "_updatepower",
  "client_udid": "{设备编号}",
  "data": [
    {
      "address": 1,
      "data_channel": [
        {"innum": 1, "status": 1, "power": 1, "level": 1.1},
        {"innum": 2, "status": 1, "power": 1, "level": 1.1}
      ]
    }
  ]
}
```

### 2.2 Excel 批量导入优化

#### 2.2.1 Excel 模板新增列

| 列 | 表头 | 必填 | 说明 |
|----|------|------|------|
| A | 环境配置名称 | 是 | 需与已创建的环境配置名称一致 |
| B | 设备名称 | 是 | |
| C | 设备编号 | 是 | 原列名"设备ID" |
| D | 会议室编号 | 是 | 用于订阅主题和部分类型的 client_udid |
| E | 设备类型 | 是 | 会议室在线/设备在线/音频系统/视频系统/控制系统/网络系统/电源系统 |
| F | 自动重连 | 否 | 默认 true |
| G | 启用定时上报 | 否 | 默认 true |
| H | 上报间隔(秒) | 否 | 默认 30 |

#### 2.2.2 导入逻辑

1. 解析"设备类型"列，转换为类型编号（1-7）
2. 将设备类型存入 `topic_params.device_type`
3. 将会议室编号存入 `topic_params.room_id`
4. 将设备编号存入 `topic_params.device_number`
5. 根据设备类型选择对应的主题模板

### 2.3 界面动态切换

#### 2.3.1 设备列表新增操作

在设备列表的"操作"列新增下拉框：

```
[设备类型 ▼]
├── 会议室在线
├── 设备在线
├── 音频系统
├── 视频系统
├── 控制系统
├── 网络系统
└── 电源系统
```

#### 2.3.2 切换逻辑

1. 用户选择新的设备类型
2. 前端调用 `PATCH /api/device-sim/devices/{device_id}` 更新 `topic_params.device_type`
3. 如果设备正在运行：
   - 停止当前设备
   - 更新配置
   - 重新启动设备
4. 如果设备未运行：
   - 仅更新配置，下次启动时生效

### 2.4 主题模板扩展

#### 2.4.1 新增主题模板定义

在 `topic_templates.py` 中为中控设备定义 7 种主题模板：

```python
"central": [
    # 会议室在线
    {
        "key": "room_online",
        "template_subscribe": "/maintain/room/master/{room_id}/",
        "template_publish": "/maintain/room/online/{room_id}/",
        "label": "会议室在线",
        "device_type": "room_online",
        ...
    },
    # 设备在线
    {
        "key": "device_online",
        "template_subscribe": "/maintain/room/master/{room_id}/",
        "template_publish": "/maintain/room/master/client/",
        "label": "设备在线",
        "device_type": "device_online",
        ...
    },
    # ... 其他 5 种类型
]
```

---

## 三、技术方案

### 3.1 后端改动

#### 3.1.1 数据模型

无需修改数据库结构，复用现有 `topic_params` JSON 字段：

```json
{
  "room_id": "A101",
  "device_number": "central_001",
  "device_type": "audio"  // 新增字段：room_online/device_online/audio/video/control/network/power
}
```

#### 3.1.2 模拟器改动

`CentralSimulator` 类新增方法：

| 方法 | 说明 |
|------|------|
| `build_room_online_payload()` | 构建会议室在线消息体 |
| `build_device_online_payload()` | 构建设备在线消息体 |
| `build_audio_payload()` | 构建音频系统消息体 |
| `build_video_payload()` | 构建视频系统消息体 |
| `build_control_payload()` | 构建控制系统消息体 |
| `build_network_payload()` | 构建网络系统消息体 |
| `build_power_payload()` | 构建电源系统消息体 |

根据 `topic_params.device_type` 动态选择调用方法。

#### 3.1.3 API 改动

| API | 改动 |
|-----|------|
| `GET /api/device-sim/devices/import/template` | Excel 模板新增"设备类型"列 |
| `POST /api/device-sim/devices/import` | 解析"设备类型"列，存入 topic_params |
| `PATCH /api/device-sim/devices/{device_id}` | 支持更新 topic_params.device_type |

### 3.2 前端改动

#### 3.2.1 Excel 导入弹窗

- 新增"设备类型"列说明
- 更新模板下载逻辑

#### 3.2.2 设备列表

- 新增"设备类型"显示列
- 新增"切换类型"下拉操作

---

## 四、非功能需求

### 4.1 性能要求

- Excel 导入 1000 台设备耗时 < 5s
- 切换设备类型响应时间 < 500ms
- 设备重启时间 < 3s

### 4.2 兼容性要求

- 向后兼容：已创建的中控设备默认为"设备在线"类型
- Excel 模板兼容：支持旧版模板（缺少"设备类型"列时默认为"设备在线"）

### 4.3 可扩展性

- 支持后续新增主题类型，无需修改数据库结构

---

## 五、验收标准

### 5.1 功能验收

| 编号 | 验收项 | 预期结果 |
|------|--------|---------|
| F01 | Excel 导入中控设备（指定设备类型） | 成功导入，topic_params 包含正确的 device_type |
| F02 | 设备列表显示设备类型 | 正确显示中文名称（如"音频系统"） |
| F03 | 运行中切换设备类型 | 设备重启，新消息体格式生效 |
| F04 | 未运行时切换设备类型 | 配置更新成功，下次启动生效 |
| F05 | 查看上报日志 | 消息体格式符合对应类型定义 |

### 5.2 边界验收

| 编号 | 边界场景 | 预期结果 |
|------|---------|---------|
| B01 | Excel 缺少"设备类型"列 | 默认为"设备在线"类型 |
| B02 | 设备类型填写错误值 | 导入失败，提示正确选项 |
| B03 | 切换类型时设备异常 | 回滚到原类型，提示错误信息 |

---

## 六、附录

### 6.1 参考文档

- 中控设备主题说明（用户提供）
- `_PRD_需求文档_设备模拟模块.md`

### 6.2 术语说明

| 术语 | 说明 |
|------|------|
| 会议室编号 | 用于订阅主题 `{room_id}` 占位符 |
| 设备编号 | 用于消息体 `client_udid`（部分类型） |
| 设备类型 | 中控设备的上报主题类型（7 种之一） |

---

*文档结束*