464 lines
14 KiB
Markdown
464 lines
14 KiB
Markdown
# 设计文档
|
||
|
||
## 概述
|
||
|
||
红绿灯信号集成功能为QAUP机场管理系统提供实时路口状态监控能力。该功能通过TCP服务器监听外部红绿灯硬件发送的状态信号,解析DI格式的原始数据,转换为系统内部的标准化消息格式,并通过WebSocket实时广播给前端客户端。
|
||
|
||
该设计遵循现有系统的架构模式,集成到现有的数据采集和WebSocket通信框架中,确保与其他系统组件的一致性和兼容性。
|
||
|
||
## 架构
|
||
|
||
### 整体架构图
|
||
|
||
```mermaid
|
||
graph TB
|
||
A[红绿灯硬件] -->|TCP连接<br/>端口8082| B[TrafficLightTcpServer]
|
||
B --> C[TrafficLightDataCollector]
|
||
C --> D[DataProcessingService]
|
||
D --> E[TrafficLightSignalParser]
|
||
E --> F[TrafficLightStatusEvent]
|
||
F --> G[WebSocketMessageBroadcaster]
|
||
G -->|WebSocket| H[前端客户端]
|
||
|
||
I[Spring配置] --> B
|
||
J[应用配置文件] --> I
|
||
|
||
subgraph "datacollector模块"
|
||
B
|
||
C
|
||
end
|
||
|
||
subgraph "dataprocessing模块"
|
||
D
|
||
E
|
||
F
|
||
end
|
||
|
||
subgraph "现有系统组件"
|
||
G
|
||
K[UniversalMessage]
|
||
L[TrafficLightStatusPayload]
|
||
end
|
||
|
||
F --> K
|
||
F --> L
|
||
```
|
||
|
||
### 数据流程
|
||
|
||
1. **信号接收**: TCP服务器(datacollector模块)监听8082端口,接收红绿灯硬件发送的JSON格式信号
|
||
2. **数据采集**: TrafficLightDataCollector收集原始信号数据,传递给数据处理服务
|
||
3. **数据处理**: DataProcessingService(dataprocessing模块)调用信号解析器处理数据
|
||
4. **信号解析**: TrafficLightSignalParser将DI格式的原始信号转换为标准化的红绿灯状态
|
||
5. **事件发布**: 数据处理服务通过Spring事件机制发布红绿灯状态变更事件
|
||
6. **WebSocket广播**: 事件监听器将状态更新广播给所有连接的前端客户端
|
||
|
||
## 组件和接口
|
||
|
||
### 1. TrafficLightTcpServer (datacollector模块)
|
||
|
||
**职责**: TCP服务器,负责监听和接收红绿灯硬件信号
|
||
|
||
**接口设计**:
|
||
```java
|
||
@Component
|
||
public class TrafficLightTcpServer {
|
||
// 启动TCP服务器
|
||
public void startServer();
|
||
|
||
// 停止TCP服务器
|
||
public void stopServer();
|
||
|
||
// 处理客户端连接
|
||
private void handleClientConnection(Socket clientSocket);
|
||
|
||
// 获取服务器状态
|
||
public ServerStatus getServerStatus();
|
||
}
|
||
```
|
||
|
||
**配置属性**:
|
||
- `traffic.light.tcp.port`: TCP监听端口(默认8082)
|
||
- `traffic.light.tcp.enabled`: 是否启用TCP服务器(默认true)
|
||
- `traffic.light.tcp.max-connections`: 最大连接数(默认10)
|
||
|
||
### 2. TrafficLightDataCollector (datacollector模块)
|
||
|
||
**职责**: 集成到现有数据采集框架,收集红绿灯原始数据并传递给数据处理服务
|
||
|
||
**接口设计**:
|
||
```java
|
||
@Service
|
||
public class TrafficLightDataCollector {
|
||
// 处理TCP服务器接收到的原始信号
|
||
public void collectTrafficLightSignal(String rawJsonSignal);
|
||
|
||
// 获取采集统计信息
|
||
public CollectionStatistics getStatistics();
|
||
}
|
||
```
|
||
|
||
### 3. TrafficLightSignalParser (dataprocessing模块)
|
||
|
||
**职责**: 解析DI格式的红绿灯信号,转换为内部状态枚举
|
||
|
||
**接口设计**:
|
||
```java
|
||
@Component
|
||
public class TrafficLightSignalParser {
|
||
// 解析原始JSON信号
|
||
public TrafficLightStatus parseSignal(String rawJsonSignal);
|
||
|
||
// 验证信号格式
|
||
public boolean isValidSignal(String rawJsonSignal);
|
||
|
||
// 获取解析统计信息
|
||
public ParseStatistics getStatistics();
|
||
}
|
||
```
|
||
|
||
**信号状态枚举**:
|
||
```java
|
||
public enum SignalState {
|
||
RED("red"),
|
||
YELLOW("yellow"),
|
||
GREEN("green"),
|
||
UNKNOWN("unknown");
|
||
}
|
||
|
||
public class TrafficLightStatus {
|
||
private String deviceId; // 红绿灯设备编号
|
||
private String intersectionId; // 关联的路口编号
|
||
private SignalState nsStatus; // 南北方向状态
|
||
private SignalState ewStatus; // 东西方向状态
|
||
private long timestamp; // 信号时间戳
|
||
private String rawSignal; // 原始信号数据(用于调试)
|
||
}
|
||
```
|
||
|
||
### 6. IntersectionService (新增服务)
|
||
|
||
**职责**: 管理路口信息,提供路口数据的CRUD操作
|
||
|
||
**接口设计**:
|
||
```java
|
||
@Service
|
||
public class IntersectionService {
|
||
// 根据路口编号获取路口信息
|
||
public Intersection getIntersectionById(String intersectionId);
|
||
|
||
// 获取所有激活的路口
|
||
public List<Intersection> getAllActiveIntersections();
|
||
|
||
// 添加新路口
|
||
public void addIntersection(Intersection intersection);
|
||
|
||
// 更新路口信息
|
||
public void updateIntersection(Intersection intersection);
|
||
}
|
||
```
|
||
|
||
### 7. TrafficLightService (新增服务)
|
||
|
||
**职责**: 管理红绿灯设备信息,提供设备数据的CRUD操作
|
||
|
||
**接口设计**:
|
||
```java
|
||
@Service
|
||
public class TrafficLightService {
|
||
// 根据设备编号获取红绿灯信息
|
||
public TrafficLight getTrafficLightByDeviceId(String deviceId);
|
||
|
||
// 根据路口编号获取红绿灯设备
|
||
public List<TrafficLight> getTrafficLightsByIntersection(String intersectionId);
|
||
|
||
// 更新设备在线状态
|
||
public void updateDeviceOnlineStatus(String deviceId, boolean isOnline);
|
||
|
||
// 更新设备心跳时间
|
||
public void updateDeviceHeartbeat(String deviceId);
|
||
}
|
||
```
|
||
|
||
**实体类**:
|
||
```java
|
||
@Entity
|
||
@Table(name = "intersections")
|
||
public class Intersection {
|
||
@Id
|
||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||
private Long id;
|
||
|
||
@Column(name = "intersection_id", unique = true, nullable = false)
|
||
private String intersectionId;
|
||
|
||
@Column(name = "intersection_name", nullable = false)
|
||
private String intersectionName;
|
||
|
||
@Column(name = "latitude", nullable = false)
|
||
private Double latitude;
|
||
|
||
@Column(name = "longitude", nullable = false)
|
||
private Double longitude;
|
||
|
||
@Column(name = "area_code")
|
||
private String areaCode;
|
||
|
||
@Column(name = "description")
|
||
private String description;
|
||
|
||
@Column(name = "is_active")
|
||
private Boolean isActive = true;
|
||
|
||
// getters and setters...
|
||
}
|
||
|
||
@Entity
|
||
@Table(name = "traffic_lights")
|
||
public class TrafficLight {
|
||
@Id
|
||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||
private Long id;
|
||
|
||
@Column(name = "device_id", unique = true, nullable = false)
|
||
private String deviceId;
|
||
|
||
@Column(name = "device_name", nullable = false)
|
||
private String deviceName;
|
||
|
||
@Column(name = "intersection_id", nullable = false)
|
||
private String intersectionId;
|
||
|
||
@Column(name = "device_type")
|
||
private String deviceType = "STANDARD";
|
||
|
||
@Column(name = "manufacturer")
|
||
private String manufacturer;
|
||
|
||
@Column(name = "model")
|
||
private String model;
|
||
|
||
@Column(name = "install_date")
|
||
private LocalDate installDate;
|
||
|
||
@Column(name = "is_online")
|
||
private Boolean isOnline = false;
|
||
|
||
@Column(name = "last_heartbeat")
|
||
private LocalDateTime lastHeartbeat;
|
||
|
||
@Column(name = "is_active")
|
||
private Boolean isActive = true;
|
||
|
||
// getters and setters...
|
||
}
|
||
```
|
||
|
||
### 4. DataProcessingService扩展 (dataprocessing模块)
|
||
|
||
**职责**: 在现有数据处理服务中添加红绿灯数据处理逻辑
|
||
|
||
**接口扩展**:
|
||
```java
|
||
@Service
|
||
public class DataProcessingService {
|
||
// 现有方法...
|
||
|
||
// 新增:处理红绿灯信号数据
|
||
public void processTrafficLightSignal(String rawJsonSignal);
|
||
|
||
// 创建WebSocket消息载荷(包含路口位置信息)
|
||
private TrafficLightStatusPayload createTrafficLightPayload(
|
||
TrafficLightStatus status,
|
||
TrafficLight device,
|
||
Intersection intersection
|
||
);
|
||
|
||
// 发布状态变更事件
|
||
private void publishTrafficLightStatusEvent(TrafficLightStatusPayload payload);
|
||
|
||
// 验证设备是否存在和在线
|
||
private boolean isValidTrafficLightDevice(String deviceId);
|
||
|
||
// 更新设备心跳和在线状态
|
||
private void updateDeviceStatus(String deviceId);
|
||
}
|
||
```
|
||
|
||
### 5. TrafficLightStatusEventListener (websocket模块)
|
||
|
||
**职责**: 监听红绿灯状态事件,通过WebSocket广播更新
|
||
|
||
**接口设计**:
|
||
```java
|
||
@Component
|
||
public class TrafficLightStatusEventListener {
|
||
// 处理红绿灯状态事件
|
||
@EventListener
|
||
public void handleTrafficLightStatusEvent(TrafficLightStatusEvent event);
|
||
|
||
// 广播WebSocket消息
|
||
private void broadcastStatusUpdate(TrafficLightStatusPayload payload);
|
||
}
|
||
```
|
||
|
||
## 数据模型
|
||
|
||
### 原始信号格式
|
||
```json
|
||
{
|
||
"device_id": "TL_001", // 红绿灯设备编号(新增)
|
||
"DI-01": 0,
|
||
"DI-02": 0,
|
||
"DI-11": 1, // 北红
|
||
"DI-12": 0, // 北黄
|
||
"DI-13": 0, // 北绿
|
||
"DI-14": 0, // 东红
|
||
"DI-15": 0, // 东黄
|
||
"DI-16": 1, // 东绿
|
||
"DI-17": 0,
|
||
"DI-18": 0
|
||
}
|
||
```
|
||
|
||
### 内部状态模型
|
||
```java
|
||
public class TrafficLightStatus {
|
||
private SignalState nsStatus; // 南北方向状态
|
||
private SignalState ewStatus; // 东西方向状态
|
||
private long timestamp; // 微秒级时间戳
|
||
private String intersectionId; // 路口标识符
|
||
}
|
||
```
|
||
|
||
### WebSocket消息格式
|
||
```json
|
||
{
|
||
"type": "intersection_traffic_light_status",
|
||
"timestamp": 1704067200000000,
|
||
"payload": {
|
||
"intersection_id": "INTERSECTION_001",
|
||
"intersection_name": "主要路口1号",
|
||
"device_id": "TL_001",
|
||
"device_name": "主路口红绿灯1号",
|
||
"position": {
|
||
"latitude": 39.9042,
|
||
"longitude": 116.4074
|
||
},
|
||
"ns_status": "red",
|
||
"ew_status": "green",
|
||
"timestamp": 1704067200000000,
|
||
"area_code": "AREA_A"
|
||
}
|
||
}
|
||
```
|
||
|
||
## 错误处理
|
||
|
||
### 1. 网络错误处理
|
||
- **连接断开**: 记录日志,等待客户端重新连接
|
||
- **端口占用**: 尝试备用端口,记录错误信息
|
||
- **网络超时**: 设置合理的超时时间,自动重试机制
|
||
|
||
### 2. 数据解析错误处理
|
||
- **JSON格式错误**: 记录原始数据,跳过当前消息
|
||
- **DI字段缺失**: 使用默认安全状态(红灯)
|
||
- **无效状态值**: 映射到UNKNOWN状态,记录警告
|
||
|
||
### 3. 系统错误处理
|
||
- **内存不足**: 限制连接数,清理过期数据
|
||
- **线程池满**: 使用队列缓冲,记录性能指标
|
||
- **WebSocket断开**: 继续处理信号,不影响数据采集
|
||
|
||
## 测试策略
|
||
|
||
### 1. 单元测试
|
||
- **信号解析器测试**: 验证各种DI组合的解析结果
|
||
- **状态转换测试**: 验证信号状态到枚举的映射
|
||
- **错误处理测试**: 验证异常情况的处理逻辑
|
||
|
||
### 2. 集成测试
|
||
- **TCP服务器测试**: 模拟红绿灯硬件连接和数据发送
|
||
- **WebSocket广播测试**: 验证消息格式和广播功能
|
||
- **端到端测试**: 从信号接收到前端显示的完整流程
|
||
|
||
### 3. 性能测试
|
||
- **高频信号测试**: 验证每秒多次信号的处理能力
|
||
- **并发连接测试**: 验证多个硬件设备同时连接
|
||
- **长时间运行测试**: 验证系统稳定性和内存泄漏
|
||
|
||
## 配置管理
|
||
|
||
### 应用配置文件 (application.yml)
|
||
```yaml
|
||
traffic:
|
||
light:
|
||
tcp:
|
||
enabled: true
|
||
port: 8082
|
||
max-connections: 50 # 支持更多路口连接
|
||
connection-timeout: 30000
|
||
processing:
|
||
enable-statistics: true
|
||
statistics-interval: 60000
|
||
default-intersection:
|
||
latitude: 0.0 # 默认坐标,实际坐标从数据库获取
|
||
longitude: 0.0
|
||
```
|
||
|
||
### 数据库表设计
|
||
|
||
#### 路口信息表 (intersections)
|
||
```sql
|
||
CREATE TABLE intersections (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
intersection_id VARCHAR(50) UNIQUE NOT NULL, -- 路口编号
|
||
intersection_name VARCHAR(100) NOT NULL, -- 路口名称
|
||
latitude DECIMAL(10, 8) NOT NULL, -- 纬度
|
||
longitude DECIMAL(11, 8) NOT NULL, -- 经度
|
||
area_code VARCHAR(20), -- 区域编码
|
||
description TEXT, -- 路口描述
|
||
is_active BOOLEAN DEFAULT true, -- 是否激活
|
||
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
|
||
-- 创建索引
|
||
CREATE INDEX idx_intersection_id ON intersections(intersection_id);
|
||
CREATE INDEX idx_area_code ON intersections(area_code);
|
||
```
|
||
|
||
#### 红绿灯设备表 (traffic_lights)
|
||
```sql
|
||
CREATE TABLE traffic_lights (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
device_id VARCHAR(50) UNIQUE NOT NULL, -- 红绿灯设备编号
|
||
device_name VARCHAR(100) NOT NULL, -- 设备名称
|
||
intersection_id VARCHAR(50) NOT NULL, -- 关联的路口编号
|
||
device_type VARCHAR(20) DEFAULT 'STANDARD', -- 设备类型
|
||
manufacturer VARCHAR(50), -- 制造商
|
||
model VARCHAR(50), -- 型号
|
||
install_date DATE, -- 安装日期
|
||
is_online BOOLEAN DEFAULT false, -- 是否在线
|
||
last_heartbeat TIMESTAMP, -- 最后心跳时间
|
||
is_active BOOLEAN DEFAULT true, -- 是否激活
|
||
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
|
||
-- 外键约束
|
||
CONSTRAINT fk_traffic_light_intersection
|
||
FOREIGN KEY (intersection_id)
|
||
REFERENCES intersections(intersection_id)
|
||
);
|
||
|
||
-- 创建索引
|
||
CREATE INDEX idx_traffic_light_device_id ON traffic_lights(device_id);
|
||
CREATE INDEX idx_traffic_light_intersection ON traffic_lights(intersection_id);
|
||
CREATE INDEX idx_traffic_light_online ON traffic_lights(is_online);
|
||
```
|
||
|
||
### 日志配置
|
||
- **信号接收日志**: DEBUG级别,记录原始信号数据
|
||
- **解析错误日志**: WARN级别,记录解析失败的信号
|
||
- **系统状态日志**: INFO级别,定期记录处理统计信息
|
||
- **网络错误日志**: ERROR级别,记录连接和网络问题 |