QDAirPortBackend0122/doc/guide/guide.md
2026-01-22 13:19:47 +08:00

17 KiB
Raw Permalink Blame History

QAUP机场车辆管理系统使用指南

系统概述

QAUP是一个集成的机场车辆管理系统包含

  • 基础信息管理:车辆档案、驾驶员信息、车辆类型等
  • 实时位置监控基于PostGIS的空间数据管理
  • 碰撞避免系统:实时安全规则检测和预警
  • 轨迹管理:车辆历史路径记录和分析
  • 航空器生命周期模拟CA3456航空器状态和路由模拟系统

API接口测试

航空器生命周期模拟API

系统提供了完整的航空器生命周期模拟API支持CA3456航空器的状态循环和路由管理。

1. 登录认证

# 基本登录(推荐)
curl -X POST "http://localhost:8090/login?username=dianxin&password=dianxin@123"

# 使用表单数据登录
curl -X POST "http://localhost:8090/login" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=dianxin&password=dianxin@123"

# 使用JSON数据登录
curl -X POST "http://localhost:8090/login" \
  -H "Content-Type: application/json" \
  -d '{"username":"dianxin","password":"dianxin@123"}'

预期响应:

{
  "data": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MzI3ODMwOTAsInVzZXJuYW1lIjoiYWRtaW4ifQ.y9feEL_9NT8UzED9NNkb0Ln6C-PBoufiSHWobWe5vWY",
  "msg": "登入成功",
  "status": 200
}

2. 航空器状态查询

# 查询CA3456当前状态
curl -X GET "http://localhost:8090/aircraftStatusController/getAircraftStatus" \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MzI3ODMwOTAsInVzZXJuYW1lIjoiYWRtaW4ifQ.y9feEL_9NT8UzED9NNkb0Ln6C-PBoufiSHWobWe5vWY"

预期响应:

{
  "data": {
    "contactCross": "F1",
    "flightNo": "CA3456",
    "inRunway": "35",
    "outRunway": "34",
    "seat": "138",
    "timestamp": 1752567616199,
    "type": "IN"  // 状态: IN(进港), ARRIVED(到达), OUT(出港)
  },
  "msg": "航空器状态查询成功",
  "status": 200
}

3. 进港路由查询

# 查询进港滑行路线
curl -X GET "http://localhost:8090/runwayPathPlanningController/findArrTaxiwayByRunwayAndContactCrossAndSeat?inRunway=35&outRunway=34&contactCross=F1&seat=138" \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MzI3ODMwOTAsInVzZXJuYW1lIjoiYWRtaW4ifQ.y9feEL_9NT8UzED9NNkb0Ln6C-PBoufiSHWobWe5vWY"

预期响应:

{
  "data": {
    "type": "IN",
    "status": "COMPLETE",
    "codes": "F1,L4,138",
    "geometry": null,
    "geoPath": {
      "type": "FeatureCollection",
      "features": [
        {
          "type": "Feature",
          "geometry": {
            "type": "LineString",
            "coordinates": [
              [120.086263, 36.370484],
              [120.085000, 36.370000],
              [120.084000, 36.369500],
              [120.083000, 36.369000],
              [120.082000, 36.368500],
              [120.081000, 36.368000],
              [120.080996, 36.369105]
            ]
          },
          "properties": {
            "code": "L4"
          }
        }
      ]
    }
  },
  "msg": "进港滑行路线查询成功",
  "status": 200
}

4. 出港路由查询

# 查询出港滑行路线
curl -X GET "http://localhost:8090/runwayPathPlanningController/findDepTaxiwayByRunwayAndContactCrossAndSeat?inRunway=35&outRunway=34&startSeat=138" \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MzI3ODMwOTAsInVzZXJuYW1lIjoiYWRtaW4ifQ.y9feEL_9NT8UzED9NNkb0Ln6C-PBoufiSHWobWe5vWY"

预期响应:

