puzhibing
2026-05-12 08cc6d5cf7e93b75cfabe7dcc2aeaa9afa1117eb
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java
@@ -3,31 +3,32 @@
import cn.hutool.core.lang.Snowflake;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.collect.ImmutableMap;
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.OrderMissionClient;
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.operation.XpSystemSettingClient;
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.operation.XpSystemSetting;
import com.xiaopeng.api.model.order.XpCruiseOrder;
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.api.model.order.XpTestOrder;
@@ -38,16 +39,23 @@
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.job.base.QuartzManager;
import com.xiaopeng.automaticPilot.job.base.TimeJobType;
import com.xiaopeng.automaticPilot.job.jobs.OrderExceptionJob;
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.DateUtils;
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.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.MongoTemplate;
@@ -59,6 +67,7 @@
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
@@ -71,6 +80,9 @@
@Slf4j
@Service
public class KafkaConsumerService {
    private static final String REASSIGN_CANCEL_CONTEXT_PREFIX = "REASSIGN_CANCEL_CONTEXT:";
    private static final String CANCEL_ORDER_CONTEXT_PREFIX = "CANCEL_ORDER_CONTEXT:";
    @Resource
    private XpMapClient xpMapClient;
@@ -114,13 +126,25 @@
    @Value("${robotaxi.appId:xp_robotaxi_api}")
    private String appid;
    @Value("${automatic.content.waittime:20000}")
    private Long waittime;
    @Resource
    private XpTaskClient xpTaskClient;
    @Resource
    private VehicleBuriedPointClient vehicleBuriedPointClient;
    @Value("${xpu.res.ping.enable: true}")
    private boolean xpuResPingEnable;
    @Resource
    private XpTestOrderClient testOrderClient;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private XpSystemSettingClient systemSettingClient;
    private static final JsonFormat.Printer jsonPrinter = JsonFormat.printer()
            .printingEnumsAsInts()
@@ -196,7 +220,7 @@
            switch (cmd) {
                case SYSTEM_STATUS_XPU:
                    log.info("XPU发布系统运行状态 (XPU→云端):{}", message);
                    systemStatusXpu(msgContent);
                    systemStatusXpu(cmd, msgContent);
                    systemStatusXpuAndReassign(msgContent);
                    break;
                case XPU_NAVIGATION_REQUEST:
@@ -208,6 +232,7 @@
                    break;
                case PULLOVER_STATUS_EVENT:
                    log.info("靠边停车状态(XPU→云端)(XPU→座舱):{}", message);
                    pulloverStatusEvent(msgContent);
                    break;
                case DRIVING_MODE_UPDATE_EVENT:
                    log.info("驾驶模式变化(XPU→云端)(XPU→座舱):{}", message);
@@ -220,7 +245,7 @@
                    break;
                case ORDER_STATE_UPDATE_EVENT:
                    log.info("订单状态变化(XPU→云端)(XPU→座舱):{}", message);
                    orderStateUpdateEvent(msgContent);
                    orderStateUpdateEvent(cmd, msgContent);
                    break;
                case POINT_ARRIVAL_STATUS_EVENT:
                    log.info("到达目标点状态(XPU→云端)(XPU→座舱):{}", message);
@@ -250,6 +275,12 @@
                case ORDER_STATE_UPDATE_TO_CDU_EVENT:
                    log.info("更新订单状态到CDU (XPU→云端):{}", message);
                    break;
                case ORDER_NEAR_DESTINATION_EVENT:
                    log.info("车辆即将到达订单终点 (XPU→云端):{}", message);
//                    if(orderId.contains("XU")){
//                        buildPushOrderStatus(orderId, OrderStatusEnum.COMPLETED, sequence);
//                    }
                    break;
                default:
                    log.info("消息不在处理范围内,忽略:{}", message);
            }
@@ -268,7 +299,12 @@
                RtTaskListResponse response = msgContent.getRtTaskListResponse();
                try {
                    log.info("云端下发订单操作的响应消息 (XPU→云端):{}", jsonPrinter.print(response));
                    Object sequence = redisService.getCacheObject("CREATE_ORDER:" + response.getResults().getOrderId());
                    RtTaskResult rtTaskResult = response.getResults(0);
                    if (rtTaskResult.getStatus() != TaskResultStatus.ACCEPTED) {
                        log.error("订单操作失败,orderId {} taskId {} 错误码 {}", rtTaskResult.getOrderId(), rtTaskResult.getTaskId(), rtTaskResult.getStatus());
                        return;
                    }
                    Object sequence = redisService.getCacheObject("CREATE_ORDER:" + response.getResults(0).getOrderId());
                    if(sequence!=null){
                        JSONObject jsonObject = JSON.parseObject(sequence.toString());
                        String orderId = jsonObject.getString("orderId");
@@ -285,7 +321,7 @@
                        dto.setXpVehicleVin(vin);
                        dto.setOrderType(orderType);
                        xpOrderClient.popOrder(dto);
                        log.info("订单状态更新:{}", response.getResults().getOrderId());
                        log.info("订单状态更新:{}", response.getResults(0).getOrderId());
                    }
                } catch (InvalidProtocolBufferException e) {
                    log.error("Failed to print RtTaskListResponse: {}", response, e);
@@ -305,7 +341,7 @@
     *
     * @param msgContent
     */
    public void systemStatusXpu(MsgContent msgContent) {
    public void systemStatusXpu(RTCmdType cmd, MsgContent msgContent) {
        //开始处理消息对应的业务逻辑
        SystemRuntimeStatus systemRuntimeStatus = msgContent.getSystemRuntimeStatus();
        //获取实时位置
@@ -319,90 +355,133 @@
        VehicleStaticInfo staticInfo = systemRuntimeStatus.getVehicleStatus().getStaticInfo();
        String xpuId = staticInfo.getXpuId();
        XpVehicle xpVehicle = xpVehicleClient.findByVehicleXpuId(xpuId).getData();
        if(null == xpVehicle){
            log.info("XPUID查询车辆无效 {}", xpuId);
            return;
        }
        String vin = xpVehicle.getVehicleVin();
        //先响应消息
        long sequence = msgContent.getHeader().getSequence();
        responseMessage(sequence, vin);
        //保存车辆实时位置到redis
        if(0 != longitude && 0 != latitude){
            redisTemplate.opsForGeo().add("vehiclePosition:" + vin, new Point(longitude, latitude), vin);
        if (xpuResPingEnable) {
            responseMessage(cmd, sequence, vin);
        }
        VehicleStatus vehicleStatus = systemRuntimeStatus.getVehicleStatus();
        OrderStatusInfo runningOrderStatusInfo = systemRuntimeStatus.getRunningOrderStatusInfo();
        String order_id = runningOrderStatusInfo.getOrderId();
        //车辆动态信息
        VehicleDynamicStatus dynamicStatus = vehicleStatus.getDynamicStatus();
        Long orderId = null;
        Integer hasOrder = 0;
        if (StringUtils.isNotEmpty(order_id)) {
            if (order_id.contains("XU")) {
                hasOrder = 1;
                orderId = Long.parseLong(order_id.substring(2));
            } else if(order_id.contains("TEST")) {
                orderId = Long.parseLong(order_id.substring(4));
            }else{
                orderId = Long.parseLong(order_id);
        RLock lock = redissonClient.getLock("PUSH_ORDER_ROUTE_LOCK:" + order_id);
        try {
            boolean tryLock = lock.tryLock(10, 10, TimeUnit.SECONDS);
            if (!tryLock) {
                log.info("获取锁失败,订单ID:{} 无法完成车辆实时位置的逻辑处理。", order_id);
                return;
            }
        }
        //保存车辆实时信息到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);
            //车辆动态信息
            VehicleDynamicStatus dynamicStatus = vehicleStatus.getDynamicStatus();
            Long orderId = null;
            Integer hasOrder = 0;
            if (StringUtils.isNotEmpty(order_id)) {
                if (order_id.contains("XU")) {
                    hasOrder = 1;
                    orderId = Long.parseLong(order_id.substring(2));
                } else if(order_id.contains("TEST")) {
                    orderId = Long.parseLong(order_id.substring(4));
                }else{
                    orderId = Long.parseLong(order_id);
                }
                //存储历史轨迹
                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);
            }
            //保存车辆实时信息到mongodb
            if(0 != longitude && 0 != latitude){
                //缓存车辆历史定位,用户辅助获取导航抓路用
//            List<HistoryPointDto> history = redisService.getCacheList("VEHICLE_HISTORY_POINT_LIST:" + xpVehicle.getId());
//            if(history.size() >= 10){
//                history = new ArrayList<>(history.subList(history.size() - 9, history.size()));
//            }
//            HistoryPointDto historyPointDto = new HistoryPointDto();
//            historyPointDto.setLocation(longitude + "," + latitude);
//            historyPointDto.setLocateTime(System.currentTimeMillis() + "");
//            historyPointDto.setAccuracy(naviPose.getPosAcc());
//            historyPointDto.setDirection(new BigDecimal(course).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
//            historyPointDto.setSpeed(dynamicStatus.getSpeed());
//            historyPointDto.setHeight(naviPose.getAlt());
//            history.add(historyPointDto);
//            redisService.setCacheList("VEHICLE_HISTORY_POINT_LIST:" + xpVehicle.getId(), history);
                redisTemplate.opsForGeo().add("vehiclePosition:" + vin, new Point(longitude, latitude), vin);
                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);
                }
                //调用推送服务接口,给乘客推送剩余轨迹和里程时长
                RtTripInfo rtTripInfo = systemRuntimeStatus.getRunningOrderStatusInfo().getRtTripInfo();
                if (null != orderId && !order_id.contains("XU")) {
                    PushOrderRouteDTO dto = new PushOrderRouteDTO();
                    dto.setMessageType(PushMessageTypeEnum.ORDER_ROUTE.getDesc());
                    dto.setOrderId(orderId);
                    dto.setRouteType(1);
                    dto.setLongitude(longitude);
                    dto.setLatitude(latitude);
                    dto.setSpeed(dynamicStatus.getSpeed());
                    if (rtTripInfo.hasCurrentTask() && rtTripInfo.getCurrentTask().hasNaviProgressInfo()) {
                        dto.setDuration(rtTripInfo.getCurrentTask().getNaviProgressInfo().getRouteRemainTime());
                        dto.setDistance(rtTripInfo.getCurrentTask().getNaviProgressInfo().getRouteRemainDist());
                        dto.setDirection(course.intValue());
                    }
                    OrderTrajectoryVo orderTrajectory = new OrderTrajectoryVo();
                    orderTrajectory.setOrderId(orderId);
                    orderTrajectory.setLocation(longitude + "," + latitude);
                    orderTrajectory.setDirection(dto.getDirection());
                    orderTrajectory.setSpeed((double) dynamicStatus.getSpeed());
                    orderTrajectory.setLocatetime(System.currentTimeMillis());
                    orderTrajectory.setCreateTime(new Date());
                    //只有乘客订单需要推送剩余导航数据
                    if(!order_id.contains("TEST")){
                        xpPushMessageClient.pushOrderRoute(dto);//存储历史轨迹
                        // 给连环派单的用户推送
                        String json = redisService.getCacheObject(CacheConstants.nextOrder(order_id));
                        if (StringUtils.isNotEmpty(json)){
                            JSONObject jsonObject = JSON.parseObject(json);
                            dto.setOrderId(jsonObject.getLong("orderId"));
                            dto.setEndLongitude(jsonObject.getDouble("endLongitude"));
                            dto.setEndLatitude(jsonObject.getDouble("endLatitude"));
                            xpPushMessageClient.pushOrderRoute(dto);
                        }
                        xpOrderClient.saveVehicleLocation(orderTrajectory);
                    }else{
                        testOrderClient.saveVehicleLocation(orderTrajectory);
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
@@ -422,6 +501,7 @@
        GearLevel gearLevel = systemRuntimeStatus.getVehicleStatus().getDynamicStatus().getGearLevel();
        int value = gearLevel.getNumber();
        redisService.setCacheObject(CacheConstants.GEAR_LEVEL + systemRuntimeStatus.getVehicleStatus().getStaticInfo().getXpuId(), value);
        log.info("车辆挡位:{} {}", CacheConstants.GEAR_LEVEL + systemRuntimeStatus.getVehicleStatus().getStaticInfo().getXpuId(), value);
        // 判断是否为故障状态
        XpVehicle vehicle = null;
        if (abnormalReason == AbnormalReason.FAULT) {
@@ -441,6 +521,7 @@
                }
            }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) {
@@ -452,14 +533,20 @@
                    log.info("车辆故障,车辆状态修改0 {}", vehicle.getPlateNumber());
                }
            }else {
                //正常订单
                //正常订单 车辆故障
                /*
                1.将订单信息车辆的 查询出来 设置故障状态
                2.解除用户和车的关系
                3.如果是 接驾中的车需要重新派车
                4.如果是行驶中的车需要将订单结束 计算金额
                 */
                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.setState(0);//车辆接单状态 1接单中 0空闲
                    vehicle1.setOperatingStatus(4);//运营状态 1运营中 2维修中 3已收车 4车辆异常
                    vehicle1.setId(vehicle.getId());
                    xpVehicleClient.updateVehicleById(vehicle1);
                    log.info("车辆故障,车辆状态修改0 {}", vehicle.getPlateNumber());
@@ -471,18 +558,28 @@
                    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);
                //status 状态 0=已取消,1=待接单,2=待出发,3=接驾中,4=待客上车,5=乘客已上车,6=服务中,7=待客下车,8=待付款,9=待评价,10=已完成
                List<Integer> notDrive = new ArrayList<Integer>(){{ //未行驶的情况下订单故障状态点 status=2、3、4、5
                    add(OrderStatusEnum.READY_DEPART.getCode());add(OrderStatusEnum.PICK_UP.getCode());
                    add(OrderStatusEnum.PICK_UP_GUESTS.getCode());add(OrderStatusEnum.PASSENGER_BOARDED.getCode());
                }};
                if(xpOrder.getStatus().equals(OrderStatusEnum.IN_SERVICE.getCode()) ){ //6=服务中  在行驶中 修改订单-已完成  需要处理订单金额
                    //行驶中车辆异常,订单状态修改- 修改状态=7 再修改 金额 再将状态修改成8
                    xpOrderClient.carAbnormalUpdateOrderStatus(Long.parseLong(orderId));
                }else if(notDrive.contains(xpOrder.getStatus())){//在接驾中 车辆出现故障 重新派单 改派
                    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(xpOrder.getStartLon());
                    reassignOrderDTO.setLatitude(xpOrder.getStartLat());
                    reassignOrderClient.reassignOrder(reassignOrderDTO);
                }
            }
            //添加车辆异常任务和发送消息
            xpTaskClient.saveVehicleAccidentError(vehicle.getId());
@@ -514,7 +611,7 @@
     */
    public void xpuNavigationRequest(MsgContent msgContent) {
        //开始处理消息对应的业务逻辑
        NavigationRequest naviRequest = msgContent.getNavigationRequset();
        NavigationRequest naviRequest = msgContent.getNavigationRequest();
        String requestId = naviRequest.getRequestId();
        String orderId = naviRequest.getOrderId();
        String taskId = naviRequest.getTaskId();
@@ -527,15 +624,15 @@
                break;
            case ROUTE_TO_PICKUP:
                log.info("驶往上车点的行程 {}", orderId);
                buildNaviRequest(requestId, orderId, orderPhase, msgContent.getHeader().getSequence());
                buildNaviRequest(requestId, orderId, orderPhase, msgContent.getHeader().getSequence(), taskId);
                break;
            case ROUTE_TO_DESTINATION:
                log.info("驶往下车点的行程 {}", orderId);
                buildNaviRequest(requestId, orderId, orderPhase, msgContent.getHeader().getSequence());
                buildNaviRequest(requestId, orderId, orderPhase, msgContent.getHeader().getSequence(), taskId);
                break;
            case ROUTE_TO_CRUISE:
                log.info("巡游阶段路线 {}", orderId);
                buildNaviRequest(requestId, orderId, orderPhase, msgContent.getHeader().getSequence());
                buildNaviRequest(requestId, orderId, orderPhase, msgContent.getHeader().getSequence(), taskId);
                break;
        }
    }
@@ -549,7 +646,7 @@
    public void navigationDeviationEvent(MsgContent msgContent) {
        //开始处理消息对应的业务逻辑
        NavigationDeviationEvent deviationEvent = msgContent.getNaviDeviationEvent();
        String requestId = deviationEvent.getNavigationDeviationMessage().getNaviRecalcRequestSeq() + "";
        String requestId = deviationEvent.getNavigationDeviationMessage().getRequestId() + "";
        //导航id
        String routeID = "";
        Long vehicleId = null;
@@ -564,97 +661,216 @@
        //订单类型  1:乘客订单,2=巡游订单
        LonLatDto destination = new LonLatDto();
        LonLatDto origin = new LonLatDto();
        RouteVo routeVo = null;
        String key = "";
        Float speed = 0f;
        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("获取订单线路和运费失败");
        //添加redis锁,用于在发生偏航后重新规划线路与正常推送剩余导航数据之间的冲突
        RLock lock = redissonClient.getLock("PUSH_ORDER_ROUTE_LOCK:" + orderId);
        try {
            boolean tryLock = lock.tryLock(10, 10, TimeUnit.SECONDS);
            if(!tryLock){
                log.info("获取锁失败,订单ID:{} 无法完成偏航后的逻辑处理。", orderId);
                return;
            }
            RouteVo routeVo = routeVoR.getData();
            routeID = routeVo.getRouteID();
            if (orderId.contains("XU")) {
                orderType = OrderType.CRUISE_ORDER;
                R<XpCruiseOrder> cruiseOrder = xpCruiseOrderClient.getCruiseOrder(Long.parseLong(orderId.substring(2)));
                XpCruiseOrder xpCruiseOrder = cruiseOrder.getData();
            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();
            //驶往上车点的行程
            if (3 == xpOrder.getStatus()) {
                redisService.deleteObject("ORDER_NAVIGATION_START_DATA:" + xpOrder.getAppUserId());
                //查询司机当前位置到起点的线路
                //构建导航数据给到车端
                origin.setLongitude(longitude);
                origin.setLatitude(latitude);
                destination.setLongitude(xpOrder.getStartLon());
                destination.setLatitude(xpOrder.getStartLat());
                destination.setLongitude(xpCruiseOrder.getEndLon());
                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(1);
                dto.setRouteType(3);
                R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto);
                if (200 != routeVoR.getCode()) {
                    throw new RuntimeException("获取订单线路和运费失败");
                }
                RouteVo routeVo = routeVoR.getData();
                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("获取订单线路和运费失败");
                vehicleId = xpCruiseOrder.getVehicleId();
            } 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();
                VehiclePosition vehiclePosition = mongoTemplate.findOne(Query.query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class);
                if(null != vehiclePosition){
                    speed = vehiclePosition.getSpeed();
                }
                RouteVo routeVo = routeVoR.getData();
                routeID = routeVo.getRouteID();
                //缓存导航数据,用于后面的逻辑中给乘客端推送导航数据
                redisService.setCacheObject("ORDER_NAVIGATION_END_DATA:" + xpOrder.getAppUserId(), JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS);
                //区分测试单和测试巡游单
                if(1 == testOrder.getOrderType()){
                    orderType = OrderType.TEST_ORDER;
                    //驶往上车点的行程
                    if (3 == testOrder.getStatus()) {
                        //查询司机当前位置到起点的线路
                        origin.setLongitude(longitude);
                        origin.setLatitude(latitude);
                        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(1);
                        dto.setVehicleId(testOrder.getVehicleId());
                        R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto);
                        if (200 != routeVoR.getCode()) {
                            throw new RuntimeException("获取订单线路和运费失败");
                        }
                        routeVo = routeVoR.getData();
                        routeID = routeVo.getRouteID();
                        key = "TEST_ORDER_NAVIGATION_START_DATA:" + testOrder.getVehicleId();
                    }
                    //驶往下车点的行程
                    if (6 == testOrder.getStatus()) {
                        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(2);
                        R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto);
                        if (200 != routeVoR.getCode()) {
                            throw new RuntimeException("获取订单线路和运费失败");
                        }
                        routeVo = routeVoR.getData();
                        routeID = routeVo.getRouteID();
                        key = "TEST_ORDER_NAVIGATION_END_DATA:" + testOrder.getVehicleId();
                    }
                }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("获取订单线路和运费失败");
                    }
                    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();
                VehiclePosition vehiclePosition = mongoTemplate.findOne(Query.query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class);
                if(null != vehiclePosition){
                    speed = vehiclePosition.getSpeed();
                }
                //驶往上车点的行程
                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);
                    dto.setVehicleId(xpOrder.getVehicleId());
                    R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto);
                    if (200 != routeVoR.getCode()) {
                        throw new RuntimeException("获取订单线路和运费失败");
                    }
                    routeVo = routeVoR.getData();
                    routeID = routeVo.getRouteID();
                    key = "ORDER_NAVIGATION_START_DATA:" + xpOrder.getAppUserId();
                }
                //驶往下车点的行程
                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 = routeVoR.getData();
                    routeID = routeVo.getRouteID();
                    key = "ORDER_NAVIGATION_END_DATA:" + xpOrder.getAppUserId();
                }
                vehicleId = xpOrder.getVehicleId();
            }
            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获取车端需要的导航数据失败");
            //直接响应回最新导航数据
            if(StringUtils.isNotEmpty(routeID)){
                //推送小程序新的导航数据
                if(orderType.equals(OrderType.USER_ORDER)){
                    //缓存导航数据,用于后面的逻辑中给乘客端推送导航数据
                    redisService.setCacheObject(key, JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS);
                    PushOrderRouteDTO dto = new PushOrderRouteDTO();
                    dto.setOrderId(Long.parseLong(orderId));
                    dto.setRouteType(1);
                    dto.setLongitude(longitude);
                    dto.setLatitude(latitude);
                    dto.setSpeed(speed);
                    if (null != routeVo) {
                        dto.setDuration(null == routeVo.getDuration() ? 0 : routeVo.getDuration().doubleValue());
                        dto.setDistance(null == routeVo.getDistance() ? 0 : routeVo.getDistance().doubleValue());
                        dto.setDirection(null == routeVo.getDirection() ? 0 : routeVo.getDirection().intValue());
                    }
                    dto.setMessageType(PushMessageTypeEnum.ORDER_UPDATE_LINE.getDesc());
                    xpPushMessageClient.pushOrderRoute(dto);
                    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("开始下发XPU导航偏离后新的导航数据:" + orderId);
                //构建响应导航数据给车端
                cloudPushNavigationInfo(requestId, routeID, stringR.getData(), orderType, orderId, xpVehicle.getVehicleVin(), xpVehicle.getXpuId(), taskId);
                log.info("完成下发XPU导航偏离后新的导航数据:" + orderId);
            }
            //构建响应导航数据给车端
            cloudPushNavigationInfo(requestId, routeID, stringR.getData(), orderType, orderId, xpVehicle.getVehicleVin(), xpVehicle.getXpuId());
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
@@ -665,7 +881,7 @@
     * @param orderId
     * @param orderPhase
     */
    public void buildNaviRequest(String requestId, String orderId, OrderPhase orderPhase, Long sequence) {
    public void buildNaviRequest(String requestId, String orderId, OrderPhase orderPhase, Long sequence, String taskId) {
        //订单类型  1:乘客订单,2=巡游订单
        LonLatDto destination = new LonLatDto();
        LonLatDto origin = new LonLatDto();
@@ -702,71 +918,101 @@
                vehicleId = xpCruiseOrder.getVehicleId();
            }
        } else if(orderId.contains("TEST")){
            orderType = OrderType.TEST_ORDER;
            //正常单
            R<XpTestOrder> xpOrderR = testOrderClient.queryOrderById(Long.parseLong(orderId.substring(4)));
            if (200 != xpOrderR.getCode()) {
                throw new RuntimeException("订单不存在 " + orderId);
            }
            XpTestOrder xpOrder = xpOrderR.getData();
            XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData();
            //驶往上车点的行程
            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("车辆位置信息不存在");
            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);
                        dto.setVehicleId(testOrder.getVehicleId());
                        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();
                    }
                }
                //查询司机当前位置到起点的线路
                origin.setLongitude(vehiclePosition.getPoint().getX());
                origin.setLatitude(vehiclePosition.getPoint().getY());
                destination.setLongitude(xpOrder.getStartLon());
                destination.setLatitude(xpOrder.getStartLat());
                //驶往下车点的行程
                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();
                    }
                }
                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("TEST_ORDER_NAVIGATION_START_DATA:" + xpOrder.getVehicleId(), JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS);
            }
            //驶往下车点的行程
            if (orderPhase.equals(OrderPhase.ROUTE_TO_DESTINATION)) {
                //直接取缓存中的导航数据推送给车端和乘客
                Object cacheObject = redisService.getCacheObject("TEST_ORDER_NAVIGATION_END_DATA:" + xpOrder.getVehicleId());
                if(null == cacheObject){
                    //没有缓存数据,重新规划线路
                    //查询起点到终点的线路
                    origin.setLongitude(xpOrder.getStartLon());
                    origin.setLatitude(xpOrder.getStartLat());
                    destination.setLongitude(xpOrder.getEndLon());
                    destination.setLatitude(xpOrder.getEndLat());
            }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));
                    dto.setOrderId(Long.parseLong(orderId.substring(4)));
                    dto.setOrigin(origin);
                    dto.setDestination(destination);
                    dto.setRouteType(2);
                    dto.setRouteType(3);
                    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:" + xpOrder.getVehicleId(), JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS);
                }else{
                    RouteVo routeVo = JSON.parseObject(cacheObject.toString(), RouteVo.class);
                    routeID = routeVo.getRouteID();
                }
            }
            vehicleId = xpOrder.getVehicleId();
            vehicleId = testOrder.getVehicleId();
        }else{
            orderType = OrderType.USER_ORDER;
            //正常单
@@ -778,31 +1024,37 @@
            XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData();
            //驶往上车点的行程
            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("车辆位置信息不存在");
                }
                redisService.deleteObject("ORDER_NAVIGATION_START_DATA:" + xpOrder.getAppUserId());
                //查询司机当前位置到起点的线路
                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);
                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);
                    OrderRouteAndFareDto dto = new OrderRouteAndFareDto();
                    dto.setOrderId(Long.parseLong(orderId));
                    dto.setOrigin(origin);
                    dto.setDestination(destination);
                    dto.setRouteType(1);
                    dto.setVehicleId(xpOrder.getVehicleId());
                    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)) {
@@ -845,7 +1097,7 @@
            }
            log.info("根据导航ID获取车端需要的导航数据 订单 {} 导航数据 {}", orderId, stringR.getData());
            //构建导航下发请求对象
            cloudPushNavigationInfo(requestId, routeID, stringR.getData(), orderType, orderId, xpVehicle.getVehicleVin(), xpVehicle.getXpuId());
            cloudPushNavigationInfo(requestId, routeID, stringR.getData(), orderType, orderId, xpVehicle.getVehicleVin(), xpVehicle.getXpuId(), taskId);
        }
    }
