c8de85433e5800a7b5595a96d99f4b49f24c38b4..7a546480f6ddfaee1366f280981a002a08412c11
2025-12-17 Junjie
#
7a5464 对比 | 目录
2025-12-17 Junjie
#
0c5a58 对比 | 目录
2025-12-17 Junjie
#
96f987 对比 | 目录
1个文件已删除
1个文件已添加
21个文件已修改
1368 ■■■■■ 已修改文件
src/main/java/com/zy/asrs/controller/OpenController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/model/Shelves.java 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/service/CommonService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/NavigateSolution.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/NavigateUtils.java 174 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/MainProcess.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/ServerBootstrap.java 46 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/config/FakeTaskNoAreaInitializer.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/RedisKeyType.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/WrkIoType.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/StationObjModel.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/ZyCrnConnectDriver.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/ZyRgvConnectDriver.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/ZyStationConnectDriver.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/fake/ZyStationFakeConnect.java 381 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/real/ZyStationRealConnect.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/plugin/FakeProcess.java 49 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/impl/ZyRgvThread.java 71 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/impl/ZySiemensCrnThread.java 70 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/impl/ZyStationThread.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/utils/StationOperateProcessUtils.java 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/map/上海临港哥斯拉项目.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/OpenController.java
@@ -69,8 +69,8 @@
        if (param == null) {
            return R.error("参数不能为空");
        }
        boolean result = commonService.createInTask(param);
        if (result) {
        WrkMast wrkMast = commonService.createInTask(param);
        if (wrkMast != null) {
            return R.ok();
        }
        return R.error("生成入库任务失败");
src/main/java/com/zy/common/model/Shelves.java
File was deleted
src/main/java/com/zy/common/service/CommonService.java
@@ -184,7 +184,7 @@
    }
    //入库任务
    public boolean createInTask(CreateInTaskParam param) {
    public WrkMast createInTask(CreateInTaskParam param) {
        Date now = new Date();
        LocMast locMast = locMastService.queryByLoc(param.getLocNo());
        if (null == locMast) {
@@ -234,7 +234,7 @@
        //缓存记录当前命令堆垛机编号
        redisUtil.set(RedisKeyType.CURRENT_CIRCLE_TASK_CRN_NO.key, crnNo, 60 * 60 * 24);
        return true;
        return wrkMast;
    }
    //出库任务
src/main/java/com/zy/common/utils/NavigateSolution.java
@@ -10,6 +10,8 @@
import com.zy.common.model.NavigateNode;
import com.zy.core.enums.MapNodeType;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiFunction;
/**
 * A*算法实现类
@@ -157,6 +159,115 @@
        return null;
    }
    public List<List<NavigateNode>> allSimplePaths(
            List<List<NavigateNode>> map,
            NavigateNode start,
            NavigateNode end,
            int maxDepth,    // æœ€å¤§æ­¥æ•°(边数). å»ºè®®ï¼š50/100/200;<=0 è¡¨ç¤ºä¸é™åˆ¶ï¼ˆä¸å»ºè®®ï¼‰
            int maxPaths,    // æœ€å¤§è¿”回条数. å»ºè®®ï¼š100/500/2000;<=0 è¡¨ç¤ºä¸é™åˆ¶ï¼ˆä¸å»ºè®®ï¼‰
            int maxCost      // æœ€å¤§æ€»ä»£ä»·(含拐点惩罚). <=0 è¡¨ç¤ºä¸é™åˆ¶
    ) {
        List<List<NavigateNode>> results = new ArrayList<>();
        if (map == null || map.isEmpty() || map.get(0).isEmpty()) return results;
        if (start == null || end == null) return results;
        if (start.getValue() == MapNodeType.DISABLE.id || end.getValue() == MapNodeType.DISABLE.id) return results;
        // visited ç”¨åæ ‡ key,避免 NavigateNode equals/hashCode ä¸å¯é å¯¼è‡´é‡å¤åˆ¤æ–­å¤±æ•ˆ
        Set<String> visited = new HashSet<>(map.size() * map.get(0).size() * 2);
        LinkedList<NavigateNode> path = new LinkedList<>();
        String startKey = keyOf(start);
        visited.add(startKey);
        path.add(start);
        AtomicInteger pathCount = new AtomicInteger(0);
        dfsAllSimplePaths(map, start, end,
                visited, path, results,
                0,  // depth
                0,  // cost
                maxDepth, maxPaths, maxCost,
                pathCount
        );
        return results;
    }
    /**
     * DFS + å›žæº¯ï¼šæžšä¸¾æ‰€æœ‰ç®€å•路径(路径中不允许重复节点)
     */
    private void dfsAllSimplePaths(
            List<List<NavigateNode>> map,
            NavigateNode current,
            NavigateNode end,
            Set<String> visited,
            LinkedList<NavigateNode> path,
            List<List<NavigateNode>> results,
            int depth,     // å½“前步数(边数)
            int cost,      // å½“前总代价(你可以认为是 g)
            int maxDepth,
            int maxPaths,
            int maxCost,
            AtomicInteger pathCount
    ) {
        // é˜²çˆ†ï¼šæ¡æ•°é™åˆ¶
        if (maxPaths > 0 && pathCount.get() >= maxPaths) return;
        // åˆ°è¾¾ç»ˆç‚¹ï¼šæ”¶é›†è·¯å¾„
        if (current.getX() == end.getX() && current.getY() == end.getY()) {
            results.add(new ArrayList<>(path));
            pathCount.incrementAndGet();
            return;
        }
        // é˜²çˆ†ï¼šæ·±åº¦é™åˆ¶ï¼ˆdepth è¡¨ç¤ºå·²èµ°çš„边数)
        if (maxDepth > 0 && depth >= maxDepth) return;
        // æ‰©å±•邻居(严格复用你自己的可行走方向规则)
        ArrayList<NavigateNode> neighbors = extend_current_node(map, current);
        if (neighbors == null || neighbors.isEmpty()) return;
        for (NavigateNode next : neighbors) {
            // é˜²çˆ†ï¼šæ¡æ•°é™åˆ¶
            if (maxPaths > 0 && pathCount.get() >= maxPaths) return;
            if (next == null) continue;
            if (next.getValue() == MapNodeType.DISABLE.id) continue;
            String nk = keyOf(next);
            // ç®€å•路径:不允许重复节点
            if (visited.contains(nk)) continue;
            // ä½ çš„代价规则:每步 1 + æ‹ç‚¹æƒ©ç½š
            int stepCost = 1 + calcNodeExtraCost(current, next, end);
            int newCost = cost + stepCost;
            // é˜²çˆ†ï¼šæ€»ä»£ä»·é™åˆ¶
            if (maxCost > 0 && newCost > maxCost) continue;
            // è¿›å…¥
            visited.add(nk);
            path.addLast(next);
            dfsAllSimplePaths(map, next, end,
                    visited, path, results,
                    depth + 1,
                    newCost,
                    maxDepth, maxPaths, maxCost,
                    pathCount
            );
            // å›žæº¯
            path.removeLast();
            visited.remove(nk);
        }
    }
    private String keyOf(NavigateNode n) {
        return n.getX() + "_" + n.getY();
    }
    public ArrayList<NavigateNode> extend_current_node(List<List<NavigateNode>> map, NavigateNode current_node) {
        //获取当前结点的x, y
        int x = current_node.getX();
src/main/java/com/zy/common/utils/NavigateUtils.java
@@ -2,16 +2,28 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import com.zy.core.News;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.SpringUtils;
import com.core.exception.CoolException;
import com.zy.common.model.NavigateNode;
import com.zy.asrs.entity.DeviceConfig;
import com.zy.asrs.service.DeviceConfigService;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.protocol.StationProtocol;
import com.zy.core.thread.StationThread;
import com.zy.system.entity.Config;
import com.zy.system.service.ConfigService;
@Component
public class NavigateUtils {
@@ -32,31 +44,16 @@
        long startTime = System.currentTimeMillis();
        News.info("[WCS Debug] ç«™ç‚¹è·¯å¾„开始计算,startStationId={},endStationId={}", startStationId, endStationId);
        NavigateNode res_node = navigateSolution.astarSearchJava(stationMap, startNode, endNode);
        if (res_node == null) {
        List<List<NavigateNode>> allList = navigateSolution.allSimplePaths(stationMap, startNode, endNode, 120, 500, 300);
        if (allList.isEmpty()) {
            throw new CoolException("未找到该路径");
        }
        News.info("[WCS Debug] ç«™ç‚¹è·¯å¾„计算完成,耗时:{}ms", System.currentTimeMillis() - startTime);
        ArrayList<NavigateNode> list = new ArrayList<>();
        // ä½¿ç”¨ visited é›†åˆé˜²æ­¢çˆ¶é“¾å‡ºçŽ°çŽ¯å¯¼è‡´æ­»å¾ªçŽ¯ï¼ŒåŒæ—¶è®¾ç½®å®‰å…¨æ­¥æ•°ä¸Šé™
        HashSet<NavigateNode> visited = new HashSet<>();
        int maxSteps = stationMap.size() * stationMap.get(0).size() + 5; // å®‰å…¨ä¸Šé™
        int steps = 0;
        while (res_node != null && visited.add(res_node) && steps++ < maxSteps) {
            list.add(res_node);
            res_node = res_node.getFather();//迭代操作
        }
        if (steps >= maxSteps) {
            throw new CoolException("路径回溯超出安全上限,疑似存在父链循环");
        }
        Collections.reverse(list);
        //将每个节点里面的fatherNode至为null(方便后续计算时父节点过多导致显示的节点太多)
        for (NavigateNode navigateNode : list) {
            //父节点设置为null,不影响计算结果,不影响后续操作。
            //此操作仅为后续排查处理提供视觉方便。
            navigateNode.setFather(null);
        }
        startTime = System.currentTimeMillis();
        News.info("[WCS Debug] ç«™ç‚¹è·¯å¾„权重开始分析,startStationId={},endStationId={}", startStationId, endStationId);
        List<NavigateNode> list = findStationBestPath(allList);
        News.info("[WCS Debug] ç«™ç‚¹è·¯å¾„权重分析完成,耗时:{}ms", System.currentTimeMillis() - startTime);
        //去重
        HashSet<Integer> set = new HashSet<>();
@@ -152,4 +149,139 @@
        return liftStationList;
    }
    public synchronized List<NavigateNode> findStationBestPath(List<List<NavigateNode>> allList) {
        if (allList == null || allList.isEmpty()) {
            return new ArrayList<>();
        }
        Map<Integer, StationProtocol> statusMap = new HashMap<>();
        try {
            DeviceConfigService deviceConfigService = SpringUtils.getBean(DeviceConfigService.class);
            if (deviceConfigService != null) {
                List<DeviceConfig> devpList = deviceConfigService.selectList(new EntityWrapper<DeviceConfig>()
                        .eq("device_type", String.valueOf(SlaveType.Devp)));
                for (DeviceConfig deviceConfig : devpList) {
                    StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, deviceConfig.getDeviceNo());
                    if (stationThread == null) {
                        continue;
                    }
                    Map<Integer, StationProtocol> m = stationThread.getStatusMap();
                    if (m != null && !m.isEmpty()) {
                        statusMap.putAll(m);
                    }
                }
            }
        } catch (Exception ignore) {}
        List<List<NavigateNode>> candidates = new ArrayList<>();
        List<Integer> lens = new ArrayList<>();
        List<Integer> tasksList = new ArrayList<>();
        List<Double> congs = new ArrayList<>();
        for (List<NavigateNode> path : allList) {
            if (path == null || path.isEmpty()) {
                continue;
            }
            int len = path.size();
            int tasks = 0;
            HashSet<Integer> stationIdSet = new HashSet<>();
            for (NavigateNode node : path) {
                JSONObject value = null;
                try {
                    value = JSON.parseObject(node.getNodeValue());
                } catch (Exception ignore) {}
                if (value == null) {
                    continue;
                }
                Integer stationId = value.getInteger("stationId");
                if (stationId == null) {
                    continue;
                }
                if (!stationIdSet.add(stationId)) {
                    continue;
                }
                StationProtocol protocol = statusMap.get(stationId);
                if (protocol != null && protocol.getTaskNo() != null && protocol.getTaskNo() > 0) {
                    tasks++;
                }
            }
            double cong = len <= 0 ? 0.0 : (double) tasks / (double) len;
            candidates.add(path);
            lens.add(len);
            tasksList.add(tasks);
            congs.add(cong);
        }
        if (candidates.isEmpty()) {
            return allList.get(0);
        }
        int minLen = Integer.MAX_VALUE;
        int maxLen = Integer.MIN_VALUE;
        double minCong = Double.MAX_VALUE;
        double maxCong = -Double.MAX_VALUE;
        for (int i = 0; i < candidates.size(); i++) {
            int l = lens.get(i);
            double c = congs.get(i);
            if (l < minLen) minLen = l;
            if (l > maxLen) maxLen = l;
            if (c < minCong) minCong = c;
            if (c > maxCong) maxCong = c;
        }
        //长度权重百分比
        double lenWeightPercent = 50.0;
        //拥堵权重百分比
        double congWeightPercent = 50.0;
        try {
            ConfigService configService = SpringUtils.getBean(ConfigService.class);
            if (configService != null) {
                Config cfgLen = configService.selectOne(new EntityWrapper<Config>().eq("code", "stationPathLenWeightPercent"));
                if (cfgLen != null && cfgLen.getValue() != null) {
                    String v = cfgLen.getValue().trim();
                    if (v.endsWith("%")) v = v.substring(0, v.length() - 1);
                    try { lenWeightPercent = Double.parseDouble(v); } catch (Exception ignore) {}
                }
                Config cfgCong = configService.selectOne(new EntityWrapper<Config>().eq("code", "stationPathCongWeightPercent"));
                if (cfgCong != null && cfgCong.getValue() != null) {
                    String v = cfgCong.getValue().trim();
                    if (v.endsWith("%")) v = v.substring(0, v.length() - 1);
                    try { congWeightPercent = Double.parseDouble(v); } catch (Exception ignore) {}
                }
            }
        } catch (Exception ignore) {}
        double weightSum = lenWeightPercent + congWeightPercent;
        double lenW = weightSum <= 0 ? 0.5 : lenWeightPercent / weightSum;
        double congW = weightSum <= 0 ? 0.5 : congWeightPercent / weightSum;
        List<NavigateNode> best = null;
        double bestCost = Double.MAX_VALUE;
        int bestTasks = Integer.MAX_VALUE;
        int bestLen = Integer.MAX_VALUE;
        for (int i = 0; i < candidates.size(); i++) {
            int l = lens.get(i);
            int t = tasksList.get(i);
            double c = congs.get(i);
            //归一化
            double lenNorm = (maxLen - minLen) <= 0 ? 0.0 : (l - minLen) / (double) (maxLen - minLen);
            double congNorm = (maxCong - minCong) <= 0 ? 0.0 : (c - minCong) / (double) (maxCong - minCong);
            //获取权重
            double cost = lenNorm * lenW + congNorm * congW;
            if (cost < bestCost
                    || (cost == bestCost && t < bestTasks)
                    || (cost == bestCost && t == bestTasks && l < bestLen)) {
                best = candidates.get(i);
                bestCost = cost;
                bestTasks = t;
                bestLen = l;
            }
        }
        if (best == null) {
            return allList.get(0);
        }
        return best;
    }
}
src/main/java/com/zy/core/MainProcess.java
@@ -55,6 +55,8 @@
                }
            }
        });
        thread.setName("MainProcess");
        thread.setDaemon(true);
        thread.start();
    }
