优化任务接口数据源并修复路径点坐标映射
- 将任务接口数据源从 activeMovingObjectsCache 改为从 HTTP 缓存获取 - 新增路径点 x/y 坐标字段支持,兼容不同数据源格式 - 修复路径点状态字段空指针异常,添加安全处理逻辑 - 优化路径点坐标映射逻辑(x 对应 latitude,y 对应 longitude) - 添加详细的调试日志输出,便于问题排查 - 更新生产环境配置,设置默认的无人车服务地址 - 新增接口文档3.md,记录相关接口信息
This commit is contained in:
parent
dc4934d4d6
commit
85d0472f91
@ -86,7 +86,7 @@ data:
|
||||
at-manager-bsm: /ws/at_manager_bsm
|
||||
at-manager-path: /ws/at_manager_path
|
||||
http:
|
||||
base-url: ${VEHICLE_MANAGER_HTTP_BASE_URL:}
|
||||
base-url: ${VEHICLE_MANAGER_HTTP_BASE_URL:http://localhost:8020}
|
||||
status: /api/vehicle_manager/v1/vehicles/{vehicleId}/status
|
||||
vehicle-details: /api/vehicle_details
|
||||
poll-interval-ms: 1000
|
||||
|
||||
@ -116,6 +116,7 @@ public class UnmannedVehicle extends MovingObject {
|
||||
@lombok.Builder
|
||||
@lombok.NoArgsConstructor
|
||||
@lombok.AllArgsConstructor
|
||||
@com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public static class WaypointInfo {
|
||||
private String waypointId;
|
||||
private Double latitude;
|
||||
|
||||
@ -51,67 +51,113 @@ public class VehicleTaskController {
|
||||
private String status;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@GetMapping
|
||||
public AjaxResult list(@RequestParam(required = false, defaultValue = "1") int pageNum,
|
||||
@RequestParam(required = false, defaultValue = "10") int pageSize,
|
||||
@RequestParam(required = false) String status) {
|
||||
Map<String, MovingObject> activeMovingObjectsCache = dataCollectorService.getActiveMovingObjectsCache();
|
||||
// 从 HTTP 缓存获取车辆状态数据
|
||||
Map<String, DataCollectorService.UniversalVehicleStatusCacheEntry> httpCache = dataCollectorService.getUniversalStatusCache();
|
||||
List<VehicleTaskDTO> allTasks = new ArrayList<>();
|
||||
|
||||
for (MovingObject movingObject : activeMovingObjectsCache.values()) {
|
||||
if (!(movingObject instanceof UnmannedVehicle vehicle)) {
|
||||
System.out.println("[DEBUG] ========== 任务接口调试信息 ==========");
|
||||
System.out.println("[DEBUG] httpCache size: " + httpCache.size());
|
||||
System.out.println("[DEBUG] httpCache keys: " + httpCache.keySet());
|
||||
|
||||
for (Map.Entry<String, DataCollectorService.UniversalVehicleStatusCacheEntry> entry : httpCache.entrySet()) {
|
||||
String cacheKey = entry.getKey();
|
||||
DataCollectorService.UniversalVehicleStatusCacheEntry cacheEntry = entry.getValue();
|
||||
|
||||
System.out.println("[DEBUG] Processing cacheKey: " + cacheKey);
|
||||
|
||||
if (cacheEntry.getStatusData() == null) {
|
||||
System.out.println("[DEBUG] - statusData is null, skipping");
|
||||
continue;
|
||||
}
|
||||
|
||||
String vehicleId = vehicle.getObjectId();
|
||||
String missionId = vehicle.getMissionId();
|
||||
// 从 cacheKey 中提取 vehicleId(格式:universal_status_vehicleId)
|
||||
String vehicleId = cacheKey.replace("universal_status_", "");
|
||||
System.out.println("[DEBUG] - vehicleId: " + vehicleId);
|
||||
|
||||
com.qaup.collision.datacollector.model.dto.UniversalVehicleStatusDTO statusData = cacheEntry.getStatusData();
|
||||
com.qaup.collision.datacollector.model.dto.MissionContextDTO missionContext = statusData.getMissionContext();
|
||||
|
||||
System.out.println("[DEBUG] - missionContext: " + (missionContext != null ? missionContext.getClass().getSimpleName() : "null"));
|
||||
if (missionContext != null) {
|
||||
System.out.println("[DEBUG] - currentMission: " + (missionContext.getCurrentMission() != null ? missionContext.getCurrentMission().getClass().getSimpleName() : "null"));
|
||||
}
|
||||
|
||||
if (missionContext == null || missionContext.getCurrentMission() == null) {
|
||||
System.out.println("[DEBUG] - Skipping (no missionContext)");
|
||||
continue;
|
||||
}
|
||||
|
||||
com.qaup.collision.datacollector.model.dto.MissionContextDTO.CurrentMissionDTO currentMission = missionContext.getCurrentMission();
|
||||
String missionId = currentMission.getMissionId();
|
||||
|
||||
System.out.println("[DEBUG] - missionId: " + missionId);
|
||||
|
||||
// 如果没有任务ID,跳过
|
||||
if (missionId == null || missionId.isBlank()) {
|
||||
System.out.println("[DEBUG] - Skipping (no missionId)");
|
||||
continue;
|
||||
}
|
||||
|
||||
String missionStatus = vehicle.getMissionStatus() != null ? vehicle.getMissionStatus().name() : "UNKNOWN";
|
||||
// 获取车辆类型(VehicleInfoDTO 只有 vehicleId,没有 vehicleType,使用默认值)
|
||||
String vehicleType = "UNMANNED_VEHICLE";
|
||||
|
||||
// 获取任务状态(从 operationalStatus 获取 operationalMode)
|
||||
String missionStatus = "UNKNOWN";
|
||||
if (statusData.getOperationalStatus() != null) {
|
||||
missionStatus = statusData.getOperationalStatus().getOperationalMode();
|
||||
}
|
||||
|
||||
// 状态筛选
|
||||
if (status != null && !status.isEmpty() && !status.equalsIgnoreCase(missionStatus)) {
|
||||
System.out.println("[DEBUG] - Skipping (status filter: " + status + " != " + missionStatus + ")");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 获取车辆类型
|
||||
String vehicleType = vehicle.getObjectType().name();
|
||||
System.out.println("[DEBUG] - Adding task: " + vehicleId + ", MissionId: " + missionId);
|
||||
|
||||
// 获取路径点
|
||||
List<WaypointDTO> waypoints = new ArrayList<>();
|
||||
if (vehicle.getWaypoints() != null) {
|
||||
for (UnmannedVehicle.WaypointInfo wp : vehicle.getWaypoints()) {
|
||||
System.out.println("[DEBUG] - missionContext.getWaypoints(): " + missionContext.getWaypoints());
|
||||
if (missionContext.getWaypoints() != null) {
|
||||
System.out.println("[DEBUG] - waypoints size: " + missionContext.getWaypoints().size());
|
||||
for (com.qaup.collision.datacollector.model.dto.MissionContextDTO.WaypointDTO wp : missionContext.getWaypoints()) {
|
||||
System.out.println("[DEBUG] - waypoint: " + wp.getWaypointId() + ", lat: " + wp.getLatitude() + ", lon: " + wp.getLongitude() + ", status: " + wp.getStatus());
|
||||
WaypointDTO waypoint = WaypointDTO.builder()
|
||||
.waypointId(wp.getWaypointId())
|
||||
.latitude(wp.getLatitude())
|
||||
.longitude(wp.getLongitude())
|
||||
.status(wp.getStatus().name())
|
||||
.status(wp.getStatus())
|
||||
.build();
|
||||
waypoints.add(waypoint);
|
||||
}
|
||||
} else {
|
||||
System.out.println("[DEBUG] - waypoints is null");
|
||||
}
|
||||
System.out.println("[DEBUG] - final waypoints size: " + waypoints.size());
|
||||
|
||||
VehicleTaskDTO task = VehicleTaskDTO.builder()
|
||||
.vehicleId(vehicleId)
|
||||
.vehicleType(vehicleType)
|
||||
.missionId(missionId)
|
||||
.missionType(vehicle.getMissionType())
|
||||
.missionType(currentMission.getMissionType())
|
||||
.missionStatus(missionStatus)
|
||||
.missionStartTime(vehicle.getMissionStartTime())
|
||||
.estimatedEndTime(vehicle.getEstimatedEndTime())
|
||||
.progress(vehicle.getProgress())
|
||||
.totalMileage(vehicle.getTotalMileage())
|
||||
.missionStartTime(currentMission.getStartTime())
|
||||
.estimatedEndTime(currentMission.getEstimatedEndTime())
|
||||
.progress(currentMission.getProgress())
|
||||
.totalMileage(currentMission.getTotalMileage())
|
||||
.waypoints(waypoints)
|
||||
.lastSeenAt(null) // 暂时设为null,后续可以从缓存获取
|
||||
.lastSeenAt(cacheEntry.getTimestamp())
|
||||
.build();
|
||||
|
||||
allTasks.add(task);
|
||||
}
|
||||
|
||||
System.out.println("[DEBUG] Total tasks found: " + allTasks.size());
|
||||
System.out.println("[DEBUG] =========================================");
|
||||
|
||||
// 按任务开始时间倒序排序
|
||||
allTasks.sort((a, b) -> {
|
||||
if (a.getMissionStartTime() == null && b.getMissionStartTime() == null) return 0;
|
||||
@ -136,29 +182,41 @@ public class VehicleTaskController {
|
||||
|
||||
@GetMapping("/{vehicleId}")
|
||||
public AjaxResult get(@PathVariable String vehicleId) {
|
||||
Map<String, MovingObject> activeMovingObjectsCache = dataCollectorService.getActiveMovingObjectsCache();
|
||||
MovingObject movingObject = activeMovingObjectsCache.get(vehicleId);
|
||||
// 从 HTTP 缓存获取车辆状态数据(使用正确的 cacheKey 格式)
|
||||
String cacheKey = "universal_status_" + vehicleId;
|
||||
DataCollectorService.UniversalVehicleStatusCacheEntry entry = dataCollectorService.getUniversalStatusCache().get(cacheKey);
|
||||
|
||||
if (!(movingObject instanceof UnmannedVehicle vehicle)) {
|
||||
return AjaxResult.error(HttpStatus.NOT_FOUND, "车辆不存在或无任务").put("timestamp", System.currentTimeMillis());
|
||||
if (entry == null || entry.getStatusData() == null) {
|
||||
return AjaxResult.error(HttpStatus.NOT_FOUND, "车辆不存在或无数据").put("timestamp", System.currentTimeMillis());
|
||||
}
|
||||
|
||||
String missionId = vehicle.getMissionId();
|
||||
com.qaup.collision.datacollector.model.dto.UniversalVehicleStatusDTO statusData = entry.getStatusData();
|
||||
com.qaup.collision.datacollector.model.dto.MissionContextDTO missionContext = statusData.getMissionContext();
|
||||
|
||||
if (missionContext == null || missionContext.getCurrentMission() == null) {
|
||||
return AjaxResult.error(HttpStatus.NOT_FOUND, "车辆无任务").put("timestamp", System.currentTimeMillis());
|
||||
}
|
||||
|
||||
com.qaup.collision.datacollector.model.dto.MissionContextDTO.CurrentMissionDTO currentMission = missionContext.getCurrentMission();
|
||||
String missionId = currentMission.getMissionId();
|
||||
|
||||
if (missionId == null || missionId.isBlank()) {
|
||||
return AjaxResult.error(HttpStatus.NOT_FOUND, "车辆无任务").put("timestamp", System.currentTimeMillis());
|
||||
}
|
||||
|
||||
String vehicleType = vehicle.getObjectType().name();
|
||||
String vehicleType = "UNMANNED_VEHICLE";
|
||||
String missionStatus = statusData.getOperationalStatus() != null
|
||||
? statusData.getOperationalStatus().getOperationalMode()
|
||||
: "UNKNOWN";
|
||||
|
||||
List<WaypointDTO> waypoints = new ArrayList<>();
|
||||
if (vehicle.getWaypoints() != null) {
|
||||
for (UnmannedVehicle.WaypointInfo wp : vehicle.getWaypoints()) {
|
||||
if (missionContext.getWaypoints() != null) {
|
||||
for (com.qaup.collision.datacollector.model.dto.MissionContextDTO.WaypointDTO wp : missionContext.getWaypoints()) {
|
||||
WaypointDTO waypoint = WaypointDTO.builder()
|
||||
.waypointId(wp.getWaypointId())
|
||||
.latitude(wp.getLatitude())
|
||||
.longitude(wp.getLongitude())
|
||||
.status(wp.getStatus().name())
|
||||
.status(wp.getStatus())
|
||||
.build();
|
||||
waypoints.add(waypoint);
|
||||
}
|
||||
@ -168,14 +226,14 @@ public class VehicleTaskController {
|
||||
.vehicleId(vehicleId)
|
||||
.vehicleType(vehicleType)
|
||||
.missionId(missionId)
|
||||
.missionType(vehicle.getMissionType())
|
||||
.missionStatus(vehicle.getMissionStatus() != null ? vehicle.getMissionStatus().name() : "UNKNOWN")
|
||||
.missionStartTime(vehicle.getMissionStartTime())
|
||||
.estimatedEndTime(vehicle.getEstimatedEndTime())
|
||||
.progress(vehicle.getProgress())
|
||||
.totalMileage(vehicle.getTotalMileage())
|
||||
.missionType(currentMission.getMissionType())
|
||||
.missionStatus(missionStatus)
|
||||
.missionStartTime(currentMission.getStartTime())
|
||||
.estimatedEndTime(currentMission.getEstimatedEndTime())
|
||||
.progress(currentMission.getProgress())
|
||||
.totalMileage(currentMission.getTotalMileage())
|
||||
.waypoints(waypoints)
|
||||
.lastSeenAt(null) // 暂时设为null
|
||||
.lastSeenAt(entry.getTimestamp())
|
||||
.build();
|
||||
|
||||
return AjaxResult.success(task).put("timestamp", System.currentTimeMillis());
|
||||
|
||||
@ -76,6 +76,7 @@ public class MissionContextDTO {
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public static class WaypointDTO {
|
||||
/**
|
||||
* 路径点ID
|
||||
@ -96,5 +97,31 @@ public class MissionContextDTO {
|
||||
* 状态 (PENDING, COMPLETED, SKIPPED)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* X坐标 (经度)
|
||||
*/
|
||||
@com.fasterxml.jackson.annotation.JsonProperty("x")
|
||||
private Double x;
|
||||
|
||||
/**
|
||||
* Y坐标 (纬度)
|
||||
*/
|
||||
@com.fasterxml.jackson.annotation.JsonProperty("y")
|
||||
private Double y;
|
||||
|
||||
/**
|
||||
* 获取纬度,如果为null则返回x值
|
||||
*/
|
||||
public Double getLatitude() {
|
||||
return latitude != null ? latitude : x;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取经度,如果为null则返回y值
|
||||
*/
|
||||
public Double getLongitude() {
|
||||
return longitude != null ? longitude : y;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -632,12 +632,29 @@ public class DataCollectorService {
|
||||
// 提取路径点信息
|
||||
if (missionContext.getWaypoints() != null) {
|
||||
java.util.List<UnmannedVehicle.WaypointInfo> waypoints = missionContext.getWaypoints().stream()
|
||||
.map(wp -> UnmannedVehicle.WaypointInfo.builder()
|
||||
.waypointId(wp.getWaypointId())
|
||||
.latitude(wp.getLatitude())
|
||||
.longitude(wp.getLongitude())
|
||||
.status(UnmannedVehicle.WaypointStatus.valueOf(wp.getStatus()))
|
||||
.build())
|
||||
.map(wp -> {
|
||||
// 安全处理状态字段,避免 null 导致 NPE
|
||||
UnmannedVehicle.WaypointStatus status = UnmannedVehicle.WaypointStatus.PENDING;
|
||||
if (wp.getStatus() != null && !wp.getStatus().isEmpty()) {
|
||||
try {
|
||||
status = UnmannedVehicle.WaypointStatus.valueOf(wp.getStatus());
|
||||
} catch (IllegalArgumentException e) {
|
||||
// 如果状态值无效,使用默认值
|
||||
status = UnmannedVehicle.WaypointStatus.PENDING;
|
||||
}
|
||||
}
|
||||
|
||||
// x 对应 latitude(纬度),y 对应 longitude(经度)
|
||||
Double lat = wp.getX() != null ? wp.getX() : wp.getLatitude();
|
||||
Double lon = wp.getY() != null ? wp.getY() : wp.getLongitude();
|
||||
|
||||
return UnmannedVehicle.WaypointInfo.builder()
|
||||
.waypointId(wp.getWaypointId())
|
||||
.latitude(lat)
|
||||
.longitude(lon)
|
||||
.status(status)
|
||||
.build();
|
||||
})
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
vehicleBuilder.waypoints(waypoints);
|
||||
}
|
||||
@ -798,21 +815,47 @@ public class DataCollectorService {
|
||||
|
||||
// 如果存在missionContext数据,更新到activeMovingObjectsCache中的无人车对象
|
||||
if (statusData.getMissionContext() != null) {
|
||||
log.info("========== 开始更新任务上下文 ==========");
|
||||
log.info("vehicleId: {}", vehicleId);
|
||||
log.info("missionContext: {}", statusData.getMissionContext());
|
||||
log.info("waypoints: {}", statusData.getMissionContext().getWaypoints());
|
||||
updateUnmannedVehicleMissionContext(vehicleId, statusData.getMissionContext());
|
||||
log.info("========== 任务上下文更新完成 ==========");
|
||||
}
|
||||
|
||||
log.debug("缓存通用车辆状态数据: vehicleId={}, cacheKey={}, 包含任务上下文: {}",
|
||||
vehicleId, cacheKey, statusData.getMissionContext() != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新无人车的任务上下文信息
|
||||
*/
|
||||
private void updateUnmannedVehicleMissionContext(String vehicleId, MissionContextDTO missionContext) {
|
||||
MovingObject existingObject = activeMovingObjectsCache.get(vehicleId);
|
||||
/**
|
||||
|
||||
if (existingObject instanceof UnmannedVehicle) {
|
||||
UnmannedVehicle unmannedVehicle = (UnmannedVehicle) existingObject;
|
||||
* 更新无人车的任务上下文信息
|
||||
|
||||
*/
|
||||
|
||||
private void updateUnmannedVehicleMissionContext(String vehicleId, MissionContextDTO missionContext) {
|
||||
|
||||
log.info("========== updateUnmannedVehicleMissionContext 开始 ==========");
|
||||
|
||||
log.info("vehicleId: {}", vehicleId);
|
||||
|
||||
log.info("activeMovingObjectsCache 是否包含 vehicleId: {}", activeMovingObjectsCache.containsKey(vehicleId));
|
||||
|
||||
|
||||
|
||||
MovingObject existingObject = activeMovingObjectsCache.get(vehicleId);
|
||||
|
||||
log.info("existingObject: {}", existingObject);
|
||||
|
||||
log.info("existingObject 类型: {}", existingObject != null ? existingObject.getClass().getName() : "null");
|
||||
|
||||
|
||||
|
||||
if (existingObject instanceof UnmannedVehicle) {
|
||||
|
||||
log.info("找到 UnmannedVehicle 对象,开始更新任务上下文");
|
||||
|
||||
UnmannedVehicle unmannedVehicle = (UnmannedVehicle) existingObject;
|
||||
|
||||
// 更新任务上下文信息
|
||||
if (missionContext.getCurrentMission() != null) {
|
||||
@ -827,15 +870,38 @@ public class DataCollectorService {
|
||||
|
||||
// 更新路径点信息
|
||||
if (missionContext.getWaypoints() != null) {
|
||||
log.info("更新路径点信息: vehicleId={}, waypoints数量={}", vehicleId, missionContext.getWaypoints().size());
|
||||
java.util.List<UnmannedVehicle.WaypointInfo> waypoints = missionContext.getWaypoints().stream()
|
||||
.map(wp -> UnmannedVehicle.WaypointInfo.builder()
|
||||
.waypointId(wp.getWaypointId())
|
||||
.latitude(wp.getLatitude())
|
||||
.longitude(wp.getLongitude())
|
||||
.status(UnmannedVehicle.WaypointStatus.valueOf(wp.getStatus()))
|
||||
.build())
|
||||
.map(wp -> {
|
||||
// 安全处理状态字段,避免 null 导致 NPE
|
||||
UnmannedVehicle.WaypointStatus status = UnmannedVehicle.WaypointStatus.PENDING;
|
||||
if (wp.getStatus() != null && !wp.getStatus().isEmpty()) {
|
||||
try {
|
||||
status = UnmannedVehicle.WaypointStatus.valueOf(wp.getStatus());
|
||||
} catch (IllegalArgumentException e) {
|
||||
// 如果状态值无效,使用默认值
|
||||
status = UnmannedVehicle.WaypointStatus.PENDING;
|
||||
}
|
||||
}
|
||||
|
||||
// x 对应 latitude(纬度),y 对应 longitude(经度)
|
||||
Double lat = wp.getX() != null ? wp.getX() : wp.getLatitude();
|
||||
Double lon = wp.getY() != null ? wp.getY() : wp.getLongitude();
|
||||
|
||||
log.info(" 路径点: waypointId={}, x={}, y={}, latitude={}, longitude={}, status={}",
|
||||
wp.getWaypointId(), wp.getX(), wp.getY(), lat, lon, wp.getStatus());
|
||||
return UnmannedVehicle.WaypointInfo.builder()
|
||||
.waypointId(wp.getWaypointId())
|
||||
.latitude(lat)
|
||||
.longitude(lon)
|
||||
.status(status)
|
||||
.build();
|
||||
})
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
unmannedVehicle.setWaypoints(waypoints);
|
||||
log.info("路径点更新完成: vehicleId={}, 设置的路径点数量={}", vehicleId, waypoints.size());
|
||||
} else {
|
||||
log.debug("路径点为空: vehicleId={}", vehicleId);
|
||||
}
|
||||
|
||||
// 更新缓存
|
||||
@ -849,6 +915,7 @@ public class DataCollectorService {
|
||||
} else {
|
||||
log.debug("缓存中未找到无人车对象或类型不匹配,跳过任务上下文更新: vehicleId={}", vehicleId);
|
||||
}
|
||||
log.info("========== updateUnmannedVehicleMissionContext 完成 ==========");
|
||||
}
|
||||
|
||||
// 用于存储通用车辆状态数据的缓存
|
||||
|
||||
28
接口文档3.md
Normal file
28
接口文档3.md
Normal file
@ -0,0 +1,28 @@
|
||||
车辆管理系统接口文档
|
||||
1. 查询车辆列表
|
||||
接口描述
|
||||
该接口用于查询项目车辆列表数据。
|
||||
|
||||
接口详情
|
||||
协议名称: HTTP
|
||||
|
||||
接口地址: /api/vehicle_details
|
||||
|
||||
请求方法: GET
|
||||
|
||||
请求参数: 无
|
||||
参数名称,参数类型,描述
|
||||
code,int,状态码
|
||||
msg,str,任务信息
|
||||
data,str,车辆列表
|
||||
timestamp,float,时间戳
|
||||
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": [
|
||||
"AET02",
|
||||
"AET01"
|
||||
],
|
||||
"timestamp": 0
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user