zc
2025-10-20 0ca395093d7d783197d8f848aea8bd5eae86b978
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java
@@ -1,6 +1,7 @@
package com.zy.acs.manager.core.service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zy.acs.common.domain.AgvAction;
import com.zy.acs.common.domain.AgvActionItem;
@@ -26,6 +27,7 @@
import com.zy.acs.manager.core.domain.Lane;
import com.zy.acs.manager.core.domain.TaskPosDto;
import com.zy.acs.manager.core.service.astart.MapDataDispatcher;
import com.zy.acs.manager.core.utils.HttpHandler;
import com.zy.acs.manager.manager.controller.param.OpenBusSubmitParam;
import com.zy.acs.manager.manager.entity.*;
import com.zy.acs.manager.manager.enums.*;
@@ -40,7 +42,9 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@@ -132,6 +136,9 @@
        if (!busService.save(bus)) {
            throw new BusinessException("Internal Server Error!");
        }
        Boolean locStaStatusCheck = configService.getVal("LOC_STA_STATUS_CHECK", Boolean.class, true);
        Integer locStaTaskNum = configService.getVal("LOC_STA_TASK_NUM", Integer.class, 2);
        // 保存任务
        for (Task task : taskList) {
@@ -149,7 +156,7 @@
            switch (TaskTypeType.get(task.getTaskTypeEl())) {
                case LOC_TO_LOC:
                    oriLoc = locService.getById(task.getOriLoc());
                    if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
                    if (locStaStatusCheck && !oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
                        throw new BusinessException("oriLoc:" + task.getOriLoc$() + " is not in STOCK status");
                    }
                    oriLoc.setLocSts(LocStsType.PAKOUT.val());
@@ -159,7 +166,7 @@
                    }
                    destLoc = locService.getById(task.getDestLoc());
                    if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
                    if (locStaStatusCheck && !destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
                        throw new BusinessException("destLoc:" + task.getDestLoc$() + " is not in IDLE status");
                    }
                    destLoc.setLocSts(LocStsType.PAKIN.val());
@@ -170,7 +177,7 @@
                    break;
                case LOC_TO_STA:
                    oriLoc = locService.getById(task.getOriLoc());
                    if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
                    if (locStaStatusCheck && !oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
                        throw new BusinessException("oriLoc:" + task.getOriLoc$() + " is not in STOCK status");
                    }
                    oriLoc.setLocSts(LocStsType.PAKOUT.val());
@@ -180,8 +187,15 @@
                    }
                    destSta = staService.getById(task.getDestSta());
                    if (!destSta.getStaSts().equals(StaStsType.IDLE.val())) {
                        throw new BusinessException("destSta:" + task.getDestSta$() + " is not in IDLE status");
                    if (destSta.getStaTypeIsCheck() != 1) {
                        if (locStaStatusCheck && !destSta.getStaSts().equals(StaStsType.IDLE.val())) {
                            throw new BusinessException("destSta:" + task.getDestSta$() + " is not in IDLE status");
                        }
                    } else {
                        List<Task> list = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getDestSta, destSta.getId()).in(Task::getTaskSts, TaskStsType.INIT.val(), TaskStsType.WAITING.val(), TaskStsType.ASSIGN.val(), TaskStsType.PROGRESS.val()));
                        if (!Cools.isEmpty(list) && list.size() >= locStaTaskNum) {
                            throw new BusinessException("destSta:" + task.getDestSta$() + " task more");
                        }
                    }
                    destSta.setStaSts(StaStsType.READY_RELEASE.val());
                    destSta.setUpdateTime(now);
@@ -191,8 +205,10 @@
                    break;
                case STA_TO_LOC:
                    oriSta = staService.getById(task.getOriSta());
                    if (!oriSta.getStaSts().equals(StaStsType.STOCK.val())) {
                        throw new BusinessException("oriSta:" + task.getOriSta$() + " is not in STOCK status");
                    if (oriSta.getStaTypeIsCheck() != 1) {
                        if (locStaStatusCheck && !oriSta.getStaSts().equals(StaStsType.STOCK.val())) {
                            throw new BusinessException("oriSta:" + task.getOriSta$() + " is not in STOCK status");
                        }
                    }
                    oriSta.setStaSts(StaStsType.READY_TAKE.val());
                    oriSta.setUpdateTime(now);
@@ -201,7 +217,7 @@
                    }
                    destLoc = locService.getById(task.getDestLoc());
                    if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
                    if (locStaStatusCheck && !destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
                        throw new BusinessException("destLoc:" + task.getDestLoc$() + " is not in IDLE status");
                    }
                    destLoc.setLocSts(LocStsType.PAKIN.val());
@@ -212,8 +228,10 @@
                    break;
                case STA_TO_STA:
                    oriSta = staService.getById(task.getOriSta());
                    if (!oriSta.getStaSts().equals(StaStsType.STOCK.val())) {
                        throw new BusinessException("oriSta:" + task.getOriSta$() + " is not in STOCK status");
                    if (oriSta.getStaTypeIsCheck() != 1) {
                        if (locStaStatusCheck && !oriSta.getStaSts().equals(StaStsType.STOCK.val())) {
                            throw new BusinessException("oriSta:" + task.getOriSta$() + " is not in STOCK status");
                        }
                    }
                    oriSta.setStaSts(StaStsType.READY_TAKE.val());
                    oriSta.setUpdateTime(now);
@@ -222,8 +240,15 @@
                    }
                    destSta = staService.getById(task.getDestSta());
                    if (!destSta.getStaSts().equals(StaStsType.IDLE.val())) {
                        throw new BusinessException("destSta:" + task.getDestSta$() + " is not in IDLE status");
                    if (destSta.getStaTypeIsCheck() != 1) {
                        if (locStaStatusCheck && !destSta.getStaSts().equals(StaStsType.IDLE.val())) {
                            throw new BusinessException("destSta:" + task.getDestSta$() + " is not in IDLE status");
                        }
                    } else {
                        List<Task> list = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getDestSta, destSta.getId()).in(Task::getTaskSts, TaskStsType.INIT.val(), TaskStsType.WAITING.val(), TaskStsType.ASSIGN.val(), TaskStsType.PROGRESS.val()));
                        if (!Cools.isEmpty(list) && list.size() >= locStaTaskNum) {
                            throw new BusinessException("destSta:" + task.getDestSta$() + " task more");
                        }
                    }
                    destSta.setStaSts(StaStsType.READY_RELEASE.val());
                    destSta.setUpdateTime(now);
