#
Junjie
2024-06-06 627f9f28c8a19d9deae694c11c10dec1d4593270
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/service/impl/MainServiceImpl.java
@@ -1,26 +1,33 @@
package com.zy.asrs.wcs.core.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zy.asrs.framework.common.Cools;
import com.zy.asrs.framework.common.SnowflakeIdWorker;
import com.zy.asrs.wcs.core.domain.dto.RedisMapDto;
import com.zy.asrs.wcs.core.domain.dto.StaDto;
import com.zy.asrs.wcs.core.entity.*;
import com.zy.asrs.wcs.core.kernel.AnalyzeService;
import com.zy.asrs.wcs.core.model.MapNode;
import com.zy.asrs.wcs.core.model.enums.DeviceCtgType;
import com.zy.asrs.wcs.core.model.enums.MotionStsType;
import com.zy.asrs.wcs.core.model.enums.TaskStsType;
import com.zy.asrs.wcs.core.service.*;
import com.zy.asrs.wcs.core.utils.RedisUtil;
import com.zy.asrs.wcs.core.utils.ShuttleDispatcher;
import com.zy.asrs.wcs.core.utils.Utils;
import com.zy.asrs.wcs.rcs.News;
import com.zy.asrs.wcs.rcs.cache.SlaveConnection;
import com.zy.asrs.wcs.rcs.constant.DeviceRedisConstant;
import com.zy.asrs.wcs.rcs.entity.Device;
import com.zy.asrs.wcs.rcs.entity.DeviceType;
import com.zy.asrs.wcs.rcs.model.enums.ShuttleProtocolStatusType;
import com.zy.asrs.wcs.rcs.model.enums.SlaveType;
import com.zy.asrs.wcs.rcs.model.protocol.ShuttleProtocol;
import com.zy.asrs.wcs.rcs.model.protocol.StaProtocol;
import com.zy.asrs.wcs.rcs.service.DeviceService;
import com.zy.asrs.wcs.rcs.service.DeviceTypeService;
import com.zy.asrs.wcs.rcs.thread.BarcodeThread;
import com.zy.asrs.wcs.rcs.thread.DevpThread;
import com.zy.asrs.wcs.rcs.thread.ShuttleThread;
import com.zy.asrs.wcs.system.entity.Dict;
@@ -30,9 +37,7 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.*;
/**
 * 立体仓库WCS系统主流程业务
@@ -52,8 +57,6 @@
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private DeviceTypeService deviceTypeService;
    @Autowired
    private LocCtgService locCtgService;
    @Autowired
    private LocService locService;
@@ -65,13 +68,351 @@
    private DictService dictService;
    @Autowired
    private ShuttleDispatcher shuttleDispatcher;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private BasConveyorService basConveyorService;
    /**
     * 组托
     * 入库站,根据条码扫描生成入库工作档,工作状态 2
     */
    public synchronized void generateInboundWrk() {
        try {
            // 根据输送线plc遍历
            List<Device> list = deviceService.list(new LambdaQueryWrapper<Device>()
                    .eq(Device::getDeviceType, DeviceCtgType.CONVEYOR.val())
                    .eq(Device::getStatus, 1));
            for (Device devp : list) {
                BasConveyor basConveyor = basConveyorService.getOne(new LambdaQueryWrapper<BasConveyor>().eq(BasConveyor::getDeviceId, devp.getId()).eq(BasConveyor::getHostId, devp.getHostId()));
                // 遍历入库口
                for (StaDto inSta : JSON.parseArray(basConveyor.getInSta(), StaDto.class)) {
                    // 获取入库站信息
                    DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId().intValue());
                    StaProtocol staProtocol = devpThread.getStation().get(inSta.getStaNo());
                    if (staProtocol == null) {
                        continue;
                    } else {
                        staProtocol = staProtocol.clone();
                    }
                    Short workNo = staProtocol.getWorkNo();
                    // 尺寸检测异常
                    boolean back = false;
                    String errMsg = "异常:";
                    if (staProtocol.isFrontErr()) {
                        errMsg = errMsg + "前超限;";
                        back = true;
                    }
                    if (staProtocol.isBackErr()) {
                        errMsg = errMsg + "后超限";
                        back = true;
                    }
                    if (staProtocol.isHighErr()) {
                        errMsg = errMsg + "高超限";
                        back = true;
                    }
                    if (staProtocol.isLeftErr()) {
                        errMsg = errMsg + "左超限";
                        back = true;
                    }
                    if (staProtocol.isRightErr()) {
                        errMsg = errMsg + "右超限";
                        back = true;
                    }
                    if (staProtocol.isWeightErr()) {
                        errMsg = errMsg + "超重";
                        back = true;
                    }
                    if (staProtocol.isBarcodeErr()) {
                        errMsg = errMsg + "扫码失败";
                        back = true;
                    }
                    // 退回
                    if (back) {
//                        // led 异常显示
//                        LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, inSta.getLed());
//                        if (ledThread != null) {
//                            MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, errMsg));
//                        }
                        continue;
                    }
                    // 判断是否满足入库条件
                    if (staProtocol.isAutoing() && staProtocol.isLoading()
                            && staProtocol.isInEnable()
                            && !staProtocol.isEmptyMk() && (workNo == 0 || (workNo >= 9990 && workNo <= 9999))
                    ) {
                        // 获取条码扫描仪信息
                        BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, inSta.getBarcode());
                        if (barcodeThread == null) {
                            continue;
                        }
                        String barcode = barcodeThread.getBarcode();
                        if (!Cools.isEmpty(barcode)) {
//                        News.info("{}号条码扫描器检测条码信息:{}", inSta.getBarcode(), barcode);
                            if ("NG".endsWith(barcode) || "NoRead".equals(barcode) || "empty".equals(barcode) || "00000000".equals(barcode)) {
//                            staProtocol.setWorkNo((short) 32002);
//                            staProtocol.setStaNo(inSta.getBackSta().shortValue());
//                            devpThread.setPakMk(staProtocol.getSiteId(), false);
//                            MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                                // led 异常显示
//                                LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, inSta.getLed());
//                                if (ledThread != null) {
//                                    String errorMsg = "扫码失败,请重试";
//                                    MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, errorMsg));
//                                }
                                continue;
                            }
                        } else {
//                        staProtocol.setWorkNo((short) 32002);
//                        staProtocol.setStaNo(inSta.getBackSta().shortValue());
//                        devpThread.setPakMk(staProtocol.getSiteId(), false);
//                        MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                        // led 异常显示
//                        LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, inSta.getLed());
//                        if (ledThread != null) {
//                            String errorMsg = "扫码失败,请重试";
//                            MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, errorMsg));
//                        }
                            continue;
                        }
//                        // 过滤盘点/拣料/并板任务
//                        WrkMast wrkMast1 = wrkMastMapper.selectPickStepByBarcode(barcode);
//                        if (null != wrkMast1) {
//                            continue;
//                        }
//
//                        // 判断重复工作档
//                        WrkMast wrkMast2 = wrkMastMapper.selectPakInStep1(inSta.getStaNo(), barcode);
//                        if (wrkMast2 != null) {
//                            News.error("工作档中已存在该站状态为( 2.设备上走 )的数据,工作号={}", wrkMast2.getWrkNo());
//                            continue;
//                        }
//
//                        try {
//                            LocTypeDto locTypeDto = new LocTypeDto(staProtocol);
//                            SearchLocParam param = new SearchLocParam();
//                            param.setBarcode(barcode);
//                            param.setIoType(1);
//                            param.setSourceStaNo(inSta.getStaNo());
//                            param.setLocType1(locTypeDto.getLocType1());
//                            String response = new HttpHandler.Builder()
//                                    .setUri(wmsUrl)
//                                    .setPath("/rpc/pakin/loc/v2")
//                                    .setJson(JSON.toJSONString(param))
//                                    .build()
//                                    .doPost();
//                            JSONObject jsonObject = JSON.parseObject(response);
//                            LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, inSta.getLed());
//                            Integer code = jsonObject.getInteger("code");
//                            if (code.equals(200)) {
//                                StartupDto dto = jsonObject.getObject("data", StartupDto.class);
////                            staProtocol.setWorkNo(dto.getWorkNo().shortValue());
////                            staProtocol.setStaNo(dto.getStaNo().shortValue());
////                            devpThread.setPakMk(staProtocol.getSiteId(), false);
////
////                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
////                            if (!result) {
////                                throw new CoolException("更新plc站点信息失败");
////                            }
//
//                                // 判断重复工作档
//                                WrkMast wrkMast = wrkMastMapper.selectPakInStep11(inSta.getStaNo());
//                                if (wrkMast == null) {
//                                    continue;
//                                }
//
//                                // 更新工作主档
//                                wrkMast.setWrkSts(2L); // 工作状态:2.设备上走
//                                wrkMast.setModiTime(new Date());
//                                if (wrkMastMapper.updateById(wrkMast) == 0) {
//                                    News.error("更新工作档失败!!! [工作号:{}]", wrkMast.getWrkNo());
//                                }
//
//                            } else if (code == 500) {
//                                if (ledThread != null) {
//                                    String errorMsg = jsonObject.getString("msg");
//                                    if (!Cools.isEmpty(errorMsg)) {
//                                        MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, errorMsg));
//                                        ledThread.setLedMk(false);
//                                    }
//                                }
//                                News.error("请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/pakin/loc/v2", JSON.toJSONString(param), response);
//                            } else if (code == 700) {
////                            staProtocol.setWorkNo((short) 32002);
////                            staProtocol.setRollback102(1);//102站回退信号
////                            devpThread.setPakMk(staProtocol.getSiteId(), false);
////                            MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(5, staProtocol));
//
//                                // led 异常显示
//                                if (ledThread != null) {
//                                    String errorMsg = barcode + "托盘识别异常,请先进行组托!";
//                                    MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, errorMsg));
//                                    ledThread.setLedMk(false);
//                                }
//                            }
//                        } catch (Exception e) {
//                            e.printStackTrace();
//                            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 初始化实时地图
     */
    public synchronized void initRealtimeBasMap() {
        try {
            List<Dict> dicts = dictService.list(new LambdaQueryWrapper<Dict>()
                    .like(Dict::getFlag, "map-")
                    .eq(Dict::getStatus, 1));
            TreeMap<Integer, ArrayList<ArrayList<MapNode>>> levData = new TreeMap<>();
            for (Dict dict : dicts) {
                String[] split = dict.getFlag().split("-");
                int lev = Integer.parseInt(split[1]);
                TreeMap<Integer, List<JSONObject>> rows = new TreeMap<>();
                //排序Row
                JSONArray value = JSON.parseArray(dict.getValue());
                for (Object o : value) {
                    JSONObject item = JSON.parseObject(o.toString());
                    if (item.getString("type").equals("SHELF")) {
                        JSONObject property = JSON.parseObject(item.getString("property"));
                        Integer row1 = property.getInteger("row");
                        ArrayList<JSONObject> bays = new ArrayList<>();
                        if (rows.containsKey(row1)) {
                            bays.addAll(rows.get(row1));
                        }
                        bays.add(property);
                        rows.put(row1, bays);
                    }
                }
                ArrayList<ArrayList<MapNode>> list = new ArrayList<>();
                //排序Bay
                for (Map.Entry<Integer, List<JSONObject>> entry : rows.entrySet()) {
                    ArrayList<MapNode> nodes = new ArrayList<>();
                    for (JSONObject object : entry.getValue()) {
                        MapNode mapNode = new MapNode();
                        mapNode.setValue(object.getInteger("shelfType"));
                        mapNode.setTop(object.getInteger("top"));
                        mapNode.setBottom(object.getInteger("bottom"));
                        mapNode.setLeft(object.getInteger("left"));
                        mapNode.setRight(object.getInteger("right"));
                        mapNode.setRow(object.getInteger("row"));
                        mapNode.setBay(object.getInteger("bay"));
                        mapNode.setNo(object.getString("row") + "-" + object.getString("bay"));
                        mapNode.setXBase(object.getInteger("refx"));
                        mapNode.setYBase(object.getInteger("refy"));
                        nodes.add(mapNode);
                    }
                    Collections.sort(nodes, new Comparator<MapNode>() {
                        @Override
                        public int compare(MapNode o1, MapNode o2) {
                            return Integer.compare(o1.getBay(), o2.getBay());
                        }
                    });
                    ArrayList<MapNode> sortNodes = new ArrayList<>();
                    int defaultBay = 1;//默认从1列开始
                    for (MapNode node : nodes) {
                        if (node.getBay() == defaultBay) {
                            defaultBay++;
                            sortNodes.add(node);
                            continue;
                        }
                        //存在空缺节点,自动补足
                        for (int i = defaultBay; i < node.getBay(); i++) {
                            MapNode mapNode = new MapNode();
                            mapNode.setValue(-1);
                            mapNode.setTop(1000);
                            mapNode.setBottom(1000);
                            mapNode.setLeft(1000);
                            mapNode.setRight(1000);
                            mapNode.setRow(node.getRow());
                            mapNode.setBay(i);
                            mapNode.setNo(node.getRow() + "-" + i);
                            mapNode.setXBase(0);
                            mapNode.setYBase(0);
                            sortNodes.add(mapNode);
                        }
                        defaultBay = node.getBay() + 1;
                        sortNodes.add(node);
                    }
                    list.add(sortNodes);
                }
                levData.put(lev, list);
            }
            for (Map.Entry<Integer, ArrayList<ArrayList<MapNode>>> entry : levData.entrySet()) {
                ArrayList<ArrayList<MapNode>> lists = entry.getValue();//获取地图
                MapNode mapNode = new MapNode();
                mapNode.setValue(-1);
                mapNode.setTop(1000);
                mapNode.setBottom(1000);
                mapNode.setLeft(1000);
                mapNode.setRight(1000);
                mapNode.setRow(0);
                mapNode.setBay(0);
                mapNode.setNo("0-0");
                mapNode.setXBase(0);
                mapNode.setYBase(0);
                //获取最长row
                int row = 0;
                //给每个row首尾增加-1节点
                for (ArrayList<MapNode> list : lists) {
                    if (list.size() > row) {
                        row = list.size();
                    }
                    list.add(0, mapNode.clone());
                    list.add(mapNode.clone());
                }
                ArrayList<MapNode> headNodes = new ArrayList<>();
                ArrayList<MapNode> footerNodes = new ArrayList<>();
                for (int i = 0; i < row+2; i++) {
                    headNodes.add(mapNode.clone());
                    footerNodes.add(mapNode.clone());
                }
                lists.add(0, headNodes);
                lists.add(footerNodes);
                Integer lev = entry.getKey();
                Date now = new Date();
                RedisMapDto map = new RedisMapDto();
                map.setData(JSON.toJSONString(lists));
                map.setCreateTime(now);
                map.setUpdateTime(now);
                map.setLev(lev);
                Object data = redisUtil.get(DeviceRedisConstant.MAP + lev);
                if (data == null) {
                    //将地图数据存入redis
                    redisUtil.set(DeviceRedisConstant.MAP + lev, JSON.toJSONString(map));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 解析入库工作档
@@ -173,15 +514,8 @@
            return;
        }
        DeviceType deviceType = deviceTypeService.getOne(new LambdaQueryWrapper<DeviceType>()
                .eq(DeviceType::getFlag, String.valueOf(SlaveType.Shuttle))
                .eq(DeviceType::getStatus, 1));
        if (deviceType == null) {
            return;
        }
        List<Device> list = deviceService.list(new LambdaQueryWrapper<Device>()
                .eq(Device::getDeviceType, deviceType.getId())
                .eq(Device::getDeviceType, DeviceCtgType.SHUTTLE.val())
                .eq(Device::getStatus, 1));
        for (Device device : list) {
            //获取四向穿梭车线程
@@ -196,6 +530,10 @@
            }
            if (!shuttleProtocol.getProtocolStatusType().equals(ShuttleProtocolStatusType.IDLE)) {
                continue;
            }
            if (!shuttleThread.isRequireCharge()) {
                continue;
            }
@@ -268,7 +606,7 @@
            Task task = new Task();
            task.setUuid(String.valueOf(snowflakeIdWorker.nextId()));
            task.setTaskNo(String.valueOf(Utils.getTaskNo("CHARGE")));
            task.setTaskSts(TaskStsType.NEW_CHARGE.getId());
            task.setTaskSts(TaskStsType.NEW_CHARGE.sts);
            task.setTaskCtg(taskCtg.getId());
            task.setPriority(10);
            task.setOriginSite(null);
@@ -320,20 +658,18 @@
            return;
        }
        DeviceType deviceType = deviceTypeService.getOne(new LambdaQueryWrapper<DeviceType>()
                .eq(DeviceType::getFlag, String.valueOf(SlaveType.Shuttle))
                .eq(DeviceType::getStatus, 1));
        if (deviceType == null) {
            return;
        }
        List<Device> list = deviceService.list(new LambdaQueryWrapper<Device>()
                .eq(Device::getDeviceType, deviceType.getId())
                .eq(Device::getDeviceType, DeviceCtgType.SHUTTLE.val())
                .eq(Device::getStatus, 1));
        for (Device device : list) {
            //获取四向穿梭车线程
            ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue());
            if (shuttleThread == null) {
                continue;
            }
            ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
            if (shuttleProtocol == null) {
                continue;
            }
@@ -365,7 +701,7 @@
            Task task = new Task();
            task.setUuid(String.valueOf(snowflakeIdWorker.nextId()));
            task.setTaskNo(String.valueOf(Utils.getTaskNo("MOVE")));
            task.setTaskSts(TaskStsType.NEW_MOVE.getId());
            task.setTaskSts(TaskStsType.NEW_MOVE.sts);
            task.setTaskCtg(taskCtg.getId());
            task.setPriority(10);
            task.setOriginSite(null);