puzhibing
2026-04-11 b6f3de8451867d85242b2bd706fcfa4a65df4ff7
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java
@@ -1,70 +1,70 @@
package com.xiaopeng.automaticPilot.service;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat;
import com.xiaopeng.api.dto.automaticPilot.MqttPublishDto;
import com.xiaopeng.api.dto.automaticPilot.PushOrderDto;
import com.xiaopeng.api.dto.automaticPilot.VehicleEventDTO;
import com.xiaopeng.api.dto.map.OrderRouteAndFareDto;
import com.xiaopeng.api.dto.operation.CruisePointDto;
import com.xiaopeng.api.dto.operation.LonLatDto;
import com.xiaopeng.api.dto.operation.ReassignOrderDTO;
import com.xiaopeng.api.dto.order.AddCruiseMissionDto;
import com.xiaopeng.api.dto.order.PopOrderDto;
import com.xiaopeng.api.dto.pushMessage.PushOrderRouteDTO;
import com.xiaopeng.api.dto.pushMessage.SendMessageDTO;
import com.xiaopeng.api.dto.vehicleConvoy.UpdateVehicleStateDto;
import com.xiaopeng.api.feignClient.automaticPilot.VehicleBuriedPointClient;
import com.xiaopeng.api.feignClient.maintenance.XpTaskClient;
import com.xiaopeng.api.feignClient.map.XpMapClient;
import com.xiaopeng.api.feignClient.operation.ReassignOrderClient;
import com.xiaopeng.api.feignClient.operation.XpCruisePlanClient;
import com.xiaopeng.api.feignClient.order.XpCruiseOrderClient;
import com.xiaopeng.api.feignClient.order.XpOrderClient;
import com.xiaopeng.api.feignClient.order.XpTestOrderClient;
import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.UserVehicleClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
import com.xiaopeng.api.model.order.XpCruiseOrder;
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.api.model.order.XpTestOrder;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.OrderType;
import com.xiaopeng.api.vo.SystemEventType;
import com.xiaopeng.api.vo.automaticPilot.VehiclePosition;
import com.xiaopeng.api.vo.automaticPilot.proto.down.GeoPoint;
import com.xiaopeng.api.vo.automaticPilot.proto.down.ResponseMessage;
import com.xiaopeng.api.vo.automaticPilot.proto.down.StatusCode;
import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudCreateOrder.RTTask;
import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudCreateOrder.TaskStatus;
import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudCreateOrder.TaskType;
import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudOrderOperation.*;
import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudPushNavigation.RestoreNavigationData;
import com.xiaopeng.api.vo.automaticPilot.proto.up.MessageType;
import com.xiaopeng.api.vo.automaticPilot.proto.up.MsgContent;
import com.xiaopeng.api.vo.automaticPilot.proto.up.RTCmdType;
import com.xiaopeng.api.vo.automaticPilot.proto.up.RtMsgHeader;
import com.xiaopeng.api.vo.automaticPilot.proto.up.navigationDeviationEvent.NavigationDeviationEvent;
import com.xiaopeng.api.vo.automaticPilot.proto.up.navigationDeviationEvent.NavigationDeviationMessage;
import com.xiaopeng.api.vo.automaticPilot.proto.up.navigationDeviationEvent.RtEventType;
import com.xiaopeng.api.vo.automaticPilot.proto.up.orderStateUpdateEvent.OrderStatusInfoEvent;
import com.xiaopeng.api.vo.automaticPilot.proto.up.systemStatusXpu.*;
import com.xiaopeng.api.vo.automaticPilot.proto.up.xpuNavigationRequest.NavigationRequest;
import com.xiaopeng.api.vo.automaticPilot.proto.up.xpuNavigationRequest.OrderPhase;
import com.xiaopeng.api.vo.automaticPilot.protobuf.*;
import com.xiaopeng.api.vo.operation.RouteVo;
import com.xiaopeng.api.vo.order.OrderTrajectoryVo;
import com.xiaopeng.api.vo.vehicleConvoy.CancelTaxiPassengerVo;
import com.xiaopeng.automaticPilot.util.XPUUtil;
import com.xiaopeng.common.core.constant.CacheConstants;
import com.xiaopeng.common.core.constant.Constants;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.enums.CancelOrderSceneEnum;
import com.xiaopeng.common.core.enums.OrderStatusEnum;
import com.xiaopeng.common.core.enums.PushMessageTypeEnum;
import com.xiaopeng.common.core.utils.SnowFlake;
import com.xiaopeng.common.core.utils.StringUtils;
import com.xiaopeng.common.core.utils.uuid.UUID;
import com.xiaopeng.common.redis.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
 * Kafka 消费者服务
