#
vincentlu
2026-04-27 dcf49806e12b014cf6471910814fdbcb6f494c44
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java
@@ -8,10 +8,7 @@
import com.zy.acs.common.domain.protocol.*;
import com.zy.acs.common.domain.protocol.action.*;
import com.zy.acs.common.enums.*;
import com.zy.acs.common.utils.Base62;
import com.zy.acs.common.utils.GsonUtils;
import com.zy.acs.common.utils.RedisSupport;
import com.zy.acs.common.utils.Utils;
import com.zy.acs.common.utils.*;
import com.zy.acs.framework.common.Cools;
import com.zy.acs.framework.common.SnowflakeIdWorker;
import com.zy.acs.framework.exception.CoolException;
@@ -20,10 +17,12 @@
import com.zy.acs.manager.common.exception.BusinessException;
import com.zy.acs.manager.core.domain.AgvBackpackDto;
import com.zy.acs.manager.core.domain.LaneDto;
import com.zy.acs.manager.core.domain.PathDto;
import com.zy.acs.manager.core.domain.TaskPosDto;
import com.zy.acs.manager.core.integrate.conveyor.ConveyorStationService;
import com.zy.acs.manager.core.service.astart.MapDataDispatcher;
import com.zy.acs.manager.core.integrate.dto.OpenBusSubmitParam;
import com.zy.acs.manager.core.service.hik.HikOrderPublishService;
import com.zy.acs.manager.core.service.astart.MapDataDispatcher;
import com.zy.acs.manager.manager.entity.*;
import com.zy.acs.manager.manager.enums.*;
import com.zy.acs.manager.manager.service.*;
@@ -36,6 +35,7 @@
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import com.zy.acs.common.utils.News;
import java.util.*;
import java.util.stream.Collectors;
@@ -99,15 +99,18 @@
    private StaReserveService staReserveService;
    @Autowired
    private ConveyorStationService conveyorStationService;
    @Autowired
    private HikOrderPublishService hikOrderPublishService;
    @SuppressWarnings("all")
    @Transactional
    public Bus generateBusAndTask(OpenBusSubmitParam busSubmitParam, String memo) {
        String errorMsg = busService.checkoutValid(busSubmitParam);
        Boolean maintainLocSts = configService.getVal("maintainLocSts", Boolean.class);
        if (!Cools.isEmpty(errorMsg)) {
            throw new BusinessException(errorMsg);
        }
        String batch = busSubmitParam.getBatchNo();
        String batchNo = busSubmitParam.getBatchNo();
        List<TaskDto> taskDtoList = busSubmitParam.getTasks();
        if (Cools.isEmpty(taskDtoList)) {
            throw new BusinessException("taskList can't be empty!");
@@ -123,7 +126,7 @@
        Date now = new Date();
        Bus bus = new Bus();
        bus.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
        bus.setBusNo(batch);
        bus.setBusNo(batchNo);
        bus.setStartTime(now);
        bus.setBusSts(BusStsType.RECEIVE.val());
        bus.setMemo(memo);
@@ -147,35 +150,39 @@
            Sta destSta = null;
            switch (TaskTypeType.get(task.getTaskTypeEl())) {
                case LOC_TO_LOC:
                    oriLoc = locService.getById(task.getOriLoc());
                    if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
                        throw new BusinessException("oriLoc:" + task.getOriLoc$() + " is not in STOCK status");
                    }
                    oriLoc.setLocSts(LocStsType.PAKOUT.val());
                    oriLoc.setUpdateTime(now);
                    if (!locService.updateById(oriLoc)) {
                        throw new BusinessException("oriLoc:" + task.getOriLoc$() + " failed to update");
                    }
                    if (maintainLocSts) {
                        oriLoc = locService.getById(task.getOriLoc());
                        if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
                            throw new BusinessException("oriLoc:" + task.getOriLoc$() + " is not in STOCK status");
                        }
                        oriLoc.setLocSts(LocStsType.PAKOUT.val());
                        oriLoc.setUpdateTime(now);
                        if (!locService.updateById(oriLoc)) {
                            throw new BusinessException("oriLoc:" + task.getOriLoc$() + " failed to update");
                        }
                    destLoc = locService.getById(task.getDestLoc());
                    if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
                        throw new BusinessException("destLoc:" + task.getDestLoc$() + " is not in IDLE status");
                    }
                    destLoc.setLocSts(LocStsType.PAKIN.val());
                    destLoc.setUpdateTime(now);
                    if (!locService.updateById(destLoc)) {
                        throw new BusinessException("destLoc:" + task.getDestLoc$() + " failed to update");
                        destLoc = locService.getById(task.getDestLoc());
                        if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
                            throw new BusinessException("destLoc:" + task.getDestLoc$() + " is not in IDLE status");
                        }
                        destLoc.setLocSts(LocStsType.PAKIN.val());
                        destLoc.setUpdateTime(now);
                        if (!locService.updateById(destLoc)) {
                            throw new BusinessException("destLoc:" + task.getDestLoc$() + " failed to update");
                        }
                    }
                    break;
                case LOC_TO_STA:
                    oriLoc = locService.getById(task.getOriLoc());
                    if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
                        throw new BusinessException("oriLoc:" + task.getOriLoc$() + " is not in STOCK status");
                    }
                    oriLoc.setLocSts(LocStsType.PAKOUT.val());
                    oriLoc.setUpdateTime(now);
                    if (!locService.updateById(oriLoc)) {
                        throw new BusinessException("oriLoc:" + task.getOriLoc$() + " failed to update");
                    if (maintainLocSts) {
                        oriLoc = locService.getById(task.getOriLoc());
                        if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
                            throw new BusinessException("oriLoc:" + task.getOriLoc$() + " is not in STOCK status");
                        }
                        oriLoc.setLocSts(LocStsType.PAKOUT.val());
                        oriLoc.setUpdateTime(now);
                        if (!locService.updateById(oriLoc)) {
                            throw new BusinessException("oriLoc:" + task.getOriLoc$() + " failed to update");
                        }
                    }
                    destSta = staService.getById(task.getDestSta());
