自动化立体仓库 - WCS系统
luxiaotao1123
2020-09-08 28a7821e43bd5763739fe67384cfea6693b3500b
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
@@ -9,21 +9,26 @@
import com.zy.asrs.mapper.WaitPakinMapper;
import com.zy.asrs.mapper.WrkMastMapper;
import com.zy.asrs.service.*;
import com.zy.common.model.MatDto;
import com.zy.common.model.StartupDto;
import com.zy.common.service.CommonService;
import com.zy.common.utils.CollectionUtils;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.*;
import com.zy.core.model.CrnSlave;
import com.zy.core.model.DevpSlave;
import com.zy.core.model.LedSlave;
import com.zy.core.model.Task;
import com.zy.core.model.command.CrnCommand;
import com.zy.core.model.command.LedCommand;
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 com.zy.core.thread.LedThread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
@@ -31,8 +36,7 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
@@ -80,9 +84,12 @@
                // 获取入库站信息
                DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                StaProtocol staProtocol = devpThread.getStation().get(inSta.getStaNo());
                if (staProtocol == null) {
                    continue;
                }
                // 判断是否满足入库条件
                if (staProtocol.isAutoing() && staProtocol.isLoading()
                        && !staProtocol.isEmptyMk() && staProtocol.isInreq1() && staProtocol.getWorkNo()==0
                        && !staProtocol.isEmptyMk() && staProtocol.getWorkNo() == 0
                        && staProtocol.isPakMk() && !Cools.isEmpty(barcode)) {
                    // 判断重复工作档
                    WrkMast wrkMast = wrkMastMapper.selectPakInStep1(inSta.getStaNo(), barcode);
@@ -148,7 +155,6 @@
                    staProtocol.setWorkNo((short) workNo);
                    staProtocol.setStaNo(startupDto.getStaNo().shortValue());
                    staProtocol.setPakMk(false);
                    staProtocol.setInreq1(false);
                    boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                    if (!result) {
                        throw new CoolException("更新plc站点信息失败");
@@ -162,6 +168,55 @@
    }
    /**
     * 入库站,根据条码扫描生成入库工作档,工作状态 1 ==>> 2
     */
    @Async
    public void generateStoreWrkFile2() {
        // 根据输送线plc遍历
        for (DevpSlave devp : slaveProperties.getDevp()) {
            // 遍历入库口
            for (DevpSlave.Sta inSta : devp.getInSta()) {
                // 获取入库站信息
                DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                StaProtocol staProtocol = devpThread.getStation().get(inSta.getStaNo());
                if (staProtocol == null) { continue; }
                // 判断是否满足入库条件
                if (staProtocol.isAutoing() && staProtocol.isLoading()
                        && !staProtocol.isEmptyMk() && staProtocol.getWorkNo() == 0
                        && staProtocol.isPakMk()) {
                    // 判断重复工作档
                    WrkMast wrkMast = wrkMastMapper.selectPakInStep11(inSta.getStaNo());
                    if (wrkMast == null) {
                        continue;
                    }
                    // 更新工作主档
                    wrkMast.setWrkSts(2L); // 工作状态:2.设备上走
                    wrkMast.setModiTime(new Date());
                    Integer update = wrkMastMapper.updateById(wrkMast);
                    if (update == 0) {
                        throw new CoolException("更新工作档失败");
                    }
                    // 命令下发区 --------------------------------------------------------------------------
                    // 更新站点信息 且 下发plc命令
                    staProtocol.setWorkNo(wrkMast.getWrkNo().shortValue());
                    staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
                    staProtocol.setPakMk(false);
                    boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                    if (!result) {
                        throw new CoolException("更新plc站点信息失败");
                    }
                }
            }
        }
    }
    /**
     * 拣料、并板、盘点再入库
@@ -174,8 +229,8 @@
                // 获取拣料入库站信息
                DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                StaProtocol staProtocol = devpThread.getStation().get(pickSta.getStaNo());
                if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.isInreq1()
                if (staProtocol == null) { continue; }
                if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.isInEnable()
                    && staProtocol.getWorkNo() > 0 && staProtocol.isPakMk()){
                    WrkMast wrkMast = wrkMastMapper.selectPickStep(staProtocol.getWorkNo().intValue());
                    if (wrkMast == null) {
@@ -228,7 +283,6 @@
                    staProtocol.setWorkNo(wrkMast.getWrkNo().shortValue());
                    staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
                    staProtocol.setPakMk(false);
                    staProtocol.setInreq1(false);
                    boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                    if (!result) {
                        throw new CoolException("更新plc站点信息失败");
@@ -246,12 +300,13 @@
     */
    @Async
    public void crnStnToOutStn() {
        for (DevpSlave devp : slaveProperties.getDevp()) {
            // 遍历拣料入库口
            for (DevpSlave.Sta outSta : devp.getOutSta()) {
        for (CrnSlave crnSlave : slaveProperties.getCrn()) {
            // 遍历堆垛机出库站
            for (CrnSlave.CrnStn crnStn : crnSlave.getCrnOutStn()) {
                // 获取堆垛机出库站信息
                DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                StaProtocol staProtocol = devpThread.getStation().get(outSta.getStaNo());
                DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, crnStn.getDevpPlcId());
                StaProtocol staProtocol = devpThread.getStation().get(crnStn.getStaNo());
                if (staProtocol == null) { continue; }
                if (staProtocol.isAutoing() && staProtocol.isLoading() && (staProtocol.getWorkNo() == 0 || staProtocol.getStaNo() == null)) {
                    // 查询工作档
                    WrkMast wrkMast = wrkMastMapper.selectPakOutStep2(staProtocol.getSiteId());
@@ -269,32 +324,32 @@
                        // 移动中
                        continue;
                    }
                    // 更新工作档状态为14失败 todo:luxiaotao
                    //  判断堆垛机状态等待确认
                    if (crnProtocol.modeType == CrnModeType.AUTO && crnProtocol.getTaskNo().equals(wrkMast.getWrkNo().shortValue())
                            && crnProtocol.statusType == CrnStatusType.IDLE
                            && crnProtocol.statusType == CrnStatusType.WAITING
                            && crnProtocol.forkPosType == CrnForkPosType.HOME) {
                        // 命令下发区 --------------------------------------------------------------------------
                        // 1.复位堆垛机
                        crnThread.setResetFlag(true);
                        // 2.下发站点信息
                        staProtocol.setWorkNo(wrkMast.getWrkNo().shortValue());
                        staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
                        if (!MessageQueue.offer(SlaveType.Devp, crnStn.getDevpPlcId(), new Task(2, staProtocol))) {
                            throw new CoolException("更新plc站点信息失败");
                        }
                        // 更新工作档状态为14失败
                        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().shortValue());
                    staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
                    if (!MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol))) {
                        throw new CoolException("更新plc站点信息失败");
                    }
                }
            }
        }
