lty
3 天以前 09f634c766e8daeeb687d48fd645f225afc3c082
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
@@ -10,6 +10,7 @@
import com.zy.asrs.entity.*;
import com.zy.asrs.mapper.*;
import com.zy.asrs.service.*;
import com.zy.system.service.*;
import com.zy.asrs.utils.RouteUtils;
import com.zy.asrs.utils.Utils;
import com.zy.asrs.utils.VersionUtils;
@@ -38,6 +39,9 @@
import com.zy.core.thread.LedThread;
import com.zy.core.thread.RgvThread;
import com.zy.core.thread.SiemensDevpThread;
import com.zy.system.entity.Config;
import com.zy.system.mapper.ConfigMapper;
import com.zy.system.service.ConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@@ -45,7 +49,10 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -94,6 +101,8 @@
    private WrkMastService wrkMastService;
    @Autowired
    private BasRgvMapService basRgvMapService;
    @Autowired
    private ConfigService configService;
    @Value("${wms.url}")
    private String wmsUrl;
@@ -101,12 +110,9 @@
    private boolean isToOrigin;
    public Integer wrkNo = 10000;
    /**
     * 组托
     * 入库站,根据条码扫描生成入库工作档,工作状态 2
     */
    public synchronized void generateStoreWrkFile(Integer mark) {
    @Autowired
    private ConfigMapper configMapper;
    public synchronized void generateStoreWrkFile3(Integer mark) {
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        // 根据输送线plc遍历
        for (DevpSlave devp : slaveProperties.getDevp()) {
@@ -117,16 +123,23 @@
                LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, inSta.getLed());
                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                StaProtocol staProtocol = devpThread.getStation().get(inSta.getStaNo());
                StaProtocol staProtocolIn = devpThread.getStation().get(inSta.getStaNo() -1);
                if (staProtocolIn == null) {
                    continue;
                } else {
                    staProtocolIn = staProtocolIn.clone();
                }
                if (barcodeThread == null) {
                    continue;
                }
                String barcode = barcodeThread.getBarcode();
                if (staProtocol == null) {
                    continue;
                } else {
                    staProtocol = staProtocol.clone();
                }
                if (barcodeThread == null) {
                    continue;
                }
                String barcode = barcodeThread.getBarcode();
                // 尺寸检测异常
                boolean back = false;
                String errMsg = "";
@@ -218,7 +231,7 @@
//
//                        }
                        News.error(barcode + "条码已存在状态为( 2.设备上走 )的数据,请查看WCS输送线界面,工作号={}", wrkMast.getWrkNo());
                        MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, barcode + "条码已存在状态为( 2.设备上走 )的任务,工作号=" + wrkMast.getWrkNo()));
//                        MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, barcode + "条码已存在状态为( 2.设备上走 )的任务,工作号=" + wrkMast.getWrkNo()));
                        continue;
//                        barcodeThread.setBarcode("");
//                        staProtocol.setWorkNo(wrkMast.getWrkNo());
@@ -283,27 +296,6 @@
                            }
                        } else {
                            if (jsonObject.getString("msg").equals("工作档已存在")) {
                                //工作档已存在    再次进去
//                                wrkMast = wrkMastMapper.selectPakInStepBarcode(barcode);
//                                if (wrkMast != null) {
//                                    barcodeThread.setBarcode("");
//                                    staProtocol.setWorkNo(9999);
//                                    //staProtocol.setWorkNo(wrkMast.getWrkNo());
//                                    //staProtocol.setStaNo(RouteUtils.SouStaEnd(dto.getStaNo(),dto.getSourceStaNo()));
//                                    staProtocol.setStaNo(inSta.getBackSta().shortValue());
//                                    devpThread.setPakMk(staProtocol.getSiteId(), false);
//                                    boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                                    log.error("输送线下发2:" + wrkMast.getWrkNo() + "," + wrkMast.getStaNo());
//                                    ledThread.errorReset();
//                                    log.error("组托请求后LED错误清除");
//                                    if (!result) {
//                                        News.error(methodName + ":更新plc站点信息失败");
//
//                                        throw new CoolException("更新plc站点信息失败");
//                                    }
//                                }
                                continue;
                            }
                            staProtocol.setWorkNo(wrkNo);
@@ -336,6 +328,436 @@
//        News.infoNoLog(""+mark+" - 0"+" - 组托  ===》执行完成");
    }
    /**
     * 组托
     * 入库站,根据条码扫描生成入库工作档,工作状态 2
     */