@@ -903,21 +1155,21 @@
    /**
     * 构建响应消息
     */
    public void responseMessage(Long request_seq, String vin) {
    public void responseMessage(RTCmdType cmd, Long request_seq, String vin) {
        ResponseMessage.Builder responseMessageBuilder = ResponseMessage.newBuilder();
        responseMessageBuilder.setRequestSeq(request_seq);
        responseMessageBuilder.setCode(StatusCode.OK);
        responseMessageBuilder.setTimestamp(System.currentTimeMillis());
        xpuUtil.responseMessage(responseMessageBuilder.build(), vin);
        xpuUtil.responseMessage(cmd, responseMessageBuilder.build(), vin);
    }
    @Resource OrderMissionClient orderMissionClient;
    /**
     * 订单状态更新事件
     * @param msgContent
     */
    public void orderStateUpdateEvent(MsgContent msgContent) {
    public void orderStateUpdateEvent(RTCmdType cmd, MsgContent msgContent) {
        //先响应消息
        long sequence = msgContent.getHeader().getSequence();
        //开始处理消息对应的业务逻辑
@@ -939,8 +1191,8 @@
                        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());
                            buildPushOrderStatus(cmd, orderId, OrderStatusEnum.READY_DEPART, sequence);
                            xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.READY_DEPART.getCode(), false);
                        }
                    }
                    break;