@@ -189,14 +196,16 @@
                        throw new BusinessException("oriSta:" + task.getOriSta$() + " failed to reserve");
                    }
                    destLoc = locService.getById(task.getDestLoc());
                    if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
                        throw new BusinessException("destLoc:" + task.getDestLoc$() + " is not in IDLE status");
                    }
                    destLoc.setLocSts(LocStsType.PAKIN.val());
                    destLoc.setUpdateTime(now);
                    if (!locService.updateById(destLoc)) {
                        throw new BusinessException("destLoc:" + task.getDestLoc$() + " failed to update");
                    if (maintainLocSts) {
                        destLoc = locService.getById(task.getDestLoc());
                        if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
                            throw new BusinessException("destLoc:" + task.getDestLoc$() + " is not in IDLE status");
                        }
                        destLoc.setLocSts(LocStsType.PAKIN.val());
                        destLoc.setUpdateTime(now);
                        if (!locService.updateById(destLoc)) {
                            throw new BusinessException("destLoc:" + task.getDestLoc$() + " failed to update");
                        }
                    }
                    break;
                case STA_TO_STA:
@@ -236,7 +245,7 @@
                    bus.setBusSts(BusStsType.PROGRESS.val());
                    bus.setUpdateTime(now);
                    if (!busService.updateById(bus)) {
                        log.error("Bus [{}] failed to Update !!!", bus.getUuid());
                        News.error("Bus [{}] failed to Update !!!", bus.getUuid());
                    }
                }
                return;
@@ -284,7 +293,7 @@
                            currSeg.setState(SegmentStateType.INIT.toString());
                            currSeg.setUpdateTime(now);
                            if (!segmentService.updateById(currSeg)) {
//                                log.error("Segment [{}] failed to update !!!", currSeg.getGroupId() + " - " + currSeg.getSerial());
//                                News.error("Segment [{}] failed to update !!!", currSeg.getGroupId() + " - " + currSeg.getSerial());
                                throw new CoolException("failed to update segment [" + currSeg.getGroupId() + "-" + currSeg.getSerial() + "] failed");
                            }
@@ -302,7 +311,7 @@
                            loadSeg.setCreateTime(now);
                            loadSeg.setUpdateTime(now);
                            if (!segmentService.save(loadSeg)) {
//                                log.error("Segment [{}] failed to save !!!", loadSeg.getTravelId() + " - " + loadSeg.getSerial());
//                                News.error("Segment [{}] failed to save !!!", loadSeg.getTravelId() + " - " + loadSeg.getSerial());
                                throw new CoolException("failed to save segment [" + loadSeg.getGroupId() + "-" + loadSeg.getSerial() + "] failed");
                            }
@@ -376,7 +385,7 @@
                            int idx = -1;
                            for (int i = 0; i < destPosList.size(); i++) {
                                if (Objects.equals(destPosList.get(i).getTaskId(), newDto.getTaskId())
                                 && Objects.equals(destPosList.get(i).getCodeId(), newDto.getCodeId())) {
                                        && Objects.equals(destPosList.get(i).getCodeId(), newDto.getCodeId())) {
                                    idx = i;
                                    break;
                                }
@@ -426,7 +435,7 @@
                            placeSeg.setCreateTime(now);
                            placeSeg.setUpdateTime(now);
                            if (!segmentService.save(placeSeg)) {
//                                log.error("Segment [{}] failed to save !!!", placeSeg.getTravelId() + " - " + placeSeg.getSerial());
//                                News.error("Segment [{}] failed to save !!!", placeSeg.getTravelId() + " - " + placeSeg.getSerial());
                                throw new CoolException("failed to save segment [" + placeSeg.getGroupId() + "-" + placeSeg.getSerial() + "] failed");
                            }
@@ -456,7 +465,7 @@
                            staReserveService.allocateCallBack(task, agvId);
                        });
//                if (Cools.isEmpty(agvNo)) {
////                    log.warn("Task[{}] has an issue, because it failed to check out agv which is idle...", task.getSeqNum());
////                    News.warn("Task[{}] has an issue, because it failed to check out agv which is idle...", task.getSeqNum());
//                    continue;
//                }
//                task.setAgvId(agvService.getAgvId(agvNo));
@@ -468,7 +477,7 @@
//                }
            }
        } catch (Exception e) {
            log.error("mainService.infuseAgvForTask", e);
            News.error("mainService.infuseAgvForTask", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }
@@ -645,7 +654,7 @@
                    dropGroups.add(group);
                } else {
                    // import tip: the list must only contain ORIGIN and DESTINATION
                    log.error("the list must only contain ORIGIN and DESTINATION");
                    News.error("the list must only contain ORIGIN and DESTINATION");
                }
            }
