From ab389a5a6b329b15a655340ba7b87bce7fd7871d Mon Sep 17 00:00:00 2001
From: huang <1532065656@qq.com>
Date: 星期三, 24 十二月 2025 17:16:19 +0800
Subject: [PATCH] 添加新增设备自动生成编码
---
mes-processes/mes-plcSend/src/main/java/com/mes/plc/client/impl/ModbusPlcClient.java | 370 ++++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 325 insertions(+), 45 deletions(-)
diff --git a/mes-processes/mes-plcSend/src/main/java/com/mes/plc/client/impl/ModbusPlcClient.java b/mes-processes/mes-plcSend/src/main/java/com/mes/plc/client/impl/ModbusPlcClient.java
index 03f03c7..0a12508 100644
--- a/mes-processes/mes-plcSend/src/main/java/com/mes/plc/client/impl/ModbusPlcClient.java
+++ b/mes-processes/mes-plcSend/src/main/java/com/mes/plc/client/impl/ModbusPlcClient.java
@@ -1,13 +1,15 @@
package com.mes.plc.client.impl;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.mes.connect.modbus.ModbusTcpClient;
import com.mes.device.entity.DeviceConfig;
+import com.mes.device.util.ConfigJsonHelper;
import com.mes.plc.client.PlcClient;
import lombok.extern.slf4j.Slf4j;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
+import java.io.IOException;
+import java.util.*;
/**
* Modbus鍗忚PLC瀹㈡埛绔疄鐜�
@@ -20,34 +22,44 @@
*/
@Slf4j
public class ModbusPlcClient implements PlcClient {
-
+
// PLC IP鍦板潃
private final String plcIp;
-
+
// PLC绔彛
private final int plcPort;
-
+
// 浠庣珯鍦板潃
private final int unitId;
-
+
+ // 璁惧閰嶇疆
+ private final DeviceConfig device;
+
// Modbus瀹㈡埛绔疄渚�
private ModbusTcpClient modbusClient;
-
+
// 杩炴帴鐘舵��
private boolean connected = false;
-
+
// 瓒呮椂鏃堕棿锛堟绉掞級
private int timeout = 5000;
-
+
+ // ObjectMapper鐢ㄤ簬JSON瑙f瀽
+ private final ObjectMapper objectMapper = new ObjectMapper();
+
+ // 鍦板潃鏄犲皠缂撳瓨锛氬瓧娈靛悕 -> Modbus鍦板潃
+ private Map<String, String> addressMappingCache;
+
/**
* 鏋勯�犲嚱鏁�
*
* @param device 璁惧閰嶇疆
*/
public ModbusPlcClient(DeviceConfig device) {
+ this.device = device;
this.plcIp = device.getPlcIp();
this.plcPort = device.getPlcPort() != null ? device.getPlcPort() : 502;
-
+
// 浠庨厤缃腑鑾峰彇浠庣珯鍦板潃锛岄粯璁�1
int unitIdValue = 1;
try {
@@ -64,8 +76,11 @@
log.warn("瑙f瀽unitId澶辫触锛屼娇鐢ㄩ粯璁ゅ��1: deviceId={}", device.getId(), e);
}
this.unitId = unitIdValue;
+
+ // 鍒濆鍖栧湴鍧�鏄犲皠
+ this.addressMappingCache = loadAddressMapping();
}
-
+
/**
* 瑙f瀽璁惧鐨別xtraParams
*
@@ -74,29 +89,126 @@
*/
private Map<String, Object> parseExtraParams(String extraParamsJson) {
if (extraParamsJson == null || extraParamsJson.isEmpty()) {
- return null;
- }
-
- try {
- // 杩欓噷绠�鍖栧鐞嗭紝瀹為檯椤圭洰涓簲璇ヤ娇鐢↗ackson鎴朑son瑙f瀽
- // 鐢变簬椤圭洰涓凡鏈塐bjectMapper锛岃繖閲屾殏鏃惰繑鍥炵┖Map锛屽悗缁畬鍠�
return new HashMap<>();
+ }
+
+ try {
+ TypeReference<Map<String, Object>> typeRef = new TypeReference<Map<String, Object>>() {};
+ return objectMapper.readValue(extraParamsJson, typeRef);
} catch (Exception e) {
log.error("瑙f瀽extraParams澶辫触: {}", extraParamsJson, e);
- return null;
+ return new HashMap<>();
}
}
-
+
+ /**
+ * 鍔犺浇鍦板潃鏄犲皠閰嶇疆锛堜粠configJson鎴杄xtraParams.addressMapping锛�
+ *
+ * @return 瀛楁鍚� -> Modbus鍦板潃鐨勬槧灏�
+ */
+ private Map<String, String> loadAddressMapping() {
+ Map<String, String> mapping = new HashMap<>();
+
+ try {
+ // 1. 浼樺厛浠巆onfigJson鑾峰彇
+ Map<String, Object> configParams = ConfigJsonHelper.parseToMap(device.getConfigJson(), objectMapper);
+ if (!configParams.isEmpty()) {
+ for (Map.Entry<String, Object> entry : configParams.entrySet()) {
+ String fieldName = entry.getKey();
+ Object addressObj = entry.getValue();
+ if (addressObj != null) {
+ mapping.put(fieldName, String.valueOf(addressObj));
+ }
+ }
+ if (!mapping.isEmpty()) {
+ log.info("浠巆onfigJson鍔犺浇Modbus鍦板潃鏄犲皠鎴愬姛: deviceId={}, count={}", device.getId(), mapping.size());
+ return mapping;
+ }
+ }
+
+ // 2. 浠巈xtraParams.addressMapping鑾峰彇
+ Map<String, Object> extraParams = parseExtraParams(device.getExtraParams());
+ Object addressMappingObj = extraParams.get("addressMapping");
+ if (addressMappingObj != null) {
+ if (addressMappingObj instanceof Map) {
+ @SuppressWarnings("unchecked")
+ Map<String, Object> addrMap = (Map<String, Object>) addressMappingObj;
+ for (Map.Entry<String, Object> entry : addrMap.entrySet()) {
+ mapping.put(entry.getKey(), String.valueOf(entry.getValue()));
+ }
+ } else if (addressMappingObj instanceof String) {
+ // 濡傛灉鏄疛SON瀛楃涓诧紝瑙f瀽瀹�
+ TypeReference<Map<String, Object>> typeRef = new TypeReference<Map<String, Object>>() {};
+ Map<String, Object> addrMap = objectMapper.readValue((String) addressMappingObj, typeRef);
+ for (Map.Entry<String, Object> entry : addrMap.entrySet()) {
+ mapping.put(entry.getKey(), String.valueOf(entry.getValue()));
+ }
+ }
+ if (!mapping.isEmpty()) {
+ log.info("浠巈xtraParams.addressMapping鍔犺浇Modbus鍦板潃鏄犲皠鎴愬姛: deviceId={}, count={}", device.getId(), mapping.size());
+ return mapping;
+ }
+ }
+
+ log.warn("鏈壘鍒癕odbus鍦板潃鏄犲皠閰嶇疆: deviceId={}", device.getId());
+ } catch (Exception e) {
+ log.error("鍔犺浇Modbus鍦板潃鏄犲皠澶辫触: deviceId={}", device.getId(), e);
+ }
+
+ return mapping;
+ }
+
+ /**
+ * 鑾峰彇瀛楁瀵瑰簲鐨凪odbus鍦板潃
+ *
+ * @param fieldName 瀛楁鍚�
+ * @return Modbus鍦板潃锛堟牸寮忥細鍔熻兘鐮�.瀵勫瓨鍣ㄥ湴鍧�锛屽 "3.40001"锛�
+ */
+ private String getModbusAddress(String fieldName) {
+ String address = addressMappingCache.get(fieldName);
+ if (address == null || address.isEmpty()) {
+ log.warn("瀛楁 {} 鏈壘鍒癕odbus鍦板潃鏄犲皠: deviceId={}", fieldName, device.getId());
+ return null;
+ }
+ return address;
+ }
+
+ /**
+ * 鎺ㄦ柇鏁版嵁绫诲瀷锛堟牴鎹瓧娈靛悕鎴栧�硷級
+ */
+ private String inferDataType(String fieldName, Object value) {
+ if (value == null) {
+ // 鏍规嵁瀛楁鍚嶆帹鏂�
+ String lowerName = fieldName.toLowerCase();
+ if (lowerName.contains("float") || lowerName.contains("real")) {
+ return "float";
+ } else if (lowerName.contains("string") || lowerName.contains("str") || lowerName.contains("id")) {
+ return "string";
+ }
+ return "int"; // 榛樿int
+ }
+
+ // 鏍规嵁鍊肩被鍨嬫帹鏂�
+ if (value instanceof Float || value instanceof Double) {
+ return "float";
+ } else if (value instanceof String) {
+ return "string";
+ } else if (value instanceof Number) {
+ return "int";
+ }
+ return "int";
+ }
+
@Override
public boolean connect() {
try {
if (modbusClient != null && isConnected()) {
return true;
}
-
+
// 鍒涘缓Modbus瀹㈡埛绔疄渚�
this.modbusClient = new ModbusTcpClient(this.plcIp, this.plcPort, this.unitId);
-
+
// 杩炴帴PLC
this.modbusClient.connect();
this.connected = true;
@@ -108,7 +220,7 @@
return false;
}
}
-
+
@Override
public void disconnect() {
try {
@@ -123,56 +235,169 @@
this.modbusClient = null;
}
}
-
+
@Override
public Map<String, Object> readAllData() {
if (!isConnected() && !connect()) {
log.error("Modbus PLC鏈繛鎺ワ紝鏃犳硶璇诲彇鏁版嵁: {}:{}", this.plcIp, this.plcPort);
return Collections.emptyMap();
}
-
+
try {
- // TODO: 瀹炵幇Modbus璇诲彇鎵�鏈夋暟鎹�
- // 杩欓噷鏆傛椂杩斿洖绌篗ap锛屽悗缁畬鍠�
- log.warn("Modbus readAllData鏈疄鐜帮紝杩斿洖绌篗ap");
- return new HashMap<>();
+ if (addressMappingCache.isEmpty()) {
+ log.warn("Modbus鍦板潃鏄犲皠涓虹┖锛屾棤娉曡鍙栨墍鏈夋暟鎹�: deviceId={}", device.getId());
+ return Collections.emptyMap();
+ }
+
+ // 璇诲彇鎵�鏈夐厤缃殑瀛楁
+ Map<String, Object> result = new HashMap<>();
+ for (String fieldName : addressMappingCache.keySet()) {
+ try {
+ Object value = readFieldValue(fieldName);
+ if (value != null) {
+ result.put(fieldName, value);
+ }
+ } catch (Exception e) {
+ log.warn("璇诲彇瀛楁澶辫触: fieldName={}, deviceId={}, error={}", fieldName, device.getId(), e.getMessage());
+ }
+ }
+
+ log.info("Modbus璇诲彇鎵�鏈夋暟鎹垚鍔�: deviceId={}, fieldCount={}", device.getId(), result.size());
+ return result;
} catch (Exception e) {
log.error("Modbus PLC璇诲彇鎵�鏈夋暟鎹け璐�: {}:{}", this.plcIp, this.plcPort, e);
this.connected = false;
return Collections.emptyMap();
}
}
-
+
@Override
public Map<String, Object> readData(String... fields) {
if (!isConnected() && !connect()) {
log.error("Modbus PLC鏈繛鎺ワ紝鏃犳硶璇诲彇鏁版嵁: {}:{}", this.plcIp, this.plcPort);
return Collections.emptyMap();
}
-
+
+ if (fields == null || fields.length == 0) {
+ return readAllData();
+ }
+
try {
- // TODO: 瀹炵幇Modbus璇诲彇鎸囧畾瀛楁鏁版嵁
- // 杩欓噷鏆傛椂杩斿洖绌篗ap锛屽悗缁畬鍠�
- log.warn("Modbus readData鏈疄鐜帮紝杩斿洖绌篗ap");
- return new HashMap<>();
+ Map<String, Object> result = new HashMap<>();
+ for (String fieldName : fields) {
+ if (fieldName == null || fieldName.isEmpty()) {
+ continue;
+ }
+ try {
+ Object value = readFieldValue(fieldName);
+ if (value != null) {
+ result.put(fieldName, value);
+ }
+ } catch (Exception e) {
+ log.warn("璇诲彇瀛楁澶辫触: fieldName={}, deviceId={}, error={}", fieldName, device.getId(), e.getMessage());
+ }
+ }
+
+ log.info("Modbus璇诲彇鎸囧畾瀛楁鏁版嵁鎴愬姛: deviceId={}, fields={}, resultCount={}",
+ device.getId(), Arrays.toString(fields), result.size());
+ return result;
} catch (Exception e) {
log.error("Modbus PLC璇诲彇鏁版嵁澶辫触: {}:{}", this.plcIp, this.plcPort, e);
this.connected = false;
return Collections.emptyMap();
}
}
-
+
+ /**
+ * 璇诲彇鍗曚釜瀛楁鐨勫��
+ */
+ private Object readFieldValue(String fieldName) throws IOException {
+ String address = getModbusAddress(fieldName);
+ if (address == null) {
+ return null;
+ }
+
+ // 鏍规嵁瀛楁鍚嶆帹鏂暟鎹被鍨嬶紙浼樺厛浠庨厤缃腑鑾峰彇锛�
+ String dataType = inferDataType(fieldName, null);
+
+ // 浠巈xtraParams涓幏鍙栧瓧娈电殑鏁版嵁绫诲瀷閰嶇疆
+ Map<String, Object> extraParams = parseExtraParams(device.getExtraParams());
+ @SuppressWarnings("unchecked")
+ Map<String, Object> fieldConfigs = (Map<String, Object>) extraParams.get("fieldConfigs");
+ if (fieldConfigs != null) {
+ @SuppressWarnings("unchecked")
+ Map<String, Object> fieldConfig = (Map<String, Object>) fieldConfigs.get(fieldName);
+ if (fieldConfig != null && fieldConfig.get("dataType") != null) {
+ dataType = String.valueOf(fieldConfig.get("dataType"));
+ }
+ }
+
+ // 鏍规嵁鏁版嵁绫诲瀷璇诲彇
+ switch (dataType.toLowerCase()) {
+ case "float":
+ case "real":
+ return modbusClient.readFloat(address);
+ case "string":
+ case "str":
+ // 瀛楃涓查渶瑕佹寚瀹氶暱搴︼紝榛樿32瀛楃
+ int stringLength = 32;
+ if (fieldConfigs != null) {
+ @SuppressWarnings("unchecked")
+ Map<String, Object> fieldConfig = (Map<String, Object>) fieldConfigs.get(fieldName);
+ if (fieldConfig != null && fieldConfig.get("length") != null) {
+ stringLength = ((Number) fieldConfig.get("length")).intValue();
+ }
+ }
+ return modbusClient.readString(address, stringLength);
+ case "int":
+ case "integer":
+ case "word":
+ default:
+ return modbusClient.readRegister(address);
+ }
+ }
+
@Override
public boolean writeData(Map<String, Object> data) {
if (!isConnected() && !connect()) {
log.error("Modbus PLC鏈繛鎺ワ紝鏃犳硶鍐欏叆鏁版嵁: {}:{}", this.plcIp, this.plcPort);
return false;
}
-
+
+ if (data == null || data.isEmpty()) {
+ log.warn("鍐欏叆鏁版嵁涓虹┖锛岃烦杩囨搷浣�: deviceId={}", device.getId());
+ return true;
+ }
+
try {
- // TODO: 瀹炵幇Modbus鍐欏叆鏁版嵁
- // 杩欓噷鏆傛椂杩斿洖true锛屽悗缁畬鍠�
- log.warn("Modbus writeData鏈疄鐜帮紝杩斿洖鎴愬姛");
+ int successCount = 0;
+ int failCount = 0;
+
+ for (Map.Entry<String, Object> entry : data.entrySet()) {
+ String fieldName = entry.getKey();
+ Object value = entry.getValue();
+
+ if (value == null) {
+ continue; // 璺宠繃null鍊�
+ }
+
+ try {
+ writeFieldValue(fieldName, value);
+ successCount++;
+ } catch (Exception e) {
+ log.error("鍐欏叆瀛楁澶辫触: fieldName={}, value={}, deviceId={}, error={}",
+ fieldName, value, device.getId(), e.getMessage());
+ failCount++;
+ }
+ }
+
+ if (failCount > 0) {
+ log.warn("Modbus鍐欏叆鏁版嵁閮ㄥ垎澶辫触: deviceId={}, success={}, fail={}",
+ device.getId(), successCount, failCount);
+ return false;
+ }
+
+ log.info("Modbus鍐欏叆鏁版嵁鎴愬姛: deviceId={}, fieldCount={}", device.getId(), successCount);
return true;
} catch (Exception e) {
log.error("Modbus PLC鍐欏叆鏁版嵁澶辫触: {}:{}", this.plcIp, this.plcPort, e);
@@ -180,7 +405,63 @@
return false;
}
}
-
+
+ /**
+ * 鍐欏叆鍗曚釜瀛楁鐨勫��
+ */
+ private void writeFieldValue(String fieldName, Object value) throws IOException {
+ String address = getModbusAddress(fieldName);
+ if (address == null) {
+ throw new IllegalArgumentException("瀛楁 " + fieldName + " 鏈壘鍒癕odbus鍦板潃鏄犲皠");
+ }
+
+ // 鏍规嵁鍊肩被鍨嬫帹鏂暟鎹被鍨�
+ String dataType = inferDataType(fieldName, value);
+
+ // 浠巈xtraParams涓幏鍙栧瓧娈电殑鏁版嵁绫诲瀷閰嶇疆
+ Map<String, Object> extraParams = parseExtraParams(device.getExtraParams());
+ @SuppressWarnings("unchecked")
+ Map<String, Object> fieldConfigs = (Map<String, Object>) extraParams.get("fieldConfigs");
+ if (fieldConfigs != null) {
+ @SuppressWarnings("unchecked")
+ Map<String, Object> fieldConfig = (Map<String, Object>) fieldConfigs.get(fieldName);
+ if (fieldConfig != null && fieldConfig.get("dataType") != null) {
+ dataType = String.valueOf(fieldConfig.get("dataType"));
+ }
+ }
+
+ // 鏍规嵁鏁版嵁绫诲瀷鍐欏叆
+ switch (dataType.toLowerCase()) {
+ case "float":
+ case "real":
+ float floatValue;
+ if (value instanceof Number) {
+ floatValue = ((Number) value).floatValue();
+ } else {
+ floatValue = Float.parseFloat(String.valueOf(value));
+ }
+ modbusClient.writeFloat(address, floatValue);
+ break;
+ case "string":
+ case "str":
+ String stringValue = String.valueOf(value);
+ modbusClient.writeString(address, stringValue);
+ break;
+ case "int":
+ case "integer":
+ case "word":
+ default:
+ int intValue;
+ if (value instanceof Number) {
+ intValue = ((Number) value).intValue();
+ } else {
+ intValue = Integer.parseInt(String.valueOf(value));
+ }
+ modbusClient.writeRegister(address, intValue);
+ break;
+ }
+ }
+
@Override
public boolean isConnected() {
try {
@@ -194,20 +475,19 @@
return false;
}
}
-
+
@Override
public String getPlcType() {
return "MODBUS";
}
-
+
@Override
public int getTimeout() {
return this.timeout;
}
-
+
@Override
public void setTimeout(int timeout) {
this.timeout = timeout;
- // ModbusTcpClient涓嶆敮鎸佺洿鎺ヨ缃秴鏃讹紝杩欓噷浠呰褰曡秴鏃舵椂闂�
}
}
\ No newline at end of file
--
Gitblit v1.8.0