修正命名错误
|
# NewLife.JT808 架构设计
> 版本:v2.1 | 日期:2026-07-15
> 需求对应:[需求文档](/NewLife/NewLife.JT808/Blob/master/Doc/需求文档.md) | 功能清å•:[功能清å•](/NewLife/NewLife.JT808/Blob/master/Doc/功能清å•.md)
## 1. 整体架构
### 1.1 系统分层
NewLife.JT808 采用**三层架构(数æ®å±‚ → æœåС层 → 表现层)+ å议基础设施**,å‚考 GPS808 ä¸é€šç§‘技æˆç†Ÿæ–¹æ¡ˆï¼š
```
┌──────────────────────────────────────────────────────────────────â”
│ 表现层(JT808.Web) │
│ NewLife.Cube Areas: JT808Area / SafetyArea / PlatformArea │
│ ┌──────────────────────────────────────────────────────────────┠│
│ │ EntityController<Device> EntityController<PositionData> │ │
│ │ CommandClient(指令下å‘) ç»Ÿè®¡çœ‹æ¿ â”‚ │
│ └──────────────────────────────────────────────────────────────┘ │
├──────────────────────────────────────────────────────────────────┤
│ æœåС层 │
│ ┌────────────────────────┠┌─────────────────────────────────┠│
│ │ JT808.Server(网关æœåŠ¡ï¼‰â”‚ │ JT808.Worker(消费æœåŠ¡ï¼‰ │ │
│ │ ┌─ 5个指令处ç†å™¨ ────┠│ │ ┌─ 7个 Worker ──────────────┠│ │
│ │ │ Normal/Info/Media │ │ │ │ Position/Sensor/Event │ │ │
│ │ │ Position/FileHandler│ │ │ │ ADAS/DSM/BSD/TirePressure│ │ │
│ │ └────────────────────┘ │ │ └──────────────────────────┘ │ │
│ │ ┌─ 6个业务æœåŠ¡ ─────┠│ └─────────────────────────────────┘ │
│ │ │ Device/Queue/Biz │ │ │
│ │ │ AlarmEvent/Map/Mq │ │ │
│ │ └────────────────────┘ │ │
│ └────────────────────────┘ │
├──────────────────────────────────────────────────────────────────┤
│ æ•°æ®å±‚(JT808.Data) │
│ XCode ORM - 7 个数æ®åŸŸï¼Œ30+ 实体 │
│ ┌──────┠┌──────┠┌──────┠┌──────┠┌──────┠┌──────┠┌──────┠│
│ │ æ ¸å¿ƒåŸŸâ”‚ │ 安全域│ │平å°åŸŸâ”‚ │ 车è”域│ │ 行程域│ │地ç†åŸŸâ”‚ │统计域│ │
│ │GPS │ │Safety│ │Platfm│ │IoC │ │Segmnt│ │Locatn│ │Stat │ │
│ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ │
├──────────────────────────────────────────────────────────────────┤
│ å议基础设施(Newlife.JT808) │
│ JTMessage / MessageFactory / JTCodec / JT808Server │
│ T0001~T8A00 / ADASInfo~TPMSInfo / Helper / Enums │
└──────────────────────────────────────────────────────────────────┘
```
### 1.2 æ•°æ®æµæž¶æž„
```
终端设备 (JT808 TCP)
│ (TCP 808 端å£)
â–¼
JT808Server (NetServer<JT808Session>) ↠GpsHostedService 管ç†ç”Ÿå‘½å‘¨æœŸ
│ JTCodec è§£ç → 分包åˆå¹¶ → 消æ¯è·¯ç”±
â–¼
指令处ç†å™¨ï¼ˆ5个):Normal/Info/Media/Position/FileHandler
│ 注册/鉴æƒ/ä½ç½®/媒体/文件 处ç†
â–¼
业务æœåС层
├─ DeviceService 设备认è¯ã€åœ¨çº¿çжæ€ã€ä½ç½®ä¿å˜
├─ QueueService Redis Stream 消æ¯ç”Ÿäº§ï¼ˆ7个主题)
├─ AlarmEventService 报è¦äº‹ä»¶èšåˆå¤„ç†
├─ MediaService 多媒体文件管ç†
└─ MapService åæ ‡è½¬æ¢ï¼ˆå¯é€‰ï¼‰
│
├──→ æ•°æ®åº“(JT808.Data — XCode ORM)
│ æ ¸å¿ƒåŸŸ(GPS) / 安全域(Safety) / å¹³å°åŸŸ(Platform)
│
├──→ Redis Stream ──→ JT808.Worker(独立消费进程)
│ PositionData / SensorData / EventData
│ ADASAlarm / DSMAlarm / BSDAlarm / TirePressure
│
└──→ Redis 队列 ──→ 指令下å‘通é“
Web 端通过 CommandClient å‘布到 Redis command 队列
Server 端消费åŽä¸‹å‘åˆ°ç›®æ ‡ç»ˆç«¯
│
â–¼
JT808.Web (NewLife.Cube)
└─ JT808 Area: 设备/产å“/ä½ç½®/在线/指令/æŠ¥è¦ CRUD
└─ Safety Area: ADAS/DSM/BSD/TPMS 报è¦ç®¡ç†
└─ Platform Area: 转å‘/媒体/监管æœåŠ¡é…ç½®
└─ 指令下å‘页é¢ï¼šè®¾å¤‡è¯¦æƒ…é¡µé›†æˆ Redis 指令下å‘
```
## 2. æ ¸å¿ƒç»„ä»¶
### 2.1 å议基础设施(Newlife.JT808 — ä¿æŒä¸å˜ï¼‰
| 组件 | 命å空间 | 说明 |
|------|----------|------|
| `JTMessage` | `NewLife.JT808.Protocols` | JT/T 808 消æ¯å¸§ï¼Œè´Ÿè´£ 0x7E 帧解æžã€è½¬ä¹‰å¤„ç†ã€å¼‚æˆ–æ ¡éªŒã€åˆ†åŒ…å…ƒæ•°æ® |
| `MessageFactory` | `NewLife.JT808.Protocols` | 消æ¯å·¥åŽ‚ï¼Œç»´æŠ¤ `MessageKinds↔Type` æ˜ å°„ï¼Œæä¾› `Create/Parse` 方法 |
| `MessageKinds` | `NewLife.JT808.Protocols` | 消æ¯ç±»åž‹æžšä¸¾ï¼ˆUInt16 åº•å±‚å€¼ï¼‰ï¼Œè¦†ç›–å…¨éƒ¨æ ‡å‡†æ¶ˆæ¯ID |
| `TLV` | `NewLife.JT808.Protocols` | Type(4B)-Length(1B)-Value 通用编解ç ,用于 0x8103/0x0104 |
| `KLV` | `NewLife.JT808.Protocols` | Kind(1B)-Length(1B)-Value 通用编解ç ,用于 0x0200 é™„åŠ ä¿¡æ¯ |
| `Helper` | `NewLife.JT808.UtilTool` | 辅助类:GBK ç¼–ç æ³¨å†Œã€ç‰ˆæœ¬æ„ŸçŸ¥ Binary 创建ã€FastReadã€ToJsonJT808 |
| `JT808Config` | `NewLife.JT808.Protocols` | åè®®é…ç½®ï¼šç‰ˆæœ¬ã€æ ¡éªŒå¼€å…³ã€åР坆坆钥ã€å·¥åŽ‚åˆå§‹åŒ– |
### 2.2 æ•°æ®å±‚(JT808.Data — 新增/扩展)
| æ•°æ®åŸŸ | 命å空间 | 连接å | 主è¦å®žä½“ |
|--------|----------|--------|----------|
| æ ¸å¿ƒåŸŸ | `JT808.Data` | `GPS` | Product, Device, DeviceGroup, DeviceOnline, DeviceHistory, DeviceCommand, PositionData, RawData, MediaInfo, MediaRecord, Driver, TirePressure |
| 安全域 | `JT808.Data.Safety` | `Safety` | AlarmEvent, ADASAlarm, DSMAlarm, BSDAlarm, TPMSAlarm, AlarmFile, MediaResource |
| å¹³å°åŸŸ | `JT808.Data.Platform` | `Platform` | ForwardServer, MediaServer, SuperviseServer, SuperviseOnline, CarList, SimCard |
> **说明**ï¼šæž¶æž„å›¾ä¸æ ‡æ³¨çš„ 7 个数æ®åŸŸï¼ˆæ ¸å¿ƒåŸŸ/安全域/å¹³å°åŸŸ/车è”域/行程域/地ç†åŸŸ/统计域)å‚考 GPS808 设计。当å‰å·²å®žçŽ°å‰ 3 ä¸ªåŸŸï¼ˆæ ¸å¿ƒåŸŸ/安全域/å¹³å°åŸŸï¼‰ï¼Œåˆè®¡ 30+ 实体。车è”域/行程域/地ç†åŸŸ/统计域列为åŽç»è¿ä»£ï¼Œå¾…æ•°æ®æ¨¡åž‹å®Œå–„åŽè¡¥å……。
### 2.3 æœåŠ¡å±‚ï¼ˆJT808.Server — 新增)
| 组件 | 类型 | 说明 |
|------|------|------|
| `NormalController` | IJT808Controller | 注册/鉴æƒ/注销/å¿ƒè·³å¤„ç† |
| `InfoController` | IJT808Controller | 傿•°æŸ¥è¯¢/设置/终端å‡çº§ |
| `MediaController` | IJT808Controller | 多媒体事件/å˜å‚¨æ£€ç´¢ |
| `PositionController` | IJT808Controller | ä½ç½®ä¸ŠæŠ¥/电åå›´æ /行驶记录 |
| `FileHandler` | IJT808Controller | æ–‡ä»¶ä¸Šä¼ /è¡¥ä¼ /主动安全附件 |
| `DeviceService` | Singleton | 设备认è¯/在线/ä½ç½®ä¿å˜ |
| `QueueService` | Singleton | Redis Stream 生产者 |
| `AlarmEventService` | Singleton | 报è¦èšåˆå¤„ç† |
| `MediaService` | Singleton | å¤šåª’ä½“æ–‡ä»¶ç®¡ç† |
| `GpsHostedService` | HostedService | JT808Server 生命周期 |
| `DeviceOnlineHostedService` | HostedService | 在线状æ€ç»´æŠ¤ |
| `PreheatHostedService` | HostedService | å¯åŠ¨é¢„çƒ |
| `DataRetentionService` | HostedService | æ•°æ®è¿‡æœŸæ¸…ç† |
### 2.4 表现层(JT808.Web — 新增)
| Area | 说明 | ä¸»è¦æŽ§åˆ¶å™¨ |
|------|------|-----------|
| `Areas/JT808/` | æ ¸å¿ƒç®¡ç† | DeviceController, ProductController, DeviceOnlineController, DeviceHistoryController, DeviceGroupController, DeviceParameterController, PositionDataController, DeviceCommandController, AlarmController, RawDataController, DriverController, MediaInfoController, MediaRecordController, TirePressureController |
| `Areas/Safety/` | 主动安全 | AlarmEventController, ADASAlarmController, DSMAlarmController, BSDAlarmController, TPMSAlarmController, AlarmFileController, MediaResourceController |
| `Areas/Platform/` | å¹³å°ç®¡ç† | ForwardServerController, MediaServerController, SuperviseServerController, SuperviseOnlineController, CarListController, SimCardController |
### 2.5 消费æœåŠ¡ï¼ˆJT808.Worker — 新增)
独立进程è¿è¡Œï¼Œé€šè¿‡ Redis Stream 消费组消费å„主题数æ®ã€‚
| 组件 | 类型 | 说明 |
|------|------|------|
| `PositionWorker` | IHostedService | 消费 PositionData 主题,里程计算/åæ ‡è½¬æ¢ |
| `SensorWorker` | IHostedService | 消费 SensorData ä¸»é¢˜ï¼Œä¼ æ„Ÿå™¨æ•°æ®å¤„ç† |
| `EventWorker` | IHostedService | 消费 EventData ä¸»é¢˜ï¼Œè®¾å¤‡äº‹ä»¶å¤„ç† |
| `ADASAlarmWorker` | IHostedService | 消费 ADASAlarm 主题,ADAS æŠ¥è¦æŒä¹…化和èšåˆ |
| `DSMAlarmWorker` | IHostedService | 消费 DSMAlarm 主题,DSM æŠ¥è¦æŒä¹…化和èšåˆ |
| `BSDAlarmWorker` | IHostedService | 消费 BSDAlarm 主题,BSD æŠ¥è¦æŒä¹…化和èšåˆ |
| `TirePressureWorker` | IHostedService | 消费 TirePressure 主题,胎压数æ®å¤„ç† |
| `QueueService` | Singleton | Redis Stream 消费者工厂,创建 `IProducerConsumer<T>` 实例 |
## 3. 关键æµç¨‹
### 3.1 æ¶ˆæ¯æŽ¥æ”¶æµæ°´çº¿
```mermaid
sequenceDiagram
participant TCP as TCP æ•°æ®æµ
participant Codec as JTCodec
participant Frame as JTMessage
participant Factory as MessageFactory
participant Model as 业务模型(T0200ç‰)
TCP->>Codec: 原始å—节æµ
Codec->>Codec: 0x7E 分割粘包
Codec->>Codec: 0x7D 转义还原
Codec->>Frame: å•帧数æ®
Frame->>Frame: è¯»å– MessageKinds/Version/Mobile
Frame->>Frame: æ ¡éªŒå’ŒéªŒè¯
Frame->>Factory: Parse(JTMessage)
Factory->>Factory: Create(kind) 实例化
Factory->>Model: IAccessor.Read() 或 åå°„åºåˆ—化
Model-->>Factory: 业务模型对象
```
### 3.2 消æ¯å‘逿µæ°´çº¿
```mermaid
sequenceDiagram
participant App as 应用代ç
participant Factory as MessageFactory
participant Model as 业务模型
participant Frame as JTMessage
participant Codec as JTCodec
participant TCP as TCP æ•°æ®æµ
App->>Model: new T8001 { ... }
App->>Frame: new JTMessage { Kind, Mobile, Payload }
Model->>Frame: IAccessor.Write() → Payload
Frame->>Frame: 组帧(转义/æ ¡éªŒ/0x7E)
Frame->>Codec: 输出二进制帧
Codec->>TCP: å‘é€
```
### 3.3 版本兼容机制
```
JTMessage.Version
│
├── Version=0 (2013版)
│ └── [JT2019] ç‰¹æ€§æ ‡è®°çš„å—æ®µ → 跳过
│
└── Version=1 (2019版)
├── [JT2019] ç‰¹æ€§æ ‡è®°çš„å—æ®µ → 读写
├── [FullString2(Version="2013")] → 跳过
└── [FullString2(Version="2019")] → 读写
```
Binary åºåˆ—化器通过 `Binary.Version` å—符串("2013"/"2019")驱动特性æ¡ä»¶åˆ¤æ–,`Helper.CreateReader/CreateWriter` æ ¹æ® `JTMessage.Version` 自动设置。
### 3.4 Redis 消æ¯é˜Ÿåˆ—æµç¨‹
```mermaid
sequenceDiagram
participant TCP as TCP 终端
participant Handler as 指令处ç†å™¨
participant QueueS as QueueService(生产者)
participant Redis as Redis Stream
å‚与者的 Worker as JT808.Worker(消费者)
å‚与者的 DB as MySQL
TCP->>Handler: ä½ç½®ä¸ŠæŠ¥(T0200)
Handler->>Handler: è§£æžé™„åŠ ä¿¡æ¯
Handler->>QueueS: AddPosition()
QueueS->>Redis: PositionData Stream
Handler->>DB: SaveAsync(PositionData)
注:Worker 是独立进程,通过 Redis Stream 消费组消费
Redis->>Worker: 消费 PositionData
Worker->>Worker: 里程计算/åæ ‡è½¬æ¢
Worker->>DB: 写入处ç†ç»“æžœ
```
### 3.5 æŒ‡ä»¤ä¸‹å‘æµç¨‹ï¼ˆRedis 队列模å¼ï¼‰
```mermaid
sequenceDiagram
participant Web as JT808.Web
participant CmdClient as CommandClient
participant Redis as Redis command 队列
participant Server as JT808.Server
participant TCP2 as ç›®æ ‡ç»ˆç«¯ TCP
Web->>CmdClient: 选择指令类型/填充傿•°
CmdClient->>Redis: å‘布 CommandModel (Mobile/BodyType/BodyData)
Redis-->>Server: 消费 CommandModel
Server->>Server: 查找 Mobile 对应会è¯
alt 设备在本æœåС噍
Server->>TCP2: ç¼–ç 为 JT808 消æ¯å¹¶ä¸‹å‘
TCP2-->>Server: 终端应ç”
Server->>DB: æ›´æ–° DeviceCommand 状æ€
else 设备ä¸åœ¨æœ¬æœåС噍
Server->>Server: 跳过(集群场景下其他节点处ç†ï¼‰
end
```
### 3.6 设备注册/é‰´æƒæµç¨‹
```mermaid
sequenceDiagram
participant Device as 终端设备
participant Server as JT808.Server
participant Service as DeviceService
participant DB as JT808.Data
Device->>Server: T0100 终端注册
Server->>Service: AutoRegister(message)
Service->>DB: 查询 Device (按 Mobile/Code)
alt 设备ä¸å˜åœ¨ä¸”å…许自动注册
Service->>DB: Insert Device(分é…鉴æƒç )
Service-->>Server: 返回鉴æƒç
Server-->>Device: T8100 注册应ç”(å«é‰´æƒç )
else 设备已å˜åœ¨
Service-->>Server: 返回已有鉴æƒç
Server-->>Device: T8100 注册应ç”
end
Device->>Server: T0102 终端鉴æƒï¼ˆæºå¸¦é‰´æƒç )
Server->>Service: Authenticate(mobile, code)
Service->>DB: 验è¯é‰´æƒç
alt é‰´æƒæˆåŠŸ
Service->>DB: Update DeviceOnline(上线)
Server-->>Device: T8001 通用应ç”(æˆåŠŸï¼‰
else 鉴æƒå¤±è´¥
Server-->>Device: T8001 通用应ç”(失败)
end
```
## 4. åºåˆ—化ç–ç•¥
### 4.1 å射自动åºåˆ—åŒ–ï¼ˆç®€å•æ¶ˆæ¯ä½“)
é€‚ç”¨åœºæ™¯ï¼šå±žæ€§ç±»åž‹ä¸ºåŸºç¡€ç±»åž‹ã€æ— 特殊编解ç é€»è¾‘ã€æ— ç‰ˆæœ¬å·®å¼‚å—æ®µã€‚
```csharp
[MessageKind(MessageKinds.å¹³å°é€šç”¨åº”ç”)]
public class T8001
{
public UInt16 Sequence { get; set; }
public MessageKinds Kind { get; set; }
public ResultKinds Result { get; set; }
}
```
åºåˆ—化过程:
1. `Binary.TryWrite(null, ref obj)` åå°„é历属性
2. 检查 `[FieldSize]`ã€`[FullBytes]`ã€`[JT2019]` ç‰ç‰¹æ€§
3. 按声明顺åºè¯»å†™ï¼Œå¤§ç«¯åº
### 4.2 IAccessor 手动åºåˆ—åŒ–ï¼ˆå¤æ‚消æ¯ä½“)
é€‚ç”¨åœºæ™¯ï¼šå¤šç‰ˆæœ¬å—æ®µé•¿åº¦ä¸åŒã€åµŒå¥—结构ã€éœ€è¦ç‰¹æ®Šå¤„ç†çš„分支逻辑。
```csharp
[MessageKind(MessageKinds.终端注册)]
public class T0100 : IAccessor
{
public Boolean Read(Stream stream, Object context)
{
var reader = Helper.CreateReader(stream, context as JTMessage);
// 手写精确的读å–逻辑,å¯è®¿é—® header.Version 判æ–版本
}
}
```
é€‰æ‹©ä¾æ®ï¼š
- åå°„åºåˆ—化优先级更高(å‡å°‘æ ·æ¿ä»£ç )
- 仅当åå°„æ— æ³•æ»¡è¶³æ—¶ï¼ˆç‰ˆæœ¬å·®å¼‚ã€åµŒå¥—读å–ã€æ¡ä»¶è·³è¿‡ï¼‰æ‰é™çº§ä¸º IAccessor
## 5. 设计决ç–
### 5.1 å议库决ç–(Newlife.JT808 — ä¿æŒä¸å˜ï¼‰
| å†³ç– | 选项 | 选择 | ç†ç”± |
|------|------|------|------|
| åºåˆ—åŒ–æ¨¡å¼ | å…¨åå°„ vs 全手动 vs åŒæ¨¡å¼ | åŒæ¨¡å¼ | 大多数消æ¯ç®€å•å¯ç”¨åå°„ï¼Œå°‘æ•°å¤æ‚消æ¯éœ€è¦ç²¾ç¡®æŽ§åˆ¶ |
| 版本兼容 | if分支 vs 特性驱动 | 特性驱动 | 声明å¼çš„ `[JT2019]` 比内è”if更清晰,å‡å°‘é—æ¼ |
| 命å空间 | `NewLife.IoT` vs `NewLife.JT808` | `NewLife.JT808` | JT808 是独立å议领域,与 Modbus å¹³ç‰ |
| ç›®æ ‡æ¡†æž¶ | net7.0 vs å¤šç›®æ ‡ | å¤šç›®æ ‡ | 与 NewLife 生æ€ä¸€è‡´ï¼Œæœ€å¤§åŒ–兼容性 |
| 网络层 | 内置 vs å•独包 | 内置(åŒä¸€åŒ…) | ç²˜åŒ…ç¼–è§£ç æ˜¯åè®®åº“å¸¸ç”¨åŠŸèƒ½ï¼Œæ— éœ€å•独包 |
### 5.2 平尿ž¶æž„决ç–(新增)
| å†³ç– | 选项 | 选择 | ç†ç”± |
|------|------|------|------|
| 消æ¯é˜Ÿåˆ— | DefaultMsgQueue vs Redis Stream | **Redis Stream** | å¯¹æ ‡ GPS808 æˆç†Ÿæ¨¡å¼ï¼Œæ¶ˆè´¹ç»„+ACK,跨进程解耦 |
| æŒ‡ä»¤ä¸‹å‘ | StarFactory 事件总线 vs Redis 队列 | **Redis 队列** | 解耦 Web å’Œ Server,ä¸ä¾èµ–星尘,更适åˆç‹¬ç«‹éƒ¨ç½² |
| æ•°æ®åŸŸåˆ’分 | å• xml vs 多 xml 分域 | **多 xml 分域** | 实体超过 30 å¼ ï¼ŒæŒ‰åŸŸæ‹†åˆ†æ›´æ¸…æ™°ï¼ˆGPS/Safety/Platform) |
| 主键ç–ç•¥ | Int32 自增 vs Int64 雪花 | **æ··åˆ**:基础表 Int32 自增,大数æ®è¡¨ Int64 雪花 | PositionData/AlarmEvent ç‰é«˜é¢‘表用雪花é¿å…åˆ†ç‰‡å†²çª |
| æœåŠ¡ç«¯å¯åЍ | 控制å°ç›´å¯ vs HostedService | **HostedService** | 统一生命周期管ç†ï¼Œé¢„çƒæœºåˆ¶ï¼Œä¼˜é›…退出 |
| Server 框架 | çº¯æŽ§åˆ¶å° vs WebApplication | **WebApplication** | 内置å¥åº·æ£€æŸ¥ã€é…置系统,与 ASP.NET 生æ€ä¸€è‡´ |
| Worker 部署 | åˆå¹¶åœ¨ Server vs 独立进程 | **独立进程** | 解耦计算压力,å¯ç‹¬ç«‹æ‰©ç¼©å®¹ï¼Œå¯¹æ ‡ GpsWorker |
| Web 框架 | 原生 MVC vs Cube | **Cubeï¼ˆé”æ–¹ï¼‰** | 零代ç CRUD,Area 自动生æˆï¼Œå—段é…ç½®çµæ´» |
| æ•°æ®åº“连接 | å•库 vs 多连接串 | **多连接串 MapTo** | æ ¸å¿ƒ GPS 独立库,Safety/Platform å¯ MapTo 共享物ç†åº“或独立 |
| 分布å¼ç¼“å˜ | æ— vs RedisCacheProvider | **RedisCacheProvider** | 设备在线/会è¯çжæ€éœ€è¦åˆ†å¸ƒå¼å…±äº« |
| æ˜Ÿå°˜é›†æˆ | å¯é€‰ vs 强制 | **æ‰€æœ‰é¡¹ç›®å‡æ³¨å†Œ** | 统一æœåŠ¡æ²»ç†ï¼Œé…ç½®ä¸å¿ƒï¼Œå¥åº·ç›‘测 |
|