@@ -721,7 +730,7 @@
        } catch (Exception e) {
            log.error("mainService.buildMajorTask[task]", e);
            News.error("mainService.buildMajorTask[task]", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }
@@ -758,7 +767,7 @@
                        endCode = codeService.getCacheById(funcSta.getCode());
                    }
                    if (null == endCode) {
                        log.warn("AGV[{}] failed to search destination,there hadn't any idle funSta,TaskTypeType:{}", agvNo, taskType.toString());
                        News.warn("AGV[{}] failed to search destination,there hadn't any idle funSta,TaskTypeType:{}", agvNo, taskType.toString());
                    }
                    break;
                case MOVE:
@@ -864,7 +873,7 @@
                    destFuncSta.setState(FuncStaStateType.OCCUPIED.toString());
                    destFuncSta.setUpdateTime(now);
                    if (!funcStaService.updateById(destFuncSta)) {
                        log.error("FuncSta [{}] failed to update !!!", destFuncSta.getName());
                        News.error("FuncSta [{}] failed to update !!!", destFuncSta.getName());
                    }
                    break;
                case MOVE:
@@ -875,7 +884,7 @@
            return true;
        } catch (Exception e) {
            log.error("mainService.buildMinorTask[task]", e);
            News.error("mainService.buildMinorTask[task]", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
@@ -886,12 +895,12 @@
     * 根据分片生成动作 ( 车辆可能已经做过一些任务了,正在等待下一段任务 )
     */
    @Transactional
    public synchronized void generateAction(Long agvId, List<Segment> segmentList, List<String> pathList, Date algoStartTime) {
    public synchronized List<PathDto> generateAction(Long agvId, List<Segment> segmentList, List<String> pathList, Date algoStartTime) {
        List<PathDto> pathTrace = new ArrayList<>();
        try {
            if (Cools.isEmpty(agvId, segmentList)) { return; }
            if (Cools.isEmpty(agvId, segmentList)) { return pathTrace; }
            Date now = new Date();
            long actionPrepareSts = ActionStsType.PREPARE.val();
//            JSONObject storeDirection = configService.getVal("storeDirection", JSONObject.class);
            int angleOffsetVal = configService.getVal("mapAngleOffsetVal", Integer.class);
//            Double defaultShelfDepth = configService.getVal("defaultShelfDepth", Double.class);
//            defaultShelfDepth = Optional.ofNullable(defaultShelfDepth).orElse((double) 0);
@@ -917,6 +926,7 @@
            if (!lastCode.getData().equals(pathList.get(0))) {
                throw new CoolException("AGV[" + agvNo + "]定位偏移...");
            }
            pathTrace.add(new PathDto(lastCode.getData(), lastDirection, false));
            boolean first = true;
            for (Segment segment : segmentList) {
@@ -982,6 +992,7 @@
                                        now    // 工作时间
                                ));
                                lastDirection = nextLaneDir;
                                PathDto.markTurn(pathTrace, lastDirection);
                            }
                            if (nextDirection.equals(oppNextLaneDir)) {
@@ -1050,6 +1061,7 @@
                                        ));
                                        lastDirection = nextDirection;
                                        PathDto.markTurn(pathTrace, lastDirection);
                                    }
                                }
                            }
@@ -1075,6 +1087,7 @@
                            ));
                            lastDirection = nextDirection;
                            PathDto.markTurn(pathTrace, lastDirection);
                        }
                        // run
@@ -1097,6 +1110,7 @@
                        ));
                        lastCode = nextCode;
                        pathTrace.add(new PathDto(lastCode.getData(), lastDirection, false));
                    }