{
  "data": {
    "type": "OUT",
    "status": "COMPLETE", 
    "codes": "138,L4,F1",
    "geometry": null,
    "geoPath": {
      "type": "FeatureCollection",
      "features": [
        {
          "type": "Feature",
          "geometry": {
            "type": "LineString",
            "coordinates": [
              [120.080996, 36.369105],
              [120.081000, 36.368000],
              [120.082000, 36.368500],
              [120.083000, 36.369000],
              [120.084000, 36.369500],
              [120.085000, 36.370000],
              [120.086263, 36.370484]
            ]
          },
          "properties": {
            "code": "L4"
          }
        }
      ]
    }
  },
  "msg": "出港滑行路线查询成功",
  "status": 200
}

5. 状态循环测试

# 连续监控CA3456状态变化
for i in {1..6}; do
  echo "=== 第 $i 次调用 ($(date +%H:%M:%S)) ==="
  curl -s -X GET "http://localhost:8090/aircraftStatusController/getAircraftStatus" \
    -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MzI3ODMwOTAsInVzZXJuYW1lIjoiYWRtaW4ifQ.y9feEL_9NT8UzED9NNkb0Ln6C-PBoufiSHWobWe5vWY" \
    | python3 -c "import sys,json; data=json.load(sys.stdin); print(f'状态: {data[\"data\"][\"type\"]}, 航班号: {data[\"data\"][\"flightNo\"]}, 时间戳: {data[\"data\"][\"timestamp\"]}')"
  sleep 15
done

预期输出:

=== 第 1 次调用 (16:22:45) ===
状态: IN, 航班号: CA3456, 时间戳: 1752567765233
=== 第 2 次调用 (16:23:00) ===
状态: IN, 航班号: CA3456, 时间戳: 1752567780372
=== 第 3 次调用 (16:23:15) ===
状态: ARRIVED, 航班号: CA3456, 时间戳: 1752567795496
=== 第 4 次调用 (16:23:30) ===
状态: ARRIVED, 航班号: CA3456, 时间戳: 1752567810629
=== 第 5 次调用 (16:23:45) ===
状态: IN, 航班号: CA3456, 时间戳: 1752567825769
=== 第 6 次调用 (16:24:00) ===
状态: IN, 航班号: CA3456, 时间戳: 1752567840897

6. 路由API简化测试

# 简化的路由测试
echo "=== 测试进港路由 ==="
curl -s -X GET "http://localhost:8090/runwayPathPlanningController/findArrTaxiwayByRunwayAndContactCrossAndSeat?inRunway=35&outRunway=34&contactCross=F1&seat=138" \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MzI3ODMwOTAsInVzZXJuYW1lIjoiYWRtaW4ifQ.y9feEL_9NT8UzED9NNkb0Ln6C-PBoufiSHWobWe5vWY" \
  | python3 -c "import sys,json; data=json.load(sys.stdin); print(f'路由类型: {data[\"data\"][\"type\"]}, 编码: {data[\"data\"][\"codes\"]}, 状态: {data[\"data\"][\"status\"]}')"

echo "=== 测试出港路由 ==="
curl -s -X GET "http://localhost:8090/runwayPathPlanningController/findDepTaxiwayByRunwayAndContactCrossAndSeat?inRunway=35&outRunway=34&startSeat=138" \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MzI3ODMwOTAsInVzZXJuYW1lIjoiYWRtaW4ifQ.y9feEL_9NT8UzED9NNkb0Ln6C-PBoufiSHWobWe5vWY" \
  | python3 -c "import sys,json; data=json.load(sys.stdin); print(f'路由类型: {data[\"data\"][\"type\"]}, 编码: {data[\"data\"][\"codes\"]}, 状态: {data[\"data\"][\"status\"]}')"

CA3456生命周期说明

CA3456航空器按照以下周期进行状态模拟

  1. 进港阶段30秒type = "IN"

    • 航空器正在进场,执行进港滑行
    • 使用进港路由F1,L4,138
  2. 停留阶段60秒type = "ARRIVED"

    • 航空器已到达机位,进行客货作业
    • 停留在138机位
  3. 出港阶段30秒type = "OUT"

    • 航空器开始出港,执行出港滑行
    • 使用出港路由138,L4,F1
  4. 循环周期总计122秒包含2秒状态切换时间

