package com.billion.main.plc.sub; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.billion.main.da.domain.DaCollectionParamConf; import com.billion.main.da.domain.DaParamCollection; import com.billion.main.da.domain.DaStationCollection; import com.billion.main.da.domain.DaTightenCollection; import com.billion.main.da.service.IDaCollectionParamConfService; import com.billion.main.da.service.IDaParamCollectionService; import com.billion.main.da.service.IDaStationCollectionService; import com.billion.main.da.service.IDaTightenCollectionService; import com.billion.main.plc.constant.Constants; import com.billion.main.sc.domain.ScCollectionParamConf; import com.billion.main.sc.service.IScCollectionParamConfService; import com.billion.system.domain.SysNotice; import com.billion.system.service.impl.SysNoticeServiceImpl; 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.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; 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 { private static final Logger logger = LoggerFactory.getLogger("sys-user"); public static MiloService miloService; public static IScCollectionParamConfService collectionParamConfService; public static IDaParamCollectionService paramCollectionService; public static IDaStationCollectionService stationCollectionService; public static IDaCollectionParamConfService daCollectionParamConfService; public static IDaTightenCollectionService daTightenCollectionService; public static SysNoticeServiceImpl sysNoticeService; public OPCUaSubscription(MiloService miloService, IScCollectionParamConfService collectionParamConfService ,IDaParamCollectionService paramCollectionService,IDaStationCollectionService stationCollectionService,SysNoticeServiceImpl sysNoticeService ,IDaCollectionParamConfService daCollectionParamConfService,IDaTightenCollectionService daTightenCollectionService) { OPCUaSubscription.miloService = miloService; OPCUaSubscription.collectionParamConfService = collectionParamConfService; OPCUaSubscription.paramCollectionService = paramCollectionService; OPCUaSubscription.stationCollectionService = stationCollectionService; OPCUaSubscription.sysNoticeService = sysNoticeService; OPCUaSubscription.daCollectionParamConfService = daCollectionParamConfService; OPCUaSubscription.daTightenCollectionService = daTightenCollectionService; } @Override public void onSubscribe(String identifier, Object value) { log.info("地址:"+identifier+"值:"+value); try { if(ObjUtil.isNotNull(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 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)){ if(valueString.equals(Constants.ONE)){ // Object StationStatusObject = miloService.readFromOpcUa(thoroughfare + "." + device + ".StationStatus").getValue(); // if (ObjUtil.isNotNull(StationStatusObject)){ // String StationStatus = StationStatusObject.toString(); // if (!Constants.ONE.equals(StationStatus)){ // miloService.writeToOpcShort(ReadWriteEntity.builder().identifier(thoroughfare + "." + device + ".RecordDataDone").value(Constants.INTEGER_ONE_TWO).build()); // } else { // miloService.writeToOpcShort(ReadWriteEntity.builder().identifier(thoroughfare + "." + device + ".RecordDataDone").value(Constants.INTEGER_ONE_ONE).build()); // } // } miloService.writeToOpcShort(ReadWriteEntity.builder().identifier(thoroughfare + "." + device + ".RecordDataDone").value(Constants.INTEGER_ONE_ONE).build()); } else if(valueString.equals(Constants.TWO)){ //如果是2做出站处理 Object SNCodeObject = miloService.readFromOpcUa(thoroughfare + "." + device + ".SNCode").getValue(); if (ObjUtil.isNotNull(SNCodeObject)){ String SnCode = SNCodeObject.toString(); if (StrUtil.isNotBlank(SnCode)){ savePassingStation(thoroughfare,device,SnCode); saveParamCollection(device, SnCode, "stationStatus"); } } Integer result = Constants.INTEGER_TWO_ONE; miloService.writeToOpcShort(ReadWriteEntity.builder().identifier(thoroughfare + "." + device + ".RecordDataDone").value(result).build()); } } else if (tab.startsWith("OP")){ //处理设备报警 if (Constants.FIVE.equals(valueString)){ //重置 List list = sysNoticeService.list(new LambdaQueryWrapper() .eq(SysNotice::getNoticeTitle, tab) .eq(SysNotice::getStatus, Constants.ONE) .eq(SysNotice::getNoticeType,valueString)); if (CollUtil.isNotEmpty(list)){ list.forEach(x ->{ x.setStatus(Constants.ZERO); }); sysNoticeService.updateBatchById(list); } } else { SysNotice sysNotice = new SysNotice(); sysNotice.setNoticeTitle(tab); sysNotice.setNoticeType(valueString); String type = ""; if (Constants.ONE.equals(valueString)){ type = "缺料"; } else if (Constants.TWO.equals(valueString)){ type = "故障"; } else if (Constants.THREE.equals(valueString)){ type = "设备"; } else if (Constants.FOUR.equals(valueString)){ type = "急停"; } String content = tab + "工位" +type+ "报警"; sysNotice.setNoticeContent(content); sysNotice.setStatus(Constants.ONE); sysNoticeService.insertNotice(sysNotice); } } }catch (Exception e) { log.error(e.getMessage()); } } /** * 保存过站数据 * * @param device 工位 * @param snCode 产品序列号 * @return Integer * @throws Exception e */ private static void savePassingStation(String thoroughfare, String device, String snCode){ try { DaStationCollection daStationCollection = new DaStationCollection(); daStationCollection.setSfcCode(snCode); daStationCollection.setLocationCode(device); daStationCollection.setInboundTime(new Date()); daStationCollection.setOutboundTime(new Date()); Object StationStatusObject = miloService.readFromOpcUa(thoroughfare + "." + device + ".StationStatus").getValue(); if (ObjUtil.isNotNull(StationStatusObject)){ String StationStatus = StationStatusObject.toString(); daStationCollection.setStatus(StationStatus); } daStationCollection.setCollectTime(new Date()); stationCollectionService.insertDaStationCollection(daStationCollection); } catch (Exception e) { throw new RuntimeException(e); } } /** * 保存参数数据和发送工厂MES * @param device 工位 * @param snCode 产品SN * @param stationStatus 站状态 * @return result * @throws Exception e */ private static void saveParamCollection(String device, String snCode, String stationStatus) { try { // 查询参数配置表 List list = daCollectionParamConfService.list(new LambdaQueryWrapper() .eq(DaCollectionParamConf::getProcessesCode, device) .eq(DaCollectionParamConf::getRemarks, Constants.ONE) .orderByAsc(DaCollectionParamConf::getGatherSequence) ); if (CollUtil.isNotEmpty(list)) { // 获取参数值 List collect = list.stream() .map(DaCollectionParamConf::getGatherAddress) .map(String::trim) .collect(Collectors.toList()); List 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("保存数据异常"); } } /** * 保存采集数据 */ private static void saveCollectionData(String device, String snCode, List list, List readWriteEntityList) { ArrayList collectionList = new ArrayList<>(); if(Constants.TIGHTENCOLLECTION_LIST.contains(device)){ //存拧紧数据 try { LinkedHashMap> groupMap = new LinkedHashMap<>(); for (int i = 0; i < list.size(); i += 3) { try { String groupKey = String.valueOf(i/3); String paramSetName = list.get(i).getParameterSetName(); int secondSlash = paramSetName.indexOf("/", paramSetName.indexOf("/") + 1); paramSetName = secondSlash > 0 ? paramSetName.substring(0, secondSlash) : paramSetName; Map paramMap = new HashMap<>(); // 获取扭矩值 Object torqueObj = readWriteEntityList.get(i).getValue(); String torqueValue = torqueObj == null ? null : torqueObj.toString(); if (torqueValue != null && !"0.0".equals(torqueValue)) { paramMap.put("torque", Double.parseDouble(torqueValue)); } // 获取角度值 Object angleObj = readWriteEntityList.get(i + 1).getValue(); String angleValue = angleObj == null ? null : angleObj.toString(); if (angleValue != null && !"0.0".equals(angleValue)) { paramMap.put("angle", Double.parseDouble(angleValue)); } // 获取状态值 Object statusObj = readWriteEntityList.get(i + 2).getValue(); String statusValue = statusObj == null ? null : statusObj.toString(); if (statusValue != null && !"0.0".equals(statusValue)) { paramMap.put("angleStatus", statusValue); paramMap.put("paramSetName", paramSetName); groupMap.put(groupKey, paramMap); } } catch (Exception e) { logger.error("{}发动机拧紧数据第{}组处理失败: {}", snCode, i/3, e.getMessage()); } } List tightenList = new ArrayList<>(); for (Map paramMap : groupMap.values()) { try { DaTightenCollection tighten = new DaTightenCollection(); tighten.setSfcCode(snCode); tighten.setLocationCode(device); tighten.setParamSetName((String) paramMap.get("paramSetName")); tighten.setTorque(paramMap.get("torque") != null ? paramMap.get("torque").toString() : null); tighten.setAngle(paramMap.get("angle") != null ? paramMap.get("angle").toString() : null); tighten.setAngleStatus((String) paramMap.get("angleStatus")); tighten.setCollectTime(new Date()); tightenList.add(tighten); } catch (Exception e) { logger.error("{}发动机拧紧数据对象转换失败: {}", snCode, e.getMessage()); } } if(tightenList.size()>0){ try { daTightenCollectionService.saveBeachDaTightenCollection(tightenList); logger.info("{}发动机存拧紧数据保存完成",snCode); } catch (Exception e) { logger.error("{}发动机拧紧数据批量保存失败: {}", snCode, e.getMessage()); } } } catch (Exception e) { logger.error("{}发动机拧紧数据处理异常: {}", snCode, e.getMessage()); } }else { for (int i = 0; i < readWriteEntityList.size(); i++) { DaParamCollection daParamCollection = new DaParamCollection(); daParamCollection.setSfcCode(snCode); daParamCollection.setLocationCode(device); daParamCollection.setParamCode(list.get(i).getParameterSetCode()); daParamCollection.setParamName(list.get(i).getParameterSetName()); daParamCollection.setParamValue(readWriteEntityList.get(i).getValue().toString()); daParamCollection.setCollectTime(new Date()); collectionList.add(daParamCollection); } paramCollectionService.insertBatch(collectionList); } } /** * 创建工位对象并赋值 */ private static Object createStationObject(String device, List list, List 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 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; } }