src/main/java/com/zy/core/ServerBootstrap.java
@@ -17,7 +17,6 @@
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import javax.annotation.PreDestroy;
import java.util.List;
/**
@@ -92,7 +91,10 @@
                throw new CoolException("未知的线程实现");
            }
            new Thread(thread).start();
            Thread t = new Thread(thread);
            t.setName("CrnThread-" + deviceConfig.getDeviceNo());
            t.setDaemon(true);
            t.start();
            SlaveConnection.put(SlaveType.Crn, deviceConfig.getDeviceNo(), thread);
        }
@@ -107,7 +109,10 @@
                throw new CoolException("未知的线程实现");
            }
            new Thread(thread).start();
            Thread t = new Thread(thread);
            t.setName("DevpThread-" + deviceConfig.getDeviceNo());
            t.setDaemon(true);
            t.start();
            SlaveConnection.put(SlaveType.Devp, deviceConfig.getDeviceNo(), thread);
        }
@@ -122,40 +127,13 @@
                throw new CoolException("未知的线程实现");
            }
            new Thread(thread).start();
            Thread t = new Thread(thread);
            t.setName("RgvThread-" + deviceConfig.getDeviceNo());
            t.setDaemon(true);
            t.start();
            SlaveConnection.put(SlaveType.Rgv, deviceConfig.getDeviceNo(), thread);
        }
    }
    @PreDestroy
    public void destroy() {
        try {
            List<DeviceConfig> crnList = deviceConfigService.selectList(new EntityWrapper<DeviceConfig>()
                    .eq("device_type", String.valueOf(SlaveType.Crn)));
            for (DeviceConfig deviceConfig : crnList) {
                SlaveConnection.remove(SlaveType.Crn, deviceConfig.getDeviceNo());
            }
        } catch (Exception ignore) {}
        try {
            List<DeviceConfig> devpList = deviceConfigService.selectList(new EntityWrapper<DeviceConfig>()
                    .eq("device_type", String.valueOf(SlaveType.Devp)));
            for (DeviceConfig deviceConfig : devpList) {
                SlaveConnection.remove(SlaveType.Devp, deviceConfig.getDeviceNo());
            }
        } catch (Exception ignore) {}
        try {
            List<DeviceConfig> rgvList = deviceConfigService.selectList(new EntityWrapper<DeviceConfig>()
                    .eq("device_type", String.valueOf(SlaveType.Rgv)));
            for (DeviceConfig deviceConfig : rgvList) {
                SlaveConnection.remove(SlaveType.Rgv, deviceConfig.getDeviceNo());
            }
        } catch (Exception ignore) {}
        try {
            mainProcess.shutDown();
        } catch (Exception ignore) {}
    }
}
src/main/java/com/zy/core/config/FakeTaskNoAreaInitializer.java
New file
@@ -0,0 +1,38 @@
package com.zy.core.config;
import com.alibaba.fastjson.JSON;
import com.core.common.Cools;
import com.core.exception.CoolException;
import com.zy.asrs.entity.WrkLastno;
import com.zy.asrs.service.WrkLastnoService;
import com.zy.common.utils.RedisUtil;
import com.zy.core.enums.RedisKeyType;
import com.zy.core.enums.WrkIoType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.HashMap;
@Component
public class FakeTaskNoAreaInitializer {
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private WrkLastnoService wrkLastnoService;
    @PostConstruct
    public void init() {
        WrkLastno wrkLastno = wrkLastnoService.selectById(WrkIoType.FAKE_TASK_NO.id);
        if (Cools.isEmpty(wrkLastno)) {
            throw new CoolException("数据异常,请联系管理员");
        }
        HashMap<String, Object> map = new HashMap<>();
        map.put("start", wrkLastno.getSNo());
        map.put("end", wrkLastno.getENo());
        redisUtil.set(RedisKeyType.FAKE_TASK_NO_AREA.key, JSON.toJSONString(map));
    }
}
src/main/java/com/zy/core/enums/RedisKeyType.java
@@ -16,6 +16,7 @@
    LOG_LIMIT("log_limit_"),
    SYSTEM_CONFIG_MAP("system_config_map"),
    FAKE_TASK_NO_AREA("fake_task_no_area"),
    LOC_MAP_BASE("loc_map_base"),
    LOC_MAST_MAP_LIST("loc_mast_map_list"),
@@ -30,6 +31,8 @@
    CHECK_OUT_STATION_STAY_TIME_OUT_LIMIT("check_out_station_stay_time_out_limit_"),
    CHECK_IN_STATION_STAY_TIME_OUT_LIMIT("check_in_station_stay_time_out_limit_"),
    CRN_IO_EXECUTE_FINISH_LIMIT("crn_io_execute_finish_limit_"),
    STATION_IN_EXECUTE_LIMIT("station_in_execute_limit_"),
    STATION_OUT_EXECUTE_LIMIT("station_out_execute_limit_"),
    CURRENT_CIRCLE_TASK_CRN_NO("current_circle_task_crn_no_"),
    AI_CHAT_HISTORY("ai_chat_history_"),
src/main/java/com/zy/core/enums/WrkIoType.java
@@ -9,6 +9,7 @@
    LOC_MOVE(201, "移库任务"),
    PREVIEW_LIFT_MOVE(98, "提升机预调度移动任务"),
    MANUAL(99, "手动任务"),
    FAKE_TASK_NO(9999, "仿真随机工作号"),
    ;
    WrkIoType(int id, String desc) {
src/main/java/com/zy/core/model/StationObjModel.java
@@ -15,4 +15,6 @@
    private Integer deviceLev;
    private StationObjModel barcodeStation;
}
src/main/java/com/zy/core/network/ZyCrnConnectDriver.java
@@ -9,6 +9,10 @@
import com.zy.core.network.fake.ZyCrnFakeConnect;
import com.zy.core.network.real.ZyCrnRealConnect;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
 * è¿žæŽ¥é©±åЍ
@@ -20,29 +24,15 @@
    private DeviceConfig deviceConfig;
    private ZyCrnConnectApi zyCrnConnectApi;
    private volatile boolean closed = false;
    private Thread selfThread;
    private ScheduledExecutorService executor;
    public ZyCrnConnectDriver(DeviceConfig deviceConfig) {
        this.deviceConfig = deviceConfig;
    }
    @Override
    @SuppressWarnings("InfiniteLoopStatement")
    public void run() {
        selfThread = Thread.currentThread();
        while (!closed && !Thread.currentThread().isInterrupted()) {
            try {
                if (!connected) {
                    connect();
                }
                Thread.sleep(1000);
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
                break;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    @Override
@@ -61,9 +51,9 @@
    @Override
    public void close() {
        closed = true;
        Thread t = selfThread;
        if (t != null) {
            try { t.interrupt(); } catch (Exception ignore) {}
        ScheduledExecutorService ex = executor;
        if (ex != null) {
            try { ex.shutdownNow(); } catch (Exception ignore) {}
        }
        if (zyCrnConnectApi != null) {
            zyCrnConnectApi.disconnect();
@@ -73,8 +63,27 @@
    }
    public void start() {
        Thread t = new Thread(this);
        t.start();
        executor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName("CrnConnect-" + deviceConfig.getDeviceNo());
                t.setDaemon(true);
                return t;
            }
        });
        executor.scheduleAtFixedRate(() -> {
            if (closed || Thread.currentThread().isInterrupted()) {
                return;
            }
            try {
                if (!connected) {
                    connect();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, 0, 1000, TimeUnit.MILLISECONDS);
    }
    public ZyCrnStatusEntity getStatus() {
src/main/java/com/zy/core/network/ZyRgvConnectDriver.java
@@ -9,6 +9,10 @@
import com.zy.core.network.fake.ZyRgvFakeConnect;
import com.zy.core.network.real.ZyRgvRealConnect;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
@Slf4j
public class ZyRgvConnectDriver implements ThreadHandler {
@@ -16,29 +20,15 @@
    private DeviceConfig deviceConfig;
    private ZyRgvConnectApi zyRgvConnectApi;
    private volatile boolean closed = false;
    private Thread selfThread;
    private ScheduledExecutorService executor;
    public ZyRgvConnectDriver(DeviceConfig deviceConfig) {
        this.deviceConfig = deviceConfig;
    }
    @Override
    @SuppressWarnings("InfiniteLoopStatement")
    public void run() {
        selfThread = Thread.currentThread();
        while (!closed && !Thread.currentThread().isInterrupted()) {
            try {
                if (!connected) {
                    connect();
                }
                Thread.sleep(1000);
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
                break;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    @Override
@@ -56,9 +46,9 @@
    @Override
    public void close() {
        closed = true;
        Thread t = selfThread;
        if (t != null) {
            try { t.interrupt(); } catch (Exception ignore) {}
        ScheduledExecutorService ex = executor;
        if (ex != null) {
            try { ex.shutdownNow(); } catch (Exception ignore) {}
        }
        if (zyRgvConnectApi != null) {
            zyRgvConnectApi.disconnect();
@@ -68,8 +58,27 @@
    }
    public void start() {
        Thread t = new Thread(this);
        t.start();
        executor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName("RgvConnect-" + deviceConfig.getDeviceNo());
                t.setDaemon(true);
                return t;
            }
        });
        executor.scheduleAtFixedRate(() -> {
            if (closed || Thread.currentThread().isInterrupted()) {
                return;
            }
            try {
                if (!connected) {
                    connect();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, 0, 1000, TimeUnit.MILLISECONDS);
    }
    public ZyRgvStatusEntity getStatus() {
src/main/java/com/zy/core/network/ZyStationConnectDriver.java
@@ -1,6 +1,7 @@
package com.zy.core.network;
import com.zy.asrs.entity.DeviceConfig;
import com.zy.common.utils.RedisUtil;
import com.zy.core.ThreadHandler;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.command.StationCommand;
@@ -10,6 +11,10 @@
import com.zy.core.network.fake.ZyStationFakeConnect;
import com.zy.core.network.real.ZyStationRealConnect;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
 * è¾“送站连接驱动
@@ -19,39 +24,27 @@
    private boolean connected = false;
    private DeviceConfig deviceConfig;
    private RedisUtil redisUtil;
    private ZyStationConnectApi zyStationConnectApi;
    private volatile boolean closed = false;
    private Thread selfThread;
    private ScheduledExecutorService executor;
    public ZyStationConnectDriver(DeviceConfig deviceConfig) {
    public ZyStationConnectDriver(DeviceConfig deviceConfig, RedisUtil redisUtil) {
        this.deviceConfig = deviceConfig;
        this.redisUtil = redisUtil;
    }
    @Override
    @SuppressWarnings("InfiniteLoopStatement")
    public void run() {
        selfThread = Thread.currentThread();
        while (!closed && !Thread.currentThread().isInterrupted()) {
            try {
                if (!connected) {
                    connect();
                }
                Thread.sleep(1000);
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
                break;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    @Override
    public boolean connect() {
        if (deviceConfig.getFake() == 0) {
            zyStationConnectApi = new ZyStationRealConnect(deviceConfig);
            zyStationConnectApi = new ZyStationRealConnect(deviceConfig, redisUtil);
        } else {
            zyStationConnectApi = new ZyStationFakeConnect(deviceConfig);
            zyStationConnectApi = new ZyStationFakeConnect(deviceConfig, redisUtil);
        }
        boolean connect = zyStationConnectApi.connect();
@@ -62,9 +55,9 @@
    @Override
    public void close() {
        closed = true;
        Thread t = selfThread;
        if (t != null) {
            try { t.interrupt(); } catch (Exception ignore) {}
        ScheduledExecutorService ex = executor;
        if (ex != null) {
            try { ex.shutdownNow(); } catch (Exception ignore) {}
        }
        if (zyStationConnectApi != null) {
            zyStationConnectApi.disconnect();
@@ -74,8 +67,28 @@
    }
    public void start() {
        Thread t = new Thread(this);
        t.start();
        executor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName("DevpConnect-" + deviceConfig.getDeviceNo());
                t.setDaemon(true);
                return t;
            }
        });
        executor.scheduleAtFixedRate(() -> {
            if (closed || Thread.currentThread().isInterrupted()) {
                return;
            }
            try {
                if (!connected) {
                    connect();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, 0, 1000, TimeUnit.MILLISECONDS);
    }
    public List<ZyStationStatusEntity> getStatus() {
src/main/java/com/zy/core/network/fake/ZyStationFakeConnect.java
@@ -6,31 +6,37 @@
import com.zy.asrs.entity.DeviceConfig;
import com.zy.common.model.NavigateNode;
import com.zy.common.utils.NavigateUtils;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.enums.RedisKeyType;
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.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Supplier;
/**
 * è¾“送站假连接(模拟)
 */