@@ -309,6 +364,7 @@
            // 获取堆垛机信息
            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crn.getId());
            CrnProtocol crnProtocol = crnThread.getCrnProtocol();
            if (crnProtocol == null) { continue; }
            BasCrnp basCrnp = basCrnpService.selectById(crn.getId());
            if (basCrnp == null) {
                log.error("{}号堆垛机尚未在数据库进行维护!", crn.getId());
@@ -319,26 +375,26 @@
                // 如果最近一次是入库模式
                if (crnProtocol.getLastIo().equals("I")) {
                    if (basCrnp.getInEnable().equals("Y")) {
                        this.crnStnToLoc(crn); //  入库
                        this.crnStnToLoc(crn, crnProtocol); //  入库
                        crnProtocol.setLastIo("O");
                    } else if (basCrnp.getOutEnable().equals("Y")) {
                        this.locToCrnStn(crn); //  出库
                        this.locToCrnStn(crn, crnProtocol); //  出库
                        crnProtocol.setLastIo("I");
                    }
                }
                // 如果最近一次是出库模式
                else if (crnProtocol.getLastIo().equals("O")) {
                    if (basCrnp.getOutEnable().equals("Y")) {
                        this.locToCrnStn(crn); //  出库
                        this.locToCrnStn(crn, crnProtocol); //  出库
                        crnProtocol.setLastIo("I");
                    } else if (basCrnp.getInEnable().equals("Y")) {
                        this.crnStnToLoc(crn); //  入库
                        this.crnStnToLoc(crn, crnProtocol); //  入库
                        crnProtocol.setLastIo("O");
                    }
                }
            }
            // 库位移转
            this.locToLoc(crn);
            this.locToLoc(crn, crnProtocol);
        }
    }