@@ -954,8 +1206,8 @@
                        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());
                            buildPushOrderStatus(cmd, orderId, OrderStatusEnum.PICK_UP, sequence);
                            xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.PICK_UP.getCode(), false);
                        }
                    }
                    break;
@@ -969,8 +1221,8 @@
                        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());
                            buildPushOrderStatus(cmd, orderId, OrderStatusEnum.PICK_UP_GUESTS, sequence);
                            xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.PICK_UP_GUESTS.getCode(), false);
                        }
                    }
                    break;
@@ -980,8 +1232,8 @@
                        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());
                            buildPushOrderStatus(cmd, orderId, OrderStatusEnum.PASSENGER_BOARDED, sequence);
                            xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.PASSENGER_BOARDED.getCode(), false);
                        }
                    }
                    break;
@@ -991,8 +1243,8 @@
                        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());
                            buildPushOrderStatus(cmd, orderId, OrderStatusEnum.IN_SERVICE, sequence);
                            xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.IN_SERVICE.getCode(), false);
                        }
                    }
                    break;
@@ -1006,18 +1258,14 @@
                        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());
                            buildPushOrderStatus(cmd, orderId, OrderStatusEnum.SEE_OFF_GUESTS, sequence);
                            xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.SEE_OFF_GUESTS.getCode(), false);
                        }
                    }
                    break;
                case ORDER_DROPOFF_COMPLETED:
                    //下车完成,不需要处理状态,由后续的乘客主动触发或者定时任务触发
                    log.info("乘客已下车,不做任何处理:{}", orderId);
