package com.zy.core.network.fake; import com.alibaba.fastjson.JSON; import com.zy.asrs.entity.DeviceConfig; import com.zy.core.News; import com.zy.core.model.CommandResponse; import com.zy.core.model.protocol.StationTaskBufferItem; import com.zy.core.network.entity.ZyStationStatusEntity; import com.zy.core.thread.support.StationTaskLocationRegistry; import com.core.common.SpringUtils; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Random; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.locks.ReentrantLock; public class FakeStationStateManager { private final StationTaskLocationRegistry stationTaskLocationRegistry = SpringUtils.getBean(StationTaskLocationRegistry.class); private interface StationMutation { void apply(ZyStationStatusEntity status); } private interface StationRead { T apply(ZyStationStatusEntity status); } private final Map> deviceStatusMap = new ConcurrentHashMap>(); private final Map deviceConfigMap = new ConcurrentHashMap(); private final Map stationLocks = new ConcurrentHashMap(); private interface StationLockedMutation { void apply(ZyStationStatusEntity status); } private interface StationLockedRead { T apply(ZyStationStatusEntity status); } private ReentrantLock getStationLock(Integer stationId) { return stationLocks.computeIfAbsent(stationId, key -> new ReentrantLock()); } public void lockStations(Integer... stationIds) { if (stationIds == null || stationIds.length == 0) { return; } Integer[] sorted = java.util.Arrays.copyOf(stationIds, stationIds.length); java.util.Arrays.sort(sorted); for (Integer stationId : sorted) { if (stationId != null) { getStationLock(stationId).lock(); } } } public void unlockStations(Integer... stationIds) { if (stationIds == null || stationIds.length == 0) { return; } Integer[] sorted = java.util.Arrays.copyOf(stationIds, stationIds.length); java.util.Arrays.sort(sorted); for (int i = sorted.length - 1; i >= 0; i--) { Integer stationId = sorted[i]; if (stationId != null) { getStationLock(stationId).unlock(); } } } private boolean mutateLockedStation(Integer deviceNo, Integer stationId, StationLockedMutation mutation) { if (stationId == null || mutation == null) { return false; } lockStations(stationId); try { ZyStationStatusEntity status = findStationStatus(deviceNo, stationId); if (status == null) { return false; } mutation.apply(status); return true; } finally { unlockStations(stationId); } } private T readLockedStation(Integer deviceNo, Integer stationId, StationLockedRead read) { if (stationId == null || read == null) { return null; } lockStations(stationId); try { ZyStationStatusEntity status = findStationStatus(deviceNo, stationId); if (status == null) { return null; } return read.apply(status); } finally { unlockStations(stationId); } } private boolean updateStationDataWithinLock(Integer stationId, Integer deviceNo, Integer taskNo, Integer targetStaNo, Boolean isLoading, String barcode, Boolean runBlock) { ZyStationStatusEntity currentStatus = findStationStatus(deviceNo, stationId); 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); } syncTaskLocationInternal(deviceNo, currentStatus); return true; } public void registerDevice(DeviceConfig deviceConfig) { if (deviceConfigMap.containsKey(deviceConfig.getDeviceNo())) { return; } deviceConfigMap.put(deviceConfig.getDeviceNo(), deviceConfig); deviceStatusMap.put(deviceConfig.getDeviceNo(), new CopyOnWriteArrayList()); } public Map> getDeviceStatusMap() { return deviceStatusMap; } public Map getDeviceConfigMap() { return deviceConfigMap; } public List getStatus(Integer deviceNo) { List statusList = deviceStatusMap.get(deviceNo); if (statusList == null) { return new ArrayList(); } DeviceConfig deviceConfig = deviceConfigMap.get(deviceNo); if (statusList.isEmpty() && deviceConfig != null) { List 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.setIoMode(2); status.setEmptyMk(false); status.setFullPlt(false); status.setRunBlock(false); status.setPalletHeight(0); status.setError(0); status.setBarcode(""); } } } return statusList; } public ZyStationStatusEntity findStationStatus(Integer deviceNo, Integer stationId) { if (deviceNo == null || stationId == null) { return null; } List statusList = deviceStatusMap.get(deviceNo); if (statusList == null) { return null; } return statusList.stream() .filter(item -> item.getStationId().equals(stationId)) .findFirst().orElse(null); } public Integer getDeviceNoByStationId(Integer stationId) { for (Map.Entry> entry : deviceStatusMap.entrySet()) { List list = entry.getValue(); if (list == null) { continue; } for (ZyStationStatusEntity entity : list) { if (entity.getStationId() != null && entity.getStationId().equals(stationId)) { return entry.getKey(); } } } return null; } public Integer findCurrentStationIdByTask(Integer taskNo) { for (List list : deviceStatusMap.values()) { if (list == null) { continue; } for (ZyStationStatusEntity entity : list) { Integer stationId = entity == null ? null : entity.getStationId(); Integer matchedStationId = stationId == null ? null : readStation(getDeviceNoByStationId(stationId), stationId, new StationRead() { @Override public Integer apply(ZyStationStatusEntity status) { if (status.getTaskNo() != null && status.getTaskNo().equals(taskNo) && status.isLoading()) { return status.getStationId(); } return null; } }); if (matchedStationId != null) { return matchedStationId; } } } return null; } public String getThreadImpl(Integer deviceNo) { DeviceConfig deviceConfig = deviceConfigMap.get(deviceNo); return deviceConfig == null ? "" : deviceConfig.getThreadImpl(); } public boolean isStationLoadingTask(Integer deviceNo, Integer stationId, Integer taskNo) { Boolean result = readStation(deviceNo, stationId, new StationRead() { @Override public Boolean apply(ZyStationStatusEntity status) { return status.getTaskNo() != null && status.getTaskNo().equals(taskNo) && status.isLoading(); } }); return Boolean.TRUE.equals(result); } public boolean isStationClearedForTask(Integer deviceNo, Integer stationId, Integer taskNo) { Boolean result = readStation(deviceNo, stationId, new StationRead() { @Override public Boolean apply(ZyStationStatusEntity status) { boolean emptyStation = !status.isLoading() && (status.getTaskNo() == null || status.getTaskNo() <= 0); return emptyStation; } }); return result == null || result; } public boolean isFinalStationOwnerConflict(Integer deviceNo, Integer stationId, Integer taskNo) { Boolean result = readStation(deviceNo, stationId, new StationRead() { @Override public Boolean apply(ZyStationStatusEntity status) { return status.isLoading() && taskNo != null && status.getTaskNo() != null && status.getTaskNo() > 0 && !taskNo.equals(status.getTaskNo()); } }); return Boolean.TRUE.equals(result); } public boolean isOccupiedByOtherLoadingTask(Integer deviceNo, Integer stationId, Integer taskNo) { Boolean result = readStation(deviceNo, stationId, new StationRead() { @Override public Boolean apply(ZyStationStatusEntity status) { return status.isLoading() && status.getTaskNo() != null && status.getTaskNo() > 0 && (taskNo == null || !taskNo.equals(status.getTaskNo())); } }); return Boolean.TRUE.equals(result); } public ZyStationStatusEntity snapshotStation(Integer deviceNo, Integer stationId) { return readStation(deviceNo, stationId, new StationRead() { @Override public ZyStationStatusEntity apply(ZyStationStatusEntity status) { return JSON.parseObject(JSON.toJSONString(status), ZyStationStatusEntity.class); } }); } private boolean mutateStation(Integer deviceNo, Integer stationId, StationMutation mutation) { if (mutation == null) { return false; } return mutateLockedStation(deviceNo, stationId, new StationLockedMutation() { @Override public void apply(ZyStationStatusEntity status) { mutation.apply(status); } }); } private T readStation(Integer deviceNo, Integer stationId, StationRead read) { if (read == null) { return null; } return readLockedStation(deviceNo, stationId, new StationLockedRead() { @Override public T apply(ZyStationStatusEntity status) { return read.apply(status); } }); } public boolean updateStationDataWithHeldLock(Integer stationId, Integer deviceNo, Integer taskNo, Integer targetStaNo, Boolean isLoading, String barcode, Boolean runBlock) { return updateStationDataWithinLock(stationId, deviceNo, taskNo, targetStaNo, isLoading, barcode, runBlock); } public boolean updateStationDataInternal(Integer stationId, Integer deviceNo, Integer taskNo, Integer targetStaNo, Boolean isLoading, String barcode, Boolean runBlock) { return mutateLockedStation(deviceNo, stationId, new StationLockedMutation() { @Override public void apply(ZyStationStatusEntity currentStatus) { updateStationDataWithinLock(stationId, deviceNo, taskNo, targetStaNo, isLoading, barcode, runBlock); } }); } public void syncTaskLocation(Integer deviceNo, Integer stationId) { if (deviceNo == null || stationId == null) { return; } readStation(deviceNo, stationId, new StationRead() { @Override public Void apply(ZyStationStatusEntity status) { syncTaskLocationInternal(deviceNo, status); return null; } }); } public void removeTaskLocation(Integer taskNo, Integer deviceNo, Integer stationId) { if (stationTaskLocationRegistry == null || taskNo == null || taskNo <= 0) { return; } stationTaskLocationRegistry.remove(taskNo, deviceNo, stationId); } private void syncTaskLocationInternal(Integer deviceNo, ZyStationStatusEntity status) { if (stationTaskLocationRegistry == null || deviceNo == null || status == null) { return; } Integer taskNo = status.getTaskNo(); if (taskNo != null && taskNo > 0 && status.isLoading() && status.getStationId() != null) { stationTaskLocationRegistry.update(taskNo, deviceNo, status.getStationId(), true, status.isRunBlock(), System.currentTimeMillis()); } } public void clearTaskLocationIfMatches(Integer taskNo, Integer deviceNo, Integer stationId) { if (taskNo == null || taskNo <= 0 || deviceNo == null || stationId == null) { return; } readStation(deviceNo, stationId, new StationRead() { @Override public Void apply(ZyStationStatusEntity status) { if (status.getTaskNo() == null || !taskNo.equals(status.getTaskNo()) || !status.isLoading()) { removeTaskLocation(taskNo, deviceNo, stationId); } return null; } }); } public void publishTaskLocation(Integer taskNo, Integer deviceNo, Integer stationId, boolean loading, boolean runBlock) { if (stationTaskLocationRegistry == null || taskNo == null || taskNo <= 0 || deviceNo == null || stationId == null || !loading) { return; } stationTaskLocationRegistry.update(taskNo, deviceNo, stationId, true, runBlock, System.currentTimeMillis()); } public void generateStationData(Integer deviceNo, Integer taskNo, Integer stationId, Integer targetStationId) { mutateStation(deviceNo, stationId, new StationMutation() { @Override public void apply(ZyStationStatusEntity status) { News.info("仿真站点生成任务数据,设备号={},站点号={},原taskNo={},新taskNo={},原targetStaNo={},新targetStaNo={},原loading={},barcode={}", deviceNo, stationId, status.getTaskNo(), taskNo, status.getTargetStaNo(), targetStationId, status.isLoading(), status.getBarcode()); status.setTaskNo(taskNo); status.setTargetStaNo(targetStationId); status.setLoading(false); } }); } public void generateFakeOutStationData(Integer deviceNo, Integer stationId) { mutateStation(deviceNo, stationId, new StationMutation() { @Override public void apply(ZyStationStatusEntity status) { News.info("仿真出库站点数据生成,设备号={},站点号={},原taskNo={},原targetStaNo={},原loading={},原barcode={},动作=generateFakeOutStationData", deviceNo, stationId, status.getTaskNo(), status.getTargetStaNo(), status.isLoading(), status.getBarcode()); status.setLoading(true); News.info("仿真出库站点数据生成完成,设备号={},站点号={},新taskNo={},新targetStaNo={},新loading={},新barcode={}", deviceNo, stationId, status.getTaskNo(), status.getTargetStaNo(), status.isLoading(), status.getBarcode()); } }); } public void resetStation(Integer deviceNo, Integer stationId) { if (findStationStatus(deviceNo, stationId) == null) { return; } clearStationForDispatch(deviceNo, stationId, "resetStation"); } public void clearStationForDispatch(Integer deviceNo, Integer stationId, String reason) { mutateStation(deviceNo, stationId, new StationMutation() { @Override public void apply(ZyStationStatusEntity status) { News.info("仿真站点状态清除,设备号={},站点号={},原taskNo={},原targetStaNo={},原loading={},原barcode={},动作={}", deviceNo, stationId, status.getTaskNo(), status.getTargetStaNo(), status.isLoading(), status.getBarcode(), reason); status.setTaskNo(0); status.setTargetStaNo(0); status.setLoading(false); status.setBarcode(""); status.setRunBlock(false); } }); } public void handoffBarcodeStation(Integer deviceNo, Integer taskNo, Integer stationId, Integer targetStationId) { mutateLockedStation(deviceNo, stationId, new StationLockedMutation() { @Override public void apply(ZyStationStatusEntity status) { News.info("仿真站点生成任务数据,设备号={},站点号={},原taskNo={},新taskNo={},原targetStaNo={},新targetStaNo={},原loading={},barcode={}", deviceNo, stationId, status.getTaskNo(), taskNo, status.getTargetStaNo(), targetStationId, status.isLoading(), status.getBarcode()); status.setTaskNo(taskNo); status.setTargetStaNo(targetStationId); status.setLoading(false); News.info("仿真站点状态清除,设备号={},站点号={},原taskNo={},原targetStaNo={},原loading={},原barcode={},动作={}", deviceNo, stationId, status.getTaskNo(), status.getTargetStaNo(), status.isLoading(), status.getBarcode(), "barcodeTaskHandoff"); status.setTaskNo(0); status.setTargetStaNo(0); status.setLoading(false); status.setBarcode(""); status.setRunBlock(false); } }); } public void updateStationBarcode(Integer deviceNo, Integer stationId, String barcode) { mutateStation(deviceNo, stationId, new StationMutation() { @Override public void apply(ZyStationStatusEntity status) { status.setBarcode(barcode); } }); } public boolean generateStationBarcode(Integer lockTaskNo, Integer currentStationId, Integer currentStationDeviceNo) { ZyStationStatusEntity currentStatus = findStationStatus(currentStationDeviceNo, currentStationId); 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); } public CommandResponse clearTaskBufferSlot(Integer deviceNo, Integer stationId, Integer slotIdx) { if (deviceNo == null || stationId == null || slotIdx == null || slotIdx <= 0) { return new CommandResponse(false, "清理缓存区槽位参数无效"); } List statusList = deviceStatusMap.get(deviceNo); if (statusList == null) { return new CommandResponse(false, "未找到设备状态"); } for (ZyStationStatusEntity status : statusList) { if (status == null || !stationId.equals(status.getStationId())) { continue; } List 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, "未找到站点状态"); } }