@@ -346,19 +402,21 @@
     * 入库  ===>>  堆垛机站到库位
     */
    @Async
    public void crnStnToLoc(CrnSlave slave){
    public void crnStnToLoc(CrnSlave slave, CrnProtocol crnProtocol){
        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());
            if (staProtocol == null) { continue; }
            // 查询站点详细信息
            BasDevp staDetl = basDevpService.selectById(crnStn.getStaNo());
            if (staDetl == null) {
                log.error("入库 ===>> 堆垛机站点在数据库不存在, 站点编号={}", crnStn.getStaNo());
                continue;
            }
            if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.getWorkNo() > 0 && staDetl.getCanining().equals("Y")) {
            if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.getWorkNo() > 0
                    && staDetl.getCanining()!=null && staDetl.getCanining().equals("Y")) {
                flag = true;
            }
            if (!flag) {
@@ -378,6 +436,11 @@
            }
            if (!locMast.getLocSts().equals("S") && !locMast.getLocSts().equals("Q")) {
                log.error("入库操作库位状态不符合--状态, 库位号={},库位状态={}", wrkMast.getLocNo(), locMast.getLocSts());
                continue;
            }
            // 堆垛机控制过滤
            if (!crnProtocol.getStatusType().equals(CrnStatusType.IDLE) || crnProtocol.getTaskNo() != 0) {
                continue;
            }
