修复坐标转换问题并新增车辆列表接口

- 修正经纬度坐标转换错误(longitude/latitude互换)
- 新增车辆列表查询接口 GET /api/vehicle-manager/vehicles
- 支持分页、状态筛选和离线判定
- 更新生产环境配置(Redis主机和无人车服务地址)
- 优化任务路径点坐标映射
This commit is contained in:
shan 2026-01-22 22:40:47 +08:00
parent 5309b98bcf
commit 8347eae959
6 changed files with 184 additions and 14 deletions

View File

@ -21,7 +21,7 @@ spring:
# Redis配置支持环境变量
data:
redis:
host: ${REDIS_HOST:localhost}
host: ${REDIS_HOST:10.0.0.58}
port: ${REDIS_PORT:6379}
database: ${REDIS_DATABASE:0}
password: ${REDIS_PASSWORD:}
@ -77,8 +77,8 @@ data:
retry-attempts: ${VEHICLE_API_RETRY:3}
vehicle-manager:
host: ${VEHICLE_MANAGER_HOST:}
port: ${VEHICLE_MANAGER_PORT:0}
host: ${VEHICLE_MANAGER_HOST:localhost}
port: ${VEHICLE_MANAGER_PORT:8020}
reconnect-delay-millis: ${VEHICLE_MANAGER_RECONNECT_DELAY:3000}
ws:
at-manager: /ws/at_manager

View File

@ -40,7 +40,7 @@ spring:
# 默认激活的profile开发环境
profiles:
# active: dev,druid
#active: dev,druid
active: prod,druid
# 文件上传

View File

