package com.mes.service.impl;
|
|
import com.alibaba.fastjson.JSONObject;
|
import com.github.xingshuangs.iot.common.enums.EDataType;
|
import com.github.xingshuangs.iot.protocol.s7.serializer.S7Parameter;
|
import com.mes.entity.PlcAddress;
|
import com.mes.s7.enhanced.EnhancedS7Serializer;
|
import com.mes.service.PlcDynamicDataService;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.stereotype.Service;
|
|
import java.util.ArrayList;
|
import java.util.HashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
/**
|
* PLC动态数据读写服务实现
|
* 通过PlcAddress中的addressMapping配置动态读写任意字段组合
|
*
|
* @author huang
|
* @date 2025/11/05
|
*/
|
@Slf4j
|
@Service
|
public class PlcDynamicDataServiceImpl implements PlcDynamicDataService {
|
|
/**
|
* 根据PlcAddress配置和字段名称读取PLC数据
|
*
|
* @param config PLC地址映射配置
|
* @param fieldNames 要读取的字段名称列表
|
* @param s7Serializer S7序列化器
|
* @return 字段名->值 的Map
|
*/
|
@Override
|
public Map<String, Object> readPlcData(PlcAddress config, List<String> fieldNames, EnhancedS7Serializer s7Serializer) {
|
if (config == null || config.getAddressMapping() == null) {
|
throw new IllegalArgumentException("PlcAddress配置或addressMapping不能为空");
|
}
|
|
try {
|
// 解析addressMapping JSON配置
|
JSONObject addressMapping = JSONObject.parseObject(config.getAddressMapping());
|
|
// 构建S7Parameter列表
|
List<S7Parameter> parameters = buildS7Parameters(config, addressMapping, fieldNames);
|
|
// 从PLC读取数据
|
List<S7Parameter> results = s7Serializer.read(parameters);
|
|
// 将结果转换为Map
|
Map<String, Object> resultMap = new HashMap<>();
|
for (int i = 0; i < fieldNames.size() && i < results.size(); i++) {
|
String fieldName = fieldNames.get(i);
|
Object value = results.get(i).getValue();
|
resultMap.put(fieldName, value);
|
}
|
|
return resultMap;
|
} catch (Exception e) {
|
log.error("读取PLC数据失败,请检查:1.PLC IP地址是否正确[{}] 2.PLC设备是否在线 3.网络连接是否正常,module: {}, 详细错误: {}",
|
config.getPlcIp(), config.getModule(), e.getMessage(), e);
|
return new HashMap<>();
|
}
|
}
|
|
/**
|
* 根据PlcAddress配置和数据Map写入PLC
|
*
|
* @param config PLC地址映射配置
|
* @param dataMap 字段名->值 的Map
|
* @param s7Serializer S7序列化器
|
*/
|
@Override
|
public void writePlcData(PlcAddress config, Map<String, Object> dataMap, EnhancedS7Serializer s7Serializer) {
|
if (config == null || config.getAddressMapping() == null) {
|
throw new IllegalArgumentException("PlcAddress配置或addressMapping不能为空");
|
}
|
|
try {
|
// 解析addressMapping JSON配置
|
JSONObject addressMapping = JSONObject.parseObject(config.getAddressMapping());
|
|
// 构建S7Parameter列表,并填充值
|
List<S7Parameter> parameters = buildS7ParametersWithValues(config, addressMapping, dataMap);
|
|
// 写入PLC
|
s7Serializer.write(parameters);
|
} catch (Exception e) {
|
log.error("写入PLC数据失败,请检查:1.PLC IP地址是否正确[{}] 2.PLC设备是否在线 3.网络连接是否正常,module: {}, 详细错误: {}",
|
config.getPlcIp(), config.getModule(), e.getMessage(), e);
|
}
|
}
|
|
/**
|
* 读取PLC所有字段
|
*
|
* @param config PLC地址映射配置
|
* @param s7Serializer S7序列化器
|
* @return 所有字段的值
|
*/
|
@Override
|
public Map<String, Object> readAllPlcData(PlcAddress config, EnhancedS7Serializer s7Serializer) {
|
if (config == null || config.getAddressMapping() == null) {
|
throw new IllegalArgumentException("PlcAddress配置或addressMapping不能为空");
|
}
|
|
// 获取所有字段名
|
JSONObject addressMapping = JSONObject.parseObject(config.getAddressMapping());
|
List<String> allFields = new ArrayList<>(addressMapping.keySet());
|
|
// 读取所有字段
|
return readPlcData(config, allFields, s7Serializer);
|
}
|
|
/**
|
* 读取单个字段
|
*
|
* @param config PLC地址映射配置
|
* @param fieldName 字段名
|
* @param s7Serializer S7序列化器
|
* @return 字段值
|
*/
|
@Override
|
public Object readPlcField(PlcAddress config, String fieldName, EnhancedS7Serializer s7Serializer) {
|
List<String> fields = new ArrayList<>();
|
fields.add(fieldName);
|
|
Map<String, Object> result = readPlcData(config, fields, s7Serializer);
|
return result.get(fieldName);
|
}
|
|
/**
|
* 写入单个字段
|
*
|
* @param config PLC地址映射配置
|
* @param fieldName 字段名
|
* @param value 字段值
|
* @param s7Serializer S7序列化器
|
*/
|
@Override
|
public void writePlcField(PlcAddress config, String fieldName, Object value, EnhancedS7Serializer s7Serializer) {
|
Map<String, Object> dataMap = new HashMap<>();
|
dataMap.put(fieldName, value);
|
|
writePlcData(config, dataMap, s7Serializer);
|
}
|
|
/**
|
* 构建S7Parameter列表(不包含值)
|
*
|
* @param config PLC地址配置
|
* @param addressMapping 地址映射
|
* @param fieldNames 字段名列表
|
* @return S7Parameter列表
|
*/
|
private List<S7Parameter> buildS7Parameters(PlcAddress config, JSONObject addressMapping, List<String> fieldNames) {
|
List<S7Parameter> parameters = new ArrayList<>();
|
|
for (String fieldName : fieldNames) {
|
if (!addressMapping.containsKey(fieldName)) {
|
log.warn("字段 {} 在addressMapping中不存在,跳过", fieldName);
|
continue;
|
}
|
|
// 获取字段的偏移地址
|
int offset = addressMapping.getInteger(fieldName);
|
|
// 构建完整地址:dbArea + offset(如:DB12.2)
|
String fullAddress = config.getDbArea() + "." + offset;
|
|
// 创建S7Parameter,默认使用UINT16类型(16位无符号整数)
|
S7Parameter parameter = new S7Parameter(fullAddress, EDataType.UINT16, 1);
|
parameters.add(parameter);
|
}
|
|
return parameters;
|
}
|
|
/**
|
* 构建S7Parameter列表(包含值)
|
*
|
* @param config PLC地址配置
|
* @param addressMapping 地址映射
|
* @param dataMap 字段名->值 的Map
|
* @return S7Parameter列表
|
*/
|
private List<S7Parameter> buildS7ParametersWithValues(PlcAddress config, JSONObject addressMapping, Map<String, Object> dataMap) {
|
List<S7Parameter> parameters = new ArrayList<>();
|
|
for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
|
String fieldName = entry.getKey();
|
Object value = entry.getValue();
|
|
if (!addressMapping.containsKey(fieldName)) {
|
log.warn("字段 {} 在addressMapping中不存在,跳过", fieldName);
|
continue;
|
}
|
|
// 获取字段的偏移地址
|
int offset = addressMapping.getInteger(fieldName);
|
|
// 构建完整地址
|
String fullAddress = config.getDbArea() + "." + offset;
|
|
// 创建S7Parameter,设置值
|
S7Parameter parameter = new S7Parameter(fullAddress, EDataType.UINT16, 1);
|
parameter.setValue(value);
|
parameters.add(parameter);
|
}
|
|
return parameters;
|
}
|
}
|