From 6bde5b6f7f4ad8c1bac3732e46cf8d966deab845 Mon Sep 17 00:00:00 2001
From: vincentlu <t1341870251@gmail.com>
Date: 星期五, 27 二月 2026 16:23:05 +0800
Subject: [PATCH] #
---
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/GuaranteeRuntimeService.java | 169 +++++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 147 insertions(+), 22 deletions(-)
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/GuaranteeRuntimeService.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/GuaranteeRuntimeService.java
index 5c5abec..edebd10 100644
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/GuaranteeRuntimeService.java
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/GuaranteeRuntimeService.java
@@ -1,32 +1,157 @@
package com.zy.acs.manager.core.service;
-import com.zy.acs.manager.manager.entity.Guarantee;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.zy.acs.common.enums.AgvStatusType;
+import com.zy.acs.manager.manager.entity.*;
+import com.zy.acs.manager.manager.enums.*;
+import com.zy.acs.manager.manager.service.AgvDetailService;
+import com.zy.acs.manager.manager.service.AgvService;
+import com.zy.acs.manager.manager.service.SegmentService;
+import com.zy.acs.manager.manager.service.TaskService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Objects;
-/**
- * Runtime guarantee orchestration entry.
- */
-public interface GuaranteeRuntimeService {
+@Slf4j
+@Service
+public class GuaranteeRuntimeService {
- /**
- * Lead time entrance: make sure enough vehicles can reach the target window.
- */
- void prepare(Guarantee plan, LocalDateTime targetTime);
+ @Autowired
+ private SegmentService segmentService;
- /**
- * Lock stage: restrict non-essential dispatching for reserve vehicles.
- */
- void lock(Guarantee plan, LocalDateTime targetTime);
+ private final AgvService agvService;
+ private final AgvDetailService agvDetailService;
+ private final TaskService taskService;
+ private final MainLockWrapService mainLockWrapService;
- /**
- * Executed repeatedly during the guarantee window to keep SLA.
- */
- void checkWindow(Guarantee plan, LocalDateTime targetTime);
+ public GuaranteeRuntimeService(AgvService agvService,
+ AgvDetailService agvDetailService,
+ TaskService taskService,
+ MainLockWrapService mainLockWrapService) {
+ this.agvService = agvService;
+ this.agvDetailService = agvDetailService;
+ this.taskService = taskService;
+ this.mainLockWrapService = mainLockWrapService;
+ }
- /**
- * Called once after the window ends to release state/records.
- */
- void finish(Guarantee plan, LocalDateTime targetTime);
+ public void prepare(Guarantee plan, LocalDateTime targetTime) {
+ int requiredCount = plan.getRequiredCount() == null ? 0 : plan.getRequiredCount();
+ if (requiredCount <= 0) {
+ log.warn("Guarantee[{}] requiredCount is not configured, skip", plan.getName());
+ return;
+ }
+ int minSoc = plan.getMinSoc();
+ List<Agv> scopedAgvList = findScopedAgvList(plan);
+ int available = 0;
+ List<ChargeCandidate> candidates = new ArrayList<>();
+ for (Agv agv : scopedAgvList) {
+ AgvDetail detail = agvDetailService.selectMajorByAgvId(agv.getId());
+ if (null == detail || null == detail.getSoc() || null == detail.getAgvStatus()) {
+ continue;
+ }
+ if (detail.getAgvStatus().equals(AgvStatusType.CHARGE)) {
+ continue;
+ }
+ if (!isIdle(agv, detail)) {
+ continue;
+ }
+ int soc = detail.getSoc();
+ if (soc >= minSoc) {
+ available++;
+ } else {
+ candidates.add(new ChargeCandidate(agv, soc));
+ }
+ }
+ if (available >= requiredCount) {
+// log.debug("Guarantee[{}] already has {} vehicles >= {}% SOC for {}", plan.getName(), available, minSoc, targetTime);
+ return;
+ }
+ int shortage = requiredCount - available;
+ candidates.sort(Comparator.comparingInt(ChargeCandidate::getSoc));
+ int scheduled = 0;
+ for (ChargeCandidate candidate : candidates) {
+ if (scheduled >= shortage) {
+ break;
+ }
+ log.info("Guarantee[{}] schedule AGV {} charging (soc={}%) for target {}",
+ plan.getName(), candidate.getAgv().getName(), candidate.getSoc(), targetTime);
+ mainLockWrapService.buildMinorTask(candidate.getAgv().getId(), TaskTypeType.TO_CHARGE, null, null);
+ scheduled++;
+ }
+ if (scheduled < shortage) {
+ log.warn("Guarantee[{}] still short of {} vehicles for {} (only {} idle low-soc AGVs)",
+ plan.getName(), shortage - scheduled, targetTime, candidates.size());
+ }
+ }
+
+ private boolean isIdle(Agv agv, AgvDetail detail) {
+ if (!Objects.equals(agv.getStatus(), StatusType.ENABLE.val)) {
+ return false;
+ }
+ if (detail.getAgvStatus() != null && detail.getAgvStatus().equals(AgvStatusType.CHARGE)) {
+ return false;
+ }
+
+ if (0 < taskService.count(new LambdaQueryWrapper<Task>()
+ .eq(Task::getAgvId, agv.getId())
+// .and(i -> {
+// i.eq(Task::getTaskSts, TaskStsType.WAITING.val())
+// .or().eq(Task::getTaskSts, TaskStsType.ASSIGN.val())
+// .or().eq(Task::getTaskSts, TaskStsType.PROGRESS.val());
+// })
+ .in(Task::getTaskSts,
+ TaskStsType.WAITING.val(),
+ TaskStsType.ASSIGN.val(),
+ TaskStsType.PROGRESS.val())
+ )) {
+ return false;
+ }
+ if (0 < segmentService.count(new LambdaQueryWrapper<Segment>()
+ .eq(Segment::getAgvId, agv.getId())
+ .and( i -> {
+// i.eq(Segment::getState, SegmentStateType.WAITING.toString()).or()
+ i.eq(Segment::getState, SegmentStateType.RUNNING.toString());
+ })
+ )) {
+ return false;
+ }
+ return true;
+ }
+
+ private List<Agv> findScopedAgvList(Guarantee plan) {
+ LambdaQueryWrapper<Agv> wrapper = new LambdaQueryWrapper<Agv>()
+ .eq(Agv::getStatus, StatusType.ENABLE.val);
+ if (GuaranteeScopeType.MODEL.toString().equalsIgnoreCase(plan.getScopeType()) && plan.getScopeValue() != null) {
+ try {
+ wrapper.eq(Agv::getAgvModel, Long.valueOf(plan.getScopeValue()));
+ } catch (NumberFormatException ignore) {
+ log.warn("Guarantee[{}] invalid scopeValue {}", plan.getName(), plan.getScopeValue());
+ }
+ }
+ return agvService.list(wrapper);
+ }
+
+ private static class ChargeCandidate {
+ private final Agv agv;
+ private final int soc;
+
+ ChargeCandidate(Agv agv, int soc) {
+ this.agv = agv;
+ this.soc = soc;
+ }
+
+ public Agv getAgv() {
+ return agv;
+ }
+
+ public int getSoc() {
+ return soc;
+ }
+ }
}
-
--
Gitblit v1.9.1