src/main/java/com/zy/asrs/controller/BasStationOptController.java
@@ -43,6 +43,7 @@ convert(param, wrapper); allLike(BasStationOpt.class, param.keySet(), wrapper, condition); if (!Cools.isEmpty(orderByField)){wrapper.orderBy(humpToLine(orderByField), "asc".equals(orderByType));} wrapper.orderBy("send_time", false); return R.ok(basStationOptService.selectPage(new Page<>(curr, limit), wrapper)); } src/main/java/com/zy/asrs/controller/ConsoleController.java
@@ -116,6 +116,7 @@ vo.setEmptyMk(stationProtocol.isEmptyMk()); // 是否空板 vo.setFullPlt(stationProtocol.isFullPlt()); // 是否满板 vo.setRunBlock(stationProtocol.isRunBlock());// 运行堵塞 vo.setEnableIn(stationProtocol.isEnableIn());// 启动入库 vo.setPalletHeight(stationProtocol.getPalletHeight()); // 托盘高度 vo.setError(stationProtocol.getError()); // 错误码 vo.setBarcode(stationProtocol.getBarcode()); // 条码 src/main/java/com/zy/asrs/controller/StationController.java
@@ -1,10 +1,9 @@ package com.zy.asrs.controller; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.zy.asrs.entity.BasDevp; import com.zy.asrs.service.BasDevpService; import com.zy.core.enums.StationCommandType; import com.zy.core.model.StationObjModel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; @@ -68,7 +67,7 @@ return R.error("线程不存在"); } StationCommand command = stationThread.getMoveCommand(taskNo, stationId, targetStationId, 0); StationCommand command = stationThread.getCommand(StationCommandType.MOVE, taskNo, stationId, targetStationId, 0); MessageQueue.offer(SlaveType.Devp, devpNo, new Task(2, command)); return R.ok(); } src/main/java/com/zy/asrs/domain/vo/StationLatestDataVo.java
@@ -35,6 +35,9 @@ // 运行阻塞 private boolean runBlock; // 启动入库 private boolean enableIn; // 托盘高度 private Integer palletHeight; src/main/java/com/zy/core/ServerBootstrap.java
@@ -11,6 +11,7 @@ import com.zy.core.thread.impl.ZySiemensCrnThread; import com.zy.core.thread.impl.ZySiemensDualCrnThread; import com.zy.core.thread.impl.ZyStationThread; import com.zy.core.thread.impl.ZyStationV3Thread; import com.zy.core.thread.impl.ZyRgvThread; import lombok.extern.slf4j.Slf4j; @@ -134,6 +135,8 @@ ThreadHandler thread = null; if (deviceConfig.getThreadImpl().equals("ZyStationThread")) { thread = new ZyStationThread(deviceConfig, redisUtil); } else if (deviceConfig.getThreadImpl().equals("ZyStationV3Thread")) { thread = new ZyStationV3Thread(deviceConfig, redisUtil); } else { throw new CoolException("未知的线程实现"); } src/main/java/com/zy/core/enums/StationCommandType.java
New file @@ -0,0 +1,18 @@ package com.zy.core.enums; import lombok.Getter; @Getter public enum StationCommandType { MOVE("MOVE", "移动"), WRITE_INFO("WRITE_INFO", "信息写入"), RESET("RESET", "复位"); private final String code; private final String desc; StationCommandType(String code, String desc) { this.code = code; this.desc = desc; } } src/main/java/com/zy/core/model/command/StationCommand.java
@@ -1,6 +1,9 @@ package com.zy.core.model.command; import lombok.Data; import java.util.List; import com.zy.core.enums.StationCommandType; @Data public class StationCommand { @@ -14,4 +17,8 @@ // 托盘大小,如无特殊情况,默认0 private Integer palletSize; private List<Integer> navigatePath; private StationCommandType commandType; } src/main/java/com/zy/core/model/protocol/StationProtocol.java
@@ -40,6 +40,9 @@ // 运行阻塞 private boolean runBlock; // 启动入库 private boolean enableIn; // 托盘高度 private Integer palletHeight; src/main/java/com/zy/core/network/ZyStationConnectDriver.java
@@ -9,7 +9,9 @@ import com.zy.core.network.entity.ZyStationStatusEntity; import java.util.List; import com.zy.core.network.fake.ZyStationFakeConnect; import com.zy.core.network.fake.ZyStationFakeSegConnect; import com.zy.core.network.real.ZyStationRealConnect; import com.zy.core.network.real.ZyStationV3RealConnect; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -23,6 +25,7 @@ public class ZyStationConnectDriver implements ThreadHandler { private static final ZyStationFakeConnect zyStationFakeConnect = new ZyStationFakeConnect(); private static final ZyStationFakeSegConnect zyStationFakeSegConnect = new ZyStationFakeSegConnect(); private boolean connected = false; private DeviceConfig deviceConfig; @@ -44,10 +47,19 @@ @Override public boolean connect() { if (deviceConfig.getFake() == 0) { zyStationConnectApi = new ZyStationRealConnect(deviceConfig, redisUtil); if ("ZyStationV3Thread".equals(deviceConfig.getThreadImpl())) { zyStationConnectApi = new ZyStationV3RealConnect(deviceConfig, redisUtil); } else { zyStationConnectApi = new ZyStationRealConnect(deviceConfig, redisUtil); } } else { zyStationFakeConnect.addFakeConnect(deviceConfig, redisUtil); zyStationConnectApi = zyStationFakeConnect; if ("ZyStationV3Thread".equals(deviceConfig.getThreadImpl())) { zyStationFakeSegConnect.addFakeConnect(deviceConfig, redisUtil); zyStationConnectApi = zyStationFakeSegConnect; } else { zyStationFakeConnect.addFakeConnect(deviceConfig, redisUtil); zyStationConnectApi = zyStationFakeConnect; } } boolean connect = zyStationConnectApi.connect(); src/main/java/com/zy/core/network/entity/ZyStationStatusEntity.java
@@ -50,6 +50,9 @@ //运行堵塞 private boolean runBlock = false; //启动入库 private boolean enableIn = false; @Override public ZyStationStatusEntity clone() { try { src/main/java/com/zy/core/network/fake/ZyStationFakeConnect.java
@@ -11,6 +11,7 @@ import com.zy.common.utils.RedisUtil; import com.zy.core.News; import com.zy.core.enums.RedisKeyType; import com.zy.core.enums.StationCommandType; import com.zy.core.model.CommandResponse; import com.zy.core.model.command.StationCommand; import com.zy.core.network.api.ZyStationConnectApi; @@ -116,24 +117,29 @@ Integer taskNo = command.getTaskNo(); Integer stationId = command.getStationId(); Integer targetStationId = command.getTargetStaNo(); StationCommandType commandType = command.getCommandType(); boolean generateBarcode = false; if(taskNo == 0 && targetStationId == 0){ //清空站点 resetStation(deviceNo, stationId); return; if(commandType == StationCommandType.RESET){ if(taskNo == 0 && targetStationId == 0){ //清空站点 resetStation(deviceNo, stationId); return; } } if(commandType == StationCommandType.WRITE_INFO){ if (taskNo == 9998 && targetStationId == 0) { //生成出库站点仿真数据 generateFakeOutStationData(deviceNo, stationId); return; } } //任务号属于仿真入库任务号 if (checkTaskNoInArea(taskNo)) { //生成仿真数据 generateBarcode = true; } if (taskNo == 9998 && targetStationId == 0) { //生成出库站点仿真数据 generateFakeOutStationData(deviceNo, stationId); return; } if (taskNo > 0 && taskNo != 9999 && taskNo != 9998 && stationId == targetStationId) { src/main/java/com/zy/core/network/fake/ZyStationFakeSegConnect.java
New file @@ -0,0 +1,733 @@ package com.zy.core.network.fake; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.zy.asrs.entity.DeviceConfig; import com.zy.common.model.NavigateNode; import com.zy.common.utils.RedisUtil; import com.zy.core.News; import com.zy.core.enums.RedisKeyType; import com.zy.core.enums.StationCommandType; import com.zy.core.model.CommandResponse; import com.zy.core.model.command.StationCommand; import com.zy.core.network.api.ZyStationConnectApi; import com.zy.core.network.entity.ZyStationStatusEntity; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Random; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.Map; import java.util.function.Supplier; public class ZyStationFakeSegConnect implements ZyStationConnectApi { private static int LOCK_STATION = 0; private HashMap<Integer, List<ZyStationStatusEntity>> deviceStatusMap = new HashMap<>(); private HashMap<Integer, DeviceConfig> deviceConfigMap = new HashMap<>(); private RedisUtil redisUtil; private final Map<Integer, BlockingQueue<StationCommand>> taskQueues = new ConcurrentHashMap<>(); private final Map<Integer, Long> taskLastUpdateTime = new ConcurrentHashMap<>(); private final Map<Integer, Boolean> taskRunning = new ConcurrentHashMap<>(); private final ExecutorService executor = Executors.newCachedThreadPool(); public void addFakeConnect(DeviceConfig deviceConfig, RedisUtil redisUtil) { this.redisUtil = redisUtil; if (deviceConfigMap.containsKey(deviceConfig.getDeviceNo())) { return; } deviceConfigMap.put(deviceConfig.getDeviceNo(), deviceConfig); deviceStatusMap.put(deviceConfig.getDeviceNo(), new CopyOnWriteArrayList<>()); } @Override public boolean connect() { return true; } @Override public boolean disconnect() { executor.shutdownNow(); return true; } @Override public List<ZyStationStatusEntity> getStatus(Integer deviceNo) { List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo); if (statusList == null) { return new ArrayList<>(); } DeviceConfig deviceConfig = deviceConfigMap.get(deviceNo); if (statusList.isEmpty()) { List<ZyStationStatusEntity> init = JSON.parseArray(deviceConfig.getFakeInitStatus(), ZyStationStatusEntity.class); if (init != null) { statusList.addAll(init); for (ZyStationStatusEntity status : statusList) { status.setAutoing(true); status.setLoading(false); status.setInEnable(true); status.setOutEnable(true); status.setEmptyMk(false); status.setFullPlt(false); status.setRunBlock(false); status.setPalletHeight(0); status.setError(0); status.setBarcode(""); } } } return statusList; } @Override public CommandResponse sendCommand(Integer deviceNo, StationCommand command) { Integer taskNo = command.getTaskNo(); if (taskNo == null) { return new CommandResponse(false, "任务号为空"); } taskQueues.computeIfAbsent(taskNo, k -> new LinkedBlockingQueue<>()).offer(command); taskLastUpdateTime.put(taskNo, System.currentTimeMillis()); if (taskRunning.putIfAbsent(taskNo, true) == null) { executor.submit(() -> runTaskLoop(deviceNo, taskNo)); } return new CommandResponse(true, "命令已受理(异步执行)"); } private void runTaskLoop(Integer deviceNo, Integer taskNo) { try { // 用于存储当前任务待执行的完整路径队列 BlockingQueue<Integer> pathQueue = new LinkedBlockingQueue<>(); // 当前是否正在执行移动 boolean isMoving = false; // 当前移动到的路径索引 int currentPathIndex = 0; // 完整路径记录 List<Integer> fullPath = new ArrayList<>(); StationCommand initialCommand = null; Integer finalTargetStationId = null; boolean generateBarcode = false; while (true) { BlockingQueue<StationCommand> commandQueue = taskQueues.get(taskNo); if (commandQueue == null) { break; } // 尝试获取新命令,如果没有新命令则继续执行现有路径 StationCommand command = commandQueue.poll(100, TimeUnit.MILLISECONDS); if (command != null) { taskLastUpdateTime.put(taskNo, System.currentTimeMillis()); if (initialCommand == null) { initialCommand = command; finalTargetStationId = command.getTargetStaNo(); if (checkTaskNoInArea(taskNo)) { generateBarcode = true; } } List<Integer> newPath = command.getNavigatePath(); if (newPath != null && !newPath.isEmpty()) { // 如果是第一段路径 if (fullPath.isEmpty()) { fullPath.addAll(newPath); for (Integer stationId : newPath) { pathQueue.offer(stationId); } } else { // 追加路径,需要去重衔接点 Integer lastStationId = fullPath.get(fullPath.size() - 1); int startIndex = 0; if (!newPath.isEmpty() && newPath.get(0).equals(lastStationId)) { startIndex = 1; } for (int i = startIndex; i < newPath.size(); i++) { Integer stationId = newPath.get(i); fullPath.add(stationId); pathQueue.offer(stationId); } } } // 处理非移动命令 if (command.getCommandType() != StationCommandType.MOVE) { handleCommand(deviceNo, command); } } // 执行移动逻辑 if (!pathQueue.isEmpty()) { // 如果刚开始,先初始化当前位置 if (currentPathIndex == 0 && !fullPath.isEmpty()) { Integer startStationId = fullPath.get(0); Integer deviceId = getDeviceNoByStationId(startStationId); if (deviceId != null) { initStationMove(taskNo, startStationId, deviceId, taskNo, finalTargetStationId, true, null); } } // 取出下一个目标点 Integer nextStationId = pathQueue.peek(); // 这里的逻辑需要改为逐个行走 // 实际行走逻辑应该是在这里消费 pathQueue // 为了简化,我们将 pathQueue 转为 stationMoveByPathIds 的逻辑,但这里需要改造成步进式 // 重新设计:runTaskLoop 负责不断消费 pathQueue 并执行单步移动 if (nextStationId != null) { Integer currentStationId = fullPath.get(currentPathIndex); if (currentStationId.equals(nextStationId)) { pathQueue.poll(); // 移除已到达的点 continue; } // 执行从 currentStationId 到 nextStationId 的移动 Integer currentDeviceNo = getDeviceNoByStationId(currentStationId); Integer nextDeviceNo = getDeviceNoByStationId(nextStationId); if (currentDeviceNo != null && nextDeviceNo != null) { boolean moveSuccess = stationMoveToNext(taskNo, currentStationId, currentDeviceNo, nextStationId, nextDeviceNo, taskNo, finalTargetStationId); if (moveSuccess) { currentPathIndex++; pathQueue.poll(); sleep(1000); // 模拟耗时 } else { sleep(1000); // 失败重试等待 } } else { pathQueue.poll(); // 无法执行,跳过 } } } else { // 队列为空,检查是否超时 Long lastTime = taskLastUpdateTime.get(taskNo); if (lastTime != null && System.currentTimeMillis() - lastTime > 30000) { // 完成任务后清理 if (fullPath.size() > 0 && generateBarcode) { Integer lastStation = fullPath.get(fullPath.size()-1); Integer lastDevice = getDeviceNoByStationId(lastStation); if (lastDevice != null) { generateStationBarcode(taskNo, finalTargetStationId, lastDevice); } } break; } } } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { taskQueues.remove(taskNo); taskLastUpdateTime.remove(taskNo); taskRunning.remove(taskNo); } } @Override public CommandResponse sendOriginCommand(String address, short[] data) { return new CommandResponse(true, "原始命令已受理(异步执行)"); } @Override public byte[] readOriginCommand(String address, int length) { return new byte[0]; } private void handleCommand(Integer deviceNo, StationCommand command) { News.info("[WCS Debug] 站点仿真模拟(V3)已启动,命令数据={}", JSON.toJSONString(command)); Integer taskNo = command.getTaskNo(); Integer stationId = command.getStationId(); Integer targetStationId = command.getTargetStaNo(); boolean generateBarcode = false; if (command.getCommandType() == StationCommandType.RESET) { resetStation(deviceNo, stationId); return; } if (checkTaskNoInArea(taskNo)) { generateBarcode = true; } if (command.getCommandType() == StationCommandType.WRITE_INFO) { if (taskNo == 9998 && targetStationId == 0) { //生成出库站点仿真数据 generateFakeOutStationData(deviceNo, stationId); return; } } if (taskNo > 0 && taskNo != 9999 && taskNo != 9998 && stationId == targetStationId) { generateStationData(deviceNo, taskNo, stationId, targetStationId); } List<Integer> navigatePath = command.getNavigatePath(); if (navigatePath != null && !navigatePath.isEmpty()) { segmentedPathCommand(command, generateBarcode); return; } } private void generateFakeOutStationData(Integer deviceNo, Integer stationId) { List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo); ZyStationStatusEntity status = statusList.stream() .filter(item -> item.getStationId().equals(stationId)).findFirst().orElse(null); if (status == null) { return; } synchronized (status) { status.setLoading(true); } } private void generateStationData(Integer deviceNo, Integer taskNo, Integer stationId, Integer targetStationId) { List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo); ZyStationStatusEntity status = statusList.stream() .filter(item -> item.getStationId().equals(stationId)).findFirst().orElse(null); if (status == null) { return; } synchronized (status) { status.setTaskNo(taskNo); status.setTargetStaNo(targetStationId); } } private void resetStation(Integer deviceNo, Integer stationId) { List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo); ZyStationStatusEntity status = statusList.stream() .filter(item -> item.getStationId().equals(stationId)).findFirst().orElse(null); if (status == null) { return; } synchronized (status) { status.setTaskNo(0); status.setLoading(false); status.setBarcode(""); } } private void segmentedPathCommand(StationCommand command, boolean generateBarcode) { Integer taskNo = command.getTaskNo(); Integer finalTargetStationId = command.getTargetStaNo(); List<Integer> path = command.getNavigatePath(); if (path == null || path.isEmpty()) { return; } Integer currentStationId = findCurrentStationIdByTask(taskNo); int startIdx = 0; if (currentStationId != null) { int idx = path.indexOf(currentStationId); if (idx >= 0) { startIdx = idx; } } Integer segmentTargetStationId = path.get(path.size() - 1); int endIdx = path.size() - 1; boolean isFinalSegment = segmentTargetStationId.equals(finalTargetStationId); boolean appendMode = currentStationId != null && path.indexOf(currentStationId) >= 0; boolean generateBarcodeFinal = generateBarcode && isFinalSegment; stationMoveByPathIds(path, taskNo, finalTargetStationId, false, generateBarcodeFinal, startIdx, endIdx, appendMode); } private Integer getDeviceNoByStationId(Integer stationId) { for (Integer devNo : deviceStatusMap.keySet()) { List<ZyStationStatusEntity> list = deviceStatusMap.get(devNo); if (list == null) { continue; } for (ZyStationStatusEntity e : list) { if (e.getStationId() != null && e.getStationId().equals(stationId)) { return devNo; } } } return null; } private Integer findCurrentStationIdByTask(Integer taskNo) { for (Integer devNo : deviceStatusMap.keySet()) { List<ZyStationStatusEntity> list = deviceStatusMap.get(devNo); if (list == null) { continue; } for (ZyStationStatusEntity e : list) { if (e.getTaskNo() != null && e.getTaskNo().equals(taskNo) && e.isLoading()) { return e.getStationId(); } } } return null; } private boolean stationMoveByPathIds(List<Integer> stationPath, Integer taskNo, Integer targetStationId, boolean clearData, boolean generateBarcode, int startIdx, int endIdx, boolean appendMode) { Integer lastStationId = null; Integer targetStationDeviceNo = getDeviceNoByStationId(targetStationId); long executeTime = System.currentTimeMillis(); int i = Math.max(0, startIdx); while (i < stationPath.size() && i <= endIdx) { if (Thread.currentThread().isInterrupted()) { return false; } Integer currentStationId = stationPath.get(i); Integer currentStationDeviceNo = getDeviceNoByStationId(currentStationId); if (currentStationDeviceNo == null) { return false; } Integer nextStationId = null; Integer nextStationDeviceNo = null; try { nextStationId = stationPath.get(i + 1); nextStationDeviceNo = getDeviceNoByStationId(nextStationId); } catch (Exception ignore) {} if (!checkTaskNoInArea(taskNo)) { boolean fakeAllowCheckBlock = true; Object systemConfigMapObj = redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key); if (systemConfigMapObj != null) { HashMap<String, String> systemConfigMap = (HashMap<String, String>) systemConfigMapObj; if (!systemConfigMap.get("fakeAllowCheckBlock").equals("Y")) { fakeAllowCheckBlock = false; } } if (fakeAllowCheckBlock && System.currentTimeMillis() - executeTime > 1000 * 10) { boolean result = runBlockStation(taskNo, currentStationId, currentStationDeviceNo, taskNo, currentStationId); if(!result) { continue; } return false; } } if (i == startIdx && !appendMode) { boolean result = initStationMove(taskNo, currentStationId, currentStationDeviceNo, taskNo, targetStationId, true, null); if (!result) { continue; } sleep(1000); if (Thread.currentThread().isInterrupted()) { return false; } } if (nextStationId != null && nextStationDeviceNo != null) { boolean result = stationMoveToNext(taskNo, currentStationId, currentStationDeviceNo, nextStationId, nextStationDeviceNo, taskNo, targetStationId); if (!result) { continue; } lastStationId = currentStationId; } if (currentStationId.equals(targetStationId)) { break; } i++; executeTime = System.currentTimeMillis(); sleep(1000); if (Thread.currentThread().isInterrupted()) { return false; } } if (generateBarcode) { if (lastStationId != null && targetStationDeviceNo != null) { while (true) { if (Thread.currentThread().isInterrupted()) { break; } boolean result = generateStationBarcode(taskNo, targetStationId, targetStationDeviceNo); sleep(1000); if (!result) { continue; } break; } } } if (clearData) { sleep(10000); if (Thread.currentThread().isInterrupted()) { return true; } if (lastStationId != null && targetStationDeviceNo != null) { while (true) { if (Thread.currentThread().isInterrupted()) { break; } boolean result = clearStation(targetStationDeviceNo, taskNo, targetStationId); sleep(1000); if (!result) { continue; } break; } } } return true; } private void sleep(long ms) { try { Thread.sleep(ms); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } public synchronized boolean setLockStation(Integer uuid) { if (LOCK_STATION == 0) { LOCK_STATION = uuid; return true; }else { if(LOCK_STATION == uuid) { return true; } } return false; } public synchronized boolean releaseLockStation(Integer uuid) { if (LOCK_STATION != uuid) { return false; } LOCK_STATION = 0; return true; } public synchronized boolean updateStationData(Integer lockTaskNo, Integer stationId, Integer deviceNo, Integer taskNo, Integer targetStaNo, Boolean isLoading, String barcode, Boolean runBlock) { if (LOCK_STATION != lockTaskNo) { return false; } List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo); if (statusList == null) { return false; } ZyStationStatusEntity currentStatus = statusList.stream() .filter(item -> item.getStationId().equals(stationId)).findFirst().orElse(null); if (currentStatus == null) { return false; } if (taskNo != null) { currentStatus.setTaskNo(taskNo); } if (targetStaNo != null) { currentStatus.setTargetStaNo(targetStaNo); } if (isLoading != null) { currentStatus.setLoading(isLoading); } if (barcode != null) { currentStatus.setBarcode(barcode); } if (runBlock != null) { currentStatus.setRunBlock(runBlock); } return true; } public synchronized boolean initStationMove(Integer lockTaskNo, Integer currentStationId, Integer currentStationDeviceNo, Integer taskNo, Integer targetStationId, Boolean isLoading, String barcode) { boolean executeResult = lockExecute(lockTaskNo, () -> { List<ZyStationStatusEntity> statusList = deviceStatusMap.get(currentStationDeviceNo); if (statusList == null) { return false; } ZyStationStatusEntity currentStatus = statusList.stream() .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null); if (currentStatus == null) { return false; } if (currentStatus.getTaskNo() > 0) { if (!currentStatus.getTaskNo().equals(taskNo) && currentStatus.isLoading()) { return false; } } boolean result = updateStationData(lockTaskNo, currentStationId, currentStationDeviceNo, taskNo, targetStationId, isLoading, barcode, false); if (!result) { return false; } return true; }); return executeResult; } public synchronized boolean stationMoveToNext(Integer lockTaskNo, Integer currentStationId, Integer currentStationDeviceNo, Integer nextStationId, Integer nextStationDeviceNo, Integer taskNo, Integer targetStaNo) { boolean executeResult = lockExecute(lockTaskNo, () -> { List<ZyStationStatusEntity> statusList = deviceStatusMap.get(currentStationDeviceNo); if (statusList == null) { return false; } List<ZyStationStatusEntity> nextStatusList = deviceStatusMap.get(nextStationDeviceNo); if (statusList == null) { return false; } ZyStationStatusEntity currentStatus = statusList.stream() .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null); ZyStationStatusEntity nextStatus = nextStatusList.stream() .filter(item -> item.getStationId().equals(nextStationId)).findFirst().orElse(null); if (currentStatus == null || nextStatus == null) { return false; } if (nextStatus.getTaskNo() > 0 || nextStatus.isLoading()) { return false; } boolean result = updateStationData(lockTaskNo, nextStationId, nextStationDeviceNo, taskNo, targetStaNo, true, null, false); if (!result) { return false; } boolean result2 = updateStationData(lockTaskNo, currentStationId, currentStationDeviceNo, 0, 0, false, "", false); if (!result2) { return false; } return true; }); return executeResult; } public synchronized boolean generateStationBarcode(Integer lockTaskNo, Integer currentStationId, Integer currentStationDeviceNo) { boolean executeResult = lockExecute(lockTaskNo, () -> { List<ZyStationStatusEntity> statusList = deviceStatusMap.get(currentStationDeviceNo); if (statusList == null) { return false; } ZyStationStatusEntity currentStatus = statusList.stream() .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null); if (currentStatus == null) { return false; } Random random = new Random(); String barcodeTime = String.valueOf(System.currentTimeMillis()); String barcode = String.valueOf(random.nextInt(10)) + String.valueOf(random.nextInt(10)) + barcodeTime.substring(7); boolean result = updateStationData(lockTaskNo, currentStationId, currentStationDeviceNo, null, null, null, barcode, null); if (!result) { return false; } return true; }); return executeResult; } public synchronized boolean clearStation(Integer deviceNo, Integer lockTaskNo, Integer currentStationId) { boolean executeResult = lockExecute(lockTaskNo, () -> { List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo); if (statusList == null) { return false; } ZyStationStatusEntity currentStatus = statusList.stream() .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null); if (currentStatus == null) { return false; } boolean result = updateStationData(deviceNo, lockTaskNo, currentStationId, 0, 0, false, "", false); if (!result) { return false; } return true; }); return executeResult; } public synchronized boolean runBlockStation(Integer lockTaskNo, Integer currentStationId, Integer currentStationDeviceNo, Integer taskNo, Integer blockStationId) { boolean executeResult = lockExecute(lockTaskNo, () -> { List<ZyStationStatusEntity> statusList = deviceStatusMap.get(currentStationDeviceNo); if (statusList == null) { return false; } ZyStationStatusEntity currentStatus = statusList.stream() .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null); if (currentStatus == null) { return false; } boolean result = updateStationData(lockTaskNo, currentStationId, currentStationDeviceNo, taskNo, blockStationId, true, "", true); if (!result) { return false; } return true; }); return executeResult; } public boolean lockExecute(Integer taskNo, Supplier<Boolean> function) { if (!setLockStation(taskNo)) { return false; } boolean result = function.get(); releaseLockStation(taskNo); return result; } private boolean checkTaskNoInArea(Integer taskNo) { Object fakeTaskNoAreaObj = redisUtil.get(RedisKeyType.FAKE_TASK_NO_AREA.key); if (fakeTaskNoAreaObj == null) { return false; } JSONObject data = JSON.parseObject(String.valueOf(fakeTaskNoAreaObj)); Integer start = data.getInteger("start"); Integer end = data.getInteger("end"); if(taskNo >= start && taskNo <= end) { return true; } return false; } } src/main/java/com/zy/core/network/real/ZyStationV3RealConnect.java
New file @@ -0,0 +1,237 @@ package com.zy.core.network.real; import HslCommunication.Core.Types.OperateResult; import HslCommunication.Core.Types.OperateResultExOne; import HslCommunication.Profinet.Siemens.SiemensPLCS; import HslCommunication.Profinet.Siemens.SiemensS7Net; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.core.common.DateUtils; import com.core.common.SpringUtils; import com.zy.asrs.entity.BasDevp; import com.zy.asrs.entity.DeviceConfig; import com.zy.asrs.service.BasDevpService; import com.zy.common.utils.RedisUtil; import com.zy.core.News; import com.zy.core.cache.OutputQueue; import com.zy.core.enums.StationCommandType; import com.zy.core.model.CommandResponse; import com.zy.core.model.command.StationCommand; import com.zy.core.network.api.ZyStationConnectApi; import com.zy.core.network.entity.ZyStationStatusEntity; import lombok.extern.slf4j.Slf4j; import java.text.MessageFormat; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; /** * 输送站真实连接(PLC) */ @Slf4j public class ZyStationV3RealConnect implements ZyStationConnectApi { private List<ZyStationStatusEntity> statusList; private List<ZyStationStatusEntity> barcodeStatusList; private SiemensS7Net siemensNet; private DeviceConfig deviceConfig; private RedisUtil redisUtil; private final static int taskAddressLength = 48; private final static int taskAddressLimit = 50; public ZyStationV3RealConnect(DeviceConfig deviceConfig, RedisUtil redisUtil) { this.deviceConfig = deviceConfig; this.redisUtil = redisUtil; } @Override public boolean connect() { boolean connected = false; siemensNet = new SiemensS7Net(SiemensPLCS.S1200, deviceConfig.getIp()); OperateResult connect = siemensNet.ConnectServer(); if (connect.IsSuccess) { connected = true; OutputQueue.DEVP.offer(MessageFormat.format("【{0}】输送站plc连接成功 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), deviceConfig.getDeviceNo(), deviceConfig.getIp(), deviceConfig.getPort())); News.info("输送站plc连接成功 ===>> [id:{}] [ip:{}] [port:{}]", deviceConfig.getDeviceNo(), deviceConfig.getIp(), deviceConfig.getPort()); } else { OutputQueue.DEVP.offer(MessageFormat.format("【{0}】输送站plc连接失败!!! ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), deviceConfig.getDeviceNo(), deviceConfig.getIp(), deviceConfig.getPort())); News.error("输送站plc连接失败!!! ===>> [id:{}] [ip:{}] [port:{}]", deviceConfig.getDeviceNo(), deviceConfig.getIp(), deviceConfig.getPort()); } return connected; } @Override public boolean disconnect() { siemensNet.ConnectClose(); return true; } @Override public List<ZyStationStatusEntity> getStatus(Integer deviceNo) { if (statusList == null) { BasDevpService basDevpService = SpringUtils.getBean(BasDevpService.class); if (basDevpService == null) { return Collections.emptyList(); } BasDevp basDevp = basDevpService .selectOne(new EntityWrapper<BasDevp>().eq("devp_no", deviceConfig.getDeviceNo())); if (basDevp == null) { return Collections.emptyList(); } statusList = JSONObject.parseArray(basDevp.getStationList(), ZyStationStatusEntity.class); if (statusList != null) { statusList.sort(Comparator.comparing(ZyStationStatusEntity::getStationId)); } barcodeStatusList = JSONObject.parseArray(basDevp.getBarcodeStationList(), ZyStationStatusEntity.class); if (barcodeStatusList != null) { barcodeStatusList.sort(Comparator.comparing(ZyStationStatusEntity::getStationId)); } } OperateResultExOne<byte[]> result = siemensNet.Read("DB100.0", (short) (statusList.size() * 8)); if (result.IsSuccess) { for (int i = 0; i < statusList.size(); i++) { ZyStationStatusEntity statusEntity = statusList.get(i); // 站点编号 statusEntity.setTaskNo(siemensNet.getByteTransform().TransInt32(result.Content, i * 8)); // 工作号 statusEntity.setTargetStaNo((int) siemensNet.getByteTransform().TransInt16(result.Content, i * 8 + 4)); // 目标站 boolean[] status = siemensNet.getByteTransform().TransBool(result.Content, i * 8 + 6, 1); statusEntity.setAutoing(status[0]); // 自动 statusEntity.setLoading(status[1]); // 有物 statusEntity.setInEnable(status[2]); // 可入 statusEntity.setOutEnable(status[3]);// 可出 statusEntity.setEmptyMk(status[4]); // 空托盘 statusEntity.setFullPlt(status[5]); // 满托盘 boolean[] status2 = siemensNet.getByteTransform().TransBool(result.Content, i * 8 + 7, 1); statusEntity.setRunBlock(status2[1]);//重新规划路线 statusEntity.setEnableIn(status2[3]);//启动入库 } } // 条码扫描器 OperateResultExOne<byte[]> result2 = siemensNet.Read("DB101.0", (short) (statusList.size() * 10)); if (result2.IsSuccess) { for (int i = 0; i < barcodeStatusList.size(); i++) { ZyStationStatusEntity barcodeEntity = barcodeStatusList.get(i); ZyStationStatusEntity statusEntity = findStatusEntity(barcodeEntity.getStationId()); if (statusEntity == null) { continue; } String barcode = siemensNet.getByteTransform().TransString(result2.Content, i * 10 + 2, 8, "UTF-8"); barcode = barcode.trim(); barcodeEntity.setBarcode(barcode); } } return statusList; } @Override public CommandResponse sendCommand(Integer deviceNo, StationCommand command) { CommandResponse commandResponse = new CommandResponse(false); if (null == command) { commandResponse.setMessage("命令为空"); return commandResponse; } if (command.getCommandType().equals(StationCommandType.MOVE)) { int enableCommandIdx = -1; while (true) { enableCommandIdx = getEnableCommandIdx(); if(enableCommandIdx == -1) { try { Thread.sleep(300); }catch (Exception e) {} }else { break; } } List<Integer> pathList = command.getNavigatePath(); short[] data = new short[22]; data[0] = command.getTargetStaNo().shortValue(); int dataIdx = 1; for (Integer path : pathList) { data[dataIdx++] = path.shortValue(); } OperateResult writeTask = siemensNet.Write("DB23." + enableCommandIdx * taskAddressLength, command.getTaskNo()); OperateResult writeData = siemensNet.Write("DB23." + enableCommandIdx * taskAddressLength + 4, data); if(writeTask.IsSuccess && writeData.IsSuccess) { log.error("写入输送线命令成功。任务号={},站点数据={}", command.getTaskNo(), JSON.toJSON(command)); commandResponse.setResult(true); }else { log.error("写入输送线命令失败。站点编号={},站点数据={}", command.getTaskNo(), JSON.toJSON(command)); commandResponse.setResult(false); } } return commandResponse; } @Override public CommandResponse sendOriginCommand(String address, short[] data) { CommandResponse commandResponse = new CommandResponse(false); if (null == data || data.length == 0) { commandResponse.setMessage("数据为空"); return commandResponse; } OperateResult write = siemensNet.Write(address, data); if (write.IsSuccess) { log.info("写入原始命令成功。地址={},数据={}", address, JSON.toJSON(data)); commandResponse.setResult(true); } else { log.error("写入原始命令失败。地址={},数据={}", address, JSON.toJSON(data)); commandResponse.setResult(false); } return commandResponse; } @Override public byte[] readOriginCommand(String address, int length) { OperateResultExOne<byte[]> result = siemensNet.Read(address, (short) length); if (result.IsSuccess) { return result.Content; } return new byte[0]; } private ZyStationStatusEntity findStatusEntity(Integer stationId) { for (ZyStationStatusEntity statusEntity : statusList) { if (statusEntity.getStationId().equals(stationId)) { return statusEntity; } } return null; } private int getEnableCommandIdx() { int useIdx = -1; for (int i = 0; i < taskAddressLimit; i++) { OperateResultExOne<byte[]> result = siemensNet.Read("DB23." + i * taskAddressLength, (short) taskAddressLength); int taskStatus = siemensNet.getByteTransform().TransInt16(result.Content, i * taskAddressLength + 46); if (taskStatus == 1) { continue; } useIdx = i; break; } return useIdx; } } src/main/java/com/zy/core/plugin/FakeProcess.java
@@ -236,7 +236,7 @@ && !stationProtocol.isLoading() && stationProtocol.getTaskNo() == 0 ) { StationCommand command = stationThread.getMoveCommand(commonService.getWorkNo(WrkIoType.FAKE_TASK_NO.id), stationId, entity.getBarcodeStation().getStationId(), 0); StationCommand command = stationThread.getCommand(StationCommandType.MOVE, commonService.getWorkNo(WrkIoType.FAKE_TASK_NO.id), stationId, entity.getBarcodeStation().getStationId(), 0); MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command)); redisUtil.set(RedisKeyType.GENERATE_FAKE_IN_STATION_DATA_LIMIT.key + stationId, "lock", 5); } @@ -325,7 +325,7 @@ taskParam.setBarcode(stationProtocol.getBarcode()); WrkMast wrkMast = commonService.createInTask(taskParam); StationCommand command = stationThread.getMoveCommand(wrkMast.getWrkNo(), stationId, stationId, 0); StationCommand command = stationThread.getCommand(StationCommandType.MOVE, wrkMast.getWrkNo(), stationId, stationId, 0); if(command == null){ News.taskInfo(wrkMast.getWrkNo(), "获取输送线命令失败"); continue; @@ -467,7 +467,7 @@ taskParam.setBarcode(stationProtocol.getBarcode()); WrkMast wrkMast = commonService.createInTask(taskParam); StationCommand command = stationThread.getMoveCommand(wrkMast.getWrkNo(), stationId, stationId, 0); StationCommand command = stationThread.getCommand(StationCommandType.WRITE_INFO, wrkMast.getWrkNo(), stationId, stationId, 0); if(command == null){ News.taskInfo(wrkMast.getWrkNo(), "获取输送线命令失败"); continue; @@ -528,7 +528,7 @@ continue; } StationCommand command = stationThread.getMoveCommand(0, stationObjModel.getStationId(), 0, 0); StationCommand command = stationThread.getCommand(StationCommandType.RESET, 0, stationObjModel.getStationId(), 0, 0); if(command == null){ continue; } @@ -576,11 +576,6 @@ continue; } StationCommand command = stationThread.getMoveCommand(0, stationObjModel.getStationId(), 0, 0); if(command == null){ continue; } Map<Integer, StationProtocol> statusMap = stationThread.getStatusMap(); StationProtocol stationProtocol = statusMap.get(stationObjModel.getStationId()); if (stationProtocol == null) { @@ -588,6 +583,11 @@ } if(stationProtocol.getTaskNo() > 0) { StationCommand command = stationThread.getCommand(StationCommandType.RESET, 0, stationObjModel.getStationId(), 0, 0); if(command == null){ continue; } WrkMast wrkMast = wrkMastService.selectByWorkNo(stationProtocol.getTaskNo()); if (wrkMast == null) { MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command)); @@ -693,7 +693,7 @@ continue; } //生成仿真站点数据 StationCommand command = stationThread.getMoveCommand(9998, wrkMast.getSourceStaNo(), 0, 0); StationCommand command = stationThread.getCommand(StationCommandType.WRITE_INFO, 9998, wrkMast.getSourceStaNo(), 0, 0); MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command)); } }else if(wrkMast.getWrkSts() == WrkStsType.LOC_MOVE_RUN.sts){ src/main/java/com/zy/core/thread/StationThread.java
@@ -1,6 +1,7 @@ package com.zy.core.thread; import com.zy.core.ThreadHandler; import com.zy.core.enums.StationCommandType; import com.zy.core.model.CommandResponse; import com.zy.core.model.command.StationCommand; import com.zy.core.model.protocol.StationProtocol; @@ -13,7 +14,7 @@ Map<Integer, StationProtocol> getStatusMap(); StationCommand getMoveCommand(Integer taskNo, Integer stationId, Integer targetStationId, Integer palletSize); StationCommand getCommand(StationCommandType commandType, Integer taskNo, Integer stationId, Integer targetStationId, Integer palletSize); CommandResponse sendCommand(StationCommand command); src/main/java/com/zy/core/thread/impl/ZyStationThread.java
@@ -20,6 +20,7 @@ import com.zy.core.cache.OutputQueue; import com.zy.core.enums.RedisKeyType; import com.zy.core.enums.SlaveType; import com.zy.core.enums.StationCommandType; import com.zy.core.model.CommandResponse; import com.zy.core.model.Task; import com.zy.core.model.command.StationCommand; @@ -179,12 +180,13 @@ } @Override public StationCommand getMoveCommand(Integer taskNo, Integer stationId, Integer targetStationId, Integer palletSize) { public StationCommand getCommand(StationCommandType commandType, Integer taskNo, Integer stationId, Integer targetStationId, Integer palletSize) { StationCommand stationCommand = new StationCommand(); stationCommand.setTaskNo(taskNo); stationCommand.setStationId(stationId); stationCommand.setTargetStaNo(targetStationId); stationCommand.setPalletSize(palletSize); stationCommand.setCommandType(commandType); return stationCommand; } src/main/java/com/zy/core/thread/impl/ZyStationV3Thread.java
New file @@ -0,0 +1,390 @@ package com.zy.core.thread.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.core.common.DateUtils; import com.core.common.SpringUtils; import com.zy.asrs.entity.BasDevp; import com.zy.asrs.entity.BasStationOpt; import com.zy.asrs.entity.DeviceConfig; import com.zy.asrs.entity.DeviceDataLog; import com.zy.asrs.service.BasDevpService; import com.zy.asrs.service.BasStationOptService; import com.zy.asrs.utils.Utils; import com.zy.common.model.NavigateNode; import com.zy.common.utils.NavigateUtils; import com.zy.common.utils.RedisUtil; import com.zy.core.cache.MessageQueue; import com.zy.core.cache.OutputQueue; import com.zy.core.cache.SlaveConnection; import com.zy.core.enums.RedisKeyType; import com.zy.core.enums.SlaveType; import com.zy.core.enums.StationCommandType; import com.zy.core.model.CommandResponse; import com.zy.core.model.Task; import com.zy.core.model.command.StationCommand; import com.zy.core.model.protocol.StationProtocol; import com.zy.core.network.DeviceConnectPool; import com.zy.core.network.ZyStationConnectDriver; import com.zy.core.network.entity.ZyStationStatusEntity; import lombok.Data; import lombok.extern.slf4j.Slf4j; import java.text.MessageFormat; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @Data @Slf4j public class ZyStationV3Thread implements Runnable, com.zy.core.thread.StationThread { private List<StationProtocol> statusList = new ArrayList<>(); private DeviceConfig deviceConfig; private RedisUtil redisUtil; private ZyStationConnectDriver zyStationConnectDriver; private int deviceLogCollectTime = 200; private long deviceDataLogTime = System.currentTimeMillis(); private ExecutorService executor = Executors.newFixedThreadPool(9999); public ZyStationV3Thread(DeviceConfig deviceConfig, RedisUtil redisUtil) { this.deviceConfig = deviceConfig; this.redisUtil = redisUtil; } @Override @SuppressWarnings("InfiniteLoopStatement") public void run() { this.connect(); deviceLogCollectTime = Utils.getDeviceLogCollectTime(); Thread readThread = new Thread(() -> { while (true) { try { deviceLogCollectTime = Utils.getDeviceLogCollectTime(); readStatus(); Thread.sleep(100); } catch (Exception e) { log.error("StationV3Thread Fail", e); } } }); readThread.start(); Thread processThread = new Thread(() -> { while (true) { try { int step = 1; Task task = MessageQueue.poll(SlaveType.Devp, deviceConfig.getDeviceNo()); if (task != null) { step = task.getStep(); } if (step == 2) { StationCommand cmd = (StationCommand) task.getData(); executor.submit(() -> executeMoveWithSeg(cmd)); } Thread.sleep(100); } catch (Exception e) { log.error("StationV3Process Fail", e); } } }); processThread.start(); } private void readStatus() { if (zyStationConnectDriver == null) { return; } if (statusList.isEmpty()) { BasDevpService basDevpService = null; try { basDevpService = SpringUtils.getBean(BasDevpService.class); } catch (Exception e) { } if (basDevpService == null) { return; } BasDevp basDevp = basDevpService .selectOne(new EntityWrapper<BasDevp>().eq("devp_no", deviceConfig.getDeviceNo())); if (basDevp == null) { return; } List<ZyStationStatusEntity> list = JSONObject.parseArray(basDevp.getStationList(), ZyStationStatusEntity.class); for (ZyStationStatusEntity entity : list) { StationProtocol stationProtocol = new StationProtocol(); stationProtocol.setStationId(entity.getStationId()); statusList.add(stationProtocol); } } List<ZyStationStatusEntity> zyStationStatusEntities = zyStationConnectDriver.getStatus(); for (ZyStationStatusEntity statusEntity : zyStationStatusEntities) { for (StationProtocol stationProtocol : statusList) { if (stationProtocol.getStationId().equals(statusEntity.getStationId())) { stationProtocol.setTaskNo(statusEntity.getTaskNo()); stationProtocol.setTargetStaNo(statusEntity.getTargetStaNo()); stationProtocol.setAutoing(statusEntity.isAutoing()); stationProtocol.setLoading(statusEntity.isLoading()); stationProtocol.setInEnable(statusEntity.isInEnable()); stationProtocol.setOutEnable(statusEntity.isOutEnable()); stationProtocol.setEmptyMk(statusEntity.isEmptyMk()); stationProtocol.setFullPlt(statusEntity.isFullPlt()); stationProtocol.setPalletHeight(statusEntity.getPalletHeight()); stationProtocol.setError(statusEntity.getError()); stationProtocol.setBarcode(statusEntity.getBarcode()); stationProtocol.setRunBlock(statusEntity.isRunBlock()); stationProtocol.setEnableIn(statusEntity.isEnableIn()); } } } OutputQueue.DEVP.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功", DateUtils.convert(new Date()), deviceConfig.getDeviceNo())); if (System.currentTimeMillis() - deviceDataLogTime > deviceLogCollectTime) { DeviceDataLog deviceDataLog = new DeviceDataLog(); deviceDataLog.setOriginData(JSON.toJSONString(zyStationStatusEntities)); deviceDataLog.setWcsData(JSON.toJSONString(statusList)); deviceDataLog.setType(String.valueOf(SlaveType.Devp)); deviceDataLog.setDeviceNo(deviceConfig.getDeviceNo()); deviceDataLog.setCreateTime(new Date()); redisUtil.set(RedisKeyType.DEVICE_LOG_KEY.key + System.currentTimeMillis(), deviceDataLog, 60 * 60 * 24); deviceDataLogTime = System.currentTimeMillis(); } } @Override public boolean connect() { zyStationConnectDriver = new ZyStationConnectDriver(deviceConfig, redisUtil); zyStationConnectDriver.start(); DeviceConnectPool.put(SlaveType.Devp, deviceConfig.getDeviceNo(), zyStationConnectDriver); return true; } @Override public void close() { if (zyStationConnectDriver != null) { zyStationConnectDriver.close(); } if (executor != null) { try { executor.shutdownNow(); } catch (Exception ignore) {} } } @Override public List<StationProtocol> getStatus() { return statusList; } @Override public Map<Integer, StationProtocol> getStatusMap() { Map<Integer, StationProtocol> map = new HashMap<>(); for (StationProtocol stationProtocol : statusList) { map.put(stationProtocol.getStationId(), stationProtocol); } return map; } @Override public StationCommand getCommand(StationCommandType commandType, Integer taskNo, Integer stationId, Integer targetStationId, Integer palletSize) { StationCommand stationCommand = new StationCommand(); stationCommand.setTaskNo(taskNo); stationCommand.setStationId(stationId); stationCommand.setTargetStaNo(targetStationId); stationCommand.setPalletSize(palletSize); stationCommand.setCommandType(commandType); if (commandType == StationCommandType.MOVE) { if (!stationId.equals(targetStationId)) { List<Integer> path = calcPathStationIds(stationId, targetStationId); stationCommand.setNavigatePath(path); } } return stationCommand; } @Override public CommandResponse sendCommand(StationCommand command) { CommandResponse commandResponse = null; try { commandResponse = zyStationConnectDriver.sendCommand(command); return commandResponse; } finally { BasStationOptService optService = SpringUtils.getBean(BasStationOptService.class); List<ZyStationStatusEntity> statusListEntity = zyStationConnectDriver.getStatus(); ZyStationStatusEntity matched = null; if (statusListEntity != null) { for (ZyStationStatusEntity e : statusListEntity) { if (e.getStationId() != null && e.getStationId().equals(command.getStationId())) { matched = e; break; } } } BasStationOpt basStationOpt = new BasStationOpt( command.getTaskNo(), command.getStationId(), new Date(), String.valueOf(command.getCommandType()), command.getStationId(), command.getTargetStaNo(), null, null, null, JSON.toJSONString(command), JSON.toJSONString(matched), 1, JSON.toJSONString(commandResponse) ); if (optService != null) { optService.insert(basStationOpt); } } } @Override public CommandResponse sendOriginCommand(String address, short[] data) { return zyStationConnectDriver.sendOriginCommand(address, data); } @Override public byte[] readOriginCommand(String address, int length) { return zyStationConnectDriver.readOriginCommand(address, length); } private List<Integer> calcPathStationIds(Integer startStationId, Integer targetStationId) { NavigateUtils navigateUtils = SpringUtils.getBean(NavigateUtils.class); if (navigateUtils == null) { return new ArrayList<>(); } List<NavigateNode> nodes = navigateUtils.calcByStationId(startStationId, targetStationId); List<Integer> ids = new ArrayList<>(); for (NavigateNode n : nodes) { JSONObject v = JSONObject.parseObject(n.getNodeValue()); if (v != null) { ids.add(v.getInteger("stationId")); } } return ids; } private void executeMoveWithSeg(StationCommand original) { if(original.getCommandType() == StationCommandType.MOVE){ List<Integer> path = original.getNavigatePath(); if (path == null || path.isEmpty()) { path = calcPathStationIds(original.getStationId(), original.getTargetStaNo()); } if (path == null || path.isEmpty()) { return; } int total = path.size(); List<Integer> segmentTargets = new ArrayList<>(); List<Integer> segmentEndIndices = new ArrayList<>(); int idx = 0; while (idx < total) { int end = Math.min(idx + 20, total) - 1; segmentTargets.add(path.get(end)); segmentEndIndices.add(end); idx = end + 1; } int segCursor = 0; Integer currentTarget = segmentTargets.get(segCursor); Integer currentEndIdx = segmentEndIndices.get(segCursor); Integer currentStartIdx = 0; StationCommand segCmd = new StationCommand(); segCmd.setTaskNo(original.getTaskNo()); segCmd.setStationId(original.getStationId()); segCmd.setTargetStaNo(original.getTargetStaNo()); segCmd.setCommandType(original.getCommandType()); segCmd.setPalletSize(original.getPalletSize()); segCmd.setNavigatePath(new ArrayList<>(path.subList(0, currentEndIdx + 1))); sendCommand(segCmd); boolean finished = false; while (!finished) { try { Integer currentStationId = findCurrentStationByTask(original.getTaskNo()); if (currentStationId == null) { Thread.sleep(500); continue; } int currentIndex = path.indexOf(currentStationId); if (currentIndex < 0) { Thread.sleep(500); continue; } int remaining = total - currentIndex - 1; if (remaining <= 0) { finished = true; break; } int currentSegEndIndex = path.indexOf(segmentTargets.get(segCursor)); int currentSegStartIndex = segCursor == 0 ? 0 : path.indexOf(segmentTargets.get(segCursor - 1)) + 1; int segLen = currentSegEndIndex - currentSegStartIndex + 1; int remainingSegment = Math.max(0, currentSegEndIndex - currentIndex); int thresholdSegment = (int) Math.ceil(segLen * 0.3); if (remainingSegment <= thresholdSegment && segCursor < segmentTargets.size() - 1) { segCursor++; currentEndIdx = segmentEndIndices.get(segCursor); currentStartIdx = segmentEndIndices.get(segCursor - 1) + 1; StationCommand nextCmd = new StationCommand(); nextCmd.setTaskNo(original.getTaskNo()); nextCmd.setStationId(original.getStationId()); nextCmd.setTargetStaNo(original.getTargetStaNo()); nextCmd.setCommandType(original.getCommandType()); nextCmd.setPalletSize(original.getPalletSize()); nextCmd.setNavigatePath(new ArrayList<>(path.subList(currentStartIdx, currentEndIdx + 1))); sendCommand(nextCmd); } Thread.sleep(500); } catch (Exception e) { break; } } }else { sendCommand(original); } } private Integer findCurrentStationByTask(Integer taskNo) { try { com.zy.asrs.service.DeviceConfigService deviceConfigService = SpringUtils.getBean(com.zy.asrs.service.DeviceConfigService.class); if (deviceConfigService == null) { return null; } List<DeviceConfig> devpList = deviceConfigService.selectList(new EntityWrapper<DeviceConfig>() .eq("device_type", String.valueOf(SlaveType.Devp))); for (DeviceConfig dc : devpList) { com.zy.core.thread.StationThread t = (com.zy.core.thread.StationThread) SlaveConnection.get(SlaveType.Devp, dc.getDeviceNo()); if (t == null) { continue; } Map<Integer, StationProtocol> m = t.getStatusMap(); if (m == null || m.isEmpty()) { continue; } for (StationProtocol sp : m.values()) { if (sp.getTaskNo() != null && sp.getTaskNo().equals(taskNo) && sp.isLoading()) { return sp.getStationId(); } } } } catch (Exception e) { return null; } return null; } } src/main/java/com/zy/core/utils/DualCrnOperateProcessUtils.java
@@ -578,7 +578,7 @@ continue; } //生成仿真站点数据 StationCommand command = stationThread.getMoveCommand(9998, wrkMast.getSourceStaNo(), 0, 0); StationCommand command = stationThread.getCommand(StationCommandType.WRITE_INFO, 9998, wrkMast.getSourceStaNo(), 0, 0); MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command)); } } src/main/java/com/zy/core/utils/StationOperateProcessUtils.java
@@ -15,6 +15,7 @@ import com.zy.core.cache.SlaveConnection; import com.zy.core.enums.RedisKeyType; import com.zy.core.enums.SlaveType; import com.zy.core.enums.StationCommandType; import com.zy.core.enums.WrkStsType; import com.zy.core.model.StationObjModel; import com.zy.core.model.Task; @@ -107,7 +108,7 @@ continue; } StationCommand command = stationThread.getMoveCommand(wrkMast.getWrkNo(), stationId, targetStationId, 0); StationCommand command = stationThread.getCommand(StationCommandType.MOVE, wrkMast.getWrkNo(), stationId, targetStationId, 0); if(command == null){ News.taskInfo(wrkMast.getWrkNo(), "获取输送线命令失败"); continue; @@ -174,7 +175,7 @@ && stationProtocol.isLoading() && stationProtocol.getTaskNo() == 0 ) { StationCommand command = stationThread.getMoveCommand(wrkMast.getWrkNo(), stationProtocol.getStationId(), wrkMast.getStaNo(), 0); StationCommand command = stationThread.getCommand(StationCommandType.MOVE, wrkMast.getWrkNo(), stationProtocol.getStationId(), wrkMast.getStaNo(), 0); if(command == null){ News.taskInfo(wrkMast.getWrkNo(), "获取输送线命令失败"); continue; @@ -312,7 +313,7 @@ continue; } StationCommand command = stationThread.getMoveCommand(wrkMast.getWrkNo(), stationProtocol.getStationId(), targetStationId, 0); StationCommand command = stationThread.getCommand(StationCommandType.MOVE, wrkMast.getWrkNo(), stationProtocol.getStationId(), targetStationId, 0); if(command == null){ News.taskInfo(wrkMast.getWrkNo(), "获取输送线命令失败"); continue; @@ -348,7 +349,7 @@ } }else { //运行堵塞,重新计算路线 StationCommand command = stationThread.getMoveCommand(wrkMast.getWrkNo(), stationProtocol.getStationId(), wrkMast.getStaNo(), 0); StationCommand command = stationThread.getCommand(StationCommandType.MOVE, wrkMast.getWrkNo(), stationProtocol.getStationId(), wrkMast.getStaNo(), 0); if(command == null){ News.taskInfo(wrkMast.getWrkNo(), "获取输送线命令失败"); continue; src/main/webapp/components/DevpCard.js
@@ -40,6 +40,7 @@ <el-descriptions-item label="空板信号">{{ item.emptyMk ? 'Y' : 'N' }}</el-descriptions-item> <el-descriptions-item label="满板信号">{{ item.fullPlt ? 'Y' : 'N' }}</el-descriptions-item> <el-descriptions-item label="运行阻塞">{{ item.runBlock ? 'Y' : 'N' }}</el-descriptions-item> <el-descriptions-item label="启动入库">{{ item.enableIn ? 'Y' : 'N' }}</el-descriptions-item> <el-descriptions-item label="托盘高度">{{ item.palletHeight }}</el-descriptions-item> <el-descriptions-item label="条码">{{ item.barcode }}</el-descriptions-item> <el-descriptions-item label="故障代码">{{ item.error }}</el-descriptions-item>