huang
2025-11-18 1566e4c7604d85737ea67fe6757e71b8185fa48e
mes-processes/mes-plcSend/src/main/java/com/mes/service/impl/PlcDynamicDataServiceImpl.java
@@ -1,8 +1,12 @@
package com.mes.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.xingshuangs.iot.common.enums.EDataType;
import com.github.xingshuangs.iot.protocol.s7.serializer.S7Parameter;
import com.mes.device.entity.DeviceConfig;
import com.mes.device.util.ConfigJsonHelper;
import com.mes.entity.PlcAddress;
import com.mes.s7.enhanced.EnhancedS7Serializer;
import com.mes.service.PlcDynamicDataService;
@@ -10,6 +14,7 @@
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -24,6 +29,9 @@
@Slf4j
@Service
public class PlcDynamicDataServiceImpl implements PlcDynamicDataService {
    private final ObjectMapper objectMapper = new ObjectMapper();
    private static final TypeReference<Map<String, Object>> MAP_TYPE = new TypeReference<Map<String, Object>>() {};
    /**
     * 根据PlcAddress配置和字段名称读取PLC数据
@@ -59,8 +67,8 @@
            
            return resultMap;
        } catch (Exception e) {
            log.error("读取PLC数据失败,请检查:1.PLC IP地址是否正确[{}] 2.PLC设备是否在线 3.网络连接是否正常,module: {}, 详细错误: {}",
                config.getPlcIp(), config.getModule(), e.getMessage(), e);
            log.error("读取PLC数据失败,请检查:1.PLC IP地址是否正确[{}] 2.PLC设备是否在线 3.网络连接是否正常,详细错误: {}",
                config.getPlcIp(), e.getMessage(), e);
            return new HashMap<>();
        }
    }
@@ -88,8 +96,8 @@
            // 写入PLC
            s7Serializer.write(parameters);
        } catch (Exception e) {
            log.error("写入PLC数据失败,请检查:1.PLC IP地址是否正确[{}] 2.PLC设备是否在线 3.网络连接是否正常,module: {}, 详细错误: {}",
                config.getPlcIp(), config.getModule(), e.getMessage(), e);
            log.error("写入PLC数据失败,请检查:1.PLC IP地址是否正确[{}] 2.PLC设备是否在线 3.网络连接是否正常,详细错误: {}",
                config.getPlcIp(), e.getMessage(), e);
        }
    }
@@ -212,4 +220,287 @@
        
        return parameters;
    }
    /**
     * 从DeviceConfig中提取地址映射配置
     *
     * @param device 设备配置
     * @return 地址映射JSON字符串
     */
    private String extractAddressMapping(DeviceConfig device) {
        // configJson 现在仅存放字段地址映射(数组形式)
        Map<String, Object> configParams = ConfigJsonHelper.parseToMap(device.getConfigJson(), objectMapper);
        if (!configParams.isEmpty()) {
            try {
                return objectMapper.writeValueAsString(configParams);
            } catch (Exception e) {
                log.warn("序列化configJson地址映射失败, deviceId={}", device.getId(), e);
            }
        }
        // 其次从extraParams中获取(兼容旧结构)
        Map<String, Object> extraParams = parseExtraParams(device);
        Object addressMapping = extraParams.get("addressMapping");
        if (addressMapping != null) {
            if (addressMapping instanceof String) {
                return (String) addressMapping;
            } else {
                try {
                    return objectMapper.writeValueAsString(addressMapping);
                } catch (Exception e) {
                    log.warn("序列化extraParams.addressMapping失败, deviceId={}", device.getId(), e);
                }
            }
        }
        throw new IllegalArgumentException("设备配置中未找到addressMapping, deviceId=" + device.getId());
    }
    /**
     * 从DeviceConfig中提取dbArea
     *
     * @param device 设备配置
     * @return dbArea
     */
    private String extractDbArea(DeviceConfig device) {
        // 从extraParams.plcConfig中获取(新结构)
        Map<String, Object> plcConfig = getPlcConfig(device);
        Object dbArea = plcConfig.get("dbArea");
        if (dbArea != null) {
            return String.valueOf(dbArea);
        }
        // 兼容旧结构:extraParams根节点
        Map<String, Object> extraParams = parseExtraParams(device);
        Object legacyDbArea = extraParams.get("dbArea");
        if (legacyDbArea != null) {
            return String.valueOf(legacyDbArea);
        }
        // 默认值
        return "DB12";
    }
    /**
     * 从DeviceConfig中提取beginIndex
     *
     * @param device 设备配置
     * @return beginIndex
     */
    private int extractBeginIndex(DeviceConfig device) {
        // 从extraParams.plcConfig中获取
        Map<String, Object> plcConfig = getPlcConfig(device);
        Object beginIndex = plcConfig.get("beginIndex");
        if (beginIndex != null) {
            return parseInteger(beginIndex);
        }
        // 兼容旧结构:extraParams根节点
        Map<String, Object> extraParams = parseExtraParams(device);
        Object legacyBeginIndex = extraParams.get("beginIndex");
        if (legacyBeginIndex != null) {
            return parseInteger(legacyBeginIndex);
        }
        // 默认值
        return 0;
    }
    private Map<String, Object> parseExtraParams(DeviceConfig device) {
        if (device.getExtraParams() == null || device.getExtraParams().trim().isEmpty()) {
            return Collections.emptyMap();
        }
        try {
            return objectMapper.readValue(device.getExtraParams(), MAP_TYPE);
        } catch (Exception e) {
            log.warn("解析设备extraParams失败, deviceId={}", device.getId(), e);
            return Collections.emptyMap();
        }
    }
    @SuppressWarnings("unchecked")
    private Map<String, Object> getPlcConfig(DeviceConfig device) {
        Map<String, Object> extraParams = parseExtraParams(device);
        Object plcConfig = extraParams.get("plcConfig");
        if (plcConfig instanceof Map) {
            return (Map<String, Object>) plcConfig;
        }
        if (plcConfig instanceof String) {
            try {
                return objectMapper.readValue((String) plcConfig, MAP_TYPE);
            } catch (Exception e) {
                log.warn("解析extraParams.plcConfig失败, deviceId={}", device.getId(), e);
            }
        }
        return Collections.emptyMap();
    }
    private int parseInteger(Object value) {
        if (value instanceof Number) {
            return ((Number) value).intValue();
        }
        try {
            return Integer.parseInt(String.valueOf(value));
        } catch (NumberFormatException ex) {
            log.warn("无法解析整数值: {}", value);
            return 0;
        }
    }
    @Override
    public Map<String, Object> readPlcData(DeviceConfig device, List<String> fieldNames, EnhancedS7Serializer s7Serializer) {
        if (device == null) {
            throw new IllegalArgumentException("设备配置不能为空");
        }
        String addressMapping = extractAddressMapping(device);
        if (addressMapping == null || addressMapping.isEmpty()) {
            throw new IllegalArgumentException("设备配置中addressMapping不能为空");
        }
        try {
            // 解析addressMapping JSON配置
            JSONObject addressMappingObj = JSONObject.parseObject(addressMapping);
            // 构建S7Parameter列表
            String dbArea = extractDbArea(device);
            List<S7Parameter> parameters = buildS7ParametersForDevice(device, dbArea, addressMappingObj, 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.网络连接是否正常,deviceId: {}, 详细错误: {}",
                device.getPlcIp(), device.getId(), e.getMessage(), e);
            return new HashMap<>();
        }
    }
    @Override
    public void writePlcData(DeviceConfig device, Map<String, Object> dataMap, EnhancedS7Serializer s7Serializer) {
        if (device == null) {
            throw new IllegalArgumentException("设备配置不能为空");
        }
        String addressMapping = extractAddressMapping(device);
        if (addressMapping == null || addressMapping.isEmpty()) {
            throw new IllegalArgumentException("设备配置中addressMapping不能为空");
        }
        try {
            // 解析addressMapping JSON配置
            JSONObject addressMappingObj = JSONObject.parseObject(addressMapping);
            // 构建S7Parameter列表,并填充值
            String dbArea = extractDbArea(device);
            List<S7Parameter> parameters = buildS7ParametersWithValuesForDevice(device, dbArea, addressMappingObj, dataMap);
            // 写入PLC
            s7Serializer.write(parameters);
        } catch (Exception e) {
            log.error("写入PLC数据失败,请检查:1.PLC IP地址是否正确[{}] 2.PLC设备是否在线 3.网络连接是否正常,deviceId: {}, 详细错误: {}",
                device.getPlcIp(), device.getId(), e.getMessage(), e);
        }
    }
    @Override
    public Map<String, Object> readAllPlcData(DeviceConfig device, EnhancedS7Serializer s7Serializer) {
        if (device == null) {
            throw new IllegalArgumentException("设备配置不能为空");
        }
        String addressMapping = extractAddressMapping(device);
        if (addressMapping == null || addressMapping.isEmpty()) {
            throw new IllegalArgumentException("设备配置中addressMapping不能为空");
        }
        // 获取所有字段名
        JSONObject addressMappingObj = JSONObject.parseObject(addressMapping);
        List<String> allFields = new ArrayList<>(addressMappingObj.keySet());
        // 读取所有字段
        return readPlcData(device, allFields, s7Serializer);
    }
    @Override
    public Object readPlcField(DeviceConfig device, String fieldName, EnhancedS7Serializer s7Serializer) {
        List<String> fields = new ArrayList<>();
        fields.add(fieldName);
        Map<String, Object> result = readPlcData(device, fields, s7Serializer);
        return result.get(fieldName);
    }
    @Override
    public void writePlcField(DeviceConfig device, String fieldName, Object value, EnhancedS7Serializer s7Serializer) {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put(fieldName, value);
        writePlcData(device, dataMap, s7Serializer);
    }
    /**
     * 构建S7Parameter列表(不包含值)- 基于DeviceConfig
     */
    private List<S7Parameter> buildS7ParametersForDevice(DeviceConfig device, String dbArea, 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 = dbArea + "." + offset;
            // 创建S7Parameter,默认使用UINT16类型(16位无符号整数)
            S7Parameter parameter = new S7Parameter(fullAddress, EDataType.UINT16, 1);
            parameters.add(parameter);
        }
        return parameters;
    }
    /**
     * 构建S7Parameter列表(包含值)- 基于DeviceConfig
     */
    private List<S7Parameter> buildS7ParametersWithValuesForDevice(DeviceConfig device, String dbArea, 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 = dbArea + "." + offset;
            // 创建S7Parameter,设置值
            S7Parameter parameter = new S7Parameter(fullAddress, EDataType.UINT16, 1);
            parameter.setValue(value);
            parameters.add(parameter);
        }
        return parameters;
    }
}