#
vincentlu
2026-03-26 67ae8ce8379029b17dfd2426bf13924cc1433d2a
#
1个文件已添加
1个文件已修改
194 ■■■■■ 已修改文件
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/HkAgvDataService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/HkOrderStateClosureService.java 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/HkAgvDataService.java
@@ -45,6 +45,8 @@
    private ThreadPoolRegulator threadPoolRegulator;
    @Autowired
    private JamService jamService;
    @Autowired
    private HkOrderStateClosureService hkOrderStateClosureService;
    @Async
    public void dataProcess(HkState state) {
@@ -92,6 +94,8 @@
            return;
        }
        hkOrderStateClosureService.process(state);
        if (PRINT_LOG) {
            News.info("Hk Agv [{}] state ===>> {}", agvNo, JSON.toJSONString(state));
        }
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/HkOrderStateClosureService.java
New file
@@ -0,0 +1,190 @@
package com.zy.acs.manager.core.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zy.acs.common.hk.state.HkState;
import com.zy.acs.common.hk.state.HkStateActionState;
import com.zy.acs.common.hk.state.type.HkActionStatusType;
import com.zy.acs.common.utils.RedisSupport;
import com.zy.acs.framework.common.Cools;
import com.zy.acs.manager.manager.entity.Action;
import com.zy.acs.manager.manager.entity.Segment;
import com.zy.acs.manager.manager.enums.ActionStsType;
import com.zy.acs.manager.manager.enums.SegmentStateType;
import com.zy.acs.manager.manager.service.ActionService;
import com.zy.acs.manager.manager.service.SegmentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
/**
 * 海康 VDA state 闭环处理。
 * 仅复用现有结算逻辑,不改原有完成订阅逻辑。
 */
@Slf4j
@Service
public class HkOrderStateClosureService {
    private static final String HK_ORDER_COMPLETE_FLAG = "HK_AGV_ORDER_COMPLETE";
    private static final int COMPLETE_MARK_EXPIRE_SECONDS = 7 * 24 * 60 * 60;
    private final RedisSupport redis = RedisSupport.defaultRedisSupport;
    @Autowired
    private ActionService actionService;
    @Autowired
    private SegmentService segmentService;
    @Autowired
    private MainService mainService;
    @Transactional
    public void process(HkState state) {
        if (state == null || Cools.isEmpty(state.getOrderId())) {
            return;
        }
        syncFinishedActions(state);
        if (!isOrderCompleted(state)) {
            return;
        }
        settleCompletedOrder(state);
    }
    private void syncFinishedActions(HkState state) {
        if (Cools.isEmpty(state.getActionStates())) {
            return;
        }
        Date now = new Date();
        String orderId = state.getOrderId();
        for (HkStateActionState actionState : state.getActionStates()) {
            if (actionState == null || actionState.getActionStatus() != HkActionStatusType.FINISHED) {
                continue;
            }
            Long actionId = parseActionId(actionState.getActionId());
            if (actionId == null) {
                continue;
            }
            Action action = actionService.getOne(new LambdaQueryWrapper<Action>()
                    .eq(Action::getId, actionId)
                    .eq(Action::getGroupId, orderId)
                    .eq(Action::getActionSts, ActionStsType.ISSUED.val())
                    .last("limit 1"));
            if (action == null) {
                continue;
            }
            action.setActionSts(ActionStsType.FINISH.val());
            action.setEndTime(now);
            action.setUpdateTime(now);
            if (!actionService.updateById(action)) {
                log.error("hk state close action failed, orderId={}, actionId={}", orderId, actionId);
            } else {
                log.info("hk state close action success, orderId={}, actionId={}, hkActionId={}",
                        orderId, actionId, actionState.getActionId());
            }
        }
    }
    private boolean isOrderCompleted(HkState state) {
        if (!Cools.isEmpty(state.getNodeStates()) || !Cools.isEmpty(state.getEdgeStates())) {
            return false;
        }
        if (Cools.isEmpty(state.getActionStates())) {
            return true;
        }
        for (HkStateActionState actionState : state.getActionStates()) {
            if (actionState == null) {
                continue;
            }
            HkActionStatusType status = actionState.getActionStatus();
            if (status == null
                    || status == HkActionStatusType.WAITING
                    || status == HkActionStatusType.INITIALIZING
                    || status == HkActionStatusType.RUNNING
                    || status == HkActionStatusType.PAUSED
                    || status == HkActionStatusType.FAILED) {
                return false;
            }
        }
        return true;
    }
    private void settleCompletedOrder(HkState state) {
        String orderId = state.getOrderId();
        String completeKey = buildCompleteKey(state);
        if (redis.getObject(HK_ORDER_COMPLETE_FLAG, completeKey) != null) {
            return;
        }
        List<Segment> segmentList = segmentService.list(new LambdaQueryWrapper<Segment>()
                .eq(Segment::getGroupId, orderId)
                .orderByAsc(Segment::getSerial));
        if (Cools.isEmpty(segmentList)) {
            log.warn("hk state order completed but no segment found, agvNo={}, orderId={}, orderUpdateId={}",
                    state.getSerialNumber(), orderId, state.getOrderUpdateId());
            return;
        }
        if (!hasReachedOrderTail(state, segmentList)) {
            return;
        }
        boolean needSettle = segmentList.stream()
                .anyMatch(segment -> !SegmentStateType.FINISH.toString().equals(segment.getState()));
        if (!needSettle) {
            redis.setObject(HK_ORDER_COMPLETE_FLAG, completeKey, Boolean.TRUE, COMPLETE_MARK_EXPIRE_SECONDS);
            return;
        }
        mainService.settleSegmentList(segmentList, orderId);
        redis.setObject(HK_ORDER_COMPLETE_FLAG, completeKey, Boolean.TRUE, COMPLETE_MARK_EXPIRE_SECONDS);
        log.info("hk state settle completed order, agvNo={}, orderId={}, orderUpdateId={}",
                state.getSerialNumber(), orderId, state.getOrderUpdateId());
    }
    private String buildCompleteKey(HkState state) {
        return state.getSerialNumber()
                + "_"
                + state.getOrderId()
                + "_"
                + (state.getOrderUpdateId() == null ? "null" : state.getOrderUpdateId());
    }
    private boolean hasReachedOrderTail(HkState state, List<Segment> segmentList) {
        Long lastNodeSequenceId = state.getLastNodeSequenceId();
        if (lastNodeSequenceId == null) {
            return false;
        }
        long expectedLastNodeSequenceId = segmentList.size() * 2L;
        return lastNodeSequenceId >= expectedLastNodeSequenceId;
    }
    private Long parseActionId(String hkActionId) {
        if (Cools.isEmpty(hkActionId) || hkActionId.length() < 2) {
            return null;
        }
        if (hkActionId.charAt(0) != 'A' && hkActionId.charAt(0) != 'a') {
            return null;
        }
        try {
            return Long.parseLong(hkActionId.substring(1));
        } catch (NumberFormatException e) {
            log.warn("parse hk action id failed, hkActionId={}", hkActionId);
            return null;
        }
    }
}