39 KiB
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/2:AI1/AI2,范围0-20A,需量程转换(0-65535映射)
- 质量1/2:AI3/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)
新增字段:
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)
新增字段:
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)
修改字段枚举:
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计数器逻辑(修订版):
// 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位),然后取反
解析代码示例:
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_1(0为通道号,1为值)
解析代码示例:
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)
- 增量值 = 当前值 - 上次值
完整处理流程:
// 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开始
- 下位机继续传累计值,不受影响
数据库字段:
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
字段映射:
- 帧头: +YAV(固定)
- id: 1001(设备ID,对应g_tDevParam.Address)
- 电流1原始值: 32768(AI1,0-65535,对应usSRegHoldBuf[0])
- 电流2原始值: 16384(AI2,0-65535,对应usSRegHoldBuf[1])
- 质量1原始值: 49152(AI3,0-65535,对应usSRegHoldBuf[2])
- 质量2原始值: 8192(AI4,0-65535,对应usSRegHoldBuf[3])
- 温度: 25.5°C(保留1位小数)
- 湿度: 65.0%RH(保留1位小数)
- DI状态复合: 15(工作/停机/故障/清零,对应usSRegHoldBuf[DI_REG])
- 频率1: 5000Hz(对应freq1)
- 计数1: 100(对应num_count1)
- 频率2: 3000Hz(对应freq2)
- 计数2: 50(对应num_count2)
- 继电器+DO状态复合: 3(供电/报警/软启动/停止,对应usSRegHoldBuf[DO_REG])
- 从机数据1: 1000(对应usSRegHoldBuf[DATA_REG_1])
- 从机数据2: 2000(对应usSRegHoldBuf[DATA_REG_1+1])
- 触摸屏: 0(固定发送0)
- 帧尾: EEFF(固定)
5.2 设备配置接口(扩展现有)
新增量程配置接口: PUT /equipment/info/device/range
请求参数:
{
"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
}
响应:
{
"code": 200,
"msg": "量程配置成功"
}
5.3 设备创建接口(扩展现有)
接口路径: POST /equipment/info/device
请求参数扩展:
{
"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 设备配置对话框
新增配置项:
- 协议类型选择: 8ADPRO / 8Multi
- 量程配置 (仅8Multi显示):
- 电流1量程 (A)
- 电流2量程 (A)
- 质量1量程 (kg)
- 质量2量程 (kg)
- 校准配置:
- 校准偏移量
- 校准系数
七、实现步骤
7.1 数据库变更
- ✅ 执行device表ALTER语句,新增协议类型和量程字段
- ✅ 执行device_data表ALTER语句,新增8Multi专属字段
- ✅ 修改device_field_header_config表枚举,支持新字段
7.2 后端开发(已完成)
7.2.1 实体类扩展
-
✅ MesDevice.java - 添加17个8Multi字段
// 协议类型、量程起点/终点、单位、计数器基准值、电压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; } -
✅ DeviceData.java - 添加29个8Multi字段
// 电流/质量原始值和实际值、湿度、状态位、频率、计数器、继电器、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层
- ✅ Multi8ProtocolService.java - 8Multi协议解析服务
parse8MultiProtocol()- 协议解析方法convertRangeValue()- 量程转换方法resetCounter()- 计数器清零方法
7.2.3 Controller层
- ✅ Multi8Controller.java - 8Multi设备控制器
POST /equipment/multi8/resetCounter- 计数器清零PUT /equipment/multi8/updateDeviceConfig- 更新设备配置GET /equipment/multi8/getDeviceDetail/{id}- 获取设备详情
7.2.4 Mapper层
-
✅ DeviceDataMapper.java - 添加方法
DeviceData selectLastByDeviceId(@Param("deviceId") Long deviceId); -
✅ MesDeviceMapper.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:
<!-- 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方法扩展
// 计算功率
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 测试验证
- 8ADPRO协议回归测试(确保不受影响)
- 8Multi协议功能测试
- 量程转换准确性测试
- 校准功能测试
- 混合设备场景测试
八、待确认事项
8.1 位运算解析规则
- DI状态字段:已确认,U16格式取最后4位F然后取反,DI1=工作,DI2=停机,DI3=故障,DI4=清零
- 继电器+DO字段:已确认,直接读取不取反(下位机上传状态)
8.2 校准功能细节
- 校准功能:已确认不需要校准偏移量和校准系数
8.3 状态上传功能
- 继电器+DO状态:已确认为下位机上传的状态,不涉及下发控制功能
8.4 从机和触摸屏数据
- 从机数据展示:已确认,从机数据1/2直接展示原始值
- 触摸屏数据:已确认固定发送0
8.5 协议格式细节
- 设备ID映射关系:已确认,device_no>200为8MULTI,<=200为8ADPRO
- 触摸屏固定值:已确认,触摸屏字段固定发送0
- 字段顺序确认:已确认,协议字段顺序完全按照文档描述
8.6 量程和单位配置
- 电流量程范围:已确认,AI1/AI2电流范围为0-20A
- 质量量程配置:已确认,质量1/质量2(AI3/AI4)需要前端配置量程起点和终点
- 量程转换公式:已确认,实际值=(原始值/65535)*量程范围+量程起点
- 量程必填:已确认,8Multi设备创建时必须强制配置量程
- 量程修改影响:已确认,量程修改后不需要重新计算已存储的历史数据
- 单位配置:已确认,质量单位和电流单位由前端配置
8.7 计数器处理逻辑
- 计数器数据类型:已确认,下位机传的计数1和计数2是累计值
- 计数器处理方式:已确认,需要做减运算(当前值-上次值),存储累计值和增量值
- 计数器清零:已确认,前端提供清零按钮,清零后设置基准值,增量=当前值-基准值
- 频率显示:已确认,频率1和频率2显示原始值
8.8 数据上报和存储
- 上报间隔:已确认,8Multi设备上报频率为10秒
- 数据去重:已确认,短时间内收到相同数据全部存储
- 离线缓存:已确认,不需要关注离线缓存补发,由下位机处理
8.9 设备状态判断
- 运行判断依据:已确认,电流1实际值>=2A 且 电流2实际值>=2A(与运算)
- 功率计算规则:已确认需要计算功率,前端配置电压1和电压2,功率1=电压1电流1,功率2=电压2电流2(分别计算)
- 状态指示灯颜色:已确认,工作=绿色,停机=黄色,故障=红色,报警=红色
8.10 前端展示规范
- 原始值显示:已确认,前端只显示实际值,不显示原始值
- 历史数据图表:已确认,先不做历史数据图表
8.11 数据有效性校验
- 数据校验:已确认,不需要数据有效性校验
8.12 权限和安全
- 数据加密传输:已确认,设备上报的数据不需要加密传输
8.13 兼容性和迁移
- 协议切换:已确认,同一设备不能在8ADPRO和8Multi之间切换协议
- 数据迁移工具:已确认,不需要提供数据迁移工具
- 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个核心文件:
-
EquipmentInfoController.java
- 数据接收接口保持不变
- 可能需要添加设备配置更新接口(量程、单位、电压)
-
EquipmentInfoServiceImpl.java
ingestFrame()方法:添加协议类型判断(device_no>200为8Multi)- 新增8Multi协议解析分支
- 实现量程转换逻辑
- 实现计数器减运算逻辑
- 实现功率计算逻辑
-
MesDevice.java
- 添加17个新字段(协议类型、量程起点/终点、单位、计数器基准值、电压1/电压2)
-
DeviceData.java
- 添加29个新字段(8Multi协议数据字段,含counter1_total_8multi/counter2_total_8multi)
-
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 实际值=(原始值/65535)*量程范围+量程起点 实际值>=2A为设备开启 |
| 4 | 电流2 | 模拟输入AI2 | int(0-65535) | usSRegHoldBuf[1] | 范围0-20A 实际值=(原始值/65535)*量程范围+量程起点 |
| 5 | 质量1 | 模拟输入AI3 | int(0-65535) | usSRegHoldBuf[2] | 实际值=(原始值/65535)*量程范围+量程起点 前端配置量程 |
| 6 | 质量2 | 模拟输入AI4 | int(0-65535) | usSRegHoldBuf[3] | 实际值=(原始值/65535)*量程范围+量程起点 前端配置量程 |
| 7 | 温度 | 温湿度传感器温度 | String | temp | 保留1位小数 |
| 8 | 湿度 | 温湿度传感器湿度 | String | dht | 保留1位小数 |
| 9 | DI状态 | 工作/停机/故障/清零 | int | usSRegHoldBuf[DI_REG] | U16格式,取最后4位F,然后取反 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] | 直接读取,不取反 下发格式: DO=0_1(0为通道号,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 - 修改点:
- 注入Multi8ProtocolService
- 在ingestFrame方法开头添加协议判断
- 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个字段
- 不修改触发器(使用独立字段)
十四、后续工作
待完成
- 前端代码实现(参考第7.3节)
- 集成测试
- 8ADPRO回归测试
注意事项
⚠️ 千万不要影响8ADPRO的功能! ⚠️ 所有修改都要通过协议类型判断 ⚠️ 前端要在现有代码基础上扩展,不要删除任何8ADPRO代码