620 lines
20 KiB
Markdown
620 lines
20 KiB
Markdown
# YJH-MES 8Multi协议接入优化文档
|
||
|
||
> **版本**: v1.0.30
|
||
> **更新日期**: 2025-12-01
|
||
> **项目**: YJH-MES (yjh-mes + mes-ui)
|
||
> **说明**: 本文档基于项目实际代码编写,准确反映当前实现
|
||
|
||
---
|
||
|
||
## 一、项目概述
|
||
|
||
### 1.1 技术栈
|
||
|
||
| 层级 | 技术 | 说明 |
|
||
|------|------|------|
|
||
| **后端** | Spring Boot + MyBatis-Plus | yjh-mes模块 |
|
||
| **前端** | Vue 2 + Element UI | mes-ui模块 |
|
||
| **数据库** | MySQL 8.0 | device / device_data 表 |
|
||
|
||
### 1.2 协议类型
|
||
|
||
| 协议 | 数据格式 | 判断条件 | 设备号来源 |
|
||
|------|---------|---------|-----------|
|
||
| **8ADPRO** | 帧格式 | 以`+`开头且以`EEFF`结尾 | parts[0] |
|
||
| **8MULTI** | JSON格式 | 以`{`开头且以`}`结尾 | id字段后4位 |
|
||
|
||
---
|
||
|
||
## 二、数据上报接口
|
||
|
||
### 2.1 接口信息
|
||
|
||
```
|
||
POST /equipment/info/ingest/raw
|
||
Content-Type: text/plain
|
||
```
|
||
|
||
### 2.2 8ADPRO帧格式
|
||
|
||
```
|
||
+YAV:设备号,温度,电流,计数1,计数2,模拟1,模拟2,模拟3,模拟4,模拟5,模拟6,模拟7,数字1,数字2,数字3,数字4,数字5,数字6,EEFF
|
||
```
|
||
|
||
**示例**:
|
||
```
|
||
+YAV:1,25.5,3.2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,EEFF
|
||
```
|
||
|
||
### 2.3 8MULTI JSON格式
|
||
|
||
```json
|
||
{
|
||
"header": "+YAV",
|
||
"Card": "8multi",
|
||
"id": 101126010002,
|
||
"dt": 300,
|
||
"a1": 0.106,
|
||
"a2": 0.106,
|
||
"q1": 0.098,
|
||
"q2": 0.098,
|
||
"t1": 25.5,
|
||
"t2": 26.0,
|
||
"dht1": 65.0,
|
||
"dht2": 60.0,
|
||
"cn_reg": 1,
|
||
"f1": 50.00,
|
||
"f2": 50.00,
|
||
"c1": 5,
|
||
"c2": 3,
|
||
"do_reg": 0,
|
||
"reg1": 0.000,
|
||
"reg2": 0.000,
|
||
"tv": 0,
|
||
"save": 0,
|
||
"oee": 100,
|
||
"end": "EEFF"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 三、8MULTI卡号ID格式
|
||
|
||
```
|
||
卡号ID共12位: 品牌1位 + 年份1位 + 月日4位 + 用户号2位 + 序号4位
|
||
|
||
示例: 101126010002
|
||
1 - 品牌前缀
|
||
0 - 年份(0=2025, 1=2026, 2=2027...)
|
||
1126 - 月日(11月26日)
|
||
01 - 用户号
|
||
0002 - 设备序号(后端使用后4位作为设备号)
|
||
```
|
||
|
||
---
|
||
|
||
## 四、8MULTI JSON字段映射
|
||
|
||
### 4.1 字段对照表
|
||
|
||
| JSON字段 | 数据库字段 | 含义 | 说明 |
|
||
|---------|-----------|------|------|
|
||
| id | device_no | 卡号 | 取后4位作为设备号 |
|
||
| a1 | current1_value | 电流1 | 已换算实际值(A) |
|
||
| a2 | current2_value | 电流2 | 已换算实际值(A) |
|
||
| q1 | quality1_value | 质量1 | 已换算实际值 |
|
||
| q2 | quality2_value | 质量2 | 已换算实际值 |
|
||
| t1 | temperature_c | 温度1 | °C |
|
||
| t2 | analog4 | 温度2 | °C(预留) |
|
||
| dht1 | humidity | 湿度1 | % |
|
||
| dht2 | analog5 | 湿度2 | %(预留) |
|
||
| c1 | counter1 | 计数1 | 发送完清零 |
|
||
| c2 | counter2 | 计数2 | 发送完清零 |
|
||
| f1 | f1 | 测频1 | Hz |
|
||
| f2 | f2 | 测频2 | Hz |
|
||
| cn_reg | cn_reg | 屏幕状态 | 0-7 |
|
||
| do_reg | do_reg | 状态输出 | 位编码 |
|
||
| reg1 | reg1 | 从机数据1 | |
|
||
| reg2 | reg2 | 从机数据2 | |
|
||
| tv | tv | 显示 | 1有0无 |
|
||
| save | save_flag | 边缘存储 | 1有0无 |
|
||
| oee | oee | OEE计算 | 0或100 |
|
||
| dt | dt | 采样间隔 | 秒 |
|
||
|
||
### 4.2 cn_reg屏幕状态定义
|
||
|
||
| 值 | 含义 | 前端颜色 |
|
||
|----|------|---------|
|
||
| 0 | 计划停机 | 灰色(info) |
|
||
| 1 | 正常工作 | 绿色(success) |
|
||
| 2 | 待机 | 黄色(warning) |
|
||
| 3 | 故障 | 红色(danger) |
|
||
| 4 | 在修 | 黄色(warning) |
|
||
| 5 | 缺人 | 黄色(warning) |
|
||
| 6 | 缺料 | 黄色(warning) |
|
||
| 7 | 清零 | 灰色(info) |
|
||
|
||
### 4.3 cn_reg自动判断逻辑(下位机执行)
|
||
|
||
```
|
||
cn_reg=0(计划停机): 3次都是 [(a1'<20%) & (a2'<20%)] || [(f1=0) & (f2=0)]
|
||
cn_reg=1(正常工作): 3次都是 (a1'>40%) || (a2'>40%) || (f1>0.1) || (f2>0.1)
|
||
cn_reg=2(待机) : 3次都是 (a1介于20-40%) || (a2介于20-40%)
|
||
cn_reg=3-7 : 人工设置(触摸屏点击)
|
||
```
|
||
|
||
### 4.4 OEE计算规则
|
||
|
||
```
|
||
下位机逻辑: if(cn_reg=1) oee=100; else oee=0;
|
||
上位机: 计算时间段内oee均值
|
||
```
|
||
|
||
### 4.5 上报频率
|
||
|
||
```
|
||
1. 开机上发一次(dt=0)
|
||
2. 开机60s内,10s发一次
|
||
3. 开机超过60s,按设置间隔发送(默认300s)
|
||
4. 计数值改变时上发(间隔至少60s,dt=60)
|
||
5. 不接计数器时300s发一次(dt=300)
|
||
```
|
||
|
||
---
|
||
|
||
## 五、数据库设计
|
||
|
||
### 5.1 device表扩展字段
|
||
|
||
```sql
|
||
-- 协议类型
|
||
ALTER TABLE `device` ADD COLUMN `protocol_type` VARCHAR(16) DEFAULT '8ADPRO'
|
||
COMMENT '协议类型(8ADPRO/8MULTI)';
|
||
|
||
-- 量程配置(用于超量程警告)
|
||
ALTER TABLE `device` ADD COLUMN `current1_range_start` DECIMAL(10,3) DEFAULT NULL;
|
||
ALTER TABLE `device` ADD COLUMN `current1_range_end` DECIMAL(10,3) DEFAULT NULL;
|
||
ALTER TABLE `device` ADD COLUMN `current2_range_start` DECIMAL(10,3) DEFAULT NULL;
|
||
ALTER TABLE `device` ADD COLUMN `current2_range_end` DECIMAL(10,3) DEFAULT NULL;
|
||
ALTER TABLE `device` ADD COLUMN `quality1_range_start` DECIMAL(10,3) DEFAULT NULL;
|
||
ALTER TABLE `device` ADD COLUMN `quality1_range_end` DECIMAL(10,3) DEFAULT NULL;
|
||
ALTER TABLE `device` ADD COLUMN `quality2_range_start` DECIMAL(10,3) DEFAULT NULL;
|
||
ALTER TABLE `device` ADD COLUMN `quality2_range_end` DECIMAL(10,3) DEFAULT NULL;
|
||
ALTER TABLE `device` ADD COLUMN `quality1_unit` VARCHAR(10) DEFAULT 'kg';
|
||
ALTER TABLE `device` ADD COLUMN `quality2_unit` VARCHAR(10) DEFAULT 'kg';
|
||
ALTER TABLE `device` ADD COLUMN `current_unit` VARCHAR(10) DEFAULT 'A';
|
||
ALTER TABLE `device` ADD COLUMN `voltage1` DECIMAL(10,3) DEFAULT NULL COMMENT '电压1(用于功率计算)';
|
||
ALTER TABLE `device` ADD COLUMN `voltage2` DECIMAL(10,3) DEFAULT NULL COMMENT '电压2(用于功率计算)';
|
||
ALTER TABLE `device` ADD COLUMN `counter1_baseline` INT DEFAULT 0 COMMENT '计数1清零基准';
|
||
ALTER TABLE `device` ADD COLUMN `counter2_baseline` INT DEFAULT 0 COMMENT '计数2清零基准';
|
||
|
||
-- 设备扩展信息
|
||
ALTER TABLE `device` ADD COLUMN `location` VARCHAR(255) DEFAULT NULL COMMENT '设备位置';
|
||
ALTER TABLE `device` ADD COLUMN `brand` VARCHAR(128) DEFAULT NULL COMMENT '设备品牌';
|
||
ALTER TABLE `device` ADD COLUMN `model` VARCHAR(128) DEFAULT NULL COMMENT '设备型号';
|
||
ALTER TABLE `device` ADD COLUMN `workshop_id` BIGINT DEFAULT NULL COMMENT '车间ID(关联md_workshop)';
|
||
ALTER TABLE `device` ADD COLUMN `section` VARCHAR(64) DEFAULT NULL COMMENT '工序';
|
||
```
|
||
|
||
### 5.2 device_data表扩展字段
|
||
|
||
```sql
|
||
-- 8Multi V2.8 专用字段
|
||
ALTER TABLE `device_data` ADD COLUMN `current1_value` DECIMAL(10,3) DEFAULT NULL COMMENT '电流1实际值';
|
||
ALTER TABLE `device_data` ADD COLUMN `current2_value` DECIMAL(10,3) DEFAULT NULL COMMENT '电流2实际值';
|
||
ALTER TABLE `device_data` ADD COLUMN `quality1_value` DECIMAL(10,3) DEFAULT NULL COMMENT '质量1实际值';
|
||
ALTER TABLE `device_data` ADD COLUMN `quality2_value` DECIMAL(10,3) DEFAULT NULL COMMENT '质量2实际值';
|
||
ALTER TABLE `device_data` ADD COLUMN `humidity` DECIMAL(10,3) DEFAULT NULL COMMENT '湿度';
|
||
ALTER TABLE `device_data` ADD COLUMN `f1` DECIMAL(10,2) DEFAULT NULL COMMENT '测频1(Hz)';
|
||
ALTER TABLE `device_data` ADD COLUMN `f2` DECIMAL(10,2) DEFAULT NULL COMMENT '测频2(Hz)';
|
||
ALTER TABLE `device_data` ADD COLUMN `cn_reg` INT DEFAULT NULL COMMENT '屏幕状态(0-7)';
|
||
ALTER TABLE `device_data` ADD COLUMN `do_reg` VARCHAR(16) DEFAULT NULL COMMENT '状态输出';
|
||
ALTER TABLE `device_data` ADD COLUMN `reg1` DECIMAL(12,3) DEFAULT NULL COMMENT '从机数据1';
|
||
ALTER TABLE `device_data` ADD COLUMN `reg2` DECIMAL(12,3) DEFAULT NULL COMMENT '从机数据2';
|
||
ALTER TABLE `device_data` ADD COLUMN `tv` INT DEFAULT NULL COMMENT '显示';
|
||
ALTER TABLE `device_data` ADD COLUMN `save_flag` INT DEFAULT NULL COMMENT '边缘存储';
|
||
ALTER TABLE `device_data` ADD COLUMN `oee` INT DEFAULT NULL COMMENT 'OEE计算值';
|
||
ALTER TABLE `device_data` ADD COLUMN `dt` INT DEFAULT NULL COMMENT '采样间隔(秒)';
|
||
ALTER TABLE `device_data` ADD COLUMN `power1` DECIMAL(12,3) DEFAULT NULL COMMENT '功率1';
|
||
ALTER TABLE `device_data` ADD COLUMN `power2` DECIMAL(12,3) DEFAULT NULL COMMENT '功率2';
|
||
```
|
||
|
||
### 5.3 计数器触发器(仅8ADPRO使用)
|
||
|
||
```sql
|
||
DROP TRIGGER IF EXISTS `update_counter_totals_on_insert`;
|
||
|
||
DELIMITER $$
|
||
CREATE TRIGGER `update_counter_totals_on_insert`
|
||
BEFORE INSERT ON `device_data`
|
||
FOR EACH ROW
|
||
BEGIN
|
||
DECLARE last_c1 BIGINT UNSIGNED DEFAULT 0;
|
||
DECLARE last_c2 BIGINT UNSIGNED DEFAULT 0;
|
||
DECLARE proto VARCHAR(16) DEFAULT '8ADPRO';
|
||
|
||
SELECT IFNULL(protocol_type, '8ADPRO') INTO proto FROM device WHERE id = NEW.device_id LIMIT 1;
|
||
|
||
-- 仅8ADPRO使用触发器累计
|
||
IF proto = '8ADPRO' OR proto IS NULL THEN
|
||
SELECT IFNULL(counter1_total, 0), IFNULL(counter2_total, 0) INTO last_c1, last_c2
|
||
FROM device_data WHERE device_id = NEW.device_id ORDER BY collected_at DESC LIMIT 1;
|
||
|
||
SET NEW.counter1_total = IF(NEW.counter1 > 0, last_c1 + NEW.counter1, last_c1);
|
||
SET NEW.counter2_total = IF(NEW.counter2 > 0, last_c2 + NEW.counter2, last_c2);
|
||
END IF;
|
||
END$$
|
||
DELIMITER ;
|
||
```
|
||
|
||
---
|
||
|
||
## 六、后端核心代码
|
||
|
||
### 6.1 文件清单
|
||
|
||
```
|
||
yjh-mes/src/main/java/cn/sourceplan/equipment/
|
||
├── controller/
|
||
│ └── EquipmentInfoController.java # 设备信息控制器
|
||
├── service/
|
||
│ ├── IEquipmentInfoService.java # 服务接口
|
||
│ ├── Multi8ProtocolService.java # 8Multi协议解析服务 ⭐
|
||
│ └── impl/
|
||
│ └── EquipmentInfoServiceImpl.java # 服务实现
|
||
├── domain/
|
||
│ ├── MesDevice.java # 设备实体
|
||
│ └── DeviceData.java # 设备数据实体
|
||
└── mapper/
|
||
├── MesDeviceMapper.java # 设备Mapper
|
||
└── DeviceDataMapper.java # 数据Mapper
|
||
```
|
||
|
||
### 6.2 协议判断入口 (EquipmentInfoServiceImpl.java)
|
||
|
||
```java
|
||
@Override
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public void ingestFrame(String frameRaw) {
|
||
if (StringUtils.isBlank(frameRaw)) throw new IllegalArgumentException("frame is empty");
|
||
String raw = frameRaw.trim();
|
||
|
||
// 8Multi: 以{开头且以}结尾(JSON格式)
|
||
if (raw.startsWith("{") && raw.endsWith("}")) {
|
||
log.info("检测到8Multi协议(JSON格式)");
|
||
multi8ProtocolService.parse8MultiJson(raw);
|
||
return;
|
||
}
|
||
|
||
// 8AdPro: 以+开头且以EEFF结尾(帧格式)
|
||
if (!raw.startsWith("+") || !raw.endsWith("EEFF")) {
|
||
throw new IllegalArgumentException("协议格式无效");
|
||
}
|
||
|
||
// ... 8ADPRO处理逻辑
|
||
}
|
||
```
|
||
|
||
### 6.3 8Multi JSON解析 (Multi8ProtocolService.java)
|
||
|
||
```java
|
||
public void parse8MultiJson(String rawJson) {
|
||
JSONObject json = JSONUtil.parseObj(rawJson);
|
||
|
||
// 1. 提取设备号(ID后4位)
|
||
String idStr = json.getStr("id");
|
||
String lastFour = idStr.substring(idStr.length() - 4);
|
||
Integer deviceNo = Integer.valueOf(lastFour);
|
||
|
||
// 2. 查找或创建设备
|
||
MesDevice device = findOrCreateDevice(deviceNo);
|
||
|
||
// 3. 构建DeviceData
|
||
DeviceData data = new DeviceData();
|
||
data.setDeviceId(device.getId());
|
||
data.setCollectedAt(new Timestamp(System.currentTimeMillis()));
|
||
data.setFrameRaw(rawJson);
|
||
|
||
// 4. 字段映射(下位机已换算,直接存储)
|
||
data.setCurrent1Value(parseDecimal(json.getStr("a1")));
|
||
data.setCurrent2Value(parseDecimal(json.getStr("a2")));
|
||
data.setQuality1Value(parseDecimal(json.getStr("q1")));
|
||
data.setQuality2Value(parseDecimal(json.getStr("q2")));
|
||
data.setTemperatureC(parseDecimal(json.getStr("t1")));
|
||
data.setHumidity(parseDecimal(json.getStr("dht1")));
|
||
data.setCounter1(parseInt(json.getStr("c1")));
|
||
data.setCounter2(parseInt(json.getStr("c2")));
|
||
data.setF1(parseDecimal(json.getStr("f1")));
|
||
data.setF2(parseDecimal(json.getStr("f2")));
|
||
data.setCnReg(parseInt(json.getStr("cn_reg")));
|
||
data.setDoReg(json.getStr("do_reg"));
|
||
data.setReg1(parseDecimal(json.getStr("reg1")));
|
||
data.setReg2(parseDecimal(json.getStr("reg2")));
|
||
data.setTv(parseInt(json.getStr("tv")));
|
||
data.setSaveFlag(parseInt(json.getStr("save")));
|
||
data.setOee(parseInt(json.getStr("oee")));
|
||
data.setDt(parseInt(json.getStr("dt")));
|
||
|
||
// 5. 计数器累计
|
||
DeviceData lastData = deviceDataMapper.selectLastByDeviceId(device.getId());
|
||
Long counter1Total = (lastData != null ? lastData.getCounter1Total() : 0L);
|
||
Long counter2Total = (lastData != null ? lastData.getCounter2Total() : 0L);
|
||
if (data.getCounter1() != null && data.getCounter1() > 0) {
|
||
counter1Total += data.getCounter1();
|
||
}
|
||
if (data.getCounter2() != null && data.getCounter2() > 0) {
|
||
counter2Total += data.getCounter2();
|
||
}
|
||
data.setCounter1Total(counter1Total);
|
||
data.setCounter2Total(counter2Total);
|
||
|
||
// 6. 保存
|
||
deviceDataMapper.insert(data);
|
||
}
|
||
```
|
||
|
||
### 6.4 OEE均值查询 (DeviceDataMapper.java)
|
||
|
||
```java
|
||
@Select({
|
||
"<script>",
|
||
"SELECT AVG(oee) FROM device_data ",
|
||
"WHERE device_id = #{deviceId} AND oee IS NOT NULL",
|
||
"<if test='from != null and from != \"\"'>",
|
||
" AND collected_at >= #{from}",
|
||
"</if>",
|
||
"<if test='to != null and to != \"\"'>",
|
||
" AND collected_at <= #{to}",
|
||
"</if>",
|
||
"</script>"
|
||
})
|
||
Double selectOeeAvg(@Param("deviceId") Long deviceId, @Param("from") String from, @Param("to") String to);
|
||
```
|
||
|
||
---
|
||
|
||
## 七、前端实现
|
||
|
||
### 7.1 文件位置
|
||
|
||
```
|
||
mes-ui/src/views/mes/equipment/info/index.vue # 设备监控页面
|
||
mes-ui/src/api/mes/equipment/info.js # API接口
|
||
```
|
||
|
||
### 7.2 API接口
|
||
|
||
```javascript
|
||
// 获取设备OEE均值
|
||
export function getOeeAvg(deviceId, from, to) {
|
||
return request({
|
||
url: '/equipment/info/oee/avg',
|
||
method: 'get',
|
||
params: { deviceId, from, to }
|
||
})
|
||
}
|
||
```
|
||
|
||
### 7.3 协议类型判断显示
|
||
|
||
```vue
|
||
<!-- 8ADPRO设备显示 -->
|
||
<div v-if="!d.protocol_type || d.protocol_type === '8ADPRO'" class="metrics">
|
||
<!-- 温度、电流、计数器等 -->
|
||
</div>
|
||
|
||
<!-- 8MULTI设备显示 -->
|
||
<div v-else-if="d.protocol_type === '8MULTI'" class="metrics">
|
||
<!-- 电流1/2、质量1/2、温湿度、OEE、状态等 -->
|
||
</div>
|
||
```
|
||
|
||
### 7.4 cn_reg状态显示
|
||
|
||
```javascript
|
||
// 状态文本
|
||
cnRegText(val) {
|
||
const map = {
|
||
0: '计划停机', 1: '正常工作', 2: '待机', 3: '故障',
|
||
4: '在修', 5: '缺人', 6: '缺料', 7: '清零'
|
||
}
|
||
return map[val] || '未知'
|
||
},
|
||
|
||
// 状态颜色
|
||
cnRegType(val) {
|
||
const map = {
|
||
0: 'info', 1: 'success', 2: 'warning', 3: 'danger',
|
||
4: 'warning', 5: 'warning', 6: 'warning', 7: 'info'
|
||
}
|
||
return map[val] || 'info'
|
||
}
|
||
```
|
||
|
||
### 7.5 超量程红色警告
|
||
|
||
```javascript
|
||
// 判断是否超量程
|
||
isOutOfRange(value, rangeStart, rangeEnd) {
|
||
if (value === null || value === undefined) return false
|
||
if (rangeStart === null && rangeEnd === null) return false
|
||
if (rangeStart !== null && value < rangeStart) return true
|
||
if (rangeEnd !== null && value > rangeEnd) return true
|
||
return false
|
||
}
|
||
```
|
||
|
||
```vue
|
||
<!-- 超量程显示红色 -->
|
||
<span :style="{color: isOutOfRange(d.current1_value, d.current1RangeStart, d.current1RangeEnd) ? '#F56C6C' : ''}">
|
||
{{ fmt(d.current1_value, 'A', 2) }}
|
||
</span>
|
||
```
|
||
|
||
### 7.6 设备编辑表单扩展
|
||
|
||
新增字段:
|
||
- **设备位置** (location)
|
||
- **设备品牌** (brand)
|
||
- **设备型号** (model)
|
||
- **所属车间** (workshopId) - 从md_workshop表读取
|
||
- **所属工序** (section) - 从pro_process表读取
|
||
- **量程配置** (current1/2RangeStart/End, quality1/2RangeStart/End) - 用于超量程警告
|
||
|
||
---
|
||
|
||
## 八、废弃字段说明
|
||
|
||
8Multi V2.8协议中不再使用,但保留以兼容8ADPRO:
|
||
|
||
| 废弃字段 | 替代方案 | 说明 |
|
||
|---------|---------|------|
|
||
| current1_raw, current2_raw | current1_value | 下位机已换算 |
|
||
| quality1_raw, quality2_raw | quality1_value | 下位机已换算 |
|
||
| status_work/stop/fault/reset | cn_reg (0-7) | 统一用屏幕状态 |
|
||
| frequency1, frequency2 | f1, f2 | 使用新测频字段 |
|
||
| counter1_total_8multi | counter1_total | 统一使用 |
|
||
| relay_power/alarm, do_soft_start/stop | do_reg | 统一用状态输出 |
|
||
| slave_data1/2 | reg1, reg2 | 使用新从机数据字段 |
|
||
| touchscreen_data | tv | 使用新显示字段 |
|
||
|
||
---
|
||
|
||
## 九、设备OEE功能
|
||
|
||
### 9.1 OEE页面改造
|
||
|
||
将设备OEE页面与8ADPRO/8MULTI设备关联,不再使用车间设备。
|
||
|
||
**文件清单**:
|
||
```
|
||
mes-ui/src/views/mes/equipment/oeeGantt/index.vue # OEE时序图页面
|
||
mes-ui/src/api/mes/equipment/equipment.js # API接口
|
||
yjh-mes/.../controller/EquipmentController.java # 控制器
|
||
yjh-mes/.../service/impl/EquipmentServiceImpl.java # 服务实现
|
||
yjh-mes/.../mapper/EquipmentMapper.java # Mapper接口
|
||
yjh-mes/.../resources/mapper/equipment/EquipmentMapper.xml # SQL
|
||
```
|
||
|
||
### 9.2 OEE页面筛选功能
|
||
|
||
```vue
|
||
<!-- 协议类型筛选 -->
|
||
<el-select v-model="queryParams.deviceType" @change="onDeviceTypeChange">
|
||
<el-option label="全部" value="" />
|
||
<el-option label="8ADPRO" value="8ADPRO" />
|
||
<el-option label="8MULTI" value="8MULTI" />
|
||
</el-select>
|
||
|
||
<!-- 设备筛选 -->
|
||
<el-select v-model="queryParams.deviceId" filterable>
|
||
<el-option v-for="d in deviceList" :key="d.id" :label="d.name" :value="d.id" />
|
||
</el-select>
|
||
```
|
||
|
||
### 9.3 设备列表API
|
||
|
||
```java
|
||
// EquipmentController.java
|
||
@GetMapping("/allDevices")
|
||
public AjaxResult listAllDevices(String deviceType) {
|
||
return success(equipmentService.listAllDevices(deviceType));
|
||
}
|
||
```
|
||
|
||
```xml
|
||
<!-- EquipmentMapper.xml -->
|
||
<select id="selectMesDevices" resultType="Map">
|
||
SELECT id, device_no, device_name, protocol_type
|
||
FROM device WHERE is_active = 1
|
||
<if test="deviceType != null and deviceType != ''">
|
||
AND protocol_type = #{deviceType}
|
||
</if>
|
||
ORDER BY device_no
|
||
</select>
|
||
```
|
||
|
||
### 9.4 OEE数据查询
|
||
|
||
```xml
|
||
<!-- EquipmentMapper.xml -->
|
||
<select id="selectMesDeviceOee" parameterType="Map" resultType="Map">
|
||
SELECT
|
||
d.id as equipment_id,
|
||
d.device_name as equipment_name,
|
||
d.device_no as equipment_number,
|
||
dd.collected_at as record_time,
|
||
dd.cn_reg as equipment_status,
|
||
dd.oee as oee_value,
|
||
d.protocol_type
|
||
FROM device d
|
||
LEFT JOIN device_data dd ON dd.device_id = d.id
|
||
WHERE d.is_active = 1
|
||
AND dd.collected_at IS NOT NULL
|
||
AND dd.collected_at >= #{map.beginDate}
|
||
AND dd.collected_at <= #{map.endDate}
|
||
<if test="map.deviceType != null and map.deviceType != ''">
|
||
AND d.protocol_type = #{map.deviceType}
|
||
</if>
|
||
<if test="map.deviceId != null and map.deviceId != ''">
|
||
AND d.id = #{map.deviceId}
|
||
</if>
|
||
ORDER BY d.id DESC, dd.collected_at DESC
|
||
</select>
|
||
```
|
||
|
||
### 9.5 OEE状态映射
|
||
|
||
cn_reg值映射到OEE图表状态:
|
||
|
||
| cn_reg值 | 含义 | OEE状态 | 颜色 |
|
||
|----------|------|---------|------|
|
||
| 1 | 正常工作 | 运行中 | 绿色(#67C23A) |
|
||
| 3 | 故障 | 故障 | 红色(#F56C6C) |
|
||
| 0,2,4,5,6,7 | 其他 | 停机 | 灰色(#909399) |
|
||
|
||
```java
|
||
// EquipmentServiceImpl.java - 状态转换
|
||
Integer cnReg = ((Number)cnRegObj).intValue();
|
||
Integer status;
|
||
switch (cnReg) {
|
||
case 1: status = 0; break; // 正常工作 -> 运行中
|
||
case 3: status = 2; break; // 故障
|
||
default: status = 1; break; // 其他 -> 停机
|
||
}
|
||
```
|
||
|
||
### 9.6 前端调整
|
||
|
||
**移除的功能**:
|
||
- 设备卡片上的OEE显示
|
||
- 设备详情中的OEE时段均值查询
|
||
|
||
**保留的功能**:
|
||
- OEE时序图页面(独立页面)
|
||
- 设备类型/设备筛选
|
||
- 时序图和饼状图显示
|
||
- 设备状态统计卡片
|
||
|
||
---
|
||
|
||
## 十、计数器处理差异
|
||
|
||
| 协议 | counter1/2值 | 累计方式 | 触发器 |
|
||
|------|-------------|---------|--------|
|
||
| **8ADPRO** | limitToBinary(>0→1) | 数据库触发器累加 | ✅使用 |
|
||
| **8MULTI** | 原始增量值 | Java代码累加 | ❌不使用 |
|
||
|
||
---
|
||
|
||
## 十一、注意事项
|
||
|
||
1. **8MULTI协议识别**: 根据数据格式判断,JSON格式即为8MULTI
|
||
2. **设备号提取**: 8MULTI使用ID后4位作为设备号
|
||
3. **量程配置**: 8MULTI下位机已换算,量程配置仅用于超量程警告显示
|
||
4. **计数器清零**: 通过设置baseline实现软清零
|
||
5. **OEE页面**: 仅显示8ADPRO/8MULTI设备,不显示车间设备
|
||
6. **OEE状态**: 基于cn_reg字段判断(1=运行中,3=故障,其他=停机)
|
||
7. **兼容性**: 所有修改不影响8ADPRO原有功能
|