package com.zy.asrs.service.impl; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.mapper.Wrapper; import com.core.common.Cools; import com.core.exception.CoolException; import com.zy.asrs.entity.*; import com.zy.asrs.mapper.WaitPakinMapper; import com.zy.asrs.mapper.WrkMastMapper; import com.zy.asrs.service.BasCrnpService; import com.zy.asrs.service.LocMastService; import com.zy.asrs.service.StaDescService; import com.zy.asrs.service.WrkDetlService; import com.zy.common.model.StartupDto; import com.zy.core.cache.MessageQueue; import com.zy.core.cache.SlaveConnection; import com.zy.core.enums.CrnStatusType; import com.zy.core.enums.SlaveType; import com.zy.core.model.CrnSlave; import com.zy.core.model.DevpSlave; import com.zy.core.model.Task; import com.zy.core.model.command.CrnCommand; import com.zy.core.model.protocol.CrnProtocol; import com.zy.core.model.protocol.StaProtocol; import com.zy.core.properties.SlaveProperties; import com.zy.core.thread.BarcodeThread; import com.zy.core.thread.CrnThread; import com.zy.core.thread.DevpThread; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Date; import java.util.List; import java.util.stream.Collectors; /** * Created by vincent on 2020/8/6 */ @Slf4j @Service("mainService") public class MainServiceImpl { @Autowired private CommonService commonService; @Autowired private SlaveProperties slaveProperties; @Autowired private WrkMastMapper wrkMastMapper; @Autowired private WrkDetlService wrkDetlService; @Autowired private WaitPakinMapper waitPakinMapper; @Autowired private LocMastService locMastService; @Autowired private StaDescService staDescService; @Autowired private BasCrnpService basCrnpService; @Autowired private JdbcTemplate jdbcTemplate; /** * 入库站,根据条码扫描生成入库工作档,工作状态 2 */ @Transactional public void generateStoreWrkFile() { // 根据输送线plc遍历 for (DevpSlave devp : slaveProperties.getDevp()) { // 遍历入库口 for (DevpSlave.Sta inSta : devp.getInSta()) { // 获取条码 BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, inSta.getBarcode()); String barcode = barcodeThread.getBarcode(); // 获取入库站信息 DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId()); StaProtocol staProtocol = devpThread.getStation().get(inSta.getStaNo()); // 判断是否满足入库条件 if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.isInreq1() && !staProtocol.isEmptyMk() && staProtocol.isInreq1() && staProtocol.getWorkNo() ==0 && staProtocol.isPakMk() && !Cools.isEmpty(barcode)) { // 判断重复工作档 WrkMast wrkMast = wrkMastMapper.selectPakInStep1(inSta.getStaNo(), barcode); if (wrkMast != null) { log.warn("工作档中已存在该站状态为1的数据,工作号-{}", wrkMast.getWrkNo()); continue; } // 获取入库通知档 List waitPakins = waitPakinMapper.selectList(new EntityWrapper().eq("barcode", barcode)); // 工作号 int workNo = commonService.getWorkNo(0); // 检索库位 List matNos = waitPakins.stream().map(WaitPakin::getMatnr).distinct().collect(Collectors.toList()); StartupDto startupDto = commonService.getLocNo(1, 1, inSta.getStaNo(), matNos); String locNo = startupDto.getLocNo(); if (!waitPakins.isEmpty()) { // 插入工作明细档 wrkDetlService.createWorkDetail(workNo, waitPakins, barcode); } else { log.warn("无此入库条码数据---{}", barcode); continue; } // 插入工作主档 wrkMast = new WrkMast(); wrkMast.setWrkNo(workNo); wrkMast.setIoTime(new Date()); wrkMast.setWrkSts(2L); // 工作状态:2.设备上走 wrkMast.setIoType(1); // 入出库状态:1.入库 wrkMast.setIoPri(10D); // 优先级:10 wrkMast.setCrnNo(startupDto.getCrnNo()); wrkMast.setSourceStaNo(startupDto.getSourceStaNo()); wrkMast.setStaNo(startupDto.getStaNo()); wrkMast.setLocNo(startupDto.getLocNo()); wrkMast.setBarcode(barcode); // 托盘码 wrkMast.setFullPlt("Y"); // 满板:Y wrkMast.setPicking("N"); // 拣料 wrkMast.setExitMk("N"); // 退出 wrkMast.setEmptyMk("N"); // 空板 wrkMast.setLinkMis("N"); // wrkMast.setCtnType(sourceStaNo.getCtnType()); // 容器类型 // 操作人员数据 wrkMast.setAppeTime(new Date()); wrkMast.setModiTime(new Date()); Integer insert = wrkMastMapper.insert(wrkMast); if (insert == 0) { throw new CoolException("保存工作档失败"); } // 更新目标库位状态 LocMast locMast = locMastService.selectById(startupDto.getLocNo()); locMast.setLocSts("S"); // S.入库预约 locMast.setModiTime(new Date()); if (!locMastService.updateById(locMast)){ throw new CoolException("改变库位状态失败"); } // 更新站点信息 且 下发plc命令 barcodeThread.setBarcode(""); staProtocol.setWorkNo(workNo); staProtocol.setStaNo(startupDto.getStaNo()); staProtocol.setPakMk(false); staProtocol.setInreq1(false); boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task<>(4, staProtocol)); if (!result) { throw new CoolException("更新plc站点信息失败"); } } } } } /** * 拣料、并板、盘点再入库 */ public void stnToCrnStnPick(){ for (DevpSlave devp : slaveProperties.getDevp()) { // 遍历拣料入库口 for (DevpSlave.Sta pickSta : devp.getPickSta()) { // 获取拣料入库站信息 DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId()); StaProtocol staProtocol = devpThread.getStation().get(pickSta.getStaNo()); if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.isInreq1() && staProtocol.getWorkNo() > 0 && staProtocol.isPakMk()){ WrkMast wrkMast = wrkMastMapper.selectPickStep(staProtocol.getWorkNo()); if (wrkMast == null) { // 无拣料数据 continue; } if ((wrkMast.getIoType() != 103 && wrkMast.getIoType() != 104 && wrkMast.getIoType() != 1070) || Cools.isEmpty(wrkMast.getStaNo()) || Cools.isEmpty(wrkMast.getSourceStaNo()) ) { continue; } // 保存工作明细档历史档 if (wrkMastMapper.saveWrkDetlLog(wrkMast.getWrkNo()) == 0) { throw new CoolException("保存工作明细档历史档失败"); } // 保存工作主档历史档 if (wrkMastMapper.saveWrkMastLog(wrkMast.getWrkNo()) == 0) { throw new CoolException("保存工作主档历史档失败"); } // 获取目标站 Wrapper wrapper = new EntityWrapper() .eq("type_no", wrkMast.getIoType() - 50) .eq("stn_no", wrkMast.getStaNo()) // 作业站点 = 拣料出库的目标站 .eq("crn_no", wrkMast.getCrnNo()); // 堆垛机号 StaDesc staDesc = staDescService.selectOne(wrapper); if (Cools.isEmpty(staDesc)) { throw new CoolException("入库路径不存在"); } // 堆垛机站点(目标站) Integer staNo = staDesc.getCrnStn(); // 更新工作档数据状态 wrkMast.setIoType(wrkMast.getIoType() - 50); // 入出库类型: 103->53,104->54,107->57 wrkMast.setWrkSts(2L); // 工作状态: 2.设备上走 wrkMast.setSourceStaNo(wrkMast.getStaNo()); // 源站 wrkMast.setStaNo(staNo); // 目标站 wrkMast.setLocNo(wrkMast.getSourceLocNo()); // 目标库位 = 出库时的源库位 wrkMast.setSourceLocNo(""); // 源库位清空 wrkMast.setModiTime(new Date()); if (wrkMastMapper.updateById(wrkMast) == 0) { throw new CoolException("更新工作档数据状态失败"); } // 修改库位状态 Q.拣料/盘点/并板再入库 LocMast locMast = locMastService.selectById(wrkMast.getLocNo()); locMast.setLocSts("Q"); locMast.setModiTime(new Date()); if (!locMastService.updateById(locMast)) { throw new CoolException("修改库位状态失败"); } // 更新站点信息 且 下发plc命令 staProtocol.setWorkNo(wrkMast.getWrkNo()); staProtocol.setStaNo(wrkMast.getStaNo()); staProtocol.setPakMk(false); staProtocol.setInreq1(false); boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task<>(4, staProtocol)); if (!result) { throw new CoolException("更新plc站点信息失败"); } } } } } /** * 堆垛机站出库到出库站 */ public void crnStnToOutStn() { for (DevpSlave devp : slaveProperties.getDevp()) { // 遍历拣料入库口 for (DevpSlave.Sta outSta : devp.getOutSta()) { // 获取堆垛机出库站信息 DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId()); StaProtocol staProtocol = devpThread.getStation().get(outSta.getStaNo()); if (staProtocol.isAutoing() && staProtocol.isLoading() && (staProtocol.getWorkNo() == 0 || staProtocol.getStaNo() == null)) { // 查询工作档 WrkMast wrkMast = wrkMastMapper.selectPakOutStep2(staProtocol.getSiteId()); if (wrkMast == null) { continue; } // 判断工作档条件 if (wrkMast.getIoType() < 100 || wrkMast.getStaNo() == null || wrkMast.getSourceStaNo() == null) { continue; } // 判断吊车是否实际已完成,且电脑状态在move中,以备电脑进行更新工作档 CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, wrkMast.getCrnNo()); CrnProtocol crnProtocol = crnThread.getCrnProtocol(); if (crnProtocol.statusType == CrnStatusType.FETCHING || crnProtocol.statusType == CrnStatusType.PUTTING) { // 移动中 continue; } // 更新工作档状态为14失败 todo:luxiaotao if (crnProtocol.mode == 3 && crnProtocol.getTaskNo() == wrkMast.getWrkNo() && crnProtocol.statusType == CrnStatusType.IDLE && crnProtocol.forkPos==0) { wrkMast.setWrkSts(14L); wrkMast.setCrnEndTime(new Date()); if (wrkMastMapper.updateById(wrkMast) == 0) { throw new CoolException("更新工作档的工作状态为14失败,工作号"+wrkMast.getWrkNo()); } } // 命令下发区 -------------------------------------------------------------------------- // 1.复位堆垛机 更新堆垛机信息 且 下发plc命令 todo:luxiaotao crnProtocol.setStatus(CrnStatusType.IDLE); crnProtocol.setTaskNo((short)0); if (!MessageQueue.offer(SlaveType.Crn, wrkMast.getCrnNo(), new Task<>(4, crnProtocol))) { throw new CoolException("更新堆垛机信息失败"); } // 2.下发站点信息 staProtocol.setWorkNo(wrkMast.getWrkNo()); staProtocol.setStaNo(wrkMast.getStaNo()); if (!MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task<>(4, staProtocol))) { throw new CoolException("更新plc站点信息失败"); } } } } } /** * 入出库 ===>> 堆垛机站到库位 堆垛机入出库作业下发 */ public void crnIoExecute(){ for (CrnSlave crn : slaveProperties.getCrn()) { // 获取堆垛机信息 CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crn.getId()); CrnProtocol crnProtocol = crnThread.getCrnProtocol(); BasCrnp basCrnp = basCrnpService.selectById(crn.getId()); if (basCrnp == null) { continue; } // 只有当堆垛机空闲 并且 无任务时才继续执行 if (crnProtocol.getStatusType() == CrnStatusType.IDLE && crnProtocol.getTaskNo() == 0) { // 如果最近一次是入库模式 if (crnProtocol.getLastIo().equals("I")) { if (basCrnp.getInEnable().equals("Y")) { this.crnStnToLoc(crn); // 入库 crnProtocol.setLastIo("O"); } else if (basCrnp.getOutEnable().equals("Y")) { this.locToCrnStn(crn); // 出库 crnProtocol.setLastIo("I"); } } // 如果最近一次是出库模式 else if (crnProtocol.getLastIo().equals("O")) { if (basCrnp.getOutEnable().equals("Y")) { this.locToCrnStn(crn); // 出库 crnProtocol.setLastIo("I"); } else if (basCrnp.getInEnable().equals("Y")) { this.crnStnToLoc(crn); // 入库 crnProtocol.setLastIo("O"); } } } // 库位移转 this.locToLoc(); } } /** * 入库 ===>> 堆垛机站到库位 */ private void crnStnToLoc(CrnSlave slave){ for (CrnSlave.CrnStn crnStn : slave.getCrnInStn()) { boolean flag = false; // 获取堆垛机入库站信息 DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, crnStn.getDevpPlcId()); StaProtocol staProtocol = devpThread.getStation().get(crnStn.getStaNo()); // todo:luxiaotao if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.getWorkNo() > 0) { flag = true; } if (!flag) { continue; } // 获取工作状态为2(设备上走)的入库工作档 WrkMast wrkMast = wrkMastMapper.selectPakInStep2(slave.getId(), staProtocol.getWorkNo()); if(null == wrkMast) { log.error("查询无待入库数据--wrk_sts=2, 工作号={}", staProtocol.getWorkNo()); continue; } // 获取库位信息 LocMast locMast = locMastService.selectById(wrkMast.getLocNo()); if (locMast == null) { log.error("查询库存无数据--库位号{}", wrkMast.getLocNo()); continue; } if (!locMast.getLocSts().equals("S") && !locMast.getLocSts().equals("Q")) { log.error("库位状态不符合--状态, 库位号={},库位状态={}", wrkMast.getLocNo(), locMast.getLocSts()); continue; } // 命令下发区 -------------------------------------------------------------------------- // CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, slave.getId()); // CrnProtocol crnProtocol = crnThread.getCrnProtocol(); CrnCommand crnCommand = new CrnCommand(); crnCommand.setTaskNo(wrkMast.getWrkNo().shortValue()); // 工作号 crnCommand.setDestinationPosX(locMast.getRow1().shortValue()); // 排 crnCommand.setDestinationPosY(locMast.getBay1().shortValue()); // 列 crnCommand.setDestinationPosZ(locMast.getLev1().shortValue()); // 层 if (!MessageQueue.offer(SlaveType.Crn, wrkMast.getCrnNo(), new Task<>(2, crnCommand))) { log.error("堆垛机命令下发失败,堆垛机号={},任务数据={}", wrkMast.getCrnNo(), JSON.toJSON(crnCommand)); } } } /** * 出库 ===>> 库位到堆垛机站 */ private void locToCrnStn(CrnSlave slave){ for (CrnSlave.CrnStn crnStn : slave.getCrnOutStn()) { // 获取堆垛机出库站信息 DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, crnStn.getDevpPlcId()); StaProtocol staProtocol = devpThread.getStation().get(crnStn.getStaNo()); // 获取工作状态为11(生成出库ID)的出库工作档 WrkMast wrkMast = wrkMastMapper.selectPakOutStep1(slave.getId()); if (wrkMast == null) { continue; } } } /** * 库位移转 */ private void locToLoc(){ } /** * 执行对工作档的入库完成 */ public void storeFinished() { for (CrnSlave crn : slaveProperties.getCrn()) { // 获取堆垛机信息 CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crn.getId()); CrnProtocol crnProtocol = crnThread.getCrnProtocol(); } } /** * 更新堆垛机移动时工作档状态 */ public void updateCrnMove() { for (CrnSlave crn : slaveProperties.getCrn()) { // 获取堆垛机信息 CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crn.getId()); CrnProtocol crnProtocol = crnThread.getCrnProtocol(); // todo if (crnProtocol.getStatusType() == CrnStatusType.FETCH_POSITION) { WrkMast wrkMast = wrkMastMapper.selectById(crnProtocol.getTaskNo()); } } } }