add
吴健
9 天以前 f48c38125956578611832f6017b0cb2ffdbe3725
billion-main/src/main/java/com/billion/main/plc/sub/OPCUaSubscription.java
@@ -1,286 +1,237 @@
package com.billion.main.plc.sub;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.billion.main.api.domain.StationST180;
import com.billion.main.da.domain.DaParamCollection;
import com.billion.main.da.service.IDaParamCollectionService;
import com.billion.main.da.service.IDaStationCollectionService;
import com.billion.main.plc.constant.Constants;
import com.billion.main.sc.domain.ScCollectionParamConf;
import com.billion.main.sc.service.IScCollectionParamConfService;
import com.kangaroohy.milo.model.ReadWriteEntity;
import com.kangaroohy.milo.runner.subscription.SubscriptionCallback;
import com.kangaroohy.milo.service.MiloService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.lang.reflect.Field;
@Slf4j
@Component
public class OPCUaSubscription implements SubscriptionCallback {
    public static MiloService miloService;
    public static IScCollectionParamConfService collectionParamConfService;
    public static IDaParamCollectionService paramCollectionService;
    public static IDaStationCollectionService stationCollectionService;
    public OPCUaSubscription(MiloService miloService, IScCollectionParamConfService collectionParamConfService
            ,IDaParamCollectionService paramCollectionService,IDaStationCollectionService stationCollectionService) {
        OPCUaSubscription.miloService = miloService;
        OPCUaSubscription.collectionParamConfService = collectionParamConfService;
        OPCUaSubscription.paramCollectionService = paramCollectionService;
        OPCUaSubscription.stationCollectionService = stationCollectionService;
    }
    @Override
    public void onSubscribe(String identifier, Object value) {
        log.info("地址:"+identifier+"值:"+value);
        try {
            if(null != value && !Constants.ZERO.equals(value.toString())) {
                String[] nodes = identifier.split("[.]");
                String thoroughfare = nodes[0];//通道
                String device = nodes[1];//设备
                String tab = nodes[2];//标记
                String valueString = value.toString();//地址值
                CompletableFuture<Void> cp1 = CompletableFuture.runAsync(() -> {
                    subHandle(thoroughfare,device,tab,valueString);
                });
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }
    public void subHandle(String thoroughfare,String device,String tab,String valueString){
        try{
            //监听recordData
            if(tab.equals(Constants.RECORD_DATA)){
                //如果是2做出站处理
                if(valueString.equals(Constants.TWO)){
                    Integer result = Constants.INTEGER_TWO_ONE;
                    result = saveParamCollection(device, "snCode", "stationStatus");
                    miloService.writeToOpcShort(ReadWriteEntity.builder().identifier(thoroughfare + "." + device + ".RecordDataDone").value(result).build());
                }
            }
        }catch (Exception e) {
            log.error(e.getMessage());
        }
    }
    /**
     * 保存过站数据
     *
     * @param device       工位
     * @param snCode       产品序列号
     * @return Integer
     * @throws Exception e
     */
    private static Integer savePassingStation(String device, String snCode,String stationStatus){
        Integer result = 21;
        try {
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return result;
    }
    /**
     * 保存参数数据和发送工厂MES
     * @param device 工位
     * @param snCode 产品SN
     * @param stationStatus 站状态
     * @return result
     * @throws Exception e
     */
    private static Integer saveParamCollection(String device, String snCode, String stationStatus) {
        Integer result = Constants.INTEGER_TWO_ONE;
        try {
            // 查询参数配置表
            List<ScCollectionParamConf> list = collectionParamConfService.list(new LambdaQueryWrapper<ScCollectionParamConf>()
                    .eq(ScCollectionParamConf::getLocationCode, device)
                    .eq(ScCollectionParamConf::getSubscribe, Constants.ONE)
                    .orderByDesc(ScCollectionParamConf::getOrderNum)
            );
            if (CollUtil.isNotEmpty(list)) {
                // 获取参数值
                List<String> collect = list.stream()
                        .map(ScCollectionParamConf::getNode)
                        .collect(Collectors.toList());
                List<ReadWriteEntity> readWriteEntityList = miloService.readFromOpcUa(collect);
                // 保存采集数据
                saveCollectionData(device, snCode, list, readWriteEntityList);
                // 创建工位对象并赋值
                Object stationObject = createStationObject(device, list, readWriteEntityList);
                if (stationObject != null) {
                    System.out.println("工位" + device + "对象创建成功:" + stationObject);
                    // 这里可以对创建的对象进行进一步处理
                    handleMesRequest(stationObject, device);
                }
            }
        } catch (Exception e) {
            log.error("保存数据异常", e);
            throw new RuntimeException("保存数据发送工厂MES异常");
        }
        return result;
    }
    /**
     * 保存采集数据
     */
    private static void saveCollectionData(String device, String snCode,
            List<ScCollectionParamConf> list, List<ReadWriteEntity> readWriteEntityList) {
        ArrayList<DaParamCollection> collectionList = new ArrayList<>();
        for (int i = 0; i < readWriteEntityList.size(); i++) {
            DaParamCollection daParamCollection = new DaParamCollection();
            daParamCollection.setSfcCode(snCode);
            daParamCollection.setLocationCode(device);
            daParamCollection.setParamCode(list.get(i).getParamCode());
            daParamCollection.setParamName(list.get(i).getParamName());
            daParamCollection.setParamValue(readWriteEntityList.get(i).getValue().toString());
            daParamCollection.setCollectTime(new Date());
            collectionList.add(daParamCollection);
        }
        paramCollectionService.insertBatch(collectionList);
    }
    /**
     * 创建工位对象并赋值
     */
    private static Object createStationObject(String device,
            List<ScCollectionParamConf> list, List<ReadWriteEntity> readWriteEntityList) {
        try {
            // 构建完整的类名
            String className = "com.billion.main.api.domain.Station" + device;
            Class<?> stationClass = Class.forName(className);
            Object stationObject = stationClass.newInstance();
            // 获取所有属性
            Field[] fields = stationClass.getDeclaredFields();
            // 创建参数值Map,方便查找
            Map<String, String> paramValueMap = new HashMap<>();
            for (int i = 0; i < list.size(); i++) {
                paramValueMap.put(list.get(i).getParamCode(),
                    readWriteEntityList.get(i).getValue().toString());
            }
            // 按顺序给属性赋值
            for (Field field : fields) {
                field.setAccessible(true);
                String paramCode = field.getName(); // 假设属性名与参数编码一致
                String value = paramValueMap.get(paramCode);
                if (value != null) {
                    // 根据字段类型转换值
                    Object convertedValue = convertValue(value, field.getType());
                    field.set(stationObject, convertedValue);
                }
            }
            return stationObject;
        } catch (Exception e) {
            log.error("创建工位对象失败:" + device, e);
            return null;
        }
    }
    /**
     * 根据字段类型转换值
     */
    private static Object convertValue(String value, Class<?> type) {
        if (type == String.class) {
            return value;
        } else if (type == Integer.class || type == int.class) {
            return Integer.parseInt(value);
        } else if (type == Double.class || type == double.class) {
            return Double.parseDouble(value);
        } else if (type == Float.class || type == float.class) {
            return Float.parseFloat(value);
        } else if (type == Long.class || type == long.class) {
            return Long.parseLong(value);
        } else if (type == Boolean.class || type == boolean.class) {
            return Boolean.parseBoolean(value);
        } else if (type == Date.class) {
            try {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                return sdf.parse(value);
            } catch (ParseException e) {
                return null;
            }
        }
        return value;
    }
    private static void handleMesRequest(Object stationObject, String device) {
        try {
            // 发送HTTP请求
            HttpResponse response = HttpRequest.post(Constants.SY_MES_URL)
                    .body(JSONUtil.toJsonStr(stationObject))
                    .timeout(5000) // 设置超时时间
                    .execute();
            // 解析响应
            if (response.isOk()) { // 请求成功
                JSONObject jsonResponse = JSONUtil.parseObj(response.body());
                String message = jsonResponse.getStr("message");
                if (!"ok".equals(message)) {
                    // 响应不是ok,保存失败记录
                    saveMesFailRecord(stationObject, device, "响应异常:" + message);
                }
            } else {
                // HTTP请求失败,保存失败记录
                saveMesFailRecord(stationObject, device, "HTTP状态码:" + response.getStatus());
            }
        } catch (Exception e) {
            // 发生异常(比如连接超时、服务不可用等),保存失败记录
            saveMesFailRecord(stationObject, device, "请求异常:" + e.getMessage());
        }
    }
    /**
     * 保存MES推送失败记录
     */
    private static void saveMesFailRecord(Object stationObject, String device, String errorMsg) {
        try {
            MesFailRecord failRecord = new MesFailRecord();
            failRecord.setDeviceCode(device);
            failRecord.setRequestData(JSONUtil.toJsonStr(stationObject));
            failRecord.setErrorMsg(errorMsg);
            failRecord.setCreateTime(new Date());
            failRecord.setStatus(0); // 0:未处理 1:已处理
            failRecord.setRetryCount(0); // 重试次数
            // 保存到数据库
            mesFailRecordService.save(failRecord);
            log.error("MES推送失败,已保存失败记录。设备:{},错误:{}", device, errorMsg);
        } catch (Exception e) {
            log.error("保存MES失败记录时发生错误", e);
        }
    }
}
//package com.billion.main.plc.sub;
//
//
//import cn.hutool.core.collection.CollUtil;
//import cn.hutool.core.util.ObjectUtil;
//import cn.hutool.http.HttpRequest;
//import cn.hutool.http.HttpResponse;
//import cn.hutool.json.JSONUtil;
//import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
//import com.billion.main.api.domain.StationST180;
//import com.billion.main.da.domain.DaParamCollection;
//import com.billion.main.da.service.IDaParamCollectionService;
//import com.billion.main.da.service.IDaStationCollectionService;
//import com.billion.main.plc.constant.Constants;
//import com.billion.main.sc.domain.ScCollectionParamConf;
//import com.billion.main.sc.service.IScCollectionParamConfService;
//import com.kangaroohy.milo.model.ReadWriteEntity;
//import com.kangaroohy.milo.runner.subscription.SubscriptionCallback;
//import com.kangaroohy.milo.service.MiloService;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.stereotype.Component;
//import com.alibaba.fastjson.JSONObject;
//
//import java.text.ParseException;
//import java.text.SimpleDateFormat;
//import java.util.*;
//import java.util.concurrent.CompletableFuture;
//import java.util.stream.Collectors;
//import java.lang.reflect.Field;
//
//
//@Slf4j
//@Component
//public class OPCUaSubscription implements SubscriptionCallback {
//
//    public static MiloService miloService;
//    public static IScCollectionParamConfService collectionParamConfService;
//    public static IDaParamCollectionService paramCollectionService;
//    public static IDaStationCollectionService stationCollectionService;
//
//    public OPCUaSubscription(MiloService miloService, IScCollectionParamConfService collectionParamConfService
//            ,IDaParamCollectionService paramCollectionService,IDaStationCollectionService stationCollectionService) {
//        OPCUaSubscription.miloService = miloService;
//        OPCUaSubscription.collectionParamConfService = collectionParamConfService;
//        OPCUaSubscription.paramCollectionService = paramCollectionService;
//        OPCUaSubscription.stationCollectionService = stationCollectionService;
//    }
//
//    @Override
//    public void onSubscribe(String identifier, Object value) {
//        log.info("地址:"+identifier+"值:"+value);
//        try {
//            if(null != value && !Constants.ZERO.equals(value.toString())) {
//                String[] nodes = identifier.split("[.]");
//                String thoroughfare = nodes[0];//通道
//                String device = nodes[1];//设备
//                String tab = nodes[2];//标记
//                String valueString = value.toString();//地址值
//
//                CompletableFuture<Void> cp1 = CompletableFuture.runAsync(() -> {
//                    subHandle(thoroughfare,device,tab,valueString);
//                });
//
//            }
//        } catch (Exception e) {
//            log.error(e.getMessage());
//        }
//    }
//
//    public void subHandle(String thoroughfare,String device,String tab,String valueString){
//        try{
//            //监听recordData
//            if(tab.equals(Constants.RECORD_DATA)){
//                //如果是2做出站处理
//                if(valueString.equals(Constants.TWO)){
//                    Integer result = Constants.INTEGER_TWO_ONE;
//                    result = saveParamCollection(device, "snCode", "stationStatus");
//                    miloService.writeToOpcShort(ReadWriteEntity.builder().identifier(thoroughfare + "." + device + ".RecordDataDone").value(result).build());
//                }
//            }
//        }catch (Exception e) {
//            log.error(e.getMessage());
//        }
//    }
//
//    /**
//     * 保存过站数据
//     *
//     * @param device       工位
//     * @param snCode       产品序列号
//     * @return Integer
//     * @throws Exception e
//     */
//    private static Integer savePassingStation(String device, String snCode,String stationStatus){
//        Integer result = 21;
//        try {
//
//
//        } catch (Exception e) {
//            throw new RuntimeException(e);
//        }
//
//        return result;
//    }
//
//    /**
//     * 保存参数数据和发送工厂MES
//     * @param device 工位
//     * @param snCode 产品SN
//     * @param stationStatus 站状态
//     * @return result
//     * @throws Exception e
//     */
//    private static Integer saveParamCollection(String device, String snCode, String stationStatus) {
//        Integer result = Constants.INTEGER_TWO_ONE;
//        try {
//            // 查询参数配置表
//            List<ScCollectionParamConf> list = collectionParamConfService.list(new LambdaQueryWrapper<ScCollectionParamConf>()
//                    .eq(ScCollectionParamConf::getLocationCode, device)
//                    .eq(ScCollectionParamConf::getSubscribe, Constants.ONE)
//                    .orderByDesc(ScCollectionParamConf::getOrderNum)
//            );
//
//            if (CollUtil.isNotEmpty(list)) {
//                // 获取参数值
//                List<String> collect = list.stream()
//                        .map(ScCollectionParamConf::getNode)
//                        .collect(Collectors.toList());
//                List<ReadWriteEntity> readWriteEntityList = miloService.readFromOpcUa(collect);
//
//                // 保存采集数据
//                saveCollectionData(device, snCode, list, readWriteEntityList);
//
//                // 创建工位对象并赋值
//                Object stationObject = createStationObject(device, list, readWriteEntityList);
//                if (stationObject != null) {
//                    System.out.println("工位" + device + "对象创建成功:" + stationObject);
//                    // 这里可以对创建的对象进行进一步处理
//
//                }
//            }
//
//        } catch (Exception e) {
//            log.error("保存数据异常", e);
//            throw new RuntimeException("保存数据发送工厂MES异常");
//        }
//        return result;
//    }
//
//    /**
//     * 保存采集数据
//     */
//    private static void saveCollectionData(String device, String snCode,
//            List<ScCollectionParamConf> list, List<ReadWriteEntity> readWriteEntityList) {
//        ArrayList<DaParamCollection> collectionList = new ArrayList<>();
//        for (int i = 0; i < readWriteEntityList.size(); i++) {
//            DaParamCollection daParamCollection = new DaParamCollection();
//            daParamCollection.setSfcCode(snCode);
//            daParamCollection.setLocationCode(device);
//            daParamCollection.setParamCode(list.get(i).getParamCode());
//            daParamCollection.setParamName(list.get(i).getParamName());
//            daParamCollection.setParamValue(readWriteEntityList.get(i).getValue().toString());
//            daParamCollection.setCollectTime(new Date());
//            collectionList.add(daParamCollection);
//        }
//        paramCollectionService.insertBatch(collectionList);
//    }
//
//    /**
//     * 创建工位对象并赋值
//     */
//    private static Object createStationObject(String device,
//            List<ScCollectionParamConf> list, List<ReadWriteEntity> readWriteEntityList) {
//        try {
//            // 构建完整的类名
//            String className = "com.billion.main.api.domain.Station" + device;
//            Class<?> stationClass = Class.forName(className);
//            Object stationObject = stationClass.newInstance();
//
//            // 获取所有属性
//            Field[] fields = stationClass.getDeclaredFields();
//
//            // 创建参数值Map,方便查找
//            Map<String, String> paramValueMap = new HashMap<>();
//            for (int i = 0; i < list.size(); i++) {
//                paramValueMap.put(list.get(i).getParamCode(),
//                    readWriteEntityList.get(i).getValue().toString());
//            }
//
//            // 按顺序给属性赋值
//            for (Field field : fields) {
//                field.setAccessible(true);
//                String paramCode = field.getName(); // 假设属性名与参数编码一致
//                String value = paramValueMap.get(paramCode);
//
//                if (value != null) {
//                    // 根据字段类型转换值
//                    Object convertedValue = convertValue(value, field.getType());
//                    field.set(stationObject, convertedValue);
//                }
//            }
//
//            return stationObject;
//        } catch (Exception e) {
//            log.error("创建工位对象失败:" + device, e);
//            return null;
//        }
//    }
//
//    /**
//     * 根据字段类型转换值
//     */
//    private static Object convertValue(String value, Class<?> type) {
//        if (type == String.class) {
//            return value;
//        } else if (type == Integer.class || type == int.class) {
//            return Integer.parseInt(value);
//        } else if (type == Double.class || type == double.class) {
//            return Double.parseDouble(value);
//        } else if (type == Float.class || type == float.class) {
//            return Float.parseFloat(value);
//        } else if (type == Long.class || type == long.class) {
//            return Long.parseLong(value);
//        } else if (type == Boolean.class || type == boolean.class) {
//            return Boolean.parseBoolean(value);
//        } else if (type == Date.class) {
//            try {
//                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//                return sdf.parse(value);
//            } catch (ParseException e) {
//                return null;
//            }
//        }
//        return value;
//    }
//
//}