@@ -1142,13 +1156,14 @@
                        ));
                        lastDirection = firstTurnDir;
                        PathDto.markTurn(pathTrace, lastDirection);
                    }
                    first = false;
                }
                // 作业点动作
                AgvDirectionType agvDirectionType;
                ActuatorDirectionType actuatorDirectionType;
                Double staWorkDirection;
                AgvBackpackType backpackType = AgvBackpackType.query(segment.getBackpack());
                switch (Objects.requireNonNull(TaskPosDto.queryPosType(segment.getPosType()))) {
@@ -1161,7 +1176,8 @@
                        // 货架取货
                        Loc oriLoc = locService.getById(task.getOriLoc());
                        // 计算左右方向
                        agvDirectionType = mapService.calculateAgvWorkDirectionByShelf(oriLoc, lastCode);
                        actuatorDirectionType = ActuatorDirectionType.fromVal(oriLoc.getCompDirect());
//                        actuatorDirectionType = mapService.calculateAgvWorkDirectionByShelf(oriLoc, lastCode);
                        actionList.add(new Action(
                                null,    // 编号
                                task.getBusId(),    // 总线
@@ -1169,7 +1185,7 @@
                                null,    // 动作号
                                null,    // 优先级
                                ActionTypeType.ReadyTakeFromShelvesLoc.desc,    // 名称
                                (double) agvDirectionType.val,    // 属性值
                                (double) actuatorDirectionType.val,    // 属性值
                                lastCode.getData(),    // 地面码
                                JSON.toJSONString(new HeightDepthDto(oriLoc.getOffset())),   // 动作参数
                                ActionTypeType.ReadyTakeFromShelvesLoc.val(),    // 动作类型
@@ -1224,15 +1240,16 @@
                        // 货架放货
                        Loc destLoc = locService.getById(task.getDestLoc());
                        // 计算左右方向
                        agvDirectionType = mapService.calculateAgvWorkDirectionByShelf(destLoc, lastCode);
                        actuatorDirectionType = ActuatorDirectionType.fromVal(destLoc.getCompDirect());
//                        actuatorDirectionType = mapService.calculateAgvWorkDirectionByShelf(destLoc, lastCode);
                        actionList.add(new Action(
                                null,    // 编号
                                task.getBusId(),    // 总线
                                task.getId(),    // 任务
                                null,    // 动作号
                                 null,    // 优先级
                                null,    // 优先级
                                ActionTypeType.ReadyReleaseToShelvesLoc.desc,    // 名称
                                (double) agvDirectionType.val,    // 属性值
                                (double) actuatorDirectionType.val,    // 属性值
                                lastCode.getData(),    // 地面码
                                JSON.toJSONString(new HeightDepthDto(destLoc.getOffset())),   // 动作参数
                                ActionTypeType.ReadyReleaseToShelvesLoc.val(),    // 动作类型
@@ -1244,7 +1261,7 @@
                    case ORI_STA:
                        // 站点取货
                        Sta oriSta = staService.getById(task.getOriSta());
                        Double oriStaWorkDirection = mapService.getStaAngle(oriSta, workDirection);
                        Double oriStaWorkDirection = mapService.getStaAngle(oriSta);
                        // 检验方向
                        if (!lastDirection.equals(oriStaWorkDirection)) {
                            if (!lastCode.getCornerBool()) {
@@ -1267,9 +1284,11 @@
                                    now    // 工作时间
                            ));
                            lastDirection = oriStaWorkDirection;
                            PathDto.markTurn(pathTrace, lastDirection);
                        }
                        // 计算货叉工作方向
                        staWorkDirection = mapService.calculateAgvWorkDirectionByStation(oriStaWorkDirection, lastDirection);
                        actuatorDirectionType = ActuatorDirectionType.fromVal(oriSta.getActDir());
//                        staWorkDirection = mapService.calculateAgvWorkDirectionByStation(oriStaWorkDirection, lastDirection);
                        actionList.add(new Action(
                                null,    // 编号
                                task.getBusId(),    // 总线
@@ -1277,7 +1296,7 @@
                                null,    // 动作号
                                null,    // 优先级
                                ActionTypeType.ReadyTakeFromConveyorSta.desc,    // 名称
                                staWorkDirection,    // 属性值
                                (double) actuatorDirectionType.val,    // 属性值
                                lastCode.getData(),    // 地面码
                                JSON.toJSONString(new HeightDepthDto(oriSta.getHeight(), Optional.ofNullable(oriSta.getDepth()).orElse((double) 0))),   // 动作参数
                                ActionTypeType.ReadyTakeFromConveyorSta.val(),    // 动作类型
@@ -1308,7 +1327,7 @@
                    case DEST_STA:
                        // 站点放货
                        Sta destSta = staService.getById(task.getDestSta());
                        Double destStaWorkDirection = mapService.getStaAngle(destSta, workDirection);
                        Double destStaWorkDirection = mapService.getStaAngle(destSta);
                        // 检验方向
                        if (!lastDirection.equals(destStaWorkDirection)) {
                            if (!lastCode.getCornerBool()) {
@@ -1331,6 +1350,7 @@
                                    now    // 工作时间
                            ));
                            lastDirection = destStaWorkDirection;
                            PathDto.markTurn(pathTrace, lastDirection);
                        }
                        // 背篓取货
                        if (backupAction) {
@@ -1352,7 +1372,8 @@
                            ));
                        }
                        // 计算货叉工作方向
                        staWorkDirection = mapService.calculateAgvWorkDirectionByStation(destStaWorkDirection, lastDirection);
//                        staWorkDirection = mapService.calculateAgvWorkDirectionByStation(destStaWorkDirection, lastDirection);
                        actuatorDirectionType = ActuatorDirectionType.fromVal(destSta.getActDir());
                        actionList.add(new Action(
                                null,    // 编号
                                task.getBusId(),    // 总线
@@ -1360,7 +1381,7 @@
                                null,    // 动作号
                                null,    // 优先级
                                ActionTypeType.ReadyReleaseToConveyorSta.desc,    // 名称
                                staWorkDirection,    // 属性值
                                (double) actuatorDirectionType.val,    // 属性值
                                lastCode.getData(),    // 地面码
                                JSON.toJSONString(new HeightDepthDto(destSta.getHeight(), Optional.ofNullable(destSta.getDepth()).orElse((double) 0))),   // 动作参数
                                ActionTypeType.ReadyReleaseToConveyorSta.val(),    // 动作类型
@@ -1390,6 +1411,7 @@
                                    now    // 工作时间
                            ));
                            lastDirection = chargeDirection;
                            PathDto.markTurn(pathTrace, lastDirection);
                        }
                        // charge
@@ -1543,9 +1565,10 @@
                throw new BusinessException("group[" + groupId + "] 动作保存失败");
            }
            log.info("{}号Agv动作组装完成,指令数量:{}", agvNo, newActionList.size());
            News.info("{}号Agv动作组装完成,指令数量:{}", agvNo, newActionList.size());
            return pathTrace;
        } catch (Exception e) {
            log.error("mainService.generateAction", e);
            News.error("mainService.generateAction", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            if (!Cools.isEmpty(pathList)) {
@@ -1561,22 +1584,21 @@
    @Transactional
    public void publishAction(String actionGroupId) {
        try {
            Date now = new Date();
            // action
            List<Action> actionList = actionService.list(new LambdaQueryWrapper<Action>()
                    .eq(Action::getGroupId, actionGroupId).eq(Action::getActionSts, ActionStsType.PREPARE.val())
                    .eq(Action::getGroupId, actionGroupId)
                    .eq(Action::getActionSts, ActionStsType.PREPARE.val())
                    .orderByDesc(Action::getPriority));
            if (Cools.isEmpty(actionList)) {
                return;
            }
            Long agvId = actionList.get(0).getAgvId();
            String agvNo = agvService.getAgvNo(agvId);
            if (!agvService.judgeOnline(agvId)) {
                return;
            }
            Date now = new Date();
            long actionIssuedSts = ActionStsType.ISSUED.val();
            for (Action action : actionList) {
                action.setActionSts(actionIssuedSts);
@@ -1603,129 +1625,142 @@
                }
            }
            AgvAction agvAction = new AgvAction(agvNo, actionGroupId);
            for (Action action : actionList) {
                switch (Objects.requireNonNull(ActionTypeType.get(action.getActionTypeEl()))) {
                    case TurnCorner:
                        agvAction.add(new AgvActionItem<>(TurnCornerAction.class)
                                .setQrCode(action.getCode())
                                .setVal(Optional.ofNullable(action.getVal()).orElse(0D).intValue())
                                .bodySync(body -> body.setAngle((short) Double.parseDouble(action.getParams())))
                        );
                        break;
                    case StraightBackUnturnable:
                        break;
                    case StraightBackTurnable:
                        agvAction.add(new AgvActionItem<>(StraightBackTurnableAction.class)
                                .setVal(action.getVal().intValue())
                                .setQrCode(action.getCode())
                                .bodySync(body -> body.setDistance((short) Double.parseDouble(action.getParams())))
                        );
                        break;
                    case StraightAheadUnturnable:
                        break;
                    case StraightAheadTurnable:
                        agvAction.add(new AgvActionItem<>(StraightAheadTurnableAction.class)
                                .setVal(action.getVal().intValue())
                                .setQrCode(action.getCode())
                                .bodySync(body -> body.setDistance((short) Double.parseDouble(action.getParams())))
                        );
                        break;
                    case ReadyTakeFromShelvesLoc:
                        agvAction.add(new AgvActionItem<>(ReadyTakeFromShelvesLoc.class)
                                .setVal(action.getVal().intValue())
                                .setQrCode(action.getCode())
                                .bodySync((body) -> {
                                    HeightDepthDto heightDepthDto = JSON.parseObject(action.getParams(), HeightDepthDto.class);
                                    body.setHeight(heightDepthDto.getHeight());
                                    body.setDepth(heightDepthDto.getDepth());
                                })
                        );
                        break;
                    case ReadyTakeFromConveyorSta:
                        agvAction.add(new AgvActionItem<>(ReadyTakeFromConveyorSta.class)
                                .setVal(action.getVal().intValue())
                                .setQrCode(action.getCode())
                                .bodySync((body) -> {
                                    HeightDepthDto heightDepthDto = JSON.parseObject(action.getParams(), HeightDepthDto.class);
                                    body.setHeight(heightDepthDto.getHeight());
                                    body.setDepth(heightDepthDto.getDepth());
                                })
                        );
                        break;
                    case ReadyTakeFromAgvSite:
                        agvAction.add(new AgvActionItem<>(ReadyTakeFromAgvSite.class)
                                .setVal(action.getVal().intValue())
                                .setQrCode(action.getCode())
                                .bodySync(body -> body.setDepth((short) Double.parseDouble(action.getParams())))
                        );
                        break;
                    case ReadyReleaseToShelvesLoc:
                        agvAction.add(new AgvActionItem<>(ReadyReleaseToShelvesLoc.class)
                                .setVal(action.getVal().intValue())
                                .setQrCode(action.getCode())
                                .bodySync((body) -> {
                                    HeightDepthDto heightDepthDto = JSON.parseObject(action.getParams(), HeightDepthDto.class);
                                    body.setHeight(heightDepthDto.getHeight());
                                    body.setDepth(heightDepthDto.getDepth());
                                })
                        );
                        break;
                    case ReadyReleaseToConveyorSta:
                        agvAction.add(new AgvActionItem<>(ReadyReleaseToConveyorSta.class)
                                .setVal(action.getVal().intValue())
                                .setQrCode(action.getCode())
                                .bodySync((body) -> {
                                    HeightDepthDto heightDepthDto = JSON.parseObject(action.getParams(), HeightDepthDto.class);
                                    body.setHeight(heightDepthDto.getHeight());
                                    body.setDepth(heightDepthDto.getDepth());
                                })
                        );
                        break;
                    case ReadyReleaseToAgvSite:
                        agvAction.add(new AgvActionItem<>(ReadyReleaseToAgvSite.class)
                                .setVal(action.getVal().intValue())
                                .setQrCode(action.getCode())
                                .bodySync(body -> body.setDepth((short) Double.parseDouble(action.getParams())))
                        );
                        break;
                    case LoadPlatformLift:
                        agvAction.add(new AgvActionItem<>(LoadPlatformLift.class)
                                .setVal(action.getVal().intValue())
                                .setQrCode(action.getCode())
                                .bodySync(body -> body.setHeight((short) Double.parseDouble(action.getParams())))
                        );
                        break;
                    case FinishPath:
                        agvAction.add(new AgvActionItem<>(FinishPathAction.class)
                                .setQrCode(action.getCode())
                        );
                        break;
                    case DockingCharge:
                        agvAction.add(new AgvActionItem<>(DockingChargeAction.class)
                                .setQrCode(action.getCode())
                        );
                        break;
                    case UndockingCharge:
                        agvAction.add(new AgvActionItem<>(UndockingChargeAction.class)
                                .setQrCode(action.getCode())
                        );
                        break;
                    default:
                        break;
            String agvNo = agvService.getAgvNo(agvId);
            AgvModel agvModel = agvModelService.getByAgvId(agvId);
            // hik robot
            if (hikOrderPublishService.support(agvModel)) {
                hikOrderPublishService.publish(actionGroupId, agvNo, agvModel, actionList);
                News.info("海康任务组 [{}] order 已下发 ===>> 指令数量:{}", actionGroupId, actionList.size());
            // zoneyung robot
            } else {
                AgvAction agvAction = new AgvAction(agvNo, actionGroupId);
                for (Action action : actionList) {
                    switch (Objects.requireNonNull(ActionTypeType.get(action.getActionTypeEl()))) {
                        case TurnCorner:
                            agvAction.add(new AgvActionItem<>(TurnCornerAction.class)
                                    .setQrCode(action.getCode())
                                    .setVal(Optional.ofNullable(action.getVal()).orElse(0D).intValue())
                                    .bodySync(body -> body.setAngle((short) Double.parseDouble(action.getParams())))
                            );
                            break;
                        case StraightBackUnturnable:
                            break;
                        case StraightBackTurnable:
                            agvAction.add(new AgvActionItem<>(StraightBackTurnableAction.class)
                                    .setVal(action.getVal().intValue())
                                    .setQrCode(action.getCode())
                                    .bodySync(body -> body.setDistance((short) Double.parseDouble(action.getParams())))
                            );
                            break;
                        case StraightAheadUnturnable:
                            break;
                        case StraightAheadTurnable:
                            agvAction.add(new AgvActionItem<>(StraightAheadTurnableAction.class)
                                    .setVal(action.getVal().intValue())
                                    .setQrCode(action.getCode())
                                    .bodySync(body -> body.setDistance((short) Double.parseDouble(action.getParams())))
                            );
                            break;
                        case ReadyTakeFromShelvesLoc:
                            agvAction.add(new AgvActionItem<>(ReadyTakeFromShelvesLoc.class)
                                    .setVal(action.getVal().intValue())
                                    .setQrCode(action.getCode())
                                    .bodySync((body) -> {
                                        HeightDepthDto heightDepthDto = JSON.parseObject(action.getParams(), HeightDepthDto.class);
                                        body.setHeight(heightDepthDto.getHeight());
                                        body.setDepth(heightDepthDto.getDepth());
                                    })
                            );
                            break;
                        case ReadyTakeFromConveyorSta:
                            agvAction.add(new AgvActionItem<>(ReadyTakeFromConveyorSta.class)
                                    .setVal(action.getVal().intValue())
                                    .setQrCode(action.getCode())
                                    .bodySync((body) -> {
                                        HeightDepthDto heightDepthDto = JSON.parseObject(action.getParams(), HeightDepthDto.class);
                                        body.setHeight(heightDepthDto.getHeight());
                                        body.setDepth(heightDepthDto.getDepth());
                                    })
                            );
                            break;
                        case ReadyTakeFromAgvSite:
                            agvAction.add(new AgvActionItem<>(ReadyTakeFromAgvSite.class)
                                    .setVal(action.getVal().intValue())
                                    .setQrCode(action.getCode())
                                    .bodySync(body -> body.setDepth((short) Double.parseDouble(action.getParams())))
                            );
                            break;
                        case ReadyReleaseToShelvesLoc:
                            agvAction.add(new AgvActionItem<>(ReadyReleaseToShelvesLoc.class)
                                    .setVal(action.getVal().intValue())
                                    .setQrCode(action.getCode())
                                    .bodySync((body) -> {
                                        HeightDepthDto heightDepthDto = JSON.parseObject(action.getParams(), HeightDepthDto.class);
                                        body.setHeight(heightDepthDto.getHeight());
                                        body.setDepth(heightDepthDto.getDepth());
                                    })
                            );
                            break;
                        case ReadyReleaseToConveyorSta:
                            agvAction.add(new AgvActionItem<>(ReadyReleaseToConveyorSta.class)
                                    .setVal(action.getVal().intValue())
                                    .setQrCode(action.getCode())
                                    .bodySync((body) -> {
                                        HeightDepthDto heightDepthDto = JSON.parseObject(action.getParams(), HeightDepthDto.class);
                                        body.setHeight(heightDepthDto.getHeight());
                                        body.setDepth(heightDepthDto.getDepth());
                                    })
                            );
                            break;
                        case ReadyReleaseToAgvSite:
                            agvAction.add(new AgvActionItem<>(ReadyReleaseToAgvSite.class)
                                    .setVal(action.getVal().intValue())
                                    .setQrCode(action.getCode())
                                    .bodySync(body -> body.setDepth((short) Double.parseDouble(action.getParams())))
                            );
                            break;
                        case LoadPlatformLift:
                            agvAction.add(new AgvActionItem<>(LoadPlatformLift.class)
                                    .setVal(action.getVal().intValue())
                                    .setQrCode(action.getCode())
                                    .bodySync(body -> body.setHeight((short) Double.parseDouble(action.getParams())))
                            );
                            break;
                        case FinishPath:
                            agvAction.add(new AgvActionItem<>(FinishPathAction.class)
                                    .setQrCode(action.getCode())
                            );
                            break;
                        case DockingCharge:
                            agvAction.add(new AgvActionItem<>(DockingChargeAction.class)
                                    .setQrCode(action.getCode())
                            );
                            break;
                        case UndockingCharge:
                            agvAction.add(new AgvActionItem<>(UndockingChargeAction.class)
                                    .setQrCode(action.getCode())
                            );
                            break;
                        default:
                            break;
                    }
                }
                BaseResult<?> result = agvCmdService.executeAgvActionCmd(agvAction);
                if (result.success()) {
                    News.info("任务组 [{}] 动作指令已下发 ===>> 指令数量:{}", actionGroupId, actionList.size());
                } else {
                    News.error("任务组 [{}] 动作指令下发失败 !!!", actionGroupId);
                    throw new CoolException("任务组 [{" + actionGroupId + "}] 动作指令下发失败 !!!");
                }
            }
            BaseResult<?> result = agvCmdService.executeAgvActionCmd(agvAction);
            if (result.success()) {
                log.info("任务组 [{}] 动作指令已下发 ===>> 指令数量:{}", actionGroupId, actionList.size());
            } else {
                log.error("任务组 [{}] 动作指令下发失败 !!!", actionGroupId);
                throw new CoolException("任务组 [{" + actionGroupId + "}] 动作指令下发失败 !!!");
            }
        } catch (Exception e) {
            log.error("mainService.publishAction", e);
            News.error("mainService.publishAction", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
@@ -1737,7 +1772,7 @@
        Agv agv = agvService.selectByUuid(protocol.getAgvNo());
        if (null == agv) {
            log.warn("Agv [{}] 尚未鉴权 !!!", protocol.getAgvNo());
            News.warn("Agv [{}] 尚未鉴权 !!!", protocol.getAgvNo());
            return;
        }
@@ -1749,7 +1784,7 @@
            AGV_11_UP agv_11_up = (AGV_11_UP) msgBody;
            String serialNo = agv_11_up.getSerialNo();
            log.info("Agv [{}] 动作完成包 ===>> {}", protocol.getAgvNo(), JSON.toJSONString(agv_11_up));
            News.info("Agv [{}] 动作完成包 ===>> {}", protocol.getAgvNo(), JSON.toJSONString(agv_11_up));
            // 入库放货
            if (agv_11_up.getCompleteType().equals(AgvCompleteType.RELEASE_FROM_SHELVES_COMPLETE)) {
@@ -1757,7 +1792,7 @@
                Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getBarcode, String.valueOf(Integer.parseInt(agv_11_up.getLocCode()))));
                if (null == loc) {
                    log.warn("Agv [{}] 上报往货架放货完成时,库位码[{}]无效。", protocol.getAgvNo(), agv_11_up.getLocCode());
                    News.warn("Agv [{}] 上报往货架放货完成时,库位码[{}]无效。", protocol.getAgvNo(), agv_11_up.getLocCode());
                } else {
                    List<Long> taskIds = actionService.selectTaskIdsByGroupId(serialNo);
                    for (Long taskId : taskIds) {
@@ -1775,7 +1810,7 @@
                                action.setEndTime(now);
                                action.setUpdateTime(now);
                                if (!actionService.updateById(action)) {
                                    log.error("Action [{}] 更新失败 !!!", action.getPriority() + " - " + action.getName());
                                    News.error("Action [{}] 更新失败 !!!", action.getPriority() + " - " + action.getName());
                                }
                            }
@@ -1790,7 +1825,7 @@
                Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getBarcode, String.valueOf(Integer.parseInt(agv_11_up.getLocCode()))));
                if (null == loc) {
                    log.warn("Agv [{}] 上报从货架取货完成,库位码[{}]无效。", protocol.getAgvNo(), agv_11_up.getLocCode());
                    News.warn("Agv [{}] 上报从货架取货完成,库位码[{}]无效。", protocol.getAgvNo(), agv_11_up.getLocCode());
                } else {
                    List<Long> taskIds = actionService.selectTaskIdsByGroupId(serialNo);
@@ -1808,7 +1843,7 @@
                                action.setEndTime(now);
                                action.setUpdateTime(now);
                                if (!actionService.updateById(action)) {
                                    log.error("Action [{}] 更新失败 !!!", action.getPriority() + " - " + action.getName());
                                    News.error("Action [{}] 更新失败 !!!", action.getPriority() + " - " + action.getName());
                                }
                            }
                        }
@@ -1822,15 +1857,15 @@
                // segment list
                List<Segment> segmentList = segmentService.list(new LambdaQueryWrapper<Segment>()
                        .eq(Segment::getGroupId, serialNo)
                                .eq(Segment::getGroupId, serialNo)
//                        .eq(Segment::getState, SegmentStateType.RUNNING.toString())
                        .orderByAsc(Segment::getSerial)
                                .orderByAsc(Segment::getSerial)
                );
                // settlement
                this.settleSegmentList(segmentList, serialNo);
                log.info("Agv [{}] {}作业完毕 ==========>> ", protocol.getAgvNo(), serialNo);
                News.info("Agv [{}] {} 路径作业已完成", protocol.getAgvNo(), serialNo);
            }
        }
@@ -1838,7 +1873,7 @@
        // 取放货请求包
        if (msgBody instanceof AGV_06_UP) {
            AGV_06_UP agv_06_up = (AGV_06_UP) msgBody;
            log.info("Agv [{}] 取放货请求包 ===>> {}", protocol.getAgvNo(), JSON.toJSONString(agv_06_up));
            News.info("Agv [{}] 取放货请求包 ===>> {}", protocol.getAgvNo(), JSON.toJSONString(agv_06_up));
            boolean success = false;
@@ -1848,14 +1883,14 @@
                // query current segment
                Segment currSeg = segmentService.getCurrRunningSeg(null, agv.getId(), code.getId());
                if (null == currSeg) {
                    log.error("failed to find curr segment [{}]", agv.getUuid());
                    News.error("failed to find curr segment [{}]", agv.getUuid());
                } else {
                    // query current task
                    Task currTask = taskService.getById(currSeg.getTaskId());
                    if (currTask == null || !currTask.getTaskSts().equals(TaskStsType.PROGRESS.val())) {
                        log.error("agv[{}] task invalid, task={}", protocol.getAgvNo(), currSeg.getTaskId());
                        News.error("agv[{}] task invalid, task={}", protocol.getAgvNo(), currSeg.getTaskId());
                    } else {
                        Sta sta;
@@ -1869,44 +1904,22 @@
                            case ORI_STA:
                                // load from sta
                                sta = staService.getById(currTask.getOriSta());
                                // reserve to be waiting
                                if (!staReserveService.waitingStaReserve(sta, currTask, currSeg, 1, StaReserveType.OUT)) {
                                    break;
                                }
                                // convey plc valid
                                if (!conveyorStationService.allowAgvWork(sta, currTask, currSeg, StaReserveType.OUT)) {
                                    // reserve rollback
                                    staReserveService.rollbackWaitingToReserved(sta, currTask, StaReserveType.OUT);
                                    break;
                                }
                                log.info("AGV [{}] load permitted at conveyor station [{}]", protocol.getAgvNo(), sta.getStaNo());
                                success = true;
                                success = staService.allowAgvWorkAtSta(protocol.getAgvNo(), sta, currTask, currSeg, StaReserveType.OUT);
                                break;
                            case DEST_STA:
                                // place to sta
                                sta = staService.getById(currTask.getDestSta());
                                // reserve to be waiting
                                if (!staReserveService.waitingStaReserve(sta, currTask, currSeg, 1, StaReserveType.IN)) {
                                    break;
                                }
                                // convey plc valid
                                if (!conveyorStationService.allowAgvWork(sta, currTask, currSeg, StaReserveType.IN)) {
                                    // reserve rollback
                                    staReserveService.rollbackWaitingToReserved(sta, currTask, StaReserveType.IN);
                                    break;
                                }
                                log.info("AGV [{}] unload permitted at conveyor station [{}]", protocol.getAgvNo(), sta.getStaNo());
                                success = true;
                                success = staService.allowAgvWorkAtSta(protocol.getAgvNo(), sta, currTask, currSeg, StaReserveType.IN);
                                break;
                            default:
                                log.error("AGV [{}] has wrong posType [{}], segment [{}]", protocol.getAgvNo(), posType.toString(), currSeg.getId());
                                News.error("AGV [{}] has wrong posType [{}], segment [{}]", protocol.getAgvNo(), posType.toString(), currSeg.getId());
                                break;
                        }
                    }
                }
            } catch (Exception e) {
                log.error("agv[{}] failed to deal with action request, qrCode={}", agv.getUuid(), agv_06_up.getVal(), e);
                News.error("agv[{}] failed to deal with action request, qrCode={}", agv.getUuid(), agv_06_up.getVal(), e);
            }
            AGV_06_DOWN agv_06_down = new AGV_06_DOWN();
@@ -1920,7 +1933,7 @@
        if (msgBody instanceof AGV_70_UP) {
            AGV_70_UP agv_70_up = (AGV_70_UP) msgBody;
            log.info("Agv [{}] 料仓信息包 ===>> {}", protocol.getAgvNo(), JSON.toJSONString(agv_70_up));
            News.info("Agv [{}] 料仓信息包 ===>> {}", protocol.getAgvNo(), JSON.toJSONString(agv_70_up));
        }
    }