public class ZyStationFakeConnect implements ZyStationConnectApi {
    private List<ZyStationStatusEntity> statusList = new ArrayList<>();
    private final List<ZyStationStatusEntity> statusList = new CopyOnWriteArrayList<>();
    private static int LOCK_STATION = 0;
    private final DeviceConfig deviceConfig;
    private RedisUtil redisUtil;
    // å…è®¸å¹¶è¡Œæ‰§è¡Œå¤šä¸ªå‘½ä»¤ä»»åŠ¡ï¼ˆå›ºå®šçº¿ç¨‹æ± ï¼‰ã€‚å¦‚éœ€æ›´é«˜å¹¶å‘å¯è°ƒæ•´å¤§å°ã€‚
    private final ExecutorService executor = Executors
            .newFixedThreadPool(9999);
    public ZyStationFakeConnect(DeviceConfig deviceConfig) {
    public ZyStationFakeConnect(DeviceConfig deviceConfig, RedisUtil redisUtil) {
        this.deviceConfig = deviceConfig;
        this.redisUtil = redisUtil;
    }
    @Override
@@ -47,18 +53,20 @@
    @Override
    public List<ZyStationStatusEntity> getStatus() {
        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("");// æ¨¡æ‹Ÿæ— æ¡ç 
            List<ZyStationStatusEntity> init = JSON.parseArray(deviceConfig.getFakeInitStatus(), ZyStationStatusEntity.class);
            if (init != null) {
                statusList.addAll(init);
                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("");// æ¨¡æ‹Ÿæ— æ¡ç 
                }
            }
        }
@@ -82,6 +90,7 @@
        Integer taskNo = command.getTaskNo();
        Integer stationId = command.getStationId();
        Integer targetStationId = command.getTargetStaNo();
        boolean generateBarcode = false;
        if(taskNo == 0 && targetStationId == 0){
            //清空站点
@@ -89,10 +98,10 @@
            return;
        }
        if (taskNo == 9999 && targetStationId == 0) {
        //任务号属于仿真入库任务号
        if (checkTaskNoInArea(taskNo)) {
            //生成仿真数据
            generateFakeData(stationId, taskNo);
            return;
            generateBarcode = true;
        }
        if (taskNo == 9998 && targetStationId == 0) {
@@ -101,29 +110,19 @@
            return;
        }
        if (taskNo > 0 && taskNo != 9999 && taskNo != 9998 && stationId == targetStationId) {
            //下发任务数据-不允许只是下发数据
            generateStationData(taskNo, stationId, targetStationId);
        }
        String startLev = String.valueOf(stationId).substring(0, 1);
        String endLev = String.valueOf(targetStationId).substring(0, 1);
        if (startLev.equals(endLev)) {
            currentLevCommand(command);
            currentLevCommand(command, generateBarcode);
        }else {
            diffLevCommand(command);
            diffLevCommand(command, generateBarcode);
        }
    }
    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) {
@@ -133,7 +132,22 @@
            return;
        }
        status.setLoading(true);
        synchronized (status) {
            status.setLoading(true);
        }
    }
    private void generateStationData(Integer taskNo, Integer stationId, Integer targetStationId) {
        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 stationId) {
@@ -143,12 +157,14 @@
            return;
        }
        status.setTaskNo(0);
        status.setLoading(false);
        status.setBarcode("");
        synchronized (status) {
            status.setTaskNo(0);
            status.setLoading(false);
            status.setBarcode("");
        }
    }
    private void currentLevCommand(StationCommand command) {
    private void currentLevCommand(StationCommand command, boolean generateBarcode) {
        NavigateUtils navigateUtils = SpringUtils.getBean(NavigateUtils.class);
        if (navigateUtils == null) {
            return;
@@ -172,10 +188,10 @@
            return;
        }
        stationMove(navigateNodes, taskNo, targetStationId, false);
        stationMove(navigateNodes, taskNo, targetStationId, false, generateBarcode);
    }
    private void diffLevCommand(StationCommand command) {
    private void diffLevCommand(StationCommand command, boolean generateBarcode) {
        NavigateUtils navigateUtils = SpringUtils.getBean(NavigateUtils.class);
        if (navigateUtils == null) {
            return;
@@ -247,75 +263,75 @@
            return;
        }
        stationMove(navigateNodes, taskNo, stationId, true);
        stationMove(targetNavigateNodes, taskNo, targetStationId, false);
        stationMove(navigateNodes, taskNo, stationId, true, generateBarcode);
        stationMove(targetNavigateNodes, taskNo, targetStationId, false, generateBarcode);
    }
    private void stationMove(List<NavigateNode> navigateNodes, Integer taskNo, Integer targetStationId, boolean clearData) {
    private void stationMove(List<NavigateNode> navigateNodes, Integer taskNo, Integer targetStationId, boolean clearData, boolean generateBarcode) {
        Integer lastStationId = null;
        for (int i = 0; i < navigateNodes.size(); i++) {
        int i = 0;
        while (i < navigateNodes.size()) {
            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;
            Integer nextStationId = null;
            try {
                NavigateNode nextNode = navigateNodes.get(i + 1);
                JSONObject nextValueObject = JSON.parseObject(nextNode.getNodeValue());
                nextStationId = nextValueObject.getInteger("stationId");
            } catch (Exception e) {
            }
            try {
                while (!Thread.currentThread().isInterrupted()) {
                    ZyStationStatusEntity nextStatus = statusList.stream()
                            .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null);
                    if (nextStatus == null) {
            if (nextStationId != null) {
            }
            if (i == 0) {
                boolean result = initStationMove(taskNo, currentStationId, taskNo, targetStationId, true, null);
                if (!result) {
                    continue;
                }
                sleep(1000);
            }
            if(nextStationId != null) {
                boolean result = stationMoveToNext(taskNo, currentStationId, nextStationId, taskNo, targetStationId);
                if (!result) {
                    continue;
                }
                lastStationId = currentStationId;
            }
            i++;
            sleep(1000);
        }
        if (generateBarcode) {
            if (lastStationId != null) {
                while (true) {
                    boolean result = generateStationBarcode(taskNo, targetStationId);
                    sleep(1000);
                    if (!result) {
                        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);
                    }
                    break;
                }
            }
            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);
                while (true) {
                    boolean result = clearStation(taskNo, targetStationId);
                    sleep(1000);
                    if (!result) {
                        continue;
                    }
                    break;
                }
            }
        }
@@ -328,4 +344,181 @@
            e.printStackTrace();
        }
    }
}
    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 taskNo, Integer targetStaNo, Boolean isLoading, String barcode) {
        if (LOCK_STATION != lockTaskNo) {
            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);
        }
        return true;
    }
    public synchronized boolean initStationMove(Integer lockTaskNo, Integer currentStationId, Integer taskNo, Integer targetStationId, Boolean isLoading, String barcode) {
        boolean executeResult = lockExecute(lockTaskNo, () -> {
            ZyStationStatusEntity currentStatus = statusList.stream()
                .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null);
            if (currentStatus == null) {
                return false;
            }
            if(currentStatus.getTaskNo().equals(taskNo)) {
                return true;
            }
            if (currentStatus.getTaskNo() > 0 || currentStatus.isLoading()) {
                return false;
            }
            boolean result = updateStationData(taskNo, currentStationId, taskNo, targetStationId, isLoading, barcode);
            if (!result) {
                return false;
            }
            return true;
        });
        return executeResult;
    }
    public synchronized boolean stationMoveToNext(Integer lockTaskNo, Integer currentStationId, Integer nextStationId, Integer taskNo, Integer targetStaNo) {
        boolean executeResult = lockExecute(lockTaskNo, () -> {
            ZyStationStatusEntity currentStatus = statusList.stream()
                    .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null);
            ZyStationStatusEntity nextStatus = statusList.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, taskNo, targetStaNo, true, null);
            if (!result) {
                return false;
            }
            boolean result2 = updateStationData(lockTaskNo, currentStationId, 0, 0, false, null);
            if (!result2) {
                return false;
            }
            return true;
        });
        return executeResult;
    }
    public synchronized boolean generateStationBarcode(Integer lockTaskNo, Integer currentStationId) {
        boolean executeResult = lockExecute(lockTaskNo, () -> {
            ZyStationStatusEntity currentStatus = statusList.stream()
                    .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null);
            if (currentStatus == null) {
                return false;
            }
            String barcodeTime = String.valueOf(System.currentTimeMillis());
            String barcode = barcodeTime.substring(5);
            boolean result = updateStationData(lockTaskNo, currentStationId, null, null, null, barcode);
            if (!result) {
                return false;
            }
            return true;
        });
        return executeResult;
    }
    public synchronized boolean clearStation(Integer lockTaskNo, Integer currentStationId) {
        boolean executeResult = lockExecute(lockTaskNo, () -> {
            ZyStationStatusEntity currentStatus = statusList.stream()
                    .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null);
            if (currentStatus == null) {
                return false;
            }
            boolean result = updateStationData(lockTaskNo, currentStationId, 0, 0, false, "");
            if (!result) {
                return false;
            }
            return true;
        });
        return executeResult;
    }
    public synchronized boolean lockExecute(Integer taskNo, Supplier<Boolean> function) {
        if (!setLockStation(taskNo)) {
            return false;
        }
        boolean result = function.get();
        releaseLockStation(taskNo);
        return result;
    }
    private synchronized 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/ZyStationRealConnect.java
