| | |
| | | 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; |
| | | // } |
| | | // |
| | | //} |