liujie
2026-02-26 f3518f2c19303bdd7ca4a8b196e63c05a67829bd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
package com.xiaopeng.automaticPilot.util;
 
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.down.*;
import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudCreateOrder.RTTask;
import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudOrderOperation.OrderOperation;
import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudPushNavigation.RestoreNavigationData;
import com.xiaopeng.common.core.utils.StringUtils;
import com.xiaopeng.common.core.utils.uuid.UUID;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
 
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Map;
 
/**
 * 自动驾驶接口对接文档
 */
@Slf4j
@Component
public class XPUUtil {
 
    @Value("${xpu.topic.msg.prefix:Robotaxi/Msg/Xpu}")
    private String topicPrefix;
 
    @Resource
    private XPUClient xpuClient;
 
    @Resource
    private VmpOpenServiceClient vmpOpenServiceClient;
 
    // 查询车管绑定类型,1:XPUID,2:待扩展
    public static final String XPU_ID_TYPE = "1";
    // 查询车管 车辆xpuid信息返回字段,用于按需返回字段
    public static final List<String> TYPE_LIST = Collections.singletonList("1");
 
    /**
     * Robotaxi创建订单推送给XPU
     *
     * @param task
     * @return
     */
    //TODO 处理feign调用的异常
    public MqttPublishDto cloudCreateOrder(RTTask task, String vin, Long sequence) {
        MsgContent msgContent = new MsgContent();
        // 消息头
        RtMsgHeader header = new RtMsgHeader();
        header.setMsg_id(UUID.randomUUID().toString());
        header.setTimestamp(System.currentTimeMillis());
        header.setCmd(RTCmdType.CLOUD_CREATE_ORDER);
        header.setSequence(sequence);
        header.setType(MessageType.MESSAGE_TYPE_REQUEST);
        header.setSource(SourceType.CLOUD);
        msgContent.setHeader(header);
        // 消息内容
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("task", task);
        msgContent.setContent_detail(jsonObject);
        MqttPublishVo vo = new MqttPublishVo();
        vo.setTopic(buildTopicByVin(vin));
        vo.setPayload(JSON.toJSONString(msgContent));
 
        log.info("云端-->XPU 创建订单:{}", vo);
        return xpuClient.publish(vo);
    }
 
 
    /**
     * 取消订单、修改途经点、终点
     * @param operation
     * @return
     */
    //TODO 处理feign调用的异常
    public MqttPublishDto cloudOrderOperation(OrderOperation operation, String vin, Long sequence) {
        MsgContent msgContent = new MsgContent();
        // 消息头
        RtMsgHeader header = new RtMsgHeader();
        header.setMsg_id(UUID.randomUUID().toString());
        header.setTimestamp(System.currentTimeMillis());
        header.setCmd(RTCmdType.CLOUD_ORDER_OPERATION);
        header.setSequence(sequence);
        header.setType(MessageType.MESSAGE_TYPE_REQUEST);
        header.setSource(SourceType.CLOUD);
        msgContent.setHeader(header);
        // 消息内容
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("operation", operation);
        msgContent.setContent_detail(jsonObject);
        MqttPublishVo vo = new MqttPublishVo();
        vo.setTopic(buildTopicByVin(vin));
        vo.setPayload(JSON.toJSONString(msgContent));
 
        log.info("云端-->XPU 修改订单:{}", vo);
        return xpuClient.publish(vo);
    }
 
 
 
 
    /**
     * 响应消息
     *
     * @param responseMessage
     * @return
     */
    public MqttPublishDto responseMessage(ResponseMessage responseMessage, String vin) {
        MsgContent msgContent = new MsgContent();
        // 消息头
        RtMsgHeader header = new RtMsgHeader();
        header.setMsg_id(UUID.randomUUID().toString());
        header.setTimestamp(System.currentTimeMillis());
        header.setCmd(RTCmdType.CLOUD_TASK_CONTROL);
        Snowflake snowflake = IdUtil.getSnowflake(0, 0);
        header.setSequence(snowflake.nextId());
        header.setType(MessageType.MESSAGE_TYPE_RESPONSE);
        header.setSource(SourceType.CLOUD);
        msgContent.setHeader(header);
        // 消息内容
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("resposne", responseMessage);
        msgContent.setContent_detail(jsonObject);
        MqttPublishVo vo = new MqttPublishVo();
        vo.setTopic(buildTopicByVin(vin));
        vo.setPayload(JSON.toJSONString(msgContent));
 
        log.info("云端-->XPU 响应消息:{}", vo);
        return xpuClient.publish(vo);
    }
 
    /**
     * 下发导航地址到车端
     *
     * @param navigationData
     * @return
     */
    //TODO 处理feign调用的异常
    public MqttPublishDto cloudPushNavigation(RestoreNavigationData navigationData, String xpuId, Long sequence) {
        MsgContent msgContent = new MsgContent();
        // 消息头
        RtMsgHeader header = new RtMsgHeader();
        header.setMsg_id(UUID.randomUUID().toString());
        header.setTimestamp(System.currentTimeMillis());
        header.setCmd(RTCmdType.CLOUD_NAVIGATION_RESPONSE);
        header.setSequence(sequence);
        header.setType(MessageType.MESSAGE_TYPE_RESPONSE);
        header.setSource(SourceType.CLOUD);
        msgContent.setHeader(header);
        // 消息内容
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("navigationData", navigationData);
        msgContent.setContent_detail(jsonObject);
        MqttPublishVo vo = new MqttPublishVo();
        vo.setTopic(buildTopicByXpuId(xpuId));
        vo.setPayload(JSON.toJSONString(msgContent));
 
        log.info("云端-->XPU 下发导航信息:{}", vo);
        return xpuClient.publish(vo);
    }
 
 
    /**
     * @description: 根据vin查询xpuId
     * @param: vin
     * @return: xpuId
     */
    public String getXpuIdByVin(String vin)  {
        Map<String, String> xpuIdMapping = vmpOpenServiceClient.getVehicleBindInfoByVin(vin, TYPE_LIST);
        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信息为空");
        }
        return xpuIdMapping.get(XPU_ID_TYPE);
    }
 
    private String buildTopicByVin(String vin) {
        String xpuId = getXpuIdByVin(vin);
        return this.buildTopicByXpuId(xpuId);
    }
 
    private String buildTopicByXpuId(String xpuId) {
        String prefix = topicPrefix == null ? "" : topicPrefix;
        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";
    }
 
}