| | |
| | | package com.zy.ai.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.zy.ai.domain.autotune.AutoTuneControlModeSnapshot; |
| | | import com.zy.ai.domain.autotune.AutoTuneTaskDetailItem; |
| | | import com.zy.ai.domain.autotune.AutoTuneParameterSnapshot; |
| | | import com.zy.ai.domain.autotune.AutoTuneRoutePressureSnapshot; |
| | | import com.zy.ai.domain.autotune.AutoTuneRuleDefinition; |
| | | import com.zy.ai.domain.autotune.AutoTuneRuleSnapshotItem; |
| | | 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.AutoTuneControlModeService; |
| | | import com.zy.ai.service.AutoTuneSnapshotService; |
| | | import com.zy.ai.service.FlowTopologySnapshotService; |
| | | import com.zy.ai.service.RoutePressureSnapshotService; |
| | | 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.BasDevp; |
| | | import com.zy.asrs.entity.BasDualCrnp; |
| | | import com.zy.asrs.entity.BasStation; |
| | | import com.zy.asrs.entity.DeviceConfig; |
| | | import com.zy.asrs.entity.WrkMast; |
| | | import com.zy.asrs.service.BasCrnpService; |
| | | import com.zy.asrs.service.BasDevpService; |
| | | import com.zy.asrs.service.BasDualCrnpService; |
| | | import com.zy.asrs.service.BasStationService; |
| | | import com.zy.asrs.service.DeviceConfigService; |
| | |
| | | import com.zy.asrs.service.WrkMastService; |
| | | import com.zy.core.cache.SlaveConnection; |
| | | import com.zy.core.enums.SlaveType; |
| | | import com.zy.core.enums.WrkIoType; |
| | | import com.zy.core.enums.WrkStsType; |
| | | import com.zy.core.model.StationObjModel; |
| | | import com.zy.core.model.protocol.StationProtocol; |
| | | import com.zy.core.thread.StationThread; |
| | | import com.zy.system.service.ConfigService; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | 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.Comparator; |
| | | 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 Logger LOGGER = LoggerFactory.getLogger(AutoTuneSnapshotServiceImpl.class); |
| | | |
| | | 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 int OUTBOUND_TASK_SAMPLE_LIMIT = 50; |
| | | private static final int STATION_LIMIT_BLOCKED_TASK_LIMIT = 50; |
| | | private static final int SYSTEM_MESSAGE_LIMIT = 160; |
| | | @Autowired |
| | | private WrkMastService wrkMastService; |
| | | |
| | |
| | | private FlowTopologySnapshotService flowTopologySnapshotService; |
| | | |
| | | @Autowired |
| | | private RoutePressureSnapshotService routePressureSnapshotService; |
| | | |
| | | @Autowired |
| | | private AutoTuneControlModeService autoTuneControlModeService; |
| | | |
| | | @Autowired |
| | | private ConfigService configService; |
| | | |
| | | @Autowired |
| | | private BasStationService basStationService; |
| | | |
| | | @Autowired |
| | | private BasDevpService basDevpService; |
| | | |
| | | @Autowired |
| | | private BasCrnpService basCrnpService; |
| | |
| | | |
| | | @Override |
| | | public AutoTuneSnapshot buildSnapshot() { |
| | | List<WrkMast> activeTasks = loadActiveTasks(); |
| | | AutoTuneTaskSnapshot taskSnapshot = buildTaskSnapshot(activeTasks); |
| | | List<AutoTuneStationRuntimeItem> stationRuntimeSnapshot = buildStationRuntimeSnapshot(); |
| | | AutoTuneRoutePressureSnapshot routePressureSnapshot = buildRoutePressureSnapshot( |
| | | activeTasks, |
| | | taskSnapshot, |
| | | stationRuntimeSnapshot |
| | | ); |
| | | |
| | | AutoTuneSnapshot snapshot = new AutoTuneSnapshot(); |
| | | snapshot.setTaskSnapshot(buildTaskSnapshot()); |
| | | snapshot.setTaskSnapshot(taskSnapshot); |
| | | snapshot.setStationRuntimeSnapshot(stationRuntimeSnapshot); |
| | | snapshot.setRoutePressureSnapshot(routePressureSnapshot); |
| | | snapshot.setCycleLoadSnapshot(buildCycleLoadSnapshot()); |
| | | snapshot.setFlowTopologySnapshot(flowTopologySnapshotService.buildSnapshot(stationRuntimeSnapshot)); |
| | | snapshot.setCurrentParameterSnapshot(buildCurrentParameterSnapshot()); |
| | | snapshot.setRuleSnapshot(buildRuleSnapshot()); |
| | | snapshot.setControlModeSnapshot(buildControlModeSnapshot()); |
| | | snapshot.setSnapshotTime(new Date()); |
| | | return snapshot; |
| | | } |
| | | |
| | | private AutoTuneTaskSnapshot buildTaskSnapshot() { |
| | | List<WrkMast> activeTasks = loadActiveTasks(); |
| | | private AutoTuneControlModeSnapshot buildControlModeSnapshot() { |
| | | return autoTuneControlModeService.currentMode(); |
| | | } |
| | | |
| | | List<AutoTuneRuleSnapshotItem> buildRuleSnapshot() { |
| | | List<AutoTuneRuleSnapshotItem> result = new ArrayList<>(); |
| | | for (AutoTuneRuleDefinition.Rule rule : AutoTuneRuleDefinition.rules().values()) { |
| | | AutoTuneRuleSnapshotItem item = new AutoTuneRuleSnapshotItem(); |
| | | item.setTargetType(rule.getTargetType().getCode()); |
| | | item.setTargetKey(rule.getTargetKey()); |
| | | item.setMinValue(rule.getMinValue()); |
| | | item.setMaxValue(rule.getMaxValue()); |
| | | item.setMaxStep(rule.getMaxStep()); |
| | | item.setCooldownMinutes(rule.getCooldownMinutes()); |
| | | item.setDynamicMaxValue(rule.isDynamicMaxValue()); |
| | | item.setDynamicMaxSource(rule.getDynamicMaxSource()); |
| | | item.setNote(rule.getNote()); |
| | | result.add(item); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | private AutoTuneTaskSnapshot buildTaskSnapshot() { |
| | | return buildTaskSnapshot(loadActiveTasks()); |
| | | } |
| | | |
| | | private AutoTuneTaskSnapshot buildTaskSnapshot(List<WrkMast> activeTasks) { |
| | | AutoTuneTaskSnapshot snapshot = new AutoTuneTaskSnapshot(); |
| | | snapshot.setActiveTaskCount(activeTasks.size()); |
| | | snapshot.setStationLimitBlockedTasks(buildStationLimitBlockedTasks(activeTasks)); |
| | | snapshot.setOutboundTaskSamples(buildOutboundTaskSamples(activeTasks)); |
| | | snapshot.setByTargetStation(countByTargetStation(activeTasks)); |
| | | snapshot.setByBatch(countByBatch(activeTasks)); |
| | | snapshot.setByStatus(countByStatus(activeTasks)); |
| | | snapshot.setByCrn(countByCrn(activeTasks)); |
| | | snapshot.setByDualCrn(countByDualCrn(activeTasks)); |
| | | snapshot.setByIoType(countByIoType(activeTasks)); |
| | | return snapshot; |
| | | } |
| | | |
| | | private AutoTuneRoutePressureSnapshot buildRoutePressureSnapshot(List<WrkMast> activeTasks, |
| | | AutoTuneTaskSnapshot taskSnapshot, |
| | | List<AutoTuneStationRuntimeItem> stationRuntimeSnapshot) { |
| | | if (routePressureSnapshotService == null) { |
| | | return new AutoTuneRoutePressureSnapshot(); |
| | | } |
| | | try { |
| | | AutoTuneRoutePressureSnapshot snapshot = routePressureSnapshotService.buildSnapshot( |
| | | activeTasks, |
| | | taskSnapshot, |
| | | stationRuntimeSnapshot |
| | | ); |
| | | return snapshot == null ? new AutoTuneRoutePressureSnapshot() : snapshot; |
| | | } catch (Exception exception) { |
| | | LOGGER.warn( |
| | | "Build auto tune route pressure snapshot failed, fallback to empty snapshot. activeTaskCount={}, stationRuntimeCount={}", |
| | | safeList(activeTasks).size(), |
| | | safeList(stationRuntimeSnapshot).size(), |
| | | exception |
| | | ); |
| | | return new AutoTuneRoutePressureSnapshot(); |
| | | } |
| | | } |
| | | |
| | | private List<AutoTuneTaskDetailItem> buildStationLimitBlockedTasks(List<WrkMast> activeTasks) { |
| | | List<AutoTuneTaskDetailItem> result = new ArrayList<>(); |
| | | for (WrkMast task : sortOutboundTasks(activeTasks)) { |
| | | if (!hasStationLimitBlockedMessage(task)) { |
| | | continue; |
| | | } |
| | | result.add(toTaskDetailItem(task)); |
| | | if (result.size() >= STATION_LIMIT_BLOCKED_TASK_LIMIT) { |
| | | break; |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | private List<AutoTuneTaskDetailItem> buildOutboundTaskSamples(List<WrkMast> activeTasks) { |
| | | List<AutoTuneTaskDetailItem> result = new ArrayList<>(); |
| | | for (WrkMast task : sortOutboundTasks(activeTasks)) { |
| | | result.add(toTaskDetailItem(task)); |
| | | if (result.size() >= OUTBOUND_TASK_SAMPLE_LIMIT) { |
| | | break; |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | private List<WrkMast> sortOutboundTasks(List<WrkMast> activeTasks) { |
| | | List<WrkMast> outboundTasks = new ArrayList<>(); |
| | | for (WrkMast task : safeList(activeTasks)) { |
| | | if (isOutboundTask(task)) { |
| | | outboundTasks.add(task); |
| | | } |
| | | } |
| | | outboundTasks.sort(Comparator |
| | | .comparing(this::taskBatch, Comparator.nullsLast(String::compareTo)) |
| | | .thenComparing(this::taskBatchSeq, Comparator.nullsLast(Integer::compareTo)) |
| | | .thenComparing(this::taskWrkNo, Comparator.nullsLast(Integer::compareTo))); |
| | | return outboundTasks; |
| | | } |
| | | |
| | | private boolean isOutboundTask(WrkMast task) { |
| | | return task != null && Integer.valueOf(WrkIoType.OUT.id).equals(task.getIoType()); |
| | | } |
| | | |
| | | private boolean hasStationLimitBlockedMessage(WrkMast task) { |
| | | if (task == null || task.getSystemMsg() == null) { |
| | | return false; |
| | | } |
| | | return task.getSystemMsg().contains("出库任务上限"); |
| | | } |
| | | |
| | | private AutoTuneTaskDetailItem toTaskDetailItem(WrkMast task) { |
| | | AutoTuneTaskDetailItem item = new AutoTuneTaskDetailItem(); |
| | | item.setWrkNo(task.getWrkNo()); |
| | | item.setWrkSts(task.getWrkSts()); |
| | | item.setWrkStsDesc(wrkStsDesc(task.getWrkSts())); |
| | | item.setIoType(task.getIoType()); |
| | | item.setIoTypeDesc(ioTypeDesc(task.getIoType())); |
| | | item.setStaNo(task.getStaNo()); |
| | | item.setSourceStaNo(task.getSourceStaNo()); |
| | | item.setSourceLocNo(task.getSourceLocNo()); |
| | | item.setCrnNo(task.getCrnNo()); |
| | | item.setDualCrnNo(task.getDualCrnNo()); |
| | | item.setBatch(task.getBatch()); |
| | | item.setBatchSeq(task.getBatchSeq()); |
| | | item.setIoTime(task.getIoTime()); |
| | | item.setSystemMsg(limitText(task.getSystemMsg(), SYSTEM_MESSAGE_LIMIT)); |
| | | return item; |
| | | } |
| | | |
| | | private String wrkStsDesc(Long wrkSts) { |
| | | if (wrkSts == null) { |
| | | return null; |
| | | } |
| | | try { |
| | | return WrkStsType.query(wrkSts).desc; |
| | | } catch (Exception ignore) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | private String ioTypeDesc(Integer ioType) { |
| | | if (ioType == null) { |
| | | return null; |
| | | } |
| | | WrkIoType wrkIoType = WrkIoType.get(ioType); |
| | | return wrkIoType == null ? null : wrkIoType.desc; |
| | | } |
| | | |
| | | private String limitText(String value, int maxLength) { |
| | | if (value == null || value.length() <= maxLength) { |
| | | return value; |
| | | } |
| | | return value.substring(0, maxLength); |
| | | } |
| | | |
| | | private String taskBatch(WrkMast task) { |
| | | return task == null ? null : task.getBatch(); |
| | | } |
| | | |
| | | private Integer taskBatchSeq(WrkMast task) { |
| | | return task == null ? null : task.getBatchSeq(); |
| | | } |
| | | |
| | | private Integer taskWrkNo(WrkMast task) { |
| | | return task == null ? null : task.getWrkNo(); |
| | | } |
| | | |
| | | private List<WrkMast> loadActiveTasks() { |
| | |
| | | return Collections.emptyList(); |
| | | } |
| | | QueryWrapper<WrkMast> wrapper = new QueryWrapper<>(); |
| | | wrapper.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 |
| | | )); |
| | | 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)); |
| | | } |
| | | |
| | |
| | | item.setAutoing(protocol.isAutoing() ? 1 : 0); |
| | | item.setLoading(protocol.isLoading() ? 1 : 0); |
| | | item.setTaskNo(protocol.getTaskNo() == null ? 0 : protocol.getTaskNo()); |
| | | item.setRunBlock(protocol.isRunBlock() ? 1 : 0); |
| | | item.setIoMode(protocol.getIoMode() == null ? null : String.valueOf(protocol.getIoMode())); |
| | | return item; |
| | | } |
| | |
| | | )); |
| | | List<BasCrnp> crnList = loadCrnList(); |
| | | List<BasDualCrnp> dualCrnList = loadDualCrnList(); |
| | | snapshot.setStationOutTaskLimits(loadStationOutTaskLimits()); |
| | | List<BasStation> outStationList = loadOutStationList(); |
| | | snapshot.setStationOutTaskLimits(buildStationOutTaskLimitMap(outStationList)); |
| | | snapshot.setStationOutBufferCapacities(buildStationOutBufferCapacityMap(outStationList)); |
| | | snapshot.setCrnMaxOutTask(buildCrnMaxOutTask(crnList)); |
| | | snapshot.setCrnMaxInTask(buildCrnMaxInTask(crnList)); |
| | | snapshot.setDualCrnMaxOutTask(buildDualCrnMaxOutTask(dualCrnList)); |
| | |
| | | } |
| | | } |
| | | |
| | | private Map<String, Integer> loadStationOutTaskLimits() { |
| | | Map<String, Integer> result = new LinkedHashMap<>(); |
| | | private List<BasStation> loadOutStationList() { |
| | | if (basStationService == null) { |
| | | return result; |
| | | return Collections.emptyList(); |
| | | } |
| | | Set<Integer> outStationIds = loadOutStationIds(); |
| | | if (outStationIds.isEmpty()) { |
| | | return Collections.emptyList(); |
| | | } |
| | | QueryWrapper<BasStation> wrapper = new QueryWrapper<>(); |
| | | wrapper.in("station_id", outStationIds); |
| | | wrapper.orderByAsc("station_id"); |
| | | return buildStationOutTaskLimitMap(basStationService.list(wrapper)); |
| | | return safeList(basStationService.list(wrapper)); |
| | | } |
| | | |
| | | private Set<Integer> loadOutStationIds() { |
| | | LinkedHashSet<Integer> stationIds = new LinkedHashSet<>(); |
| | | if (basDevpService == null) { |
| | | return stationIds; |
| | | } |
| | | QueryWrapper<BasDevp> wrapper = new QueryWrapper<>(); |
| | | wrapper.eq("status", 1); |
| | | wrapper.orderByAsc("devp_no"); |
| | | List<BasDevp> basDevpList = safeList(basDevpService.list(wrapper)); |
| | | for (BasDevp basDevp : basDevpList) { |
| | | if (basDevp == null) { |
| | | continue; |
| | | } |
| | | List<StationObjModel> outStationList = safeList(basDevp.getOutStationList$()); |
| | | for (StationObjModel stationObjModel : outStationList) { |
| | | if (stationObjModel != null && stationObjModel.getStationId() != null) { |
| | | stationIds.add(stationObjModel.getStationId()); |
| | | } |
| | | } |
| | | } |
| | | return stationIds; |
| | | } |
| | | |
| | | Map<String, Integer> buildStationOutTaskLimitMap(List<BasStation> stationList) { |
| | |
| | | for (BasStation station : safeList(stationList)) { |
| | | if (station != null && station.getStationId() != null) { |
| | | result.put(String.valueOf(station.getStationId()), station.getOutTaskLimit()); |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | Map<String, Integer> buildStationOutBufferCapacityMap(List<BasStation> stationList) { |
| | | Map<String, Integer> result = new LinkedHashMap<>(); |
| | | for (BasStation station : safeList(stationList)) { |
| | | if (station != null && station.getStationId() != null) { |
| | | result.put(String.valueOf(station.getStationId()), station.getOutBufferCapacity()); |
| | | } |
| | | } |
| | | return result; |
| | |
| | | return result; |
| | | } |
| | | |
| | | private Map<String, Integer> countByStatus(List<WrkMast> activeTasks) { |
| | | Map<String, Integer> result = new LinkedHashMap<>(); |
| | | for (WrkMast task : activeTasks) { |
| | | Long wrkSts = task == null ? null : task.getWrkSts(); |
| | | increment(result, wrkSts == null ? null : String.valueOf(wrkSts)); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | private Map<String, Integer> countByCrn(List<WrkMast> activeTasks) { |
| | | Map<String, Integer> result = new LinkedHashMap<>(); |
| | | for (WrkMast task : activeTasks) { |