package com.zy.core.utils.station; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.core.common.Cools; import com.zy.asrs.entity.BasStationOpt; import com.zy.asrs.service.BasStationOptService; import com.zy.common.utils.RedisUtil; import com.zy.core.enums.RedisKeyType; import com.zy.core.enums.StationCommandType; import com.zy.core.model.command.StationCommand; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Objects; @Component public class StationDispatchRuntimeStateSupport { private static final int STATION_IDLE_TRACK_EXPIRE_SECONDS = 60 * 60; private static final String IDLE_RECOVER_CLEARED_MEMO = "idleRecoverRerouteCleared"; @Autowired private RedisUtil redisUtil; @Autowired private BasStationOptService basStationOptService; public StationTaskIdleTrack touchIdleTrack(Integer taskNo, Integer stationId) { if (taskNo == null || taskNo <= 0 || stationId == null) { return null; } long now = System.currentTimeMillis(); StationTaskIdleTrack idleTrack = loadIdleTrack(taskNo); if (idleTrack == null || !Objects.equals(idleTrack.getStationId(), stationId)) { idleTrack = new StationTaskIdleTrack(taskNo, stationId, now); saveIdleTrack(idleTrack); } return idleTrack; } public StationTaskIdleTrack loadIdleTrack(Integer taskNo) { if (taskNo == null || taskNo <= 0 || redisUtil == null) { return null; } Object obj = redisUtil.get(RedisKeyType.STATION_TASK_IDLE_TRACK_.key + taskNo); if (obj == null) { return null; } try { return JSON.parseObject(obj.toString(), StationTaskIdleTrack.class); } catch (Exception e) { return null; } } public void saveIdleTrack(StationTaskIdleTrack idleTrack) { if (idleTrack == null || idleTrack.getTaskNo() == null || idleTrack.getTaskNo() <= 0 || redisUtil == null) { return; } redisUtil.set( RedisKeyType.STATION_TASK_IDLE_TRACK_.key + idleTrack.getTaskNo(), JSON.toJSONString(idleTrack, SerializerFeature.DisableCircularReferenceDetect), STATION_IDLE_TRACK_EXPIRE_SECONDS ); } public boolean hasRecentIssuedMoveCommand(Integer taskNo, Integer stationId, long thresholdMs) { if (taskNo == null || taskNo <= 0 || stationId == null || thresholdMs <= 0L || basStationOptService == null) { return false; } Date thresholdTime = new Date(System.currentTimeMillis() - thresholdMs); List optList = basStationOptService.list(new QueryWrapper() .select("id") .eq("task_no", taskNo) .eq("station_id", stationId) .eq("mode", String.valueOf(StationCommandType.MOVE)) .eq("send", 1) .ge("send_time", thresholdTime) .orderByDesc("send_time") .last("limit 1")); return optList != null && !optList.isEmpty(); } public int clearIssuedMoveCommandsDuringIdleStay(StationTaskIdleTrack idleTrack, Integer taskNo, Integer stationId) { if (basStationOptService == null) { return 0; } List optList; try { optList = listIssuedMoveCommandsDuringIdleStay(idleTrack, taskNo); } catch (Exception e) { return 0; } if (optList == null || optList.isEmpty()) { return 0; } Date now = new Date(); String cleanupMemo = buildIdleRecoverClearedMemo(stationId); int clearedCount = 0; for (BasStationOpt opt : optList) { if (opt == null || opt.getId() == null) { continue; } opt.setSend(0); opt.setUpdateTime(now); opt.setMemo(appendCleanupMemo(opt.getMemo(), cleanupMemo)); clearedCount++; } if (clearedCount > 0) { basStationOptService.updateBatchById(optList); } return clearedCount; } public boolean tryAcquireLock(String key, int seconds) { if (redisUtil == null || isBlank(key)) { return true; } Object lock = redisUtil.get(key); if (lock != null) { return false; } redisUtil.set(key, "lock", seconds); return true; } public boolean tryAcquireOutOrderDispatchLock(Integer wrkNo, Integer stationId, int seconds) { if (wrkNo == null || wrkNo <= 0 || stationId == null) { return true; } return tryAcquireLock(RedisKeyType.STATION_OUT_ORDER_DISPATCH_LIMIT_.key + wrkNo + "_" + stationId, seconds); } public void signalSegmentReset(Integer taskNo, long waitMs) { if (redisUtil == null || taskNo == null || taskNo <= 0) { return; } String key = RedisKeyType.DEVICE_STATION_MOVE_RESET.key + taskNo; redisUtil.set(key, "cancel", 3); try { if (waitMs > 0L) { Thread.sleep(waitMs); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (Exception ignore) { } redisUtil.del(key); } public StationCommand loadWatchCircleCommand(Integer wrkNo) { if (wrkNo == null || wrkNo <= 0 || redisUtil == null) { return null; } Object circleObj = redisUtil.get(RedisKeyType.WATCH_CIRCLE_STATION_.key + wrkNo); if (circleObj == null) { return null; } try { return JSON.parseObject(circleObj.toString(), StationCommand.class); } catch (Exception ignore) { return null; } } public void saveWatchCircleCommand(Integer wrkNo, StationCommand command) { if (wrkNo == null || wrkNo <= 0 || command == null || redisUtil == null) { return; } redisUtil.set( RedisKeyType.WATCH_CIRCLE_STATION_.key + wrkNo, JSON.toJSONString(command, SerializerFeature.DisableCircularReferenceDetect), 60 * 60 * 24 ); } public void clearWatchCircleCommand(Integer wrkNo) { if (wrkNo == null || wrkNo <= 0 || redisUtil == null) { return; } redisUtil.del(RedisKeyType.WATCH_CIRCLE_STATION_.key + wrkNo); } private List listIssuedMoveCommandsDuringIdleStay(StationTaskIdleTrack idleTrack, Integer taskNo) { if (idleTrack == null || taskNo == null || taskNo <= 0 || idleTrack.getFirstSeenTime() == null || basStationOptService == null) { return Collections.emptyList(); } List optList = basStationOptService.list(new QueryWrapper() .select("id", "task_no", "send_time", "target_station_id", "memo", "send") .eq("task_no", taskNo) .eq("mode", String.valueOf(StationCommandType.MOVE)) .eq("send", 1) .ge("send_time", new Date(idleTrack.getFirstSeenTime())) .orderByAsc("send_time")); if (optList == null || optList.isEmpty()) { return Collections.emptyList(); } return optList; } private String buildIdleRecoverClearedMemo(Integer stationId) { if (stationId == null) { return IDLE_RECOVER_CLEARED_MEMO; } return IDLE_RECOVER_CLEARED_MEMO + "(stationId=" + stationId + ")"; } private String appendCleanupMemo(String memo, String cleanupMemo) { if (Cools.isEmpty(cleanupMemo)) { return memo; } if (Cools.isEmpty(memo)) { return cleanupMemo; } if (memo.contains(cleanupMemo)) { return memo; } return memo + " | " + cleanupMemo; } private boolean isBlank(String value) { return value == null || value.trim().isEmpty(); } }