//                    if(!orderId.contains("XU")){
//                        buildPushOrderStatus(orderId, OrderStatusEnum.APPROVAL_REJECTION, sequence);
//                        xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.APPROVAL_REJECTION.getCode());
//                    }
                    break;
                case ORDER_COMPLETED:
                    //已完成
@@ -1059,17 +1307,42 @@
                case ORDER_CANCELLED:
                    //已取消
                    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(orderId, reassignCancelContext);
                            if (StringUtils.isNotEmpty(responseVin)) {
                                responseMessage(cmd, sequence, responseVin);
                            } else {
                                log.warn("改派旧车取消回调未找到响应VIN,orderId: {}, taskId: {}, context: {}",
                                        orderId, taskId, reassignCancelContext);
                            }
                            return;
                        }
                        if(orderId.contains("TEST")){
                            //判断订单状态,已经取消的不作处理
                            Object cacheObject = redisService.getCacheObject("ORDER_STATUS:" + orderId.substring(4));
                            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;
                            }
                            //行程中取消订单,按照行程结束处理
                            testOrderClient.updateOrderStatus(Long.parseLong(orderId.substring(4)), OrderStatusEnum.SEE_OFF_GUESTS.getCode());
                            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);
@@ -1079,16 +1352,50 @@
                                    return;
                                }
                            }
                            //行程中取消订单,按照行程结束处理
                            buildPushOrderStatus(orderId, OrderStatusEnum.SEE_OFF_GUESTS, sequence);
                            xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.SEE_OFF_GUESTS.getCode());
                            XpOrder xpOrder = xpOrderClient.queryOrderById(Long.parseLong(orderId)).getData();
                            if(xpOrder.getStatus() == 0 || xpOrder.getStatus() >= 8){
                                return;
                            }
                            List<Integer>  xczqx = new ArrayList<Integer>(){{
                                add(OrderStatusEnum.IN_SERVICE.getCode());//服务中
                                add(OrderStatusEnum.SEE_OFF_GUESTS.getCode());//SEE_OFF_GUESTS
                            }};
                            if(xczqx.contains(xpOrder.getStatus())){//行程中取消订单,按照行程结束处理
                                buildPushOrderStatus(cmd, orderId, OrderStatusEnum.SEE_OFF_GUESTS, sequence);
                                xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.SEE_OFF_GUESTS.getCode(), true);
                                redisService.setCacheObject("ORDER_STATUS:" + orderId, OrderStatusEnum.SEE_OFF_GUESTS.getCode(), 24L, TimeUnit.HOURS);
                                // 判断当前订单的车辆是否有连环派单,然后判断是都还满足连环派单的条件,不满足则需要重新派单
                                String json = redisService.getCacheObject(CacheConstants.nextOrder(orderId));
                                if (StringUtils.isNotEmpty(json)){
                                    JSONObject jsonObject = JSON.parseObject(json);
                                    Long nextOrderId = jsonObject.getLong("orderId");
                                    XpOrder nextOrder = xpOrderClient.queryOrderById(nextOrderId).getData();
                                    if(null != nextOrder && nextOrder.getStatus() == OrderStatusEnum.PICK_UP.getCode()){
                                        redisService.setCacheObject(CacheConstants.nextOrder(orderId),null);
                                        ReassignOrderDTO reassignOrderDTO = new ReassignOrderDTO();
                                        reassignOrderDTO.setUid(xpOrder.getAppUserId().toString());
                                        reassignOrderDTO.setOrderNo(xpOrder.getOrderNumber());
                                        reassignOrderDTO.setCount(10);
                                        reassignOrderDTO.setLongitude(xpOrder.getStartLon());
                                        reassignOrderDTO.setLatitude(xpOrder.getStartLon());
                                        reassignOrderClient.reassignOrder(reassignOrderDTO);
                                    }
                                }
                                redisService.getCacheObject("ORDER_CONNECT_ORDER:" + orderId);
                            }else{
                                buildPushOrderStatus(cmd, orderId, OrderStatusEnum.CANCELED, sequence);
                                xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.CANCELED.getCode(), true);
                                redisService.setCacheObject("ORDER_STATUS:" + orderId, OrderStatusEnum.CANCELED.getCode(), 24L, TimeUnit.HOURS);
                            }
                        }
                    }
                    break;
                case ORDER_ARRIVED_AT_CRUISE_DESTINATION:
                    //到达巡游终点
                    if(orderId.contains("XU")){
                        buildPushOrderStatus(orderId, OrderStatusEnum.COMPLETED, sequence);
                        buildPushOrderStatus(cmd, orderId, OrderStatusEnum.COMPLETED, sequence);
                        String cruiseOrderId = orderId.substring(2);
                        XpCruiseOrder xpCruiseOrder = xpCruiseOrderClient.getCruiseOrder(Long.parseLong(cruiseOrderId)).getData();
                        if (Objects.nonNull(xpCruiseOrder)){
@@ -1122,8 +1429,16 @@
                            }
                        }
                    }else if(orderId.contains("TEST")){
                        //测试巡游单处理逻辑
                        testOrderClient.updateOrderStatus(Long.parseLong(orderId.substring(4)), OrderStatusEnum.COMPLETED.getCode());
                        //测试巡游单完成状态
                        XpTestOrder testOrder = testOrderClient.queryOrderById(Long.parseLong(orderId.substring(4))).getData();
                        if(testOrder.getOrderType() == 2){
                            XpVehicle xpVehicle = xpVehicleClient.queryById(testOrder.getVehicleId()).getData();
                            //响应消息
                            responseMessage(cmd, 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:
@@ -1142,7 +1457,7 @@
     * @param orderId
     * @param status
     */
    public void buildPushOrderStatus(String orderId, OrderStatusEnum status, Long sequence){
    public void buildPushOrderStatus(RTCmdType cmd, String orderId, OrderStatusEnum status, Long sequence){
        if(orderId.contains("XU")){
            //巡游单
            //到达目的地
@@ -1158,7 +1473,7 @@
                    R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(vehicleId);
                    XpVehicle xpVehicle = xpVehicleR.getData();
                    //响应消息
                    responseMessage(sequence, xpVehicle.getVehicleVin());
                    responseMessage(cmd, sequence, xpVehicle.getVehicleVin());
                    // 运营中 继续执行
                    if(xpVehicle.getOperatingStatus()==1 && xpVehicle.getState()==0){
                        log.info("巡游单到达终点,继续执行下一笔巡游单");
@@ -1178,6 +1493,7 @@
                        newXpCruiseOrder.setStartPointName(xpCruiseOrder.getEndPointName());
                        newXpCruiseOrder.setStatus(1);
                        newXpCruiseOrder.setLastOrderId(xpCruiseOrder.getId());
                        xpCruiseOrder.setXpuTaskId(snowflake.nextId() + "");
                        // 通过车找终点id
                        CruisePointDto cruisePointDto = new CruisePointDto();
@@ -1187,7 +1503,12 @@
                        cruisePointDto.setOrderReverse(xpCruiseOrder.getOrderReverse());
                        R<XpCruiseOrder> cruisePoint = xpCruisePlanClient.getCruisePoint(cruisePointDto);
                        if(cruisePoint!=null){
                            xpCruiseOrderClient.addCruiseOrder(cruisePoint.getData());
                            XpCruiseOrder cruiseOrder1 = cruisePoint.getData();
                            //不停车替换新任务
                            cruiseOrder1.setLastOrderId1("XU" + xpCruiseOrder.getId());
                            cruiseOrder1.setLastXpuTaskId(xpCruiseOrder.getXpuTaskId());
                            cruiseOrder1.setTaskActionType(TaskActionType.kTerminateForNewTask);
                            xpCruiseOrderClient.addCruiseOrder(cruiseOrder1);
                        }
                    }
                }
@@ -1198,7 +1519,7 @@
            XpOrder xpOrder = xpOrderR.getData();
            XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData();
            //响应消息
            responseMessage(sequence, xpVehicle.getVehicleVin());
            responseMessage(cmd, sequence, xpVehicle.getVehicleVin());
            //构建推送消息
            Map<String, Object> params = new HashMap<>();
@@ -1238,6 +1559,108 @@
    }
    /**
     * 当前 cancelOrder 指令是按 taskId 记录取消上下文。
     * 改派旧车取消回调优先读取该上下文,避免依赖订单当前车/状态造成竞态误判。
     */
    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;
        }
        String taskId = orderStatusInfo.getTaskId();
        // 先按 taskId 读取当前生效的取消上下文,再兼容历史按 orderId 存储的改派上下文。
        JSONObject cancelContext = getCancelOrderContext(taskId);
        if (cancelContext == null) {
            cancelContext = getReassignCancelContext(orderId);
        }
        if (cancelContext == null) {
            log.info("改派取消回调未命中专用上下文,orderId: {}, taskId: {}, missReason: context_not_found",
                    orderId, taskId);
            return null;
        }
        String cancelScene = cancelContext.getString("cancelScene");
        if (CancelOrderSceneEnum.REASSIGN_OLD_VEHICLE != CancelOrderSceneEnum.fromCode(cancelScene)) {
            log.info("改派取消回调未命中专用上下文,orderId: {}, taskId: {}, missReason: scene_not_match, cancelScene: {}, context: {}",
                    orderId, taskId, cancelScene, cancelContext);
            return null;
        }
        String contextOrderId = cancelContext.getString("orderId");
        if (StringUtils.isNotEmpty(contextOrderId) && !Objects.equals(contextOrderId, orderId)) {
            log.info("改派取消回调未命中专用上下文,orderId: {}, taskId: {}, missReason: order_not_match, contextOrderId: {}, context: {}",
                    orderId, taskId, contextOrderId, cancelContext);
            return null;
        }
        return cancelContext;
    }
    /**
     * 当前 cancelOrder 指令是按 taskId 记录取消上下文。
     * 改派旧车取消回调优先读取该上下文,避免依赖订单当前车/状态造成竞态误判。
     */
    private JSONObject getCancelOrderContext(String taskId) {
        if (StringUtils.isEmpty(taskId)) {
            return null;
        }
        Object cacheObject = redisService.getCacheObject(CANCEL_ORDER_CONTEXT_PREFIX + taskId);
        if (cacheObject == null) {
            return null;
        }
        return JSON.parseObject(cacheObject.toString());
    }
    private String resolveReassignCancelResponseVin(String orderId, JSONObject cancelContext) {
        if (cancelContext == null) {
            return null;
        }
        String vin = cancelContext.getString("vin");
        if (StringUtils.isNotEmpty(vin)) {
            return vin;
        }
        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 newVehicleId.toString();
        }
        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();
        log.info("改派取消回调未命中专用上下文,orderId: {}, currentVehicleId: {}, newVehicleId: {}, currentStatus: {}",
                orderId, xpOrder.getVehicleId(), newVehicleId, currentStatus);
        return xpVehicle == null ? null : xpVehicle.getVehicleVin();
    }
    /**
     * 云端下发导航到XPU
     * @param requestId             XPU请求id
     * @param routeId               高德导航id
@@ -1246,17 +1669,51 @@
     * @param vin                   车辆VIN
     * @param xpuId                 XPU设备id
     */
    public void cloudPushNavigationInfo(String requestId, String routeId, String routeDataContent, String orderType, String orderId, String vin, String xpuId) {
    public void cloudPushNavigationInfo(String requestId, String routeId, String routeDataContent, String orderType, String orderId, String vin, String xpuId, String taskId) {
        //组装报文,将routeDateContent信息推送到XPU
        RestoreNavigationData.Builder navigationDataBuilder = RestoreNavigationData.newBuilder();
        navigationDataBuilder.setRouteId(routeId);
        navigationDataBuilder.setRequestId(requestId);
        navigationDataBuilder.setContent(routeDataContent);
        navigationDataBuilder.setTimestamp(System.currentTimeMillis());
        navigationDataBuilder.setOrderId(orderId);
        navigationDataBuilder.setTaskId(taskId);
        long sequence = snowflake.nextId();
        log.info("开始推送导航数据 {}", orderId);
        MqttPublishDto mqttPublishDto = xpuUtil.cloudPushNavigation(navigationDataBuilder.build(), xpuId, sequence);
        log.info("推送导航的响应消息,{}", JSON.toJSONString(mqttPublishDto));
    }
    //靠边停车处理逻辑
    public void pulloverStatusEvent(MsgContent msgContent){
        // todo 等对接完成数据结构后再实现相关功能
        //开始处理消息对应的业务逻辑
        NavigationRequest naviRequest = msgContent.getNavigationRequest();
        String requestId = naviRequest.getRequestId();
        String orderId = naviRequest.getOrderId();
        String taskId = naviRequest.getTaskId();
        OrderPhase orderPhase = naviRequest.getOrderPhase();
        log.info("订单ID:{}", orderId);
        log.info("任务ID:{}", taskId);
        //获取系统异常订单超时配置,创建定时任务取消订单
        if(!orderId.contains("XU")){
            XpSystemSetting xpSystemSetting = systemSettingClient.getSystemSettingOne().getData();
            Map<String, ? extends Object> jobMaps =
                    new ImmutableMap.Builder<String, String>()
                            .put("id", orderId)
                            .put("orderType", orderId.contains("TEST") ? OrderType.TEST_ORDER : OrderType.USER_ORDER)
                            .build();
            QuartzManager.addJob(
                    OrderExceptionJob.class,
                    (OrderExceptionJob.name + orderId).toUpperCase(),
                    TimeJobType.ERROR_ORDER_CANCEL,
                    DateUtils.localDateTimeToDate(LocalDateTime.now().plusMinutes(xpSystemSetting.getOrderExceptionalTimeout())),
                    jobMaps
            );
        }
    }
}