From c0760528d4c2c3411c8f9fff3d0e9db7ba9a658f Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期二, 03 三月 2026 16:47:06 +0800
Subject: [PATCH] #

---
 src/main/java/com/zy/core/thread/impl/ZyStationV4Thread.java |  436 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 436 insertions(+), 0 deletions(-)

diff --git a/src/main/java/com/zy/core/thread/impl/ZyStationV4Thread.java b/src/main/java/com/zy/core/thread/impl/ZyStationV4Thread.java
new file mode 100644
index 0000000..a573950
--- /dev/null
+++ b/src/main/java/com/zy/core/thread/impl/ZyStationV4Thread.java
@@ -0,0 +1,436 @@
+package com.zy.core.thread.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.core.common.Cools;
+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.*;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+@Data
+@Slf4j
+public class ZyStationV4Thread 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 ZyStationV4Thread(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.setErrorMsg(statusEntity.getErrorMsg());
+                    stationProtocol.setBarcode(statusEntity.getBarcode());
+                    stationProtocol.setRunBlock(statusEntity.isRunBlock());
+                    stationProtocol.setEnableIn(statusEntity.isEnableIn());
+                    stationProtocol.setWeight(statusEntity.getWeight());
+                }
+
+                if (!Cools.isEmpty(stationProtocol.getSystemWarning())) {
+                    if (stationProtocol.isAutoing()
+                            && !stationProtocol.isLoading()
+                    ) {
+                        stationProtocol.setSystemWarning("");
+                    }
+                }
+            }
+        }
+
+        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);
+        } catch (Exception e) {
+            e.printStackTrace();
+        } 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);
+            }
+        }
+        return commandResponse;
+    }
+
+    @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) {
+        int stationCommandSendLength = 20;
+        Object systemConfigMapObj = redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key);
+        if (systemConfigMapObj != null) {
+            try {
+                HashMap<String, String> systemConfigMap = (HashMap<String, String>) systemConfigMapObj;
+                String stationCommandSendLengthStr = systemConfigMap.get("stationCommandSendLength");
+                if(stationCommandSendLengthStr != null){
+                    stationCommandSendLength = Integer.parseInt(stationCommandSendLengthStr);
+                }
+            } catch (Exception ignore) {}
+        }
+
+        if(original.getCommandType() == StationCommandType.MOVE){
+            List<Integer> path = JSON.parseArray(JSON.toJSONString(original.getNavigatePath(), SerializerFeature.DisableCircularReferenceDetect), Integer.class);
+            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 + stationCommandSendLength, 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);
+
+            long runTime = System.currentTimeMillis();
+            boolean firstRun = true;
+            while (true) {
+                try {
+                    Object cancel = redisUtil.get(RedisKeyType.DEVICE_STATION_MOVE_RESET.key + original.getTaskNo());
+                    if (cancel != null) {
+                        break;//鏀跺埌涓柇淇″彿
+                    }
+
+                    StationProtocol currentStation = findCurrentStationByTask(original.getTaskNo());
+                    if (currentStation == null) {
+                        if(System.currentTimeMillis() - runTime > 1000 * 60){
+                            break;
+                        }
+                        Thread.sleep(500);
+                        continue;
+                    }
+
+                    runTime = System.currentTimeMillis();
+                    if (!firstRun && currentStation.isRunBlock()) {
+                        break;
+                    }
+                    int currentIndex = path.indexOf(currentStation.getStationId());
+                    if (currentIndex < 0) {
+                        Thread.sleep(500);
+                        continue;
+                    }
+                    int remaining = total - currentIndex - 1;
+                    if (remaining <= 0) {
+                        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)));
+                        nextCmd.setOriginalNavigatePath(path);
+                        while (true) {
+                            CommandResponse commandResponse = sendCommand(nextCmd);
+                            if (commandResponse == null) {
+                                Thread.sleep(200);
+                                continue;
+                            }
+
+                            if (commandResponse.getResult()) {
+                                break;
+                            }
+
+                            Thread.sleep(200);
+                        }
+                    }
+                    Thread.sleep(500);
+                } catch (Exception e) {
+                    break;
+                }
+                firstRun = false;
+            }
+        }else {
+            sendCommand(original);
+        }
+    }
+
+    private StationProtocol 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;
+                    }
+                }
+            }
+        } catch (Exception e) {
+            return null;
+        }
+        return null;
+    }
+}

--
Gitblit v1.9.1