puzhibing
2026-04-11 b6f3de8451867d85242b2bd706fcfa4a65df4ff7
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/util/XPUUtil.java
@@ -2,14 +2,13 @@
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.xiaopeng.api.dto.automaticPilot.MqttPublishDto;
import com.xiaopeng.api.feignClient.automaticPilot.VmpOpenServiceClient;
import com.xiaopeng.api.feignClient.automaticPilot.XPUClient;
import com.xiaopeng.api.vo.automaticPilot.MqttPublishVo;
import com.xiaopeng.api.vo.automaticPilot.proto.up.RTCmdType;
import com.xiaopeng.api.vo.automaticPilot.protobuf.RtTaskList;
import com.xiaopeng.api.vo.automaticPilot.protobuf.*;
import com.xiaopeng.common.core.exception.ServiceException;
import com.xiaopeng.common.core.utils.StringUtils;
import com.xiaopeng.common.core.utils.uuid.UUID;
import lombok.extern.slf4j.Slf4j;
@@ -42,25 +41,25 @@
    // 查询车管 车辆xpuid信息返回字段,用于按需返回字段
    public static final List<String> TYPE_LIST = Collections.singletonList("1");
    private static final com.google.protobuf.util.JsonFormat.Printer jsonPrinter = com.google.protobuf.util.JsonFormat.printer().printingEnumsAsInts();
    private static final com.google.protobuf.util.JsonFormat.Printer jsonPrinter = com.google.protobuf.util.JsonFormat.printer()
            .printingEnumsAsInts()
            .preservingProtoFieldNames();
    /**
     * Robotaxi创建订单推送给XPU
     *
     * @param task
     * @param taskList
     * @return
     */
    //TODO 处理feign调用的异常
    public MqttPublishDto cloudCreateOrder(RtTaskList taskList, String vin, Long sequence) {
        com.xiaopeng.api.vo.automaticPilot.protobuf.MsgContent.Builder msgContentBuilder = com.xiaopeng.api.vo.automaticPilot.protobuf.MsgContent.newBuilder();
        // 消息头
        com.xiaopeng.api.vo.automaticPilot.protobuf.MsgHeader.Builder headerBuilder = com.xiaopeng.api.vo.automaticPilot.protobuf.MsgHeader.newBuilder();
        MsgContent.Builder msgContentBuilder = MsgContent.newBuilder();
        MsgHeader.Builder headerBuilder = MsgHeader.newBuilder();
        headerBuilder.setMsgId(UUID.randomUUID().toString());
        headerBuilder.setTimestamp(System.currentTimeMillis());
        headerBuilder.setCmd(RTCmdType.CLOUD_CREATE_ORDER.getValue());
        headerBuilder.setCmd(RTCmdType.CLOUD_SEND_RT_TASK.getValue());
        headerBuilder.setSequence(sequence);
        headerBuilder.setType(com.xiaopeng.api.vo.automaticPilot.protobuf.MessageType.MESSAGE_TYPE_REQUEST);
        headerBuilder.setSource(com.xiaopeng.api.vo.automaticPilot.protobuf.SourceType.CLOUD);
        headerBuilder.setType(MessageType.MESSAGE_TYPE_REQUEST);
        headerBuilder.setSource(SourceType.CLOUD);
        msgContentBuilder.setHeader(headerBuilder.build());
        msgContentBuilder.setRtTaskList(taskList);
@@ -73,9 +72,17 @@
            log.error("Protobuf转JSON失败", e);
            throw new RuntimeException("Protobuf转JSON失败", e);
        }
        log.info("云端-->XPU 创建订单:{}", vo);
        return xpuClient.publish(vo);
        log.info("云端-->XPU 创建订单:{}", JSON.toJSONString(vo));
        try {
            MqttPublishDto dto = xpuClient.publish(vo);
            log.info("XPU返回:{}", JSON.toJSONString(dto));
            if(200 != dto.getCode()){
                dto = againPushMessage(vo);
            }
            return dto;
        }catch (Exception e){
            throw new RuntimeException("云端-->XPU 创建订单失败:", e);
        }
    }