WebSocket连接测试

系统支持WebSocket实时推送可以通过以下方式连接

// WebSocket连接示例
const ws = new WebSocket('ws://localhost:8080/ws');

ws.onmessage = function(event) {
    const data = JSON.parse(event.data);
    if (data.type === 'aircraftRouteUpdate') {
        console.log('收到航空器路由更新:', data.data);
    }
};

故障排除

常见错误

  1. 认证失败401

    • 检查token是否正确
    • 确认Authorization header格式Bearer <token>
  2. 连接超时

    • 检查Mock服务是否运行在端口8090
    • 确认Java服务是否运行在端口8080
  3. 状态不变化

    • 等待完整的状态周期122秒
    • 检查Mock服务日志

服务状态检查

# 检查Mock服务状态
curl -I http://localhost:8090/login

# 检查Java服务状态
curl -I http://localhost:8080/actuator/health

核心数据结构

主要表关系

sys_vehicle_info (基础信息)
    ├── vehicle_id: 数字ID (主键)
    └── license_plate_number: 车牌号

vehicle_locations (实时位置)
    ├── vehicle_id: 车牌号 (业务标识)
    ├── license_plate: 车牌号 (明确语义)
    └── sys_vehicle_id: 关联数字ID

通过车牌号关联: license_plate_number ↔ license_plate

业务视图

  • vehicle_complete_info: 车辆基础信息 + 最新位置
  • vehicle_info_with_location: 车辆信息与位置详细关联
  • vehicle_status_summary: 车辆实时状态统计
  • vehicle_trajectory_view: 车辆轨迹查询

实际使用指南

1. 车辆数据查询

基础查询

-- 查询所有车辆基础信息
SELECT vehicle_id, license_plate_number, brand, owning_unit, contact_person
FROM sys_vehicle_info;

-- 查询指定车辆详细信息
SELECT * FROM sys_vehicle_info 
WHERE license_plate_number = '京A12345';

车辆完整信息查询(推荐)

-- 根据车牌号查询车辆完整信息(基础信息+最新位置)
SELECT vehicle_plate, brand, owning_unit, status, 
       longitude, latitude, speed, last_update_time
FROM vehicle_info_with_location 
WHERE vehicle_plate = '京A12345';

-- 查询所有活跃车辆
SELECT vehicle_plate, brand, status, speed, last_update_time
FROM vehicle_info_with_location 
WHERE status = 'ACTIVE'
ORDER BY last_update_time DESC;

-- 查询离线车辆
SELECT vehicle_plate, brand, status, last_update_time
FROM vehicle_info_with_location 
WHERE status = 'OFFLINE'
ORDER BY last_update_time DESC;

车辆状态统计

-- 各类型车辆状态统计
SELECT vehicle_type, total_vehicles, active_vehicles, 
       inactive_vehicles, avg_speed, max_speed
FROM vehicle_status_summary;

-- 当前活跃车辆数量
SELECT COUNT(*) as active_count
FROM vehicle_info_with_location 
WHERE status = 'ACTIVE';

2. 空间查询

位置范围查询

-- 查询指定经纬度范围内的车辆
SELECT vi.vehicle_plate, vi.brand, vi.speed, vi.longitude, vi.latitude
FROM vehicle_info_with_location vi
WHERE vi.longitude BETWEEN 116.3 AND 116.4
  AND vi.latitude BETWEEN 39.9 AND 40.0
  AND vi.status = 'ACTIVE';

-- 查询距离指定点特定距离内的车辆使用PostGIS函数
SELECT vl.vehicle_id, vl.speed, ST_AsText(vl.location) as position,
       ST_Distance(vl.location, ST_Point(116.33, 39.95)) as distance_meters