@@ -1967,10 +1980,10 @@
                task.setEndTime(now);
                task.setUpdateTime(now);
                if (!taskService.updateById(task)) {
                    log.error("Task [{}] 更新失败 !!!", task.getSeqNum());
                    News.error("Task [{}] 更新失败 !!!", task.getSeqNum());
                } else {
                    taskService.maintainLocAndSta(task);
                    log.info("Task [{}] 作业完毕 ==========>> ", task.getSeqNum());
                    News.info("Task [{}] 任务运行完成.", task.getSeqNum());
                }
            }
@@ -1987,7 +2000,7 @@
                action.setEndTime(now);
                action.setUpdateTime(now);
                if (!actionService.updateById(action)) {
                    log.error("Action [{}] 更新失败 !!!", action.getPriority() + " - " + action.getName());
                    News.error("Action [{}] 更新失败 !!!", action.getPriority() + " - " + action.getName());
                }
            }
        }
@@ -1998,12 +2011,11 @@
            segment.setEndTime(now);
            segment.setUpdateTime(now);
            if (!segmentService.updateById(segment)) {
                log.error("Segment [{}] 更新失败 !!!", segment.getGroupId() + " - " + segment.getSerial());
                News.error("Segment [{}] 更新失败 !!!", segment.getGroupId() + " - " + segment.getSerial());
            }
        }
        // segment call back
        segmentService.processNext(segmentList);
    }
}