@@ -277,6 +302,7 @@
                if (!taskService.updateById(task)) {
                    throw new BusinessException("seqNum: " + task.getSeqNum() + " failed to update");
                }
                report(task, null, TaskReportStsType.START);
            }
        } catch (Exception e) {
            log.error("mainService.infuseAgvForTask", e);
@@ -763,7 +789,11 @@
                        boolean reverse = false;
                        if (nextDirection.equals((workDirection + 180) % 360)) {
                            nextDirection = workDirection;
                            reverse = true;
                            if (Objects.requireNonNull(TaskPosDto.queryPosType(segment.getPosType())).equals(TaskPosDto.PosType.ORI_STA)) {
                                reverse = false;
                            } else {
                                reverse = true;
                            }
                        }
                        // 第二步:判断当前节点是否可以旋转
@@ -784,27 +814,649 @@
                                    nextDirection = lastDirection;
                                    reverse = true;
                                } else {
                                    // turn
                                    actionList.add(new Action(
                                            null,    // 编号s
                                            task.getBusId(),    // 总线
                                            task.getId(),    // 任务
                                            null,    // 动作号
                                            null,    // 优先级
                                            ActionTypeType.TurnCorner.desc,    // 名称
                                            mapService.isTurnCorner(lastCode.getData()) ? 1D : 0D,    // 属性值
                                            lastCode.getData(),    // 地面码
                                            String.valueOf(nextDirection),   // 动作参数
                                            ActionTypeType.TurnCorner.val(),    // 动作类型
                                            actionPrepareSts,    // 动作进度
                                            agvId,    // AGV
                                            now    // 工作时间
                                    ));
                                    if ((Objects.requireNonNull(TaskPosDto.queryPosType(segment.getPosType()))
                                            .equals(TaskPosDto.PosType.ORI_STA) || Objects.requireNonNull(TaskPosDto.queryPosType(segment.getPosType()))
                                            .equals(TaskPosDto.PosType.DEST_STA)) && lastCode.getData().equals("00000050")) {
                                        // turn
                                        reverse = false;
                                        actionList.add(new Action(
                                                null,    // 编号s
                                                task.getBusId(),    // 总线
                                                task.getId(),    // 任务
                                                null,    // 动作号
                                                null,    // 优先级
                                                ActionTypeType.TurnCorner.desc,    // 名称
                                                mapService.isTurnCorner(lastCode.getData()) ? 1D : 0D,    // 属性值
                                                lastCode.getData(),    // 地面码
                                                String.valueOf(180),   // 动作参数
                                                ActionTypeType.TurnCorner.val(),    // 动作类型
                                                actionPrepareSts,    // 动作进度
                                                agvId,    // AGV
                                                now    // 工作时间
                                        ));
                                    } else {
                                        // turn
                                        actionList.add(new Action(
                                                null,    // 编号s
                                                task.getBusId(),    // 总线
                                                task.getId(),    // 任务
                                                null,    // 动作号
                                                null,    // 优先级
                                                ActionTypeType.TurnCorner.desc,    // 名称
                                                mapService.isTurnCorner(lastCode.getData()) ? 1D : 0D,    // 属性值
                                                lastCode.getData(),    // 地面码
                                                String.valueOf(nextDirection),   // 动作参数
                                                ActionTypeType.TurnCorner.val(),    // 动作类型
                                                actionPrepareSts,    // 动作进度
                                                agvId,    // AGV
                                                now    // 工作时间
                                        ));
                                    }
                                    lastDirection = nextDirection;
                                }
                            }
                        }
                        // 第一个动作一定是 turn
                        if (actionList.isEmpty()) {
                            // turn
                            actionList.add(new Action(
                                    null,    // 编号
                                    task.getBusId(),    // 总线
                                    task.getId(),    // 任务
                                    null,    // 动作号
                                    null,    // 优先级
                                    ActionTypeType.TurnCorner.desc,    // 名称
                                    mapService.isTurnCorner(lastCode.getData()) ? 1D : 0D,    // 属性值
                                    lastCode.getData(),    // 地面码
                                    String.valueOf(nextDirection),   // 动作参数
                                    ActionTypeType.TurnCorner.val(),    // 动作类型
                                    actionPrepareSts,    // 动作进度
                                    agvId,    // AGV
                                    now    // 工作时间
                            ));
                            lastDirection = nextDirection;
                        }
                        // run
                        ActionTypeType actionType = ActionTypeType.StraightAheadTurnable;
                        if (reverse) {
                            actionType = ActionTypeType.StraightBackTurnable;
                        }
                        CodeGap gap = codeGapService.findByCodeOfBoth(lastCode.getId(), nextCode.getId());
                        actionList.add(new Action(
                                null,    // 编号
                                task.getBusId(),    // 总线
                                task.getId(),    // 任务
                                null,    // 动作号
                                null,    // 优先级
                                actionType.desc,    // 名称
                                (double) agvSpeedType.val,    // 属性值
                                lastCode.getData(),    // 地面码
                                String.valueOf(gap.getDistance()),   // 动作参数
                                actionType.val(),    // 动作类型
                                actionPrepareSts,    // 动作进度
                                agvId,    // AGV
                                now    // 工作时间
                        ));
                        lastCode = nextCode;
                    }
                }
                // 初始方向值补丁
                if (first) {
                    if (Cools.isEmpty(actionList) || !actionList.get(0).getActionType().equals(ActionTypeType.TurnCorner.val())) {
                        // turn
                        actionList.add(new Action(
                                null,    // 编号
                                task.getBusId(),    // 总线
                                task.getId(),    // 任务
                                null,    // 动作号
                                null,    // 优先级
                                ActionTypeType.TurnCorner.desc,    // 名称
                                mapService.isTurnCorner(lastCode.getData()) ? 1D : 0D,    // 属性值
                                lastCode.getData(),    // 地面码
                                String.valueOf(workDirection),   // 动作参数
                                ActionTypeType.TurnCorner.val(),    // 动作类型
                                actionPrepareSts,    // 动作进度
                                agvId,    // AGV
                                now    // 工作时间
                        ));
                        lastDirection = workDirection;
                    }
                    first = false;
                }
                // 作业点动作
                AgvDirectionType agvDirectionType;
                Double staWorkDirection;
                AgvBackpackType backpackType = AgvBackpackType.query(segment.getBackpack());
                switch (Objects.requireNonNull(TaskPosDto.queryPosType(segment.getPosType()))) {
                    case ORI_LOC:
                        assert backpackType != null;
                        // 检验方向
                        if (!lastDirection.equals(workDirection)) {
                            throw new CoolException(agvNo + "号小车方向错误,请推至转弯点手动调整");
                        }
                        // 货架取货
                        Loc oriLoc = locService.getById(task.getOriLoc());
                        // 计算左右方向
                        agvDirectionType = mapService.calculateAgvWorkDirectionByShelf(oriLoc, lastCode);
                        actionList.add(new Action(
                                null,    // 编号
                                task.getBusId(),    // 总线
                                task.getId(),    // 任务
                                null,    // 动作号
                                null,    // 优先级
                                ActionTypeType.ReadyTakeFromShelvesLoc.desc,    // 名称
                                (double) agvDirectionType.val,    // 属性值
                                lastCode.getData(),    // 地面码
                                String.valueOf(oriLoc.getOffset()),   // 动作参数
                                ActionTypeType.ReadyTakeFromShelvesLoc.val(),    // 动作类型
                                actionPrepareSts,    // 动作进度
                                agvId,    // AGV
                                now    // 工作时间
                        ));
                        // 暂存点放货
                        actionList.add(new Action(
                                null,    // 编号
                                task.getBusId(),    // 总线
                                task.getId(),    // 任务
                                null,    // 动作号
                                null,    // 优先级
                                ActionTypeType.ReadyReleaseToAgvSite.desc,    // 名称
                                (double) backpackType.lev,    // 属性值
                                lastCode.getData(),    // 地面码
                                String.valueOf(backpackType.height),   // 动作参数
                                ActionTypeType.ReadyReleaseToAgvSite.val(),    // 动作类型
                                actionPrepareSts,    // 动作进度
                                agvId,    // AGV
                                now    // 工作时间
                        ));
                        break;
                    case DEST_LOC:
                        assert backpackType != null;
                        // 检验方向
                        if (!lastDirection.equals(workDirection)) {
                            throw new CoolException(agvNo + "号小车方向错误,请推至转弯点手动调整");
                        }
                        // 暂存点取货货
                        actionList.add(new Action(
                                null,    // 编号
                                task.getBusId(),    // 总线
                                task.getId(),    // 任务
                                null,    // 动作号
                                null,    // 优先级
                                ActionTypeType.ReadyTakeFromAgvSite.desc,    // 名称
                                (double) backpackType.lev,    // 属性值
                                lastCode.getData(),    // 地面码
                                String.valueOf(backpackType.height),   // 动作参数
                                ActionTypeType.ReadyTakeFromAgvSite.val(),    // 动作类型
                                actionPrepareSts,    // 动作进度
                                agvId,    // AGV
                                now    // 工作时间
                        ));
                        // 货架放货
                        Loc destLoc = locService.getById(task.getDestLoc());
                        // 计算左右方向
                        agvDirectionType = mapService.calculateAgvWorkDirectionByShelf(destLoc, lastCode);
                        actionList.add(new Action(
                                null,    // 编号
                                task.getBusId(),    // 总线
                                task.getId(),    // 任务
                                null,    // 动作号
                                null,    // 优先级
                                ActionTypeType.ReadyReleaseToShelvesLoc.desc,    // 名称
                                (double) agvDirectionType.val,    // 属性值
                                lastCode.getData(),    // 地面码
                                String.valueOf(destLoc.getOffset()),   // 动作参数
                                ActionTypeType.ReadyReleaseToShelvesLoc.val(),    // 动作类型
                                actionPrepareSts,    // 动作进度
                                agvId,    // AGV
                                now    // 工作时间
                        ));
                        break;
                    case ORI_STA:
                        // 站点取货
                        Sta oriSta = staService.getById(task.getOriSta());
                        Double oriStaWorkDirection = mapService.getStaAngle(oriSta, workDirection);
                        // 检验方向
//                        if (!lastDirection.equals(oriStaWorkDirection)) {
//                            if (!lastCode.getCornerBool()) {
//                                throw new CoolException(agvNo + "号小车方向错误,请推至转弯点手动调整");
//                            }
//                            // turn
//                            actionList.add(new Action(
//                                    null,    // 编号
//                                    task.getBusId(),    // 总线
//                                    task.getId(),    // 任务
//                                    null,    // 动作号
//                                    null,    // 优先级
//                                    ActionTypeType.TurnCorner.desc,    // 名称
//                                    mapService.isTurnCorner(lastCode.getData()) ? 1D : 0D,    // 属性값
//                                    lastCode.getData(),    // 地面码
//                                    String.valueOf(oriStaWorkDirection),   // 动作参数
//                                    ActionTypeType.TurnCorner.val(),    // 动作类型
//                                    actionPrepareSts,    // 动作进度
//                                    agvId,    // AGV
//                                    now    // 工作时间
//                            ));
//                            lastDirection = oriStaWorkDirection;
//                        }
                        // 计算货叉工作方向
                        staWorkDirection = mapService.calculateAgvWorkDirectionByStation(oriStaWorkDirection, lastDirection);
                        actionList.add(new Action(
                                null,    // 编号
                                task.getBusId(),    // 总线
                                task.getId(),    // 任务
                                null,    // 动作号
                                null,    // 优先级
                                ActionTypeType.ReadyTakeFromShelvesLoc.desc,    // 名称
                                Double.parseDouble("0"),    // 属性值
                                lastCode.getData(),    // 地面码
                                String.valueOf(oriSta.getOffset()),   // 动作参数
                                ActionTypeType.ReadyTakeFromShelvesLoc.val(),    // 动作类型
                                actionPrepareSts,    // 动作进度
                                agvId,    // AGV
                                now,    // 工作时间
                                oriSta.getStaTypeIsCheck() == 1 ? 1 : 0,
                                oriSta.getStaNo()
                        ));
                        // 暂存点放货
                        assert backpackType != null;
                        actionList.add(new Action(
                                null,    // 编号
                                task.getBusId(),    // 总线
                                task.getId(),    // 任务
                                null,    // 动作号
                                null,    // 优先级
                                ActionTypeType.ReadyReleaseToAgvSite.desc,    // 名称
                                (double) backpackType.lev,    // 属性값
                                lastCode.getData(),    // 地面码
                                String.valueOf(backpackType.height),   // 动作参数
                                ActionTypeType.ReadyReleaseToAgvSite.val(),    // 动作类型
                                actionPrepareSts,    // 动作进度
                                agvId,    // AGV
                                now    // 工作时间
                        ));
                        break;
                    case DEST_STA:
                        // 站点放货
                        Sta destSta = staService.getById(task.getDestSta());
                        Double destStaWorkDirection = mapService.getStaAngle(destSta, workDirection);
//                        CodeGap gap = codeGapService.findByCodeOfBoth(lastCode.getId(), nextCode.getId());
                        // 检验方向
//                        if (!lastDirection.equals(destStaWorkDirection)) {
//                            if (!lastCode.getCornerBool()) {
//                                throw new CoolException(agvNo + "号小车方向错误,请推至转弯点手动调整");
//                            }
//
//                            actionList.add(new Action(
//                                    null,    // 编号
//                                    task.getBusId(),    // 总线
//                                    task.getId(),    // 任务
//                                    null,    // 动作号
//                                    null,    // 优先级
//                                    actionType.desc,    // 名称
//                                    (double) agvSpeedType.val,    // 属性值
//                                    lastCode.getData(),    // 地面码
//                                    String.valueOf(gap.getDistance()),   // 动作参数
//                                    actionType.val(),    // 动作类型
//                                    actionPrepareSts,    // 动作进度
//                                    agvId,    // AGV
//                                    now    // 工作时间
//                            ));
//                            // turn
//                            actionList.add(new Action(
//                                    null,    // 编号
//                                    task.getBusId(),    // 总线
//                                    task.getId(),    // 任务
//                                    null,    // 动作号
//                                    null,    // 优先级
//                                    ActionTypeType.TurnCorner.desc,    // 名称
//                                    mapService.isTurnCorner(lastCode.getData()) ? 1D : 0D,    // 属性값
//                                    lastCode.getData(),    // 地面码
//                                    String.valueOf(destStaWorkDirection),   // 动作参数
//                                    ActionTypeType.TurnCorner.val(),    // 动作类型
//                                    actionPrepareSts,    // 动作进度
//                                    agvId,    // AGV
//                                    now   // 工作时间
//                            ));
//                            lastDirection = destStaWorkDirection;
//                        }
                        // 暂存点取货
                        assert backpackType != null;
                        actionList.add(new Action(
                                null,    // 编号
                                task.getBusId(),    // 总线
                                task.getId(),    // 任务
                                null,    // 动作号
                                null,    // 优先级
                                ActionTypeType.ReadyTakeFromAgvSite.desc,    // 名称
                                (double) backpackType.lev,    // 属性값
                                lastCode.getData(),    // 地面码
                                String.valueOf(backpackType.height),   // 动作参数
                                ActionTypeType.ReadyTakeFromAgvSite.val(),    // 动作类型
                                actionPrepareSts,    // 动作进度
                                agvId,    // AGV
                                now    // 工作时间
                        ));
                        // 计算货叉工作方向
                        staWorkDirection = mapService.calculateAgvWorkDirectionByStation(destStaWorkDirection, lastDirection);
                        actionList.add(new Action(
                                null,    // 编号
                                task.getBusId(),    // 总线
                                task.getId(),    // 任务
                                null,    // 动作号
                                null,    // 优先级
                                ActionTypeType.ReadyReleaseToShelvesLoc.desc,    // 名称
                                Double.parseDouble("0"),    // 属性值
                                lastCode.getData(),    // 地面码
                                String.valueOf(destSta.getOffset()),   // 动作参数
                                ActionTypeType.ReadyReleaseToShelvesLoc.val(),    // 动作类型
                                actionPrepareSts,    // 动作进度
                                agvId,    // AGV
                                now,    // 工作时间
                                destSta.getStaTypeIsCheck() == 1 ? 2 : 0,
                                destSta.getStaNo()
                        ));
                        break;
                    case TO_CHARGE:
                        // 检验方向
                        FuncSta chargeFuncSta = funcStaService.query(lastCode.getId(), FuncStaType.CHARGE.toString());
                        Double chargeDirection = Double.parseDouble(chargeFuncSta.getAngle());
                        if (!lastDirection.equals(chargeDirection)&&lastCode.getCornerBool()) {
                            actionList.add(new Action(
                                    null,    // 编号
                                    null,    // 总线
                                    task.getId(),    // 任务
                                    null,    // 动作号
                                    null,    // 优先级
                                    ActionTypeType.TurnCorner.desc,    // 名称
                                    mapService.isTurnCorner(lastCode.getData()) ? 1D : 0D,    // 属性값
                                    lastCode.getData(),    // 地面码
                                    String.valueOf(chargeDirection),   // 动作参数
                                    ActionTypeType.TurnCorner.val(),    // 动作类型
                                    actionPrepareSts,    // 动作进度
                                    agvId,    // AGV
                                    now    // 工作时间
                            ));
                            lastDirection = chargeDirection;
                        }
                        // charge
                        actionList.add(new Action(
                                null,    // 编号
                                null,    // 总线
                                task.getId(),    // 任务
                                null,    // 动作号
                                null,    // 优先级
                                ActionTypeType.DockingCharge.desc,    // 名称
                                null,    // 属性값
                                lastCode.getData(),    // 地面码
                                null,   // 动作参数
                                ActionTypeType.DockingCharge.val(),    // 动作类型
                                actionPrepareSts,    // 动作进度
                                agvId,    // AGV
                                now    // 工作时间
                        ));
                        break;
                    case TO_STANDBY:
//                        FuncSta standByFuncSta = funcStaService.query(agvId, lastCode.getId(), 2);
//                        Double standByDirection = Double.parseDouble(standByFuncSta.getAngle());
//                        if (!lastDirection.equals(standByDirection)) {
//                            actionList.add(new Action(
//                                    null,    // 编号
//                                    null,    // 总线
//                                    task.getId(),    // 任务
//                                    null,    // 动作号
//                                    null,    // 优先级
//                                    ActionTypeType.TurnCorner.desc,    // 名称
//                                    null,    // 属性값
//                                    lastCode.getData(),    // 地面码
//                                    String.valueOf(standByDirection),   // 动作参数
//                                    ActionTypeType.TurnCorner.val(),    // 动作类型
//                                    actionPrepareSts,    // 动作进度
//                                    agvId,    // AGV
//                                    now    // 工作时间
//                            ));
//                            lastDirection = standByDirection;
//                        }
                        String runToWaitHeightFlag = configService.getVal("RunToWaitHeightFlag", String.class);
                        if (!Cools.isEmpty(runToWaitHeightFlag) && runToWaitHeightFlag.contains(agvId.toString())) {
                            String runToWaitHeight = configService.getVal("RunToWaitHeight", String.class);
                            if (Cools.isEmpty(runToWaitHeight)) {
                                runToWaitHeight = "800";
                            }
                            Double runToWaitHeightValue = configService.getVal("RunToWaitHeightValue", Double.class);
                            if (runToWaitHeightValue == 0) {
                                runToWaitHeightValue = 1D;
                            }
                            // 修复空指针异常:检查lastCode是否为null
                            if (lastCode == null) {
                                throw new BusinessException("AGV定位信息异常,无法生成待机动作");
                            }
                            actionList.add(new Action(
                                    null,    // 编号
                                    task.getBusId(),    // 总线
                                    task.getId(),    // 任务
                                    null,    // 动作号
                                    null,    // 优先级
                                    ActionTypeType.RunToWaitHeight.desc,    // 名称
                                    runToWaitHeightValue,    // 属性값
                                    lastCode.getData(),    // 地面码
                                    runToWaitHeight,   // 动作参数
                                    ActionTypeType.RunToWaitHeight.val(),    // 动作类型
                                    actionPrepareSts,    // 动作进度
                                    agvId,    // AGV
                                    now    // 工作时间
                            ));
                        }
                        break;
                    case MOVE:
                        break;
                    default:
                        break;
                }
            }
            // finish
            actionList.add(new Action(
                    null,    // 编号
                    null,    // 总线
                    null,    // 任务
                    null,    // 动作号
                    null,    // 优先级
                    ActionTypeType.FinishPath.desc,    // 名称
                    null,    // 属性值
                    lastCode.getData(),    // 地面码
                    null,   // 动作参数
                    ActionTypeType.FinishPath.val(),    // 动作类型
                    actionPrepareSts,    // 动作进度
                    agvId,    // AGV
                    now    // 工作时间
            ));
            List<Action> newActionList = actionSorter.optimizeSort(actionList);
            String groupId = String.valueOf(snowflakeIdWorker.nextId()).substring(3);
            // save action
            int i = newActionList.size();
            for (Action action : newActionList) {
//                action.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
                action.setGroupId(groupId);
                action.setPriority(i);
                i -= 1;
            }
            if (!actionService.saveBatch(newActionList)) {
                throw new BusinessException("group[" + groupId + "] 动作保存失败");
            }
            // update segment
            for (Segment item : segmentList) {
                item.setGroupId(groupId);
                item.setState(SegmentStateType.RUNNING.toString());
                item.setUpdateTime(now);
                if (null != algoStartTime) {
                    item.setAlgoTime((int) (now.getTime() - algoStartTime.getTime()));
                }
                if (!segmentService.updateById(item)) {
                    throw new CoolException("更新Segment失败");
                }
            }
            log.info("{}号Agv动作组装完成,指令数量:{}", agvNo, newActionList.size());
        } catch (Exception e) {
            log.error("mainService.generateAction", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            if (!Cools.isEmpty(pathList)) {
                pathList.remove(0);
                List<int[]> codeMatrixIdxList = mapDataDispatcher.getCodeMatrixIdxList(null, pathList);
                mapDataDispatcher.clearDynamicMatrixByCodeList(null, codeMatrixIdxList);
            }
            throw new RuntimeException("generateAction method caught an exception, rolling back transaction.", e);
        }
    }
    /**
     * 根据分片生成动作 ( 车辆可能已经做过一些任务了,正在等待下一段任务 )
     */
    @Transactional
    public synchronized void generateActionV2(Long agvId, List<Segment> segmentList, List<String> pathList, Date algoStartTime) {
        try {
            if (Cools.isEmpty(agvId, segmentList)) {
                return;
            }
            Date now = new Date();
            long actionPrepareSts = ActionStsType.PREPARE.val();
//            JSONObject storeDirection = configService.getVal("storeDirection", JSONObject.class);
            int angleOffsetVal = configService.getVal("mapAngleOffsetVal", Integer.class);
            String agvNo = agvService.getAgvNo(agvId);
//            if (!agvService.judgeEnable(agvId)) {
//                throw new CoolException("AGV[" + agvNo + "]当前不可用...");
//            }
            AgvModel agvModel = agvModelService.getByAgvId(agvId);
            Double workDirection = agvModel.getWorkDirection();
            AgvSpeedType agvSpeedType = AgvSpeedType.query(agvModel.getTravelSpeed());
            assert agvSpeedType != null;
            AgvDetail agvDetail = agvDetailService.selectMajorByAgvId(agvId);
            List<Action> actionList = new ArrayList<>();
            // start node
            Code lastCode = codeService.getCacheById(agvDetail.getRecentCode());
            Double lastDirection = MapService.mapToNearest(agvDetail.getAgvAngle());
            if (!lastCode.getData().equals(pathList.get(0))) {
                throw new CoolException("AGV[" + agvNo + "]定位偏移...");
            }
            //String lastCorner = null;
            Integer index = -1;
            boolean corner = false;
            for (int i = pathList.size(); i < 0; i++) {
                Code nextCode = codeService.getCacheByData(pathList.get(i));
                if (nextCode != null && nextCode.getCornerBool()) {
                    //lastCorner = pathList.get(i);
                    index = i;
                }
            }
            boolean first = true;
            for (Segment segment : segmentList) {
                // 分段所属的Task
                Task task = taskService.getById(segment.getTaskId());
                // 节点条码
                Code code = codeService.getCacheById(segment.getEndNode());
                // 需要走行
                if (!lastCode.getData().equals(code.getData())) {
                    // 走行路径节点
//                    List<String> pathList = mapService.checkoutPath(agv.getUuid(), lastCode, code);
                    List<String> pathListPart = pathList.subList(pathList.indexOf(lastCode.getData()), pathList.indexOf(code.getData()) + 1);
                    for (int i = 0; i < pathListPart.size(); i++) {
                        if (i == 0) {
                            continue;
                        }
                        String next = pathListPart.get(i);
                        Code nextCode = codeService.getCacheByData(next);
                        Double nextDirection;
                        boolean reverse = false;
                        if (index >= i) {
                            // DOTO 添加转弯
                            Code endCode = codeService.getCacheByData(pathList.get(pathList.size() - 1));
                            nextDirection = mapService.calculateDirection(lastCode, endCode, angleOffsetVal);
                            reverse = true;
                        } else {
                            nextDirection = mapService.calculateDirection(lastCode, nextCode, angleOffsetVal);
                            // 第一步:如果下一个方向正好是作业方向的相反方向,则重置下一个方向为作业方向,标记 reverse = true
                            if (!nextDirection.equals((workDirection+180) % 360)) {
                                nextDirection = workDirection;
                                reverse = true;
                            }
                            // 第二步:判断当前节点是否可以旋转
                            if (!lastCode.getCornerBool()) {
                                // 如果是作业方向,但是小车在巷道内方向错误,则停止
                                if (reverse && !lastDirection.equals(nextDirection)) {
//                                throw new CoolException(agvNo + "号小车方向错误,请推至转弯点手动调整");
                                }
                                // 如果不是作业方向,判断是否相反方向,如果反方向则倒退行走
                                if (nextDirection.equals((lastDirection + 180) % 360)) {
                                    nextDirection = lastDirection;
                                    reverse = true;
                                }
                            } else {
                                if (!lastDirection.equals(nextDirection)) {
                                    // 如果下个节点方向与当前agv方向相反,则倒退行走,但是如果当前agv方向正好与工作方向相反,则旋转至工作方向
                                    if (nextDirection.equals((lastDirection + 180) % 360) && !workDirection.equals((lastDirection + 180) % 360)) {
                                        nextDirection = lastDirection;
                                        reverse = true;
                                    } else {
                                        // turn
                                        actionList.add(new Action(
                                                null,    // 编号s
                                                task.getBusId(),    // 总线
                                                task.getId(),    // 任务
                                                null,    // 动作号
                                                null,    // 优先级
                                                ActionTypeType.TurnCorner.desc,    // 名称
                                                mapService.isTurnCorner(lastCode.getData()) ? 1D : 0D,    // 属性值
                                                lastCode.getData(),    // 地面码
                                                String.valueOf(nextDirection),   // 动作参数
                                                ActionTypeType.TurnCorner.val(),    // 动作类型
                                                actionPrepareSts,    // 动作进度
                                                agvId,    // AGV
                                                now    // 工作时间
                                        ));
                                        lastDirection = nextDirection;
                                    }
                                }
                            }
                        }
                        // 第一个动作一定是 turn
                        if (actionList.isEmpty()) {
@@ -1014,7 +1666,9 @@
                                ActionTypeType.ReadyTakeFromConveyorSta.val(),    // 动作类型
                                actionPrepareSts,    // 动作进度
                                agvId,    // AGV
                                now    // 工作时间
                                now,    // 工作时间
                                oriSta.getStaTypeIsCheck() == 1 ? 1 : 0,
                                oriSta.getStaNo()
                        ));
                        // 暂存点放货
                        assert backpackType != null;
@@ -1057,7 +1711,7 @@
                                    ActionTypeType.TurnCorner.val(),    // 动作类型
                                    actionPrepareSts,    // 动作进度
                                    agvId,    // AGV
                                    now    // 工作时间
                                    now   // 工作时间
                            ));
                            lastDirection = destStaWorkDirection;
                        }
@@ -1077,6 +1731,7 @@
                                actionPrepareSts,    // 动作进度
                                agvId,    // AGV
                                now    // 工作时间
                        ));
                        // 计算货叉工作方向
                        staWorkDirection = mapService.calculateAgvWorkDirectionByStation(destStaWorkDirection, lastDirection);