@ -38,6 +38,16 @@ public class VehicleManagerApiController {
return AjaxResult.success(summary).put("timestamp", System.currentTimeMillis());
}
@GetMapping("/vehicles")
public AjaxResult getVehicleList(
@RequestParam(defaultValue = "1") int pageNum,
@RequestParam(defaultValue = "10") int pageSize,
@RequestParam(required = false) String status,
@RequestParam(defaultValue = "30000") long staleMillis) {
VehicleManagerQueryService.VehicleListResponse response = queryService.getVehicleList(pageNum, pageSize, status, staleMillis);
return AjaxResult.success(response).put("timestamp", System.currentTimeMillis());
}
@GetMapping("/vehicles/{vehicleId}")
public AjaxResult getVehicleSnapshot(@PathVariable String vehicleId) {
Map<String, Object> snapshot = queryService.getVehicleSnapshot(vehicleId);
@ -122,8 +132,8 @@ public class VehicleManagerApiController {
Double y = getDouble(node, "y");
waypoints.add(MissionContextDTO.WaypointDTO.builder()
.waypointId(String.valueOf(index++))
.longitude(x)
.latitude(y)
.longitude(y)
.latitude(x)
.status("PENDING")
.build());
}

View File

@ -297,7 +297,7 @@ public class DataCollectorService {
Double x = getDouble(dataNode, "x");
Double y = getDouble(dataNode, "y");
if (x != null && y != null) {
Point currentPosition = geometryFactory.createPoint(new org.locationtech.jts.geom.Coordinate(x, y));
Point currentPosition = geometryFactory.createPoint(new org.locationtech.jts.geom.Coordinate(y, x));
MovingObject existing = activeMovingObjectsCache.get(vehicleId);
UnmannedVehicle vehicle = existing instanceof UnmannedVehicle

View File

@ -6,9 +6,7 @@ import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.*;
@Service
@RequiredArgsConstructor
@ -187,4 +185,166 @@ public class VehicleManagerQueryService {
}
return value.asText();
}
@Data
@Builder
public static class VehicleListItemDTO {
private String vehicleId;
private String vehicleType;
private String status;
private Map<String, Object> position;
private Double speed;
private Double batteryLevel;
private Long lastSeenAt;
private Boolean isEmergency;
private Boolean isFault;
private String currentTask;
}
@Data
@Builder
public static class VehicleListResponse {
private int total;
private int pageNum;
private int pageSize;
private List<VehicleListItemDTO> rows;
private VehicleSummary summary;
}
public VehicleListResponse getVehicleList(int pageNum, int pageSize, String statusFilter, long staleMillis) {
long now = System.currentTimeMillis();
Set<String> vehicleIds = cacheService.getKnownVehicleIds();
List<VehicleListItemDTO> allVehicles = new ArrayList<>();
for (String vehicleId : vehicleIds) {
VehicleManagerCacheService.CacheEntry detailsEntry = cacheService.getVehicleDetails(vehicleId);
VehicleManagerCacheService.CacheEntry loginEntry = cacheService.getVehicleLoginStatus(vehicleId);
VehicleManagerCacheService.CacheEntry positionEntry = cacheService.getVehiclePosition(vehicleId);
VehicleManagerCacheService.CacheEntry chassisEntry = cacheService.getVehicleChassis(vehicleId);
VehicleManagerCacheService.CacheEntry suspendEntry = cacheService.getVehicleSuspend(vehicleId);
VehicleManagerCacheService.CacheEntry fmsEntry = cacheService.getVehicleFmsMessage(vehicleId);
VehicleManagerCacheService.CacheEntry orderEntry = cacheService.getVehicleOrder(vehicleId);
String vehicleType = getText(detailsEntry != null ? detailsEntry.getData() : null, "vehicleType");
String loginStatus = getText(loginEntry != null ? loginEntry.getData() : null, "loginStatus");
boolean loginStale = isStale(loginEntry, now, staleMillis);
String status;
if (loginEntry == null || loginStale) {
status = "offline";
} else {
status = "login".equalsIgnoreCase(loginStatus) ? "online" : "offline";
}
boolean isEmergency = false;
if (!isStale(suspendEntry, now, staleMillis)) {
Integer suspendStatus = getInt(suspendEntry != null ? suspendEntry.getData() : null, "suspendStatus");
if (suspendStatus != null && suspendStatus != 0) {
isEmergency = true;
status = "emergency";
}
}
boolean isFault = false;
if (!isStale(fmsEntry, now, staleMillis)) {
if (isFault(fmsEntry != null ? fmsEntry.getData() : null)) {
isFault = true;
status = "fault";
}
}
if (statusFilter != null && !statusFilter.isEmpty() && !status.equalsIgnoreCase(statusFilter)) {
continue;
}
Map<String, Object> position = null;
if (positionEntry != null && positionEntry.getData() != null) {
JsonNode posData = positionEntry.getData();
position = new HashMap<>();
position.put("x", getDouble(posData, "x"));
position.put("y", getDouble(posData, "y"));
position.put("theta", getDouble(posData, "theta"));
}
Double speed = null;
if (chassisEntry != null && chassisEntry.getData() != null) {
JsonNode chassisData = chassisEntry.getData();
JsonNode stateInfo = chassisData.path("sys_info").path("state_info");
speed = getDouble(stateInfo, "d_speed_kmph");
}
Double batteryLevel = null;
if (chassisEntry != null && chassisEntry.getData() != null) {
JsonNode chassisData = chassisEntry.getData();
JsonNode stateInfo = chassisData.path("sys_info").path("state_info");
String batteryStr = getText(stateInfo, "d_battery_available");
if (batteryStr != null) {
try {
batteryLevel = Double.parseDouble(batteryStr);
} catch (NumberFormatException ignored) {
}
}
}
String currentTask = null;
if (orderEntry != null && orderEntry.getData() != null) {
currentTask = getText(orderEntry.getData(), "businessKey");
}
VehicleListItemDTO item = VehicleListItemDTO.builder()
.vehicleId(vehicleId)
.vehicleType(vehicleType)
.status(status)
.position(position)
.speed(speed)
.batteryLevel(batteryLevel)
.lastSeenAt(getLastSeenAt(vehicleId))
.isEmergency(isEmergency)
.isFault(isFault)
.currentTask(currentTask)
.build();
allVehicles.add(item);
}
int total = allVehicles.size();
int fromIndex = (pageNum - 1) * pageSize;
int toIndex = Math.min(fromIndex + pageSize, total);
List<VehicleListItemDTO> pagedVehicles = fromIndex < total ?
allVehicles.subList(fromIndex, toIndex) : new ArrayList<>();
VehicleSummary summary = getVehicleSummary(staleMillis);
return VehicleListResponse.builder()
.total(total)
.pageNum(pageNum)
.pageSize(pageSize)
.rows(pagedVehicles)
.summary(summary)
.build();
}
private Double getDouble(JsonNode node, String field) {
if (node == null || node.isMissingNode()) {
return null;
}
JsonNode value = node.get(field);
if (value == null || value.isNull()) {
return null;
}
if (value.isDouble() || value.isFloat()) {
return value.asDouble();
}
if (value.isInt() || value.isLong()) {
return (double) value.asLong();
}
if (value.isTextual()) {
try {
return Double.parseDouble(value.asText());
} catch (NumberFormatException ignored) {
return null;
}
}
return null;
}
}

View File

@ -61,8 +61,8 @@ public class VehicleStatusAggregationService {
Double y = getDouble(data, "y");
if (x != null && y != null) {
position = MotionStatusDTO.PositionDTO.builder()
.longitude(x)
.latitude(y)
.longitude(y)
.latitude(x)
.build();
}
Double theta = getDouble(data, "theta");
@ -166,8 +166,8 @@ public class VehicleStatusAggregationService {
Double y = getDouble(node, "y");
MissionContextDTO.WaypointDTO waypoint = MissionContextDTO.WaypointDTO.builder()
.waypointId(String.valueOf(index++))
.longitude(x)
.latitude(y)
.longitude(y)
.latitude(x)
.status("PENDING")
.build();
waypoints.add(waypoint);