liujie
2026-06-09 c96fbe6b0aeb413a17c429133ee6d81d138144b9
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpVehicleOperationsController.java
@@ -1,37 +1,44 @@
package com.xiaopeng.maintenance.controller;
import cn.hutool.core.util.IdUtil;
import com.sun.xml.internal.bind.v2.TODO;
import com.xiaopeng.api.dto.automaticPilot.PushOrderDto;
import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient;
import cn.hutool.core.lang.Snowflake;
import com.alibaba.fastjson2.JSONObject;
import com.xiaopeng.api.dto.automaticPilot.VehicleEventDTO;
import com.xiaopeng.api.dto.operation.NewCruiseOrderDto;
import com.xiaopeng.api.feignClient.automaticPilot.VehicleBuriedPointClient;
import com.xiaopeng.api.feignClient.operation.XpCruisePlanClient;
import com.xiaopeng.api.feignClient.order.XpCruiseOrderClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
import com.xiaopeng.api.model.order.XpCruiseOrder;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.automaticPilot.VehiclePosition;
import com.xiaopeng.api.vo.automaticPilot.protobuf.TaskActionType;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.utils.SensitiveDataCryptoUtil;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.common.redis.service.RedisService;
import com.xiaopeng.evi.oss.service.AliOssService;
import com.xiaopeng.maintenance.dto.VehicleDispatchAcceptDTO;
import com.xiaopeng.maintenance.dto.VehicleDispatchDepartureDTO;
import com.xiaopeng.maintenance.model.query.OperationRecordsQuery;
import com.xiaopeng.maintenance.service.IXpVehiclePreparationService;
import com.xiaopeng.maintenance.model.vo.OperationRecordsVO;
import com.xiaopeng.maintenance.service.IXpVehiclePreparationService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
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.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
/**
 * <p>
@@ -46,64 +53,126 @@
@Api(tags = "车辆运维")
public class XpVehicleOperationsController {
    @Autowired
    @Resource
    private IXpVehiclePreparationService xpVehiclePreparationService;
    @Autowired
    @Resource
    private XpVehicleClient xpVehicleClient;
    @Autowired
    @Resource
    private XpCruiseOrderClient xpCruiseOrderClient;
    @Autowired
    @Resource
    private MongoTemplate mongoTemplate;
    @Resource
    private AliOssService aliOssService;
    @Autowired
    private OrderMissionClient orderMissionClient;
    private XpCruisePlanClient xpCruisePlanClient;
    @Autowired
    private VehicleBuriedPointClient vehicleBuriedPointClient;
    @Resource(name = "hutoolSnowflake")
    private Snowflake snowflake;
    /**
     * 车辆详情-车辆调度-发车 收车
     */
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation(value = "车辆运维-车辆调度-发车/收车", tags = {"运维APP-车辆管理"})
    @PostMapping("/api/v1/vehicle/vehicleDispatchDeparture")
    @PostMapping("/maintenance-app/api/v1/vehicle/vehicleDispatchDeparture")
    public R<String> vehicleDispatchDeparture(@RequestBody VehicleDispatchDepartureDTO dto) {
        // 判断是否有正在进行的正常订单
        // 查询车辆
        XpVehicle xpVehicle = xpVehicleClient.queryById(dto.getVehicleId()).getData();
        if(xpVehicle.getState()==1){
        if (xpVehicle.getState() == 1) {
            return R.fail("车辆正在接单中");
        }
        xpVehicle.setOperatingStatus(dto.getDepartureStatus());
        xpVehicleClient.updateVehicleById(xpVehicle);
        String vin = SensitiveDataCryptoUtil.decryptIfPossible(xpVehicle.getVehicleVin());
        VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(vin)), VehiclePosition.class);
        if (vehiclePosition == null || vehiclePosition.getPoint() == null) {
            return R.fail("车辆位置信息不存在");
        }
        Integer departureStatus = dto.getDepartureStatus();
        XpVehicle vehicle1 = new XpVehicle();
        vehicle1.setOperatingStatus(departureStatus);
        vehicle1.setId(xpVehicle.getId());
        xpVehicleClient.updateVehicleById(vehicle1);
        // 封装埋点消息实体
        VehicleEventDTO vehicleEventDTO = new VehicleEventDTO();
        vehicleEventDTO.setVin(vin);
        vehicleEventDTO.setXpuId("");
        vehicleEventDTO.setOrderId("");
        vehicleEventDTO.setEventKey("RT_web_vehicle_status_changed");
        vehicleEventDTO.setEventTime(System.currentTimeMillis());
        Map<String, Object> attributes = new HashMap<>();
        attributes.put("vin", vin);
        attributes.put("order_id", "");
        attributes.put("timestamp", vehicleEventDTO.getEventTime());
        // 1.0埋点新增
        attributes.put("odometer_km", vehiclePosition.getTotalOdometer());
        if (departureStatus == 1) {
            attributes.put("main_status", "ONLINE");
            // TODO 预留位置 目前无状态
            attributes.put("sub_status", "");
            attributes.put("prev_sub_status", "");
        } else {
            attributes.put("main_status", "OFFLINE");
            // TODO 预留位置 目前无状态
            attributes.put("sub_status", "");
            attributes.put("prev_sub_status", "");
        }
        vehicleEventDTO.setAttributes(attributes);
        vehicleBuriedPointClient.sendVehicleEvent(vehicleEventDTO);
        // 发车
        if(dto.getDepartureStatus()==1){
            // 找车辆的任务  生成巡游单子 下发命令 TODO
        }else if(dto.getDepartureStatus()==3){
        if (dto.getDepartureStatus() == 1) {
            // 找车辆的任务  生成巡游单子 下发命令
            //发车之前,检查所有之前没终止的数据,将其终止
            xpCruiseOrderClient.stopAllCruiseOrder(vin);
            R<XpCruiseOrder> newCruiseOrder = xpCruisePlanClient.getNewCruiseOrder(new NewCruiseOrderDto(xpVehicle.getId(), vin, xpVehicle.getFleetId(), vehiclePosition.getPoint()));
            if (newCruiseOrder.getData() != null && 200 == newCruiseOrder.getCode()) {
                //方向为正向
                XpCruiseOrder cruiseOrder = newCruiseOrder.getData();
                cruiseOrder.setOrderType(2);
                cruiseOrder.setOrderReverse(1);
                //不停车替换新任务
                cruiseOrder.setTaskActionType(TaskActionType.kTerminateForNewTask);
                R<Long> longR = xpCruiseOrderClient.addCruiseOrder(cruiseOrder);
                if (200 != longR.getCode()) {
                    return R.fail(longR.getMsg());
                }
            }
        } else if (dto.getDepartureStatus() == 3) {
            // 收车 关闭当前巡游单子 生成新的返程单子  找到收车站点
            R<String> r = xpCruiseOrderClient.updateCruiseOrder(xpVehicle.getVehicleVin());
            XpCruiseOrder oldCruiseOrder = xpCruiseOrderClient.cancelCruiseOrderByVin(vin).getData();
            // redis 获取当前最新经纬度位置
            VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class);
            double x = vehiclePosition.getPoint().getX();
            double y = vehiclePosition.getPoint().getY();
            XpCruiseOrder xpCruiseOrder = new XpCruiseOrder();
            xpCruiseOrder.setId("XU"+ IdUtil.fastUUID());
            if (vehiclePosition != null) {
                double x = vehiclePosition.getPoint().getX();
                double y = vehiclePosition.getPoint().getY();
                xpCruiseOrder.setStartLon(x);
                xpCruiseOrder.setStartLat(y);
            }
            xpCruiseOrder.setVehicleId(xpVehicle.getId());
            xpCruiseOrder.setFleetId(xpVehicle.getFleetId());
            xpCruiseOrder.setOrderType(2);
            xpCruiseOrder.setStartLon(x);
            xpCruiseOrder.setStartLat(y);
            // TODO 找到收车站点
            xpCruiseOrder.setStatus(1);
            xpCruiseOrder.setOrderReverse(1);
            xpCruiseOrder.setLastOrderId(oldCruiseOrder.getId());
            xpCruiseOrder.setOrderReverse(1);
            xpCruiseOrder.setXpuTaskId(snowflake.nextId() + "");
            // 下发命令
            orderMissionClient.pushOrder(new PushOrderDto( xpCruiseOrder.getVehicleVin(),xpCruiseOrder.getId(),null));
            // 找到收车站点
            XpCruiseOrder returnCruisePoint = xpCruisePlanClient.findReturnCruisePoint(xpCruiseOrder).getData();
            if (returnCruisePoint != null) {
                //不停车替换新任务
                returnCruisePoint.setLastOrderId1("XU" + oldCruiseOrder.getId());
                returnCruisePoint.setLastXpuTaskId(oldCruiseOrder.getXpuTaskId());
                returnCruisePoint.setTaskActionType(TaskActionType.kTerminateForNewTask);
                xpCruiseOrderClient.addCruiseOrder(returnCruisePoint);
            }
        }
        return R.ok();
    }