@@ -4,6 +4,7 @@
import HslCommunication.Core.Types.OperateResultExOne;
import HslCommunication.Profinet.Siemens.SiemensPLCS;
import HslCommunication.Profinet.Siemens.SiemensS7Net;
import com.zy.common.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import com.alibaba.fastjson.JSON;
@@ -36,9 +37,11 @@
    private List<ZyStationStatusEntity> barcodeStatusList;
    private SiemensS7Net siemensNet;
    private DeviceConfig deviceConfig;
    private RedisUtil redisUtil;
    public ZyStationRealConnect(DeviceConfig deviceConfig) {
    public ZyStationRealConnect(DeviceConfig deviceConfig, RedisUtil redisUtil) {
        this.deviceConfig = deviceConfig;
        this.redisUtil = redisUtil;
    }
    @Override
src/main/java/com/zy/core/plugin/FakeProcess.java
@@ -3,6 +3,7 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.Cools;
import com.zy.asrs.domain.param.CreateInTaskParam;
import com.zy.asrs.domain.param.CreateOutTaskParam;
import com.zy.asrs.entity.*;
@@ -145,8 +146,8 @@
                    continue;
                }
                Object object = redisUtil.get(RedisKeyType.GENERATE_FAKE_IN_STATION_DATA_LIMIT.key + stationId);
                if (object != null) {
                Object lock = redisUtil.get(RedisKeyType.GENERATE_FAKE_IN_STATION_DATA_LIMIT.key + stationId);
                if(lock != null){
                    continue;
                }
@@ -155,9 +156,9 @@
                        && !stationProtocol.isLoading()
                        && stationProtocol.getTaskNo() == 0
                ) {
                    StationCommand command = stationThread.getMoveCommand(9999, stationId, 0, 0);
                    StationCommand command = stationThread.getMoveCommand(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", 10);
                    redisUtil.set(RedisKeyType.GENERATE_FAKE_IN_STATION_DATA_LIMIT.key + stationId, "lock", 5);
                }
            }
        }
