# 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) **新增字段**: ```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_1(0为通道号,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原始值: 32768(AI1,0-65535,对应usSRegHoldBuf[0]) 4. 电流2原始值: 16384(AI2,0-65535,对应usSRegHoldBuf[1]) 5. 质量1原始值: 49152(AI3,0-65535,对应usSRegHoldBuf[2]) 6. 质量2原始值: 8192(AI4,0-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
``` #### 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/质量2(AI3/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
实际值=(原始值/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` - 修改点: 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代码**