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.common.domain.dto.StartupDto; import com.zy.asrs.common.domain.param.SearchLocParam; import com.zy.asrs.common.utils.HttpHandler; import com.zy.asrs.framework.common.Cools; import com.zy.asrs.framework.common.SnowflakeIdWorker; import com.zy.asrs.wcs.core.domain.dto.MatDto; 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.*; 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.model.command.LedCommand; 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.thread.BarcodeThread; import com.zy.asrs.wcs.rcs.thread.DevpThread; import com.zy.asrs.wcs.rcs.thread.LedThread; import com.zy.asrs.wcs.rcs.thread.ShuttleThread; import com.zy.asrs.wcs.system.entity.Dict; import com.zy.asrs.wcs.system.service.DictService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.interceptor.TransactionAspectSupport; import java.util.*; /** * 立体仓库WCS系统主流程业务 * Created by vincent on 2020/8/6 */ @Slf4j @Service("mainService") @Transactional public class MainServiceImpl { @Autowired private TaskService taskService; @Autowired private AnalyzeService analyzeService; @Autowired private MotionService motionService; @Autowired private DeviceService deviceService; @Autowired private LocCtgService locCtgService; @Autowired private LocService locService; @Autowired private SnowflakeIdWorker snowflakeIdWorker; @Autowired private TaskCtgService taskCtgService; @Autowired private DictService dictService; @Autowired private ShuttleDispatcher shuttleDispatcher; @Autowired private RedisUtil redisUtil; @Autowired private BasConveyorService basConveyorService; @Autowired private BasConveyorStaService basConveyorStaService; @Autowired private BasConveyorPathService basConveyorPathService; @Autowired private BasLedService basLedService; /** * 组托 * 入库站,根据条码扫描生成入库工作档,工作状态 2 */ public synchronized void generateInboundWrk() { try { // 根据输送线plc遍历 List list = deviceService.list(new LambdaQueryWrapper() .eq(Device::getDeviceType, DeviceCtgType.CONVEYOR.val()) .eq(Device::getStatus, 1)); for (Device devp : list) { BasConveyor basConveyor = basConveyorService.getOne(new LambdaQueryWrapper().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.Conveyor, 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) { ledThread.error(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); devpThread.writeWorkSta(staProtocol.getSiteId(), (short) 32002, inSta.getBackSta().shortValue()); // led 异常显示 LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, inSta.getLed()); if (ledThread != null) { String errorMsg = "扫码失败,请重试"; ledThread.error(errorMsg); } continue; } } //获取入库任务类型 TaskCtg taskCtg = taskCtgService.getOne(new LambdaQueryWrapper() .eq(TaskCtg::getFlag, String.valueOf(TaskCtgType.IN)) .eq(TaskCtg::getStatus, 1)); // 判断重复工作档 Task task1 = taskService.getOne(new LambdaQueryWrapper() .eq(Task::getOriginSite, inSta.getStaNo()) .eq(Task::getTaskCtg, taskCtg.getId()) .in(Task::getTaskSts, 1, 2, 3) .eq(Task::getZpallet, barcode)); if (task1 != null) { News.error("工作档已存在,工作号={}", task1.getTaskNo()); continue; } try { //获取WMS地址 Dict dict = dictService.getOne(new LambdaQueryWrapper().eq(Dict::getFlag, "WMS_URL").eq(Dict::getStatus, 1)); if (dict == null) { News.error("WMS地址未配置"); continue; } String wmsUrl = dict.getValue(); SearchLocParam param = new SearchLocParam(); param.setBarcode(barcode); param.setIoType(1); param.setSourceStaNo(inSta.getStaNo()); param.setLocType1(staProtocol.getLocType1().shortValue()); 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); //获取输送路径 BasConveyorPath conveyorPath = basConveyorPathService.getOne(new LambdaQueryWrapper() .eq(BasConveyorPath::getTypeNo, TaskCtgType.IN.val()) .eq(BasConveyorPath::getDeviceId, devp.getId()) .eq(BasConveyorPath::getStnNo, staProtocol.getSiteId())); if (conveyorPath == null) { News.error("输送路径不存在"); }else { devpThread.writeWorkSta(staProtocol.getSiteId(), dto.getWorkNo().shortValue(), conveyorPath.getDeviceStn().shortValue()); devpThread.setPakMk(staProtocol.getSiteId(), false); } }else { if (ledThread != null) { String errorMsg = jsonObject.getString("msg"); if (!Cools.isEmpty(errorMsg)) { ledThread.error(errorMsg); ledThread.setLedMk(false); } } News.error("请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/pakin/loc/v2", JSON.toJSONString(param), response); } } catch (Exception e) { e.printStackTrace(); TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } } } } } catch (Exception e) { e.printStackTrace(); } } /** * 初始化实时地图 */ public synchronized void initRealtimeBasMap() { try { List dicts = dictService.list(new LambdaQueryWrapper() .like(Dict::getFlag, "map-") .eq(Dict::getStatus, 1)); TreeMap>> levData = new TreeMap<>(); for (Dict dict : dicts) { String[] split = dict.getFlag().split("-"); int lev = Integer.parseInt(split[1]); Object data = redisUtil.get(DeviceRedisConstant.MAP + lev); if (data != null) { continue; } TreeMap> 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 bays = new ArrayList<>(); if (rows.containsKey(row1)) { bays.addAll(rows.get(row1)); } bays.add(property); rows.put(row1, bays); } } ArrayList> list = new ArrayList<>(); //排序Bay for (Map.Entry> entry : rows.entrySet()) { ArrayList 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() { @Override public int compare(MapNode o1, MapNode o2) { return Integer.compare(o1.getBay(), o2.getBay()); } }); ArrayList 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>> entry : levData.entrySet()) { ArrayList> 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 list : lists) { if (list.size() > row) { row = list.size(); } list.add(0, mapNode.clone()); list.add(mapNode.clone()); } //最后一次检测地图节点是否完整,地图矩阵row均要达到最长row for (ArrayList list : lists) { int len = (row + 2);//row+2是因为头节点和尾节点存在人为添加的-1节点 if (list.size() == len) { continue; } //节点长度不满足,进行补足 for (int i = list.size(); i < len; i++) { list.add(mapNode.clone()); } } ArrayList headNodes = new ArrayList<>(); ArrayList 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); //将地图数据存入redis redisUtil.set(DeviceRedisConstant.MAP + lev, JSON.toJSONString(map)); } } catch (Exception e) { e.printStackTrace(); } } // 解析入库工作档 public synchronized void analyzeInBoundTask() { for (Task task : taskService.selectWaitAnalyzeInBoundTask()) { if (Cools.isEmpty(task.getShuttleNo())) { //分配小车 //搜索空闲车 ShuttleThread shuttleThread = shuttleDispatcher.searchIdleShuttle(task); if (shuttleThread == null) { News.info("{}任务未找到空闲穿梭车", task.getTaskNo()); continue; } task.setShuttleNo(Integer.valueOf(shuttleThread.getDevice().getDeviceNo()));//保存穿梭车号 task.setUpdateTime(new Date()); if (!taskService.updateById(task)) { News.info("{}任务更新穿梭车号失败", task.getTaskNo()); } continue; } // generate motion list List motionList = analyzeService.generateMotion(task); if (motionList.isEmpty()) { continue; } motionService.batchInsert(motionList, task.getUuid(), Integer.valueOf(task.getTaskNo()), task.getHostId()); // 更新工作主档 task.setTaskSts(TaskStsType.ANALYZE_INBOUND.sts); // 工作状态 task.setUpdateTime(new Date()); if (!taskService.updateById(task)) { News.error("更新工作档失败!!! [工作号:{}]", task.getTaskNo()); } } } /** * 出库 ====>> 同一时间一台穿梭车只能有一个出库任务 */ public synchronized void analyzeOutBoundTask() { List tasks = taskService.selectPakOut(); if (tasks.isEmpty()) { return; } for (Task task : tasks) { BasConveyorSta originStaObj = basConveyorStaService.selectBySiteNo(task.getOriginSite());//获取源站 if (originStaObj == null) { continue; } BasConveyor basConveyor = basConveyorService.getById(originStaObj.getConveyorId()); if(basConveyor == null) { continue; } DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Conveyor, basConveyor.getDeviceId().intValue()); StaProtocol staProtocol = devpThread.getStation().get(Integer.parseInt(task.getOriginSite()));//源站 // StaProtocol staProtocol1 = devpThread.getStation().get(Integer.parseInt(task.getDestSite()));//目标站 if (staProtocol == null) { continue; } else { staProtocol = staProtocol.clone(); // staProtocol1 = staProtocol1.clone(); } // 判断堆垛机出库站状态 if (staProtocol.isAutoing() && !staProtocol.isLoading() && staProtocol.getWorkNo() == 0 && staProtocol.isOutEnable()) { // if (!(staProtocol1.isAutoing() && !staProtocol1.isLoading() && staProtocol1.getWorkNo() == 0 && staProtocol1.isOutEnable())) { // continue; // } // //同库位组校验 // List outerLoc = Utils.getGroupOuterLoc(wrkMast.getSourceLocNo()); // List outerLocMasts = locMastService.selectNotEmptyLocNos(outerLoc); // if (!outerLocMasts.isEmpty()) { // News.info("{}任务,浅库位存在货物,系统等待中", wrkMast.getWrkNo()); // continue;//浅库位存在未执行任务 // } if (Cools.isEmpty(task.getShuttleNo())) { //分配小车 //搜索空闲车 ShuttleThread shuttleThread = shuttleDispatcher.searchIdleShuttle(task); if (shuttleThread == null) { News.info("{}任务未找到空闲穿梭车", task.getTaskNo()); continue; } task.setShuttleNo(Integer.valueOf(shuttleThread.getDevice().getDeviceNo()));//保存穿梭车号 task.setUpdateTime(new Date()); if (!taskService.updateById(task)) { News.info("{}任务更新穿梭车号失败", task.getTaskNo()); } continue; } // generate motion list List motionList = analyzeService.generateMotion(task); if (Cools.isEmpty(motionList)) { log.error("出库 ===>> 暂时没有空闲小车, 任务号={}", task.getTaskNo()); continue; } motionService.batchInsert(motionList, task.getUuid(), Integer.valueOf(task.getTaskNo()), task.getHostId()); // 更新工作主档 task.setTaskSts(TaskStsType.ANALYZE_OUTBOUND.sts); // 工作状态 task.setUpdateTime(new Date()); if (!taskService.updateById(task)) { News.error("更新工作档失败!!! [工作号:{}]", task.getTaskNo()); } } } } // 解析小车移动工作档 public synchronized void analyzeMoveTask() { for (Task task : taskService.selectWaitAnalyzeMoveTask()) { if (Cools.isEmpty(task.getShuttleNo())) { //分配小车 //搜索空闲车 ShuttleThread shuttleThread = shuttleDispatcher.searchIdleShuttle(task); if (shuttleThread == null) { News.info("{}任务未找到空闲穿梭车", task.getTaskNo()); continue; } task.setShuttleNo(Integer.valueOf(shuttleThread.getDevice().getDeviceNo()));//保存穿梭车号 task.setUpdateTime(new Date()); if (!taskService.updateById(task)) { News.info("{}任务更新穿梭车号失败", task.getTaskNo()); } continue; } // generate motion list List motionList = analyzeService.generateShuttleMoveMotion(task); if (motionList.isEmpty()) { continue; } motionService.batchInsert(motionList, task.getUuid(), Integer.valueOf(task.getTaskNo()), task.getHostId()); // 更新工作主档 task.setTaskSts(TaskStsType.ANALYZE_MOVE.sts); // 工作状态 task.setUpdateTime(new Date()); if (!taskService.updateById(task)) { News.error("更新工作档失败!!! [工作号:{}]", task.getTaskNo()); } } } /** * 四向穿梭车电量检测 ===>> 发起充电 */ public synchronized void loopShuttleCharge() { //获取充电任务类型 TaskCtg taskCtg = taskCtgService.getOne(new LambdaQueryWrapper() .eq(TaskCtg::getFlag, String.valueOf(TaskCtgType.CHARGE)) .eq(TaskCtg::getStatus, 1)); if (taskCtg == null) { return; } List list = deviceService.list(new LambdaQueryWrapper() .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; } if (!shuttleProtocol.getProtocolStatusType().equals(ShuttleProtocolStatusType.IDLE)) { continue; } if (!shuttleThread.isRequireCharge()) { continue; } String currentLocNo = shuttleProtocol.getCurrentLocNo(); int lev = Utils.getLev(currentLocNo);//获取小车楼层 //搜索小车当前楼层充电桩 ArrayList allChargeLoc = new ArrayList<>(); List list1 = locService.list(new LambdaQueryWrapper() .eq(Loc::getLocSts, LocStsType.C.val()) .eq(Loc::getStatus, 1) .eq(Loc::getLev, lev)); if (!list1.isEmpty()) { allChargeLoc.addAll(list1); } //搜索其他楼层充电桩 List list2 = locService.list(new LambdaQueryWrapper() .eq(Loc::getLocSts, LocStsType.C.val()) .eq(Loc::getStatus, 1) .notIn(Loc::getLev, lev)); if (!list2.isEmpty()) { allChargeLoc.addAll(list2); } //没有找到充电桩 if (allChargeLoc.isEmpty()) { continue; } //选择空闲充电桩 Loc chargeLoc = null; for (Loc loc : allChargeLoc) { // 判断充电位是否被占用(车辆位置) if (Utils.hasShuttleInLoc(loc.getLocNo(), device.getId())) { continue; } // 盘点充电位是否存在任务档 List tasks = taskService.hasChargeInLoc(loc.getLocNo()); if (!tasks.isEmpty()) { continue; } chargeLoc = loc; break; } if (chargeLoc == null) { continue;//未找到充电桩 } if (motionService.count(new LambdaQueryWrapper() .eq(Motion::getDeviceCtg, DeviceCtgType.SHUTTLE.val()) .eq(Motion::getDevice, device.getDeviceNo()) .eq(Motion::getMotionSts, MotionStsType.EXECUTING.val())) > 0) { continue; } //判断当前小车是否满足需要充电要求 if (!shuttleThread.isRequireCharge()) { continue; } Task taskCharge = taskService.selectChargeWorking(Integer.valueOf(device.getDeviceNo())); if (taskCharge != null) {//已有充电任务 continue; } String chargeLocNo = chargeLoc.getLocNo(); Task task = new Task(); task.setUuid(String.valueOf(snowflakeIdWorker.nextId())); task.setTaskNo(String.valueOf(Utils.getTaskNo("CHARGE"))); task.setTaskSts(TaskStsType.NEW_CHARGE.sts); task.setTaskCtg(taskCtg.getId()); task.setPriority(10); task.setOriginSite(null); task.setOriginLoc(null); task.setDestSite(null); task.setDestLoc(chargeLocNo); task.setIoTime(new Date()); task.setStartTime(new Date()); task.setHostId(device.getHostId()); task.setStatus(1); task.setMemo("charge"); task.setShuttleNo(Integer.valueOf(device.getDeviceNo())); // generate motion list List motionList = analyzeService.generateChargeMotion(task); if (Cools.isEmpty(motionList)) { News.error("保存{}号四向穿梭车充电任务失败!!!", device.getDeviceNo()); continue; } motionService.batchInsert(motionList, task.getUuid(), Integer.valueOf(task.getTaskNo()), task.getHostId()); task.setTaskSts(TaskStsType.ANALYZE_CHARGE.sts); if (!taskService.save(task)) { News.error("保存{}号四向穿梭车充电任务失败!!!", device.getDeviceNo()); continue; } News.info("保存{}号四向穿梭车充电任务成功!!!", device.getDeviceNo()); } } /** * 四向穿梭车电量检测 ===>> 满电后回到待机位 */ public synchronized void loopShuttleToStandbyCauseCharge() { Integer enoughPower = 90; Dict dict = dictService.getOne(new LambdaQueryWrapper() .eq(Dict::getFlag, "chargeMaxValue") .eq(Dict::getStatus, 1)); if (dict != null) { enoughPower = Integer.parseInt(dict.getValue()); } //获取迁移任务类型 TaskCtg taskCtg = taskCtgService.getOne(new LambdaQueryWrapper() .eq(TaskCtg::getFlag, String.valueOf(TaskCtgType.MOVE)) .eq(TaskCtg::getStatus, 1)); if (taskCtg == null) { return; } List list = deviceService.list(new LambdaQueryWrapper() .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; } if (!shuttleThread.isCharging()) { continue; } if (!shuttleThread.isChargingCompleted()) { continue; } //查找充电任务 Task chargeTask = taskService.getOne(new LambdaQueryWrapper() .eq(Task::getTaskSts, TaskStsType.CHARGE_WORKING.sts) .eq(Task::getShuttleNo, device.getDeviceNo())); if (chargeTask == null) { continue; } //充电完成 // 已有迁移任务 if (taskService.selectMoveWorking(Integer.valueOf(device.getDeviceNo())) != null) { continue; } //获取避让位置 String standByLocNo = shuttleDispatcher.searchStandByLocNo(Integer.valueOf(device.getDeviceNo()), device.getHostId(), shuttleThread.getStatus().getCurrentLocNo()); Task task = new Task(); task.setUuid(String.valueOf(snowflakeIdWorker.nextId())); task.setTaskNo(String.valueOf(Utils.getTaskNo("MOVE"))); task.setTaskSts(TaskStsType.NEW_MOVE.sts); task.setTaskCtg(taskCtg.getId()); task.setPriority(10); task.setOriginSite(null); task.setOriginLoc(null); task.setDestSite(null); task.setDestLoc(standByLocNo); // 避让位置 task.setIoTime(new Date()); task.setStartTime(new Date()); task.setHostId(device.getHostId()); task.setStatus(1); task.setMemo("charge"); task.setShuttleNo(Integer.valueOf(device.getDeviceNo())); // generate motion list List motionList = analyzeService.generateShuttleChargeWrkComplete(task); if (Cools.isEmpty(motionList)) { News.error("保存{}号四向穿梭车迁移任务失败!!!", device.getDeviceNo()); continue; } motionService.batchInsert(motionList, task.getUuid(), Integer.valueOf(task.getTaskNo()), task.getHostId()); task.setTaskSts(TaskStsType.ANALYZE_MOVE.sts); if (!taskService.save(task)) { News.error("保存{}号四向穿梭车迁移任务失败!!!", device.getDeviceNo()); continue; } chargeTask.setTaskSts(TaskStsType.COMPLETE_CHARGE.sts); chargeTask.setIoTime(new Date()); taskService.updateById(chargeTask); } } /** * 出库 ===>> 工作档信息写入led显示器 */ public void ledExecute() { // 遍历LED List list = deviceService.list(new LambdaQueryWrapper() .eq(Device::getDeviceType, DeviceCtgType.LED.val()) .eq(Device::getStatus, 1)); for (Device ledDevice : list) { //获取led数据 BasLed led = basLedService.getOne(new LambdaQueryWrapper() .eq(BasLed::getDeviceId, ledDevice.getId())); List staArr = JSON.parseArray(led.getSta(), Integer.class); BasConveyor basConveyor = basConveyorService.getById(led.getConveyorId().intValue()); if (basConveyor == null) { continue; } // 获取输送线plc线程 DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Conveyor, basConveyor.getDeviceId().intValue()); // 命令集合 List commands = new ArrayList<>(); // 工作档集合 List tasks = new ArrayList<>(); for (Integer staNo : staArr) { // 获取叉车站点 StaProtocol staProtocol = devpThread.getStation().get(staNo); if (null == staProtocol || null == staProtocol.getWorkNo() || 0 == staProtocol.getWorkNo() || !staProtocol.isLoading()) { continue; } else { staProtocol = staProtocol.clone(); } // 获取工作档数据 Task task = taskService.getOne(new LambdaQueryWrapper().eq(Task::getTaskNo, staProtocol.getWorkNo())); if (null == task) { continue; } tasks.add(task); // 组装命令 LedCommand ledCommand = new LedCommand(); ledCommand.setWorkNo(task.getTaskNo()); ledCommand.setIoType(task.getTaskCtg().intValue()); ledCommand.setTitle(task.getTaskCtg$()); ledCommand.setSourceLocNo(task.getOriginLoc()); ledCommand.setLocNo(task.getDestLoc()); ledCommand.setStaNo(Integer.parseInt(task.getDestSite())); try { //获取WMS地址 Dict dict = dictService.getOne(new LambdaQueryWrapper().eq(Dict::getFlag, "WMS_URL").eq(Dict::getStatus, 1)); if (dict != null) { String wmsUrl = dict.getValue(); HashMap param = new HashMap<>(); param.put("taskNo", task.getTaskNo()); String response = new HttpHandler.Builder() .setUri(wmsUrl) .setPath("/queryTask") .setJson(JSON.toJSONString(param)) .build() .doPost(); JSONObject jsonObject = JSON.parseObject(response); Integer code = jsonObject.getInteger("code"); if (code.equals(200)) { List matDtos = JSON.parseArray(jsonObject.getString("data"), MatDto.class); ledCommand.setMatDtos(matDtos); } } } catch (Exception e) { e.printStackTrace(); } commands.add(ledCommand); } // 获取LED线程 LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, ledDevice.getId().intValue()); // 命令下发 ------------------------------------------------------------------------------- if (!commands.isEmpty()) { ledThread.write(commands); ledThread.setLedMk(false); } } } /** * 其他 ===>> LED显示器复位,显示默认信息 */ public void ledReset() { // 根据输送线plc遍历 List list = deviceService.list(new LambdaQueryWrapper() .eq(Device::getDeviceType, DeviceCtgType.LED.val()) .eq(Device::getStatus, 1)); for (Device ledDevice : list) { //获取led数据 BasLed led = basLedService.getOne(new LambdaQueryWrapper() .eq(BasLed::getDeviceId, ledDevice.getId())); List staArr = JSON.parseArray(led.getSta(), Integer.class); BasConveyor basConveyor = basConveyorService.getById(led.getConveyorId().intValue()); if (basConveyor == null) { continue; } // 获取输送线plc线程 DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Conveyor, basConveyor.getDeviceId().intValue()); // 命令集合 boolean reset = true; for (Integer staNo : staArr) { // 获取叉车站点 StaProtocol staProtocol = devpThread.getStation().get(staNo); if (staProtocol == null) { continue; } if (staProtocol.getWorkNo() != 0 && staProtocol.isLoading()) { reset = false; break; } } // 获取led线程 LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, ledDevice.getId().intValue()); // led显示默认内容 if (reset && !ledThread.isLedMk()) { ledThread.errorReset(); ledThread.setLedMk(true); } } for (Device ledDevice : list) { //获取led数据 BasLed led = basLedService.getOne(new LambdaQueryWrapper() .eq(BasLed::getDeviceId, ledDevice.getId())); List staArr = JSON.parseArray(led.getSta(), Integer.class); BasConveyor basConveyor = basConveyorService.getById(led.getConveyorId()); if (basConveyor == null) { continue; } // 获取输送线plc线程 DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Conveyor, basConveyor.getDeviceId().intValue()); // 命令集合 boolean reset = true; for (Integer staNo : staArr) { // 获取叉车站点 StaProtocol staProtocol = devpThread.getStation().get(staNo); if (staProtocol == null) { continue; } if (staProtocol.getWorkNo() != 0) { reset = false; break; } } // 获取led线程 LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, ledDevice.getId().intValue()); // led显示默认内容 if (reset && !ledThread.isLedMk()) { ledThread.reset(); ledThread.setLedMk(true); } } } }