#
vincentlu
2026-03-25 cf723668b6c5636378a276e23366298289a1a1f5
#
3个文件已添加
10个文件已修改
624 ■■■■■ 已修改文件
zy-acs-common/src/main/java/com/zy/acs/common/constant/RedisConstant.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-common/src/main/java/com/zy/acs/common/hk/action/HkAction.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-common/src/main/java/com/zy/acs/common/hk/action/HkActionParameter.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-common/src/main/java/com/zy/acs/common/hk/base/HkMessageHeader.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-common/src/main/java/com/zy/acs/common/hk/order/HkNodePosition.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-common/src/main/java/com/zy/acs/common/hk/order/HkOrderDown.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-common/src/main/java/com/zy/acs/common/hk/order/HkOrderEdge.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-common/src/main/java/com/zy/acs/common/hk/order/HkOrderMessage.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-common/src/main/java/com/zy/acs/common/hk/order/HkOrderNode.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/common/config/HikOrderProperties.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java 109 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/hik/HikOrderPublishService.java 413 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/resources/application.yml 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-common/src/main/java/com/zy/acs/common/constant/RedisConstant.java
@@ -59,4 +59,6 @@
    public static final String HK_AGV_ONLINE_FLAG = "HK_AGV_ONLINE_FLAG";
    public static final String HK_AGV_PATH_DOWN_FLAG = "HK_AGV_PATH_DOWN_FLAG";
}
zy-acs-common/src/main/java/com/zy/acs/common/hk/action/HkAction.java
@@ -4,13 +4,16 @@
import com.zy.acs.common.hk.action.type.HkBlockingType;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
 * 节点动作或即时动作的通用定义。
 */