//    public synchronized void generateStoreWrkFile(Integer mark) {
//        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
//        // 根据输送线plc遍历
//        for (DevpSlave devp : slaveProperties.getDevp()) {
//            // 遍历入库口
//            for (DevpSlave.Sta inSta : devp.getInSta()) {
//                // 获取条码扫描仪信息
//                BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, inSta.getBarcode());
//                LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, inSta.getLed());
//                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
//                StaProtocol staProtocol = devpThread.getStation().get(inSta.getStaNo());
//                StaProtocol staProtocolIn = devpThread.getStation().get(inSta.getStaNo() -1);
//                if (staProtocolIn == null) {
//                    continue;
//                } else {
//                    staProtocolIn = staProtocolIn.clone();
//                }
//                if (barcodeThread == null) {
//                    continue;
//                }
//                String barcode = barcodeThread.getBarcode();
//                if(staProtocolIn.getStamp() == 1 && barcode!=null && !barcode.isEmpty()) {
//                    log.error("生成任务中");
//
//                    WrkMast checkPick = wrkMastService.selectOne(new EntityWrapper<WrkMast>()
//                            .eq("barcode", barcode)
//                            .in("io_type", 107, 103, 57));
//                    if (!Cools.isEmpty(checkPick)) {
//                        continue;
//                    }
//                    try {
//                        LocTypeDto locTypeDto = new LocTypeDto(staProtocol);
//
//                        SearchLocParam param = new SearchLocParam();
//                        locTypeDto.setLocType1((short) 1);
//                        param.setBarcode(barcode);
//                        param.setIoType(1);
//                        param.setSourceStaNo(inSta.getStaNo());
//                        param.setLocType1(locTypeDto.getLocType1());
//                        param.setWeight(staProtocol.getWeight());
//                        String response = new HttpHandler.Builder()
//                                .setTimeout(30, TimeUnit.SECONDS)
//                                .setUri(wmsUrl)
//                                .setPath("/rpc/pakin/loc/v1")
//                                .setJson(JSON.toJSONString(param))
//                                .build()
//                                .doPost();
//                        JSONObject jsonObject = JSON.parseObject(response);
//                        if (jsonObject.getInteger("code").equals(200)) {
//                            StartupDto dto = jsonObject.getObject("data", StartupDto.class);
//                            barcodeThread.setBarcode("");
//                            staProtocolIn.setWorkNo(dto.getWorkNo());
////                            //staProtocol.setStaNo(RouteUtils.SouStaEnd(dto.getStaNo(),dto.getSourceStaNo()));
////                            staProtocol.setStaNo(dto.getStaNo().shortValue());
//                            devpThread.setPakMk(staProtocolIn.getSiteId(), false);
//                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(3, staProtocolIn));
//                            log.error("工作号下发2:" + dto.getWorkNo() + "," + dto.getStaNo());
//                            ledThread.errorReset();
//                            log.error("组托请求后LED错误清除");
//                            if (!result) {
//                                News.error(methodName + ":更新plc站点信息失败");
//
//                                throw new CoolException("更新plc站点信息失败");
//                            }
//                        }
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//                    }
//                }else{
//                    if (staProtocol == null) {
//                        continue;
//                    } else {
//                        staProtocol = staProtocol.clone();
//                    }
//
//                    // 尺寸检测异常
//                    boolean back = false;
//                    String errMsg = "";
//                    if (staProtocol.isFrontErr()) {
//                        errMsg = "前超限";
//                        back = true;
//                    }
//                    if (!back && staProtocol.isBackErr()) {
//                        errMsg = "后超限";
//                        back = true;
//                    }
//                    if (!back && staProtocol.isHighErr()) {
//                        errMsg = "高超限";
//                        back = true;
//                    }
//                    if (!back && staProtocol.isLeftErr()) {
//                        errMsg = "左超限";
//                        back = true;
//                    }
//                    if (!back && staProtocol.isRightErr()) {
//                        errMsg = "右超限";
//                        back = true;
//                    }
//                    if (!back && staProtocol.getWeight() > 1000) {
//                        errMsg = "超重或未读取";
//                        back = true;
//                    }
//                    if (!back && staProtocol.isBarcodeErr()) {
//                        errMsg = "扫码失败";
//                        back = true;
//                    }
//
//                    // 退回
//                    if (back) {
//                        log.info("errmsg: " + errMsg);
////                        News.warn("扫码入库失败,{}入库站因{}异常,托盘已被退回", inSta.getStaNo(), errMsg);
//                        MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, errMsg));
//
//                        if (!staProtocol.isLoading()) {
//                            continue;
//                        }
//                        if (!staProtocol.isPakMk()) {
//                            continue;
//                        }
//                        staProtocol.setWorkNo(wrkNo);
//                        News.info("{}PLC入库回退:{},任务号:{}", inSta.getStaNo(), errMsg, wrkNo);
//                        wrkNo++;
//                        staProtocol.setStaNo(inSta.getBackSta().shortValue());
//                        devpThread.setPakMk(staProtocol.getSiteId(), false);
//                        MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                        log.error("输送线下发1:" + wrkNo + "," + inSta.getBackSta());
//                    }
//
//                    // 判断是否满足入库条件
//                    if (staProtocol.isAutoing()
//                            && staProtocol.isLoading()
//                            && staProtocol.isInEnable()
//                            && !staProtocol.isEmptyMk()
//                            && staProtocol.isPakMk()) {
//                        if (Cools.isEmpty(barcode) || "NG".endsWith(barcode) || "NoRead".equals(barcode) || "00000000".equals(barcode)) {
//                            News.info("{}号条码扫描器检测条码信息:{}", inSta.getBarcode(), barcode);
//
//                            staProtocol.setWorkNo(wrkNo);
//                            News.info("{}barcode入库回退:{},任务号:{}", inSta.getStaNo(), errMsg, wrkNo);
//                            wrkNo++;
//                            staProtocol.setStaNo(inSta.getBackSta().shortValue());
//                            devpThread.setPakMk(staProtocol.getSiteId(), false);
//                            MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                            log.error("输送线下发1:" + wrkNo + "," + inSta.getBackSta());
//                            continue;
//                        }
//                        // 判断重复工作档
//                        WrkMast wrkMast = wrkMastMapper.selectPakInStep1(inSta.getStaNo(), barcode);
//                        if (wrkMast != null) {
//                            News.error(barcode + "条码已存在状态为( 2.设备上走 )的数据,请查看WCS输送线界面,工作号={}", wrkMast.getWrkNo());
//                            continue;
//                        }
//                        WrkMast checkPick = wrkMastService.selectOne(new EntityWrapper<WrkMast>()
//                                .eq("barcode", barcode)
//                                .in("io_type", 107, 103, 57));
//                        if (!Cools.isEmpty(checkPick)) {
//                            continue;
//                        }
//                        try {
//                            LocTypeDto locTypeDto = new LocTypeDto(staProtocol);
//
//                            SearchLocParam param = new SearchLocParam();
//                            locTypeDto.setLocType1((short) 1);
//                            param.setBarcode(barcode);
//                            param.setIoType(1);
//                            param.setSourceStaNo(inSta.getStaNo());
//                            param.setLocType1(locTypeDto.getLocType1());
//                            param.setWeight(staProtocol.getWeight());
//                            String response = new HttpHandler.Builder()
//                                    .setTimeout(30,TimeUnit.SECONDS)
//                                    .setUri(wmsUrl)
//                                    .setPath("/rpc/pakin/loc/v1")
//                                    .setJson(JSON.toJSONString(param))
//                                    .build()
//                                    .doPost();
//                            JSONObject jsonObject = JSON.parseObject(response);
//                            if (jsonObject.getInteger("code").equals(200)) {
//                                StartupDto dto = jsonObject.getObject("data", StartupDto.class);
//                                barcodeThread.setBarcode("");
//                                staProtocol.setWorkNo(dto.getWorkNo());
//                                //staProtocol.setStaNo(RouteUtils.SouStaEnd(dto.getStaNo(),dto.getSourceStaNo()));
//                                staProtocol.setStaNo(dto.getStaNo().shortValue());
//                                devpThread.setPakMk(staProtocol.getSiteId(), false);
//                                boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                                log.error("输送线下发2:" + dto.getWorkNo() + "," + dto.getStaNo());
//
//                                ledThread.errorReset();
//                                log.error("组托请求后LED错误清除");
//
//                                if (!result) {
//                                    News.error(methodName + ":更新plc站点信息失败");
//
//                                    throw new CoolException("更新plc站点信息失败");
//                                }
//                            } else {
//                                if (jsonObject.getString("msg").equals("工作档已存在")) {
//                                    continue;
//                                }
//                                staProtocol.setWorkNo(wrkNo);
//                                wrkNo++;
//                                staProtocol.setStaNo(inSta.getBackSta().shortValue());
//                                devpThread.setPakMk(staProtocol.getSiteId(), false);
//                                MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                                log.error("输送线下发2:" + staProtocol.getWorkNo() + "," + staProtocol.getStaNo());
//
//                                String errorMsg = jsonObject.getString("msg");
//                                if (!Cools.isEmpty(errorMsg)) {
//                                    MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, errorMsg));
//                                }
//                            }
//
//                        } catch (Exception e) {
//                            e.printStackTrace();
//                            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//                        }
//
//                    }
//                }
//            }
//        }
//
//    }
    // 静态线程安全Set,用于存储正在调用接口的工位号
    private static final Set<Integer> callingStations = ConcurrentHashMap.newKeySet();
    public synchronized void generateStoreWrkFile(Integer mark) {
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        final Set<String> INVALID_BARCODES = new HashSet<>(Arrays.asList("NG", "NoRead", "00000000"));
        for (DevpSlave devp : slaveProperties.getDevp()) {
            for (DevpSlave.Sta inSta : devp.getInSta()) {
                // 【判断工位是否正在调用接口,跳过正在调用的】
                int staNo = inSta.getStaNo();
                if (!callingStations.add(staNo)) {
                    // 如果已存在调用中,跳过
                    log.info("工位{}接口调用中,跳过本次", staNo);
                    continue;
                }
                try {
                    BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, inSta.getBarcode());
                    LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, inSta.getLed());
                    SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                    StaProtocol staProtocol = devpThread.getStation().get(staNo);
                    StaProtocol staProtocolIn = devpThread.getStation().get(staNo - 1);
                    if (staProtocolIn == null || barcodeThread == null) continue;
                    staProtocolIn = staProtocolIn.clone();
                    String barcode = barcodeThread.getBarcode();
                    // 如果前工位有货 + 扫码器有条码
                    if (staProtocolIn.getStamp() == 1 && !barcode.equals("00000000") && !barcode.isEmpty()) {
                        log.info("生成信号时间: {}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));
                        if (wrkMastService.selectOne(new EntityWrapper<WrkMast>()
                                .eq("barcode", barcode)
                                .in("io_type", 107, 103, 57)) != null) {
                            continue;
                        }
                        try {
                            SearchLocParam param = new SearchLocParam();
                            param.setBarcode(barcode);
                            param.setIoType(1);
                            param.setSourceStaNo(staNo);
                            param.setLocType1((short) 1);
                            param.setWeight(staProtocol.getWeight());
                            String response = new HttpHandler.Builder()
                                    .setTimeout(30, TimeUnit.SECONDS)
                                    .setUri(wmsUrl)
                                    .setPath("/rpc/pakin/loc/v1")
                                    .setJson(JSON.toJSONString(param))
                                    .build()
                                    .doPost();
                            JSONObject json = JSON.parseObject(response);
                            if (json.getInteger("code").equals(200)) {
                                StartupDto dto = json.getObject("data", StartupDto.class);
                                barcodeThread.setBarcode("");
                                staProtocolIn.setWorkNo(dto.getWorkNo());
                                devpThread.setPakMk(staProtocolIn.getSiteId(), false);
                                boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(3, staProtocolIn));
                                log.info("生成任务时间: {}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));
                                ledThread.errorReset();
                                log.error("工作号下发2:" + dto.getWorkNo() + "," + dto.getStaNo());
                                if (!result) {
                                    News.error(methodName + ":更新plc站点信息失败");
                                    throw new CoolException("更新plc站点信息失败");
                                }
                            } else {
                                String msg = json.getString("msg");
                                if (!"工作档已存在".equals(msg) && staProtocol.getWorkNo()<9999) {
                                    staProtocol.setWorkNo(wrkNo++);
                                    staProtocol.setStaNo(inSta.getBackSta().shortValue());
                                    devpThread.setPakMk(staProtocol.getSiteId(), false);
                                    MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                                    log.error("输送线下发2:" + staProtocol.getWorkNo() + "," + staProtocol.getStaNo());
                                    if (!Cools.isEmpty(msg)) {
                                        MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, msg));
                                    }
                                }
                            }
                        } catch (Exception e) {
                            log.error("组托任务异常:", e);
                            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        }
                        continue;
                    } else {
                        // 尺寸/重量/扫码异常检测
                        if (staProtocol == null) continue;
                        staProtocol = staProtocol.clone();
                        boolean back = false;
                        String errMsg = "";
                        if (staProtocol.isFrontErr()) { errMsg = "前超限"; back = true; }
                        else if (staProtocol.isBackErr()) { errMsg = "后超限"; back = true; }
                        else if (staProtocol.isHighErr()) { errMsg = "高超限"; back = true; }
                        else if (staProtocol.isLeftErr()) { errMsg = "左超限"; back = true; }
                        else if (staProtocol.isRightErr()) { errMsg = "右超限"; back = true; }
                        else if (staProtocol.getWeight() > 1000) { errMsg = "超重或未读取"; back = true; }
                        else if (staProtocol.isBarcodeErr()) { errMsg = "扫码失败"; back = true; }
                        // 尺寸异常回退
                        if (back && staProtocol.getWorkNo() <9999) {
//                            log.info("errmsg: " + errMsg);
                            MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, errMsg));
                            if (!staProtocol.isLoading() || !staProtocol.isPakMk()) continue;
                            staProtocol.setWorkNo(wrkNo++);
                            staProtocol.setStaNo(inSta.getBackSta().shortValue());
                            devpThread.setPakMk(staProtocol.getSiteId(), false);
                            MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                            log.error("输送线下发1:" + wrkNo + "," + inSta.getBackSta());
                            continue;
                        }