@@ -84,19 +91,17 @@
     * @param operation
     * @return
     */
    //TODO 处理feign调用的异常
    public MqttPublishDto cloudOrderOperation(com.xiaopeng.api.vo.automaticPilot.protobuf.OrderOperation operation, String vin, Long sequence) {
        com.xiaopeng.api.vo.automaticPilot.protobuf.MsgContent.Builder msgContentBuilder = com.xiaopeng.api.vo.automaticPilot.protobuf.MsgContent.newBuilder();
        // 消息头
        com.xiaopeng.api.vo.automaticPilot.protobuf.MsgHeader.Builder headerBuilder = com.xiaopeng.api.vo.automaticPilot.protobuf.MsgHeader.newBuilder();
    public MqttPublishDto cloudOrderOperation(OrderOperation operation, String vin, Long sequence) {
        MsgContent.Builder msgContentBuilder = MsgContent.newBuilder();
        MsgHeader.Builder headerBuilder = MsgHeader.newBuilder();
        headerBuilder.setMsgId(UUID.randomUUID().toString());
        headerBuilder.setTimestamp(System.currentTimeMillis());
        headerBuilder.setCmd(RTCmdType.CLOUD_ORDER_OPERATION.getValue());
        headerBuilder.setSequence(sequence);
        headerBuilder.setType(com.xiaopeng.api.vo.automaticPilot.protobuf.MessageType.MESSAGE_TYPE_REQUEST);
        headerBuilder.setSource(com.xiaopeng.api.vo.automaticPilot.protobuf.SourceType.CLOUD);
        headerBuilder.setType(MessageType.MESSAGE_TYPE_REQUEST);
        headerBuilder.setSource(SourceType.CLOUD);
        msgContentBuilder.setHeader(headerBuilder.build());
        msgContentBuilder.setOrderOperation(operation);
        MqttPublishVo vo = new MqttPublishVo();
@@ -107,11 +112,59 @@
            log.error("Protobuf转JSON失败", e);
            throw new RuntimeException("Protobuf转JSON失败", e);
        }
        log.info("云端-->XPU 修改订单:{}", vo);
        return xpuClient.publish(vo);
        try {
            MqttPublishDto dto = xpuClient.publish(vo);
            log.info("XPU返回:{}", JSON.toJSONString(dto));
            if(200 != dto.getCode()){
                dto = againPushMessage(vo);
            }
            return dto;
        }catch (Exception e){
            throw new RuntimeException("云端-->XPU 修改订单失败:", e);
        }
    }
    /**
     * 下发导航地址到车端
     *
     * @param navigationData
     * @return
     */
    public MqttPublishDto cloudPushNavigation(RestoreNavigationData navigationData, String xpuId, Long sequence) {
        MsgContent.Builder msgContentBuilder = MsgContent.newBuilder();
        MsgHeader.Builder headerBuilder = MsgHeader.newBuilder();
        headerBuilder.setMsgId(UUID.randomUUID().toString());
        headerBuilder.setTimestamp(System.currentTimeMillis());
        headerBuilder.setCmd(RTCmdType.CLOUD_NAVIGATION_RESPONSE.getValue());
        headerBuilder.setSequence(sequence);
        headerBuilder.setType(MessageType.MESSAGE_TYPE_RESPONSE);
        headerBuilder.setSource(SourceType.CLOUD);
        msgContentBuilder.setHeader(headerBuilder.build());
        msgContentBuilder.setRestoreNavigationData(navigationData);
        MqttPublishVo vo = new MqttPublishVo();
        vo.setTopic(buildTopicByXpuId(xpuId));
        try {
            vo.setPayload(jsonPrinter.print(msgContentBuilder.build()));
        } catch (Exception e) {
            log.error("Protobuf转JSON失败", e);
            throw new RuntimeException("Protobuf转JSON失败", e);
        }
        log.info("云端-->XPU 下发导航信息:{}", vo);
        try {
            MqttPublishDto dto = xpuClient.publish(vo);
            log.info("XPU返回:{}", JSON.toJSONString(dto));
            if(200 != dto.getCode()){
                dto = againPushMessage(vo);
            }
            return dto;
        }catch (Exception e){
            throw new RuntimeException("云端-->XPU 下发导航信息失败:", e);
        }
    }