@@ -1093,14 +1748,16 @@
                                ActionTypeType.ReadyReleaseToConveyorSta.val(),    // 动作类型
                                actionPrepareSts,    // 动作进度
                                agvId,    // AGV
                                now    // 工作时间
                                now,    // 工作时间
                                destSta.getStaTypeIsCheck() == 1 ? 2 : 0,
                                destSta.getStaNo()
                        ));
                        break;
                    case TO_CHARGE:
                        // 检验方向
                        FuncSta chargeFuncSta = funcStaService.query(lastCode.getId(), FuncStaType.CHARGE.toString());
                        Double chargeDirection = Double.parseDouble(chargeFuncSta.getAngle());
                        if (!lastDirection.equals(chargeDirection)) {
                        if (!lastDirection.equals(chargeDirection) && lastCode.getCornerBool()) {
                            actionList.add(new Action(
                                    null,    // 编号
                                    null,    // 总线
@@ -1164,7 +1821,7 @@
                                runToWaitHeight = "800";
                            }
                            Double runToWaitHeightValue = configService.getVal("RunToWaitHeightValue", Double.class);
                            if (Cools.isEmpty(runToWaitHeight) || runToWaitHeightValue == 0) {
                            if (runToWaitHeightValue == 0) {
                                runToWaitHeightValue = 1D;
                            }
                            // 修复空指针异常:检查lastCode是否为null
@@ -1243,7 +1900,7 @@
            log.info("{}号Agv动作组装完成,指令数量:{}", agvNo, newActionList.size());
        } catch (Exception e) {
            log.error("mainService.generateAction", e);
            log.error("mainService.generateActionV2", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            if (!Cools.isEmpty(pathList)) {
@@ -1252,15 +1909,16 @@
                mapDataDispatcher.clearDynamicMatrixByCodeList(null, codeMatrixIdxList);
            }
            throw new RuntimeException("generateAction method caught an exception, rolling back transaction.", e);
            throw new RuntimeException("generateActionV2 method caught an exception, rolling back transaction.", e);
        }
    }
    @Transactional
    public void publishAction(String actionGroupId) {
        try {
            Date now = new Date();
            boolean flag = true;
            // action
            List<Action> actionList = actionService.list(new LambdaQueryWrapper<Action>()
                    .eq(Action::getGroupId, actionGroupId).eq(Action::getActionSts, ActionStsType.PREPARE.val())
@@ -1342,6 +2000,9 @@
                                .setQrCode(action.getCode())
                                .bodySync(body -> body.setHeight((short) Double.parseDouble(action.getParams())))
                        );
                        if (!Cools.isEmpty(action.getAskType()) && (action.getAskType() == 1 || action.getAskType() == 2)) {
                            flag = askSta(action.getAskType(), action.getAskSta());
                        }
                        break;
                    case ReadyTakeFromAgvSite:
                        agvAction.add(new AgvActionItem<>(ReadyTakeFromAgvSite.class)
@@ -1363,6 +2024,9 @@
                                .setQrCode(action.getCode())
                                .bodySync(body -> body.setHeight((short) Double.parseDouble(action.getParams())))
                        );
                        if (!Cools.isEmpty(action.getAskType()) && (action.getAskType() == 1 || action.getAskType() == 2)) {
                            flag = askSta(action.getAskType(), action.getAskSta());
                        }
                        break;
                    case ReadyReleaseToAgvSite:
                        agvAction.add(new AgvActionItem<>(ReadyReleaseToAgvSite.class)
@@ -1393,7 +2057,10 @@
                }
            }
            if (!flag) {
                log.error("任务组 [{}] 动作指令下发失败 ,向输送线询问报错!!!", actionGroupId);
                throw new CoolException("任务组 [{" + actionGroupId + "}] 动作指令下发失败 !!!");
            }
            BaseResult<?> result = agvCmdService.executeAgvActionCmd(agvAction);
            if (result.success()) {
                log.info("任务组 [{}] 动作指令已下发 ===>> 指令数量:{}", actionGroupId, actionList.size());
@@ -1432,66 +2099,98 @@
            if (agv_11_up.getCompleteType().equals(AgvCompleteType.RELEASE_FROM_SHELVES_COMPLETE)) {
                WebsocketServiceImpl.taskShelfBarcode = agv_11_up.getLocCode();
                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());
                } else {
                    List<Long> taskIds = actionService.selectTaskIdsByGroupId(serialNo);
                    for (Long taskId : taskIds) {
                        Task task = taskService.getById(taskId);
                        if (task.getDestLoc().equals(loc.getId())) {
//                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());
//                } else {
//                    List<Long> taskIds = actionService.selectTaskIdsByGroupId(serialNo);
//                    for (Long taskId : taskIds) {
//                        Task task = taskService.getById(taskId);
//                        if (task.getDestLoc().equals(loc.getId())) {
//
//                            Action action = actionService.getOne(new LambdaQueryWrapper<Action>()
//                                    .eq(Action::getTaskId, task.getId())
//                                    .eq(Action::getActionType, ActionTypeType.ReadyReleaseToShelvesLoc.val())
//                                    .eq(Action::getActionSts, ActionStsType.ISSUED.val())
//                            );
//
//                            if (null != action) {
//                                action.setActionSts(ActionStsType.FINISH.val());
//                                action.setEndTime(now);
//                                action.setUpdateTime(now);
//                                if (!actionService.updateById(action)) {
//                                    log.error("Action [{}] 更新失败 !!!", action.getPriority() + " - " + action.getName());
//                                }
//                            }
//                            //插入一条
//                            report(task, TaskReportStsType.END);
//                        }
//                    }
//                }
                            Action action = actionService.getOne(new LambdaQueryWrapper<Action>()
                                    .eq(Action::getTaskId, task.getId())
                                    .eq(Action::getActionType, ActionTypeType.ReadyReleaseToShelvesLoc.val())
                                    .eq(Action::getActionSts, ActionStsType.ISSUED.val())
                            );
                            if (null != action) {
                                action.setActionSts(ActionStsType.FINISH.val());
                                action.setEndTime(now);
                                action.setUpdateTime(now);
                                if (!actionService.updateById(action)) {
                                    log.error("Action [{}] 更新失败 !!!", action.getPriority() + " - " + action.getName());
                                }
                            }
                        }
                    }
                }
//                List<Long> taskIds = actionService.selectTaskIdsByGroupId(serialNo);
//                for (Long taskId : taskIds) {
//                    Task task = taskService.getById(taskId);
//                    report(task, agv_11_up.getQrCode(), TaskReportStsType.END);
//                }
            }
            // 出库取货
            if (agv_11_up.getCompleteType().equals(AgvCompleteType.TAKE_FROM_SHELVES_COMPLETE)) {
                WebsocketServiceImpl.taskShelfBarcode = agv_11_up.getLocCode();
                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());
                } else {
//                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());
//                } else {
//
//                    List<Long> taskIds = actionService.selectTaskIdsByGroupId(serialNo);
//                    for (Long taskId : taskIds) {
//                        Task task = taskService.getById(taskId);
//                        if (task.getOriLoc().equals(loc.getId())) {
//
//                            Action action = actionService.getOne(new LambdaQueryWrapper<Action>()
//                                    .eq(Action::getTaskId, task.getId())
//                                    .eq(Action::getActionType, ActionTypeType.ReadyTakeFromShelvesLoc.val())
//                                    .eq(Action::getActionSts, ActionStsType.ISSUED.val())
//                            );
//                            if (null != action) {
//                                action.setActionSts(ActionStsType.FINISH.val());
//                                action.setEndTime(now);
//                                action.setUpdateTime(now);
//                                if (!actionService.updateById(action)) {
//                                    log.error("Action [{}] 更新失败 !!!", action.getPriority() + " - " + action.getName());
//                                }
//                            }
//                            report(task, TaskReportStsType.OTBIN);
//                        }
//                    }
//                }
//                List<Long> taskIds = actionService.selectTaskIdsByGroupId(serialNo);
//                for (Long taskId : taskIds) {
//                    Task task = taskService.getById(taskId);
//                    report(task, agv_11_up.getQrCode(), TaskReportStsType.OTBIN);
//                }
                    List<Long> taskIds = actionService.selectTaskIdsByGroupId(serialNo);
                    for (Long taskId : taskIds) {
                        Task task = taskService.getById(taskId);
                        if (task.getOriLoc().equals(loc.getId())) {
                            Action action = actionService.getOne(new LambdaQueryWrapper<Action>()
                                    .eq(Action::getTaskId, task.getId())
                                    .eq(Action::getActionType, ActionTypeType.ReadyTakeFromShelvesLoc.val())
                                    .eq(Action::getActionSts, ActionStsType.ISSUED.val())
                            );
                            if (null != action) {
                                action.setActionSts(ActionStsType.FINISH.val());
                                action.setEndTime(now);
                                action.setUpdateTime(now);
                                if (!actionService.updateById(action)) {
                                    log.error("Action [{}] 更新失败 !!!", action.getPriority() + " - " + action.getName());
                                }
                            }
                        }
                    }
                }
            }
            //从输送线取货完成
//            if (agv_11_up.getCompleteType().equals(AgvCompleteType.TAKE_FROM_STA_COMPLETE)) {
//                WebsocketServiceImpl.taskShelfBarcode = agv_11_up.getLocCode();
//                List<Long> taskIds = actionService.selectTaskIdsByGroupId(serialNo);
//                for (Long taskId : taskIds) {
//                    Task task = taskService.getById(taskId);
//                    report(task, agv_11_up.getQrCode(), TaskReportStsType.OTBIN);
//                }
//            }
            //往输送线放货完成
//            if (agv_11_up.getCompleteType().equals(AgvCompleteType.RELEASE_FROM_STA_COMPLETE)) {
//                WebsocketServiceImpl.taskShelfBarcode = agv_11_up.getLocCode();
//                List<Long> taskIds = actionService.selectTaskIdsByGroupId(serialNo);
//                for (Long taskId : taskIds) {
//                    Task task = taskService.getById(taskId);
//                    report(task, agv_11_up.getQrCode(), TaskReportStsType.END);
//                }
//            }
            // 路径完成 || 充电完成
            if (agv_11_up.getCompleteType().equals(AgvCompleteType.ENTIRE_PATH_COMPLETE)
@@ -1520,6 +2219,7 @@
        }
    }
    @Transactional
    public void settleSegmentList(List<Segment> segmentList, String serialNo) {
        if (Cools.isEmpty(segmentList)) {
@@ -1530,6 +2230,8 @@
        // task
        for (Segment segment : segmentList) {
            boolean taskComplete = false;
            boolean otbin = false;
            Task task = taskService.getById(segment.getTaskId());
            assert null != task;
@@ -1540,6 +2242,7 @@
            switch (Objects.requireNonNull(posType)) {
                case ORI_STA:
                case ORI_LOC:
                    otbin = true;
                    break;
                case DEST_STA:
                case DEST_LOC:
@@ -1560,33 +2263,25 @@
                    break;
            }
            if (otbin) {
                locService.taskCallBackOtbin(task);
                report(task, null, TaskReportStsType.OTBIN);
            }
            if (taskComplete) {
                locService.taskCallBack(task);
                locService.taskCallBackEnd(task);
                task.setTaskSts(TaskStsType.COMPLETE.val());
                task.setEndTime(now);
                task.setUpdateTime(now);
                if (!taskService.updateById(task)) {
                    log.error("Task [{}] 更新失败 !!!", task.getSeqNum());
                } else {
                    log.info("Task [{}] 作业完毕 ==========>> ", task.getSeqNum());
                    // TODO 插入一条上报记录
                    TaskReport taskReport = new TaskReport();
                    taskReport.setAgvId(task.getAgvId());
                    taskReport.setBusNo(task.getBusId$());
                    taskReport.setCreateTime(new Date());
                    taskReport.setDestLoc(task.getDestLoc());
                    taskReport.setDestSta(task.getDestSta());
                    taskReport.setSeqNum(task.getSeqNum());
                    taskReport.setTaskSts(task.getTaskSts());
                    taskReport.setOriLoc(task.getOriLoc());
                    taskReport.setOriSta(task.getOriSta());
                    taskReport.setZpallet(task.getZpallet());
                    if (!taskReportService.save(taskReport)) {
                        log.info("TaskReport [{}] 插入失败 ==========>> ", JSON.toJSONString(taskReport));
                    }
                }
                report(task, null, TaskReportStsType.END);
                if (task.getSeqNum() != null && task.getSeqNum().contains("SSX-CK")) {
                    report(task, "1001", TaskReportStsType.COMPLETED);
                }
            }
        }
@@ -1619,4 +2314,68 @@
        segmentService.processNext(segmentList);
    }
    /**
     * 上报给上游系统,就是插入一条数据到上报表
     */
    private void report(Task task, String qrCode, TaskReportStsType taskReportStsType) {
        // TODO 插入一条上报记录
        if (task.getBusId() == null) {
            return;
        }
        List<TaskReport> list = taskReportService.list(new LambdaQueryWrapper<TaskReport>().eq(TaskReport::getSeqNum, task.getSeqNum()).eq(TaskReport::getBusNo, task.getBusId$()).eq(TaskReport::getTaskSts, taskReportStsType.status));
        if (!Cools.isEmpty(list)) {
            log.info("TaskReport [{},{}] 已重复,不再插入 ==========>> ", taskReportStsType, JSON.toJSONString(task));
            return;
        }
        TaskReport taskReport = new TaskReport();
        taskReport.setAgvId(task.getAgvId());
        taskReport.setAgvNo(task.getAgvId$());
        taskReport.setBusNo(task.getBusId$());
        taskReport.setCreateTime(new Date());
        taskReport.setCompleted(0);
        taskReport.setQrCode(qrCode);
        taskReport.setReportTimes(0);
        taskReport.setTaskSts(taskReportStsType.status);
        taskReport.setEventType(taskReportStsType.name);
        taskReport.setSeqNum(task.getSeqNum());
        taskReport.setZpallet(task.getZpallet());
        if (!taskReportService.save(taskReport)) {
            log.info("TaskReport [{}] 插入失败 ==========>> ", JSON.toJSONString(taskReport));
        } else {
            log.info("Task [{}] 状态记录插入数据库 ==========>> ", task.getSeqNum());
        }
    }
    private boolean askSta(Integer askType, String askSta) {
        log.info("来询问输送线了,{},{}", askType, askSta);
        String wmsUrl = configService.getVal("WCS_URL", String.class);
        String wmsPath = configService.getVal("WMS_STA", String.class);
        if (Cools.isEmpty(wmsPath) || Cools.isEmpty(wmsUrl)) {
            return false;
        }
        Integer time = configService.getVal("TIMEOUT", Integer.class, 5);
        //Integer times = configService.getVal("REPORT_TIMES", Integer.class, 2);
        Map<String, Object> data = new HashMap<>();
        data.put("askType", askType);
        data.put("askSta", askSta);
        String response = null;
        try {
            response = new HttpHandler.Builder()
                    .setUri(wmsUrl)
                    .setPath(wmsPath)
                    .setTimeout(time, TimeUnit.SECONDS)
                    .setJson(JSON.toJSONString(data))
                    .build()
                    .doPost();
            log.info("返回参数:{}", response);
            JSONObject jsonObject = JSON.parseObject(response);
            if (jsonObject.getInteger("code").equals(200)) {
                return true;
            }
        } catch (IOException e) {
            log.info("报错了,{}", e);
        }
        return false;
    }
}