@@ -72,6 +72,8 @@
@Slf4j
@Service
public class KafkaConsumerService {
    private static final String REASSIGN_CANCEL_CONTEXT_PREFIX = "REASSIGN_CANCEL_CONTEXT:";
    @Resource
    private XpMapClient xpMapClient;
@@ -104,9 +106,29 @@
    private XpCruiseOrderClient xpCruiseOrderClient;
    @Resource
    private Snowflake snowflake;
    @Autowired
    private RedisService redisService;
    @Resource
    private XpCruisePlanClient xpCruisePlanClient;
    @Resource(name = "hutoolSnowflake")
    private Snowflake snowflake;
    @Value("${robotaxi.appId:xp_robotaxi_api}")
    private String appid;
    @Resource
    private XpTaskClient xpTaskClient;
    @Resource
    private VehicleBuriedPointClient vehicleBuriedPointClient;
    @Resource
    private XpTestOrderClient testOrderClient;
    private static final JsonFormat.Printer jsonPrinter = JsonFormat.printer()
            .printingEnumsAsInts()
            .preservingProtoFieldNames();
    /**
@@ -114,16 +136,46 @@
     *
     */
    public void topicProdRobotaxiXpuHigh(String message) {
        MsgContent msgContent = JSON.parseObject(message, MsgContent.class);
        handleXPUMessage(msgContent, message);
        MsgContent msgContent = parseMsgContent(message);
        if (msgContent != null) {
            handleXPUMessage(msgContent, message);
        }
    }
    /**
     * 消费消息 - XPU上报Robotaxi云端的消息topic(低优先级)
     */
    public void topicProdRobotaxiXpuNormal(String message) {
        MsgContent msgContent = JSON.parseObject(message, MsgContent.class);
        handleXPUMessage(msgContent, message);
        MsgContent msgContent = parseMsgContent(message);
        if (msgContent != null) {
            handleXPUMessage(msgContent, message);
        }
    }
    private MsgContent parseMsgContent(String message) {
        try {
            // 首先解析外层JSON,提取payload字段
            JSONObject outerJson = JSON.parseObject(message);
            String payload = outerJson.getString("payload");
            if (StringUtils.isEmpty(payload)) {
                log.error("Payload is empty in message: {}", message);
                return null;
            }
            // 使用payload构建MsgContent
            MsgContent.Builder builder = MsgContent.newBuilder();
            JsonFormat.parser().ignoringUnknownFields().merge(payload, builder);
            return builder.build();
        } catch (InvalidProtocolBufferException e) {
            log.error("Failed to parse message: {}", message, e);
            return null;
        } catch (Exception e) {
            log.error("Failed to extract payload from message: {}", message, e);
            return null;
        }
    }
@@ -133,12 +185,17 @@
     * @param message
     */
    public void handleXPUMessage(MsgContent msgContent, String message){
        RtMsgHeader header = msgContent.getHeader();
        MsgHeader header = msgContent.getHeader();
        MessageType type = header.getType();
        //处理请求消息
        if (MessageType.MESSAGE_TYPE_REQUEST == type) {
            //区分业务类型
            RTCmdType cmd = header.getCmd();
            int cmdValue = header.getCmd();
            RTCmdType cmd = RTCmdType.getByValue(cmdValue);
            if (cmd == null) {
                log.warn("Unknown cmd value: {}", cmdValue);
                return;
            }
            switch (cmd) {
                case SYSTEM_STATUS_XPU:
                    log.info("XPU发布系统运行状态 (XPU→云端):{}", message);
@@ -200,29 +257,44 @@
                    log.info("消息不在处理范围内,忽略:{}", message);
            }
        }
        //TODO 这里的逻辑要再确认下
        //消息应答
        if(MessageType.MESSAGE_TYPE_RESPONSE == type){
            com.xiaopeng.api.vo.automaticPilot.proto.up.ResponseMessage resposne = msgContent.getContent_detail().getObject("resposne", com.xiaopeng.api.vo.automaticPilot.proto.up.ResponseMessage.class);
            com.xiaopeng.api.vo.automaticPilot.proto.up.StatusCode code = resposne.getCode();
            Long requestSeq = resposne.getRequest_seq();
            if(code == com.xiaopeng.api.vo.automaticPilot.proto.up.StatusCode.OK){
                Object sequence = redisTemplate.opsForValue().get(requestSeq);
                if(sequence!=null){
                    JSONObject jsonObject = JSON.parseObject(sequence.toString());
                    String event = jsonObject.getString("event");
                    //推送导航的响应消息
                    if(SystemEventType.PUSH_NAVIGATION.equals(event)){
        if(MessageType.MESSAGE_TYPE_RESPONSE == type) {
            //区分业务类型
            int cmdValue = header.getCmd();
            RTCmdType cmd = RTCmdType.getByValue(cmdValue);
            if (cmd == null) {
                log.warn("Unknown cmd value: {}", cmdValue);
                return;
            }
            //云端下发订单的响应报文
            if (cmd == RTCmdType.CLOUD_SEND_RT_TASK) {
                RtTaskListResponse response = msgContent.getRtTaskListResponse();
                try {
                    log.info("云端下发订单操作的响应消息 (XPU→云端):{}", jsonPrinter.print(response));
                    Object sequence = redisService.getCacheObject("CREATE_ORDER:" + response.getResults().getOrderId());
                    if(sequence!=null){
                        JSONObject jsonObject = JSON.parseObject(sequence.toString());
                        String orderId = jsonObject.getString("orderId");
                        String vin = jsonObject.getString("vin");
                        String orderType = jsonObject.getString("orderType");
                        PopOrderDto dto = new PopOrderDto();
                        dto.setOrderId(Long.valueOf(orderId));
                        if(orderId.contains("XU")){
                            dto.setOrderId(Long.valueOf(orderId.substring(2)));
                        }else if(orderId.contains("TEST")){
                            dto.setOrderId(Long.valueOf(orderId.substring(4)));
                        }else{
                            dto.setOrderId(Long.valueOf(orderId));
                        }
                        dto.setXpVehicleVin(vin);
                        dto.setOrderType(orderType);
                        xpOrderClient.popOrder(dto);
                        log.info("订单状态更新:{}", response.getResults().getOrderId());
                    }
                } catch (InvalidProtocolBufferException e) {
                    log.error("Failed to print RtTaskListResponse: {}", response, e);
                }
            } else {
                log.info("响应消息不在处理范围内,忽略:{}", message);
            }
        }
    }
@@ -238,68 +310,106 @@
     */
    public void systemStatusXpu(MsgContent msgContent) {
        //开始处理消息对应的业务逻辑
        SystemRuntimeStatus systemRuntimeStatus = msgContent.getContent_detail().getObject("systemRuntimeStatus", SystemRuntimeStatus.class);
        SystemRuntimeStatus systemRuntimeStatus = msgContent.getSystemRuntimeStatus();
        //获取实时位置
        RealtimePose pose = systemRuntimeStatus.getPose();
        Wgs naviPose = pose.getNavi_pose();
        Double latitude = naviPose.getLatitude();
        Double longitude = naviPose.getLongitude();
        Wgs naviPose = pose.getNaviPose();
        double latitude = naviPose.getLatitude();
        double longitude = naviPose.getLongitude();
        Double course = naviPose.getCourse();
        Float alt = naviPose.getAlt();
        //获取车辆静态信息
        VehicleStaticInfo staticInfo = systemRuntimeStatus.getVehicle_status().getStatic_info();
        String xpuId = staticInfo.getXpu_id();
        VehicleStaticInfo staticInfo = systemRuntimeStatus.getVehicleStatus().getStaticInfo();
        String xpuId = staticInfo.getXpuId();
        XpVehicle xpVehicle = xpVehicleClient.findByVehicleXpuId(xpuId).getData();
        String vin = xpVehicle.getVehicleVin();
        //先响应消息
        Long sequence = msgContent.getHeader().getSequence();
        long sequence = msgContent.getHeader().getSequence();
        responseMessage(sequence, vin);
        //保存车辆实时位置到redis
        redisTemplate.opsForGeo().add("vehiclePosition:" + vin, new GeoJsonPoint(longitude, latitude), vin);
        //保存车辆实时信息到mongodb
        VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(vin)), VehiclePosition.class);
        if (null == vehiclePosition) {
            vehiclePosition = new VehiclePosition();
        if(0 != longitude && 0 != latitude){
            redisTemplate.opsForGeo().add("vehiclePosition:" + vin, new Point(longitude, latitude), vin);
        }
        vehiclePosition.setVin(vin);
        vehiclePosition.setPoint(new GeoJsonPoint(longitude, latitude));
        vehiclePosition.setCourse(course);
        vehiclePosition.setAlt(alt);
        VehicleStatus vehicleStatus = systemRuntimeStatus.getVehicle_status();
        VehicleStatus vehicleStatus = systemRuntimeStatus.getVehicleStatus();
        OrderStatusInfo runningOrderStatusInfo = systemRuntimeStatus.getRunningOrderStatusInfo();
        String order_id = runningOrderStatusInfo.getOrderId();
        //车辆动态信息
        VehicleDynamicStatus dynamicStatus = vehicleStatus.getDynamic_status();
        dynamicStatus.setSpeed(dynamicStatus.getSpeed());
        vehiclePosition.setCurrentElectricity(dynamicStatus.getBms_soc_disp());
        vehiclePosition.setMileageRange(dynamicStatus.getDst_bat_disp());
        //订单信息
        OrderStatusInfo runningOrderStatusInfo = systemRuntimeStatus.getRunning_order_status_info();
        VehicleDynamicStatus dynamicStatus = vehicleStatus.getDynamicStatus();
        Long orderId = null;
        String order_id = runningOrderStatusInfo.getOrder_id();
        vehiclePosition.setHasOrder(0);
        Integer hasOrder = 0;
        if (StringUtils.isNotEmpty(order_id)) {
            if (order_id.contains("XU")) {
                vehiclePosition.setHasOrder(1);
                hasOrder = 1;
                orderId = Long.parseLong(order_id.substring(2));
            } else {
            } else if(order_id.contains("TEST")) {
                orderId = Long.parseLong(order_id.substring(4));
            }else{
                orderId = Long.parseLong(order_id);
            }
        }
        vehiclePosition.setOrderId(orderId);
        mongoTemplate.save(vehiclePosition);
        //调用推送服务接口
        if (null != orderId) {
            RtTripInfo rtTripInfo = systemRuntimeStatus.getRt_trip_info();
            PushOrderRouteDTO dto = new PushOrderRouteDTO();
            dto.setOrderId(orderId);
            dto.setRouteType(order_id.contains("XU") ? 2 : 1);
            dto.setLongitude(longitude);
            dto.setLatitude(latitude);
            dto.setDuration(rtTripInfo.getRemaining_time());
            dto.setDistance(rtTripInfo.getRemaining_distance().intValue());
            xpPushMessageClient.pushOrderRoute(dto);
        //保存车辆实时信息到mongodb
        if(0 != longitude && 0 != latitude){
            VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(vin)), VehiclePosition.class);
            if (null == vehiclePosition) {
                vehiclePosition = new VehiclePosition();
                vehiclePosition.setVin(vin);
                vehiclePosition.setPoint(new GeoJsonPoint(longitude, latitude));
                vehiclePosition.setCourse(course);
                vehiclePosition.setAlt(alt);
                vehiclePosition.setSpeed(dynamicStatus.getSpeed());
                vehiclePosition.setCurrentElectricity(dynamicStatus.getBmsSocDisp());
                vehiclePosition.setMileageRange(dynamicStatus.getDstBatDisp());
                vehiclePosition.setOrderId(orderId);
                vehiclePosition.setTotalOdometer(dynamicStatus.getTotalOdometer());
                vehiclePosition.setAddTime(System.currentTimeMillis());
                mongoTemplate.save(vehiclePosition);
            }else{
                vehiclePosition.setOrderId(orderId);
                Update update = new Update()
                        .set("point", new GeoJsonPoint(longitude, latitude))
                        .set("course", course)
                        .set("alt", alt)
                        .set("speed", dynamicStatus.getSpeed())
                        .set("currentElectricity", dynamicStatus.getBmsSocDisp())
                        .set("mileageRange", dynamicStatus.getDstBatDisp())
                        .set("hasOrder", hasOrder)
                        .set("orderId", orderId)
                        .set("totalOdometer", dynamicStatus.getTotalOdometer()
                        .set("addTime", System.currentTimeMillis()));
                mongoTemplate.updateFirst(new Query(Criteria.where("vin").is(vin)), update, VehiclePosition.class);
            }
            //调用推送服务接口,给乘客推送剩余轨迹和里程时长
            if (null != orderId && !order_id.contains("XU")) {
                RtTripInfo rtTripInfo = systemRuntimeStatus.getRtTripInfo();
                PushOrderRouteDTO dto = new PushOrderRouteDTO();
                dto.setOrderId(orderId);
                dto.setRouteType(1);
                dto.setLongitude(longitude);
                dto.setLatitude(latitude);
                //TODO 这两个字段现在拿不到
//            dto.setDuration(rtTripInfo.getRemaining_time());
//            dto.setDistance(rtTripInfo.getRemaining_distance().intValue());
//            dto.setDirection();
                //只有乘客订单需要推送剩余导航数据
                if(!order_id.contains("TEST")){
                    xpPushMessageClient.pushOrderRoute(dto);
                }
                //存储历史轨迹
                OrderTrajectoryVo orderTrajectory = new OrderTrajectoryVo();
                orderTrajectory.setOrderId(orderId);
                orderTrajectory.setLocation(longitude + "," + latitude);
                orderTrajectory.setDirection(dto.getDirection());
                orderTrajectory.setSpeed(0D);
                orderTrajectory.setLocatetime(System.currentTimeMillis());
                orderTrajectory.setCreateTime(new Date());
                xpOrderClient.saveVehicleLocation(orderTrajectory);
            }
        }
    }
    /**
@@ -309,59 +419,95 @@
     */
    public void systemStatusXpuAndReassign(MsgContent msgContent) {
        //开始处理消息对应的业务逻辑
        SystemRuntimeStatus systemRuntimeStatus = msgContent.getContent_detail().getObject("systemRuntimeStatus", SystemRuntimeStatus.class);
        AbnormalReason abnormalReason = systemRuntimeStatus.getSystem_status().getAbnormal_reason();
        SystemRuntimeStatus systemRuntimeStatus = msgContent.getSystemRuntimeStatus();
        AbnormalReason abnormalReason = systemRuntimeStatus.getSystemStatus().getAbnormalReason();
        // 存储车辆挡位
        GearLevel gearLevel = systemRuntimeStatus.getVehicle_status().getDynamic_status().getGear_level();
        int value = gearLevel.getValue();
        redisTemplate.opsForValue().set(CacheConstants.GEAR_LEVEL + systemRuntimeStatus.getVehicle_status().getStatic_info().getVin(), value);
        GearLevel gearLevel = systemRuntimeStatus.getVehicleStatus().getDynamicStatus().getGearLevel();
        int value = gearLevel.getNumber();
        redisService.setCacheObject(CacheConstants.GEAR_LEVEL + systemRuntimeStatus.getVehicleStatus().getStaticInfo().getXpuId(), value);
        // 判断是否为故障状态
        XpVehicle vehicle = null;
        if (abnormalReason == AbnormalReason.FAULT) {
            log.info("车辆故障,开始处理故障");
            // TODO 添加异常任务
            // 解绑用户与车辆关系
            CancelTaxiPassengerVo cancelTaxiPassengerVo = new CancelTaxiPassengerVo();
            String orderId = systemRuntimeStatus.getRunning_order_status_info().getOrder_id();
            XpOrder xpOrder = xpOrderClient.queryOrderById(Long.parseLong(orderId)).getData();
            XpVehicle vehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData();
            if (vehicle != null) {
                // 修改车辆状态
                vehicle.setOperatingStatus(4);
                xpVehicleClient.updateVehicleById(vehicle);
                cancelTaxiPassengerVo.setVin(vehicle.getVehicleVin());
                cancelTaxiPassengerVo.setUid(xpOrder.getAppUserId().toString());
                cancelTaxiPassengerVo.setOrderNo(xpOrder.getOrderNumber());
                // TODO
//            cancelTaxiPassengerVo.setAppId();
                userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo);
            String orderId = systemRuntimeStatus.getRunningOrderStatusInfo().getOrderId();
            if(orderId.contains("XU")){
                //巡游订单,需要关闭订单
                xpCruiseOrderClient.cancelCruiseOrderById(Long.parseLong(orderId.substring(2)));
                XpCruiseOrder cruiseOrder = xpCruiseOrderClient.getCruiseOrder(Long.parseLong(orderId.substring(2))).getData();
                vehicle = xpVehicleClient.queryById(cruiseOrder.getVehicleId()).getData();
                if (vehicle != null) {
                    // 修改车辆状态
                    XpVehicle vehicle1 = new XpVehicle();
                    vehicle1.setOperatingStatus(4);
                    vehicle1.setId(vehicle.getId());
                    xpVehicleClient.updateVehicleById(vehicle1);
                }
            }else if(orderId.contains("TEST")){
                //测试订单故障则取消订单
                testOrderClient.updateOrderStatus(Long.parseLong(orderId.substring(4)), 0);
                XpTestOrder testOrder = testOrderClient.queryOrderById(Long.parseLong(orderId.substring(4))).getData();
                vehicle = xpVehicleClient.queryById(testOrder.getVehicleId()).getData();
                if (vehicle != null) {
                    // 修改车辆状态
                    XpVehicle vehicle1 = new XpVehicle();
                    vehicle1.setOperatingStatus(4);
                    vehicle1.setId(vehicle.getId());
                    xpVehicleClient.updateVehicleById(vehicle1);
                    log.info("车辆故障,车辆状态修改0 {}", vehicle.getPlateNumber());
                }
            }else {
                //正常订单
                XpOrder xpOrder = xpOrderClient.queryOrderById(Long.parseLong(orderId)).getData();
                vehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData();
                if (vehicle != null) {
                    // 修改车辆状态
                    XpVehicle vehicle1 = new XpVehicle();
                    vehicle1.setState(0);
                    vehicle1.setOperatingStatus(4);
                    vehicle1.setId(vehicle.getId());
                    xpVehicleClient.updateVehicleById(vehicle1);
                    log.info("车辆故障,车辆状态修改0 {}", vehicle.getPlateNumber());
                    // 解绑用户与车辆关系
                    CancelTaxiPassengerVo cancelTaxiPassengerVo = new CancelTaxiPassengerVo();
                    cancelTaxiPassengerVo.setVin(vehicle.getVehicleVin());
                    cancelTaxiPassengerVo.setUid(xpOrder.getAppUserId().toString());
                    cancelTaxiPassengerVo.setOrderNo(xpOrder.getOrderNumber());
                    cancelTaxiPassengerVo.setAppId(appid);
                    userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo);
                }
                // TODO 重新派单
                ReassignOrderDTO reassignOrderDTO = new ReassignOrderDTO();
                reassignOrderDTO.setUid(xpOrder.getAppUserId().toString());
                reassignOrderDTO.setOrderNo(xpOrder.getOrderNumber());
                reassignOrderDTO.setCount(10);
                RealtimePose pose = systemRuntimeStatus.getPose();
                Wgs naviPose = pose.getNaviPose();
                Double latitude = naviPose.getLatitude();
                Double longitude = naviPose.getLongitude();
                reassignOrderDTO.setLongitude(longitude);
                reassignOrderDTO.setLatitude(latitude);
                reassignOrderClient.reassignOrder(reassignOrderDTO);
            }
            // 取消订单
//            R<?> r = xpOrderClient.cancelOrder(String.valueOf(xpOrder.getId()));
//            if (r.getCode() == R.SUCCESS){
            log.info("取消订单成功");
            // TODO 重新派单
            ReassignOrderDTO reassignOrderDTO = new ReassignOrderDTO();
            reassignOrderDTO.setUid(xpOrder.getAppUserId().toString());
            reassignOrderDTO.setOrderNo(xpOrder.getOrderNumber());
            reassignOrderDTO.setCount(10);
            RealtimePose pose = systemRuntimeStatus.getPose();
            Wgs naviPose = pose.getNavi_pose();
            Double latitude = naviPose.getLatitude();
            Double longitude = naviPose.getLongitude();
            reassignOrderDTO.setLongitude(longitude);
            reassignOrderDTO.setLatitude(latitude);
            reassignOrderClient.reassignOrder(reassignOrderDTO);
            //添加车辆异常任务和发送消息
            xpTaskClient.saveVehicleAccidentError(vehicle.getId());
//            }
            // 封装埋点消息实体
            VehicleEventDTO vehicleEventDTO = new VehicleEventDTO();
            vehicleEventDTO.setVin(vehicle.getVehicleVin());
            vehicleEventDTO.setXpuId("");
            vehicleEventDTO.setOrderId("");
            vehicleEventDTO.setEventKey("RT_web_vehicle_status_changed");
            vehicleEventDTO.setEventTime(System.currentTimeMillis());
            Map<String,Object> attributes = new HashMap<>();
            attributes.put("vin",vehicle.getVehicleVin());
            attributes.put("order_id","");
            attributes.put("timestamp",vehicleEventDTO.getEventTime());
            attributes.put("main_status","OFFLINE");
            // TODO 预留位置 目前无状态
            attributes.put("sub_status","");
            attributes.put("prev_sub_status","");
            vehicleEventDTO.setAttributes(attributes);
            vehicleBuriedPointClient.sendVehicleEvent(vehicleEventDTO);
        }
    }
@@ -372,11 +518,11 @@
     */
    public void xpuNavigationRequest(MsgContent msgContent) {
        //开始处理消息对应的业务逻辑
        NavigationRequest naviRequest = msgContent.getContent_detail().getObject("naviRequest", NavigationRequest.class);
        String requestId = naviRequest.getRequest_id();
        String orderId = naviRequest.getOrder_id();
        String taskId = naviRequest.getTask_id();
        OrderPhase orderPhase = naviRequest.getOrder_phase();
        NavigationRequest naviRequest = msgContent.getNavigationRequset();
        String requestId = naviRequest.getRequestId();
        String orderId = naviRequest.getOrderId();
        String taskId = naviRequest.getTaskId();
        OrderPhase orderPhase = naviRequest.getOrderPhase();
        log.info("订单ID:{}", orderId);
        log.info("任务ID:{}", taskId);
        switch (orderPhase) {
@@ -384,15 +530,15 @@
                log.info("订单的任务未开始执行");
                break;
            case ROUTE_TO_PICKUP:
                log.info("驶往上车点的行程");
                log.info("驶往上车点的行程 {}", orderId);
                buildNaviRequest(requestId, orderId, orderPhase, msgContent.getHeader().getSequence());
                break;
            case ROUTE_TO_DESTINATION:
                log.info("驶往下车点的行程");
                log.info("驶往下车点的行程 {}", orderId);
                buildNaviRequest(requestId, orderId, orderPhase, msgContent.getHeader().getSequence());
                break;
            case ROUTE_TO_CRUISE:
                log.info("巡游阶段路线");
                log.info("巡游阶段路线 {}", orderId);
                buildNaviRequest(requestId, orderId, orderPhase, msgContent.getHeader().getSequence());
                break;
        }
@@ -405,76 +551,69 @@
     * @param msgContent
     */
    public void navigationDeviationEvent(MsgContent msgContent) {
        //先响应消息
        Long sequence = msgContent.getHeader().getSequence();
        //开始处理消息对应的业务逻辑
        NavigationDeviationEvent deviationEvent = msgContent.getContent_detail().getObject("deviationEvent", NavigationDeviationEvent.class);
        String requestId = deviationEvent.getRequest_id();
        NavigationDeviationEvent deviationEvent = msgContent.getNaviDeviationEvent();
        String requestId = deviationEvent.getNavigationDeviationMessage().getNaviRecalcRequestSeq() + "";
        //导航id
        String routeID = "";
        Long vehicleId = null;
        String orderType = "";
        //偏航事件类型 1:请求导航,2:取消导航
        if (deviationEvent.getEvent_type().equals(RtEventType.RT_EVENT_TYPE_REQUEST)) {
            NavigationDeviationMessage navigationDeviationMessage = deviationEvent.getNavigation_deviation_message();
            String orderId = navigationDeviationMessage.getOrder_id();
            String taskId = navigationDeviationMessage.getTask_id();
            Double longitude = navigationDeviationMessage.getLongitude();
            Double latitude = navigationDeviationMessage.getLatitude();
            //订单类型  1:乘客订单,2=巡游订单
            LonLatDto destination = new LonLatDto();
            LonLatDto origin = new LonLatDto();
            if (orderId.contains("XU")) {
                orderType = OrderType.CRUISE_ORDER;
        NavigationDeviationMessage navigationDeviationMessage = deviationEvent.getNavigationDeviationMessage();
        String orderId = navigationDeviationMessage.getOrderId();
        String taskId = navigationDeviationMessage.getTaskId();
        Wgs wgs = navigationDeviationMessage.getPoint();
        Double longitude = wgs.getLongitude();
        Double latitude = wgs.getLatitude();
        //订单类型  1:乘客订单,2=巡游订单
        LonLatDto destination = new LonLatDto();
        LonLatDto origin = new LonLatDto();
        if (orderId.contains("XU")) {
            orderType = OrderType.CRUISE_ORDER;
            R<XpCruiseOrder> cruiseOrder = xpCruiseOrderClient.getCruiseOrder(Long.parseLong(orderId.substring(2)));
            XpCruiseOrder xpCruiseOrder = cruiseOrder.getData();
            //构建导航数据给到车端
            origin.setLongitude(longitude);
            origin.setLatitude(latitude);
            destination.setLongitude(xpCruiseOrder.getEndLon());
            destination.setLatitude(xpCruiseOrder.getEndLat());
            OrderRouteAndFareDto dto = new OrderRouteAndFareDto();
            dto.setOrderId(Long.parseLong(orderId.substring(2)));
            dto.setOrigin(origin);
            dto.setDestination(destination);
            dto.setRouteType(3);
            R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto);
            if (200 != routeVoR.getCode()) {
                throw new RuntimeException("获取订单线路和运费失败");
            }
            RouteVo routeVo = routeVoR.getData();
            routeID = routeVo.getRouteID();
                R<XpCruiseOrder> cruiseOrder = xpCruiseOrderClient.getCruiseOrder(orderId);
                XpCruiseOrder xpCruiseOrder = cruiseOrder.getData();
                //先响应消息
                responseMessage(sequence, "");
                //构建导航数据给到车端
                origin.setLongitude(longitude);
                origin.setLatitude(latitude);
                destination.setLongitude(xpCruiseOrder.getEndLon());
                destination.setLatitude(xpCruiseOrder.getEndLat());
                OrderRouteAndFareDto dto = new OrderRouteAndFareDto();
                dto.setOrderId(Long.parseLong(orderId));
                dto.setOrigin(origin);
                dto.setDestination(destination);
                R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto);
                if (200 != routeVoR.getCode()) {
                    throw new RuntimeException("获取订单线路和运费失败");
                }
                RouteVo routeVo = routeVoR.getData();
                routeID = routeVo.getRouteID();
                vehicleId = xpCruiseOrder.getVehicleId();
            } else {
                orderType = OrderType.USER_ORDER;
                //正常单
                R<XpOrder> xpOrderR = xpOrderClient.queryOrderById(Long.parseLong(orderId));
                if (200 != xpOrderR.getCode()) {
                    throw new RuntimeException("订单不存在");
                }
                XpOrder xpOrder = xpOrderR.getData();
                XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData();
                //响应消息
                responseMessage(sequence, xpVehicle.getVehicleVin());
            vehicleId = xpCruiseOrder.getVehicleId();
        } else if(orderId.contains("TEST")){
            R<XpTestOrder> cruiseOrder = testOrderClient.queryOrderById(Long.parseLong(orderId.substring(4)));
            XpTestOrder testOrder = cruiseOrder.getData();
            //区分测试单和测试巡游单
            if(1 == testOrder.getOrderType()){
                orderType = OrderType.TEST_ORDER;
                //驶往上车点的行程
                if (Arrays.asList(3).contains(xpOrder.getStatus())) {
                if (3 == testOrder.getStatus()) {
                    //查询司机当前位置到起点的线路
                    origin.setLongitude(longitude);
                    origin.setLatitude(latitude);
                    destination.setLongitude(xpOrder.getStartLon());
                    destination.setLatitude(xpOrder.getStartLat());
                    destination.setLongitude(testOrder.getStartLon());
                    destination.setLatitude(testOrder.getStartLat());
                    OrderRouteAndFareDto dto = new OrderRouteAndFareDto();
                    dto.setOrderId(Long.parseLong(orderId));
                    dto.setOrderId(Long.parseLong(orderId.substring(4)));
                    dto.setOrigin(origin);
                    dto.setDestination(destination);
                    dto.setRouteType(1);
                    R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto);
                    if (200 != routeVoR.getCode()) {
                        throw new RuntimeException("获取订单线路和运费失败");
@@ -482,19 +621,20 @@
                    RouteVo routeVo = routeVoR.getData();
                    routeID = routeVo.getRouteID();
                    //缓存数据,用于后续推给乘客导航线路
                    redisService.setCacheObject("ORDER_NAVIGATION_START_DATA:" + xpOrder.getAppUserId(), com.alibaba.fastjson.JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS);
                    redisService.setCacheObject("TEST_ORDER_NAVIGATION_START_DATA:" + testOrder.getVehicleId(), JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS);
                }
                //驶往下车点的行程
                if (Arrays.asList(6).contains(xpOrder.getStatus())) {
                if (6 == testOrder.getStatus()) {
                    origin.setLongitude(longitude);
                    origin.setLatitude(latitude);
                    destination.setLongitude(xpOrder.getEndLon());
                    destination.setLatitude(xpOrder.getEndLat());
                    destination.setLongitude(testOrder.getEndLon());
                    destination.setLatitude(testOrder.getEndLat());
                    OrderRouteAndFareDto dto = new OrderRouteAndFareDto();
                    dto.setOrderId(Long.parseLong(orderId));
                    dto.setOrderId(Long.parseLong(orderId.substring(4)));
                    dto.setOrigin(origin);
                    dto.setDestination(destination);
                    dto.setRouteType(2);
                    R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto);
                    if (200 != routeVoR.getCode()) {
                        throw new RuntimeException("获取订单线路和运费失败");
@@ -502,19 +642,95 @@
                    RouteVo routeVo = routeVoR.getData();
                    routeID = routeVo.getRouteID();
                    //缓存导航数据,用于后面的逻辑中给乘客端推送导航数据
                    redisService.setCacheObject("ORDER_NAVIGATION_END_DATA:" + xpOrder.getAppUserId(), com.alibaba.fastjson.JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS);
                    redisService.setCacheObject("TEST_ORDER_NAVIGATION_END_DATA:" + testOrder.getVehicleId(), JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS);
                }
            }
            if(StringUtils.isNotEmpty(routeID)){
                XpVehicle xpVehicle = xpVehicleClient.queryById(vehicleId).getData();
                R<String> stringR = xpMapClient.queryRouted(routeID);
                if (200 != stringR.getCode()) {
                    throw new RuntimeException("根据导航ID获取车端需要的导航数据失败");
            }else{
                orderType = OrderType.TEST_CRUISE_ORDER;
                //构建导航数据给到车端
                origin.setLongitude(longitude);
                origin.setLatitude(latitude);
                destination.setLongitude(testOrder.getEndLon());
                destination.setLatitude(testOrder.getEndLat());
                OrderRouteAndFareDto dto = new OrderRouteAndFareDto();
                dto.setOrderId(Long.parseLong(orderId.substring(4)));
                dto.setOrigin(origin);
                dto.setDestination(destination);
                dto.setRouteType(3);
                R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto);
                if (200 != routeVoR.getCode()) {
                    throw new RuntimeException("获取订单线路和运费失败");
                }
                //构建导航下发请求对象
                cloudPushNavigationInfo(requestId, routeID, stringR.getData(), orderType, orderId, xpVehicle.getVehicleVin(), xpVehicle.getXpuId());
                RouteVo routeVo = routeVoR.getData();
                routeID = routeVo.getRouteID();
                vehicleId = testOrder.getVehicleId();
            }
        } else {
            orderType = OrderType.USER_ORDER;
            //正常单
            R<XpOrder> xpOrderR = xpOrderClient.queryOrderById(Long.parseLong(orderId));
            if (200 != xpOrderR.getCode()) {
                throw new RuntimeException("订单不存在");
            }
            XpOrder xpOrder = xpOrderR.getData();
            XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData();
            //驶往上车点的行程
            if (3 == xpOrder.getStatus()) {
                //查询司机当前位置到起点的线路
                origin.setLongitude(longitude);
                origin.setLatitude(latitude);
                destination.setLongitude(xpOrder.getStartLon());
                destination.setLatitude(xpOrder.getStartLat());
                OrderRouteAndFareDto dto = new OrderRouteAndFareDto();
                dto.setOrderId(Long.parseLong(orderId));
                dto.setOrigin(origin);
                dto.setDestination(destination);
                dto.setRouteType(1);
                R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto);
                if (200 != routeVoR.getCode()) {
                    throw new RuntimeException("获取订单线路和运费失败");
                }
                RouteVo routeVo = routeVoR.getData();
                routeID = routeVo.getRouteID();
                //缓存数据,用于后续推给乘客导航线路
                redisService.setCacheObject("ORDER_NAVIGATION_START_DATA:" + xpOrder.getAppUserId(), JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS);
            }
            //驶往下车点的行程
            if (6 == xpOrder.getStatus()) {
                origin.setLongitude(longitude);
                origin.setLatitude(latitude);
                destination.setLongitude(xpOrder.getEndLon());
                destination.setLatitude(xpOrder.getEndLat());
                OrderRouteAndFareDto dto = new OrderRouteAndFareDto();
                dto.setOrderId(Long.parseLong(orderId));
                dto.setOrigin(origin);
                dto.setDestination(destination);
                dto.setRouteType(2);
                R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto);
                if (200 != routeVoR.getCode()) {
                    throw new RuntimeException("获取订单线路和运费失败");
                }
                RouteVo routeVo = routeVoR.getData();
                routeID = routeVo.getRouteID();
                //缓存导航数据,用于后面的逻辑中给乘客端推送导航数据
                redisService.setCacheObject("ORDER_NAVIGATION_END_DATA:" + xpOrder.getAppUserId(), JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS);
            }
            vehicleId = xpOrder.getVehicleId();
        }
        //直接响应回最新导航数据
        if(StringUtils.isNotEmpty(routeID)){
            XpVehicle xpVehicle = xpVehicleClient.queryById(vehicleId).getData();
            R<String> stringR = xpMapClient.queryRouted(routeID);
            if (200 != stringR.getCode()) {
                throw new RuntimeException("根据导航ID获取车端需要的导航数据失败");
            }
            //构建响应导航数据给车端
            cloudPushNavigationInfo(requestId, routeID, stringR.getData(), orderType, orderId, xpVehicle.getVehicleVin(), xpVehicle.getXpuId());
        }
    }
@@ -534,14 +750,11 @@
        Long vehicleId = null;
        String orderType = "";
        if (orderId.contains("XU")) {
            orderType = OrderType.CRUISE_ORDER;
            //巡游单
            if (orderPhase.equals(OrderPhase.ROUTE_TO_CRUISE)) {
                //先响应消息
                responseMessage(sequence, "");
                /* 构建导航数据给到车端 */
                R<XpCruiseOrder> cruiseOrder = xpCruiseOrderClient.getCruiseOrder(orderId);
                R<XpCruiseOrder> cruiseOrder = xpCruiseOrderClient.getCruiseOrder(Long.parseLong(orderId.substring(2)));
                XpCruiseOrder xpCruiseOrder = cruiseOrder.getData();
                origin.setLongitude(xpCruiseOrder.getStartLon());
@@ -550,9 +763,10 @@
                destination.setLatitude(xpCruiseOrder.getEndLat());
                OrderRouteAndFareDto dto = new OrderRouteAndFareDto();
                dto.setOrderId(Long.parseLong(orderId));
                dto.setOrderId(Long.parseLong(orderId.substring(2)));
                dto.setOrigin(origin);
                dto.setDestination(destination);
                dto.setRouteType(3);
                R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto);
                if (200 != routeVoR.getCode()) {
                    throw new RuntimeException("获取订单线路和运费失败");
@@ -563,47 +777,147 @@
                vehicleId = xpCruiseOrder.getVehicleId();
            }
        } else {
        } else if(orderId.contains("TEST")){
            R<XpTestOrder> cruiseOrder = testOrderClient.queryOrderById(Long.parseLong(orderId.substring(4)));
            XpTestOrder testOrder = cruiseOrder.getData();
            XpVehicle xpVehicle = xpVehicleClient.queryById(testOrder.getVehicleId()).getData();
            //区分测试单和测试巡游单
            if(1 == testOrder.getOrderType()){
                orderType = OrderType.TEST_ORDER;
                //驶往上车点的行程
                if (orderPhase.equals(OrderPhase.ROUTE_TO_PICKUP)) {
                    //直接取缓存中的导航数据推送给车端和乘客
                    Object cacheObject = redisService.getCacheObject("TEST_ORDER_NAVIGATION_START_DATA:" + testOrder.getVehicleId());
                    if(null == cacheObject){
                        //没有缓存数据,重新规划线路
                        //查询车辆位置
                        VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class);
                        if (Objects.isNull(vehiclePosition)) {
                            throw new RuntimeException("车辆位置信息不存在");
                        }
                        origin.setLongitude(vehiclePosition.getPoint().getX());
                        origin.setLatitude(vehiclePosition.getPoint().getY());
                        destination.setLongitude(testOrder.getStartLon());
                        destination.setLatitude(testOrder.getStartLat());
                        OrderRouteAndFareDto dto = new OrderRouteAndFareDto();
                        dto.setOrderId(Long.parseLong(orderId.substring(4)));
                        dto.setOrigin(origin);
                        dto.setDestination(destination);
                        dto.setRouteType(2);
                        R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto);
                        if (200 != routeVoR.getCode()) {
                            throw new RuntimeException("获取订单线路和运费失败");
                        }
                        RouteVo routeVo = routeVoR.getData();
                        routeID = routeVo.getRouteID();
                        //缓存导航数据,用于后面的逻辑中给乘客端推送导航数据
                        redisService.setCacheObject("TEST_ORDER_NAVIGATION_START_DATA:" + testOrder.getVehicleId(), JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS);
                    }else{
                        RouteVo routeVo = JSON.parseObject(cacheObject.toString(), RouteVo.class);
                        routeID = routeVo.getRouteID();
                    }
                }
                //驶往下车点的行程
                if (orderPhase.equals(OrderPhase.ROUTE_TO_DESTINATION)) {
                    //直接取缓存中的导航数据推送给车端和乘客
                    Object cacheObject = redisService.getCacheObject("TEST_ORDER_NAVIGATION_END_DATA:" + testOrder.getVehicleId());
                    if(null == cacheObject){
                        //没有缓存数据,重新规划线路
                        //查询起点到终点的线路
                        origin.setLongitude(testOrder.getStartLon());
                        origin.setLatitude(testOrder.getStartLat());
                        destination.setLongitude(testOrder.getEndLon());
                        destination.setLatitude(testOrder.getEndLat());
                        OrderRouteAndFareDto dto = new OrderRouteAndFareDto();
                        dto.setOrderId(Long.parseLong(orderId.substring(4)));
                        dto.setOrigin(origin);
                        dto.setDestination(destination);
                        dto.setRouteType(2);
                        R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto);
                        if (200 != routeVoR.getCode()) {
                            throw new RuntimeException("获取订单线路和运费失败");
                        }
                        RouteVo routeVo = routeVoR.getData();
                        routeID = routeVo.getRouteID();
                        //缓存导航数据,用于后面的逻辑中给乘客端推送导航数据
                        redisService.setCacheObject("TEST_ORDER_NAVIGATION_END_DATA:" + testOrder.getVehicleId(), JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS);
                    }else{
                        RouteVo routeVo = JSON.parseObject(cacheObject.toString(), RouteVo.class);
                        routeID = routeVo.getRouteID();
                    }
                }
            }else{
                orderType = OrderType.TEST_CRUISE_ORDER;
                //巡游单
                if (orderPhase.equals(OrderPhase.ROUTE_TO_CRUISE)) {
                    /* 构建导航数据给到车端 */
                    origin.setLongitude(testOrder.getStartLon());
                    origin.setLatitude(testOrder.getStartLat());
                    destination.setLongitude(testOrder.getEndLon());
                    destination.setLatitude(testOrder.getEndLat());
                    OrderRouteAndFareDto dto = new OrderRouteAndFareDto();
                    dto.setOrderId(Long.parseLong(orderId.substring(4)));
                    dto.setOrigin(origin);
                    dto.setDestination(destination);
                    dto.setRouteType(3);
                    R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto);
                    if (200 != routeVoR.getCode()) {
                        throw new RuntimeException("获取订单线路和运费失败");
                    }
                    RouteVo routeVo = routeVoR.getData();
                    routeID = routeVo.getRouteID();
                }
            }
            vehicleId = testOrder.getVehicleId();
        }else{
            orderType = OrderType.USER_ORDER;
            //正常单
            R<XpOrder> xpOrderR = xpOrderClient.queryOrderById(Long.parseLong(orderId));
            if (200 != xpOrderR.getCode()) {
                throw new RuntimeException("订单不存在");
                throw new RuntimeException("订单不存在 " + orderId);
            }
            XpOrder xpOrder = xpOrderR.getData();
            XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData();
            //先响应消息
            responseMessage(sequence, xpVehicle.getVehicleVin());
            //驶往上车点的行程
            if (orderPhase.equals(OrderPhase.ROUTE_TO_PICKUP)) {
                //查询车辆位置
                VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class);
                if (Objects.isNull(vehiclePosition)) {
                    throw new RuntimeException("车辆位置信息不存在");
                }
                //查询司机当前位置到起点的线路
                origin.setLongitude(vehiclePosition.getPoint().getX());
                origin.setLatitude(vehiclePosition.getPoint().getY());
                destination.setLongitude(xpOrder.getStartLon());
                destination.setLatitude(xpOrder.getStartLat());
                Object cacheObject = redisService.getCacheObject("ORDER_NAVIGATION_START_DATA:" + xpOrder.getAppUserId());
                if(null == cacheObject){
                    //查询车辆位置
                    VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class);
                    if (Objects.isNull(vehiclePosition)) {
                        throw new RuntimeException("车辆位置信息不存在");
                    }
                    //查询司机当前位置到起点的线路
                    origin.setLongitude(vehiclePosition.getPoint().getX());
                    origin.setLatitude(vehiclePosition.getPoint().getY());
                    destination.setLongitude(xpOrder.getStartLon());
                    destination.setLatitude(xpOrder.getStartLat());
                OrderRouteAndFareDto dto = new OrderRouteAndFareDto();
                dto.setOrderId(Long.parseLong(orderId));
                dto.setOrigin(origin);
                dto.setDestination(destination);
                R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto);
                if (200 != routeVoR.getCode()) {
                    throw new RuntimeException("获取订单线路和运费失败");
                }
                RouteVo routeVo = routeVoR.getData();
                routeID = routeVo.getRouteID();
                //缓存数据,用于后续推给乘客导航线路
                redisService.setCacheObject("ORDER_NAVIGATION_START_DATA:" + xpOrder.getAppUserId(), com.alibaba.fastjson.JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS);
                    OrderRouteAndFareDto dto = new OrderRouteAndFareDto();
                    dto.setOrderId(Long.parseLong(orderId));
                    dto.setOrigin(origin);
                    dto.setDestination(destination);
                    dto.setRouteType(1);
                    R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto);
                    if (200 != routeVoR.getCode()) {
                        throw new RuntimeException("获取订单线路和运费失败");
                    }
                    RouteVo routeVo = routeVoR.getData();
                    routeID = routeVo.getRouteID();
                    //缓存数据,用于后续推给乘客导航线路
                    redisService.setCacheObject("ORDER_NAVIGATION_START_DATA:" + xpOrder.getAppUserId(), JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS);
                }else{
                    RouteVo routeVo = JSON.parseObject(cacheObject.toString(), RouteVo.class);
                    routeID = routeVo.getRouteID();
                };
            }
            //驶往下车点的行程
            if (orderPhase.equals(OrderPhase.ROUTE_TO_DESTINATION)) {
                //直接取缓存中的导航数据推送给车端和乘客
                Object cacheObject = redisService.getCacheObject("ORDER_NAVIGATION_DATA:" + xpOrder.getAppUserId());
                Object cacheObject = redisService.getCacheObject("ORDER_NAVIGATION_END_DATA:" + xpOrder.getAppUserId());
                if(null == cacheObject){
                    //没有缓存数据,重新规划线路
                    //查询起点到终点的线路
@@ -615,6 +929,7 @@
                    dto.setOrderId(Long.parseLong(orderId));
                    dto.setOrigin(origin);
                    dto.setDestination(destination);
                    dto.setRouteType(2);
                    R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto);
                    if (200 != routeVoR.getCode()) {
                        throw new RuntimeException("获取订单线路和运费失败");
@@ -622,7 +937,7 @@
                    RouteVo routeVo = routeVoR.getData();
                    routeID = routeVo.getRouteID();
                    //缓存导航数据,用于后面的逻辑中给乘客端推送导航数据
                    redisService.setCacheObject("ORDER_NAVIGATION_END_DATA:" + xpOrder.getAppUserId(), com.alibaba.fastjson.JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS);
                    redisService.setCacheObject("ORDER_NAVIGATION_END_DATA:" + xpOrder.getAppUserId(), JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS);
                }else{
                    RouteVo routeVo = JSON.parseObject(cacheObject.toString(), RouteVo.class);
                    routeID = routeVo.getRouteID();
@@ -632,11 +947,13 @@
        }
        if(StringUtils.isNotEmpty(routeID)){
            log.info("开始推送导航信息 {}", orderId);
            XpVehicle xpVehicle = xpVehicleClient.queryById(vehicleId).getData();
            R<String> stringR = xpMapClient.queryRouted(routeID);
            if (200 != stringR.getCode()) {
                throw new RuntimeException("根据导航ID获取车端需要的导航数据失败");
            }
            log.info("根据导航ID获取车端需要的导航数据 订单 {} 导航数据 {}", orderId, stringR.getData());
            //构建导航下发请求对象
            cloudPushNavigationInfo(requestId, routeID, stringR.getData(), orderType, orderId, xpVehicle.getVehicleVin(), xpVehicle.getXpuId());
        }
@@ -650,44 +967,46 @@
     */
    public void cloudOrderOperation(Integer orderType, String orderId, String taskId, RouteVo routeVo, String vin) {
        //构建消息体
        OrderOperation orderOperation = new OrderOperation();
        orderOperation.setOrder_id(orderId);
        orderOperation.setTask_id(taskId);
        orderOperation.setOperation_type(OrderOperationType.CLOUD_UPDATE_WAYPOINTS);
        OrderOperation.Builder orderOperationBuilder = OrderOperation.newBuilder();
        orderOperationBuilder.setOrderId(orderId);
        orderOperationBuilder.setTaskId(taskId);
        orderOperationBuilder.setOperationType(OrderOperationType.CLOUD_UPDATE_WAYPOINTS);
        //构建航点
        List<Waypoint> waypoints = new ArrayList<>();
        List<LonLatDto> polyline = routeVo.getPolyline();
        for (int i = 0; i < polyline.size(); i++) {
            LonLatDto lonLatDto = polyline.get(i);
            Waypoint waypoint = new Waypoint();
            waypoint.setWaypoint_id(UUID.randomUUID().toString());
            Waypoint.Builder waypointBuilder = Waypoint.newBuilder();
            waypointBuilder.setWaypointId(UUID.randomUUID().toString());
            if (0 == i) {
                waypoint.setPoint_type(PointType.START_POINT);
                waypointBuilder.setPointType(PointType.START_POINT);
                //订单类型不同,点位的动作类型不同
                waypoint.setAction_type(1 == orderType ? ActionType.PICK_UP : ActionType.ACTION_UNSPECIFIED);
                waypointBuilder.setActionType(1 == orderType ? ActionType.PICK_UP : ActionType.ACTION_UNSPECIFIED);
            } else if (polyline.size() - 1 == i) {
                waypoint.setPoint_type(PointType.END_POINT);
                waypoint.setAction_type(1 == orderType ? ActionType.DROP_OFF : ActionType.ACTION_UNSPECIFIED);
                waypointBuilder.setPointType(PointType.END_POINT);
                waypointBuilder.setActionType(1 == orderType ? ActionType.DROP_OFF : ActionType.ACTION_UNSPECIFIED);
            } else {
                waypoint.setPoint_type(PointType.WAY_POINT);
                waypointBuilder.setPointType(PointType.WAY_POINT);
                //订单类型不同,点位的动作类型不同
                waypoint.setAction_type(ActionType.ACTION_UNSPECIFIED);
                waypointBuilder.setActionType(ActionType.ACTION_UNSPECIFIED);
            }
            //构建经纬度
            GeoPoint geoPoint = new GeoPoint();
            geoPoint.setLongitude(lonLatDto.getLongitude());
            geoPoint.setLatitude(lonLatDto.getLatitude());
            waypoint.setPoint(geoPoint);
            waypoint.setSequence(i + 1);
            waypoints.add(waypoint);
            GeoPoint.Builder geoPointBuilder = GeoPoint.newBuilder();
            geoPointBuilder.setLongitude(lonLatDto.getLongitude());
            geoPointBuilder.setLatitude(lonLatDto.getLatitude());
            waypointBuilder.setPoint(geoPointBuilder.build());
            waypointBuilder.setSequence(i + 1);
            waypoints.add(waypointBuilder.build());
        }
        orderOperation.setWaypoints(waypoints);
        orderOperationBuilder.addAllWaypoints(waypoints);
        long sequence = snowflake.nextId();
        // 处理数据
        redisTemplate.opsForValue().set(sequence,"pushOrder_"+orderId+"_"+vin,30, TimeUnit.MINUTES);
        redisService.setCacheObject(sequence + "","pushOrder_"+orderId+"_"+vin,30L, TimeUnit.MINUTES);
        //开发发送请求到XPU
        xpuUtil.cloudOrderOperation(orderOperation, vin,sequence);
        xpuUtil.cloudOrderOperation(orderOperationBuilder.build(), vin,sequence);
    }
@@ -695,11 +1014,12 @@
     * 构建响应消息
     */
    public void responseMessage(Long request_seq, String vin) {
        ResponseMessage responseMessage = new ResponseMessage();
        responseMessage.setRequest_seq(request_seq);
        responseMessage.setCode(StatusCode.OK);
        responseMessage.setTimestamp(System.currentTimeMillis());
        xpuUtil.responseMessage(responseMessage, vin);
        ResponseMessage.Builder responseMessageBuilder = ResponseMessage.newBuilder();
        responseMessageBuilder.setRequestSeq(request_seq);
        responseMessageBuilder.setCode(StatusCode.OK);
        responseMessageBuilder.setTimestamp(System.currentTimeMillis());
        xpuUtil.responseMessage(responseMessageBuilder.build(), vin);
    }
@@ -709,15 +1029,15 @@
     */
    public void orderStateUpdateEvent(MsgContent msgContent) {
        //先响应消息
        Long sequence = msgContent.getHeader().getSequence();
        long sequence = msgContent.getHeader().getSequence();
        //开始处理消息对应的业务逻辑
        OrderStatusInfoEvent orderStatusInfoEvent = msgContent.getContent_detail().getObject("orderStatusInfoEvent", OrderStatusInfoEvent.class);
        OrderStatusInfoEvent orderStatusInfoEvent = msgContent.getOrderStatusInfoEvent();
        //只处理请求消息
        if (orderStatusInfoEvent.getEvent_type().equals(RtEventType.RT_EVENT_TYPE_REQUEST)) {
            com.xiaopeng.api.vo.automaticPilot.proto.up.orderStateUpdateEvent.OrderStatusInfo orderStatusInfo = orderStatusInfoEvent.getOrder_status_info();
            String orderId = orderStatusInfo.getOrder_id();
        if (orderStatusInfoEvent.getEventType().equals(RtEventType.kEventOrderStateUpdate)) {
            OrderStatusInfo orderStatusInfo = orderStatusInfoEvent.getOrderStatusInfo();
            String orderId = orderStatusInfo.getOrderId();
            //普通单
            com.xiaopeng.api.vo.automaticPilot.proto.up.orderStateUpdateEvent.OrderStatus status = orderStatusInfo.getStatus();
            OrderStatus status = orderStatusInfo.getStatus();
            switch (status) {
                case ORDER_STATUS_UNSPECIFIED:
                    //订单状态未知
@@ -725,8 +1045,14 @@
                    break;
                case ORDER_RECEIVED:
                    //收到订单
                    buildPushOrderStatus(orderId, OrderStatusEnum.READY_DEPART, sequence);
                    xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.READY_DEPART.getCode());
                    if(!orderId.contains("XU")){
                        if(orderId.contains("TEST")){
                            testOrderClient.updateOrderStatus(Long.parseLong(orderId.substring(4)), OrderStatusEnum.READY_DEPART.getCode());
                        }else{
                            buildPushOrderStatus(orderId, OrderStatusEnum.READY_DEPART, sequence);
                            xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.READY_DEPART.getCode());
                        }
                    }
                    break;
                case ORDER_STARTED:
                    //开始执行订单
@@ -734,8 +1060,14 @@
                    break;
                case ORDER_EN_ROUTE_TO_PICKUP:
                    //前往上车点
                    buildPushOrderStatus(orderId, OrderStatusEnum.PICK_UP, sequence);
                    xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.PICK_UP.getCode());
                    if(!orderId.contains("XU")){
                        if(orderId.contains("TEST")){
                            testOrderClient.updateOrderStatus(Long.parseLong(orderId.substring(4)), OrderStatusEnum.PICK_UP.getCode());
                        }else{
                            buildPushOrderStatus(orderId, OrderStatusEnum.PICK_UP, sequence);
                            xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.PICK_UP.getCode());
                        }
                    }
                    break;
                case ORDER_ARRIVED_AT_PICKUP:
                    //到达上车点
@@ -743,45 +1075,206 @@
                    break;
                case ORDER_WAITING_FOR_PICKUP:
                    //等待乘客上车
                    buildPushOrderStatus(orderId, OrderStatusEnum.PICK_UP_GUESTS, sequence);
                    xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.PICK_UP_GUESTS.getCode());
                    if(!orderId.contains("XU")){
                        if(orderId.contains("TEST")){
                            testOrderClient.updateOrderStatus(Long.parseLong(orderId.substring(4)), OrderStatusEnum.PICK_UP_GUESTS.getCode());
                        }else{
                            buildPushOrderStatus(orderId, OrderStatusEnum.PICK_UP_GUESTS, sequence);
                            xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.PICK_UP_GUESTS.getCode());
                        }
                    }
                    break;
                case ORDER_PASSENGER_ONBOARD:
                    //乘客已上车
                    buildPushOrderStatus(orderId, OrderStatusEnum.PASSENGER_BOARDED, sequence);
                    xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.PASSENGER_BOARDED.getCode());
                    if(!orderId.contains("XU")){
                        if(orderId.contains("TEST")){
                            testOrderClient.updateOrderStatus(Long.parseLong(orderId.substring(4)), OrderStatusEnum.PASSENGER_BOARDED.getCode());
                        }else{
                            buildPushOrderStatus(orderId, OrderStatusEnum.PASSENGER_BOARDED, sequence);
                            xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.PASSENGER_BOARDED.getCode());
                        }
                    }
                    break;
                case ORDER_EN_ROUTE_TO_DESTINATION:
                    //前往目的地
                    buildPushOrderStatus(orderId, OrderStatusEnum.IN_SERVICE, sequence);
                    xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.IN_SERVICE.getCode());
                    if(!orderId.contains("XU")){
                        if(orderId.contains("TEST")){
                            testOrderClient.updateOrderStatus(Long.parseLong(orderId.substring(4)), OrderStatusEnum.IN_SERVICE.getCode());
                        }else{
                            buildPushOrderStatus(orderId, OrderStatusEnum.IN_SERVICE, sequence);
                            xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.IN_SERVICE.getCode());
                        }
                    }
                    break;
                case ORDER_ARRIVED_AT_DESTINATION:
                    //到达目的地
                    log.info("到达目的地,不做任何处理:{}", orderId);
                    break;
                case ORDER_WAITING_FOR_DROPOFF:
                    //等待乘客下车
                    buildPushOrderStatus(orderId, OrderStatusEnum.SEE_OFF_GUESTS, sequence);
                    xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.SEE_OFF_GUESTS.getCode());
                    //等待乘客下车,开始倒计时发下巡游单
                    if(!orderId.contains("XU")){
                        if(orderId.contains("TEST")){
                            testOrderClient.updateOrderStatus(Long.parseLong(orderId.substring(4)), OrderStatusEnum.SEE_OFF_GUESTS.getCode());
                        }else{
                            buildPushOrderStatus(orderId, OrderStatusEnum.SEE_OFF_GUESTS, sequence);
                            xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.SEE_OFF_GUESTS.getCode());
                        }
                    }
                    break;
                case ORDER_DROPOFF_COMPLETED:
                    //下车完成
                    buildPushOrderStatus(orderId, OrderStatusEnum.APPROVAL_REJECTION, sequence);
                    xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.APPROVAL_REJECTION.getCode());
                    //下车完成,不需要处理状态,由后续的乘客主动触发或者定时任务触发
                    log.info("乘客已下车,不做任何处理:{}", orderId);
                    break;
                case ORDER_COMPLETED:
                    //已完成
                    log.info("已完成,不做任何处理:{}", orderId);
                    if(!orderId.contains("XU")){
                        XpOrder xpOrder = xpOrderClient.queryOrderById(Long.valueOf(orderId)).getData();
                        if (Objects.nonNull(xpOrder)){
                            // 查询车辆
                            XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData();
                            if (Objects.nonNull(xpVehicle)){
                                String vin = xpVehicle.getVehicleVin();
                                // 封装埋点消息实体
                                VehicleEventDTO vehicleEventDTO = new VehicleEventDTO();
                                vehicleEventDTO.setVin(vin);
                                vehicleEventDTO.setXpuId("");
                                vehicleEventDTO.setOrderId(orderId);
                                vehicleEventDTO.setEventKey("RT_xpu_vehicle_trace_upload");
                                vehicleEventDTO.setEventTime(System.currentTimeMillis());
                                Map<String,Object> attributes = new HashMap<>();
                                attributes.put("vin",vin);
                                attributes.put("order_id",vehicleEventDTO.getOrderId());
                                attributes.put("order_type","user_order");
                                attributes.put("timestamp",vehicleEventDTO.getEventTime());
                                attributes.put("current_main_status",OrderStatus.ORDER_COMPLETED);
                                attributes.put("current_sub_status","");
                                VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(vin)), VehiclePosition.class);
                                if(Objects.nonNull(vehiclePosition)){
                                    attributes.put("odometer_km",vehiclePosition.getTotalOdometer());
                                }else {
                                    attributes.put("odometer_km","");
                                }
                                vehicleEventDTO.setAttributes(attributes);
                                vehicleBuriedPointClient.sendVehicleEvent(vehicleEventDTO);
                                log.info("已完成,推送埋点:{}", orderId);
                            }
                        }
                    }
                    break;
                case ORDER_CANCELLED:
                    //已取消
                    buildPushOrderStatus(orderId, OrderStatusEnum.CANCELED, sequence);
                    xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.CANCELED.getCode());
                    if(!orderId.contains("XU")){
                        String taskId = orderStatusInfo.getTaskId();
                        JSONObject reassignCancelContext = resolveReassignCancelContext(orderId, orderStatusInfo);
                        if (Objects.nonNull(reassignCancelContext)) {
                            log.info("改派旧车取消回调,跳过订单取消处理,orderId: {}, taskId: {}, cancelScene: {}, context: {}",
                                    orderId, taskId, reassignCancelContext.getString("cancelScene"), reassignCancelContext);
                            //响应消息
                            String responseVin = resolveReassignCancelResponseVin(reassignCancelContext);
                            if (StringUtils.isNotEmpty(responseVin)) {
                                responseMessage(sequence, responseVin);
                            } else {
                                log.warn("改派旧车取消回调未找到响应VIN,orderId: {}, taskId: {}, context: {}",
                                        orderId, taskId, reassignCancelContext);
                            }
                            return;
                        }
                        if(orderId.contains("TEST")){
                            //判断订单状态,已经取消的不作处理
                            Object cacheObject = redisService.getCacheObject("TEST_ORDER_STATUS:" + orderId.substring(4));
                            if(null != cacheObject){
                                int order_status = Integer.parseInt(cacheObject.toString());
                                if(0 == order_status){
                                    return;
                                }
                            }
                            XpTestOrder testOrder = testOrderClient.queryOrderById(Long.valueOf(orderId.substring(4))).getData();
                            if(testOrder.getStatus() == 0 || testOrder.getStatus() >= 8){
                                return;
                            }
                            //行程中取消订单,按照行程结束处理
                            if(testOrder.getStatus() > 5 && testOrder.getStatus() < 8){
                                testOrderClient.updateOrderStatus(Long.parseLong(orderId.substring(4)), OrderStatusEnum.SEE_OFF_GUESTS.getCode());
                                redisService.setCacheObject("TEST_ORDER_STATUS:" + orderId.substring(4), OrderStatusEnum.SEE_OFF_GUESTS.getCode(), 24L, TimeUnit.HOURS);
                            }else{
                                testOrderClient.updateOrderStatus(Long.parseLong(orderId.substring(4)), OrderStatusEnum.CANCELED.getCode());
                                redisService.setCacheObject("TEST_ORDER_STATUS:" + orderId.substring(4), OrderStatusEnum.CANCELED.getCode(), 24L, TimeUnit.HOURS);
                            }
                        }else{
                            //判断订单状态,已经取消的不作处理
                            Object cacheObject = redisService.getCacheObject("ORDER_STATUS:" + orderId);
                            if(null != cacheObject){
                                int order_status = Integer.parseInt(cacheObject.toString());
                                if(0 == order_status){
                                    return;
                                }
                            }
                            XpOrder xpOrder = xpOrderClient.queryOrderById(Long.parseLong(orderId)).getData();
                            if(xpOrder.getStatus() == 0 || xpOrder.getStatus() >= 8){
                                return;
                            }
                            if(xpOrder.getStatus() > 5 && xpOrder.getStatus() < 8){
                                //行程中取消订单,按照行程结束处理
                                buildPushOrderStatus(orderId, OrderStatusEnum.SEE_OFF_GUESTS, sequence);
                                xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.SEE_OFF_GUESTS.getCode());
                                redisService.setCacheObject("ORDER_STATUS:" + orderId, OrderStatusEnum.SEE_OFF_GUESTS.getCode(), 24L, TimeUnit.HOURS);
                            }else{
                                buildPushOrderStatus(orderId, OrderStatusEnum.CANCELED, sequence);
                                xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.CANCELED.getCode());
                                redisService.setCacheObject("ORDER_STATUS:" + orderId, OrderStatusEnum.CANCELED.getCode(), 24L, TimeUnit.HOURS);
                            }
                        }
                    }
                    break;
                case ORDER_ARRIVED_AT_CRUISE_DESTINATION:
                    //到达巡游终点
                    buildPushOrderStatus(orderId, OrderStatusEnum.COMPLETED, sequence);
                    if(orderId.contains("XU")){
                        buildPushOrderStatus(orderId, OrderStatusEnum.COMPLETED, sequence);
                        String cruiseOrderId = orderId.substring(2);
                        XpCruiseOrder xpCruiseOrder = xpCruiseOrderClient.getCruiseOrder(Long.parseLong(cruiseOrderId)).getData();
                        if (Objects.nonNull(xpCruiseOrder)){
                            // 查询车辆
                            XpVehicle xpVehicle = xpVehicleClient.queryById(xpCruiseOrder.getVehicleId()).getData();
                            if (Objects.nonNull(xpVehicle)){
                                String vin = xpVehicle.getVehicleVin();
                                // 封装埋点消息实体
                                VehicleEventDTO vehicleEventDTO = new VehicleEventDTO();
                                vehicleEventDTO.setVin(vin);
                                vehicleEventDTO.setXpuId("");
                                vehicleEventDTO.setOrderId(cruiseOrderId);
                                vehicleEventDTO.setEventKey("RT_xpu_vehicle_trace_upload");
                                vehicleEventDTO.setEventTime(System.currentTimeMillis());
                                Map<String,Object> attributes = new HashMap<>();
                                attributes.put("vin",vin);
                                attributes.put("order_id",vehicleEventDTO.getOrderId());
                                attributes.put("order_type","cruise_order");
                                attributes.put("timestamp",vehicleEventDTO.getEventTime());
                                attributes.put("current_main_status",OrderStatus.ORDER_ARRIVED_AT_CRUISE_DESTINATION);
                                attributes.put("current_sub_status","");
                                VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(vin)), VehiclePosition.class);
                                if(Objects.nonNull(vehiclePosition)){
                                    attributes.put("odometer_km",vehiclePosition.getTotalOdometer());
                                }else {
                                    attributes.put("odometer_km","");
                                }
                                vehicleEventDTO.setAttributes(attributes);
                                vehicleBuriedPointClient.sendVehicleEvent(vehicleEventDTO);
                                log.info("到达巡游终点,推送埋点:{}", orderId);
                            }
                        }
                    }else if(orderId.contains("TEST")){
                        //测试巡游单完成状态
                        XpTestOrder testOrder = testOrderClient.queryOrderById(Long.parseLong(orderId.substring(4))).getData();
                        if(testOrder.getOrderType() == 2){
                            XpVehicle xpVehicle = xpVehicleClient.queryById(testOrder.getVehicleId()).getData();
                            //响应消息
                            responseMessage(sequence, xpVehicle.getVehicleVin());
                            //测试巡游单处理逻辑
                            testOrderClient.updateOrderStatus(Long.parseLong(orderId.substring(4)), OrderStatusEnum.COMPLETED.getCode());
                            redisService.setCacheObject("TEST_ORDER_STATUS:" + orderId.substring(4), OrderStatusEnum.COMPLETED.getCode(), 24L, TimeUnit.HOURS);
                        }
                    }
                    break;
                case ORDER_PAUSED:
                    //订单暂停
