package com.zy.ai.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.zy.ai.domain.autotune.AutoTuneParameterSnapshot; import com.zy.ai.domain.autotune.AutoTuneSnapshot; import com.zy.ai.domain.autotune.AutoTuneStationRuntimeItem; import com.zy.ai.domain.autotune.AutoTuneTaskSnapshot; import com.zy.ai.service.AutoTuneSnapshotService; import com.zy.ai.service.FlowTopologySnapshotService; import com.zy.asrs.domain.vo.StationCycleCapacityVo; import com.zy.asrs.domain.vo.StationCycleLoopVo; import com.zy.asrs.entity.BasCrnp; import com.zy.asrs.entity.BasDualCrnp; import com.zy.asrs.entity.BasStation; import com.zy.asrs.entity.DeviceConfig; import com.zy.asrs.entity.StationFlowCapacity; import com.zy.asrs.entity.WrkMast; import com.zy.asrs.service.BasCrnpService; import com.zy.asrs.service.BasDualCrnpService; import com.zy.asrs.service.BasStationService; import com.zy.asrs.service.DeviceConfigService; import com.zy.asrs.service.StationCycleCapacityService; import com.zy.asrs.service.StationFlowCapacityService; import com.zy.asrs.service.WrkMastService; import com.zy.core.cache.SlaveConnection; import com.zy.core.enums.SlaveType; import com.zy.core.enums.WrkStsType; import com.zy.core.model.protocol.StationProtocol; import com.zy.core.thread.StationThread; import com.zy.system.service.ConfigService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.LinkedHashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @Service("autoTuneSnapshotService") public class AutoTuneSnapshotServiceImpl implements AutoTuneSnapshotService { private static final int DEFAULT_CRN_OUT_BATCH_RUNNING_LIMIT = 5; private static final int DEFAULT_CONVEYOR_STATION_TASK_LIMIT = 30; private static final int DEFAULT_AI_AUTO_TUNE_INTERVAL_MINUTES = 10; private static final String DIRECTION_OUT = "OUT"; @Autowired private WrkMastService wrkMastService; @Autowired private DeviceConfigService deviceConfigService; @Autowired private StationCycleCapacityService stationCycleCapacityService; @Autowired private FlowTopologySnapshotService flowTopologySnapshotService; @Autowired private ConfigService configService; @Autowired private BasStationService basStationService; @Autowired private StationFlowCapacityService stationFlowCapacityService; @Autowired private BasCrnpService basCrnpService; @Autowired private BasDualCrnpService basDualCrnpService; @Override public AutoTuneSnapshot buildSnapshot() { List stationRuntimeSnapshot = buildStationRuntimeSnapshot(); AutoTuneSnapshot snapshot = new AutoTuneSnapshot(); snapshot.setTaskSnapshot(buildTaskSnapshot()); snapshot.setStationRuntimeSnapshot(stationRuntimeSnapshot); snapshot.setCycleLoadSnapshot(buildCycleLoadSnapshot()); snapshot.setFlowTopologySnapshot(flowTopologySnapshotService.buildSnapshot(stationRuntimeSnapshot)); snapshot.setCurrentParameterSnapshot(buildCurrentParameterSnapshot()); snapshot.setSnapshotTime(new Date()); return snapshot; } private AutoTuneTaskSnapshot buildTaskSnapshot() { List activeTasks = loadActiveTasks(); AutoTuneTaskSnapshot snapshot = new AutoTuneTaskSnapshot(); snapshot.setActiveTaskCount(activeTasks.size()); snapshot.setByTargetStation(countByTargetStation(activeTasks)); snapshot.setByBatch(countByBatch(activeTasks)); snapshot.setByCrn(countByCrn(activeTasks)); snapshot.setByDualCrn(countByDualCrn(activeTasks)); snapshot.setByIoType(countByIoType(activeTasks)); return snapshot; } private List loadActiveTasks() { if (wrkMastService == null) { return Collections.emptyList(); } QueryWrapper wrapper = new QueryWrapper<>(); wrapper.and(query -> query.notIn("wrk_sts", Arrays.asList( WrkStsType.COMPLETE_INBOUND.sts, WrkStsType.SETTLE_INBOUND.sts, WrkStsType.COMPLETE_OUTBOUND.sts, WrkStsType.SETTLE_OUTBOUND.sts, WrkStsType.COMPLETE_LOC_MOVE.sts, WrkStsType.COMPLETE_CRN_MOVE.sts )) .or() .isNull("wrk_sts")); return safeList(wrkMastService.list(wrapper)); } private List buildStationRuntimeSnapshot() { if (deviceConfigService == null) { return Collections.emptyList(); } QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("device_type", String.valueOf(SlaveType.Devp)); wrapper.orderByAsc("device_no"); List deviceConfigList = safeList(deviceConfigService.list(wrapper)); Map runtimeMap = new LinkedHashMap<>(); for (DeviceConfig deviceConfig : deviceConfigList) { appendStationRuntime(runtimeMap, deviceConfig); } return new ArrayList<>(runtimeMap.values()); } private void appendStationRuntime(Map runtimeMap, DeviceConfig deviceConfig) { if (deviceConfig == null || deviceConfig.getDeviceNo() == null) { return; } StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, deviceConfig.getDeviceNo()); if (stationThread == null || stationThread.getStatusMap() == null) { return; } for (StationProtocol protocol : stationThread.getStatusMap().values()) { AutoTuneStationRuntimeItem runtimeItem = toRuntimeItem(protocol); if (runtimeItem != null) { runtimeMap.put(runtimeItem.getStationId(), runtimeItem); } } } private AutoTuneStationRuntimeItem toRuntimeItem(StationProtocol protocol) { if (protocol == null || protocol.getStationId() == null) { return null; } AutoTuneStationRuntimeItem item = new AutoTuneStationRuntimeItem(); item.setStationId(protocol.getStationId()); item.setAutoing(protocol.isAutoing() ? 1 : 0); item.setLoading(protocol.isLoading() ? 1 : 0); item.setTaskNo(protocol.getTaskNo() == null ? 0 : protocol.getTaskNo()); item.setIoMode(protocol.getIoMode() == null ? null : String.valueOf(protocol.getIoMode())); return item; } private Map buildCycleLoadSnapshot() { if (stationCycleCapacityService == null) { return new LinkedHashMap<>(); } return toCycleLoadMap(stationCycleCapacityService.getLatestSnapshot()); } private Map toCycleLoadMap(StationCycleCapacityVo cycleCapacityVo) { Map result = new LinkedHashMap<>(); if (cycleCapacityVo == null) { return result; } result.put("loopList", toLoopMapList(cycleCapacityVo.getLoopList())); result.put("loopCount", cycleCapacityVo.getLoopCount()); result.put("totalStationCount", cycleCapacityVo.getTotalStationCount()); result.put("taskStationCount", cycleCapacityVo.getTaskStationCount()); result.put("manualStationCount", cycleCapacityVo.getManualStationCount()); result.put("occupiedStationCount", cycleCapacityVo.getOccupiedStationCount()); result.put("currentLoad", cycleCapacityVo.getCurrentLoad()); result.put("refreshTime", cycleCapacityVo.getRefreshTime()); return result; } private List> toLoopMapList(List loopList) { List> result = new ArrayList<>(); for (StationCycleLoopVo loopVo : safeList(loopList)) { if (loopVo == null) { continue; } Map loopMap = new LinkedHashMap<>(); loopMap.put("loopNo", loopVo.getLoopNo()); loopMap.put("stationIdList", loopVo.getStationIdList()); loopMap.put("workNoList", loopVo.getWorkNoList()); loopMap.put("stationCount", loopVo.getStationCount()); loopMap.put("taskCount", loopVo.getTaskCount()); loopMap.put("manualStationCount", loopVo.getManualStationCount()); loopMap.put("occupiedStationCount", loopVo.getOccupiedStationCount()); loopMap.put("currentLoad", loopVo.getCurrentLoad()); result.add(loopMap); } return result; } private AutoTuneParameterSnapshot buildCurrentParameterSnapshot() { AutoTuneParameterSnapshot snapshot = new AutoTuneParameterSnapshot(); snapshot.setCrnOutBatchRunningLimit(readConfigInt( "crnOutBatchRunningLimit", DEFAULT_CRN_OUT_BATCH_RUNNING_LIMIT )); snapshot.setConveyorStationTaskLimit(readConfigInt( "conveyorStationTaskLimit", DEFAULT_CONVEYOR_STATION_TASK_LIMIT )); snapshot.setAiAutoTuneIntervalMinutes(readConfigInt( "aiAutoTuneIntervalMinutes", DEFAULT_AI_AUTO_TUNE_INTERVAL_MINUTES )); List crnList = loadCrnList(); List dualCrnList = loadDualCrnList(); snapshot.setStationOutTaskLimits(loadStationOutTaskLimits()); snapshot.setCrnMaxOutTask(buildCrnMaxOutTask(crnList)); snapshot.setCrnMaxInTask(buildCrnMaxInTask(crnList)); snapshot.setDualCrnMaxOutTask(buildDualCrnMaxOutTask(dualCrnList)); snapshot.setDualCrnMaxInTask(buildDualCrnMaxInTask(dualCrnList)); return snapshot; } private int readConfigInt(String code, int defaultValue) { if (configService == null) { return defaultValue; } String value = configService.getConfigValue(code, String.valueOf(defaultValue)); if (value == null || value.trim().isEmpty()) { return defaultValue; } try { return Integer.parseInt(value.trim()); } catch (NumberFormatException exception) { return defaultValue; } } private Map loadStationOutTaskLimits() { Map result = new LinkedHashMap<>(); if (basStationService == null) { return result; } Set outStationIds = loadOutStationIds(); if (outStationIds.isEmpty()) { return result; } QueryWrapper wrapper = new QueryWrapper<>(); wrapper.in("station_id", outStationIds); wrapper.orderByAsc("station_id"); return buildStationOutTaskLimitMap(basStationService.list(wrapper)); } private Set loadOutStationIds() { LinkedHashSet stationIds = new LinkedHashSet<>(); if (stationFlowCapacityService == null) { return stationIds; } QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("direction_code", DIRECTION_OUT); wrapper.orderByAsc("station_id"); List capacityList = safeList(stationFlowCapacityService.list(wrapper)); for (StationFlowCapacity capacity : capacityList) { if (capacity != null && capacity.getStationId() != null) { stationIds.add(capacity.getStationId()); } } return stationIds; } Map buildStationOutTaskLimitMap(List stationList) { Map result = new LinkedHashMap<>(); for (BasStation station : safeList(stationList)) { if (station != null && station.getStationId() != null) { result.put(String.valueOf(station.getStationId()), station.getOutTaskLimit()); } } return result; } private Map buildCrnMaxOutTask(List crnList) { Map result = new LinkedHashMap<>(); for (BasCrnp crn : safeList(crnList)) { if (crn == null || crn.getCrnNo() == null) { continue; } result.put(String.valueOf(crn.getCrnNo()), defaultInt(crn.getMaxOutTask())); } return result; } private Map buildCrnMaxInTask(List crnList) { Map result = new LinkedHashMap<>(); for (BasCrnp crn : safeList(crnList)) { if (crn == null || crn.getCrnNo() == null) { continue; } result.put(String.valueOf(crn.getCrnNo()), defaultInt(crn.getMaxInTask())); } return result; } private Map buildDualCrnMaxOutTask(List dualCrnList) { Map result = new LinkedHashMap<>(); for (BasDualCrnp dualCrn : safeList(dualCrnList)) { if (dualCrn == null || dualCrn.getCrnNo() == null) { continue; } result.put(String.valueOf(dualCrn.getCrnNo()), defaultInt(dualCrn.getMaxOutTask())); } return result; } private Map buildDualCrnMaxInTask(List dualCrnList) { Map result = new LinkedHashMap<>(); for (BasDualCrnp dualCrn : safeList(dualCrnList)) { if (dualCrn == null || dualCrn.getCrnNo() == null) { continue; } result.put(String.valueOf(dualCrn.getCrnNo()), defaultInt(dualCrn.getMaxInTask())); } return result; } private List loadCrnList() { if (basCrnpService == null) { return Collections.emptyList(); } QueryWrapper wrapper = new QueryWrapper<>(); wrapper.orderByAsc("crn_no"); return safeList(basCrnpService.list(wrapper)); } private List loadDualCrnList() { if (basDualCrnpService == null) { return Collections.emptyList(); } QueryWrapper wrapper = new QueryWrapper<>(); wrapper.orderByAsc("crn_no"); return safeList(basDualCrnpService.list(wrapper)); } private Map countByTargetStation(List activeTasks) { Map result = new LinkedHashMap<>(); for (WrkMast task : activeTasks) { increment(result, task == null ? null : task.getStaNo()); } return result; } private Map countByBatch(List activeTasks) { Map result = new LinkedHashMap<>(); for (WrkMast task : activeTasks) { String batch = task == null ? null : task.getBatch(); if (batch != null && !batch.trim().isEmpty()) { increment(result, batch.trim()); } } return result; } private Map countByCrn(List activeTasks) { Map result = new LinkedHashMap<>(); for (WrkMast task : activeTasks) { increment(result, task == null ? null : task.getCrnNo()); } return result; } private Map countByDualCrn(List activeTasks) { Map result = new LinkedHashMap<>(); for (WrkMast task : activeTasks) { increment(result, task == null ? null : task.getDualCrnNo()); } return result; } private Map countByIoType(List activeTasks) { Map result = new LinkedHashMap<>(); for (WrkMast task : activeTasks) { increment(result, task == null ? null : task.getIoType()); } return result; } private void increment(Map result, Integer key) { if (key == null) { return; } increment(result, String.valueOf(key)); } private void increment(Map result, String key) { if (key == null || key.trim().isEmpty()) { return; } String normalizedKey = key.trim(); result.put(normalizedKey, result.getOrDefault(normalizedKey, 0) + 1); } private int defaultInt(Integer value) { return value == null ? 0 : value; } private List safeList(List value) { return value == null ? Collections.emptyList() : value; } }