@@ -412,7 +475,7 @@
     * 出库  ===>>  库位到堆垛机站
     */
    @Async
    public void locToCrnStn(CrnSlave slave){
    public void locToCrnStn(CrnSlave slave, CrnProtocol crnProtocol){
        for (CrnSlave.CrnStn crnStn : slave.getCrnOutStn()) {
            // 获取工作状态为11(生成出库ID)的出库工作档
            WrkMast wrkMast = wrkMastMapper.selectPakOutStep1(slave.getId());
@@ -433,6 +496,7 @@
            // 获取堆垛机出库站信息
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, crnStn.getDevpPlcId());
            StaProtocol staProtocol = devpThread.getStation().get(crnStn.getStaNo());
            if (staProtocol == null) { continue; }
            // 查询站点详细信息
            BasDevp staDetl = basDevpService.selectById(crnStn.getStaNo());
            if (staDetl == null) {
@@ -440,9 +504,14 @@
                continue;
            }
            // 判断堆垛机出库站状态
            if (staProtocol.isAutoing() && !staProtocol.isLoading() && staDetl.getCanouting().equals("Y")
            if (staProtocol.isAutoing() && !staProtocol.isLoading() && staDetl.getCanouting() !=null && staDetl.getCanouting().equals("Y")
                    && staProtocol.getWorkNo() == 0) {
                // 命令下发区 --------------------------------------------------------------------------
                // 堆垛机控制过滤
                if (!crnProtocol.getStatusType().equals(CrnStatusType.IDLE) || crnProtocol.getTaskNo() != 0) {
                    continue;
                }
                // 1.堆垛机开始移动
                CrnCommand crnCommand = new CrnCommand();
@@ -476,7 +545,7 @@
     * 库位移转
     */
    @Async
    public void locToLoc(CrnSlave slave){
    public void locToLoc(CrnSlave slave, CrnProtocol crnProtocol){
        // 获取工作档信息
        WrkMast wrkMast = wrkMastMapper.selectLocMove(slave.getId());
        if (null == wrkMast) {
@@ -503,6 +572,12 @@
        if (!basCrnp.getInEnable().equals("Y") && !basCrnp.getOutEnable().equals("Y")) {
            return;
        }
        // 堆垛机控制过滤
        if (!crnProtocol.getStatusType().equals(CrnStatusType.IDLE) || crnProtocol.getTaskNo() != 0) {
            return;
        }
        // 命令下发区 --------------------------------------------------------------------------
        CrnCommand crnCommand = new CrnCommand();
        crnCommand.setCrnNo(slave.getId()); // 堆垛机编号
@@ -517,7 +592,17 @@
        crnCommand.setDestinationPosZ(sta.getLev1().shortValue());     // 目标库位层
        if (!MessageQueue.offer(SlaveType.Crn, wrkMast.getCrnNo(), new Task(2, crnCommand))) {
            log.error("堆垛机命令下发失败,堆垛机号={},任务数据={}", wrkMast.getCrnNo(), JSON.toJSON(crnCommand));
        } else {
            // 修改工作档状态 11.生成出库ID => 12.吊车出库中
            Date now = new Date();
            wrkMast.setWrkSts(12L);
            wrkMast.setCrnStrTime(now);
            wrkMast.setModiTime(now);
            if (wrkMastMapper.updateById(wrkMast) == 0) {
                log.error("【库位移转】 修改工作档状态 11.生成出库ID => 12.吊车出库中 失败!!,工作号={}", wrkMast.getWrkNo());
            }
        }
    }
    /**
@@ -529,6 +614,7 @@
            // 获取堆垛机信息
            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crn.getId());
            CrnProtocol crnProtocol = crnThread.getCrnProtocol();
            if (crnProtocol == null) { continue; }
            //  状态:等待确认 并且  任务完成位 = 1
            if (crnProtocol.statusType == CrnStatusType.WAITING && crnProtocol.getTaskNo() != 0) {
                // 获取入库待确认工作档
@@ -541,8 +627,9 @@
                if (wrkMast.getWrkSts() == 3 || (wrkMast.getWrkSts() == 12 && wrkMast.getIoType() == 11)){
                    wrkMast.setWrkSts(4L);
                // 出库 + 拣料/盘点/并板出库中:12.吊车出库中 ==> 14.出库完成
                } else if (wrkMast.getWrkSts() == 12) {
                    wrkMast.setWrkSts(14L);
                    // todo:luxiaotao
//                } else if (wrkMast.getWrkSts() == 12) {
//                    wrkMast.setWrkSts(14L);
                } else  {
                    continue;
                }
@@ -551,19 +638,14 @@
                wrkMast.setModiTime(now);
                // 修改成功后复位堆垛机
                if (wrkMastMapper.updateById(wrkMast) > 0) {
                    // 命令下发区 -------------------------------------------------------------------------
                    if (crnProtocol.getStatusType().equals(CrnStatusType.WAITING)) {
                        // 堆垛机复位
                        if (!MessageQueue.offer(SlaveType.Crn, crn.getId(), new Task(3, new CrnCommand()))) {
                            log.error("堆垛机复位命令下发失败,工作号={}", wrkMast.getWrkNo());
                        }
                    }
                    // 堆垛机复位
                    crnThread.setResetFlag(true);
                }
                // 完成通知档
                if (wrkMastMapper.updateWaitPakInStep2(wrkMast.getBarcode()) == 0) {
                    log.error("入库通知档修改结束状态失败,workNo=[{}]", wrkMast.getWrkNo());
                }
//                if (wrkMastMapper.updateWaitPakInStep2(wrkMast.getBarcode()) == 0) {
//                    log.error("入库通知档修改结束状态失败,workNo=[{}]", wrkMast.getWrkNo());
//                }
            }
        }
@@ -590,13 +672,14 @@
                // 获取空板入库站信息
                DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                StaProtocol staProtocol = devpThread.getStation().get(emptyInSta.getStaNo());
                if (staProtocol == null) { continue; }
                // 站点条件判断
                if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.isInEnable()
                        && staProtocol.isEmptyMk() && staProtocol.getWorkNo() == 0 && staProtocol.isPakMk()) {
                    // 工作号
                    int workNo = commonService.getWorkNo(0);
                    // 检索库位
                    StartupDto startupDto = commonService.getLocNo(1, 1, emptyInSta.getStaNo(), null);
                    StartupDto startupDto = commonService.getLocNo(1, 10, emptyInSta.getStaNo(), null);
                    // 插入工作主档
                    WrkMast wrkMast = new WrkMast();
@@ -635,13 +718,12 @@
                    staProtocol.setWorkNo((short) workNo);
                    staProtocol.setStaNo(startupDto.getStaNo().shortValue());
                    staProtocol.setPakMk(false);
                    staProtocol.setInreq1(false);
                    boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                    if (!result) {
                        throw new CoolException("更新plc站点信息失败");
                    }
                    staProtocol.setPakMk(false);
                }
@@ -649,4 +731,63 @@
        }
    }
    /**
     * 出库  ===>> 工作档信息写入led显示器
     */
    @Async
    public void ledExecute() {
        for (LedSlave led : slaveProperties.getLed()) {
            // 获取输送线plc线程
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, led.getDevpPlcId());
            // 命令集合
            List<LedCommand> commands = new ArrayList<>();
            // 工作档集合
            List<WrkMast> wrkMasts = new ArrayList<>();
            for (Integer staNo : led.getStaArr()) {
                // 获取叉车站点
                StaProtocol staProtocol = devpThread.getStation().get(staNo);
                if (null == staProtocol || null == staProtocol.getWorkNo() || 0 == staProtocol.getWorkNo()) { continue; }
                // 获取工作档数据
                WrkMast wrkMast = wrkMastMapper.selectById(staProtocol.getWorkNo());
                if (wrkMast.getWrkSts() == 14L || wrkMast.getWrkSts() == 15L) {
                    wrkMasts.add(wrkMast);
                    // 添加命令
                    List<WrkDetl> wrkDetls = wrkDetlService.findByWorkNo(wrkMast.getWrkNo());
                    LedCommand ledCommand = new LedCommand();
                    ledCommand.setWorkNo(wrkMast.getWrkNo());
                    ledCommand.setSourceLocNo(wrkMast.getSourceLocNo());
                    ledCommand.setStaNo(wrkMast.getStaNo());
                    wrkDetls.forEach(wrkDetl -> ledCommand.getMatDtos().add(new MatDto(wrkDetl.getMatnr(), wrkDetl.getMatnr(), wrkDetl.getAnfme())));
                    commands.add(ledCommand);
                }
            }
            Set<Integer> workNos = wrkMasts.stream().map(WrkMast::getWrkNo).collect(Collectors.toSet());
            // 获取LED线程
            LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, led.getId());
            // 相同工作号集合则过滤
            if (CollectionUtils.equals(ledThread.getWorkNos(), workNos)) {
                continue;
            }
            // 命令下发 -------------------------------------------------------------------------------
            if (!commands.isEmpty()) {
                if (!MessageQueue.offer(SlaveType.Led, led.getId(), new Task(1, commands))) {
                    continue;
                }
            }
            // 修改主档led标记
            for (WrkMast wrkMast : wrkMasts) {
                wrkMast.setOveMk("Y");
                wrkMast.setModiTime(new Date());
                if (wrkMastMapper.updateById(wrkMast) == 0) {
                    throw new CoolException("更新工作档失败");
                }
            }
            // 更新线程当前工作号集合
            ledThread.setWorkNos(workNos);
        }
    }
}