| | |
| | | package com.zy.core.network.fake; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.core.common.SpringUtils; |
| | | import com.zy.asrs.entity.DeviceConfig; |
| | | import com.zy.common.model.NavigateNode; |
| | | import com.zy.common.utils.NavigateUtils; |
| | | import com.zy.core.News; |
| | | 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.Collections; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | import java.util.concurrent.ExecutorService; |
| | |
| | | */ |
| | | public class ZyStationFakeConnect implements ZyStationConnectApi { |
| | | |
| | | private ZyStationStatusEntity status; |
| | | private List<ZyStationStatusEntity> statusList = new ArrayList<>(); |
| | | private final DeviceConfig deviceConfig; |
| | | private final ExecutorService executor = Executors.newSingleThreadExecutor(); |
| | | // 允许并行执行多个命令任务(固定线程池)。如需更高并发可调整大小。 |
| | | private final ExecutorService executor = Executors |
| | | .newFixedThreadPool(9999); |
| | | |
| | | public ZyStationFakeConnect(DeviceConfig deviceConfig) { |
| | | this.deviceConfig = deviceConfig; |
| | | this.status = JSON.parseObject(deviceConfig.getFakeInitStatus(), ZyStationStatusEntity.class); |
| | | if (this.status == null) { |
| | | this.status = new ZyStationStatusEntity(); |
| | | this.status.setStationId(deviceConfig.getDeviceNo()); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | |
| | | |
| | | @Override |
| | | public boolean disconnect() { |
| | | executor.shutdownNow(); |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public List<ZyStationStatusEntity> getStatus() { |
| | | return Collections.singletonList(status); |
| | | if (this.statusList.isEmpty()) { |
| | | this.statusList = JSON.parseArray(deviceConfig.getFakeInitStatus(), ZyStationStatusEntity.class); |
| | | |
| | | for (ZyStationStatusEntity status : this.statusList) { |
| | | status.setAutoing(true);// 模拟自动运行 |
| | | status.setLoading(false);// 模拟有物 |
| | | status.setInEnable(true);// 模拟可入 |
| | | status.setOutEnable(true);// 模拟可出 |
| | | status.setEmptyMk(false);// 模拟空板信号 |
| | | status.setFullPlt(false);// 模拟满托盘 |
| | | status.setPalletHeight(0);// 模拟托盘高度为0 |
| | | status.setError(0);// 模拟无报警 |
| | | status.setBarcode("");// 模拟无条码 |
| | | } |
| | | } |
| | | |
| | | return this.statusList; |
| | | } |
| | | |
| | | @Override |
| | | public CommandResponse sendCommand(StationCommand command) { |
| | | CommandResponse response = new CommandResponse(false); |
| | | executor.submit(() -> handleCommand(command)); |
| | | response.setResult(true); |
| | | return response; |
| | | executor.submit(() -> { |
| | | try { |
| | | handleCommand(command); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | }); |
| | | return new CommandResponse(true, "命令已受理(异步执行)"); |
| | | } |
| | | |
| | | private void handleCommand(StationCommand command) { |
| | | // 简单的模拟:设置工作号和目标站,并模拟有物/可入/可出状态切换 |
| | | this.status.setTaskNo(command.getTaskNo()); |
| | | this.status.setTargetStaNo(command.getTargetStaNo()); |
| | | News.info("[WCS Debug] 站点仿真模拟已启动,命令数据={}", JSON.toJSONString(command)); |
| | | Integer taskNo = command.getTaskNo(); |
| | | Integer stationId = command.getStationId(); |
| | | Integer targetStationId = command.getTargetStaNo(); |
| | | |
| | | // 模拟到站过程 |
| | | this.status.setAutoing(true); |
| | | this.status.setLoading(true); |
| | | sleep(1000); |
| | | if(taskNo == 0 && targetStationId == 0){ |
| | | //清空站点 |
| | | resetStation(stationId); |
| | | return; |
| | | } |
| | | |
| | | // 模拟放下托盘 |
| | | this.status.setInEnable(true); |
| | | this.status.setOutEnable(false); |
| | | sleep(1000); |
| | | if (taskNo == 9999 && targetStationId == 0) { |
| | | //生成仿真数据 |
| | | generateFakeData(stationId, taskNo); |
| | | return; |
| | | } |
| | | |
| | | // 完成任务,复位状态 |
| | | this.status.setLoading(false); |
| | | this.status.setAutoing(false); |
| | | this.status.setTaskNo(0); |
| | | this.status.setInEnable(false); |
| | | this.status.setOutEnable(true); |
| | | if (taskNo == 9998 && targetStationId == 0) { |
| | | //生成出库站点仿真数据 |
| | | generateFakeOutStationData(stationId); |
| | | return; |
| | | } |
| | | |
| | | String startLev = String.valueOf(stationId).substring(0, 1); |
| | | String endLev = String.valueOf(targetStationId).substring(0, 1); |
| | | |
| | | if (startLev.equals(endLev)) { |
| | | currentLevCommand(command); |
| | | }else { |
| | | diffLevCommand(command); |
| | | } |
| | | } |
| | | |
| | | private void generateFakeData(Integer stationId, Integer taskNo) { |
| | | ZyStationStatusEntity status = statusList.stream() |
| | | .filter(item -> item.getStationId().equals(stationId)).findFirst().orElse(null); |
| | | if (status == null) { |
| | | return; |
| | | } |
| | | |
| | | String barcodeTime = String.valueOf(System.currentTimeMillis()); |
| | | String barcode = barcodeTime.substring(5); |
| | | |
| | | status.setTaskNo(taskNo); |
| | | status.setLoading(true); |
| | | status.setBarcode(barcode); |
| | | } |
| | | |
| | | private void generateFakeOutStationData(Integer stationId) { |
| | | ZyStationStatusEntity status = statusList.stream() |
| | | .filter(item -> item.getStationId().equals(stationId)).findFirst().orElse(null); |
| | | if (status == null) { |
| | | return; |
| | | } |
| | | |
| | | status.setLoading(true); |
| | | } |
| | | |
| | | private void resetStation(Integer stationId) { |
| | | ZyStationStatusEntity status = statusList.stream() |
| | | .filter(item -> item.getStationId().equals(stationId)).findFirst().orElse(null); |
| | | if (status == null) { |
| | | return; |
| | | } |
| | | |
| | | status.setTaskNo(0); |
| | | status.setLoading(false); |
| | | status.setBarcode(""); |
| | | } |
| | | |
| | | private void currentLevCommand(StationCommand command) { |
| | | NavigateUtils navigateUtils = SpringUtils.getBean(NavigateUtils.class); |
| | | if (navigateUtils == null) { |
| | | return; |
| | | } |
| | | |
| | | Integer taskNo = command.getTaskNo(); |
| | | Integer stationId = command.getStationId(); |
| | | Integer targetStationId = command.getTargetStaNo(); |
| | | |
| | | String startLev = String.valueOf(stationId).substring(0, 1); |
| | | |
| | | List<NavigateNode> navigateNodes = null; |
| | | |
| | | try { |
| | | navigateNodes = navigateUtils.calcByStationId(Integer.parseInt(startLev), stationId, targetStationId); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | if (navigateNodes == null) { |
| | | return; |
| | | } |
| | | |
| | | stationMove(navigateNodes, taskNo, targetStationId, false); |
| | | } |
| | | |
| | | private void diffLevCommand(StationCommand command) { |
| | | NavigateUtils navigateUtils = SpringUtils.getBean(NavigateUtils.class); |
| | | if (navigateUtils == null) { |
| | | return; |
| | | } |
| | | |
| | | Integer taskNo = command.getTaskNo(); |
| | | Integer stationId = command.getStationId(); |
| | | Integer targetStationId = command.getTargetStaNo(); |
| | | |
| | | String startLev = String.valueOf(stationId).substring(0, 1); |
| | | String endLev = String.valueOf(targetStationId).substring(0, 1); |
| | | |
| | | List<NavigateNode> navigateNodes = null; |
| | | List<NavigateNode> targetNavigateNodes = null; |
| | | |
| | | try { |
| | | List<NavigateNode> liftStationList = navigateUtils.findLiftStationList(Integer.parseInt(startLev)); |
| | | if(liftStationList.isEmpty()){ |
| | | //未找到提升机节点 |
| | | return; |
| | | } |
| | | |
| | | List<NavigateNode> targetLiftStationList = navigateUtils.findLiftStationList(Integer.parseInt(endLev)); |
| | | if(targetLiftStationList.isEmpty()){ |
| | | //未找到提升机节点 |
| | | return; |
| | | } |
| | | for (NavigateNode liftStation : liftStationList) { |
| | | JSONObject valuObject = JSON.parseObject(liftStation.getNodeValue()); |
| | | if(valuObject == null){ |
| | | continue; |
| | | } |
| | | Integer liftStationId = valuObject.getInteger("stationId"); |
| | | Integer liftNo = valuObject.getInteger("liftNo"); |
| | | |
| | | Integer targetLiftStationId = null; |
| | | for (NavigateNode targetLiftStation : targetLiftStationList) { |
| | | JSONObject targetValuObject = JSON.parseObject(targetLiftStation.getNodeValue()); |
| | | if(targetValuObject == null){ |
| | | continue; |
| | | } |
| | | Integer targetLiftNo = targetValuObject.getInteger("liftNo"); |
| | | if(liftNo.equals(targetLiftNo)){ |
| | | targetLiftStationId = targetValuObject.getInteger("stationId"); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if(targetLiftStationId == null){ |
| | | continue; |
| | | } |
| | | |
| | | navigateNodes = navigateUtils.calcByStationId(Integer.parseInt(startLev), stationId, liftStationId); |
| | | if(navigateNodes == null){ |
| | | continue; |
| | | } |
| | | |
| | | //计算提升机到目标站的路径 |
| | | targetNavigateNodes = navigateUtils.calcByStationId(Integer.parseInt(endLev), targetLiftStationId, targetStationId); |
| | | if(targetNavigateNodes == null) { |
| | | continue; |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | if (navigateNodes == null || targetNavigateNodes == null) { |
| | | return; |
| | | } |
| | | |
| | | stationMove(navigateNodes, taskNo, stationId, true); |
| | | stationMove(targetNavigateNodes, taskNo, targetStationId, false); |
| | | } |
| | | |
| | | private void stationMove(List<NavigateNode> navigateNodes, Integer taskNo, Integer targetStationId, boolean clearData) { |
| | | Integer lastStationId = null; |
| | | for (int i = 0; i < navigateNodes.size(); i++) { |
| | | NavigateNode navigateNode = navigateNodes.get(i); |
| | | JSONObject valueObject = JSON.parseObject(navigateNode.getNodeValue()); |
| | | Integer currentStationId = valueObject.getInteger("stationId"); |
| | | ZyStationStatusEntity status = statusList.stream() |
| | | .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null); |
| | | if (status == null) { |
| | | continue; |
| | | } |
| | | |
| | | try { |
| | | while (true) { |
| | | ZyStationStatusEntity nextStatus = statusList.stream() |
| | | .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null); |
| | | if (nextStatus == null) { |
| | | continue; |
| | | } |
| | | |
| | | if (nextStatus.getTaskNo() == 0 || nextStatus.getTaskNo() == 9999) { |
| | | break; |
| | | } |
| | | |
| | | sleep(100); |
| | | } |
| | | } catch (Exception e) { |
| | | continue; |
| | | } |
| | | |
| | | if (lastStationId != null) { |
| | | Integer finalLastStationId = lastStationId; |
| | | ZyStationStatusEntity lastStatus = statusList.stream() |
| | | .filter(item -> item.getStationId().equals(finalLastStationId)).findFirst().orElse(null); |
| | | if (lastStatus != null) { |
| | | synchronized (lastStatus) { |
| | | lastStatus.setTaskNo(0); |
| | | lastStatus.setTargetStaNo(0); |
| | | lastStatus.setLoading(false); |
| | | } |
| | | } |
| | | } |
| | | |
| | | synchronized (status) { |
| | | status.setTaskNo(taskNo); |
| | | status.setTargetStaNo(targetStationId); |
| | | status.setLoading(true); |
| | | } |
| | | |
| | | lastStationId = currentStationId; |
| | | sleep(1000); |
| | | } |
| | | |
| | | if (clearData) { |
| | | sleep(10000); |
| | | if (lastStationId != null) { |
| | | Integer finalLastStationId = lastStationId; |
| | | ZyStationStatusEntity lastStatus = statusList.stream() |
| | | .filter(item -> item.getStationId().equals(finalLastStationId)).findFirst().orElse(null); |
| | | if (lastStatus != null) { |
| | | synchronized (lastStatus) { |
| | | lastStatus.setTaskNo(0); |
| | | lastStatus.setTargetStaNo(0); |
| | | lastStatus.setLoading(false); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void sleep(long ms) { |