初始代码

This commit is contained in:
hhh
2026-04-02 10:38:23 +08:00
parent d8b4140f50
commit aed67ce1fd
1937 changed files with 447678 additions and 1 deletions

View File

@@ -0,0 +1,955 @@
# 8Multi协议设备接入技术方案
## 一、项目背景
在现有8ADPRO设备接入系统的基础上新增8Multi协议设备的接入支持。需要保持原有8ADPRO协议功能完全不受影响通过扩展现有架构实现新协议的兼容。
## 二、协议对比分析
### 2.1 原8ADPRO协议格式
```
+YAV:设备号,温度,电流,计数1,计数2,模拟1,模拟2,模拟3,模拟4,模拟5,模拟6,模拟7,数字1,数字2,数字3,数字4,数字5,数字6,EEFF
```
- **字段数量**: 19个字段
- **特点**: 简单直接,所有值都是实际物理量
### 2.2 新8Multi协议格式
```
+YAV:id,电流1,电流2,质量1,质量2,温度,湿度,工作停机故障清零,频率1,计数1,频率2,计数2,供电报警软启动停止,从机数据1,从机数据2,触摸屏,EEFF
```
**C格式**: `+YAV:%d,%d,%d,%d,%d,%.1f,%.1f,%d,%d,%d,%d,%d,%d,%d,%d,0,EEFF`
- **字段数量**: 16个字段不含帧头+YAV和帧尾EEFF
- **特点**:
- 包含设备ID字段g_tDevParam.Address
- 电流1/2AI1/AI2范围0-20A需量程转换0-65535映射
- 质量1/2AI3/AI4需量程转换0-65535映射
- 温湿度保留1位小数的实际值
- 4路DI复合状态工作/停机/故障/清零)
- 2路频率+计数
- 2路继电器+2路DO复合状态供电/报警/软启动/停止)
- 485从机数据2路
- 触摸屏数据固定发送0
### 2.3 关键差异点
| 项目 | 8ADPRO | 8Multi |
|------|--------|--------|
| 设备识别 | 第1字段设备号 | 第1字段设备ID |
| 电流采集 | 1路电流实际值 | 2路电流需量程校准 |
| 质量采集 | 无 | 2路质量需量程校准 |
| 温湿度 | 仅温度 | 温度+湿度 |
| 状态位 | 6个独立数字量 | 4个复合状态字段位运算 |
| 计数器 | 2路计数 | 2路频率+计数 |
| 状态上传 | 无 | 2路继电器+2路DO状态 |
| 扩展功能 | 无 | 485从机+触摸屏 |
**说明**8Multi协议的继电器和DO字段为下位机上传的状态不涉及下发控制功能。
## 三、数据库设计方案
### 3.1 设备主表扩展 (device)
**新增字段**:
```sql
ALTER TABLE `device`
ADD COLUMN `protocol_type` ENUM('8ADPRO', '8MULTI') NOT NULL DEFAULT '8ADPRO'
COMMENT '协议类型8ADPRO=原协议8MULTI=新协议根据device_no自动判断>200为8MULTI<=200为8ADPRO' AFTER `device_code`,
ADD COLUMN `current1_range_start` DECIMAL(10,3) DEFAULT 0
COMMENT '电流1量程起点A' AFTER `protocol_type`,
ADD COLUMN `current1_range_end` DECIMAL(10,3) DEFAULT NULL
COMMENT '电流1量程终点A用于0-65535映射8Multi设备必填' AFTER `current1_range_start`,
ADD COLUMN `current2_range_start` DECIMAL(10,3) DEFAULT 0
COMMENT '电流2量程起点A' AFTER `current1_range_end`,
ADD COLUMN `current2_range_end` DECIMAL(10,3) DEFAULT NULL
COMMENT '电流2量程终点A用于0-65535映射8Multi设备必填' AFTER `current2_range_start`,
ADD COLUMN `quality1_range_start` DECIMAL(10,3) DEFAULT 0
COMMENT '质量1量程起点' AFTER `current2_range_end`,
ADD COLUMN `quality1_range_end` DECIMAL(10,3) DEFAULT NULL
COMMENT '质量1量程终点用于0-65535映射8Multi设备必填' AFTER `quality1_range_start`,
ADD COLUMN `quality1_unit` VARCHAR(10) DEFAULT NULL
COMMENT '质量1单位前端配置如kg/g' AFTER `quality1_range_end`,
ADD COLUMN `quality2_range_start` DECIMAL(10,3) DEFAULT 0
COMMENT '质量2量程起点' AFTER `quality1_unit`,
ADD COLUMN `quality2_range_end` DECIMAL(10,3) DEFAULT NULL
COMMENT '质量2量程终点用于0-65535映射8Multi设备必填' AFTER `quality2_range_start`,
ADD COLUMN `quality2_unit` VARCHAR(10) DEFAULT NULL
COMMENT '质量2单位前端配置如kg/g' AFTER `quality2_range_end`,
ADD COLUMN `current_unit` VARCHAR(10) DEFAULT 'A'
COMMENT '电流单位前端配置如A/mA' AFTER `quality2_unit`;
```
**字段说明**:
- `protocol_type`: 区分设备使用的协议类型,根据`device_no`自动判断(>200为8MULTI<=200为8ADPRO
- `current1_range_start` / `current1_range_end`: 电流1量程起点和终点8Multi设备必填
- `current2_range_start` / `current2_range_end`: 电流2量程起点和终点8Multi设备必填
- `quality1_range_start` / `quality1_range_end`: 质量1量程起点和终点8Multi设备必填
- `quality2_range_start` / `quality2_range_end`: 质量2量程起点和终点8Multi设备必填
- `quality1_unit` / `quality2_unit`: 质量单位前端配置如kg/g
- `current_unit`: 电流单位前端配置如A/mA
**协议类型判断规则**:
- `device_no > 200`: 自动设置为8MULTI协议
- `device_no <= 200`: 自动设置为8ADPRO协议
- 同一设备不能在两种协议之间切换
**量程转换公式**:
```
量程范围 = 量程终点 - 量程起点
实际值 = (原始值 / 65535.0) * 量程范围 + 量程起点
```
**设备状态判断**:
- 电流1实际值 >= 2A **且** 电流2实际值 >= 2A设备开启状态与运算
- 其他情况:设备关闭状态
### 3.2 数据表扩展 (device_data)
**新增字段**:
```sql
ALTER TABLE `device_data`
ADD COLUMN `current1_raw` INT UNSIGNED DEFAULT NULL
COMMENT '电流1原始值0-65535' AFTER `current_value`,
ADD COLUMN `current2_raw` INT UNSIGNED DEFAULT NULL
COMMENT '电流2原始值0-65535' AFTER `current1_raw`,
ADD COLUMN `current1_value` DECIMAL(10,3) DEFAULT NULL
COMMENT '电流1实际值A经量程转换' AFTER `current2_raw`,
ADD COLUMN `current2_value` DECIMAL(10,3) DEFAULT NULL
COMMENT '电流2实际值A经量程转换' AFTER `current1_value`,
ADD COLUMN `quality1_raw` INT UNSIGNED DEFAULT NULL
COMMENT '质量1原始值0-65535' AFTER `current2_value`,
ADD COLUMN `quality2_raw` INT UNSIGNED DEFAULT NULL
COMMENT '质量2原始值0-65535' AFTER `quality1_raw`,
ADD COLUMN `quality1_value` DECIMAL(10,3) DEFAULT NULL
COMMENT '质量1实际值kg经量程转换' AFTER `quality2_raw`,
ADD COLUMN `quality2_value` DECIMAL(10,3) DEFAULT NULL
COMMENT '质量2实际值kg经量程转换' AFTER `quality1_value`,
ADD COLUMN `humidity` DECIMAL(10,3) DEFAULT NULL
COMMENT '湿度值(%RH' AFTER `quality2_value`,
ADD COLUMN `status_work` TINYINT(1) DEFAULT NULL
COMMENT '工作状态0=停止1=工作)' AFTER `humidity`,
ADD COLUMN `status_stop` TINYINT(1) DEFAULT NULL
COMMENT '停机状态0=运行1=停机)' AFTER `status_work`,
ADD COLUMN `status_fault` TINYINT(1) DEFAULT NULL
COMMENT '故障状态0=正常1=故障)' AFTER `status_stop`,
ADD COLUMN `status_reset` TINYINT(1) DEFAULT NULL
COMMENT '清零状态0=正常1=清零)' AFTER `status_fault`,
ADD COLUMN `frequency1` INT DEFAULT NULL
COMMENT '频率1原始值' AFTER `status_reset`,
ADD COLUMN `frequency2` INT DEFAULT NULL
COMMENT '频率2原始值' AFTER `frequency1`,
ADD COLUMN `counter1_current` INT DEFAULT NULL
COMMENT '计数1当前累计值下位机传值' AFTER `frequency2`,
ADD COLUMN `counter1_delta` INT DEFAULT NULL
COMMENT '计数1增量值当前值-上次值)' AFTER `counter1_current`,
ADD COLUMN `counter2_current` INT DEFAULT NULL
COMMENT '计数2当前累计值下位机传值' AFTER `counter1_delta`,
ADD COLUMN `counter2_delta` INT DEFAULT NULL
COMMENT '计数2增量值当前值-上次值)' AFTER `counter2_current`,
ADD COLUMN `counter1_total_8multi` BIGINT UNSIGNED DEFAULT NULL
COMMENT '计数1累计总数8Multi专用从清零基准值开始累计' AFTER `counter2_delta`,
ADD COLUMN `counter2_total_8multi` BIGINT UNSIGNED DEFAULT NULL
COMMENT '计数2累计总数8Multi专用从清零基准值开始累计' AFTER `counter1_total_8multi`,
ADD COLUMN `relay_power` TINYINT(1) DEFAULT NULL
COMMENT '继电器-供电状态0=断开1=闭合)' AFTER `counter2_total_8multi`,
ADD COLUMN `relay_alarm` TINYINT(1) DEFAULT NULL
COMMENT '继电器-报警状态0=正常1=报警)' AFTER `relay_power`,
ADD COLUMN `do_soft_start` TINYINT(1) DEFAULT NULL
COMMENT 'DO-软启动0=关1=开)' AFTER `relay_alarm`,
ADD COLUMN `do_stop` TINYINT(1) DEFAULT NULL
COMMENT 'DO-停止0=关1=开)' AFTER `do_soft_start`,
ADD COLUMN `slave_data1` INT DEFAULT NULL
COMMENT '485从机数据1' AFTER `do_stop`,
ADD COLUMN `slave_data2` INT DEFAULT NULL
COMMENT '485从机数据2' AFTER `slave_data1`,
ADD COLUMN `touchscreen_data` INT DEFAULT NULL
COMMENT '触摸屏数据' AFTER `slave_data2`;
```
### 3.3 动态字段配置扩展 (device_field_header_config)
**修改字段枚举**:
```sql
ALTER TABLE `device_field_header_config`
MODIFY COLUMN `field_key` ENUM(
'analog1','analog2','analog3','analog4','analog5','analog6','analog7',
'digital1','digital2','digital3','digital4','digital5','digital6',
'current1','current2','quality1','quality2','humidity',
'frequency1','frequency2','slave_data1','slave_data2','touchscreen_data'
) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL
COMMENT '字段标识支持8ADPRO和8Multi协议字段';
```
### 3.4 计数器字段设计(避免触发器冲突)
**问题**:现有触发器`update_counter_totals_on_insert`处理8ADPRO的`counter1_total`/`counter2_total`字段。
**解决方案**为8Multi添加独立的计数器总计字段不修改触发器
**字段对比**
| 协议 | 当前值字段 | 增量值字段 | 总计字段 | 触发器 |
|------|-----------|-----------|---------|--------|
| 8ADPRO | counter1/counter2 | - | counter1_total/counter2_total | ✅ 使用 |
| 8Multi | counter1_current/counter2_current | counter1_delta/counter2_delta | counter1_total_8multi/counter2_total_8multi | ❌ 不使用 |
**8Multi计数器逻辑**(修订版):
```java
// 1. 获取当前累计值(下位机传值)
int currentCounter1 = parseInt(parts[10]);
// 2. 获取清零基准值baseline
long baseline1 = device.getCounter1Baseline() != null ? device.getCounter1Baseline() : 0L;
// 3. 计算累计值(下位机当前值 - 清零基准值)
long total1 = (long)currentCounter1 - baseline1;
if (total1 < 0) total1 = 0L; // 负值保护
// 4. 计算增量值(当前值 - 上次值)
int delta1 = currentCounter1 - lastCounter1;
if (delta1 < 0) delta1 = 0; // 负值归零(下位机可能重置)
// 5. 存储
deviceData.setCounter1Current(currentCounter1); // 下位机当前累计值
deviceData.setCounter1Delta(delta1); // 本次增量
deviceData.setCounter1Total8multi(total1); // 累计总值(= 下位机值 - baseline
```
**关键设计说明**
- **累计值 = 下位机当前值 - baseline**(不是累加增量!)
- **第一条数据**:累计值 = 下位机当前值因为baseline默认为0
- **清零功能**设置baseline = 当前下位机值累计值重新从0开始
- **优点**:即使下位机重置归零,累计值仍能正确计算
**优点**
- ✅ 不修改现有触发器8ADPRO功能完全不受影响
- ✅ 8Multi使用独立字段逻辑清晰
- ✅ 两种协议完全隔离,互不干扰
## 四、数据解析规则
### 4.1 量程映射转换
**电流/质量原始值转换公式**:
```
实际值 = (原始值 / 65535.0) * 量程
```
**示例**:
- 电流1量程设置为100A
- 接收到原始值32768
- 实际电流1 = (32768 / 65535.0) * 100 = 50.0A
### 4.2 复合状态位解析
#### 4.2.1 DI状态字段解析工作/停机/故障/清零)
```
字段值: U16格式例如 0x004F
解析规则: 取最后一个F低4位然后取反
```
**解析代码示例**:
```java
int diValue = parseInt(parts[8]); // 例如 0x004F
int lastNibble = diValue & 0x0F; // 取最后4位 = 0xF = 15
int inverted = (~lastNibble) & 0x0F; // 取反并保留4位 = 0x0 = 0
// 解析各个DI状态
boolean work = (inverted & 0x01) != 0; // DI1: 工作
boolean stop = (inverted & 0x02) != 0; // DI2: 停机
boolean fault = (inverted & 0x04) != 0; // DI3: 故障
boolean reset = (inverted & 0x08) != 0; // DI4: 清零
```
#### 4.2.2 继电器+DO状态字段解析供电/报警/软启动/停止)
```
字段值: U16格式例如 0x004F
解析规则: 取最后一个F低4位然后取反与DI状态相同
下发格式: DO=0_10为通道号1为值
```
**解析代码示例**:
```java
int doValue = parseInt(parts[12]); // 例如 0x004F
int lastNibble = doValue & 0x0F; // 取最后4位 = 0xF = 15
int inverted = (~lastNibble) & 0x0F; // 取反并保留4位 = 0x0 = 0
// 解析各个继电器和DO状态
boolean power = (inverted & 0x01) != 0; // 继电器1: 供电
boolean alarm = (inverted & 0x02) != 0; // 继电器2: 报警
boolean softStart = (inverted & 0x04) != 0; // DO1: 软启动
boolean stopDo = (inverted & 0x08) != 0; // DO2: 停止
```
**下发控制示例**:
```
DO=0_1 // 通道0供电值为1开启
DO=1_0 // 通道1报警值为0关闭
```
### 4.3 计数器处理逻辑(修订版)
**核心设计原则**:
- 下位机传输的是累计值
- 累计值 = 下位机当前值 - 清零基准值baseline
- 增量值 = 当前值 - 上次值
**完整处理流程**:
```java
// 1. 获取下位机传来的当前累计值
int counter1Current = parseInt(parts[10]); // 计数器1
int counter2Current = parseInt(parts[12]); // 计数器2
// 2. 获取清零基准值(用于计算累计值)
Long baseline1 = device.getCounter1Baseline() != null ? device.getCounter1Baseline() : 0L;
Long baseline2 = device.getCounter2Baseline() != null ? device.getCounter2Baseline() : 0L;
// 3. 计算累计值(显示在前端卡片上的大数字)
Long total1 = (long)counter1Current - baseline1;
Long total2 = (long)counter2Current - baseline2;
if (total1 < 0) total1 = 0L; // 负值保护
if (total2 < 0) total2 = 0L;
// 4. 查询上次累计值(用于计算增量)
DeviceData lastData = selectLastByDeviceId(deviceId);
Integer lastCounter1 = lastData != null ? lastData.getCounter1Current() : 0;
Integer lastCounter2 = lastData != null ? lastData.getCounter2Current() : 0;
// 5. 计算增量值(显示在前端卡片上的小字)
int delta1 = counter1Current - lastCounter1;
int delta2 = counter2Current - lastCounter2;
if (delta1 < 0) delta1 = 0; // 负值归零(下位机可能重置)
if (delta2 < 0) delta2 = 0;
// 6. 存储到数据库
deviceData.setCounter1Current(counter1Current); // 下位机原始值
deviceData.setCounter1Delta(delta1); // 增量
deviceData.setCounter1Total8multi(total1); // 累计值
deviceData.setCounter2Current(counter2Current);
deviceData.setCounter2Delta(delta2);
deviceData.setCounter2Total8multi(total2);
```
**清零功能实现**:
- 前端提供清零按钮
- 点击清零:`UPDATE device SET counter1_baseline = 当前下位机值 WHERE id = ?`
- 清零后:累计值 = 下位机值 - baseline重新从0开始
- 下位机继续传累计值,不受影响
**数据库字段**:
```sql
ALTER TABLE `device`
ADD COLUMN `counter1_baseline` INT DEFAULT 0 COMMENT '计数1基准值清零后的基准',
ADD COLUMN `counter2_baseline` INT DEFAULT 0 COMMENT '计数2基准值清零后的基准',
ADD COLUMN `voltage1` DECIMAL(10,3) DEFAULT NULL COMMENT '电压1配置V用于功率1计算',
ADD COLUMN `voltage2` DECIMAL(10,3) DEFAULT NULL COMMENT '电压2配置V用于功率2计算';
```
**示例场景**:
```
时间线:
下位机值: 100 → 150 → 200 → [清零,baseline=200] → 250 → 300
累计值: 100 → 150 → 200 → 0 → 50 → 100
增量值: 0 → 50 → 50 → 0 → 50 → 50
```
## 五、接口设计方案
### 5.1 数据上报接口(复用现有)
**接口路径**: `POST /equipment/info/ingest/raw`
**请求示例**:
```
+YAV:1001,32768,16384,49152,8192,25.5,65.0,15,5000,100,3000,50,3,1000,2000,0,EEFF
```
**字段映射**:
1. 帧头: +YAV固定
2. id: 1001设备ID对应g_tDevParam.Address
3. 电流1原始值: 32768AI10-65535对应usSRegHoldBuf[0]
4. 电流2原始值: 16384AI20-65535对应usSRegHoldBuf[1]
5. 质量1原始值: 49152AI30-65535对应usSRegHoldBuf[2]
6. 质量2原始值: 8192AI40-65535对应usSRegHoldBuf[3]
7. 温度: 25.5°C保留1位小数
8. 湿度: 65.0%RH保留1位小数
9. DI状态复合: 15工作/停机/故障/清零对应usSRegHoldBuf[DI_REG]
10. 频率1: 5000Hz对应freq1
11. 计数1: 100对应num_count1
12. 频率2: 3000Hz对应freq2
13. 计数2: 50对应num_count2
14. 继电器+DO状态复合: 3供电/报警/软启动/停止对应usSRegHoldBuf[DO_REG]
15. 从机数据1: 1000对应usSRegHoldBuf[DATA_REG_1]
16. 从机数据2: 2000对应usSRegHoldBuf[DATA_REG_1+1]
17. 触摸屏: 0固定发送0
18. 帧尾: EEFF固定
### 5.2 设备配置接口(扩展现有)
**新增量程配置接口**: `PUT /equipment/info/device/range`
**请求参数**:
```json
{
"id": 1,
"current1_range": 100.0,
"current2_range": 50.0,
"quality1_range": 1000.0,
"quality2_range": 500.0,
"calibration_offset": 0.5,
"calibration_factor": 1.02
}
```
**响应**:
```json
{
"code": 200,
"msg": "量程配置成功"
}
```
### 5.3 设备创建接口(扩展现有)
**接口路径**: `POST /equipment/info/device`
**请求参数扩展**:
```json
{
"deviceNo": 1001,
"deviceName": "8Multi设备1",
"protocol_type": "8MULTI",
"current1_range": 100.0,
"current2_range": 50.0,
"quality1_range": 1000.0,
"quality2_range": 500.0,
"image_url": "/profile/upload/device.png",
"headers": {
"current1": "主电流",
"current2": "辅助电流",
"quality1": "主质量",
"quality2": "辅助质量",
"humidity": "环境湿度",
"frequency1": "主频率",
"frequency2": "辅助频率"
}
}
```
## 六、前端界面扩展
### 6.1 设备卡片展示
**8ADPRO设备卡片** (保持不变):
- 温度、电流、功率、状态
- 计数器1、计数器2
**8Multi设备卡片** (新增):
- 温度、湿度
- 电流1、电流2
- 质量1、质量2
- 工作/停机/故障状态指示灯
- 频率1、频率2
- 计数器1、计数器2
### 6.2 设备详情抽屉
**新增8Multi专属字段**:
- 电流1/电流2显示原始值和实际值
- 质量1/质量2显示原始值和实际值
- 湿度
- 工作状态、停机状态、故障状态、清零状态
- 频率1、频率2
- 继电器状态(供电、报警)
- DO状态软启动、停止
- 从机数据1、从机数据2
- 触摸屏数据
### 6.3 设备配置对话框
**新增配置项**:
1. **协议类型选择**: 8ADPRO / 8Multi
2. **量程配置** (仅8Multi显示):
- 电流1量程 (A)
- 电流2量程 (A)
- 质量1量程 (kg)
- 质量2量程 (kg)
3. **校准配置**:
- 校准偏移量
- 校准系数
## 七、实现步骤
### 7.1 数据库变更
1. ✅ 执行device表ALTER语句新增协议类型和量程字段
2. ✅ 执行device_data表ALTER语句新增8Multi专属字段
3. ✅ 修改device_field_header_config表枚举支持新字段
### 7.2 后端开发(已完成)
#### 7.2.1 实体类扩展
1.**MesDevice.java** - 添加17个8Multi字段
```java
// 协议类型、量程起点/终点、单位、计数器基准值、电压1/电压2
private String protocolType;
private BigDecimal current1RangeStart, current1RangeEnd;
private BigDecimal current2RangeStart, current2RangeEnd;
private BigDecimal quality1RangeStart, quality1RangeEnd;
private String quality1Unit, quality2Unit, currentUnit;
private Integer counter1Baseline, counter2Baseline;
private BigDecimal voltage1, voltage2;
// 辅助方法
public boolean is8Multi() { return "8MULTI".equals(this.protocolType); }
public boolean is8ADPRO() { return "8ADPRO".equals(this.protocolType) || this.protocolType == null; }
```
2. ✅ **DeviceData.java** - 添加29个8Multi字段
```java
// 电流/质量原始值和实际值、湿度、状态位、频率、计数器、继电器、DO、从机数据
private Integer current1Raw, current2Raw;
private BigDecimal current1Value, current2Value;
private Integer quality1Raw, quality2Raw;
private BigDecimal quality1Value, quality2Value;
private BigDecimal humidity;
private Integer statusWork, statusStop, statusFault, statusReset;
private Integer frequency1, frequency2;
private Integer counter1Current, counter1Delta, counter2Current, counter2Delta;
private Long counter1Total8multi, counter2Total8multi;
private Integer relayPower, relayAlarm, doSoftStart, doStop;
private Integer slaveData1, slaveData2, touchscreenData;
```
#### 7.2.2 Service层
3. ✅ **Multi8ProtocolService.java** - 8Multi协议解析服务
- `parse8MultiProtocol()` - 协议解析方法
- `convertRangeValue()` - 量程转换方法
- `resetCounter()` - 计数器清零方法
#### 7.2.3 Controller层
4. ✅ **Multi8Controller.java** - 8Multi设备控制器
- `POST /equipment/multi8/resetCounter` - 计数器清零
- `PUT /equipment/multi8/updateDeviceConfig` - 更新设备配置
- `GET /equipment/multi8/getDeviceDetail/{id}` - 获取设备详情
#### 7.2.4 Mapper层
5. ✅ **DeviceDataMapper.java** - 添加方法
```java
DeviceData selectLastByDeviceId(@Param("deviceId") Long deviceId);
```
6. ✅ **MesDeviceMapper.java** - 添加方法
```java
MesDevice selectByDeviceNo(@Param("deviceNo") Integer deviceNo);
```
### 7.3 前端开发(需手动实现)
**文件位置**`e:\Yavii_P3\MES\mes-ui\src\views\mes\equipment\info\index.vue`1178行
**修改原则**
⚠️ **在现有8ADPRO代码基础上扩展不删除任何8ADPRO功能**
⚠️ **通过`v-if`判断协议类型动态渲染不同UI**
⚠️ **所有8Multi字段都要做空值处理**
#### 7.3.1 设备卡片扩展
通过`v-if`判断协议类型动态渲染不同UI
```vue
<!-- 8ADPRO设备卡片保持不变 -->
<div v-if="!d.protocol_type || d.protocol_type === '8ADPRO'" class="device-info">
<!-- 原有字段 -->
</div>
<!-- 8Multi设备卡片新增 -->
<div v-else-if="d.protocol_type === '8MULTI'" class="device-info device-8multi">
<!-- 温度/湿度、电流1/电流2、质量1/质量2、功率1/功率2、状态 -->
</div>
```
#### 7.3.2 设备详情抽屉扩展
添加8Multi字段展示
- 温度、湿度
- 电流1/电流2、质量1/质量2
- 功率1/功率2计算显示
- 频率1/频率2
- 计数器1/计数器2含清零按钮
- 工作/停机/故障状态
- 继电器、DO状态
- 从机数据
#### 7.3.3 设备配置对话框扩展
根据`device_no > 200`动态显示8Multi配置项
- 电流1/电流2量程起点~终点)
- 质量1/质量2量程起点~终点+单位)
- 电流单位
- 电压1/电压2配置
#### 7.3.4 JavaScript方法扩展
```javascript
// 计算功率
calculatePower1(data) {
return data.voltage1 * data.current1_value
}
// 获取状态类型
getStatusType(data) {
if (data.status_fault) return 'danger' // 红色
if (data.status_stop) return 'warning' // 黄色
if (data.status_work) return 'success' // 绿色
}
// 计数器清零
resetCounter(counterNo) {
this.$http.post('/equipment/multi8/resetCounter', {...})
}
```
### 7.4 测试验证
1. 8ADPRO协议回归测试确保不受影响
2. 8Multi协议功能测试
3. 量程转换准确性测试
4. 校准功能测试
5. 混合设备场景测试
## 八、待确认事项
### 8.1 位运算解析规则
- [x] **DI状态字段**已确认U16格式取最后4位F然后取反DI1=工作DI2=停机DI3=故障DI4=清零
- [x] **继电器+DO字段**:已确认,直接读取不取反(下位机上传状态)
### 8.2 校准功能细节
- [x] **校准功能**:已确认不需要校准偏移量和校准系数
### 8.3 状态上传功能
- [x] **继电器+DO状态**:已确认为下位机上传的状态,不涉及下发控制功能
### 8.4 从机和触摸屏数据
- [x] **从机数据展示**已确认从机数据1/2直接展示原始值
- [x] **触摸屏数据**已确认固定发送0
### 8.5 协议格式细节
- [x] **设备ID映射关系**已确认device_no>200为8MULTI<=200为8ADPRO
- [x] **触摸屏固定值**已确认触摸屏字段固定发送0
- [x] **字段顺序确认**:已确认,协议字段顺序完全按照文档描述
### 8.6 量程和单位配置
- [x] **电流量程范围**已确认AI1/AI2电流范围为0-20A
- [x] **质量量程配置**已确认质量1/质量2AI3/AI4需要前端配置量程起点和终点
- [x] **量程转换公式**:已确认,实际值=(原始值/65535)*量程范围+量程起点
- [x] **量程必填**已确认8Multi设备创建时必须强制配置量程
- [x] **量程修改影响**:已确认,量程修改后不需要重新计算已存储的历史数据
- [x] **单位配置**:已确认,质量单位和电流单位由前端配置
### 8.7 计数器处理逻辑
- [x] **计数器数据类型**已确认下位机传的计数1和计数2是累计值
- [x] **计数器处理方式**:已确认,需要做减运算(当前值-上次值),存储累计值和增量值
- [x] **计数器清零**:已确认,前端提供清零按钮,清零后设置基准值,增量=当前值-基准值
- [x] **频率显示**已确认频率1和频率2显示原始值
### 8.8 数据上报和存储
- [x] **上报间隔**已确认8Multi设备上报频率为10秒
- [x] **数据去重**:已确认,短时间内收到相同数据全部存储
- [x] **离线缓存**:已确认,不需要关注离线缓存补发,由下位机处理
### 8.9 设备状态判断
- [x] **运行判断依据**已确认电流1实际值>=2A **且** 电流2实际值>=2A与运算
- [x] **功率计算规则**已确认需要计算功率前端配置电压1和电压2功率1=电压1*电流1功率2=电压2*电流2分别计算
- [x] **状态指示灯颜色**:已确认,工作=绿色,停机=黄色,故障=红色,报警=红色
### 8.10 前端展示规范
- [x] **原始值显示**:已确认,前端只显示实际值,不显示原始值
- [x] **历史数据图表**:已确认,先不做历史数据图表
### 8.11 数据有效性校验
- [x] **数据校验**:已确认,不需要数据有效性校验
### 8.12 权限和安全
- [x] **数据加密传输**:已确认,设备上报的数据不需要加密传输
### 8.13 兼容性和迁移
- [x] **协议切换**已确认同一设备不能在8ADPRO和8Multi之间切换协议
- [x] **数据迁移工具**:已确认,不需要提供数据迁移工具
- [x] **8ADPRO兼容性**已确认千万不要影响8ADPRO的功能
### 待确认事项汇总
**已确认事项**共34项
- ✅ 所有核心功能已确认
- ✅ 协议解析规则已明确
- ✅ 数据库设计已完成
- ✅ 量程配置规则已确定
- ✅ 计数器处理逻辑已明确
- ✅ 兼容性要求已明确
- ✅ 功率计算规则已明确(分别计算)
- ✅ 前端展示规范已明确(只显示实际值)
- ✅ 数据安全要求已明确(不需要加密)
- ✅ 离线缓存策略已明确(不需要关注)
**待确认事项**共0项
- 🎉 所有需求已确认完毕!
**核心要求**
- ⚠️ **千万不要影响8ADPRO的功能**
- ⚠️ **device_no>200为8MULTI<=200为8ADPRO**
- ⚠️ **同一设备不能在两种协议之间切换**
## 九、8ADPRO设备相关文件清单
**说明**以下仅列出与8ADPRO设备数据接收、解析、存储、展示相关的核心文件不包括其他IoT功能如点检、维修、车间设备等
### 9.1 后端文件Java
#### 9.1.1 Controller层
```
e:\Yavii_P3\MES\yjh-mes\src\main\java\cn\sourceplan\equipment\controller\
└── EquipmentInfoController.java # 设备信息控制器(核心:数据接收、动态表头、清零)
- ingestRawData() # 数据接收接口
- getDynamicHeaders() # 动态表头接口
- getDeviceDataPage() # 设备数据查询接口
- resetCounter() # 计数器清零接口
```
#### 9.1.2 Service层
```
e:\Yavii_P3\MES\yjh-mes\src\main\java\cn\sourceplan\equipment\service\
├── IEquipmentInfoService.java # 设备信息服务接口
└── impl\
└── EquipmentInfoServiceImpl.java # 设备信息服务实现(核心:协议解析、数据存储)
- ingestFrame() # 协议解析方法需扩展支持8Multi
- parseProtocolData() # 数据解析逻辑
- saveDeviceData() # 数据存储逻辑
- updateCounter() # 计数器累加逻辑
- mergeDynamicHeaders() # 动态表头合并逻辑
```
#### 9.1.3 Domain层实体类
```
e:\Yavii_P3\MES\yjh-mes\src\main\java\cn\sourceplan\equipment\domain\
├── MesDevice.java # 设备主表实体需添加8Multi协议字段
├── DeviceData.java # 设备数据实体需添加8Multi数据字段
├── DeviceLatest.java # 设备最新数据实体
├── DeviceLatestView.java # 设备最新数据视图实体
└── DeviceFieldHeaderConfig.java # 设备字段表头配置实体
```
#### 9.1.4 Mapper层
```
e:\Yavii_P3\MES\yjh-mes\src\main\java\cn\sourceplan\equipment\mapper\
├── MesDeviceMapper.java # 设备主表Mapper
├── DeviceDataMapper.java # 设备数据Mapper
├── DeviceLatestMapper.java # 设备最新数据Mapper
├── DeviceLatestViewMapper.java # 设备最新数据视图Mapper
├── DeviceLatestJoinMapper.java # 设备最新数据关联Mapper
└── DeviceFieldHeaderConfigMapper.java # 设备字段表头配置Mapper
```
#### 9.1.5 Mapper XML文件
```
e:\Yavii_P3\MES\yjh-mes\src\main\resources\mapper\equipment\
└── (对应Mapper的XML文件需要添加8Multi字段的SQL映射)
```
### 9.2 前端文件Vue
```
e:\Yavii_P3\MES\mes-ui\src\views\mes\equipment\info\
└── index.vue # 设备信息页面(核心:实时数据监控、动态表头、清零)
- 设备卡片展示需扩展8Multi设备卡片
- 设备详情抽屉需添加8Multi字段
- 设备配置对话框(需添加量程、单位、电压配置)
- 动态表头渲染
- 实时数据刷新
- 计数器清零按钮
- 功率计算显示
```
### 9.3 核心文件修改要点
**8Multi接入需要修改的5个核心文件**
1. **EquipmentInfoController.java**
- 数据接收接口保持不变
- 可能需要添加设备配置更新接口(量程、单位、电压)
2. **EquipmentInfoServiceImpl.java**
- `ingestFrame()`方法添加协议类型判断device_no>200为8Multi
- 新增8Multi协议解析分支
- 实现量程转换逻辑
- 实现计数器减运算逻辑
- 实现功率计算逻辑
3. **MesDevice.java**
- 添加17个新字段协议类型、量程起点/终点、单位、计数器基准值、电压1/电压2
4. **DeviceData.java**
- 添加29个新字段8Multi协议数据字段含counter1_total_8multi/counter2_total_8multi
5. **info/index.vue**
- 根据协议类型渲染不同的设备卡片
- 设备详情抽屉支持8Multi字段展示
- 设备配置对话框添加量程、单位、电压1/电压2配置
- 功率计算显示功率1=电压1*电流1功率2=电压2*电流2
### 9.4 数据库表
**核心表**
- `device`设备主表新增17个字段
- `device_data`设备数据表新增29个字段含8Multi专用计数器总计字段
- `device_latest`:设备最新数据表(视图或实体表)
- `device_field_header_config`:设备字段表头配置表
## 十、兼容性保证
### 10.1 数据库兼容
- 所有新增字段均为可空或有默认值
- 原有8ADPRO设备的protocol_type默认为'8ADPRO'
- 原有字段不做任何修改
### 10.2 代码兼容
- 通过protocol_type字段区分处理逻辑
- 8ADPRO协议解析逻辑完全保留
- 新增8Multi协议解析分支
### 10.3 前端兼容
- 根据设备协议类型动态渲染UI
- 8ADPRO设备展示保持不变
- 新增8Multi设备专属UI组件
## 十一、附录
### 11.1 8Multi协议字段详细对照表
| 序号 | 字段名 | 描述 | 数据类型 | 对应C变量 | 转换规则 |
|------|--------|------|---------|-----------|----------|
| 1 | +YAV: | 帧头 | String | 固定 | 固定发送+YAV: |
| 2 | id | 设备ID | int | g_tDevParam.Address | 设备唯一标识 |
| 3 | 电流1 | 模拟输入AI1 | int(0-65535) | usSRegHoldBuf[0] | 范围0-20A<br>实际值=(原始值/65535)*量程范围+量程起点<br>实际值>=2A为设备开启 |
| 4 | 电流2 | 模拟输入AI2 | int(0-65535) | usSRegHoldBuf[1] | 范围0-20A<br>实际值=(原始值/65535)*量程范围+量程起点 |
| 5 | 质量1 | 模拟输入AI3 | int(0-65535) | usSRegHoldBuf[2] | 实际值=(原始值/65535)*量程范围+量程起点<br>前端配置量程 |
| 6 | 质量2 | 模拟输入AI4 | int(0-65535) | usSRegHoldBuf[3] | 实际值=(原始值/65535)*量程范围+量程起点<br>前端配置量程 |
| 7 | 温度 | 温湿度传感器温度 | String | temp | 保留1位小数 |
| 8 | 湿度 | 温湿度传感器湿度 | String | dht | 保留1位小数 |
| 9 | DI状态 | 工作/停机/故障/清零 | int | usSRegHoldBuf[DI_REG] | U16格式取最后4位F然后取反<br>DI1=工作DI2=停机DI3=故障DI4=清零 |
| 10 | 频率1 | 测频器1 | String | freq1 | 实际值 |
| 11 | 计数1 | 计数器1 | int | num_count1 | 下位机传累计值 |
| 12 | 频率2 | 测频器2 | String | freq2 | 实际值 |
| 13 | 计数2 | 计数器2 | int | num_count2 | 下位机传累计值 |
| 14 | 继电器+DO | 供电/报警/软启动/停止 | int | usSRegHoldBuf[DO_REG] | 直接读取,不取反<br>下发格式: DO=0_10为通道号1为值 |
| 15 | 从机数据1 | 485从机数据1 | int | usSRegHoldBuf[DATA_REG_1] | 实际值 |
| 16 | 从机数据2 | 485从机数据2 | int | usSRegHoldBuf[DATA_REG_1+1] | 实际值 |
| 17 | 触摸屏 | 触摸屏数据 | int | 固定 | 固定发送0 |
| 18 | EEFF | 帧尾 | String | 固定 | 固定发送EEFF |
### 11.2 量程配置示例
| 设备类型 | 电流1量程 | 电流2量程 | 质量1量程 | 质量2量程 |
|---------|----------|----------|----------|----------|
| 小型设备 | 50A | 30A | 500kg | 200kg |
| 中型设备 | 100A | 80A | 1000kg | 500kg |
| 大型设备 | 200A | 150A | 2000kg | 1000kg |
---
**文档版本**: v2.1
**创建日期**: 2025-11-15
**创建人**: 周启威
**最后更新**: 2025-11-15
**更新内容**:
- v1.1: 补充待确认事项8.5-8.13,新增优先级分类
- v1.2: 根据协议详细表更新字段对照表明确C变量对应关系更新已确认事项
- v1.3: 重大更新
- 修改数据库设计:量程字段拆分为起点和终点(支持非零起点)
- 更新量程转换公式:实际值=(原始值/65535)*量程范围+量程起点
- 明确DI状态解析U16格式取最后4位F然后取反
- 明确继电器+DO解析直接读取不取反下发格式DO=通道号_值
- 明确设备开启判断电流1实际值>=2A
- 明确计数器类型:下位机传累计值
- 更新协议字段对照表,添加详细转换规则
- v2.0: 完整需求确认版本30项已确认
- 移除校准功能:不需要校准偏移量和校准系数
- 添加单位配置:质量单位和电流单位前端配置
- 协议判断规则device_no>200为8MULTI<=200为8ADPRO
- 设备状态判断电流1>=2A且电流2>=2A与运算
- 计数器处理:减运算+清零功能(存储累计值和增量值)
- 频率显示:显示原始值
- 从机数据:直接展示原始值
- 数据上报10秒间隔相同数据全部存储
- 权限管理:量程配置和下发控制需要权限
- 状态指示灯:工作=绿,停机=黄,故障=红,报警=红
- 兼容性不能切换协议不影响8ADPRO功能
- 新增计数器基准值字段和单位字段
- v2.1: 功能调整
- 移除下发控制功能继电器和DO字段改为下位机上传状态不涉及下发控制
- 移除权限管理相关需求
- 新增8ADPRO现有文件清单章节第九章
- 列出所有后端Java文件Controller、Service、Domain、Mapper、XML
- 列出所有前端Vue文件
- 标注核心文件和修改要点
- 新增功率计算功能前端配置电压1和电压2功率1=电压1*电流1功率2=电压2*电流2分别计算
- device表新增voltage1和voltage2字段共17个新字段
- 精简文件清单只列出8ADPRO设备相关文件不包括其他IoT功能
- 确认所有待确认事项:离线缓存、原始值显示、数据加密传输
- 🎉 所有34项需求已确认完毕可以开始开发
- v2.2: 代码实现完成
- ✅ 完成所有后端代码实体类、Service、Controller、Mapper
- ✅ 添加8Multi协议解析服务
- ✅ 添加设备控制器接口
- ✅ 扩展Mapper查询方法
- 📝 前端代码待实现(已提供详细说明)
## 十三、代码文件清单
### 后端文件
#### 1. 实体类2个已完成
- ✅ `MesDevice.java` - 添加17个8Multi字段
- ✅ `DeviceData.java` - 添加29个8Multi字段
#### 2. Service层1个新建 + 1个需集成
- ✅ `Multi8ProtocolService.java` - 8Multi协议解析服务新建
- ⚠️ `EquipmentInfoServiceImpl.java` - 需要集成8Multi协议判断
- 参考文档:`后端集成说明_EquipmentInfoServiceImpl.md`
- 修改点:
1. 注入Multi8ProtocolService
2. 在ingestFrame方法开头添加协议判断
3. deviceNo > 200 调用8Multi解析
#### 3. Controller层1个新建
- ✅ `Multi8Controller.java` - 8Multi设备控制器新建
#### 4. Mapper层2个已扩展
- ✅ `DeviceDataMapper.java` - 添加`selectLastByDeviceId()`方法
- ✅ `MesDeviceMapper.java` - 添加`selectByDeviceNo()`方法
#### 5. Mapper XML
- ✅ 不需要XML文件使用MyBatis-Plus注解方式
### 前端文件(待实现)
#### 1. 设备信息页面1个扩展
- `e:\Yavii_P3\MES\mes-ui\src\views\mes\equipment\info\index.vue`
- 扩展设备卡片(协议类型判断)
- 扩展详情抽屉8Multi字段展示
- 扩展配置对话框(量程、单位、电压配置)
- 添加JavaScript方法功率计算、状态判断、计数器清零
### 数据库文件
#### 1. SQL脚本1个
- `e:\Yavii_P3\MES\.tasks\2025-11-15_01_周启威_8Multi接入.sql`
- device表新增17个字段
- device_data表新增29个字段
- 不修改触发器(使用独立字段)
## 十四、后续工作
### 待完成
1. 前端代码实现参考第7.3节)
2. 集成测试
3. 8ADPRO回归测试
### 注意事项
⚠️ **千万不要影响8ADPRO的功能**
⚠️ **所有修改都要通过协议类型判断**
⚠️ **前端要在现有代码基础上扩展不要删除任何8ADPRO代码**