package com.xiaopeng.maintenance.schedule;
|
|
import cn.hutool.core.lang.Snowflake;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient;
|
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.maintenance.XpTaskRule;
|
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.maintenance.mapper.XpTaskRuleMapper;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.data.mongodb.core.MongoTemplate;
|
import org.springframework.data.mongodb.core.query.Criteria;
|
import org.springframework.data.mongodb.core.query.Query;
|
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.stereotype.Component;
|
import org.springframework.util.CollectionUtils;
|
|
import javax.annotation.Resource;
|
import java.time.LocalTime;
|
import java.util.Collections;
|
import java.util.List;
|
import java.util.stream.Collectors;
|
|
/**
|
* 车辆收车定时任务
|
* <p>
|
* 根据任务规则配置,在指定时间自动向所有车辆发起收车指令
|
* </p>
|
*
|
* @author mitao
|
* @since 2026-02-27
|
*/
|
@Component
|
public class VehicleCollectionScheduleTask {
|
|
private static final Logger log = LoggerFactory.getLogger(VehicleCollectionScheduleTask.class);
|
|
/**
|
* 任务名称
|
*/
|
private static final String TASK_NAME = "车辆收车定时任务";
|
|
@Autowired
|
private XpTaskRuleMapper taskRuleMapper;
|
|
@Autowired
|
private XpVehicleClient xpVehicleClient;
|
|
@Autowired
|
private XpCruiseOrderClient xpCruiseOrderClient;
|
|
@Autowired
|
private MongoTemplate mongoTemplate;
|
|
@Autowired
|
private OrderMissionClient orderMissionClient;
|
|
@Autowired
|
private XpCruisePlanClient xpCruisePlanClient;
|
|
@Resource(name = "hutoolSnowflake")
|
private Snowflake snowflake;
|
|
/**
|
* 每分钟检查一次是否需要执行收车任务
|
* <p>
|
* 检查逻辑:
|
* 1. 获取任务规则配置
|
* 2. 判断收车功能是否启用
|
* 3. 判断当前时间是否为配置的收车时间
|
* 4. 获取所有运营中的车辆
|
* 5. 向每辆车发送收车指令
|
* </p>
|
*/
|
@Scheduled(cron = "0 * * * * ?")
|
public void executeCollectionTask() {
|
log.info("========== 开始执行车辆收车定时任务检查 ==========");
|
|
// 1. 获取任务规则配置
|
XpTaskRule taskRule = getTaskRule();
|
if (taskRule == null) {
|
log.info("未找到任务规则配置,跳过执行");
|
return;
|
}
|
|
// 2. 判断收车功能是否启用
|
if (!Boolean.TRUE.equals(taskRule.getVehicleCollection())) {
|
log.info("车辆收车功能未启用,跳过执行");
|
return;
|
}
|
|
// 3. 判断当前时间是否为收车时间
|
if (!isExecuteTime(taskRule.getVehicleCollectionTime())) {
|
log.debug("当前时间不是收车时间,跳过执行");
|
return;
|
}
|
|
log.info("开始执行车辆收车任务");
|
|
try {
|
// 执行收车逻辑
|
int processedCount = executeVehicleCollection();
|
|
log.info("========== 车辆收车定时任务执行完成,处理车辆数: {} ==========", processedCount);
|
|
} catch (Exception e) {
|
log.error("车辆收车定时任务执行失败", e);
|
}
|
}
|
|
/**
|
* 获取任务规则配置
|
*
|
* @return 任务规则
|
*/
|
private XpTaskRule getTaskRule() {
|
return taskRuleMapper.selectOne(new LambdaQueryWrapper<XpTaskRule>().last("limit 1"));
|
}
|
|
/**
|
* 判断当前时间是否为收车时间
|
* <p>
|
* 精确到分钟级别的时间匹配
|
* </p>
|
*
|
* @param executeTime 配置的执行时间
|
* @return 是否应该执行
|
*/
|
private boolean isExecuteTime(LocalTime executeTime) {
|
if (executeTime == null) {
|
log.warn("收车时间未配置");
|
return false;
|
}
|
|
LocalTime now = LocalTime.now();
|
|
// 精确到分钟匹配
|
return executeTime.getHour() == now.getHour() && executeTime.getMinute() == now.getMinute();
|
}
|
|
/**
|
* 执行车辆收车逻辑
|
*
|
* @return 处理的车辆数量
|
*/
|
private int executeVehicleCollection() {
|
// 1. 获取所有运营中的车辆
|
List<XpVehicle> vehicles = getOperatingVehicles();
|
if (CollectionUtils.isEmpty(vehicles)) {
|
log.info("没有运营中的车辆,无需执行收车");
|
return 0;
|
}
|
|
log.info("找到 {} 辆运营中的车辆需要收车", vehicles.size());
|
|
// 2. 向每辆车发送收车指令
|
int processedCount = 0;
|
for (XpVehicle vehicle : vehicles) {
|
try {
|
sendCollectionCommand(vehicle);
|
processedCount++;
|
} catch (Exception e) {
|
log.error("向车辆[{}]发送收车指令失败", vehicle.getPlateNumber(), e);
|
}
|
}
|
|
return processedCount;
|
}
|
|
/**
|
* 获取所有运营中的车辆
|
*
|
* @return 车辆列表
|
*/
|
private List<XpVehicle> getOperatingVehicles() {
|
try {
|
R<List<XpVehicle>> result = xpVehicleClient.listVehicle();
|
if (result != null && result.getData() != null) {
|
// 过滤运营中的车辆 (vehicleType=2 表示运营, operatingStatus=1 表示运营中)
|
return result.getData().stream()
|
.filter(v -> v.getVehicleType() != null && v.getVehicleType() == 2)
|
.filter(v -> v.getOperatingStatus() != null && v.getOperatingStatus() == 1)
|
.filter(v -> v.getState() != null && v.getState() == 0)
|
.collect(Collectors.toList());
|
}
|
} catch (Exception e) {
|
log.error("获取车辆列表失败", e);
|
}
|
return Collections.emptyList();
|
}
|
|
/**
|
* 向车辆发送收车指令
|
*
|
* @param xpVehicle 车辆信息
|
*/
|
private void sendCollectionCommand(XpVehicle xpVehicle) {
|
// 收车 关闭当前巡游单子 生成新的返程单子 找到收车站点
|
XpCruiseOrder oldCruiseOrder = xpCruiseOrderClient.cancelCruiseOrderByVin(xpVehicle.getVehicleVin()).getData();
|
|
// mongodb 获取当前最新经纬度位置
|
VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class);
|
XpCruiseOrder xpCruiseOrder = new XpCruiseOrder();
|
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.setStatus(1);
|
xpCruiseOrder.setOrderReverse(1);
|
xpCruiseOrder.setLastOrderId(oldCruiseOrder.getId());
|
xpCruiseOrder.setOrderReverse(1);
|
xpCruiseOrder.setXpuTaskId(snowflake.nextId() + "");
|
|
// 找到收车站点
|
R<XpCruiseOrder> returnCruisePoint = xpCruisePlanClient.findReturnCruisePoint(xpCruiseOrder);
|
if (returnCruisePoint.getData() != null) {
|
XpCruiseOrder cruiseOrder = returnCruisePoint.getData();
|
//不停车替换新任务
|
cruiseOrder.setLastOrderId1("XU" + oldCruiseOrder.getId());
|
cruiseOrder.setLastXpuTaskId(oldCruiseOrder.getXpuTaskId());
|
cruiseOrder.setTaskActionType(TaskActionType.kTerminateForNewTask);
|
xpCruiseOrderClient.addCruiseOrder(cruiseOrder);
|
}
|
log.info("向车辆[{}]发送收车指令", xpVehicle.getPlateNumber());
|
}
|
}
|