FROM vehicle_locations vl
WHERE ST_DWithin(vl.location, ST_Point(116.33, 39.95), 1000)  -- 1000米范围内
  AND vl.timestamp > NOW() - INTERVAL '10 minutes'
ORDER BY distance_meters;

机场区域查询

-- 查询特定区域内的车辆
SELECT vl.vehicle_id, vl.speed, aa.name as area_name
FROM vehicle_locations vl
JOIN airport_areas aa ON ST_Within(vl.location, aa.boundary)
WHERE aa.area_id = 'RUNWAY_01'
  AND vl.timestamp > NOW() - INTERVAL '5 minutes';

-- 查询所有机场区域
SELECT area_id, name, type, speed_limit_kph, restricted
FROM airport_areas 
WHERE enabled = true
ORDER BY name;

3. 轨迹数据查询

车辆历史轨迹

-- 查询车辆最近7天的轨迹统计
SELECT vehicle_plate, trajectory_date, total_distance, 
       max_speed, avg_speed, duration_seconds
FROM vehicle_trajectory_view 
WHERE vehicle_plate = '京A12345'
  AND trajectory_date >= CURRENT_DATE - INTERVAL '7 days'
ORDER BY trajectory_date DESC;

-- 查询车辆详细位置历史
SELECT vehicle_id, ST_AsText(location) as position, 
       speed, heading, timestamp
FROM vehicle_locations 
WHERE vehicle_id = '京A12345'
  AND timestamp BETWEEN '2025-01-15 08:00:00' AND '2025-01-15 18:00:00'
ORDER BY timestamp;

轨迹分析

-- 统计车辆每日行驶距离
SELECT vehicle_plate, 
       DATE(start_time) as date,
       SUM(total_distance) as daily_distance,
       MAX(max_speed) as daily_max_speed
FROM vehicle_trajectory_view
WHERE vehicle_plate = '京A12345'
  AND start_time >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY vehicle_plate, DATE(start_time)
ORDER BY date DESC;

4. 安全规则和事件查询

规则违反事件

-- 查询最近的违规事件
SELECT event_id, rule_id, subject_id as vehicle_plate,
       violation_type, severity, ST_AsText(location) as violation_location,
       detected_at, response_status
FROM rule_violation_events 
WHERE detected_at > NOW() - INTERVAL '24 hours'
ORDER BY detected_at DESC;

-- 查询特定车辆的违规历史
SELECT event_id, violation_type, severity, detected_at
FROM rule_violation_events
WHERE subject_id = '京A12345'
  AND subject_type = 'VEHICLE'
ORDER BY detected_at DESC;

安全规则管理

-- 查询所有活跃的安全规则
SELECT rule_id, rule_name, rule_category, alert_level, status
FROM spatial_rules
WHERE status = 'ACTIVE'
ORDER BY priority, rule_name;

5. 数据同步管理

数据同步操作

-- 执行车辆ID同步当新增车辆信息时
SELECT update_sys_vehicle_id();

-- 检查数据同步状态
SELECT 
    'vehicle_locations' as table_name,
    COUNT(*) as total_records,
    COUNT(license_plate) as has_license_plate,
    COUNT(sys_vehicle_id) as has_sys_vehicle_id
FROM vehicle_locations
UNION ALL
SELECT 
    'vehicle_trajectories' as table_name,
    COUNT(*) as total_records,
    COUNT(license_plate) as has_license_plate,
    COUNT(sys_vehicle_id) as has_sys_vehicle_id
FROM vehicle_trajectories;

数据清理

-- 清理历史位置数据保留最近30天
DELETE FROM vehicle_locations 
WHERE timestamp < NOW() - INTERVAL '30 days';

-- 清理已解决的违规事件保留最近7天
DELETE FROM rule_violation_events 
WHERE response_status = 'RESOLVED' 
  AND resolved_at < NOW() - INTERVAL '7 days';

开发建议