@@ -186,7 +187,7 @@
            Map<Integer, StationProtocol> stationMap = stationThread.getStatusMap();
            List<StationObjModel> list = basDevp.getInStationList$();
            List<StationObjModel> list = basDevp.getBarcodeStationList$();
            for (StationObjModel model : list) {
                Integer stationId = model.getStationId();
                if(!stationMap.containsKey(stationId)){
@@ -203,11 +204,15 @@
                    return;
                }
                //满足自动、有物、工作号9999,生成入库数据
                //满足自动、有物、有工作号,生成入库数据
                if (stationProtocol.isAutoing()
                        && stationProtocol.isLoading()
                        && stationProtocol.getTaskNo() == 9999
                        && stationProtocol.getTaskNo() > 0
                ) {
                    if (Cools.isEmpty(stationProtocol.getBarcode())) {
                        continue;
                    }
                    //检测任务是否生成
                    List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("barcode", stationProtocol.getBarcode()));
                    if (!wrkMasts.isEmpty()) {
@@ -238,8 +243,14 @@
                    taskParam.setStaNo(targetStationId);
                    taskParam.setLocNo(locMast.getLocNo());
                    taskParam.setBarcode(stationProtocol.getBarcode());
                    boolean result = commonService.createInTask(taskParam);
                    WrkMast wrkMast = commonService.createInTask(taskParam);
                    StationCommand command = stationThread.getMoveCommand(wrkMast.getWrkNo(), stationId, stationId, 0);
                    if(command == null){
                        News.taskInfo(wrkMast.getWrkNo(), "获取输送线命令失败");
                        continue;
                    }
                    MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command));
                    redisUtil.set(RedisKeyType.GENERATE_FAKE_IN_TASK_LIMIT.key + stationId, "lock", 5);
                }
            }
