package com.mes.job; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.github.xingshuangs.iot.protocol.s7.serializer.S7Serializer; import com.mes.common.config.Const; import com.mes.engineering.entity.Engineering; import com.mes.engineering.mapper.EngineeringMapper; import com.mes.opctask.entity.LoadGlassDeviceTask; import com.mes.opctask.entity.LoadGlassDeviceTaskHistory; import com.mes.opctask.service.LoadGlassDeviceTaskHistoryService; import com.mes.opctask.service.LoadGlassDeviceTaskService; import com.mes.pp.entity.OptimizeProject; import com.mes.pp.service.OptimizeProjectService; import com.mes.rawglassdetails.entity.RawGlassStorageDetails; import com.mes.rawglassdetails.service.RawGlassStorageDetailsService; import com.mes.s7.entity.S7DataSP; import com.mes.uppattenusage.entity.UpPattenUsage; import com.mes.uppattenusage.entity.vo.UpPattenUsageVO; import com.mes.uppattenusage.mapper.UpPattenUsageMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * @Author : zhoush * @Date: 2024/10/23 14:30 * @Description: */ @Component @Slf4j public class OpcLoadGlassTask { @Resource private EngineeringMapper engineeringMapper; @Resource private LoadGlassDeviceTaskService loadGlassDeviceTaskService; @Resource private RawGlassStorageDetailsService rawGlassStorageDetailsService; @Resource private LoadGlassDeviceTaskHistoryService loadGlassDeviceTaskHistoryService; @Resource private UpPattenUsageMapper upPattenUsageMapper; @Resource private OptimizeProjectService optimizeProjectService; @Autowired @Qualifier("s7SerializerSPOne") private S7Serializer s7SerializerSPOne; @Autowired @Qualifier("s7SerializerSPTwo") private S7Serializer s7SerializerSPTwo; private static final List LOAD_STATION_01 = Arrays.asList(101, 102); private static final List LOAD_STATION_02 = Arrays.asList(103, 104); private static final Integer LOAD_GLASS_ONE_DEVICE = 5; private static final Integer LOAD_GLASS_TWO_DEVICE = 6; private static final String LOAD_GLASS_DEVICE_ONE_TASK = "load_glass_device_one_task"; private static final String LOAD_GLASS_DEVICE_TWO_TASK = "load_glass_device_two_task"; //设备id 上片位信息 任务表不一致 历史任务表公用一张 新增任务/任务结束,后会在历史表中新增一条记录并在结束后更新任务 一个任务即可 //定时任务扫描上片位有没有原片 //1、是否有在执行的任务 //2、1号上片位是否有原片,原片尺寸是否和上片待上片的尺寸一致 //3、1号无原片,且没有架子,2号上片位尺寸是否和带上片尺寸一致 //4、不一致可能出现玻璃破损导致的上一架原片数量不够 @Scheduled(fixedDelay = 5000) public void opcLoadGlassOne() { opcLoadGlassChild(LOAD_GLASS_DEVICE_ONE_TASK, LOAD_GLASS_ONE_DEVICE); } @Scheduled(fixedDelay = 5000) public void opcLoadGlassTwo() { opcLoadGlassChild(LOAD_GLASS_DEVICE_TWO_TASK, LOAD_GLASS_TWO_DEVICE); } @Scheduled(fixedDelay = 5000) public void opcLoadGlassOneFinish() { opcLoadGlassFinishChid(LOAD_GLASS_DEVICE_ONE_TASK, LOAD_GLASS_ONE_DEVICE); } @Scheduled(fixedDelay = 5000) public void opcLoadGlassTwoFinish() { opcLoadGlassFinishChid(LOAD_GLASS_DEVICE_TWO_TASK, LOAD_GLASS_TWO_DEVICE); } /** * 定时任务扫码已完成上片的工程,将工程状态改为已完成,同步pp表的工程表,状态改为300 */ @Scheduled(fixedDelay = 5000) public void updateEngineerState() { log.info("修改已完成工程状态任务开始执行"); List engineerings = engineeringMapper.selectList(new LambdaQueryWrapper().eq(Engineering::getState, Const.ENGINEERING_RUNNING)); for (Engineering engineering : engineerings) { Integer count = upPattenUsageMapper.selectCount(new LambdaQueryWrapper() .eq(UpPattenUsage::getEngineeringId, engineering.getEngineerId()).ne(UpPattenUsage::getState, Const.LOAD_RAW_GLASS_SUCCESS)); OptimizeProject project = optimizeProjectService.getOne(new LambdaUpdateWrapper() .eq(OptimizeProject::getProjectNo, 200) .eq(OptimizeProject::getState, engineering.getEngineerId())); if (count == 0 && project != null) { engineeringMapper.update(null, new LambdaUpdateWrapper().set(Engineering::getState, Const.ENGINEERING_SUCCESS) .eq(Engineering::getEngineerId, engineering.getEngineerId())); optimizeProjectService.update(null, new LambdaUpdateWrapper().set(OptimizeProject::getState, 300) .eq(OptimizeProject::getProjectNo, engineering.getEngineerId())); } } } private void opcLoadGlassChild(String tableName, Integer deviceId) { S7DataSP s7DataSP = new S7DataSP(); if (tableName.equals(LOAD_GLASS_DEVICE_ONE_TASK)) { s7DataSP = s7SerializerSPOne.read(S7DataSP.class); } else { s7DataSP = s7SerializerSPTwo.read(S7DataSP.class); } log.info("{}上片线,当前上片位信息:{}", deviceId, s7DataSP); Engineering engineering = engineeringMapper.selectOne(new LambdaQueryWrapper() .eq(Engineering::getState, Const.ENGINEERING_RUNNING).eq(Engineering::getStationCell, deviceId)); if (null == engineering) { log.info("{}上片线,没有工程任务", deviceId); return; } //任务暂停 S7DataSP task = new S7DataSP(); if ("0".equals(s7DataSP.getInkageState().toString())) { log.info("{}上片线,处于离线状态:{},结束本地上片请求", deviceId, s7DataSP.getInkageState().toString()); return; } if (s7DataSP.getTaskRunning()) { log.info("{}上片线,有正在执行的任务,结束本地上片请求", deviceId); return; } List pattenUsageList = upPattenUsageMapper.queryRawGlassByEngineeringId(engineering.getEngineerId()); log.info("按照当前获取到正在需要上片的原片信息有:{}", pattenUsageList); if (CollectionUtils.isEmpty(pattenUsageList)) { log.info("当前工程需要上片的原片信息为空,任务已结束"); //todo:是否将工程状态改为已完成 return; } Map> upListMap = pattenUsageList.stream() .collect(Collectors.groupingBy(UpPattenUsageVO::getGroupNumber)); log.info("获取当前需要上片的原片数据"); List usageVOS = upListMap.get("1"); // 获取1号上片位是有架子且有玻璃 List loadStation = LOAD_GLASS_DEVICE_ONE_TASK.equals(tableName) ? LOAD_STATION_01 : LOAD_STATION_02; List loadStationList = rawGlassStorageDetailsService.list(new LambdaQueryWrapper() .inSql(RawGlassStorageDetails::getSlot, "select slot from raw_glass_storage_station where enable_state = 1") .in(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN_ALL) .eq(RawGlassStorageDetails::getDeviceId, deviceId)); if (CollectionUtils.isEmpty(loadStationList)) { log.info("当前上片线路两个上片位都没有原片信息,结束本次上片任务,等待仓储调度任务"); return; } RawGlassStorageDetails oneLoadStation = loadStationList.stream().filter(e -> e.getSlot().equals(loadStation.get(0))).findFirst().orElse(null); if (null == oneLoadStation) { RawGlassStorageDetails twoLoadStation = loadStationList.stream().filter(e -> e.getSlot().equals(loadStation.get(1))).findFirst().orElse(null); if (!compareRawSize(usageVOS.get(0), twoLoadStation)) { log.info("二号上片位有架子,原片数量为0或者原片信息与待上片尺寸不一致,结束本次上片任务,等待仓储调度任务"); return; } int number = Math.min(twoLoadStation.getRemainQuantity(), usageVOS.size()); //生成上片任务 task.setTotalCount(number); task.setTaskRunning(Boolean.TRUE); task.setRawGlassWidth((int) usageVOS.get(0).getWidth()); task.setRawGlassHeight((int) usageVOS.get(0).getHeight()); task.setSlot(loadStation.get(1)); S7DataSP s7DataSPWrite = new S7DataSP(); s7DataSPWrite.setTotalCount(number); s7DataSPWrite.setTaskRunning(Boolean.TRUE); s7DataSPWrite.setRawGlassWidth((int) usageVOS.get(0).getWidth()); s7DataSPWrite.setRawGlassHeight((int) usageVOS.get(0).getHeight()); s7DataSPWrite.setSlot(loadStation.get(1)); if (LOAD_GLASS_ONE_DEVICE.equals(deviceId)) { s7SerializerSPOne.write(s7DataSPWrite); } else { s7SerializerSPTwo.write(s7DataSPWrite); } saveHistoryTask(task, deviceId); return; } //尺寸不一样或者原片数量大于0 if (!compareRawSize(usageVOS.get(0), oneLoadStation)) { log.info("一号上片位有架子,原片数量为0或者原片信息与待上片尺寸不一致,结束本次上片任务,等待仓储调度任务"); return; } //生成上片任务 int number = Math.min(oneLoadStation.getRemainQuantity(), usageVOS.size()); task.setTotalCount(number); task.setTaskRunning(Boolean.TRUE); task.setRawGlassWidth((int) usageVOS.get(0).getWidth()); task.setRawGlassHeight((int) usageVOS.get(0).getHeight()); task.setSlot(loadStation.get(0)); S7DataSP s7DataSPWrite = new S7DataSP(); s7DataSPWrite.setTotalCount(number); s7DataSPWrite.setTaskRunning(Boolean.TRUE); s7DataSPWrite.setRawGlassWidth((int) usageVOS.get(0).getWidth()); s7DataSPWrite.setRawGlassHeight((int) usageVOS.get(0).getHeight()); s7DataSPWrite.setSlot(loadStation.get(0)); if (LOAD_GLASS_ONE_DEVICE.equals(deviceId)) { s7SerializerSPOne.write(s7DataSPWrite); } else { s7SerializerSPTwo.write(s7DataSPWrite); } saveHistoryTask(task, deviceId); } private void opcLoadGlassFinishChid(String tableName, Integer deviceId) { S7DataSP s7DataSP = new S7DataSP(); if (tableName.equals(LOAD_GLASS_DEVICE_ONE_TASK)) { s7DataSP = s7SerializerSPOne.read(S7DataSP.class); } else { s7DataSP = s7SerializerSPTwo.read(S7DataSP.class); } log.info("{}上片线,当前上片位信息:{}", deviceId, s7DataSP); if (s7DataSP.getTaskRunning().toString().equals(Const.ENGINEERING_NEW)) { log.info("无任务,结束"); return; } if (Integer.parseInt(s7DataSP.getTaskState().toString()) <= 1) { log.info("任务正在执行,结束"); return; } //获取任务完成情况 // 已完成数量 破损数量 Integer finishCount = Integer.parseInt(s7DataSP.getFinishCount().toString()); Integer damageCount = Integer.parseInt(s7DataSP.getDamageCount().toString()); Integer slot = Integer.parseInt(s7DataSP.getSlot().toString()); //更新当前架子上的原片剩余情况 rawGlassStorageDetailsService.update(new UpdateWrapper() .inSql("slot", "select slot from raw_glass_storage_station where enable_state = 1") // .eq("slot", task.getSlot()) .eq("slot", slot) .eq("state", Const.RAW_GLASS_STATE_IN) .setSql("remain_quantity = remain_quantity - " + (finishCount + damageCount))); //更新工程下的原片数量 todo:sql待优化 if (finishCount > 0) { List ids = upPattenUsageMapper.queryFinishByEngineering(deviceId, finishCount); upPattenUsageMapper.update(null, new LambdaUpdateWrapper() .in(UpPattenUsage::getId, ids) .set(UpPattenUsage::getState, Const.LOAD_RAW_GLASS_SUCCESS)); } //任务表数据情况 S7DataSP s7DataSPWrite = new S7DataSP(); s7DataSPWrite.setTaskRunning(Boolean.FALSE); s7DataSPWrite.setTotalCount(0); s7DataSPWrite.setRawGlassWidth(0); s7DataSPWrite.setRawGlassHeight(0); s7DataSPWrite.setSlot(0); if (LOAD_GLASS_ONE_DEVICE.equals(deviceId)) { s7SerializerSPOne.write(s7DataSPWrite); } else { s7SerializerSPTwo.write(s7DataSPWrite); } loadGlassDeviceTaskHistoryService.update(new LambdaUpdateWrapper() .set(LoadGlassDeviceTaskHistory::getTaskState, Const.RAW_GLASS_TASK_SUCCESS) .eq(LoadGlassDeviceTaskHistory::getTaskState, Const.RAW_GLASS_TASK_NEW) .eq(LoadGlassDeviceTaskHistory::getStation, deviceId) ); } private boolean saveHistoryTask(S7DataSP task, Integer deviceId) { LoadGlassDeviceTaskHistory taskHistory = new LoadGlassDeviceTaskHistory(); BeanUtils.copyProperties(task, taskHistory); taskHistory.setStation(deviceId); taskHistory.setCreateTime(new Date()); taskHistory.setTaskState(Const.RAW_GLASS_TASK_NEW); loadGlassDeviceTaskHistoryService.save(taskHistory); return Boolean.TRUE; } /** * 尺寸一样并且原片数量大于0 * * @param upPattenUsage * @param details * @return */ private boolean compareRawSize(UpPattenUsage upPattenUsage, RawGlassStorageDetails details) { boolean flag = upPattenUsage.getWidth() == details.getPatternWidth() && upPattenUsage.getHeight() == details.getPatternHeight() && upPattenUsage.getThickness() == details.getPatternThickness() && upPattenUsage.getFilmsId().equals(details.getFilmsId()); return flag && details.getRemainQuantity() > 0; } }