@@ -112,13 +181,15 @@
     * 车辆详情-车辆调度-接单、测试
     */
    @ApiOperation(value = "车辆运维-车辆调度-接单、测试", tags = {"运维APP-车辆管理"})
    @PostMapping("/api/v1/vehicle/vehicleDispatchAccept")
    @PostMapping("/maintenance-app/api/v1/vehicle/vehicleDispatchAccept")
    public R<String> vehicleDispatchAccept(@RequestBody VehicleDispatchAcceptDTO dto) {
        // 查询车辆
        XpVehicle xpVehicle = xpVehicleClient.queryById(dto.getVehicleId()).getData();
        xpVehicle.setAcceptOrTest(dto.getAcceptOrTest());
        xpVehicle.setAcceptOrTestStatus(dto.getAcceptOrTestStatus());
        xpVehicleClient.updateVehicleById(xpVehicle);
        XpVehicle vehicle1 = new XpVehicle();
        vehicle1.setId(xpVehicle.getId());
        vehicle1.setAcceptOrTest(dto.getAcceptOrTest());
        vehicle1.setAcceptOrTestStatus(dto.getAcceptOrTestStatus());
        xpVehicleClient.updateVehicleById(vehicle1);
        return R.ok();
    }
@@ -126,9 +197,25 @@
     * 车辆详情-车辆调度-运维记录
     */
    @ApiOperation(value = "车辆运维-车辆调度-运维记录", tags = {"运维APP-车辆管理"})
    @PostMapping("/api/v1/vehicle/operationRecords")
    public R<PageInfo<OperationRecordsVO>> operationRecords(@Validated @RequestBody OperationRecordsQuery query) {
    @PostMapping("/maintenance-app/api/v1/vehicle/operationRecords")
    public R<PageInfo<OperationRecordsVO>> operationRecords(@Validated @RequestBody OperationRecordsQuery query) throws UnsupportedEncodingException {
        PageInfo<OperationRecordsVO> operationRecords = xpVehiclePreparationService.operationRecords(query);
        for (OperationRecordsVO record : operationRecords.getRecords()) {
            String vehiclePictures = record.getVehiclePictures();
            if (StringUtils.isNotBlank(vehiclePictures)) {
                JSONObject jsonObject = JSONObject.parseObject(vehiclePictures);
                // 1
                String downloadUrl = jsonObject.getString("url");
                try {
                    downloadUrl = aliOssService.getDownloadUrl(jsonObject.getString("id"), jsonObject.getString("name"), true);
                } catch (UnsupportedEncodingException e) {
                    log.error("获取图片下载地址失败", e);
                }
                jsonObject.put("url", downloadUrl);
                record.setVehiclePictures(jsonObject.toJSONString());
            }
        }
        return R.ok(operationRecords);
    }