@@ -308,7 +319,7 @@
                    taskParam.setStaNo(stationId);
                    taskParam.setLocNo(locMast.getLocNo());
                    boolean result = commonService.createOutTask(taskParam);
                    redisUtil.set(RedisKeyType.GENERATE_FAKE_OUT_TASK_LIMIT.key + stationId, "lock", 15);
                    redisUtil.set(RedisKeyType.GENERATE_FAKE_OUT_TASK_LIMIT.key + stationId, "lock", 10);
                }
            }
        }
@@ -332,7 +343,7 @@
            Map<Integer, StationProtocol> stationMap = stationThread.getStatusMap();
            List<StationObjModel> list = basDevp.getInStationList$();
            List<StationObjModel> list = basDevp.getBarcodeStationList$();
            for (StationObjModel entity : list) {
                Integer stationId = entity.getStationId();
                if(!stationMap.containsKey(stationId)){
@@ -344,11 +355,15 @@
                    continue;
                }
                //满足自动、有物、工作号9999,生成入库数据
                //满足自动、有物、有工作号,生成入库数据
                if (stationProtocol.isAutoing()
                        && stationProtocol.isLoading()
                        && stationProtocol.getTaskNo() == 9999
                        && stationProtocol.getTaskNo() > 0
                ) {
                    if (Cools.isEmpty(stationProtocol.getBarcode())) {
                        continue;
                    }
                    //检测任务是否生成
                    List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("barcode", stationProtocol.getBarcode()));
                    if (!wrkMasts.isEmpty()) {
@@ -382,7 +397,7 @@
                        continue;
                    }
                    redisUtil.set(RedisKeyType.GENERATE_IN_TASK_LIMIT.key + stationId, "lock", 15);
                    redisUtil.set(RedisKeyType.GENERATE_IN_TASK_LIMIT.key + stationId, "lock", 5);
                    HashMap<String, Object> requestParam = new HashMap<>();
                    String response = null;
@@ -407,8 +422,14 @@
                            taskParam.setLocNo(dto.getLocNo());
                            taskParam.setTaskPri(dto.getTaskPri());
                            taskParam.setBarcode(stationProtocol.getBarcode());
                            boolean result = commonService.createInTask(taskParam);
                            WrkMast wrkMast = commonService.createInTask(taskParam);
                            StationCommand command = stationThread.getMoveCommand(wrkMast.getWrkNo(), stationId, stationId, 0);
                            if(command == null){
                                News.taskInfo(wrkMast.getWrkNo(), "获取输送线命令失败");
                                continue;
                            }
                            MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command));
                            News.info("请求WMS接口成功!!!url:{};request:{};response:{}", wmsUrl + wmsSystemInUrl, JSON.toJSONString(requestParam), response);
                        } else {
                            News.error("请求WMS接口失败!!!url:{};request:{};response:{}", wmsUrl + wmsSystemInUrl, JSON.toJSONString(requestParam), response);
src/main/java/com/zy/core/thread/impl/ZyRgvThread.java
@@ -30,6 +30,10 @@
import java.text.MessageFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
@Data
@Slf4j
@@ -41,7 +45,8 @@
    private RgvProtocol rgvProtocol;
    private int deviceLogCollectTime = 200;
    private volatile boolean closed = false;
    private Thread mainThread;
    private ScheduledExecutorService readExecutor;
    private ScheduledExecutorService processExecutor;
    public ZyRgvThread(DeviceConfig deviceConfig, RedisUtil redisUtil) {
        this.deviceConfig = deviceConfig;
@@ -53,33 +58,53 @@
    public void run() {
        connect();
        initRgv();
        mainThread = Thread.currentThread();
        while (!closed && !Thread.currentThread().isInterrupted()) {
        readExecutor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName("RgvReader-" + deviceConfig.getDeviceNo());
                t.setDaemon(true);
                return t;
            }
        });
        readExecutor.scheduleAtFixedRate(() -> {
            if (closed || Thread.currentThread().isInterrupted()) {
                return;
            }
            try {
                deviceLogCollectTime = Utils.getDeviceLogCollectTime();
                readStatus();
            } catch (Exception e) {
                log.error("RgvThread Fail", e);
            }
        }, 0, 200, TimeUnit.MILLISECONDS);
        processExecutor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName("RgvWriter-" + deviceConfig.getDeviceNo());
                t.setDaemon(true);
                return t;
            }
        });
        processExecutor.scheduleAtFixedRate(() -> {
            if (closed || Thread.currentThread().isInterrupted()) {
                return;
            }
            try {
                int step = 1;
                Task task = MessageQueue.poll(SlaveType.Rgv, deviceConfig.getDeviceNo());
                if (task != null) {
                    step = task.getStep();
                }
                switch (step) {
                    case 1:
                        readStatus();
                        break;
                    case 2:
                        sendCommand((RgvCommand) task.getData());
                        break;
                    default:
                        break;
                if (step == 2 && task != null) {
                    sendCommand((RgvCommand) task.getData());
                }
                Thread.sleep(200);
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
                break;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        }, 0, 200, TimeUnit.MILLISECONDS);
    }
    private void initRgv() {
@@ -158,13 +183,17 @@
    @Override
    public void close() {
        closed = true;
        Thread t = mainThread;
        if (t != null) {
            try { t.interrupt(); } catch (Exception ignore) {}
        }
        if (zyRgvConnectDriver != null) {
            zyRgvConnectDriver.close();
        }
        ScheduledExecutorService ex = readExecutor;
        if (ex != null) {
            try { ex.shutdownNow(); } catch (Exception ignore) {}
        }
        ScheduledExecutorService px = processExecutor;
        if (px != null) {
            try { px.shutdownNow(); } catch (Exception ignore) {}
        }
    }
    @Override
src/main/java/com/zy/core/thread/impl/ZySiemensCrnThread.java
@@ -12,7 +12,6 @@
import com.zy.asrs.service.BasCrnpOptService;
import com.zy.asrs.utils.Utils;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.OutputQueue;
import com.zy.core.enums.CrnTaskModeType;
@@ -31,6 +30,10 @@
import java.text.MessageFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
 * å †åž›æœºçº¿ç¨‹
@@ -46,7 +49,8 @@
    private int deviceLogCollectTime = 200;
    private boolean resetFlag = false;
    private volatile boolean closed = false;
    private Thread mainThread;
    private ScheduledExecutorService readExecutor;
    private ScheduledExecutorService processExecutor;
    public ZySiemensCrnThread(DeviceConfig deviceConfig, RedisUtil redisUtil) {
        this.deviceConfig = deviceConfig;
@@ -58,33 +62,53 @@
    public void run() {
        this.connect();
        this.initCrn();
        mainThread = Thread.currentThread();
        while (!closed && !Thread.currentThread().isInterrupted()) {
        readExecutor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName("CrnReader-" + deviceConfig.getDeviceNo());
                t.setDaemon(true);
                return t;
            }
        });
        readExecutor.scheduleAtFixedRate(() -> {
            if (closed || Thread.currentThread().isInterrupted()) {
                return;
            }
            try {
                deviceLogCollectTime = Utils.getDeviceLogCollectTime();
                readStatus();
            } catch (Exception e) {
                log.error("CrnThread Fail", e);
            }
        }, 0, 200, TimeUnit.MILLISECONDS);
        processExecutor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName("CrnWriter-" + deviceConfig.getDeviceNo());
                t.setDaemon(true);
                return t;
            }
        });
        processExecutor.scheduleAtFixedRate(() -> {
            if (closed || Thread.currentThread().isInterrupted()) {
                return;
            }
            try {
                int step = 1;
                Task task = MessageQueue.poll(SlaveType.Crn, deviceConfig.getDeviceNo());
                if (task != null) {
                    step = task.getStep();
                }
                switch (step) {
                    case 1:
                        readStatus();
                        break;
                    case 2:
                        sendCommand((CrnCommand) task.getData());
                        break;
                    default:
                        break;
                if (step == 2 && task != null) {
                    sendCommand((CrnCommand) task.getData());
                }
                Thread.sleep(200);
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
                break;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        }, 0, 200, TimeUnit.MILLISECONDS);
    }
    /**
@@ -217,9 +241,13 @@
    @Override
    public void close() {
        closed = true;
        Thread t = mainThread;
        if (t != null) {
            try { t.interrupt(); } catch (Exception ignore) {}
        ScheduledExecutorService ex = readExecutor;
        if (ex != null) {
            try { ex.shutdownNow(); } catch (Exception ignore) {}
        }
        ScheduledExecutorService px = processExecutor;
        if (px != null) {
            try { px.shutdownNow(); } catch (Exception ignore) {}
        }
        if (zyCrnConnectDriver != null) {
            zyCrnConnectDriver.close();
src/main/java/com/zy/core/thread/impl/ZyStationThread.java
@@ -28,6 +28,10 @@
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@@ -46,8 +50,8 @@
    private int deviceLogCollectTime = 200;
    private long deviceDataLogTime = System.currentTimeMillis();
    private volatile boolean closed = false;
    private Thread mainThread;
    private Thread readThread;
    private ScheduledExecutorService readExecutor;
    private ScheduledExecutorService processExecutor;
    public ZyStationThread(DeviceConfig deviceConfig, RedisUtil redisUtil) {
        this.deviceConfig = deviceConfig;
@@ -59,45 +63,54 @@
    public void run() {
        this.connect();
        deviceLogCollectTime = Utils.getDeviceLogCollectTime();
        mainThread = Thread.currentThread();
        readThread = new Thread(() -> {
            while (!closed && !Thread.currentThread().isInterrupted()) {
                try {
                    readStatus();
                    Thread.sleep(200);
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    break;
                } catch (Exception e) {
                    log.error("StationThread Fail", e);
                }
        readExecutor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName("DevpReader-" + deviceConfig.getDeviceNo());
                t.setDaemon(true);
                return t;
            }
        });
        readThread.start();
        readExecutor.scheduleAtFixedRate(() -> {
            if (closed || Thread.currentThread().isInterrupted()) {
                return;
            }
            try {
                deviceLogCollectTime = Utils.getDeviceLogCollectTime();
                readStatus();
            } catch (Exception e) {
                log.error("StationThread Fail", e);
            }
        }, 0, 200, TimeUnit.MILLISECONDS);
        while (!closed && !Thread.currentThread().isInterrupted()) {
        processExecutor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName("DevpWriter-" + deviceConfig.getDeviceNo());
                t.setDaemon(true);
                return t;
            }
        });
        processExecutor.scheduleAtFixedRate(() -> {
            if (closed || Thread.currentThread().isInterrupted()) {
                return;
            }
            try {
                int step = 1;
                Task task = MessageQueue.poll(SlaveType.Devp, deviceConfig.getDeviceNo());
                if (task != null) {
                    step = task.getStep();
                }
                switch (step) {
                    case 2:
                        sendCommand((StationCommand) task.getData());
                        break;
                    default:
                        break;
                if (step == 2 && task != null) {
                    sendCommand((StationCommand) task.getData());
                }
                Thread.sleep(200);
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
                break;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        }, 0, 200, TimeUnit.MILLISECONDS);
    }
    private void readStatus() {
@@ -168,7 +181,7 @@
    @Override
    public boolean connect() {
        zyStationConnectDriver = new ZyStationConnectDriver(deviceConfig);
        zyStationConnectDriver = new ZyStationConnectDriver(deviceConfig, redisUtil);
        zyStationConnectDriver.start();
        DeviceConnectPool.put(SlaveType.Devp, deviceConfig.getDeviceNo(), zyStationConnectDriver);
        return true;
@@ -177,13 +190,13 @@
    @Override
    public void close() {
        closed = true;
        Thread t = mainThread;
        if (t != null) {
            try { t.interrupt(); } catch (Exception ignore) {}
        ScheduledExecutorService ex = readExecutor;
        if (ex != null) {
            try { ex.shutdownNow(); } catch (Exception ignore) {}
        }
        Thread rt = readThread;
        if (rt != null) {
            try { rt.interrupt(); } catch (Exception ignore) {}
        ScheduledExecutorService px = processExecutor;
        if (px != null) {
            try { px.shutdownNow(); } catch (Exception ignore) {}
        }
        if (zyStationConnectDriver != null) {
            zyStationConnectDriver.close();
src/main/java/com/zy/core/utils/StationOperateProcessUtils.java
@@ -11,9 +11,11 @@
import com.zy.asrs.service.BasDevpService;
import com.zy.asrs.service.WrkMastService;
import com.zy.common.service.CommonService;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.RedisKeyType;
import com.zy.core.enums.SlaveType;
import com.zy.core.enums.WrkStsType;
import com.zy.core.model.StationObjModel;
@@ -39,6 +41,8 @@
    private CommonService commonService;
    @Autowired
    private BasCrnpService basCrnpService;
    @Autowired
    private RedisUtil redisUtil;
    //执行输送站点入库任务
    public synchronized void stationInExecute() {
@@ -51,7 +55,7 @@
            Map<Integer, StationProtocol> stationMap = stationThread.getStatusMap();
            List<StationObjModel> list = basDevp.getInStationList$();
            List<StationObjModel> list = basDevp.getBarcodeStationList$();
            for (StationObjModel entity : list) {
                Integer stationId = entity.getStationId();
                if(!stationMap.containsKey(stationId)){
@@ -63,10 +67,15 @@
                    continue;
                }
                //满足自动、有物、工作号9999
                Object lock = redisUtil.get(RedisKeyType.STATION_IN_EXECUTE_LIMIT.key + stationId);
                if(lock != null){
                    continue;
                }
                //满足自动、有物、有工作号
                if (stationProtocol.isAutoing()
                        && stationProtocol.isLoading()
                        && stationProtocol.getTaskNo() == 9999
                        && stationProtocol.getTaskNo() > 0
                ) {
                    //检测任务是否生成
                    WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("barcode", stationProtocol.getBarcode()));
@@ -75,6 +84,11 @@
                    }
                    if (wrkMast.getWrkSts() == WrkStsType.INBOUND_DEVICE_RUN.sts) {
                        continue;
                    }
                    if (!wrkMast.getWrkNo().equals(stationProtocol.getTaskNo())) {
                        News.taskInfo(stationProtocol.getStationId(), "输送站点工作号:{}与条码搜索到的任务工作号:{}不一致", stationProtocol.getTaskNo(), wrkMast.getWrkNo());
                        continue;
                    }
@@ -105,6 +119,7 @@
                    if (wrkMastService.updateById(wrkMast)) {
                        MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command));
                        News.info("输送站点入库命令下发成功,站点号={},工作号={},命令数据={}", stationId, wrkMast.getWrkNo(), JSON.toJSONString(command));
                        redisUtil.set(RedisKeyType.STATION_IN_EXECUTE_LIMIT.key + stationId, "lock", 5);
                    }
                }
            }
@@ -138,6 +153,11 @@
                    continue;
                }
                Object lock = redisUtil.get(RedisKeyType.STATION_OUT_EXECUTE_LIMIT.key + stationProtocol.getStationId());
                if (lock != null) {
                    continue;
                }
                //满足自动、有物、工作号0
                if (stationProtocol.isAutoing()
                        && stationProtocol.isLoading()
@@ -155,6 +175,7 @@
                    if (wrkMastService.updateById(wrkMast)) {
                        MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command));
                        News.info("输送站点出库命令下发成功,站点号={},工作号={},命令数据={}", stationProtocol.getStationId(), wrkMast.getWrkNo(), JSON.toJSONString(command));
                        redisUtil.set(RedisKeyType.STATION_OUT_EXECUTE_LIMIT.key + stationProtocol.getStationId(), "lock", 5);
                    }
                }
            }
src/main/resources/application.yml
@@ -2,6 +2,7 @@
  port: 9090
  servlet:
    context-path: /@pom.build.finalName@
  shutdown: graceful
spring:
  application:
@@ -25,6 +26,15 @@
    scheduling:
      pool:
        size: 3
      shutdown:
        await-termination: true
        await-termination-period: 30s
    execution:
      shutdown:
        await-termination: true
        await-termination-period: 30s
  lifecycle:
    timeout-per-shutdown-phase: 20s
mybatis-plus:
  mapper-locations: classpath:mapper/*.xml
@@ -76,4 +86,4 @@
  model: deepseek-ai/DeepSeek-V3.2
#  base-url: http://34.2.134.223:3000/v1
#  api-key: sk-WabrmtOezCFwVo7XvVOrO3QkmfcKG7T7jy0BaVnmQTWm5GXh
#  model: gemini-3-pro-preview
#  model: gemini-3-pro-preview
src/main/resources/map/ÉϺ£ÁÙ¸Û¸ç˹À­ÏîÄ¿.xlsx
Binary files differ