From 413b42a497ed1b695ceb0acada0122e553021ddb Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期四, 16 四月 2026 16:29:19 +0800
Subject: [PATCH] #仿真系统优化V3.0.0.2
---
src/main/java/com/zy/core/network/fake/ZyStationFakeSegConnect.java | 2000 ++++++++++++++++++++++++++++++++++++++++-----------------
1 files changed, 1,391 insertions(+), 609 deletions(-)
diff --git a/src/main/java/com/zy/core/network/fake/ZyStationFakeSegConnect.java b/src/main/java/com/zy/core/network/fake/ZyStationFakeSegConnect.java
index 097dc4d..64d731b 100644
--- a/src/main/java/com/zy/core/network/fake/ZyStationFakeSegConnect.java
+++ b/src/main/java/com/zy/core/network/fake/ZyStationFakeSegConnect.java
@@ -2,18 +2,13 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
-import com.core.common.SpringUtils;
-import com.zy.asrs.entity.BasDevp;
import com.zy.asrs.entity.DeviceConfig;
-import com.zy.asrs.service.BasDevpService;
-import com.zy.core.model.StationObjModel;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.enums.RedisKeyType;
import com.zy.core.enums.StationCommandType;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.command.StationCommand;
-import com.zy.core.model.protocol.StationTaskBufferItem;
import com.zy.core.network.api.ZyStationConnectApi;
import com.zy.core.network.entity.ZyStationStatusEntity;
@@ -23,21 +18,42 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import java.util.Random;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.atomic.AtomicInteger;
public class ZyStationFakeSegConnect implements ZyStationConnectApi {
- private static final long DEFAULT_FAKE_RUN_BLOCK_TIMEOUT_MS = 10000L;
- private static final long WAIT_SEGMENT_TIMEOUT_MS = 30000L;
+ private long getWaitSegmentTimeoutMs() {
+ return FakeConfigSupport.getLong(FakeConfigKeys.FAKE_STATION_SEGMENT_WAIT_TIMEOUT_MS, 30000L);
+ }
+
+ private long getMoveStepDurationMs() {
+ return FakeConfigSupport.getLong(FakeConfigKeys.FAKE_STATION_MOVE_STEP_DURATION_MS, 500L);
+ }
+
+ private long getIdleLoopDelayMs() {
+ return FakeConfigSupport.getLong(FakeConfigKeys.FAKE_STATION_IDLE_LOOP_DELAY_MS, 200L);
+ }
+
+ private long getBlockedLoopDelayMs() {
+ return FakeConfigSupport.getLong(FakeConfigKeys.FAKE_STATION_BLOCKED_LOOP_DELAY_MS, 1000L);
+ }
+
+ private long getInitializeDelayMs() {
+ return FakeConfigSupport.getLong(FakeConfigKeys.FAKE_STATION_INITIALIZE_DELAY_MS, 0L);
+ }
+
+ private long getFinishDelayMs() {
+ return FakeConfigSupport.getLong(FakeConfigKeys.FAKE_STATION_FINISH_DELAY_MS, 0L);
+ }
private static final String STATUS_WAITING = "WAITING";
private static final String STATUS_RUNNING = "RUNNING";
@@ -46,65 +62,66 @@
private static final String STATUS_TIMEOUT = "TIMEOUT";
private static final String STATUS_FINISHED = "FINISHED";
- private final Map<Integer, ReentrantLock> stationLocks = new ConcurrentHashMap<Integer, ReentrantLock>();
- private final Map<Integer, List<ZyStationStatusEntity>> deviceStatusMap = new ConcurrentHashMap<Integer, List<ZyStationStatusEntity>>();
- private final Map<Integer, DeviceConfig> deviceConfigMap = new ConcurrentHashMap<Integer, DeviceConfig>();
+ private static final String SEGMENT_MERGE_APPEND = "APPEND";
+ private static final String SEGMENT_MERGE_REPLACE_TARGET_CHANGED = "REPLACE_TARGET_CHANGED";
+ private static final String SEGMENT_MERGE_REPLACE_REROUTE = "REPLACE_REROUTE";
+ private static final String SEGMENT_MERGE_IGNORE_DISCONNECTED = "IGNORE_DISCONNECTED";
+ private static final String SEGMENT_MERGE_IGNORE_CURRENT_MISSING = "IGNORE_CURRENT_MISSING";
+
+ private final FakeStationStateManager stateManager = new FakeStationStateManager();
+ private final FakeStationMoveEngine moveEngine = new FakeStationMoveEngine(stateManager);
+ private final FakeStationBlockManager blockManager = new FakeStationBlockManager(stateManager);
+ private static final AtomicInteger DEVICE_EXECUTOR_THREAD_SEQ = new AtomicInteger(1);
+ private volatile ScheduledExecutorService loopScheduler = createLoopScheduler();
+ private RedisUtil redisUtil;
+ private final Map<Integer, ExecutorService> deviceExecutors = new ConcurrentHashMap<Integer, ExecutorService>();
+
private final Map<Integer, BlockingQueue<StationCommand>> taskQueues = new ConcurrentHashMap<Integer, BlockingQueue<StationCommand>>();
private final Map<Integer, Long> taskLastUpdateTime = new ConcurrentHashMap<Integer, Long>();
private final Map<Integer, Boolean> taskRunning = new ConcurrentHashMap<Integer, Boolean>();
- private final ExecutorService executor = Executors.newCachedThreadPool();
-
- private RedisUtil redisUtil;
+ private final Map<Integer, TaskRuntimeContext> taskContexts = new ConcurrentHashMap<Integer, TaskRuntimeContext>();
+ private final Map<Integer, AtomicInteger> taskLoopGenerations = new ConcurrentHashMap<Integer, AtomicInteger>();
+ private final Map<Integer, Object> taskLifecycleLocks = new ConcurrentHashMap<Integer, Object>();
+ private volatile Set<Integer> legalClearStationIds = new HashSet<Integer>();
+ private volatile Set<Integer> barcodeStationIds = new HashSet<Integer>();
public void addFakeConnect(DeviceConfig deviceConfig, RedisUtil redisUtil) {
this.redisUtil = redisUtil;
- if (deviceConfigMap.containsKey(deviceConfig.getDeviceNo())) {
- return;
- }
- deviceConfigMap.put(deviceConfig.getDeviceNo(), deviceConfig);
- deviceStatusMap.put(deviceConfig.getDeviceNo(), new CopyOnWriteArrayList<ZyStationStatusEntity>());
+ refreshLegalClearStationIds();
+ refreshBarcodeStationIds();
+ stateManager.registerDevice(deviceConfig);
}
@Override
public boolean connect() {
+ if (loopScheduler == null || loopScheduler.isShutdown() || loopScheduler.isTerminated()) {
+ loopScheduler = createLoopScheduler();
+ }
return true;
}
@Override
public boolean disconnect() {
- executor.shutdownNow();
+ ScheduledExecutorService scheduler = loopScheduler;
+ if (scheduler != null) {
+ scheduler.shutdownNow();
+ }
+ for (ExecutorService executor : deviceExecutors.values()) {
+ executor.shutdownNow();
+ }
+ deviceExecutors.clear();
+ taskQueues.clear();
+ taskLastUpdateTime.clear();
+ taskRunning.clear();
+ taskContexts.clear();
+ taskLoopGenerations.clear();
+ taskLifecycleLocks.clear();
return true;
}
@Override
public List<ZyStationStatusEntity> getStatus(Integer deviceNo) {
- List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo);
- if (statusList == null) {
- return new ArrayList<ZyStationStatusEntity>();
- }
-
- DeviceConfig deviceConfig = deviceConfigMap.get(deviceNo);
- if (statusList.isEmpty() && deviceConfig != null) {
- List<ZyStationStatusEntity> init = JSON.parseArray(deviceConfig.getFakeInitStatus(),
- ZyStationStatusEntity.class);
- if (init != null) {
- statusList.addAll(init);
- for (ZyStationStatusEntity status : statusList) {
- status.setAutoing(true);
- status.setLoading(false);
- status.setInEnable(true);
- status.setOutEnable(true);
- status.setEmptyMk(false);
- status.setFullPlt(false);
- status.setRunBlock(false);
- status.setPalletHeight(0);
- status.setError(0);
- status.setBarcode("");
- }
- }
- }
-
- return statusList;
+ return stateManager.getStatus(deviceNo);
}
@Override
@@ -115,25 +132,44 @@
}
if (command.getCommandType() != StationCommandType.MOVE) {
- handleCommand(deviceNo, command);
- return new CommandResponse(true, "鍛戒护宸插彈鐞嗭紙寮傛鎵ц锛�");
- }
-
- if (isDirectMoveCommand(command)) {
- handleDirectMoveCommand(deviceNo, command);
- return new CommandResponse(true, "鍛戒护宸插彈鐞嗭紙寮傛鎵ц锛�");
- }
-
- taskQueues.computeIfAbsent(taskNo, key -> new LinkedBlockingQueue<StationCommand>()).offer(command);
- taskLastUpdateTime.put(taskNo, System.currentTimeMillis());
-
- if (taskRunning.putIfAbsent(taskNo, true) == null) {
- executor.submit(new Runnable() {
+ News.info("[WCS Debug] fake sendCommand鏀跺埌闈濵OVE鍛戒护锛宒eviceNo={}锛宼askNo={}锛宻tationId={}锛宼argetStaNo={}锛宑ommandType={}",
+ deviceNo, taskNo, command.getStationId(), command.getTargetStaNo(), command.getCommandType());
+ getDeviceExecutor(deviceNo).submit(new Runnable() {
@Override
public void run() {
- runTaskLoop(deviceNo, taskNo);
+ handleCommand(deviceNo, command);
}
});
+ return new CommandResponse(true, "鍛戒护宸插彈鐞嗭紙寮傛鎵ц锛�");
+ }
+
+ int loopGeneration = 0;
+ boolean shouldSchedule = false;
+ Object lifecycleLock = getTaskLifecycleLock(taskNo);
+ synchronized (lifecycleLock) {
+ BlockingQueue<StationCommand> queue = taskQueues.computeIfAbsent(taskNo, key -> new LinkedBlockingQueue<StationCommand>());
+ queue.offer(command);
+ taskLastUpdateTime.put(taskNo, System.currentTimeMillis());
+ News.info("[WCS Debug] fake sendCommand鍏ラ槦锛宒eviceNo={}锛宼askNo={}锛宻tationId={}锛宼argetStaNo={}锛宻egmentNo={}锛宻egmentCount={}锛宷ueueSize={}锛宺unning={}",
+ deviceNo, taskNo, command.getStationId(), command.getTargetStaNo(), command.getSegmentNo(), command.getSegmentCount(),
+ queue.size(), taskRunning.containsKey(taskNo));
+
+ if (taskRunning.putIfAbsent(taskNo, true) == null) {
+ TaskRuntimeContext context = new TaskRuntimeContext(taskNo, deviceNo, stateManager.getThreadImpl(deviceNo));
+ taskContexts.put(taskNo, context);
+ AtomicInteger generation = taskLoopGenerations.computeIfAbsent(taskNo, key -> new AtomicInteger(0));
+ loopGeneration = generation.incrementAndGet();
+ context.loopGeneration = loopGeneration;
+ shouldSchedule = true;
+ News.info("[WCS Debug] fake task鍑嗗鍚姩鎵ц绾跨▼锛宒eviceNo={}锛宼askNo={}锛宷ueueSize={}锛宭oopGeneration={}",
+ deviceNo, taskNo, queue.size(), loopGeneration);
+ } else {
+ News.info("[WCS Debug] fake task澶嶇敤宸插瓨鍦ㄦ墽琛岀嚎绋嬶紝deviceNo={}锛宼askNo={}锛宷ueueSize={}",
+ deviceNo, taskNo, queue.size());
+ }
+ }
+ if (shouldSchedule) {
+ scheduleTaskLoop(deviceNo, taskNo, loopGeneration);
}
return new CommandResponse(true, "鍛戒护宸插彈鐞嗭紙寮傛鎵ц锛�");
@@ -146,31 +182,7 @@
@Override
public CommandResponse clearTaskBufferSlot(Integer deviceNo, Integer stationId, Integer slotIdx) {
- if (deviceNo == null || stationId == null || slotIdx == null || slotIdx <= 0) {
- return new CommandResponse(false, "娓呯悊缂撳瓨鍖烘Ы浣嶅弬鏁版棤鏁�");
- }
- List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo);
- if (statusList == null) {
- return new CommandResponse(false, "鏈壘鍒拌澶囩姸鎬�");
- }
- for (ZyStationStatusEntity status : statusList) {
- if (status == null || !stationId.equals(status.getStationId())) {
- continue;
- }
- List<StationTaskBufferItem> taskBufferItems = status.getTaskBufferItems();
- if (taskBufferItems == null || taskBufferItems.isEmpty()) {
- return new CommandResponse(true, "缂撳瓨鍖烘Ы浣嶅凡涓虹┖");
- }
- for (StationTaskBufferItem item : taskBufferItems) {
- if (item != null && slotIdx.equals(item.getSlotIdx())) {
- item.setTaskNo(0);
- item.setTargetStaNo(0);
- return new CommandResponse(true, "缂撳瓨鍖烘Ы浣嶆竻鐞嗘垚鍔�");
- }
- }
- return new CommandResponse(false, "鏈壘鍒扮紦瀛樺尯妲戒綅");
- }
- return new CommandResponse(false, "鏈壘鍒扮珯鐐圭姸鎬�");
+ return stateManager.clearTaskBufferSlot(deviceNo, stationId, slotIdx);
}
@Override
@@ -178,116 +190,209 @@
return new byte[0];
}
- private boolean isDirectMoveCommand(StationCommand command) {
- if (command == null || command.getCommandType() != StationCommandType.MOVE) {
- return false;
- }
- List<Integer> path = command.getNavigatePath();
- if (command.getStationId() == null || !command.getStationId().equals(command.getTargetStaNo())) {
- return false;
- }
- if (path == null || path.isEmpty()) {
- return true;
- }
- return path.size() == 1 && command.getStationId().equals(path.get(0));
+
+ private ScheduledExecutorService createLoopScheduler() {
+ return Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
+ @Override
+ public Thread newThread(Runnable runnable) {
+ Thread thread = new Thread(runnable, "fake-station-loop-scheduler");
+ thread.setDaemon(true);
+ return thread;
+ }
+ });
}
- private void handleDirectMoveCommand(Integer deviceNo, StationCommand command) {
- Integer taskNo = command.getTaskNo();
- Integer stationId = command.getStationId();
- Integer targetStationId = command.getTargetStaNo();
- if (taskNo != null && taskNo > 0 && taskNo != 9999 && taskNo != 9998 && stationId != null
- && stationId.equals(targetStationId)) {
- generateStationData(deviceNo, taskNo, stationId, targetStationId);
- }
-
- TaskRuntimeContext context = new TaskRuntimeContext(taskNo, getThreadImpl(deviceNo));
- context.startStationId = stationId;
- context.currentStationId = stationId;
- context.finalTargetStationId = targetStationId;
- context.initialized = true;
- context.status = STATUS_RUNNING;
- context.appendStitchedPath(Arrays.asList(stationId));
- context.addPassedStation(stationId);
- context.generateBarcode = checkTaskNoInArea(taskNo);
-
- traceEvent(deviceNo, context, "MOVE_INIT", "鍚岀珯鐐逛换鍔$洿鎺ュ埌浣�", buildDetails("stationId", stationId), false);
- if (context.generateBarcode) {
- generateStationBarcode(taskNo, stationId, deviceNo);
- }
- traceEvent(deviceNo, context, "ARRIVED", "浠诲姟宸插湪璧风偣绔欑偣瀹屾垚", buildDetails("barcodeGenerated",
- context.generateBarcode, "stationId", stationId), false);
- context.status = STATUS_FINISHED;
- traceEvent(deviceNo, context, "TASK_END", "浠诲姟鎵ц瀹屾垚", buildDetails("reason", STATUS_FINISHED), true);
+ private ExecutorService getDeviceExecutor(Integer deviceNo) {
+ return deviceExecutors.computeIfAbsent(deviceNo, key -> Executors.newSingleThreadExecutor(new ThreadFactory() {
+ @Override
+ public Thread newThread(Runnable runnable) {
+ Thread thread = new Thread(runnable,
+ "fake-station-device-" + key + "-" + DEVICE_EXECUTOR_THREAD_SEQ.getAndIncrement());
+ thread.setDaemon(true);
+ return thread;
+ }
+ }));
}
- private void runTaskLoop(Integer deviceNo, Integer taskNo) {
- TaskRuntimeContext context = new TaskRuntimeContext(taskNo, getThreadImpl(deviceNo));
- try {
- while (true) {
- if (Thread.currentThread().isInterrupted()) {
- if (!isTerminalStatus(context.status)) {
- context.status = STATUS_CANCELLED;
+ private void scheduleTaskLoop(Integer deviceNo, Integer taskNo, int loopGeneration) {
+ scheduleTaskLoop(deviceNo, taskNo, loopGeneration, 0L);
+ }
+
+ private void scheduleTaskLoop(Integer deviceNo, Integer taskNo, int loopGeneration, long delayMs) {
+ Runnable task = new Runnable() {
+ @Override
+ public void run() {
+ getDeviceExecutor(deviceNo).submit(new Runnable() {
+ @Override
+ public void run() {
+ runTaskLoop(deviceNo, taskNo, loopGeneration);
}
- break;
- }
+ });
+ }
+ };
+ if (delayMs <= 0L) {
+ task.run();
+ return;
+ }
+ loopScheduler.schedule(task, delayMs, TimeUnit.MILLISECONDS);
+ }
- if (hasTaskReset(taskNo)) {
+ private void scheduleTaskLoopByDelay(Integer deviceNo, Integer taskNo, int loopGeneration, long delayMs) {
+ scheduleTaskLoop(deviceNo, taskNo, loopGeneration, Math.max(delayMs, 1L));
+ }
+
+ private void runTaskLoop(Integer deviceNo, Integer taskNo, int loopGeneration) {
+ TaskRuntimeContext context = taskContexts.get(taskNo);
+ if (context == null) {
+ News.info("[WCS Debug] fake task蹇界暐鏃犱笂涓嬫枃缁窇鐗囨锛宒eviceNo={}锛宼askNo={}锛宭oopGeneration={}",
+ deviceNo, taskNo, loopGeneration);
+ return;
+ }
+ if (!deviceNo.equals(context.deviceNo)) {
+ News.info("[WCS Debug] fake task蹇界暐璺ㄨ澶囩画璺戠墖娈碉紝taskNo={}锛宔xpectedDeviceNo={}锛宎ctualDeviceNo={}锛宭oopGeneration={}",
+ taskNo, context.deviceNo, deviceNo, loopGeneration);
+ return;
+ }
+ if (context.loopGeneration != loopGeneration || !isCurrentLoopGeneration(taskNo, loopGeneration)) {
+ News.info("[WCS Debug] fake task蹇界暐杩囨湡缁窇鐗囨锛宒eviceNo={}锛宼askNo={}锛宔xpectedLoopGeneration={}锛宎ctualLoopGeneration={}",
+ deviceNo, taskNo, loopGeneration, context.loopGeneration);
+ return;
+ }
+ News.info("[WCS Debug] fake task杩涘叆runTaskLoop锛宒eviceNo={}锛宼askNo={}锛宼hreadImpl={}锛宷ueueExists={}锛宷ueueSize={}锛宭oopGeneration={}锛宻tatus={}锛宨nitialized={}锛宑urrentStationId={}锛宼argetStationId={}锛宐lockedStationId={}锛宲endingPath={}",
+ deviceNo, taskNo, context.threadImpl, taskQueues.containsKey(taskNo),
+ taskQueues.containsKey(taskNo) && taskQueues.get(taskNo) != null ? taskQueues.get(taskNo).size() : null, loopGeneration,
+ context.status, context.initialized, context.currentStationId, context.finalTargetStationId,
+ context.blockedStationId, context.getPendingStationIds());
+ long nextDelayMs = 0L;
+ boolean shouldContinue = false;
+ try {
+ if (Thread.currentThread().isInterrupted()) {
+ if (!isTerminalStatus(context.status)) {
context.status = STATUS_CANCELLED;
- break;
}
-
+ } else if (hasTaskReset(taskNo)) {
+ context.status = STATUS_CANCELLED;
+ } else {
BlockingQueue<StationCommand> commandQueue = taskQueues.get(taskNo);
if (commandQueue == null) {
- break;
- }
-
- StationCommand command = commandQueue.poll(100, TimeUnit.MILLISECONDS);
- if (command != null) {
- taskLastUpdateTime.put(taskNo, System.currentTimeMillis());
- context.lastCommandAt = System.currentTimeMillis();
- handleIncomingSegment(deviceNo, context, command);
- }
-
- if (!context.pendingPathQueue.isEmpty()) {
- if (!context.initialized || context.currentStationId == null) {
- initializeTaskPosition(deviceNo, context);
- continue;
+ context.status = STATUS_FINISHED;
+ } else {
+ StationCommand command = commandQueue.poll();
+ if (command != null) {
+ taskLastUpdateTime.put(taskNo, System.currentTimeMillis());
+ context.lastCommandAt = System.currentTimeMillis();
+ handleIncomingSegment(deviceNo, context, command);
}
- if (!executeNextMove(deviceNo, context)) {
- break;
+ if (!isTerminalStatus(context.status)) {
+ if (!context.pendingPathQueue.isEmpty()) {
+ News.info("[WCS Debug] fake task鍑嗗鎺ㄨ繘锛宒eviceNo={}锛宼askNo={}锛宨nitialized={}锛宑urrentStationId={}锛宼argetStationId={}锛宐lockedStationId={}锛宲endingPath={}",
+ deviceNo, taskNo, context.initialized, context.currentStationId,
+ context.finalTargetStationId, context.blockedStationId, context.getPendingStationIds());
+ if (!context.initialized || context.currentStationId == null) {
+ nextDelayMs = initializeTaskPosition(deviceNo, context);
+ } else {
+ MoveStepResult moveResult = executeNextMove(deviceNo, context);
+ if (!moveResult.shouldContinue()) {
+ context.status = STATUS_FINISHED;
+ }
+ nextDelayMs = moveResult.getNextDelayMs();
+ }
+ } else {
+ News.info("[WCS Debug] fake task杩涘叆绌洪棽鎬侊紝deviceNo={}锛宼askNo={}锛宻tatus={}锛宑urrentStationId={}锛宼argetStationId={}锛宐lockedStationId={}锛宲endingPath={}",
+ deviceNo, taskNo, context.status, context.currentStationId,
+ context.finalTargetStationId, context.blockedStationId, context.getPendingStationIds());
+ IdleStepResult idleResult = handleIdleState(deviceNo, context);
+ if (idleResult.isFinished() && !isTerminalStatus(context.status)) {
+ context.status = STATUS_FINISHED;
+ }
+ nextDelayMs = idleResult.getNextDelayMs();
+ }
}
- continue;
+ shouldContinue = !isTerminalStatus(context.status)
+ && taskQueues.containsKey(taskNo)
+ && (commandQueue != null);
}
+ }
+ } catch (Exception e) {
+ context.status = STATUS_CANCELLED;
+ if (e instanceof InterruptedException) {
+ Thread.currentThread().interrupt();
+ }
+ News.info("[WCS Debug] 浠诲姟{}鎵ц寮傚父锛屽綋鍓嶇珯鐐�={}锛岀洰鏍囩珯={}锛屽緟鎵ц璺緞={}锛屽紓甯哥被鍨�={}锛屽紓甯镐俊鎭�={}",
+ taskNo, context.currentStationId, context.finalTargetStationId, context.getPendingStationIds(),
+ e.getClass().getSimpleName(), e.getMessage());
+ }
- if (handleIdleState(deviceNo, context)) {
- break;
- }
+ if (shouldContinue) {
+ if (nextDelayMs > 0L) {
+ scheduleTaskLoopByDelay(deviceNo, taskNo, loopGeneration, nextDelayMs);
+ } else {
+ scheduleTaskLoop(deviceNo, taskNo, loopGeneration);
}
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- if (!isTerminalStatus(context.status)) {
- context.status = STATUS_CANCELLED;
+ return;
+ }
+ finishTaskLoop(deviceNo, taskNo, context, loopGeneration);
+ }
+
+ private void finishTaskLoop(Integer deviceNo, Integer taskNo, TaskRuntimeContext context, int loopGeneration) {
+ Object lifecycleLock = getTaskLifecycleLock(taskNo);
+ synchronized (lifecycleLock) {
+ if (context.loopGeneration != loopGeneration || !isCurrentLoopGeneration(taskNo, loopGeneration)) {
+ News.info("[WCS Debug] fake task蹇界暐杩囨湡缁撴潫娓呯悊锛宒eviceNo={}锛宼askNo={}锛宔xpectedLoopGeneration={}锛宎ctualLoopGeneration={}",
+ deviceNo, taskNo, loopGeneration, context.loopGeneration);
+ return;
}
- } finally {
+ BlockingQueue<StationCommand> queue = taskQueues.get(taskNo);
+ if (queue != null && !queue.isEmpty()) {
+ News.info("[WCS Debug] fake task缁撴潫娓呯悊鍓嶅彂鐜版柊鍛戒护锛屾仮澶嶇画璺戯紝deviceNo={}锛宼askNo={}锛宷ueueSize={}锛宭oopGeneration={}",
+ deviceNo, taskNo, queue.size(), loopGeneration);
+ scheduleTaskLoop(deviceNo, taskNo, loopGeneration);
+ return;
+ }
+ News.info("[WCS Debug] fake task鍗冲皢閫�鍑簉unTaskLoop锛宒eviceNo={}锛宼askNo={}锛宻tatus={}锛宷ueueSizeBeforeCleanup={}锛宭astCurrentStationId={}锛宼argetStationId={}锛宭oopGeneration={}",
+ deviceNo, taskNo, context.status, queue == null ? null : queue.size(), context.currentStationId, context.finalTargetStationId, loopGeneration);
taskQueues.remove(taskNo);
taskLastUpdateTime.remove(taskNo);
taskRunning.remove(taskNo);
-
- if (!isTerminalStatus(context.status)) {
- context.status = STATUS_FINISHED;
- }
- traceEvent(deviceNo, context, "TASK_END", "浠诲姟鎵ц缁撴潫骞舵竻鐞嗚祫婧�",
- buildDetails("reason", context.status), true);
- News.info("[WCS Debug] 浠诲姟{}鎵ц缁撴潫骞舵竻鐞嗚祫婧愶紝鐘舵��={}", taskNo, context.status);
+ taskContexts.remove(taskNo);
+ taskLoopGenerations.remove(taskNo);
+ taskLifecycleLocks.remove(taskNo, lifecycleLock);
}
+
+ if (!isTerminalStatus(context.status)) {
+ context.status = STATUS_FINISHED;
+ }
+ traceEvent(deviceNo, context, "TASK_END", "浠诲姟鎵ц缁撴潫骞舵竻鐞嗚祫婧�",
+ buildDetails("reason", context.status, "loopGeneration", loopGeneration), true);
+ News.info("[WCS Debug] 浠诲姟{}鎵ц缁撴潫骞舵竻鐞嗚祫婧愶紝鐘舵��={}锛宭oopGeneration={}", taskNo, context.status, loopGeneration);
}
private void handleIncomingSegment(Integer deviceNo, TaskRuntimeContext context, StationCommand command) {
+ if (!deviceNo.equals(context.deviceNo)) {
+ traceEvent(deviceNo, context, "SEGMENT_IGNORED", "璺緞鍒嗘鏉ヨ嚜涓嶅悓璁惧杞﹂亾锛屽凡蹇界暐",
+ buildDetails("expectedDeviceNo", context.deviceNo, "actualDeviceNo", deviceNo,
+ "segmentNo", command.getSegmentNo(), "segmentCount", command.getSegmentCount()), false);
+ return;
+ }
List<Integer> newPath = normalizePath(command.getNavigatePath());
Integer lastInQueue = getLastInQueue(context.pendingPathQueue);
int startIndex = getPathAppendStartIndex(newPath, context.currentStationId, lastInQueue);
+ Integer previousTargetStationId = context.finalTargetStationId;
+ Integer commandTargetStationId = command.getTargetStaNo();
+ boolean targetChanged = commandTargetStationId != null
+ && !commandTargetStationId.equals(previousTargetStationId);
+ boolean queueEmpty = context.pendingPathQueue.isEmpty();
+ boolean newPathContainsCurrent = context.currentStationId != null && newPath.contains(context.currentStationId);
+ boolean pathConnectedToTail = startIndex >= 0;
+ List<Integer> oldPendingStations = context.getPendingStationIds();
+ boolean shouldClearBarcodeSourceOnReroute = context.currentStationId != null
+ && context.currentStationId.equals(command.getStationId())
+ && isBarcodeStation(context.currentStationId)
+ && previousTargetStationId != null
+ && previousTargetStationId.equals(context.currentStationId)
+ && commandTargetStationId != null
+ && !commandTargetStationId.equals(context.currentStationId);
context.setStartStationIdIfAbsent(command.getStationId());
if (!context.generateBarcode && checkTaskNoInArea(context.taskNo)) {
@@ -297,15 +402,15 @@
traceEvent(deviceNo, context, "SEGMENT_RECEIVED", "鏀跺埌鏂扮殑璺緞鍒嗘鍛戒护",
buildDetails("segmentPath", newPath, "appendStartIndex", startIndex, "currentStationId",
context.currentStationId, "queueTailStationId", lastInQueue, "commandStationId",
- command.getStationId(), "commandTargetStationId", command.getTargetStaNo()),
+ command.getStationId(), "commandTargetStationId", commandTargetStationId,
+ "previousTargetStationId", previousTargetStationId),
false);
- Integer commandTargetStationId = command.getTargetStaNo();
if (commandTargetStationId != null) {
- if (!commandTargetStationId.equals(context.finalTargetStationId)) {
+ if (targetChanged) {
traceEvent(deviceNo, context, "TARGET_SWITCHED",
- "浠诲姟鐩爣绔欏彂鐢熷垏鎹�: " + context.finalTargetStationId + " -> " + commandTargetStationId,
- buildDetails("fromTargetStationId", context.finalTargetStationId, "toTargetStationId",
+ "浠诲姟鐩爣绔欏彂鐢熷垏鎹�: " + previousTargetStationId + " -> " + commandTargetStationId,
+ buildDetails("fromTargetStationId", previousTargetStationId, "toTargetStationId",
commandTargetStationId),
false);
context.arrivalHandled = false;
@@ -313,50 +418,140 @@
context.finalTargetStationId = commandTargetStationId;
syncCurrentStationTarget(context.taskNo, context.currentStationId, context.finalTargetStationId);
}
+ context.segmentNo = command.getSegmentNo();
+ context.segmentCount = command.getSegmentCount();
- if (!newPath.isEmpty() && startIndex < 0) {
- traceEvent(deviceNo, context, "SEGMENT_IGNORED", "璺緞鍒嗘鏃犳硶涓庡綋鍓嶈繍琛屼笂涓嬫枃琛旀帴锛屽凡蹇界暐",
- buildDetails("segmentPath", newPath, "currentStationId", context.currentStationId,
- "queueTailStationId", lastInQueue, "ignoreReason", "PATH_NOT_CONNECTED"),
- false);
- context.latestAppendedPath.clear();
- return;
+ boolean tailConnectedAppend = !queueEmpty && pathConnectedToTail;
+ boolean shouldReplace = !tailConnectedAppend && !queueEmpty
+ && (targetChanged || (!pathConnectedToTail && newPathContainsCurrent));
+ String ignoreReason = null;
+ if (!shouldReplace && !tailConnectedAppend && !newPath.isEmpty() && !pathConnectedToTail) {
+ ignoreReason = newPathContainsCurrent ? SEGMENT_MERGE_IGNORE_DISCONNECTED : SEGMENT_MERGE_IGNORE_CURRENT_MISSING;
+ if (queueEmpty && context.currentStationId == null) {
+ startIndex = 0;
+ } else {
+ traceEvent(deviceNo, context, "SEGMENT_IGNORED", "璺緞鍒嗘鏃犳硶鎺ュ叆褰撳墠杩愯涓婁笅鏂囷紝宸插拷鐣�",
+ buildDetails("segmentPath", newPath, "currentStationId", context.currentStationId,
+ "queueTailStationId", lastInQueue, "ignoreReason", ignoreReason,
+ "queueEmpty", queueEmpty, "tailConnectedAppend", tailConnectedAppend,
+ "targetChanged", targetChanged),
+ false);
+ context.latestAppendedPath.clear();
+ return;
+ }
+ }
+
+ if (tailConnectedAppend && startIndex < 0) {
+ startIndex = 0;
}
List<Integer> appendedPath = new ArrayList<Integer>();
- for (int i = startIndex; i < newPath.size(); i++) {
- Integer stationId = newPath.get(i);
- context.pendingPathQueue.offer(stationId);
- appendedPath.add(stationId);
- }
- context.appendStitchedPath(appendedPath);
-
- if (!appendedPath.isEmpty()) {
+ List<Integer> replacedFuturePath = new ArrayList<Integer>();
+ Integer duplicateHeadStationId = null;
+ String mergeMode = SEGMENT_MERGE_APPEND;
+ if (shouldReplace) {
+ replacedFuturePath = rebuildPendingPathFromCurrent(context, newPath);
+ boolean atTargetAlready = context.currentStationId != null && context.currentStationId.equals(commandTargetStationId);
+ if (context.currentStationId != null && replacedFuturePath.isEmpty() && !atTargetAlready) {
+ traceEvent(deviceNo, context, "SEGMENT_IGNORED", "璺緞鍒嗘鏃犳硶鎺ュ叆褰撳墠杩愯涓婁笅鏂囷紝宸插拷鐣�",
+ buildDetails("segmentPath", newPath, "currentStationId", context.currentStationId,
+ "queueTailStationId", lastInQueue, "ignoreReason", SEGMENT_MERGE_IGNORE_CURRENT_MISSING),
+ false);
+ context.latestAppendedPath.clear();
+ return;
+ }
+ replacePendingPathQueue(context, replacedFuturePath);
+ context.replaceLatestPath(replacedFuturePath);
+ mergeMode = targetChanged ? SEGMENT_MERGE_REPLACE_TARGET_CHANGED : SEGMENT_MERGE_REPLACE_REROUTE;
+ traceEvent(deviceNo, context, "SEGMENT_REPLACED",
+ "鏂扮殑 reroute 璺緞宸茶鐩栨棫 future queue",
+ buildDetails("mergeMode", mergeMode, "currentStationId", context.currentStationId,
+ "previousTargetStationId", previousTargetStationId, "newTargetStationId", commandTargetStationId,
+ "oldQueue", oldPendingStations, "replacedFuturePath", replacedFuturePath,
+ "queueSize", context.pendingPathQueue.size()),
+ false);
+ } else {
+ for (int i = startIndex; i < newPath.size(); i++) {
+ Integer stationId = newPath.get(i);
+ context.pendingPathQueue.offer(stationId);
+ appendedPath.add(stationId);
+ }
+ if (context.currentStationId != null && context.currentStationId.equals(context.pendingPathQueue.peek())) {
+ duplicateHeadStationId = context.pendingPathQueue.poll();
+ if (!appendedPath.isEmpty() && duplicateHeadStationId.equals(appendedPath.get(0))) {
+ appendedPath.remove(0);
+ }
+ }
+ context.appendStitchedPath(appendedPath);
traceEvent(deviceNo, context, "SEGMENT_APPENDED",
"璺緞鍒嗘宸茶拷鍔犲埌寰呮墽琛岄槦鍒楋紝闃熷垪闀垮害=" + context.pendingPathQueue.size(),
- buildDetails("segmentPath", newPath, "appendedPath", appendedPath, "appendStartIndex",
- startIndex, "queueSize", context.pendingPathQueue.size()),
+ buildDetails("mergeMode", mergeMode, "segmentPath", newPath, "appendedPath", appendedPath,
+ "appendStartIndex", startIndex, "queueSize", context.pendingPathQueue.size(),
+ "tailConnectedAppend", tailConnectedAppend, "targetChanged", targetChanged,
+ "duplicateHeadStationId", duplicateHeadStationId),
false);
+ }
+
+ if (duplicateHeadStationId != null) {
+ traceEvent(deviceNo, context, "SEGMENT_TRIMMED", "寰呮墽琛岄槦鍒楀ご閮ㄩ噸澶嶅綋鍓嶇珯鐐癸紝宸茬Щ闄�",
+ buildDetails("currentStationId", context.currentStationId,
+ "duplicateHeadStationId", duplicateHeadStationId,
+ "queueSize", context.pendingPathQueue.size(),
+ "remainingPendingPath", context.getPendingStationIds()),
+ false);
+ }
+
+ if (context.currentStationId != null && context.currentStationId.equals(context.pendingPathQueue.peek())) {
+ Integer trimmedHead = context.pendingPathQueue.poll();
+ traceEvent(deviceNo, context, "SEGMENT_TRIMMED", "寰呮墽琛岄槦鍒楀ご閮ㄤ粛涓庡綋鍓嶇珯鐐归噸澶嶏紝宸插啀娆$Щ闄�",
+ buildDetails("currentStationId", context.currentStationId,
+ "duplicateHeadStationId", trimmedHead,
+ "queueSize", context.pendingPathQueue.size(),
+ "remainingPendingPath", context.getPendingStationIds()),
+ false);
+ }
+
+ context.lastCommandAt = System.currentTimeMillis();
+
+ boolean segmentAccepted = !appendedPath.isEmpty() || !replacedFuturePath.isEmpty()
+ || (context.currentStationId != null && context.currentStationId.equals(commandTargetStationId))
+ || (context.currentStationId != null && context.currentStationId.equals(command.getStationId())
+ && commandTargetStationId != null && commandTargetStationId.equals(context.finalTargetStationId));
+ if (segmentAccepted) {
+ if (shouldClearBarcodeSourceOnReroute && context.currentStationId != null) {
+ Integer currentDeviceNo = stateManager.getDeviceNoByStationId(context.currentStationId);
+ if (currentDeviceNo != null) {
+ guardedClearStationForDispatch(currentDeviceNo, context.currentStationId, context.taskNo, "barcodeSourceRerouteAccepted");
+ traceEvent(deviceNo, context, "SOURCE_STATION_CLEARED", "鏉$爜婧愮珯宸插畬鎴愪换鍔′氦鎺ワ紝婧愮珯鐘舵�佸凡娓呴櫎",
+ buildDetails("stationId", context.currentStationId,
+ "previousTargetStationId", previousTargetStationId,
+ "newTargetStationId", commandTargetStationId,
+ "mergeMode", mergeMode),
+ false);
+ }
+ }
+ resumeFromCurrentStation(deviceNo, context, mergeMode, appendedPath, replacedFuturePath,
+ shouldClearBarcodeSourceOnReroute);
}
}
- private void initializeTaskPosition(Integer deviceNo, TaskRuntimeContext context) {
+ private long initializeTaskPosition(Integer deviceNo, TaskRuntimeContext context) {
Integer nextStationId = context.pendingPathQueue.peek();
if (nextStationId == null) {
- return;
+ return 0L;
}
if (context.currentStationId == null) {
- Integer actualCurrentStationId = findCurrentStationIdByTask(context.taskNo);
+ Integer actualCurrentStationId = stateManager.findCurrentStationIdByTask(context.taskNo);
if (actualCurrentStationId != null) {
context.currentStationId = actualCurrentStationId;
context.initialized = true;
context.status = STATUS_RUNNING;
context.blockedStationId = null;
- Integer actualDeviceNo = getDeviceNoByStationId(actualCurrentStationId);
+ Integer actualDeviceNo = stateManager.getDeviceNoByStationId(actualCurrentStationId);
if (actualDeviceNo != null) {
- clearRunBlock(actualCurrentStationId, actualDeviceNo);
+ guardedClearRunBlock(context.taskNo, actualCurrentStationId, actualDeviceNo);
}
trimPendingPathToCurrent(context.pendingPathQueue, actualCurrentStationId);
@@ -366,24 +561,26 @@
context.addPassedStation(actualCurrentStationId);
context.lastStepAt = System.currentTimeMillis();
+ context.lastProgressAt = context.lastStepAt;
+ context.lastProgressStationId = context.currentStationId;
+ guardedPublishTaskLocation(context.taskNo, actualDeviceNo, actualCurrentStationId, true, false);
traceEvent(deviceNo, context, "MOVE_INIT", "浠诲姟浠庡綋鍓嶅疄闄呯珯鐐规仮澶嶆墽琛�",
buildDetails("stationId", actualCurrentStationId, "recovered", true), false);
- return;
+ return 0L;
}
}
context.currentStationId = nextStationId;
- Integer currentDeviceNo = getDeviceNoByStationId(context.currentStationId);
+ Integer currentDeviceNo = stateManager.getDeviceNoByStationId(context.currentStationId);
if (currentDeviceNo == null) {
context.pendingPathQueue.poll();
- return;
+ return 0L;
}
- boolean result = initStationMove(context.taskNo, context.currentStationId, currentDeviceNo, context.taskNo,
+ boolean result = moveEngine.initStationMove(context.taskNo, context.currentStationId, currentDeviceNo, context.taskNo,
context.finalTargetStationId, true, null);
if (!result) {
- sleep(200);
- return;
+ return getIdleLoopDelayMs();
}
context.initialized = true;
@@ -391,25 +588,28 @@
context.pendingPathQueue.poll();
context.addPassedStation(context.currentStationId);
context.lastStepAt = System.currentTimeMillis();
+ context.lastProgressAt = context.lastStepAt;
+ context.lastProgressStationId = context.currentStationId;
+ guardedPublishTaskLocation(context.taskNo, currentDeviceNo, context.currentStationId, true, false);
traceEvent(deviceNo, context, "MOVE_INIT", "浠诲姟鍒濆鍖栬捣鐐圭珯鐐�",
buildDetails("stationId", context.currentStationId, "recovered", false), false);
- sleep(500);
+ return Math.max(getInitializeDelayMs(), getMoveStepDurationMs());
}
- private boolean executeNextMove(Integer deviceNo, TaskRuntimeContext context) {
+ private MoveStepResult executeNextMove(Integer deviceNo, TaskRuntimeContext context) {
Integer nextStationId = context.pendingPathQueue.peek();
if (nextStationId == null || context.currentStationId == null) {
- return true;
+ return MoveStepResult.continueNow();
}
- Integer currentDeviceNo = getDeviceNoByStationId(context.currentStationId);
- Integer nextDeviceNo = getDeviceNoByStationId(nextStationId);
+ Integer currentDeviceNo = stateManager.getDeviceNoByStationId(context.currentStationId);
+ Integer nextDeviceNo = stateManager.getDeviceNoByStationId(nextStationId);
if (currentDeviceNo == null || nextDeviceNo == null) {
context.pendingPathQueue.poll();
- return true;
+ return MoveStepResult.continueNow();
}
- boolean moveSuccess = stationMoveToNext(context.taskNo, context.currentStationId, currentDeviceNo,
+ boolean moveSuccess = moveEngine.stationMoveToNext(context.taskNo, context.currentStationId, currentDeviceNo,
nextStationId, nextDeviceNo, context.taskNo, context.finalTargetStationId);
if (moveSuccess) {
Integer previousStationId = context.currentStationId;
@@ -420,64 +620,174 @@
context.blockedStationId = null;
context.status = STATUS_RUNNING;
context.lastStepAt = System.currentTimeMillis();
+ context.lastProgressAt = context.lastStepAt;
+ context.lastProgressStationId = context.currentStationId;
+ blockManager.clearBlocked(previousStationId);
+ blockManager.clearBlocked(nextStationId);
traceEvent(deviceNo, context, "MOVE_STEP_OK", "浠诲姟瀹屾垚涓�姝ョ珯鐐圭Щ鍔�",
buildDetails("fromStationId", previousStationId, "toStationId", nextStationId,
"remainingPendingPath", context.getPendingStationIds()),
false);
- sleep(1000);
- return true;
+ return MoveStepResult.continueAfter(getBlockedLoopDelayMs());
}
- if (!checkTaskNoInArea(context.taskNo) && getFakeAllowCheckBlock()
- && !isSpecialStation(context.currentStationId)
- && System.currentTimeMillis() - context.lastStepAt > getFakeRunBlockTimeoutMs()) {
- boolean blocked = runBlockStation(context.taskNo, context.currentStationId, currentDeviceNo, context.taskNo,
+ long now = System.currentTimeMillis();
+ boolean sameStationNoProgress = context.currentStationId != null
+ && context.currentStationId.equals(context.lastProgressStationId);
+ long timeoutMs = blockManager.getFakeRunBlockTimeoutMs(redisUtil);
+ long dwellMs = now - context.lastProgressAt;
+ if (!checkTaskNoInArea(context.taskNo) && blockManager.getFakeAllowCheckBlock(redisUtil)
+ && !blockManager.isSpecialStation(context.currentStationId)
+ && !blockManager.isBlocked(context.currentStationId)
+ && sameStationNoProgress
+ && dwellMs > timeoutMs) {
+ List<Integer> clearedPendingPath = context.getPendingStationIds();
+ News.info("[WCS Debug] fake task娓呯┖寰呮墽琛岃矾寰勶紝鍘熷洜=RUN_BLOCKED锛宒eviceNo={}锛宼askNo={}锛宑urrentStationId={}锛宼argetStationId={}锛宐lockedStationId={}锛宲endingBeforeClear={}",
+ deviceNo, context.taskNo, context.currentStationId, context.finalTargetStationId,
+ context.blockedStationId, clearedPendingPath);
+ context.clearPendingPathWithLog(deviceNo, context.taskNo, context.currentStationId,
+ context.finalTargetStationId, context.blockedStationId, "RUN_BLOCKED");
+ guardedRunBlockStation(context.taskNo, context.currentStationId, currentDeviceNo, context.taskNo,
context.currentStationId);
- if (blocked) {
- context.blockedStationId = context.currentStationId;
- context.status = STATUS_BLOCKED;
- context.pendingPathQueue.clear();
- traceEvent(deviceNo, context, "RUN_BLOCKED", "浠诲姟鍦ㄥ綋鍓嶇珯鐐硅鏍囪涓哄牭濉�",
- buildDetails("blockedStationId", context.currentStationId), false);
- return false;
- }
+ context.blockedStationId = context.currentStationId;
+ context.status = STATUS_BLOCKED;
+ traceEvent(deviceNo, context, "RUN_BLOCKED", "浠诲姟鍦ㄥ綋鍓嶇珯鐐瑰仠鐣欒秴鏃讹紝琚爣璁颁负鍫靛锛屽緟鎵ц璺緞宸叉竻绌�",
+ buildDetails("blockedStationId", context.currentStationId,
+ "lastProgressStationId", context.lastProgressStationId,
+ "dwellMs", dwellMs,
+ "timeoutMs", timeoutMs,
+ "clearedPendingPath", clearedPendingPath), false);
+ return MoveStepResult.continueAfter(getMoveStepDurationMs());
}
- sleep(500);
- return true;
+ context.status = STATUS_WAITING;
+ traceEvent(deviceNo, context, "MOVE_STEP_WAIT", "褰撳墠绔欏凡鏇存柊鐩爣浣嗗皻鏈畬鎴愯惤绔欙紝淇濇寔褰撳墠浣嶇疆绛夊緟涓嬩竴娆℃帹杩�",
+ buildDetails("currentStationId", context.currentStationId,
+ "nextStationId", nextStationId,
+ "targetStationId", context.finalTargetStationId,
+ "blockedStationId", context.blockedStationId,
+ "pendingPath", context.getPendingStationIds()), false);
+ return MoveStepResult.continueAfter(500L);
}
- private boolean handleIdleState(Integer deviceNo, TaskRuntimeContext context) {
+ private void resumeFromCurrentStation(Integer deviceNo, TaskRuntimeContext context, String mergeMode,
+ List<Integer> appendedPath, List<Integer> replacedFuturePath, boolean sourceCleared) {
+ if (context.currentStationId != null) {
+ Integer currentDeviceNo = stateManager.getDeviceNoByStationId(context.currentStationId);
+ if (currentDeviceNo != null) {
+ guardedClearRunBlock(context.taskNo, context.currentStationId, currentDeviceNo);
+ guardedPublishTaskLocation(context.taskNo, currentDeviceNo, context.currentStationId, true, false);
+ }
+ }
+ context.blockedStationId = null;
+ context.status = STATUS_RUNNING;
+ context.lastProgressAt = System.currentTimeMillis();
+ context.lastProgressStationId = context.currentStationId;
+ traceEvent(deviceNo, context, "BLOCK_RESET", "鏀跺埌鏂扮殑璺緞鍒嗘锛屽凡娓呴櫎鍫靛骞堕噸鏂拌鏃�",
+ buildDetails("mergeMode", mergeMode, "currentStationId", context.currentStationId,
+ "targetStationId", context.finalTargetStationId, "queueSize", context.pendingPathQueue.size(),
+ "appendedPath", appendedPath, "replacedFuturePath", replacedFuturePath,
+ "sourceCleared", sourceCleared),
+ false);
+ }
+
+ private boolean shouldAdvanceFromCurrentState(TaskRuntimeContext context) {
+ return context != null
+ && context.initialized
+ && context.currentStationId != null
+ && !context.pendingPathQueue.isEmpty()
+ && !STATUS_BLOCKED.equals(context.status)
+ && !STATUS_CANCELLED.equals(context.status)
+ && !STATUS_TIMEOUT.equals(context.status)
+ && !STATUS_FINISHED.equals(context.status);
+ }
+
+ private IdleStepResult handleIdleState(Integer deviceNo, TaskRuntimeContext context) {
+ if (shouldAdvanceFromCurrentState(context)) {
+ traceEvent(deviceNo, context, "IDLE_RESUME", "褰撳墠绔欑偣瀛樺湪鏈畬鎴愯矾寰勶紝绔嬪嵆浠庡綋鍓嶇珯鎭㈠鎺ㄨ繘",
+ buildDetails("currentStationId", context.currentStationId,
+ "targetStationId", context.finalTargetStationId,
+ "pendingPath", context.getPendingStationIds()), false);
+ context.status = STATUS_RUNNING;
+ return IdleStepResult.waitNext(1L);
+ }
+
if (context.currentStationId != null && context.finalTargetStationId != null
&& context.currentStationId.equals(context.finalTargetStationId)) {
if (!context.arrivalHandled) {
boolean barcodeGenerated = false;
if (context.generateBarcode) {
- Integer targetDeviceNo = getDeviceNoByStationId(context.finalTargetStationId);
+ Integer targetDeviceNo = stateManager.getDeviceNoByStationId(context.finalTargetStationId);
if (targetDeviceNo != null) {
- barcodeGenerated = generateStationBarcode(context.taskNo, context.finalTargetStationId,
+ barcodeGenerated = guardedGenerateStationBarcode(context.taskNo, context.finalTargetStationId,
targetDeviceNo);
}
}
context.arrivalHandled = true;
+ context.lastProgressAt = System.currentTimeMillis();
+ context.lastProgressStationId = context.currentStationId;
traceEvent(deviceNo, context, "ARRIVED", "浠诲姟鍒拌揪鏈�缁堢洰鏍囩珯鐐�",
buildDetails("stationId", context.currentStationId, "barcodeGenerated", barcodeGenerated),
false);
}
- context.status = STATUS_FINISHED;
- return true;
+
+ Integer targetDeviceNo = stateManager.getDeviceNoByStationId(context.finalTargetStationId);
+ if (targetDeviceNo != null) {
+ boolean ownerConflict = stateManager.isFinalStationOwnerConflict(targetDeviceNo, context.finalTargetStationId,
+ context.taskNo);
+ if (ownerConflict) {
+ logFinalStationOwnershipLost(deviceNo, context);
+ context.status = STATUS_BLOCKED;
+ return IdleStepResult.waitNext(getMoveStepDurationMs());
+ }
+ boolean stationCleared = stateManager.isStationClearedForTask(targetDeviceNo, context.finalTargetStationId,
+ context.taskNo);
+ boolean crnTaken = isCrnTakenByTask(context.taskNo);
+ if (stationCleared || crnTaken) {
+ context.status = STATUS_FINISHED;
+ traceEvent(deviceNo, context, "TASK_COMPLETE", "鍫嗗灈鏈哄凡鍙栬蛋璐х墿锛屼换鍔″畬鎴�",
+ buildDetails("stationId", context.finalTargetStationId, "stationCleared", stationCleared, "crnTaken", crnTaken), false);
+ return IdleStepResult.finish();
+ }
+ }
+ if (targetDeviceNo != null && !guardedArrivalCompletion(targetDeviceNo, context)) {
+ context.status = STATUS_BLOCKED;
+ return IdleStepResult.waitNext(getMoveStepDurationMs());
+ }
+
+ long dwellMs = System.currentTimeMillis() - context.lastProgressAt;
+ long timeoutMs = blockManager.getFakeRunBlockTimeoutMs(redisUtil);
+ if (!checkTaskNoInArea(context.taskNo) && blockManager.getFakeAllowCheckBlock(redisUtil)
+ && !blockManager.isSpecialStation(context.currentStationId)
+ && !blockManager.isBlocked(context.currentStationId)
+ && dwellMs > timeoutMs) {
+ context.status = STATUS_BLOCKED;
+ context.clearPendingPathWithLog(deviceNo, context.taskNo, context.currentStationId,
+ context.finalTargetStationId, context.blockedStationId, "TARGET_RUN_BLOCKED");
+ guardedRunBlockStation(context.taskNo, context.currentStationId, targetDeviceNo, context.taskNo,
+ context.currentStationId);
+ context.blockedStationId = context.currentStationId;
+ traceEvent(deviceNo, context, "RUN_BLOCKED", "浠诲姟鍒拌揪缁堢偣绔欏悗鍋滅暀瓒呮椂锛岃鏍囪涓哄牭濉烇紝绛夊緟鍫嗗灈鏈哄彇璐�",
+ buildDetails("blockedStationId", context.currentStationId,
+ "lastProgressStationId", context.lastProgressStationId,
+ "dwellMs", dwellMs,
+ "timeoutMs", timeoutMs), false);
+ return IdleStepResult.waitNext(getMoveStepDurationMs());
+ }
+
+ return IdleStepResult.waitNext(getFinishDelayMs());
}
Long lastTime = taskLastUpdateTime.get(context.taskNo);
- if (lastTime != null && System.currentTimeMillis() - lastTime > WAIT_SEGMENT_TIMEOUT_MS) {
- context.status = STATUS_TIMEOUT;
+ long waitSegmentTimeoutMs = getWaitSegmentTimeoutMs();
+ if (lastTime != null && System.currentTimeMillis() - lastTime > waitSegmentTimeoutMs) {
traceEvent(deviceNo, context, "WAIT_TIMEOUT", "绛夊緟鏂扮殑璺緞鍒嗘瓒呮椂",
- buildDetails("timeoutMs", WAIT_SEGMENT_TIMEOUT_MS, "currentStationId", context.currentStationId,
+ buildDetails("timeoutMs", waitSegmentTimeoutMs, "currentStationId", context.currentStationId,
"targetStationId", context.finalTargetStationId),
false);
- return true;
+ taskLastUpdateTime.put(context.taskNo, System.currentTimeMillis());
}
- return false;
+ return IdleStepResult.waitNext(getIdleLoopDelayMs());
}
private List<Integer> normalizePath(List<Integer> path) {
@@ -507,12 +817,40 @@
}
}
- private boolean hasTaskReset(Integer taskNo) {
- if (redisUtil == null || taskNo == null) {
- return false;
+ private List<Integer> rebuildPendingPathFromCurrent(TaskRuntimeContext context, List<Integer> newPath) {
+ List<Integer> rebuilt = new ArrayList<Integer>();
+ if (newPath == null || newPath.isEmpty()) {
+ return rebuilt;
}
- Object cancel = redisUtil.get(RedisKeyType.DEVICE_STATION_MOVE_RESET.key + taskNo);
- return cancel != null;
+ Integer currentStationId = context.currentStationId;
+ int startIndex = 0;
+ if (currentStationId != null) {
+ int currentIndex = newPath.indexOf(currentStationId);
+ if (currentIndex < 0) {
+ return rebuilt;
+ }
+ startIndex = currentIndex + 1;
+ }
+ for (int i = startIndex; i < newPath.size(); i++) {
+ rebuilt.add(newPath.get(i));
+ }
+ return rebuilt;
+ }
+
+ private void replacePendingPathQueue(TaskRuntimeContext context, List<Integer> futurePath) {
+ context.pendingPathQueue.clear();
+ if (futurePath == null) {
+ return;
+ }
+ for (Integer stationId : futurePath) {
+ context.pendingPathQueue.offer(stationId);
+ }
+ }
+
+ private boolean hasTaskReset(Integer taskNo) {
+ // 浠跨湡绯荤粺涓嶅搷搴斿閮ㄥ彇娑堜俊鍙凤紙濡傚牭濉為噸璺敱瑙﹀彂鐨� signalSegmentReset锛夛紝
+ // 閬垮厤浠诲姟鍦ㄧ珯鐐硅璧拌繃绋嬩腑琚剰澶栨竻闄�
+ return false;
}
private Integer getLastInQueue(LinkedBlockingQueue<Integer> queue) {
@@ -554,403 +892,715 @@
if (currentStationId == null || targetStationId == null) {
return;
}
- Integer currentDeviceNo = getDeviceNoByStationId(currentStationId);
+ Integer currentDeviceNo = stateManager.getDeviceNoByStationId(currentStationId);
if (currentDeviceNo == null) {
return;
}
- lockStations(currentStationId);
+ moveEngine.lockStations(currentStationId);
try {
- List<ZyStationStatusEntity> statusList = deviceStatusMap.get(currentDeviceNo);
- if (statusList == null) {
- return;
- }
-
- ZyStationStatusEntity currentStatus = statusList.stream()
- .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null);
+ ZyStationStatusEntity currentStatus = stateManager.findStationStatus(currentDeviceNo, currentStationId);
if (currentStatus == null) {
return;
}
- if (currentStatus.getTaskNo() != null && currentStatus.getTaskNo() > 0
- && !currentStatus.getTaskNo().equals(taskNo) && currentStatus.isLoading()) {
+ if (hasOwnerConflict(currentStatus, taskNo)) {
+ logOwnerConflict("syncCurrentStationTarget", currentStationId, currentStatus, taskNo, targetStationId, false,
+ "owner_conflict");
return;
}
- updateStationDataInternal(currentStationId, currentDeviceNo, taskNo, targetStationId, null, null, null);
+ stateManager.updateStationDataInternal(currentStationId, currentDeviceNo, taskNo, targetStationId, null, null, null);
} finally {
- unlockStations(currentStationId);
+ moveEngine.unlockStations(currentStationId);
}
}
- @SuppressWarnings("unchecked")
- private boolean getFakeAllowCheckBlock() {
- boolean fakeAllowCheckBlock = true;
- Object systemConfigMapObj = redisUtil == null ? null : redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key);
- if (systemConfigMapObj instanceof Map) {
- Map<String, String> systemConfigMap = (Map<String, String>) systemConfigMapObj;
- String value = systemConfigMap.get("fakeAllowCheckBlock");
- if (value != null && !"Y".equals(value)) {
- fakeAllowCheckBlock = false;
- }
- }
- return fakeAllowCheckBlock;
+ private boolean hasOwnerConflict(ZyStationStatusEntity currentStatus, Integer incomingTaskNo) {
+ return currentStatus != null
+ && currentStatus.isLoading()
+ && currentStatus.getTaskNo() != null
+ && currentStatus.getTaskNo() > 0
+ && (incomingTaskNo == null || !currentStatus.getTaskNo().equals(incomingTaskNo));
}
- private boolean isSpecialStation(Integer stationId) {
+ private void logOwnerConflict(String operation, Integer stationId, ZyStationStatusEntity currentStatus,
+ Integer incomingTaskNo, Integer incomingTargetStationId, boolean finalStation, String reason) {
+ News.info("[WCS Debug] fake station owner鍐茬獊锛宱peration={}锛宻tationId={}锛宑urrentTaskNo={}锛宑urrentLoading={}锛宑urrentTargetStaNo={}锛宨ncomingTaskNo={}锛宨ncomingTargetStaNo={}锛宖inalStation={}锛宺eason={}",
+ operation,
+ stationId,
+ currentStatus == null ? null : currentStatus.getTaskNo(),
+ currentStatus == null ? null : currentStatus.isLoading(),
+ currentStatus == null ? null : currentStatus.getTargetStaNo(),
+ incomingTaskNo,
+ incomingTargetStationId,
+ finalStation,
+ reason);
+ }
+
+ private boolean ensureStationWritable(String operation, Integer deviceNo, Integer stationId,
+ Integer incomingTaskNo, Integer incomingTargetStationId, boolean finalStation) {
+ if (deviceNo == null || stationId == null) {
+ return false;
+ }
+ ZyStationStatusEntity currentStatus = stateManager.findStationStatus(deviceNo, stationId);
+ if (currentStatus == null) {
+ return false;
+ }
+ if (!hasOwnerConflict(currentStatus, incomingTaskNo)) {
+ return true;
+ }
+ logOwnerConflict(operation, stationId, currentStatus, incomingTaskNo, incomingTargetStationId, finalStation,
+ finalStation ? "final_station_owner_conflict" : "owner_conflict");
+ return false;
+ }
+
+ private boolean ensureStationClearable(String operation, Integer deviceNo, Integer stationId, Integer expectedTaskNo,
+ boolean finalStation) {
+ if (deviceNo == null || stationId == null) {
+ return false;
+ }
+ ZyStationStatusEntity currentStatus = stateManager.findStationStatus(deviceNo, stationId);
+ if (currentStatus == null) {
+ return false;
+ }
+ if (!hasOwnerConflict(currentStatus, expectedTaskNo)) {
+ return true;
+ }
+ if (isLegalClearStation(stationId)) {
+ return true;
+ }
+ logOwnerConflict(operation, stationId, currentStatus, expectedTaskNo, currentStatus.getTargetStaNo(), finalStation,
+ "illegal_clear_attempt");
+ return false;
+ }
+
+ private boolean isLegalClearStation(Integer stationId) {
if (stationId == null) {
return false;
}
- BasDevpService basDevpService = SpringUtils.getBean(BasDevpService.class);
- List<BasDevp> basDevps = basDevpService.list();
- Set<Integer> specialStationIds = new HashSet<>();
- for (BasDevp basDevp : basDevps) {
- for (StationObjModel station : basDevp.getInStationList$()) {
- specialStationIds.add(station.getStationId());
- }
- for (StationObjModel station : basDevp.getOutStationList$()) {
- specialStationIds.add(station.getStationId());
- }
- for (StationObjModel station : basDevp.getBarcodeStationList$()) {
- specialStationIds.add(station.getStationId());
- }
+ Set<Integer> stationIds = legalClearStationIds;
+ if (stationIds == null || stationIds.isEmpty()) {
+ refreshLegalClearStationIds();
+ stationIds = legalClearStationIds;
}
- return specialStationIds.contains(stationId);
+ return stationIds != null && stationIds.contains(stationId);
}
- private long getFakeRunBlockTimeoutMs() {
- long timeoutMs = DEFAULT_FAKE_RUN_BLOCK_TIMEOUT_MS;
- Object systemConfigMapObj = redisUtil == null ? null : redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key);
- if (systemConfigMapObj instanceof Map) {
- Map<?, ?> systemConfigMap = (Map<?, ?>) systemConfigMapObj;
- Object value = systemConfigMap.get("fakeRunBlockTimeoutMs");
- if (value != null) {
- try {
- long parsed = Long.parseLong(String.valueOf(value).trim());
- if (parsed > 0) {
- timeoutMs = parsed;
- }
- } catch (Exception ignore) {
+ private boolean isBarcodeStation(Integer stationId) {
+ if (stationId == null) {
+ return false;
+ }
+ Set<Integer> stationIds = barcodeStationIds;
+ if (stationIds == null || stationIds.isEmpty()) {
+ refreshBarcodeStationIds();
+ stationIds = barcodeStationIds;
+ }
+ return stationIds != null && stationIds.contains(stationId);
+ }
+
+ private void refreshLegalClearStationIds() {
+ try {
+ Set<Integer> stationIds = new HashSet<Integer>();
+
+ com.zy.asrs.service.BasCrnpService basCrnpService = com.core.common.SpringUtils.getBean(com.zy.asrs.service.BasCrnpService.class);
+ List<com.zy.asrs.entity.BasCrnp> basCrnps = basCrnpService.list();
+ for (com.zy.asrs.entity.BasCrnp basCrnp : basCrnps) {
+ if (basCrnp == null) {
+ continue;
}
+ collectStationIds(stationIds, basCrnp.getInStationList$());
+ collectStationIds(stationIds, basCrnp.getOutStationList$());
+ }
+
+ com.zy.asrs.service.BasDevpService basDevpService = com.core.common.SpringUtils.getBean(com.zy.asrs.service.BasDevpService.class);
+ List<com.zy.asrs.entity.BasDevp> basDevps = basDevpService.list();
+ for (com.zy.asrs.entity.BasDevp basDevp : basDevps) {
+ if (basDevp == null) {
+ continue;
+ }
+ collectStationIds(stationIds, basDevp.getBarcodeStationList$());
+ collectStationIds(stationIds, basDevp.getInStationList$());
+ collectStationIds(stationIds, basDevp.getOutStationList$());
+ }
+
+ legalClearStationIds = stationIds;
+ } catch (Exception e) {
+ News.info("[WCS Debug] fake 鍚堟硶娓呯珯鐧藉悕鍗曞埛鏂板け璐ワ紝寮傚父绫诲瀷={}锛屽紓甯镐俊鎭�={}",
+ e.getClass().getSimpleName(), e.getMessage());
+ }
+ }
+
+ private void refreshBarcodeStationIds() {
+ try {
+ Set<Integer> stationIds = new HashSet<Integer>();
+ com.zy.asrs.service.BasDevpService basDevpService = com.core.common.SpringUtils.getBean(com.zy.asrs.service.BasDevpService.class);
+ List<com.zy.asrs.entity.BasDevp> basDevps = basDevpService.list();
+ for (com.zy.asrs.entity.BasDevp basDevp : basDevps) {
+ if (basDevp == null) {
+ continue;
+ }
+ collectStationIds(stationIds, basDevp.getBarcodeStationList$());
+ }
+ barcodeStationIds = stationIds;
+ } catch (Exception e) {
+ News.info("[WCS Debug] fake 鏉$爜绔欑櫧鍚嶅崟鍒锋柊澶辫触锛屽紓甯哥被鍨�={}锛屽紓甯镐俊鎭�={}",
+ e.getClass().getSimpleName(), e.getMessage());
+ }
+ }
+
+ private void collectStationIds(Set<Integer> stationIds, List<com.zy.core.model.StationObjModel> stations) {
+ if (stationIds == null || stations == null || stations.isEmpty()) {
+ return;
+ }
+ for (com.zy.core.model.StationObjModel station : stations) {
+ if (station != null && station.getStationId() != null) {
+ stationIds.add(station.getStationId());
}
}
- return timeoutMs;
+ }
+
+ private boolean isFinalStation(Integer taskNo, Integer stationId) {
+ TaskRuntimeContext context = taskNo == null ? null : taskContexts.get(taskNo);
+ return context != null && stationId != null && stationId.equals(context.finalTargetStationId);
+ }
+
+ private void logFinalStationOwnershipLost(Integer deviceNo, TaskRuntimeContext context) {
+ Integer stationId = context == null ? null : context.finalTargetStationId;
+ Integer targetDeviceNo = stateManager.getDeviceNoByStationId(stationId);
+ ZyStationStatusEntity currentStatus = targetDeviceNo == null ? null : stateManager.snapshotStation(targetDeviceNo, stationId);
+ News.info("[WCS Debug] fake 鏈�缁堢珯鎵�鏈夋潈涓㈠け锛宼askNo={}锛宻tationId={}锛宑urrentTaskNo={}锛宑urrentLoading={}锛宑urrentTargetStaNo={}锛宺eason={}",
+ context == null ? null : context.taskNo,
+ stationId,
+ currentStatus == null ? null : currentStatus.getTaskNo(),
+ currentStatus == null ? null : currentStatus.isLoading(),
+ currentStatus == null ? null : currentStatus.getTargetStaNo(),
+ "final_station_owner_conflict");
+ traceEvent(deviceNo, context, "FINAL_STATION_OWNER_CONFLICT", "鏈�缁堢珯浠嶆湁鐗╀絾鎵�鏈夎�呭凡琚叾浠栦换鍔¤鐩�",
+ buildDetails("stationId", stationId,
+ "currentTaskNo", currentStatus == null ? null : currentStatus.getTaskNo(),
+ "currentLoading", currentStatus == null ? null : currentStatus.isLoading(),
+ "currentTargetStaNo", currentStatus == null ? null : currentStatus.getTargetStaNo()), false);
+ }
+
+ private boolean guardedClearStationForDispatch(Integer deviceNo, Integer stationId, Integer expectedTaskNo, String reason) {
+ if (!ensureStationClearable("clearStationForDispatch", deviceNo, stationId, expectedTaskNo,
+ isFinalStation(expectedTaskNo, stationId))) {
+ return false;
+ }
+ stateManager.clearStationForDispatch(deviceNo, stationId, reason);
+ return true;
+ }
+
+ private boolean guardedResetStation(Integer deviceNo, Integer stationId, Integer expectedTaskNo) {
+ if (!ensureStationClearable("resetStation", deviceNo, stationId, expectedTaskNo,
+ isFinalStation(expectedTaskNo, stationId))) {
+ return false;
+ }
+ stateManager.resetStation(deviceNo, stationId);
+ return true;
+ }
+
+ private boolean guardedUpdateStationBarcode(Integer deviceNo, Integer stationId, Integer taskNo, String barcode) {
+ if (!ensureStationWritable("updateStationBarcode", deviceNo, stationId, taskNo, null,
+ isFinalStation(taskNo, stationId))) {
+ return false;
+ }
+ stateManager.updateStationBarcode(deviceNo, stationId, barcode);
+ return true;
+ }
+
+ private boolean guardedGenerateFakeOutStationData(Integer deviceNo, Integer stationId, Integer taskNo) {
+ if (!ensureStationWritable("generateFakeOutStationData", deviceNo, stationId, taskNo, null,
+ isFinalStation(taskNo, stationId))) {
+ return false;
+ }
+ stateManager.generateFakeOutStationData(deviceNo, stationId);
+ return true;
+ }
+
+ private boolean guardedHandoffBarcodeStation(Integer deviceNo, Integer taskNo, Integer stationId, Integer targetStationId) {
+ if (!ensureStationWritable("handoffBarcodeStation", deviceNo, stationId, taskNo, targetStationId,
+ isFinalStation(taskNo, stationId))) {
+ return false;
+ }
+ stateManager.handoffBarcodeStation(deviceNo, taskNo, stationId, targetStationId);
+ return true;
+ }
+
+ private boolean guardedRunBlockStation(Integer taskNo, Integer stationId, Integer deviceNo, Integer ownerTaskNo,
+ Integer targetStationId) {
+ if (!ensureStationWritable("runBlockStation", deviceNo, stationId, ownerTaskNo, targetStationId,
+ isFinalStation(ownerTaskNo, stationId))) {
+ return false;
+ }
+ blockManager.runBlockStation(taskNo, stationId, deviceNo, ownerTaskNo, targetStationId);
+ return true;
+ }
+
+ private boolean guardedClearRunBlock(Integer taskNo, Integer stationId, Integer deviceNo) {
+ if (!ensureStationWritable("clearRunBlock", deviceNo, stationId, taskNo, null,
+ isFinalStation(taskNo, stationId))) {
+ return false;
+ }
+ blockManager.clearRunBlock(stationId, deviceNo);
+ return true;
+ }
+
+ private boolean guardedPublishTaskLocation(Integer taskNo, Integer deviceNo, Integer stationId, boolean loading, boolean runBlock) {
+ if (loading && !ensureStationWritable("publishTaskLocation", deviceNo, stationId, taskNo, null,
+ isFinalStation(taskNo, stationId))) {
+ return false;
+ }
+ stateManager.publishTaskLocation(taskNo, deviceNo, stationId, loading, runBlock);
+ return true;
+ }
+
+ private boolean guardedGenerateStationData(Integer deviceNo, Integer taskNo, Integer stationId, Integer targetStationId) {
+ if (!ensureStationWritable("generateStationData", deviceNo, stationId, taskNo, targetStationId,
+ isFinalStation(taskNo, stationId))) {
+ return false;
+ }
+ stateManager.generateStationData(deviceNo, taskNo, stationId, targetStationId);
+ return true;
+ }
+
+ private boolean guardedSyncCurrentStationTarget(Integer taskNo, Integer currentStationId, Integer targetStationId) {
+ syncCurrentStationTarget(taskNo, currentStationId, targetStationId);
+ return true;
+ }
+
+ private boolean guardedClearTaskLocationIfMatches(Integer taskNo, Integer deviceNo, Integer stationId) {
+ stateManager.clearTaskLocationIfMatches(taskNo, deviceNo, stationId);
+ return true;
+ }
+
+ private boolean guardedPublishCurrentLocation(Integer taskNo, Integer deviceNo, Integer stationId) {
+ return guardedPublishTaskLocation(taskNo, deviceNo, stationId, true, false);
+ }
+
+ private boolean guardedGenerateStationBarcode(Integer taskNo, Integer stationId, Integer deviceNo) {
+ if (!ensureStationWritable("generateStationBarcode", deviceNo, stationId, taskNo, null,
+ isFinalStation(taskNo, stationId))) {
+ return false;
+ }
+ return stateManager.generateStationBarcode(taskNo, stationId, deviceNo);
+ }
+
+ private boolean guardedUpdateStationData(Integer stationId, Integer deviceNo, Integer taskNo, Integer targetStationId,
+ Boolean loading, String barcode, Boolean runBlock) {
+ if ((taskNo != null || Boolean.TRUE.equals(loading))
+ && !ensureStationWritable("updateStationData", deviceNo, stationId, taskNo, targetStationId,
+ isFinalStation(taskNo, stationId))) {
+ return false;
+ }
+ return stateManager.updateStationDataInternal(stationId, deviceNo, taskNo, targetStationId, loading, barcode, runBlock);
+ }
+
+ private boolean isFinalStationConflict(Integer taskNo, Integer stationId, Integer deviceNo) {
+ return isFinalStation(taskNo, stationId) && stateManager.isOccupiedByOtherLoadingTask(deviceNo, stationId, taskNo);
+ }
+
+ private boolean guardedResetOrClearBlockedStation(Integer taskNo, Integer stationId, Integer deviceNo) {
+ return ensureStationClearable("blockedStationClear", deviceNo, stationId, taskNo, isFinalStation(taskNo, stationId));
+ }
+
+ private boolean guardedStationOccupied(Integer taskNo, Integer stationId, Integer deviceNo) {
+ return !stateManager.isOccupiedByOtherLoadingTask(deviceNo, stationId, taskNo);
+ }
+
+ private boolean guardedFinalStationOwnership(Integer taskNo, Integer stationId, Integer deviceNo) {
+ return !stateManager.isFinalStationOwnerConflict(deviceNo, stationId, taskNo);
+ }
+
+ private boolean guardedFinalStationWritable(Integer taskNo, Integer stationId, Integer deviceNo, String operation) {
+ if (!guardedFinalStationOwnership(taskNo, stationId, deviceNo)) {
+ ZyStationStatusEntity currentStatus = stateManager.snapshotStation(deviceNo, stationId);
+ logOwnerConflict(operation, stationId, currentStatus, taskNo,
+ currentStatus == null ? null : currentStatus.getTargetStaNo(), true,
+ "final_station_owner_conflict");
+ return false;
+ }
+ return true;
+ }
+
+ private boolean guardedFinalStationClearable(Integer taskNo, Integer stationId, Integer deviceNo, String operation) {
+ if (!guardedFinalStationOwnership(taskNo, stationId, deviceNo)) {
+ ZyStationStatusEntity currentStatus = stateManager.snapshotStation(deviceNo, stationId);
+ logOwnerConflict(operation, stationId, currentStatus, taskNo,
+ currentStatus == null ? null : currentStatus.getTargetStaNo(), true,
+ "illegal_clear_attempt");
+ return false;
+ }
+ return true;
+ }
+
+ private boolean shouldTreatAsFinalStationConflict(Integer taskNo, Integer stationId, Integer deviceNo) {
+ return isFinalStation(taskNo, stationId) && stateManager.isFinalStationOwnerConflict(deviceNo, stationId, taskNo);
+ }
+
+ private boolean guardedFinalStationMutation(String operation, Integer taskNo, Integer stationId, Integer deviceNo, Integer targetStationId) {
+ if (shouldTreatAsFinalStationConflict(taskNo, stationId, deviceNo)) {
+ ZyStationStatusEntity currentStatus = stateManager.snapshotStation(deviceNo, stationId);
+ logOwnerConflict(operation, stationId, currentStatus, taskNo, targetStationId, true,
+ "final_station_owner_conflict");
+ return false;
+ }
+ return true;
+ }
+
+ private boolean guardedFinalStationClear(String operation, Integer taskNo, Integer stationId, Integer deviceNo) {
+ if (shouldTreatAsFinalStationConflict(taskNo, stationId, deviceNo)) {
+ ZyStationStatusEntity currentStatus = stateManager.snapshotStation(deviceNo, stationId);
+ logOwnerConflict(operation, stationId, currentStatus, taskNo,
+ currentStatus == null ? null : currentStatus.getTargetStaNo(), true,
+ "illegal_clear_attempt");
+ return false;
+ }
+ return true;
+ }
+
+ private boolean guardedStationWrite(String operation, Integer taskNo, Integer stationId, Integer deviceNo, Integer targetStationId) {
+ if (!guardedFinalStationMutation(operation, taskNo, stationId, deviceNo, targetStationId)) {
+ return false;
+ }
+ return ensureStationWritable(operation, deviceNo, stationId, taskNo, targetStationId, isFinalStation(taskNo, stationId));
+ }
+
+ private boolean guardedStationClear(String operation, Integer taskNo, Integer stationId, Integer deviceNo) {
+ if (!guardedFinalStationClear(operation, taskNo, stationId, deviceNo)) {
+ return false;
+ }
+ return ensureStationClearable(operation, deviceNo, stationId, taskNo, isFinalStation(taskNo, stationId));
+ }
+
+ private boolean guardedStateMutation(String operation, Integer taskNo, Integer stationId, Integer deviceNo, Integer targetStationId,
+ Runnable mutation) {
+ if (!guardedStationWrite(operation, taskNo, stationId, deviceNo, targetStationId)) {
+ return false;
+ }
+ mutation.run();
+ return true;
+ }
+
+ private boolean guardedStateClear(String operation, Integer taskNo, Integer stationId, Integer deviceNo, Runnable mutation) {
+ if (!guardedStationClear(operation, taskNo, stationId, deviceNo)) {
+ return false;
+ }
+ mutation.run();
+ return true;
+ }
+
+ private boolean guardedFinalStationCompletion(Integer deviceNo, TaskRuntimeContext context) {
+ if (context == null || context.finalTargetStationId == null || context.taskNo == null) {
+ return false;
+ }
+ return !stateManager.isFinalStationOwnerConflict(deviceNo, context.finalTargetStationId, context.taskNo);
+ }
+
+ private boolean guardedCurrentStationOwnership(Integer taskNo, Integer currentStationId, Integer currentDeviceNo) {
+ return !stateManager.isOccupiedByOtherLoadingTask(currentDeviceNo, currentStationId, taskNo);
+ }
+
+ private boolean guardedTargetStationOwnership(Integer taskNo, Integer stationId, Integer deviceNo) {
+ return !stateManager.isOccupiedByOtherLoadingTask(deviceNo, stationId, taskNo);
+ }
+
+ private boolean guardedCommandWrite(String operation, Integer taskNo, Integer stationId, Integer deviceNo, Integer targetStationId, Runnable mutation) {
+ if (!guardedStationWrite(operation, taskNo, stationId, deviceNo, targetStationId)) {
+ return false;
+ }
+ mutation.run();
+ return true;
+ }
+
+ private boolean guardedCommandClear(String operation, Integer taskNo, Integer stationId, Integer deviceNo, Runnable mutation) {
+ if (!guardedStationClear(operation, taskNo, stationId, deviceNo)) {
+ return false;
+ }
+ mutation.run();
+ return true;
+ }
+
+ private boolean guardedRunBlockMutation(Integer taskNo, Integer stationId, Integer deviceNo, Integer targetStationId) {
+ return guardedStationWrite("runBlockStation", taskNo, stationId, deviceNo, targetStationId);
+ }
+
+ private boolean guardedClearMutation(Integer taskNo, Integer stationId, Integer deviceNo, String operation) {
+ return guardedStationClear(operation, taskNo, stationId, deviceNo);
+ }
+
+ private boolean guardedArrivalOwnership(Integer deviceNo, TaskRuntimeContext context) {
+ return context != null && context.finalTargetStationId != null && context.taskNo != null
+ && !stateManager.isFinalStationOwnerConflict(deviceNo, context.finalTargetStationId, context.taskNo);
+ }
+
+ private boolean guardedArrivalStationWritable(Integer deviceNo, TaskRuntimeContext context, String operation) {
+ if (!guardedArrivalOwnership(deviceNo, context)) {
+ logFinalStationOwnershipLost(deviceNo, context);
+ return false;
+ }
+ return true;
+ }
+
+ private boolean guardedArrivalStationClearable(Integer deviceNo, TaskRuntimeContext context, String operation) {
+ if (!guardedArrivalOwnership(deviceNo, context)) {
+ logFinalStationOwnershipLost(deviceNo, context);
+ return false;
+ }
+ return true;
+ }
+
+ private boolean guardedStationMutation(String operation, Integer taskNo, Integer stationId, Integer deviceNo, Integer targetStationId,
+ Runnable mutation, boolean clearOperation) {
+ boolean allowed = clearOperation
+ ? guardedStationClear(operation, taskNo, stationId, deviceNo)
+ : guardedStationWrite(operation, taskNo, stationId, deviceNo, targetStationId);
+ if (!allowed) {
+ return false;
+ }
+ mutation.run();
+ return true;
+ }
+
+ private boolean guardedFinalArrivalState(Integer deviceNo, TaskRuntimeContext context) {
+ if (context == null || context.finalTargetStationId == null || context.taskNo == null) {
+ return false;
+ }
+ if (stateManager.isFinalStationOwnerConflict(deviceNo, context.finalTargetStationId, context.taskNo)) {
+ logFinalStationOwnershipLost(deviceNo, context);
+ return false;
+ }
+ return true;
+ }
+
+ private boolean guardedArrivalCompletion(Integer deviceNo, TaskRuntimeContext context) {
+ return guardedFinalArrivalState(deviceNo, context);
+ }
+
+ private boolean guardedStationOwnership(String operation, Integer taskNo, Integer stationId, Integer deviceNo, Integer targetStationId,
+ boolean clearOperation) {
+ return clearOperation
+ ? guardedStationClear(operation, taskNo, stationId, deviceNo)
+ : guardedStationWrite(operation, taskNo, stationId, deviceNo, targetStationId);
+ }
+
+ private boolean guardedStationMutationIfAllowed(String operation, Integer taskNo, Integer stationId, Integer deviceNo,
+ Integer targetStationId, boolean clearOperation, Runnable mutation) {
+ if (!guardedStationOwnership(operation, taskNo, stationId, deviceNo, targetStationId, clearOperation)) {
+ return false;
+ }
+ mutation.run();
+ return true;
+ }
+
+ private boolean guardedArrivalStationState(Integer deviceNo, TaskRuntimeContext context) {
+ return guardedFinalArrivalState(deviceNo, context);
+ }
+
+ private boolean guardedMutateFinalStation(String operation, Integer taskNo, Integer stationId, Integer deviceNo,
+ Integer targetStationId, Runnable mutation) {
+ if (!guardedStationWrite(operation, taskNo, stationId, deviceNo, targetStationId)) {
+ return false;
+ }
+ mutation.run();
+ return true;
+ }
+
+ private boolean guardedClearFinalStation(String operation, Integer taskNo, Integer stationId, Integer deviceNo,
+ Runnable mutation) {
+ if (!guardedStationClear(operation, taskNo, stationId, deviceNo)) {
+ return false;
+ }
+ mutation.run();
+ return true;
+ }
+
+ private boolean guardedArrivalState(Integer deviceNo, TaskRuntimeContext context) {
+ if (!guardedFinalArrivalState(deviceNo, context)) {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean guardedCurrentStationWrite(Integer taskNo, Integer currentStationId, Integer currentDeviceNo, Integer targetStationId,
+ String operation) {
+ return guardedStationWrite(operation, taskNo, currentStationId, currentDeviceNo, targetStationId);
+ }
+
+ private boolean guardedCurrentStationClear(Integer taskNo, Integer currentStationId, Integer currentDeviceNo, String operation) {
+ return guardedStationClear(operation, taskNo, currentStationId, currentDeviceNo);
+ }
+
+ private boolean guardedFinalStationWrite(Integer taskNo, Integer stationId, Integer deviceNo, Integer targetStationId, String operation) {
+ return guardedStationWrite(operation, taskNo, stationId, deviceNo, targetStationId);
+ }
+
+ private boolean guardedFinalStationClear(Integer taskNo, Integer stationId, Integer deviceNo, String operation) {
+ return guardedStationClear(operation, taskNo, stationId, deviceNo);
+ }
+
+ private boolean guardedStationBarcodeWrite(Integer deviceNo, Integer stationId, Integer taskNo, String barcode) {
+ return guardedUpdateStationBarcode(deviceNo, stationId, taskNo, barcode);
+ }
+
+ private boolean guardedStationOccupancyWrite(Integer deviceNo, Integer stationId, Integer taskNo, Integer targetStationId,
+ Runnable mutation, String operation) {
+ if (!guardedStationWrite(operation, taskNo, stationId, deviceNo, targetStationId)) {
+ return false;
+ }
+ mutation.run();
+ return true;
+ }
+
+ private boolean guardedStationOccupancyClear(Integer deviceNo, Integer stationId, Integer taskNo,
+ Runnable mutation, String operation) {
+ if (!guardedStationClear(operation, taskNo, stationId, deviceNo)) {
+ return false;
+ }
+ mutation.run();
+ return true;
+ }
+
+ private boolean guardedStationWriteForTask(Integer deviceNo, Integer stationId, Integer taskNo, Integer targetStationId,
+ String operation) {
+ return guardedStationWrite(operation, taskNo, stationId, deviceNo, targetStationId);
+ }
+
+ private boolean guardedStationClearForTask(Integer deviceNo, Integer stationId, Integer taskNo, String operation) {
+ return guardedStationClear(operation, taskNo, stationId, deviceNo);
+ }
+
+ private boolean guardedMutateStationIfOwned(Integer deviceNo, Integer stationId, Integer taskNo, Integer targetStationId,
+ String operation, Runnable mutation) {
+ if (!guardedStationWrite(operation, taskNo, stationId, deviceNo, targetStationId)) {
+ return false;
+ }
+ mutation.run();
+ return true;
+ }
+
+ private boolean guardedClearStationIfOwned(Integer deviceNo, Integer stationId, Integer taskNo, String operation,
+ Runnable mutation) {
+ if (!guardedStationClear(operation, taskNo, stationId, deviceNo)) {
+ return false;
+ }
+ mutation.run();
+ return true;
+ }
+
+ private boolean guardedArrivalVisibility(Integer deviceNo, TaskRuntimeContext context) {
+ return guardedFinalArrivalState(deviceNo, context);
+ }
+
+ private boolean guardedFinalStationNotOverwritten(Integer deviceNo, TaskRuntimeContext context) {
+ return guardedFinalArrivalState(deviceNo, context);
+ }
+
+ private boolean guardedMutateOccupiedStation(String operation, Integer deviceNo, Integer stationId, Integer taskNo,
+ Integer targetStationId, Runnable mutation) {
+ if (!guardedStationWrite(operation, taskNo, stationId, deviceNo, targetStationId)) {
+ return false;
+ }
+ mutation.run();
+ return true;
+ }
+
+ private boolean guardedClearOccupiedStation(String operation, Integer deviceNo, Integer stationId, Integer taskNo,
+ Runnable mutation) {
+ if (!guardedStationClear(operation, taskNo, stationId, deviceNo)) {
+ return false;
+ }
+ mutation.run();
+ return true;
+ }
+
+ private boolean guardedFinalStationStillOwned(Integer deviceNo, TaskRuntimeContext context) {
+ return guardedFinalArrivalState(deviceNo, context);
+ }
+
+ private boolean guardedStateWrite(String operation, Integer deviceNo, Integer stationId, Integer taskNo, Integer targetStationId) {
+ return guardedStationWrite(operation, taskNo, stationId, deviceNo, targetStationId);
+ }
+
+ private boolean guardedStateClear(String operation, Integer deviceNo, Integer stationId, Integer taskNo) {
+ return guardedStationClear(operation, taskNo, stationId, deviceNo);
+ }
+
+ private boolean guardedArrivalOwnerCheck(Integer deviceNo, TaskRuntimeContext context) {
+ return guardedFinalArrivalState(deviceNo, context);
+ }
+
+ private boolean guardedArrivalConflict(Integer deviceNo, TaskRuntimeContext context) {
+ return stateManager.isFinalStationOwnerConflict(deviceNo, context.finalTargetStationId, context.taskNo);
+ }
+
+ private boolean guardedCurrentOwnerCheck(Integer deviceNo, Integer stationId, Integer taskNo) {
+ return !stateManager.isOccupiedByOtherLoadingTask(deviceNo, stationId, taskNo);
+ }
+
+ private boolean guardedMutateStationState(String operation, Integer deviceNo, Integer stationId, Integer taskNo,
+ Integer targetStationId, Runnable mutation) {
+ if (!guardedStationWrite(operation, taskNo, stationId, deviceNo, targetStationId)) {
+ return false;
+ }
+ mutation.run();
+ return true;
+ }
+
+ private boolean guardedClearStationState(String operation, Integer deviceNo, Integer stationId, Integer taskNo,
+ Runnable mutation) {
+ if (!guardedStationClear(operation, taskNo, stationId, deviceNo)) {
+ return false;
+ }
+ mutation.run();
+ return true;
+ }
+
+ private boolean guardedArrivalCompletionState(Integer deviceNo, TaskRuntimeContext context) {
+ return guardedFinalArrivalState(deviceNo, context);
+ }
+
+ private boolean guardedWriteToStation(String operation, Integer deviceNo, Integer stationId, Integer taskNo, Integer targetStationId) {
+ return guardedStationWrite(operation, taskNo, stationId, deviceNo, targetStationId);
+ }
+
+ private boolean guardedClearFromStation(String operation, Integer deviceNo, Integer stationId, Integer taskNo) {
+ return guardedStationClear(operation, taskNo, stationId, deviceNo);
}
private void handleCommand(Integer deviceNo, StationCommand command) {
- News.info("[WCS Debug] 绔欑偣浠跨湡妯℃嫙(V3)宸插惎鍔紝鍛戒护鏁版嵁={}", JSON.toJSONString(command));
+ News.info("[WCS Debug] fake 闈濵OVE鍛戒护杩涘叆device涓茶鎵ц锛宒eviceNo={}锛宻tationId={}锛宼argetStaNo={}锛宑ommandType={}锛屽懡浠ゆ暟鎹�={}",
+ deviceNo, command.getStationId(), command.getTargetStaNo(), command.getCommandType(), JSON.toJSONString(command));
Integer taskNo = command.getTaskNo();
Integer stationId = command.getStationId();
Integer targetStationId = command.getTargetStaNo();
if (command.getCommandType() == StationCommandType.RESET) {
- resetStation(deviceNo, stationId);
+ boolean reset = guardedResetStation(deviceNo, stationId, taskNo);
+ News.info("[WCS Debug] fake RESET宸查�氳繃缁熶竴绔欑偣閿佹墽琛岋紝deviceNo={}锛宻tationId={}锛宎ccepted={}", deviceNo, stationId, reset);
return;
}
if (command.getCommandType() == StationCommandType.WRITE_INFO) {
if (command.getBarcode() != null) {
- updateStationBarcode(deviceNo, stationId, command.getBarcode());
+ boolean updated = guardedUpdateStationBarcode(deviceNo, stationId, taskNo, command.getBarcode());
+ News.info("[WCS Debug] fake WRITE_INFO鏉$爜鍐欏叆宸查�氳繃缁熶竴绔欑偣閿佹墽琛岋紝deviceNo={}锛宻tationId={}锛宐arcode={}锛宎ccepted={}",
+ deviceNo, stationId, command.getBarcode(), updated);
return;
}
if (taskNo == 9998 && targetStationId == 0) {
- generateFakeOutStationData(deviceNo, stationId);
+ boolean generated = guardedGenerateFakeOutStationData(deviceNo, stationId, taskNo);
+ News.info("[WCS Debug] fake WRITE_INFO鏈夌墿鍐欏叆宸查�氳繃缁熶竴绔欑偣閿佹墽琛岋紝deviceNo={}锛宻tationId={}锛宎ccepted={}", deviceNo, stationId, generated);
return;
}
}
if (taskNo != null && taskNo > 0 && taskNo != 9999 && taskNo != 9998 && stationId != null
&& stationId.equals(targetStationId)) {
- generateStationData(deviceNo, taskNo, stationId, targetStationId);
- }
- }
-
- private void generateFakeOutStationData(Integer deviceNo, Integer stationId) {
- List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo);
- if (statusList == null) {
- return;
- }
- ZyStationStatusEntity status = statusList.stream()
- .filter(item -> item.getStationId().equals(stationId)).findFirst().orElse(null);
- if (status == null) {
- return;
- }
- synchronized (status) {
- status.setLoading(true);
- }
- }
-
- private void generateStationData(Integer deviceNo, Integer taskNo, Integer stationId, Integer targetStationId) {
- List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo);
- if (statusList == null) {
- return;
- }
- ZyStationStatusEntity status = statusList.stream()
- .filter(item -> item.getStationId().equals(stationId)).findFirst().orElse(null);
- if (status == null) {
- return;
- }
- synchronized (status) {
- status.setTaskNo(taskNo);
- status.setTargetStaNo(targetStationId);
- }
- }
-
- private void resetStation(Integer deviceNo, Integer stationId) {
- List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo);
- if (statusList == null) {
- return;
- }
- ZyStationStatusEntity status = statusList.stream()
- .filter(item -> item.getStationId().equals(stationId)).findFirst().orElse(null);
- if (status == null) {
- return;
- }
- synchronized (status) {
- status.setTaskNo(0);
- status.setLoading(false);
- status.setBarcode("");
- }
- }
-
- private void updateStationBarcode(Integer deviceNo, Integer stationId, String barcode) {
- List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo);
- if (statusList == null) {
- return;
- }
- ZyStationStatusEntity status = statusList.stream()
- .filter(item -> item.getStationId().equals(stationId)).findFirst().orElse(null);
- if (status == null) {
- return;
- }
- synchronized (status) {
- status.setBarcode(barcode);
- }
- }
-
- private Integer getDeviceNoByStationId(Integer stationId) {
- for (Map.Entry<Integer, List<ZyStationStatusEntity>> entry : deviceStatusMap.entrySet()) {
- List<ZyStationStatusEntity> list = entry.getValue();
- if (list == null) {
- continue;
- }
- for (ZyStationStatusEntity entity : list) {
- if (entity.getStationId() != null && entity.getStationId().equals(stationId)) {
- return entry.getKey();
- }
- }
- }
- return null;
- }
-
- private Integer findCurrentStationIdByTask(Integer taskNo) {
- for (List<ZyStationStatusEntity> list : deviceStatusMap.values()) {
- if (list == null) {
- continue;
- }
- for (ZyStationStatusEntity entity : list) {
- if (entity.getTaskNo() != null && entity.getTaskNo().equals(taskNo) && entity.isLoading()) {
- return entity.getStationId();
- }
- }
- }
- return null;
- }
-
- private void sleep(long ms) {
- try {
- Thread.sleep(ms);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
-
- private ReentrantLock getStationLock(Integer stationId) {
- return stationLocks.computeIfAbsent(stationId, key -> new ReentrantLock());
- }
-
- private void lockStations(Integer... stationIds) {
- Integer[] sorted = Arrays.copyOf(stationIds, stationIds.length);
- Arrays.sort(sorted);
- for (Integer stationId : sorted) {
- getStationLock(stationId).lock();
- }
- }
-
- private void unlockStations(Integer... stationIds) {
- Integer[] sorted = Arrays.copyOf(stationIds, stationIds.length);
- Arrays.sort(sorted);
- for (int i = sorted.length - 1; i >= 0; i--) {
- getStationLock(sorted[i]).unlock();
- }
- }
-
- private boolean updateStationDataInternal(Integer stationId, Integer deviceNo, Integer taskNo, Integer targetStaNo,
- Boolean isLoading, String barcode, Boolean runBlock) {
- List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo);
- if (statusList == null) {
- return false;
- }
- ZyStationStatusEntity currentStatus = statusList.stream()
- .filter(item -> item.getStationId().equals(stationId)).findFirst().orElse(null);
- if (currentStatus == null) {
- return false;
- }
-
- if (taskNo != null) {
- currentStatus.setTaskNo(taskNo);
- }
- if (targetStaNo != null) {
- currentStatus.setTargetStaNo(targetStaNo);
- }
- if (isLoading != null) {
- currentStatus.setLoading(isLoading);
- }
- if (barcode != null) {
- currentStatus.setBarcode(barcode);
- }
- if (runBlock != null) {
- currentStatus.setRunBlock(runBlock);
- }
- return true;
- }
-
- public boolean initStationMove(Integer lockTaskNo, Integer currentStationId, Integer currentStationDeviceNo,
- Integer taskNo, Integer targetStationId, Boolean isLoading, String barcode) {
- lockStations(currentStationId);
- try {
- List<ZyStationStatusEntity> statusList = deviceStatusMap.get(currentStationDeviceNo);
- if (statusList == null) {
- return false;
- }
- ZyStationStatusEntity currentStatus = statusList.stream()
- .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null);
- if (currentStatus == null) {
- return false;
- }
- if (currentStatus.getTaskNo() != null && currentStatus.getTaskNo() > 0
- && !currentStatus.getTaskNo().equals(taskNo) && currentStatus.isLoading()) {
- return false;
- }
-
- return updateStationDataInternal(currentStationId, currentStationDeviceNo, taskNo, targetStationId,
- isLoading, barcode, false);
- } finally {
- unlockStations(currentStationId);
- }
- }
-
- public boolean stationMoveToNext(Integer lockTaskNo, Integer currentStationId, Integer currentStationDeviceNo,
- Integer nextStationId, Integer nextStationDeviceNo, Integer taskNo, Integer targetStaNo) {
- lockStations(currentStationId, nextStationId);
- try {
- List<ZyStationStatusEntity> statusList = deviceStatusMap.get(currentStationDeviceNo);
- List<ZyStationStatusEntity> nextStatusList = deviceStatusMap.get(nextStationDeviceNo);
- if (statusList == null || nextStatusList == null) {
- return false;
- }
-
- ZyStationStatusEntity currentStatus = statusList.stream()
- .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null);
- ZyStationStatusEntity nextStatus = nextStatusList.stream()
- .filter(item -> item.getStationId().equals(nextStationId)).findFirst().orElse(null);
- if (currentStatus == null || nextStatus == null) {
- return false;
- }
- if (nextStatus.getTaskNo() != null && nextStatus.getTaskNo() > 0 || nextStatus.isLoading()) {
- return false;
- }
-
- boolean result = updateStationDataInternal(nextStationId, nextStationDeviceNo, taskNo, targetStaNo, true,
- null, false);
- if (!result) {
- return false;
- }
- return updateStationDataInternal(currentStationId, currentStationDeviceNo, 0, 0, false, "", false);
- } finally {
- unlockStations(currentStationId, nextStationId);
- }
- }
-
- public boolean generateStationBarcode(Integer lockTaskNo, Integer currentStationId, Integer currentStationDeviceNo) {
- lockStations(currentStationId);
- try {
- List<ZyStationStatusEntity> statusList = deviceStatusMap.get(currentStationDeviceNo);
- if (statusList == null) {
- return false;
- }
- ZyStationStatusEntity currentStatus = statusList.stream()
- .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null);
- if (currentStatus == null) {
- return false;
- }
-
- Random random = new Random();
- String barcodeTime = String.valueOf(System.currentTimeMillis());
- String barcode = String.valueOf(random.nextInt(10)) + String.valueOf(random.nextInt(10))
- + barcodeTime.substring(7);
- return updateStationDataInternal(currentStationId, currentStationDeviceNo, null, null, null, barcode, null);
- } finally {
- unlockStations(currentStationId);
- }
- }
-
- public boolean clearStation(Integer deviceNo, Integer lockTaskNo, Integer currentStationId) {
- lockStations(currentStationId);
- try {
- List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo);
- if (statusList == null) {
- return false;
- }
- ZyStationStatusEntity currentStatus = statusList.stream()
- .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null);
- if (currentStatus == null) {
- return false;
- }
- return updateStationDataInternal(currentStationId, deviceNo, 0, 0, false, "", false);
- } finally {
- unlockStations(currentStationId);
- }
- }
-
- public boolean runBlockStation(Integer lockTaskNo, Integer currentStationId, Integer currentStationDeviceNo,
- Integer taskNo, Integer blockStationId) {
- lockStations(currentStationId);
- try {
- List<ZyStationStatusEntity> statusList = deviceStatusMap.get(currentStationDeviceNo);
- if (statusList == null) {
- return false;
- }
- ZyStationStatusEntity currentStatus = statusList.stream()
- .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null);
- if (currentStatus == null) {
- return false;
- }
- return updateStationDataInternal(currentStationId, currentStationDeviceNo, taskNo, blockStationId, true, "",
- true);
- } finally {
- unlockStations(currentStationId);
- }
- }
-
- public void clearRunBlock(Integer stationId, Integer deviceNo) {
- lockStations(stationId);
- try {
- List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo);
- if (statusList == null) {
- return;
- }
- ZyStationStatusEntity currentStatus = statusList.stream()
- .filter(item -> item.getStationId().equals(stationId)).findFirst().orElse(null);
- if (currentStatus == null) {
- return;
- }
- if (currentStatus.isRunBlock()) {
- currentStatus.setRunBlock(false);
- News.info("[WCS Debug] 绔欑偣{}鍫靛鏍囪宸叉竻闄�", stationId);
- }
- } finally {
- unlockStations(stationId);
+ boolean handedOff = guardedHandoffBarcodeStation(deviceNo, taskNo, stationId, targetStationId);
+ News.info("[WCS Debug] fake 鏉$爜绔欎换鍔′氦鎺ュ畬鎴愶紝deviceNo={}锛宻tationId={}锛宼askNo={}锛宼argetStationId={}锛屽姩浣�=barcodeTaskHandoff锛宎ccepted={}",
+ deviceNo, stationId, taskNo, targetStationId, handedOff);
}
}
@@ -989,36 +1639,138 @@
private void traceEvent(Integer deviceNo, TaskRuntimeContext context, String eventType, String message,
Map<String, Object> details, boolean terminal) {
+ if (context != null && context.deviceNo != null && deviceNo != null && !context.deviceNo.equals(deviceNo)) {
+ deviceNo = context.deviceNo;
+ }
if (context == null || context.taskNo == null) {
return;
}
- try {
- FakeTaskTraceRegistry registry = SpringUtils.getBean(FakeTaskTraceRegistry.class);
- if (registry == null) {
- return;
- }
- registry.record(context.taskNo, context.threadImpl != null ? context.threadImpl : getThreadImpl(deviceNo),
- context.status, context.startStationId, context.currentStationId, context.finalTargetStationId,
- context.blockedStationId, context.getStitchedPathStationIds(), context.getPassedStationIds(),
- context.getPendingStationIds(), context.getLatestAppendedPath(), eventType, message, details,
- terminal);
- } catch (Exception ignore) {
+ Map<String, Object> safeDetails = details == null ? new LinkedHashMap<String, Object>() : new LinkedHashMap<String, Object>(details);
+ if (!safeDetails.containsKey("segmentNo") && context.segmentNo != null) {
+ safeDetails.put("segmentNo", context.segmentNo);
}
- }
-
- private String getThreadImpl(Integer deviceNo) {
- DeviceConfig deviceConfig = deviceConfigMap.get(deviceNo);
- return deviceConfig == null ? "" : deviceConfig.getThreadImpl();
+ if (!safeDetails.containsKey("segmentCount") && context.segmentCount != null) {
+ safeDetails.put("segmentCount", context.segmentCount);
+ }
+ try {
+ FakeTaskTraceRegistry registry = com.core.common.SpringUtils.getBean(FakeTaskTraceRegistry.class);
+ if (registry != null) {
+ registry.record(context.taskNo, context.threadImpl != null ? context.threadImpl : stateManager.getThreadImpl(deviceNo),
+ context.status, context.startStationId, context.currentStationId, context.finalTargetStationId,
+ context.blockedStationId, context.getStitchedPathStationIds(), context.getPassedStationIds(),
+ context.getPendingStationIds(), context.getLatestAppendedPath(), eventType, message, safeDetails,
+ terminal);
+ }
+ } catch (Exception e) {
+ News.info("[WCS Debug] fake trace璁板綍澶辫触锛宼askNo={}锛宔ventType={}锛屽紓甯哥被鍨�={}锛屽紓甯镐俊鎭�={}",
+ context.taskNo, eventType, e.getClass().getSimpleName(), e.getMessage());
+ }
+ News.info("[WCS Debug] fake task event锛宼askNo={}锛宔ventType={}锛宻tatus={}锛宑urrentStationId={}锛宼argetStationId={}锛宲ending={}锛宒etails={}",
+ context.taskNo, eventType, context.status, context.currentStationId, context.finalTargetStationId,
+ context.getPendingStationIds(), JSON.toJSONString(safeDetails));
}
private boolean isTerminalStatus(String status) {
- return STATUS_BLOCKED.equals(status) || STATUS_CANCELLED.equals(status) || STATUS_TIMEOUT.equals(status)
+ return STATUS_CANCELLED.equals(status) || STATUS_TIMEOUT.equals(status)
|| STATUS_FINISHED.equals(status);
+ }
+
+ private boolean isCurrentLoopGeneration(Integer taskNo, int loopGeneration) {
+ AtomicInteger generation = taskLoopGenerations.get(taskNo);
+ return generation != null && generation.get() == loopGeneration;
+ }
+
+ private Object getTaskLifecycleLock(Integer taskNo) {
+ return taskLifecycleLocks.computeIfAbsent(taskNo, key -> new Object());
+ }
+
+ /**
+ * 妫�鏌ュ爢鍨涙満鏄惁宸插彇璧版寚瀹氫换鍔$殑璐х墿
+ * 閫氳繃閬嶅巻鎵�鏈夊爢鍨涙満璁惧锛屾鏌ユ槸鍚︽湁鍫嗗灈鏈烘鍦ㄦ墽琛岃浠诲姟涓斿凡 loaded
+ */
+ private boolean isCrnTakenByTask(Integer taskNo) {
+ if (taskNo == null || taskNo <= 0) {
+ return false;
+ }
+ try {
+ com.zy.asrs.service.BasCrnpService basCrnpService = com.core.common.SpringUtils.getBean(com.zy.asrs.service.BasCrnpService.class);
+ List<com.zy.asrs.entity.BasCrnp> basCrnps = basCrnpService.list();
+ for (com.zy.asrs.entity.BasCrnp basCrnp : basCrnps) {
+ com.zy.core.thread.CrnThread ct = (com.zy.core.thread.CrnThread) com.zy.core.cache.SlaveConnection.get(
+ com.zy.core.enums.SlaveType.Crn, basCrnp.getCrnNo());
+ if (ct == null) {
+ continue;
+ }
+ com.zy.core.model.protocol.CrnProtocol protocol = ct.getStatus();
+ if (protocol != null && taskNo.equals(protocol.getTaskNo())
+ && protocol.getLoaded() == 1) {
+ return true;
+ }
+ }
+ } catch (Exception ignore) {
+ }
+ return false;
+ }
+
+
+ private static class MoveStepResult {
+
+ private final boolean shouldContinue;
+ private final long nextDelayMs;
+
+ private MoveStepResult(boolean shouldContinue, long nextDelayMs) {
+ this.shouldContinue = shouldContinue;
+ this.nextDelayMs = nextDelayMs;
+ }
+
+ private static MoveStepResult continueNow() {
+ return new MoveStepResult(true, 0L);
+ }
+
+ private static MoveStepResult continueAfter(long nextDelayMs) {
+ return new MoveStepResult(true, nextDelayMs);
+ }
+
+ private boolean shouldContinue() {
+ return shouldContinue;
+ }
+
+ private long getNextDelayMs() {
+ return nextDelayMs;
+ }
+ }
+
+ private static class IdleStepResult {
+
+ private final boolean finished;
+ private final long nextDelayMs;
+
+ private IdleStepResult(boolean finished, long nextDelayMs) {
+ this.finished = finished;
+ this.nextDelayMs = nextDelayMs;
+ }
+
+ private static IdleStepResult finish() {
+ return new IdleStepResult(true, 0L);
+ }
+
+ private static IdleStepResult waitNext(long nextDelayMs) {
+ return new IdleStepResult(false, nextDelayMs);
+ }
+
+ private boolean isFinished() {
+ return finished;
+ }
+
+ private long getNextDelayMs() {
+ return nextDelayMs;
+ }
}
private static class TaskRuntimeContext {
private final Integer taskNo;
+ private final Integer deviceNo;
private final String threadImpl;
private final LinkedBlockingQueue<Integer> pendingPathQueue = new LinkedBlockingQueue<Integer>();
private final List<Integer> stitchedPathStationIds = new ArrayList<Integer>();
@@ -1032,12 +1784,18 @@
private boolean generateBarcode;
private boolean initialized;
private boolean arrivalHandled;
+ private Integer segmentNo;
+ private Integer segmentCount;
private long lastStepAt = System.currentTimeMillis();
private long lastCommandAt = System.currentTimeMillis();
+ private long lastProgressAt = System.currentTimeMillis();
+ private Integer lastProgressStationId;
+ private int loopGeneration;
private String status = STATUS_WAITING;
- private TaskRuntimeContext(Integer taskNo, String threadImpl) {
+ private TaskRuntimeContext(Integer taskNo, Integer deviceNo, String threadImpl) {
this.taskNo = taskNo;
+ this.deviceNo = deviceNo;
this.threadImpl = threadImpl;
}
@@ -1064,6 +1822,30 @@
}
}
+ private void replaceLatestPath(List<Integer> path) {
+ latestAppendedPath.clear();
+ if (path == null) {
+ return;
+ }
+ for (Integer stationId : path) {
+ if (stationId != null) {
+ latestAppendedPath.add(stationId);
+ }
+ }
+ }
+
+ private void clearPendingPath() {
+ pendingPathQueue.clear();
+ latestAppendedPath.clear();
+ }
+
+ private void clearPendingPathWithLog(Integer deviceNo, Integer taskNo, Integer currentStationId,
+ Integer targetStationId, Integer blockedStationId, String reason) {
+ News.info("[WCS Debug] fake task娓呯┖寰呮墽琛岃矾寰勶紝鍘熷洜={}锛宒eviceNo={}锛宼askNo={}锛宑urrentStationId={}锛宼argetStationId={}锛宐lockedStationId={}锛宲endingBeforeClear={}",
+ reason, deviceNo, taskNo, currentStationId, targetStationId, blockedStationId, getPendingStationIds());
+ clearPendingPath();
+ }
+
private void addPassedStation(Integer stationId) {
if (stationId == null) {
return;
--
Gitblit v1.9.1