//                        // 入库条件满足,开始请求入库地址
//                        if (staProtocol.isAutoing() && staProtocol.isLoading()
//                                && staProtocol.isInEnable() && !staProtocol.isEmptyMk() && staProtocol.isPakMk()) {
//
//                            if (Cools.isEmpty(barcode) || INVALID_BARCODES.contains(barcode)) {
//                                News.info("{}号条码扫描器检测条码信息:{}", inSta.getBarcode(), barcode);
//                                staProtocol.setWorkNo(wrkNo++);
//                                staProtocol.setStaNo(inSta.getBackSta().shortValue());
//                                devpThread.setPakMk(staProtocol.getSiteId(), false);
//                                MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                                log.error("输送线下发1:{} , {}", wrkNo, inSta.getBackSta());
//                                continue;
//                            }
//
//                            if (wrkMastMapper.selectPakInStep1(staNo, barcode) != null ||
//                                    wrkMastService.selectOne(new EntityWrapper<WrkMast>()
//                                            .eq("barcode", barcode)
//                                            .in("io_type", 107, 103, 57)) != null) {
//                                News.error(barcode + "条码已存在状态为(2.设备上走)的数据,请查看WCS输送线界面");
//                                continue;
//                            }
//
//                            try {
//                                SearchLocParam param = new SearchLocParam();
//                                param.setBarcode(barcode);
//                                param.setIoType(1);
//                                param.setSourceStaNo(staNo);
//                                param.setLocType1((short) 1);
//                                param.setWeight(staProtocol.getWeight());
//
//                                String response = new HttpHandler.Builder()
//                                        .setTimeout(30, TimeUnit.SECONDS)
//                                        .setUri(wmsUrl)
//                                        .setPath("/rpc/pakin/loc/v1")
//                                        .setJson(JSON.toJSONString(param))
//                                        .build()
//                                        .doPost();
//
//                                JSONObject json = JSON.parseObject(response);
//                                if (json.getInteger("code").equals(200)) {
//                                    StartupDto dto = json.getObject("data", StartupDto.class);
//                                    barcodeThread.setBarcode("");
//                                    staProtocol.setWorkNo(dto.getWorkNo());
//                                    staProtocol.setStaNo(dto.getStaNo().shortValue());
//                                    devpThread.setPakMk(staProtocol.getSiteId(), false);
//                                    boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                                    ledThread.errorReset();
//                                    log.error("输送线下发2:" + dto.getWorkNo() + "," + dto.getStaNo());
//
//                                    if (!result) {
//                                        News.error(methodName + ":更新plc站点信息失败");
//                                        throw new CoolException("更新plc站点信息失败");
//                                    }
//                                } else {
//                                    String msg = json.getString("msg");
//                                    if (!"工作档已存在".equals(msg)) {
//                                        staProtocol.setWorkNo(wrkNo++);
//                                        staProtocol.setStaNo(inSta.getBackSta().shortValue());
//                                        devpThread.setPakMk(staProtocol.getSiteId(), false);
//                                        MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                                        log.error("输送线下发2:" + staProtocol.getWorkNo() + "," + staProtocol.getStaNo());
//                                        if (!Cools.isEmpty(msg)) {
//                                            MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, msg));
//                                        }
//                                    }
//                                }
//                            } catch (Exception e) {
//                                log.error("组托任务异常:", e);
//                                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//                            }
//                        }
                    }
                } finally {
                    // 【无论接口调用是否成功,最后都释放调用标记】
                    callingStations.remove(staNo);
                    log.debug("工位{}接口调用完成,释放调用标记", staNo);
                }
            }
        }
    }
    /**
     * wms入库
@@ -922,7 +1344,7 @@
                if (crnProtocol.getLastIo().equals("I")) {
                    if (basCrnp.getInEnable().equals("Y")) {
                        //mark - 1 - ....
                        this.crnStnToLoc(crn, crnProtocol, mark); //  入库
                        this.crnStnToLoc(crn, crnProtocol, mark, crnThread); //  入库
                        crnProtocol.setLastIo("O");
                    } else if (basCrnp.getOutEnable().equals("Y")) {
                        //mark - 2 - ....
@@ -936,7 +1358,7 @@
                        this.locToCrnStn(crn, crnProtocol, mark); //  出库
                        crnProtocol.setLastIo("I");
                    } else if (basCrnp.getInEnable().equals("Y")) {
                        this.crnStnToLoc(crn, crnProtocol, mark); //  入库
                        this.crnStnToLoc(crn, crnProtocol, mark, crnThread); //  入库
                        crnProtocol.setLastIo("O");
                    }
                }
@@ -944,7 +1366,7 @@
            // 库位移转
            //mark - 3 - ....
            this.locToLoc(crn, crnProtocol, mark);
//            this.crnRebackHp(crnProtocol, crnThread);
            this.crnRebackHp(crnProtocol, crnThread,null);
        }
//        News.infoNoLog(""+mark+" - 0"+" - 堆垛机入出库作业下发执行完成");
@@ -953,55 +1375,103 @@
    /**
     * 回原点,堆垛机没有执行中任务,设备存在入库任务时叫回原点
     */
    public synchronized void crnRebackHp(CrnProtocol crnProtocol, CrnThread crnThread) {
//        for (CrnSlave crn : slaveProperties.getCrn()) {
//            // 获取堆垛机信息
//            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());
//                continue;
//            }
        if (crnProtocol.getStatusType() == CrnStatusType.IDLE && crnProtocol.getTaskNo() == 0 && crnProtocol.getModeType() == CrnModeType.AUTO) {
            if (crnProtocol.getBay() == 1 && crnProtocol.getLevel() == 1) {
                return;
    public synchronized void crnRebackHp(CrnProtocol crnProtocol, CrnThread crnThread,String staNo) {
        if(staNo == null){
            if (crnProtocol.getStatusType() == CrnStatusType.IDLE && crnProtocol.getTaskNo() == 0 && crnProtocol.getModeType() == CrnModeType.AUTO) {
                if (crnProtocol.getBay() == 121 || crnProtocol.getBay() == 1) {
                    return;
                }
                int x=1;
                switch (crnProtocol.getCrnNo()){
                    case 1: x =1; break;
                    case 2: x =3; break;
                    case 3: x =5; break;
                    case 4: x =7; break;
                }
                // 已经存在吊车执行任务时,则过滤3,12
                if (wrkMastMapper.selectWorking(crnProtocol.getCrnNo()) != null) {
                    return;
                }
                //堆垛机有执行中任务,过滤3,4,11,12
                if (wrkMastMapper.selectCrnWorking(crnProtocol.getCrnNo()) != null) {
                    return;
                }
                //输送线没有入库任务,过滤2
                if (wrkMastMapper.selectDevWorking(crnProtocol.getCrnNo()) != null) {
                    return;
                }
                News.info("堆垛机召回原点==>>" + crnProtocol.getCrnNo() + "号堆垛机有入库任务,召回原点");
                // 命令下发区 --------------------------------------------------------------------------
                CrnCommand crnCommand = new CrnCommand();
                crnCommand.setCrnNo(crnProtocol.getCrnNo()); // 堆垛机编号
                crnCommand.setTaskNo((short) 9999); // 工作号
                crnCommand.setAckFinish((short) 0);  // 任务完成确认位
                crnCommand.setTaskMode(CrnTaskModeType.X_MOVE); // 任务模式:  回原点
                crnCommand.setSourcePosX((short) x);     // 源库位排
                crnCommand.setSourcePosY((short) 121);     // 源库位列
                crnCommand.setSourcePosZ((short) 2);     // 源库位层
                crnCommand.setDestinationPosX((short) 0);     // 目标库位排
                crnCommand.setDestinationPosY((short) 0);     // 目标库位列
                crnCommand.setDestinationPosZ((short) 0);     // 目标库位层
                if (!MessageQueue.offer(SlaveType.Crn, crnProtocol.getCrnNo(), new Task(2, crnCommand))) {
                    News.error("堆垛机回原点命令下发失败,堆垛机号={},任务数据={}", crnProtocol.getCrnNo(), JSON.toJSON(crnCommand));
                }
                crnThread.setBackHpFlag(true);
            }
        } else {
            int y = 1; // 默认列
            int x=1;
            switch (crnProtocol.getCrnNo()){
                case 1: x =1; break;
                case 2: x =3; break;
                case 3: x =5; break;
                case 4: x =7; break;
            }
            int staNoInt = Integer.parseInt(staNo);
            int z = staNoInt / 100; // 层
            if ((staNoInt >= 121 && staNoInt <= 126) || (staNoInt >= 221 && staNoInt <= 231) || (staNoInt >= 411 && staNoInt <= 414)) {
                y = 121;
            }
            // 已经存在吊车执行任务时,则过滤3,12
            if (wrkMastMapper.selectWorking(crnProtocol.getCrnNo()) != null) {
                return;
            }
            if (crnProtocol.getStatusType() == CrnStatusType.IDLE && crnProtocol.getTaskNo() == 0 && crnProtocol.getModeType() == CrnModeType.AUTO) {
                if (crnProtocol.getBay() == y) {
                    return;
                }
            //堆垛机有执行中任务,过滤3,4,11,12
            if (wrkMastMapper.selectCrnWorking(crnProtocol.getCrnNo()) != null) {
                return;
            }
                // 已经存在吊车执行任务时,则过滤
                if (wrkMastMapper.selectWorking(crnProtocol.getCrnNo()) != null) {
                    return;
                }
            //输送线没有入库任务,过滤2
            if (wrkMastMapper.selectDevWorking(crnProtocol.getCrnNo()) == null) {
                return;
                // 堆垛机有执行中任务
                if (wrkMastMapper.selectCrnWorking(crnProtocol.getCrnNo()) != null) {
                    return;
                }
                News.info("堆垛机召回原点==>>" + crnProtocol.getCrnNo() + "号堆垛机有入库任务,召回原点");
                // 命令下发
                CrnCommand crnCommand = new CrnCommand();
                crnCommand.setCrnNo(crnProtocol.getCrnNo());
                crnCommand.setTaskNo((short) 9999);
                crnCommand.setAckFinish((short) 0);
                crnCommand.setTaskMode(CrnTaskModeType.X_MOVE);
                crnCommand.setSourcePosX((short) x); // 默认排始终为1
                crnCommand.setSourcePosY((short) y); // 动态列
                crnCommand.setSourcePosZ((short) z); // 动态层
                crnCommand.setDestinationPosX((short) 0);
                crnCommand.setDestinationPosY((short) 0);
                crnCommand.setDestinationPosZ((short) 0);
                if (!MessageQueue.offer(SlaveType.Crn, crnProtocol.getCrnNo(), new Task(2, crnCommand))) {
                    News.error("堆垛机回原点命令下发失败,堆垛机号={},任务数据={}", crnProtocol.getCrnNo(), JSON.toJSON(crnCommand));
                }
                crnThread.setBackHpFlag(true);
            }
            News.info("堆垛机召回原点==>>" + crnProtocol.getCrnNo() + "号堆垛机有入库任务,召回原点");
            // 命令下发区 --------------------------------------------------------------------------
            CrnCommand crnCommand = new CrnCommand();
            crnCommand.setCrnNo(crnProtocol.getCrnNo()); // 堆垛机编号
            crnCommand.setTaskNo((short) 9999); // 工作号
            crnCommand.setAckFinish((short) 0);  // 任务完成确认位
            crnCommand.setTaskMode(CrnTaskModeType.GO_ORIGIN); // 任务模式:  回原点
            crnCommand.setSourcePosX((short) 0);     // 源库位排
            crnCommand.setSourcePosY((short) 0);     // 源库位列
            crnCommand.setSourcePosZ((short) 0);     // 源库位层
            crnCommand.setDestinationPosX((short) 0);     // 目标库位排
            crnCommand.setDestinationPosY((short) 0);     // 目标库位列
            crnCommand.setDestinationPosZ((short) 0);     // 目标库位层
            if (!MessageQueue.offer(SlaveType.Crn, crnProtocol.getCrnNo(), new Task(2, crnCommand))) {
                News.error("堆垛机回原点命令下发失败,堆垛机号={},任务数据={}", crnProtocol.getCrnNo(), JSON.toJSON(crnCommand));
            }
            crnThread.setBackHpFlag(true);
        }
//        }
    }
@@ -1009,7 +1479,7 @@
    /**
     * 入库  ===>>  堆垛机站到库位
     */
    public synchronized void crnStnToLoc(CrnSlave slave, CrnProtocol crnProtocol, Integer mark) {
    public synchronized void crnStnToLoc(CrnSlave slave, CrnProtocol crnProtocol, Integer mark,CrnThread crnThread) {
        News.warnNoLog("" + mark + " - 1" + " - 0" + " - 堆垛机入出库作业下发:执行入库");
        for (CrnSlave.CrnStn crnStn : slave.getCrnInStn()) {
            boolean flag = false;
@@ -1028,11 +1498,23 @@
                News.error("" + mark + " - 1" + " - 2" + " - 入库 ===>> 堆垛机站点在数据库不存在, 站点编号={}", crnStn.getStaNo());
                continue;
            }
//            if(staProtocol.getWorkNo() == 9998){
//                continue;
            WrkMast wrkMast1 = wrkMastMapper.selectPakInOne(slave.getId());
            if(wrkMast1 != null){
                crnRebackHp(crnProtocol,crnThread,wrkMast1.getStaNo().toString());
            }
//            if(staProtocol.getSiteId() == 225){
//                News.info("入库站点信息{}",staProtocol);
//            staProtocol.isLoading() &&
//            }
            if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.getWorkNo() > 0 && staProtocol.isInEnable()
            if(staProtocol.getWorkNo() > 0 && staProtocol.getWorkNo() <9998){
                log.info("读取到工作号时间: {}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));
            }
//             && staProtocol.getWorkNo() > 0 && staProtocol.getWorkNo() <9998
            if (staProtocol.isAutoing() && staProtocol.getWorkNo() > 0 && staProtocol.getWorkNo() <9998
                    && staDetl.getCanining() != null && staDetl.getCanining().equals("Y")) {
                log.info("任务满足下发时间: {}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));
                flag = true;
            }
            if (!flag) {
@@ -1043,8 +1525,10 @@
                continue;
            }
            // 获取工作状态为2(设备上走)的入库工作档
            WrkMast wrkMast = wrkMastMapper.selectPakInStep2(slave.getId(), staProtocol.getWorkNo().intValue(), crnStn.getStaNo());
            WrkMast wrkMast = wrkMastMapper.selectPakInStep2(slave.getId(), staProtocol.getWorkNo(), crnStn.getStaNo());
//            wrkMast = wrkMast1;
            if (null == wrkMast) {
                log.info("" + mark + " - 1" + " - 4" + " - 查询无待入库数据--wrk_sts=2, 工作号={}", staProtocol.getWorkNo());
                News.infoNoLog("" + mark + " - 1" + " - 4" + " - 查询无待入库数据--wrk_sts=2, 工作号={}", staProtocol.getWorkNo());
//                log.error("查询无待入库数据--wrk_sts=2, 工作号={}", staProtocol.getWorkNo());
                continue;
@@ -1071,48 +1555,6 @@
                continue;
            }
//            // 双深库位且浅库位有货,则需先对浅库位进行库位移转
//            if (Utils.isDeepLoc(slaveProperties, wrkMast.getLocNo())) {
//                News.warnNoLog("" + mark + " - 1" + " - 8" + " - 双深库位且浅库位有货,则需先对浅库位进行库位移转 : 开始执行 任务号={}", wrkMast.getWrkNo());
//                String shallowLocNo = Utils.getShallowLoc(slaveProperties, wrkMast.getLocNo());
//                LocMast shallowLoc = locMastService.selectById(shallowLocNo);
//                // O.空库位、Q.拣料/盘点/并板再入库、S.入库预约、X.禁用 直接搬!
//                if (shallowLoc.getLocSts().equals("P") || shallowLoc.getLocSts().equals("R")) {
//                    News.warnNoLog("" + mark + " - 1" + " - 9" + " - // O.空库位、Q.拣料/盘点/并板再入库、S.入库预约、X.禁用 直接搬!库位状态={}", shallowLoc.getLocSts());
//                    WrkMast waitWrkMast = wrkMastMapper.selectByLocNo(shallowLocNo);
//                    if (null == waitWrkMast) {
//                        News.error("" + mark + " - 1" + " - 10" + " - {}库位异常,未检索到相应工作档!", shallowLocNo);
//                    } else {
//                        waitWrkMast.setIoPri(15D);
//                        waitWrkMast.setModiTime(new Date());
//                        if (wrkMastMapper.updateById(waitWrkMast) == 0) {
//                            News.error("" + mark + " - 1" + " - 11" + " - 调整工作档优先级失败!工作号={}", waitWrkMast.getWrkNo());
//                        }
//                        continue;
//                    }
//
//                } else if (shallowLoc.getLocSts().equals("F") || shallowLoc.getLocSts().equals("D")) {
//                    News.warnNoLog("" + mark + " - 1" + " - 12" + " - // F、D  库位状态={}", shallowLoc.getLocSts());
//                    // 此标记避免多次执行移库任务
//                    if (Cools.isEmpty(wrkMast.getUpdMk()) || "N".equals(wrkMast.getUpdMk())) {
//                        wrkMast.setUpdMk("Y");
//                        wrkMast.setIoPri(14D);
//                        wrkMastMapper.updateById(wrkMast);
//                        // 生成工作档,将浅库位移转到新的库位中
//                        moveLocForDeepLoc(slave, shallowLoc, mark);
//                        // 生成工作档、改变浅库位的源库/目标库 库位状态、下发堆垛机命令(立马执行)
////                        moveLocForDeepLocPakin(slave, shallowLoc, wrkMast);
//                    }
//                    continue;
//                } else if (shallowLoc.getLocSts().equals("Q")) {
//                    News.warnNoLog("" + mark + " - 1" + " - 13" + " - // Q  库位状态={}", shallowLoc.getLocSts());
//                    WrkMast waitWrkMast = wrkMastMapper.selectByLocNo(shallowLocNo);
//                    if (null != waitWrkMast && waitWrkMast.getWrkSts() == 4) {
//                        News.infoNoLog("" + mark + " - 1" + " - 14" + " - // F、D  工作状态(判断条件为==4)={}", waitWrkMast.getWrkSts());
//                        continue;
//                    }
//                }
//            }
            News.warnNoLog("" + mark + " - 1" + " - 15" + " - 命令下发 : 工作号={},源排={},源列={},源层={},目标排={},目标列={},目标层={}", wrkMast.getWrkNo().shortValue()
                    , crnStn.getRow().shortValue(), crnStn.getBay().shortValue(), crnStn.getLev().shortValue()
                    , locMast.getRow1().shortValue(), locMast.getBay1().shortValue(), locMast.getLev1().shortValue());
@@ -1130,21 +1572,12 @@
            crnCommand.setDestinationPosY((short) (locMast.getBay1() + slave.getOffset()));     // 目标库位列
            crnCommand.setDestinationPosZ((short) (locMast.getLev1() + slave.getOffset()));     // 目标库位层
//            crnCommand.setTraySize(locMast.getLocType1() == 2);
            log.info("堆垛机任务下发时间: {}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));
            if (!MessageQueue.offer(SlaveType.Crn, wrkMast.getCrnNo(), new Task(2, crnCommand))) {
                News.error("" + mark + " - 1" + " - 16" + " - 堆垛机命令下发失败,堆垛机号={},任务数据={}", wrkMast.getCrnNo(), JSON.toJSON(crnCommand));
            } else {
//                long startTime = System.currentTimeMillis();
//                while ((System.currentTimeMillis() - startTime) < COMMAND_TIMEOUT) {
//
//                    if (true) {
//                        break;
//                    }
//
//                    try{
//                        Thread.sleep(500);
//                    }catch(Exception ignore){}
//                }
                // 修改工作档状态 2.设备上走 => 3.吊车入库中
                Date now = new Date();
@@ -1209,10 +1642,21 @@
                    break;
//                    continue;
                }
//                 && !staProtocol.isLoading() && staDetl.getCanouting() != null && staDetl.getCanouting().equals("Y")
//                        && staProtocol.getWorkNo() == 0 && staProtocol.isOutEnable()
                boolean canOut;
                Config config = configService.selectConfigByCode("C-OUT-OP");
                if (Cools.isEmpty(config) || config.getValue().equals("false") ){
                    canOut = staProtocol.isAutoing()
                            && !staProtocol.isLoading()
                            && "Y".equals(staDetl.getCanouting())
                            && staProtocol.getWorkNo() == 0
                            && staProtocol.isOutEnable();
                } else {
                    canOut = staProtocol.isAutoing();
                }
                // 判断堆垛机出库站状态
                if (staProtocol.isAutoing()) {
                if (canOut) {
                    // 命令下发区 --------------------------------------------------------------------------
                    // 堆垛机控制过滤
@@ -1520,35 +1964,49 @@
            if (crnProtocol == null) {
                continue;
            }
            //  状态:等待确认 并且  任务完成位 = 1
            if (crnProtocol.statusType == CrnStatusType.WAITING && crnProtocol.getTaskNo() != 0) {
                News.warnNoLog("" + mark + " - 0" + " - 开始执行对工作档的完成操作,任务号:" + crnProtocol.getTaskNo());
            if(crnProtocol.getTaskNo() == 9999){
                //  状态:等待确认 并且  任务完成位 = 1
                if (crnProtocol.statusType == CrnStatusType.WAITING && crnProtocol.getTaskNo() != 0) {
                    News.warnNoLog("" + mark + " - 0" + " - 开始执行对工作档的完成操作,任务号:" + crnProtocol.getTaskNo());
                // 获取入库待确认工作档
                WrkMast wrkMast = wrkMastMapper.selectPakInStep3(crnProtocol.getTaskNo().intValue());
                if (wrkMast == null) {
                    News.error("" + mark + " - 1" + " - 堆垛机处于等待确认且任务完成状态,但未找到工作档。堆垛机号={},工作号={}", crn.getId(), crnProtocol.getTaskNo());
                    continue;
                }
                // 入库 + 库位转移  ==> 4.入库完成
                if (wrkMast.getWrkSts() == 3 || (wrkMast.getWrkSts() == 12 && wrkMast.getIoType() == 11)) {
                    wrkMast.setWrkSts(4L);
                } else {
                    continue;
                }
                Date now = new Date();
                wrkMast.setCrnEndTime(now);
                wrkMast.setModiTime(now);
                // 修改成功后复位堆垛机
                if (wrkMastMapper.updateById(wrkMast) > 0) {
                    // 堆垛机复位
                    log.error(wrkMast.getWrkNo() + "任务修改状态4成功,复位堆垛机={}", crnThread.getCrnProtocol().getCrnNo());
                    News.warnNoLog("" + mark + " - 2" + " - 修改成功后复位堆垛机 : 堆垛机号={}", crnThread.getCrnProtocol().getCrnNo());
                    crnThread.setResetFlag(true);
                }
            }else{
                //  状态:等待确认 并且  任务完成位 = 1
                if (crnProtocol.statusType == CrnStatusType.WAITING && crnProtocol.getTaskNo() != 0) {
                    News.warnNoLog("" + mark + " - 0" + " - 开始执行对工作档的完成操作,任务号:" + crnProtocol.getTaskNo());
                    // 获取入库待确认工作档
                    WrkMast wrkMast = wrkMastMapper.selectPakInStep3(crnProtocol.getTaskNo().intValue());
                    if (wrkMast == null ) {
                        News.error("" + mark + " - 1" + " - 堆垛机处于等待确认且任务完成状态,但未找到工作档。堆垛机号={},工作号={}", crn.getId(), crnProtocol.getTaskNo());
                        continue;
                    }
                    // 入库 + 库位转移  ==> 4.入库完成
                    if (wrkMast.getWrkSts() == 3 || (wrkMast.getWrkSts() == 12 && wrkMast.getIoType() == 11)) {
                        wrkMast.setWrkSts(4L);
                    } else {
                        continue;
                    }
                    Date now = new Date();
                    wrkMast.setCrnEndTime(now);
                    wrkMast.setModiTime(now);
                    // 修改成功后复位堆垛机
                    if (wrkMastMapper.updateById(wrkMast) > 0) {
                        // 堆垛机复位
                        log.error(wrkMast.getWrkNo() + "任务修改状态4成功,复位堆垛机={}", crnThread.getCrnProtocol().getCrnNo());
                        News.warnNoLog("" + mark + " - 2" + " - 修改成功后复位堆垛机 : 堆垛机号={}", crnThread.getCrnProtocol().getCrnNo());
                        crnThread.setResetFlag(true);
                    }
                }
            }
        }
//        News.infoNoLog(""+mark+" - 0"+" - 对工作档的完成操作执行完成");
    }