@Data
public class HkAction {
public class HkAction implements Serializable {
    private static final long serialVersionUID = 9208981967595060577L;
    // 动作名称
    private HkActionType actionType;
zy-acs-common/src/main/java/com/zy/acs/common/hk/action/HkActionParameter.java
@@ -2,11 +2,15 @@
import lombok.Data;
import java.io.Serializable;
/**
 * 动作参数键值对。
 */
@Data
public class HkActionParameter {
public class HkActionParameter implements Serializable {
    private static final long serialVersionUID = -6011550732051385556L;
    // 参数键
    private String key;
zy-acs-common/src/main/java/com/zy/acs/common/hk/base/HkMessageHeader.java
@@ -2,11 +2,15 @@
import lombok.Data;
import java.io.Serializable;
/**
 * 海康 VDA 协议通用消息头。
 */
@Data
public class HkMessageHeader {
public class HkMessageHeader implements Serializable {
    private static final long serialVersionUID = 2608659928820261100L;
    // 消息头 ID
    private Long headerId;
zy-acs-common/src/main/java/com/zy/acs/common/hk/order/HkNodePosition.java
@@ -2,11 +2,15 @@
import lombok.Data;
import java.io.Serializable;
/**
 * 任务节点地图坐标信息。
 */
@Data
public class HkNodePosition {
public class HkNodePosition implements Serializable {
    private static final long serialVersionUID = 2188583893729134558L;
    // 节点在地图坐标系上的 x 坐标,单位 m
    private Double x;
zy-acs-common/src/main/java/com/zy/acs/common/hk/order/HkOrderDown.java
New file
@@ -0,0 +1,20 @@
package com.zy.acs.common.hk.order;
import lombok.Data;
import java.io.Serializable;
/**
 * 海康任务下发队列消息。
 */
@Data
public class HkOrderDown implements Serializable {
    private static final long serialVersionUID = 3445498438437676925L;
    private String agvNo;
    private String actionGroupId;
    private HkOrderMessage orderMessage;
}
zy-acs-common/src/main/java/com/zy/acs/common/hk/order/HkOrderEdge.java
@@ -3,13 +3,16 @@
import com.zy.acs.common.hk.action.HkAction;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
 * order 消息中的路径段定义。
 */
@Data
public class HkOrderEdge {
public class HkOrderEdge implements Serializable {
    private static final long serialVersionUID = -2771742971185587954L;
    // 路径段唯一标识
    private String edgeId;
zy-acs-common/src/main/java/com/zy/acs/common/hk/order/HkOrderMessage.java
@@ -13,6 +13,8 @@
@Data
public class HkOrderMessage extends HkMessageHeader {
    private static final long serialVersionUID = 1000719280604107938L;
    // 任务 ID
    private String orderId;
zy-acs-common/src/main/java/com/zy/acs/common/hk/order/HkOrderNode.java
@@ -3,13 +3,16 @@
import com.zy.acs.common.hk.action.HkAction;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
 * order 消息中的节点定义。
 */
@Data
public class HkOrderNode {
public class HkOrderNode implements Serializable {
    private static final long serialVersionUID = -6654224020581088208L;
    // 节点唯一标识
    private String nodeId;
zy-acs-manager/src/main/java/com/zy/acs/manager/common/config/HikOrderProperties.java
New file
@@ -0,0 +1,31 @@
package com.zy.acs.manager.common.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties(prefix = "hik")
public class HikOrderProperties {
    private String interfaceName = "VDA";
    private String majorVersion = "V2.0.0";
    private String manufacturer = "HikRobot";
    private String zoneSetId = "default";
    private String mapId = "default";
    private String mapDescription = "RCS Map";
    private double coordinateScale = 1D;
    private double metricScale = 0.001D;
    private double defaultAllowedDeviationXY = 0.05D;
    private double defaultAllowedDeviationTheta = 0.08726646259971647D;
}
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java
@@ -21,6 +21,7 @@
import com.zy.acs.manager.core.domain.TaskPosDto;
import com.zy.acs.manager.core.integrate.conveyor.ConveyorStationService;
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.*;
@@ -98,6 +99,8 @@
    private StaReserveService staReserveService;
    @Autowired
    private ConveyorStationService conveyorStationService;
    @Autowired
    private HikOrderPublishService hikOrderPublishService;
    @SuppressWarnings("all")
    @Transactional
@@ -1582,47 +1585,25 @@
    @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())
                    .orderByDesc(Action::getPriority));
            List<Action> actionList = listPrepareActions(actionGroupId);
            if (Cools.isEmpty(actionList)) {
                return;
            }
            Long agvId = actionList.get(0).getAgvId();
            AgvModel agvModel = agvModelService.getByAgvId(agvId);
            if (hikOrderPublishService.support(agvModel)) {
                publishActionForHik(actionGroupId);
                return;
            }
            Date now = new Date();
            String agvNo = agvService.getAgvNo(agvId);
            if (!agvService.judgeOnline(agvId)) {
                return;
            }
            long actionIssuedSts = ActionStsType.ISSUED.val();
            for (Action action : actionList) {
                action.setActionSts(actionIssuedSts);
                action.setStartTime(now);
                action.setIoTime(now);
                action.setUpdateTime(now);
            }
            if (!actionService.updateBatchById(actionList)) {
                throw new BusinessException("failed to update action batch !!!");
            }
            // task
            List<Long> taskIds = actionService.selectTaskIdsByGroupId(actionGroupId);
            long taskAssignSts = TaskStsType.ASSIGN.val();
            long taskProgressSts = TaskStsType.PROGRESS.val();
            for (Long taskId : taskIds) {
                Task task = taskService.getById(taskId);
                if (task.getTaskSts().equals(taskAssignSts)) {
                    task.setTaskSts(taskProgressSts);
                    task.setUpdateTime(now);
                    if (!taskService.updateById(task)) {
                        throw new BusinessException(task.getSeqNum() + "任务更新失败");
                    }
                }
            }
            markActionAndTaskIssued(actionGroupId, actionList, now);
            AgvAction agvAction = new AgvAction(agvNo, actionGroupId);
            for (Action action : actionList) {
@@ -1750,6 +1731,70 @@
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }
    @Transactional
    public void publishActionForHik(String actionGroupId) {
        try {
            List<Action> actionList = listPrepareActions(actionGroupId);
            if (Cools.isEmpty(actionList)) {
                return;
            }
            Long agvId = actionList.get(0).getAgvId();
            String agvNo = agvService.getAgvNo(agvId);
            if (!agvService.judgeOnline(agvId)) {
                return;
            }
            AgvModel agvModel = agvModelService.getByAgvId(agvId);
            if (!hikOrderPublishService.support(agvModel)) {
                throw new CoolException("agv [" + agvNo + "] protocol is not hik");
            }
            Date now = new Date();
            markActionAndTaskIssued(actionGroupId, actionList, now);
            hikOrderPublishService.publish(actionGroupId, agvNo, agvModel, actionList);
            News.info("海康任务组 [{}] order 已下发 ===>> 指令数量:{}", actionGroupId, actionList.size());
        } catch (Exception e) {
            News.error("mainService.publishActionForHik", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }
    private List<Action> listPrepareActions(String actionGroupId) {
        return actionService.list(new LambdaQueryWrapper<Action>()
                .eq(Action::getGroupId, actionGroupId)
                .eq(Action::getActionSts, ActionStsType.PREPARE.val())
                .orderByDesc(Action::getPriority));
    }
    private void markActionAndTaskIssued(String actionGroupId, List<Action> actionList, Date now) {
        long actionIssuedSts = ActionStsType.ISSUED.val();
        for (Action action : actionList) {
            action.setActionSts(actionIssuedSts);
            action.setStartTime(now);
            action.setIoTime(now);
            action.setUpdateTime(now);
        }
        if (!actionService.updateBatchById(actionList)) {
            throw new BusinessException("failed to update action batch !!!");
        }
        List<Long> taskIds = actionService.selectTaskIdsByGroupId(actionGroupId);
        long taskAssignSts = TaskStsType.ASSIGN.val();
        long taskProgressSts = TaskStsType.PROGRESS.val();
        for (Long taskId : taskIds) {
            Task task = taskService.getById(taskId);
            if (task != null && task.getTaskSts().equals(taskAssignSts)) {
                task.setTaskSts(taskProgressSts);
                task.setUpdateTime(now);
                if (!taskService.updateById(task)) {
                    throw new BusinessException(task.getSeqNum() + "任务更新失败");
                }
            }
        }
    }
    @Transactional
@@ -2027,4 +2072,4 @@
        segmentService.processNext(segmentList);
    }
}
}
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/hik/HikOrderPublishService.java
New file
@@ -0,0 +1,413 @@
package com.zy.acs.manager.core.service.hik;
import com.alibaba.fastjson.JSON;
import com.zy.acs.common.constant.RedisConstant;
import com.zy.acs.common.hk.action.HkAction;
import com.zy.acs.common.hk.action.HkActionParameter;
import com.zy.acs.common.hk.action.type.HkActionType;
import com.zy.acs.common.hk.action.type.HkBlockingType;
import com.zy.acs.common.hk.order.HkNodePosition;
import com.zy.acs.common.hk.order.HkOrderDown;
import com.zy.acs.common.hk.order.HkOrderEdge;
import com.zy.acs.common.hk.order.HkOrderMessage;
import com.zy.acs.common.hk.order.HkOrderNode;
import com.zy.acs.common.utils.RedisSupport;
import com.zy.acs.framework.common.SnowflakeIdWorker;
import com.zy.acs.framework.exception.CoolException;
import com.zy.acs.manager.common.config.HikOrderProperties;
import com.zy.acs.manager.manager.entity.Action;
import com.zy.acs.manager.manager.entity.AgvModel;
import com.zy.acs.manager.manager.entity.Code;
import com.zy.acs.manager.manager.enums.ActionTypeType;
import com.zy.acs.manager.manager.service.CodeService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
@Slf4j
@Service
public class HikOrderPublishService {
    @Autowired
    private HikOrderProperties hikOrderProperties;
    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
    @Autowired
    private CodeService codeService;
    private final RedisSupport redis = RedisSupport.defaultRedisSupport;
    public boolean support(AgvModel agvModel) {
        if (agvModel == null || !StringUtils.hasText(agvModel.getProtocol())) {
            return false;
        }
        return agvModel.getProtocol().toLowerCase(Locale.ROOT).contains("hik");
    }
    public void publish(String actionGroupId, String agvNo, AgvModel agvModel, List<Action> actionList) {
        HkOrderMessage orderMessage = buildOrderMessage(actionGroupId, agvNo, agvModel, actionList);
        HkOrderDown orderDown = new HkOrderDown();
        orderDown.setAgvNo(agvNo);
        orderDown.setActionGroupId(actionGroupId);
        orderDown.setOrderMessage(orderMessage);
        redis.push(RedisConstant.HK_AGV_PATH_DOWN_FLAG, orderDown);
        log.info("push hik order to redis, agvNo={}, actionGroupId={}, nodeCount={}, edgeCount={}, redisKey={}",
                agvNo,
                actionGroupId,
                orderMessage.getNodes().size(),
                orderMessage.getEdges().size(),
                RedisConstant.HK_AGV_PATH_DOWN_FLAG);
    }
    private HkOrderMessage buildOrderMessage(String actionGroupId, String agvNo, AgvModel agvModel, List<Action> actionList) {
        if (!StringUtils.hasText(actionGroupId)) {
            throw new CoolException("actionGroupId can not be blank");
        }
        if (!StringUtils.hasText(agvNo)) {
            throw new CoolException("agvNo can not be blank");
        }
        if (actionList == null || actionList.isEmpty()) {
            throw new CoolException("actionList can not be empty");
        }
        Action firstAction = findFirstActionWithCode(actionList);
        if (firstAction == null) {
            throw new CoolException("hik order adaptation failed: no start code found");
        }
        HkOrderMessage orderMessage = new HkOrderMessage();
        orderMessage.setHeaderId(snowflakeIdWorker.nextId());
        orderMessage.setTimestamp(Instant.now().toString());
        orderMessage.setVersion(hikOrderProperties.getMajorVersion());
        orderMessage.setManufacturer(hikOrderProperties.getManufacturer());
        orderMessage.setSerialNumber(agvNo);
        orderMessage.setOrderId(actionGroupId);
        orderMessage.setOrderUpdateId(0L);
        orderMessage.setZoneSetId(hikOrderProperties.getZoneSetId());
        List<HkOrderNode> nodes = new ArrayList<>();
        List<HkOrderEdge> edges = new ArrayList<>();
        long sequenceId = 0L;
        int nodeIndex = 0;
        int edgeIndex = 0;
        NodeCursor currentNode = createNode(actionGroupId, firstAction.getCode(), nodeIndex++, sequenceId++);
        nodes.add(currentNode.node);
        Double currentTheta = currentNode.node.getNodePosition().getTheta();
        for (int i = 0; i < actionList.size(); i++) {
            Action action = actionList.get(i);
            ActionTypeType actionType = resolveActionType(action);
            String actionCode = action.getCode();
            if (StringUtils.hasText(actionCode) && !Objects.equals(actionCode, currentNode.code)) {
                throw new CoolException("hik order adaptation failed: action code jump without move, groupId="
                        + actionGroupId + ", currentCode=" + currentNode.code + ", actionCode=" + actionCode);
            }
            switch (actionType) {
                case TurnCorner:
                    currentTheta = parseThetaRadians(action.getParams());
                    currentNode.node.getNodePosition().setTheta(currentTheta);
                    break;
                case StraightAheadTurnable:
                case StraightAheadUnturnable:
                case StraightBackTurnable:
                case StraightBackUnturnable:
                    String endCode = findNextMoveEndCode(actionList, i, currentNode.code);
                    Double edgeTheta = currentTheta != null ? currentTheta : calculateTheta(currentNode.code, endCode);
                    HkOrderEdge edge = createEdge(actionGroupId, edgeIndex++, sequenceId++, currentNode, endCode, edgeTheta, action, agvModel);
                    edges.add(edge);
                    NodeCursor nextNode = createNode(actionGroupId, endCode, nodeIndex++, sequenceId++);
                    nextNode.node.getNodePosition().setTheta(edgeTheta);
                    nodes.add(nextNode.node);
                    currentNode = nextNode;
                    currentTheta = edgeTheta;
                    break;
                case FinishPath:
                    break;
                default:
                    currentNode.node.getActions().add(buildNodeAction(action, actionType, currentTheta));
                    break;
            }
        }
        orderMessage.setNodes(nodes);
        orderMessage.setEdges(edges);
        return orderMessage;
    }
    private Action findFirstActionWithCode(List<Action> actionList) {
        for (Action action : actionList) {
            if (StringUtils.hasText(action.getCode())) {
                return action;
            }
        }
        return null;
    }
    private ActionTypeType resolveActionType(Action action) {
        ActionTypeType actionType = ActionTypeType.get(action.getActionTypeEl());
        if (actionType == null) {
            throw new CoolException("unsupported action type, actionId=" + action.getId());
        }
        return actionType;
    }
    private NodeCursor createNode(String actionGroupId, String code, int nodeIndex, long sequenceId) {
        Code codeEntity = codeService.getCacheByData(code);
        if (codeEntity == null) {
            throw new CoolException("hik order adaptation failed: code not found, code=" + code);
        }
        HkOrderNode node = new HkOrderNode();
        node.setNodeId(buildId(actionGroupId, "N", nodeIndex, code));
        node.setSequenceId(sequenceId);
        node.setNodeDescription(code);
        node.setReleased(Boolean.TRUE);
        node.setAllowedDeviationXY(hikOrderProperties.getDefaultAllowedDeviationXY());
        node.setAllowedDeviationTheta(hikOrderProperties.getDefaultAllowedDeviationTheta());
        node.setMapId(hikOrderProperties.getMapId());
        node.setMapDescription(hikOrderProperties.getMapDescription());
        node.setActions(new ArrayList<>());
        node.setNodePosition(buildNodePosition(codeEntity));
        return new NodeCursor(code, node);
    }
    private HkNodePosition buildNodePosition(Code codeEntity) {
        HkNodePosition nodePosition = new HkNodePosition();
        nodePosition.setX(scaleCoordinate(codeEntity.getX()));
        nodePosition.setY(scaleCoordinate(codeEntity.getY()));
        nodePosition.setTheta(null);
        return nodePosition;
    }
    private HkOrderEdge createEdge(String actionGroupId,
                                   int edgeIndex,
                                   long sequenceId,
                                   NodeCursor startNode,
                                   String endCode,
                                   Double edgeTheta,
                                   Action action,
                                   AgvModel agvModel) {
        HkOrderEdge edge = new HkOrderEdge();
        edge.setEdgeId(buildId(actionGroupId, "E", edgeIndex, startNode.code + "_" + endCode));
        edge.setSequenceId(sequenceId);
        edge.setEdgeDescription(startNode.code + "->" + endCode);
        edge.setReleased(Boolean.TRUE);
        edge.setStartNodeId(startNode.node.getNodeId());
        edge.setEndNodeId(buildId(actionGroupId, "N", edgeIndex + 1, endCode));
        edge.setMaxSpeed(resolveMaxSpeed(action, agvModel));
        edge.setOrientation(edgeTheta);
        edge.setOrientationType("GLOBAL");
        edge.setRotationAllowed(Boolean.FALSE);
        edge.setActions(new ArrayList<>());
        return edge;
    }
    private String findNextMoveEndCode(List<Action> actionList, int currentIndex, String currentCode) {
        for (int i = currentIndex + 1; i < actionList.size(); i++) {
            String code = actionList.get(i).getCode();
            if (!StringUtils.hasText(code)) {
                continue;
            }
            if (!Objects.equals(code, currentCode)) {
                return code;
            }
        }
        throw new CoolException("hik order adaptation failed: move action missing end code, startCode=" + currentCode);
    }
    private HkAction buildNodeAction(Action action, ActionTypeType actionType, Double currentTheta) {
        HkAction hkAction = new HkAction();
        hkAction.setActionId("A" + action.getId());
        hkAction.setActionDescription(actionType.desc);
        hkAction.setBlockingType(HkBlockingType.HARD);
        hkAction.setActionType(resolveHkActionType(actionType));
        List<HkActionParameter> parameters = new ArrayList<>();
        addParameter(parameters, "sourceActionType", actionType.name());
        addParameter(parameters, "sourceActionId", action.getId());
        switch (actionType) {
            case ReadyTakeFromShelvesLoc:
            case ReadyTakeFromConveyorSta:
            case ReadyReleaseToShelvesLoc:
            case ReadyReleaseToConveyorSta:
                addParameter(parameters, "loadType", resolveLoadType(actionType));
                addParameter(parameters, "actuatorDirection", resolveDirection(action.getVal()));
                HeightDepthParam heightDepthParam = parseHeightDepth(action.getParams());
                addMetricParameter(parameters, "height", heightDepthParam.height);
                addMetricParameter(parameters, "depth", heightDepthParam.depth);
                break;
            case ReadyTakeFromAgvSite:
            case ReadyReleaseToAgvSite:
                addParameter(parameters, "loadType", "AGV_SITE");
                addParameter(parameters, "level", toInteger(action.getVal()));
                addMetricParameter(parameters, "height", parseDouble(action.getParams()));
                break;
            case DockingCharge:
            case UndockingCharge:
                break;
            case LoadPlatformLift:
                addMetricParameter(parameters, "height", parseDouble(action.getParams()));
                if (currentTheta != null) {
                    addParameter(parameters, "angle", currentTheta);
                }
                break;
            default:
                throw new CoolException("hik order adaptation failed: unsupported node action type=" + actionType);
        }
        hkAction.setActionParameters(parameters);
        return hkAction;
    }
    private HkActionType resolveHkActionType(ActionTypeType actionType) {
        switch (actionType) {
            case ReadyTakeFromShelvesLoc:
            case ReadyTakeFromConveyorSta:
            case ReadyTakeFromAgvSite:
                return HkActionType.PICK;
            case ReadyReleaseToShelvesLoc:
            case ReadyReleaseToConveyorSta:
            case ReadyReleaseToAgvSite:
                return HkActionType.DROP;
            case DockingCharge:
                return HkActionType.START_CHARGING;
            case UndockingCharge:
                return HkActionType.STOP_CHARGING;
            case LoadPlatformLift:
                return HkActionType.ROTATE_LOAD_LIFT;
            default:
                throw new CoolException("hik action mapping not found: " + actionType);
        }
    }
    private String resolveLoadType(ActionTypeType actionType) {
        switch (actionType) {
            case ReadyTakeFromShelvesLoc:
            case ReadyReleaseToShelvesLoc:
                return "SHELF";
            case ReadyTakeFromConveyorSta:
            case ReadyReleaseToConveyorSta:
                return "CONVEYOR";
            default:
                return "UNKNOWN";
        }
    }
    private String resolveDirection(Double val) {
        if (val == null) {
            return null;
        }
        int direct = val.intValue();
        if (direct == 1) {
            return "LEFT";
        }
        if (direct == 2) {
            return "RIGHT";
        }
        if (direct == 3) {
            return "FORWARD";
        }
        return String.valueOf(direct);
    }
    private HeightDepthParam parseHeightDepth(String params) {
        com.zy.acs.common.domain.HeightDepthDto heightDepthDto = JSON.parseObject(params, com.zy.acs.common.domain.HeightDepthDto.class);
        if (heightDepthDto == null) {
            throw new CoolException("hik order adaptation failed: invalid height/depth params");
        }
        return new HeightDepthParam(heightDepthDto.getHeight(), heightDepthDto.getDepth());
    }
    private Double parseThetaRadians(String params) {
        return Math.toRadians(parseDouble(params));
    }
    private Double calculateTheta(String startCode, String endCode) {
        Code start = codeService.getCacheByData(startCode);
        Code end = codeService.getCacheByData(endCode);
        if (start == null || end == null) {
            throw new CoolException("hik order adaptation failed: code position missing");
        }
        return Math.atan2(end.getY() - start.getY(), end.getX() - start.getX());
    }
    private Double resolveMaxSpeed(Action action, AgvModel agvModel) {
        if (agvModel != null && agvModel.getTravelSpeed() != null) {
            return agvModel.getTravelSpeed() * hikOrderProperties.getMetricScale();
        }
        if (action.getVal() != null) {
            return action.getVal();
        }
        return null;
    }
    private Double scaleCoordinate(Double value) {
        if (value == null) {
            return null;
        }
        return value * hikOrderProperties.getCoordinateScale();
    }
    private void addMetricParameter(List<HkActionParameter> parameters, String key, Number value) {
        if (value == null) {
            return;
        }
        addParameter(parameters, key, value.doubleValue() * hikOrderProperties.getMetricScale());
    }
    private void addParameter(List<HkActionParameter> parameters, String key, Object value) {
        if (value == null) {
            return;
        }
        HkActionParameter parameter = new HkActionParameter();
        parameter.setKey(key);
        parameter.setValue(value);
        parameters.add(parameter);
    }
    private Double parseDouble(String value) {
        if (!StringUtils.hasText(value)) {
            return null;
        }
        return Double.parseDouble(value);
    }
    private Integer toInteger(Double value) {
        return value == null ? null : value.intValue();
    }
    private String buildId(String actionGroupId, String prefix, int index, String suffix) {
        return actionGroupId + "-" + prefix + String.format("%03d", index) + "-" + sanitize(suffix);
    }
    private String sanitize(String value) {
        return value == null ? "NA" : value.replaceAll("[^0-9A-Za-z_-]", "_");
    }
    @AllArgsConstructor
    private static class NodeCursor {
        private final String code;
        private final HkOrderNode node;
    }
    @AllArgsConstructor
    private static class HeightDepthParam {
        private final Number height;
        private final Number depth;
    }
}
zy-acs-manager/src/main/resources/application.yml
@@ -99,4 +99,16 @@
  swagger-base-package: com.zy.acs
  swagger-title: RCS API文档
  swagger-version: 1.0
  token-key: KUHSMcYQ4lePt3r6bckz0P13cBJyoonYqInThvQlUnbsFCIcCcZZAbWZ6UNFztYNYPhGdy6eyb8WdIz8FU2Cz396TyTJk3NI2rtXMHBOehRb4WWJ4MdYVVg2oWPyqRQ2
  token-key: KUHSMcYQ4lePt3r6bckz0P13cBJyoonYqInThvQlUnbsFCIcCcZZAbWZ6UNFztYNYPhGdy6eyb8WdIz8FU2Cz396TyTJk3NI2rtXMHBOehRb4WWJ4MdYVVg2oWPyqRQ2
hik:
  interface-name: VDA
  major-version: V2.0.0
  manufacturer: HikRobot
  zone-set-id: default
  map-id: default
  map-description: RCS Map
  coordinate-scale: 1.0
  metric-scale: 0.001
  default-allowed-deviation-xy: 0.05
  default-allowed-deviation-theta: 0.08726646259971647