推荐做法

  1. 统一使用车牌号作为业务标识符

    -- 推荐:使用车牌号查询
    SELECT * FROM vehicle_info_with_location WHERE vehicle_plate = '京A12345';
    
  2. 优先使用业务视图进行复杂查询

    -- 推荐:使用视图获取完整信息
    SELECT * FROM vehicle_info_with_location;
    
    -- 避免:手动关联多个表
    -- SELECT * FROM sys_vehicle_info vi JOIN vehicle_locations vl ON ...;
    
  3. 定期执行数据同步

    -- 建议在车辆信息变更后执行
    SELECT update_sys_vehicle_id();
    
  4. 使用PostGIS函数进行空间查询

    -- 推荐使用PostGIS函数
    SELECT * FROM vehicle_locations 
    WHERE ST_DWithin(location, ST_Point(116.33, 39.95), 1000);
    

⚠️ 注意事项

  1. 数据类型一致性

    • sys_vehicle_info.vehicle_id: BIGINT数字ID
    • vehicle_locations.vehicle_id: VARCHAR车牌号
    • 关联通过:license_plate_numberlicense_plate
  2. 时区处理

    • 新表使用 TIMESTAMP WITH TIME ZONE
    • 查询时注意时区一致性
  3. 空间坐标系

    • 所有空间数据使用 WGS84 坐标系SRID: 4326
    • 经度范围:-180 到 180
    • 纬度范围:-90 到 90
  4. 性能优化

    • 大量空间查询时使用已建立的GIST索引
    • 时间范围查询利用时间戳索引
    • 避免全表扫描善用WHERE条件

常用查询模板

实时监控查询

-- 车辆实时状态大屏
SELECT 
    COUNT(*) as total_vehicles,
    COUNT(CASE WHEN status = 'ACTIVE' THEN 1 END) as active_vehicles,
    COUNT(CASE WHEN status = 'INACTIVE' THEN 1 END) as inactive_vehicles,
    COUNT(CASE WHEN status = 'OFFLINE' THEN 1 END) as offline_vehicles,
    AVG(CASE WHEN status = 'ACTIVE' THEN speed END) as avg_speed
FROM vehicle_info_with_location;

区域车辆分布

-- 各区域车辆分布统计
SELECT 
    aa.name as area_name,
    aa.type as area_type,
    COUNT(vl.vehicle_id) as vehicle_count
FROM airport_areas aa
LEFT JOIN vehicle_locations vl ON ST_Within(vl.location, aa.boundary)
    AND vl.timestamp > NOW() - INTERVAL '5 minutes'
WHERE aa.enabled = true
GROUP BY aa.area_id, aa.name, aa.type
ORDER BY vehicle_count DESC;

安全监控查询

-- 安全事件实时监控
SELECT 
    COUNT(*) as total_events,
    COUNT(CASE WHEN severity = 'CRITICAL' THEN 1 END) as critical_events,
    COUNT(CASE WHEN severity = 'HIGH' THEN 1 END) as high_events,
    COUNT(CASE WHEN response_status = 'PENDING' THEN 1 END) as pending_events
FROM rule_violation_events 
WHERE detected_at > NOW() - INTERVAL '1 hour';

故障排除

常见问题

  1. 车辆位置数据无法关联

    • 检查车牌号格式是否一致
    • 执行数据同步:SELECT update_sys_vehicle_id();
  2. 空间查询结果为空

    • 确认坐标系是否为WGS84SRID: 4326
    • 检查经纬度值是否合理
  3. 性能问题

    • 检查是否使用了适当的索引
    • 时间范围查询添加时间限制条件

数据检查命令

-- 检查PostGIS扩展
SELECT PostGIS_Version();

-- 检查表结构
\d+ vehicle_locations
\d+ sys_vehicle_info

-- 检查数据完整性
SELECT table_name, column_name 
FROM information_schema.columns 
WHERE table_name LIKE 'vehicle%' 
AND column_name IN ('license_plate', 'sys_vehicle_id');

联系支持

如有问题,请查看:

  • 系统日志:logs/ 目录
  • 数据库日志PostgreSQL日志
  • 开发文档:doc/ 目录下的相关文档