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("s7SerializerSP1") private S7Serializer s7SerializerSPOne; @Autowired @Qualifier("s7SerializerSP2") 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 = 2000) 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 = 2000) 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(); // s7DataSP.setPlcRequest(1); // s7DataSP.setMesConfirm(0); 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.getPlcRequest() == 0) { if (s7DataSP.getMesSend() != 0) { S7DataSP resetSend = new S7DataSP(); resetSend.setMesSend(0); s7SerializerSPOne.write(resetSend); log.info("{}上片线,PLC请求清零,MES同步清零mesSend", deviceId); } return; } // 当PLC请求新任务(plcRequest=1)且无未确认汇报(mesConfirm=0)时处理 if (s7DataSP.getPlcRequest() != 1 || s7DataSP.getMesConfirm() != 0) { log.info("{}上片线,PLC未请求新任务或存在未确认汇报,跳过本次处理", deviceId); return; } Engineering engineering = engineeringMapper.selectOne(new LambdaQueryWrapper() .eq(Engineering::getState, Const.ENGINEERING_RUNNING) .eq(Engineering::getStationCell, deviceId)); if (null == engineering) { log.info("{}上片线,没有工程任务", deviceId); return; } List pattenUsageList = upPattenUsageMapper.queryRawGlassByEngineeringId(engineering.getEngineerId()); log.info("按照当前获取到正在需要上片的原片信息有:{}", pattenUsageList); if (CollectionUtils.isEmpty(pattenUsageList)) { log.info("当前工程需要上片的原片信息为空,任务已结束"); 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) .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()); //生成上片任务 LoadGlassDeviceTaskHistory task = new LoadGlassDeviceTaskHistory(); task.setTotalCount(number); task.setTaskRunning(1); task.setRawGlassWidth((int) usageVOS.get(0).getWidth()); task.setRawGlassHeight((int) usageVOS.get(0).getHeight()); task.setSlot(loadStation.get(0)); task.setRawGlassFilmsId(usageVOS.get(0).getFilmsId()); task.setEngineeringId(usageVOS.get(0).getEngineeringId()); saveHistoryTask(task, deviceId); S7DataSP s7DataSPWrite = new S7DataSP(); s7DataSPWrite.setMesSend(1); 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); } return; } //尺寸不一样或者原片数量大于0 if (!compareRawSize(usageVOS.get(0), oneLoadStation)) { log.info("一号上片位有架子,原片数量为0或者原片信息与待上片尺寸不一致,结束本次上片任务,等待仓储调度任务"); return; } //生成上片任务 int number = Math.min(oneLoadStation.getRemainQuantity(), usageVOS.size()); LoadGlassDeviceTaskHistory task = new LoadGlassDeviceTaskHistory(); task.setTotalCount(number); task.setTaskRunning(1); task.setRawGlassWidth((int) usageVOS.get(0).getWidth()); task.setRawGlassHeight((int) usageVOS.get(0).getHeight()); task.setRawGlassThickness((int) usageVOS.get(0).getThickness()); task.setSlot(loadStation.get(0)); task.setRawGlassFilmsId(usageVOS.get(0).getFilmsId()); task.setEngineeringId(usageVOS.get(0).getEngineeringId()); saveHistoryTask(task, deviceId); UpPattenUsage upPattenUsage = upPattenUsageMapper.selectById(usageVOS.get(0).getId()); upPattenUsage.setState(101); upPattenUsageMapper.updateById(upPattenUsage); S7DataSP s7DataSPWrite = new S7DataSP(); s7DataSPWrite.setMesSend(1); 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); } } private void opcLoadGlassFinishChid(String tableName, Integer deviceId) { S7DataSP s7DataSP = new S7DataSP(); // s7DataSP.setPlcReport(1); // s7DataSP.setMesConfirm(0); 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.getPlcReport() == 0) { if (s7DataSP.getMesConfirm() != 0) { S7DataSP resetConfirm = new S7DataSP(); resetConfirm.setMesConfirm(0); s7SerializerSPOne.write(resetConfirm); log.info("{}上片线,PLC汇报清零,MES同步清零mesConfirm", deviceId); } return; } if (s7DataSP.getPlcReport() == 0 || s7DataSP.getMesConfirm() != 0) { log.info("{}上片线,无PLC汇报或已确认,跳过本次处理", deviceId); return; } LoadGlassDeviceTaskHistory unconfirmedTask = loadGlassDeviceTaskHistoryService.getOne( new LambdaQueryWrapper() .eq(LoadGlassDeviceTaskHistory::getStation, deviceId) .eq(LoadGlassDeviceTaskHistory::getTaskState, Const.RAW_GLASS_TASK_RUNNING) ); String upUsageId = unconfirmedTask.getEngineeringId(); if (s7DataSP.getPlcReport() == 1) { // 汇报成功:更新上片记录为“成功” upPattenUsageMapper.update(null, new LambdaUpdateWrapper() .set(UpPattenUsage::getState, Const.LOAD_RAW_GLASS_SUCCESS) .eq(UpPattenUsage::getEngineeringId, upUsageId) .eq(UpPattenUsage::getState, 101) ); unconfirmedTask.setTaskState(Const.RAW_GLASS_TASK_SUCCESS); unconfirmedTask.setFinishCount(unconfirmedTask.getFinishCount() + 1); log.info("{}上片线,任务汇报成功,更新上片记录[{}]为成功", deviceId, upUsageId); } else if (s7DataSP.getPlcReport() == 2) { // 汇报破损 unconfirmedTask.setTaskState(200); unconfirmedTask.setDamageCount(unconfirmedTask.getDamageCount() + 1); log.warn("{}上片线,任务汇报破损,上片记录[{}]标记为破损", deviceId, upUsageId); } unconfirmedTask.setUpdateTime(new Date()); loadGlassDeviceTaskHistoryService.updateById(unconfirmedTask); //更新当前架子上的原片剩余情况 rawGlassStorageDetailsService.update(new UpdateWrapper() .inSql("slot", "select slot from raw_glass_storage_station where enable_state = 1") // .eq("slot", task.getSlot()) .eq("slot", unconfirmedTask.getSlot()) .eq("state", Const.RAW_GLASS_STATE_IN) .setSql("remain_quantity = GREATEST(remain_quantity - 1, 0)")); //汇报字给1 S7DataSP s7DataSPWrite = new S7DataSP(); s7DataSPWrite.setMesConfirm(1); s7SerializerSPOne.write(s7DataSPWrite); } private boolean saveHistoryTask(LoadGlassDeviceTaskHistory task, Integer deviceId) { LoadGlassDeviceTaskHistory taskHistory = new LoadGlassDeviceTaskHistory(); BeanUtils.copyProperties(task, taskHistory); taskHistory.setStation(deviceId); taskHistory.setCreateTime(new Date()); taskHistory.setTaskState(Const.RAW_GLASS_TASK_RUNNING); 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; } }