@@ -121,21 +174,18 @@
     * @param responseMessage
     * @return
     */
    public MqttPublishDto responseMessage(com.xiaopeng.api.vo.automaticPilot.protobuf.ResponseMessage responseMessage, String vin) {
        com.xiaopeng.api.vo.automaticPilot.protobuf.MsgContent.Builder msgContentBuilder = com.xiaopeng.api.vo.automaticPilot.protobuf.MsgContent.newBuilder();
        // 消息头
        com.xiaopeng.api.vo.automaticPilot.protobuf.MsgHeader.Builder headerBuilder = com.xiaopeng.api.vo.automaticPilot.protobuf.MsgHeader.newBuilder();
    public MqttPublishDto responseMessage(ResponseMessage responseMessage, String vin) {
        MsgContent.Builder msgContentBuilder = MsgContent.newBuilder();
        MsgHeader.Builder headerBuilder = MsgHeader.newBuilder();
        headerBuilder.setMsgId(UUID.randomUUID().toString());
        headerBuilder.setTimestamp(System.currentTimeMillis());
        headerBuilder.setCmd(RTCmdType.CLOUD_TASK_CONTROL.getValue());
        Snowflake snowflake = IdUtil.getSnowflake(0, 0);
        headerBuilder.setSequence(snowflake.nextId());
        headerBuilder.setType(com.xiaopeng.api.vo.automaticPilot.protobuf.MessageType.MESSAGE_TYPE_RESPONSE);
        headerBuilder.setSource(com.xiaopeng.api.vo.automaticPilot.protobuf.SourceType.CLOUD);
        headerBuilder.setType(MessageType.MESSAGE_TYPE_RESPONSE);
        headerBuilder.setSource(SourceType.CLOUD);
        msgContentBuilder.setHeader(headerBuilder.build());
        msgContentBuilder.setResponse(responseMessage);
        MqttPublishVo vo = new MqttPublishVo();
        vo.setTopic(buildTopicByVin(vin));
        try {
@@ -144,44 +194,11 @@
            log.error("Protobuf转JSON失败", e);
            throw new RuntimeException("Protobuf转JSON失败", e);
        }
        log.info("云端-->XPU 响应消息:{}", vo);
        return xpuClient.publish(vo);
    }
    /**
     * 下发导航地址到车端
     *
     * @param navigationData
     * @return
     */
    //TODO 处理feign调用的异常
    public MqttPublishDto cloudPushNavigation(com.xiaopeng.api.vo.automaticPilot.protobuf.RestoreNavigationData navigationData, String xpuId, Long sequence) {
        com.xiaopeng.api.vo.automaticPilot.protobuf.MsgContent.Builder msgContentBuilder = com.xiaopeng.api.vo.automaticPilot.protobuf.MsgContent.newBuilder();
        // 消息头
        com.xiaopeng.api.vo.automaticPilot.protobuf.MsgHeader.Builder headerBuilder = com.xiaopeng.api.vo.automaticPilot.protobuf.MsgHeader.newBuilder();
        headerBuilder.setMsgId(UUID.randomUUID().toString());
        headerBuilder.setTimestamp(System.currentTimeMillis());
        headerBuilder.setCmd(RTCmdType.CLOUD_NAVIGATION_RESPONSE.getValue());
        headerBuilder.setSequence(sequence);
        headerBuilder.setType(com.xiaopeng.api.vo.automaticPilot.protobuf.MessageType.MESSAGE_TYPE_RESPONSE);
        headerBuilder.setSource(com.xiaopeng.api.vo.automaticPilot.protobuf.SourceType.CLOUD);
        msgContentBuilder.setHeader(headerBuilder.build());
        msgContentBuilder.setRestoreNavigationData(navigationData);
        MqttPublishVo vo = new MqttPublishVo();
        vo.setTopic(buildTopicByXpuId(xpuId));
        try {
            vo.setPayload(jsonPrinter.print(msgContentBuilder.build()));
        } catch (Exception e) {
            log.error("Protobuf转JSON失败", e);
            throw new RuntimeException("Protobuf转JSON失败", e);
        }
        log.info("云端-->XPU 下发导航信息:{}", vo);
        return xpuClient.publish(vo);
    }
    /**
@@ -194,7 +211,7 @@
        log.info("getMqttPublishTopic vin,{},xpuIdMapping,{}", vin,  JSON.toJSONString(xpuIdMapping));
        if (xpuIdMapping == null || StringUtils.isEmpty(xpuIdMapping.get(XPU_ID_TYPE)) ) {
            log.error("根据vin查询车辆xpuid信息为空,vin={}", vin);
            throw new RuntimeException("根据vin查询车辆xpuid信息为空");
            throw new ServiceException("根据vin查询车辆xpuid信息为空");
        }
        return xpuIdMapping.get(XPU_ID_TYPE);
    }
@@ -209,13 +226,35 @@
        if (!prefix.endsWith("/")) {
            prefix = prefix + "/";
        }
        String value = xpuId;
        if (xpuId.length() > 10) {
            int start = 10;
            int end = Math.min(24, xpuId.length());
            value = xpuId.substring(start, end);
        }
        return prefix + value + "00000000";
//        String value = xpuId;
//        if (xpuId.length() > 10) {
//            int start = 10;
//            int end = Math.min(24, xpuId.length());
//            value = xpuId.substring(start, end);
//        }
        return prefix + xpuId;
    }
    /**
     * 消息下发XPU重试机制
     * @param message
     * @return
     */
    public MqttPublishDto againPushMessage(MqttPublishVo message) {
        log.info("云端-->XPU 消息重试:{}", message);
        MqttPublishDto dto = null;
        for (int i = 0; i < 3; i++) {
            try {
                dto = xpuClient.publish(message);
                log.info("云端-->XPU 消息重试{}次:{}", (i+1), message);
                if (dto.getCode() == 200) {
                    break;
                }
            }catch (Exception e){
                log.error("云端-->XPU 推送失败:{}", message);
            }
        }
        return dto;
    }
}