@@ -802,56 +1295,51 @@
    public void buildPushOrderStatus(String orderId, OrderStatusEnum status, Long sequence){
        if(orderId.contains("XU")){
            //巡游单
            //响应消息
            responseMessage(sequence, "");
            //前往目的地
            if(OrderStatusEnum.IN_SERVICE.equals(status)){
            }
            //到达目的地
            if(OrderStatusEnum.COMPLETED.equals(status)){
                // 返程找到目前的订单 -》之前的订单 查询生成一个   正常巡游 找到下一个点位   若到达最后点位  则反向找点位  每次判断是否收车状态 是则不进行处理了
                // 找到这个订单
                R<XpCruiseOrder> cruiseOrder = xpCruiseOrderClient.getCruiseOrder(orderId);
                R<XpCruiseOrder> cruiseOrder = xpCruiseOrderClient.getCruiseOrder(Long.parseLong(orderId.substring(2)));
                if(cruiseOrder!=null){
                    XpCruiseOrder xpCruiseOrder = cruiseOrder.getData();
                    Long vehicleId = xpCruiseOrder.getVehicleId();
                    // 完成当前巡游单子 已完成
                    xpCruiseOrderClient.closeCruiseOrder(xpCruiseOrder.getVehicleVin());
                    xpCruiseOrderClient.completeCruiseOrder(Long.parseLong(orderId.substring(2)));
                    R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(vehicleId);
                    XpVehicle xpVehicle = xpVehicleR.getData();
                    //响应消息
                    responseMessage(sequence, xpVehicle.getVehicleVin());
                    // 运营中 继续执行
                    if(xpVehicle.getOperatingStatus()==1 && xpVehicle.getState()==0){
                        log.info("巡游单到达终点,继续执行下一笔巡游单");
                        // 创建新的巡游单子  判断是否为返程单子
                        if(xpCruiseOrder.getOrderType()==2){
                            R<XpCruiseOrder> lastOrder = xpCruiseOrderClient.getCruiseOrder(xpCruiseOrder.getLastOrderId());
                            XpCruiseOrder lastXpCruiseOrder = lastOrder.getData();
                        // 正常巡游 找到下一个点位   若到达最后点位  则反向找点位
                        // 起点
                        Double endLon = xpCruiseOrder.getEndLon();
                        Double endLat = xpCruiseOrder.getEndLat();
                        XpCruiseOrder newXpCruiseOrder = new XpCruiseOrder();
                        newXpCruiseOrder.setVehicleId(xpCruiseOrder.getVehicleId());
                        newXpCruiseOrder.setVehicleVin(xpCruiseOrder.getVehicleVin());
                        newXpCruiseOrder.setFleetId(xpCruiseOrder.getFleetId());
                        newXpCruiseOrder.setOrderType(1);
                        newXpCruiseOrder.setStartLat(endLat);
                        newXpCruiseOrder.setStartLon(endLon);
                        newXpCruiseOrder.setStartPointId(xpCruiseOrder.getEndPointId());
                        newXpCruiseOrder.setStartPointName(xpCruiseOrder.getEndPointName());
                        newXpCruiseOrder.setStatus(1);
                        newXpCruiseOrder.setLastOrderId(xpCruiseOrder.getId());
                            // 修改一下id 加一个一样的巡游单子
                            lastXpCruiseOrder.setId("XU"+ IdUtil.fastUUID());
                            lastXpCruiseOrder.setStatus(1);
                            xpCruiseOrderClient.addCruiseOrder(lastXpCruiseOrder);
                            RTTask task = new RTTask();
                            task.setOrder_id(lastXpCruiseOrder.getId());
                            task.setTask_id("MISSION_"+ IdUtil.fastUUID());
                            task.setTask_type(TaskType.CRUISE);
                            task.setStatus(TaskStatus.PENDING);
                            SnowFlake snowFlake = new SnowFlake(0, 0);
                            snowFlake.withStartTimestamp(1420041600000L);
                            long sequence1 = snowFlake.nextId();
                            xpuUtil.cloudCreateOrder(task, xpVehicle.getVehicleVin(),sequence1);
                        }else if(xpCruiseOrder.getOrderType()==1){
                           // 正常巡游 找到下一个点位   若到达最后点位  则反向找点位 TODO v
                        // 通过车找终点id
                        CruisePointDto cruisePointDto = new CruisePointDto();
                        cruisePointDto.setNewXpCruiseOrder(newXpCruiseOrder);
                        cruisePointDto.setVehicleId(xpCruiseOrder.getVehicleId());
                        cruisePointDto.setPointId(newXpCruiseOrder.getStartPointId());
                        cruisePointDto.setOrderReverse(xpCruiseOrder.getOrderReverse());
                        R<XpCruiseOrder> cruisePoint = xpCruisePlanClient.getCruisePoint(cruisePointDto);
                        if(cruisePoint!=null){
                            xpCruiseOrderClient.addCruiseOrder(cruisePoint.getData());
                        }
                    }
                }
            }
        }else{
@@ -865,7 +1353,7 @@
            //构建推送消息
            Map<String, Object> params = new HashMap<>();
            Map<String, Object> content = new HashMap<>();
            content.put("orderId", orderId);
            content.put("orderId", orderId.toString());
            content.put("status", status.getCode());
            params.put("type", PushMessageTypeEnum.ORDER_STATUS.getDesc());
            params.put("content", JSONObject.toJSONString(content));
@@ -876,10 +1364,85 @@
            dto.setAppUserId(appUserId + "");
            dto.setMessage(message);
            R<String> stringR = xpPushMessageClient.sendStatus(dto);
            if (R.isError(stringR)) {
                log.error("推送消息失败:{}", stringR.getMsg());
            //推送失败,重试3次
            if(stringR.getCode() != Constants.SUCCESS){
                ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
                executor.execute(() -> {
                    for (int i = 0; i < 3; i++) {
                        R<String> stringR1 = xpPushMessageClient.sendStatus(dto);
                        if(stringR1.getCode() == Constants.SUCCESS){
                            break;
                        }
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                        log.info("推送订单状态消息失败:{} {} {}", stringR1.getMsg(), JSON.toJSONString(dto), xpOrder.getOrderNumber());
                    }
                });
            }
        }
    }
    private JSONObject getReassignCancelContext(String orderId) {
        if (StringUtils.isEmpty(orderId)) {
            return null;
        }
        Object cacheObject = redisService.getCacheObject(REASSIGN_CANCEL_CONTEXT_PREFIX + orderId);
        if (cacheObject == null) {
            return null;
        }
        return JSON.parseObject(cacheObject.toString());
    }
    private JSONObject resolveReassignCancelContext(String orderId, OrderStatusInfo orderStatusInfo) {
        if (OrderStateChangeSource.ORDER_STATE_CHANGE_SOURCE_VEHICLE != orderStatusInfo.getChangeSource()) {
            return null;
        }
        JSONObject cancelContext = getReassignCancelContext(orderId);
        if (cancelContext == null) {
            return null;
        }
        if (CancelOrderSceneEnum.REASSIGN_OLD_VEHICLE != CancelOrderSceneEnum.fromCode(
                cancelContext.getString("cancelScene"))) {
            return null;
        }
        R<XpOrder> orderResult = xpOrderClient.queryOrderById(Long.parseLong(orderId));
        XpOrder xpOrder = orderResult == null ? null : orderResult.getData();
        if (xpOrder == null) {
            log.warn("改派取消回调识别失败,订单不存在,orderId: {}, context: {}", orderId, cancelContext);
            return null;
        }
        Long newVehicleId = cancelContext.getLong("newVehicleId");
        Integer currentStatus = xpOrder.getStatus();
        boolean vehicleMatched = Objects.nonNull(newVehicleId) && Objects.equals(newVehicleId, xpOrder.getVehicleId());
        boolean statusMatched = Objects.nonNull(currentStatus) && currentStatus > 0 && currentStatus < 8;
        if (vehicleMatched && statusMatched) {
            return cancelContext;
        }
        log.info("改派取消回调未命中专用上下文,orderId: {}, currentVehicleId: {}, newVehicleId: {}, currentStatus: {}",
                orderId, xpOrder.getVehicleId(), newVehicleId, currentStatus);
        return null;
    }
    private String resolveReassignCancelResponseVin(JSONObject cancelContext) {
        if (cancelContext == null) {
            return null;
        }
        String oldVehicleVin = cancelContext.getString("oldVehicleVin");
        if (StringUtils.isNotEmpty(oldVehicleVin)) {
            return oldVehicleVin;
        }
        Long oldVehicleId = cancelContext.getLong("oldVehicleId");
        if (Objects.isNull(oldVehicleId)) {
            return null;
        }
        R<XpVehicle> vehicleResult = xpVehicleClient.queryById(oldVehicleId);
        XpVehicle xpVehicle = vehicleResult == null ? null : vehicleResult.getData();
        return xpVehicle == null ? null : xpVehicle.getVehicleVin();
    }
    /**
@@ -893,20 +1456,15 @@
     */
    public void cloudPushNavigationInfo(String requestId, String routeId, String routeDataContent, String orderType, String orderId, String vin, String xpuId) {
        //组装报文,将routeDateContent信息推送到XPU
        RestoreNavigationData navigationData = new RestoreNavigationData();
        navigationData.setRoute_id(routeId);
        navigationData.setRequest_id(requestId);
        navigationData.setContent(routeDataContent);
        navigationData.setTimestamp(System.currentTimeMillis());
        RestoreNavigationData.Builder navigationDataBuilder = RestoreNavigationData.newBuilder();
        navigationDataBuilder.setRouteId(routeId);
        navigationDataBuilder.setRequestId(requestId);
        navigationDataBuilder.setContent(routeDataContent);
        navigationDataBuilder.setTimestamp(System.currentTimeMillis());
        long sequence = snowflake.nextId();
        // 处理数据
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("event", SystemEventType.PUSH_NAVIGATION);
        jsonObject.put("orderType", orderType);
        jsonObject.put("orderId", orderId);
        jsonObject.put("vin", vin);
        redisTemplate.opsForValue().set(sequence, jsonObject.toJSONString(),30, TimeUnit.MINUTES);
        xpuUtil.cloudPushNavigation(navigationData, xpuId, sequence);
        log.info("开始推送导航数据 {}", orderId);
        MqttPublishDto mqttPublishDto = xpuUtil.cloudPushNavigation(navigationDataBuilder.build(), xpuId, sequence);
        log.info("推送导航的响应消息,{}", JSON.toJSONString(mqttPublishDto));
    }
}