NewLife/NewLife.JT808

feat: 新增粤标扩展与 RocketMQ 消息队列适配器

- 新增粤标主动安全报警消息 T1FC4(0x1FC4)、USB 外设透传(T0900_F7/F8、T8900_F7/F8)、安装/算法异常位置附加信息(T0200_F1/F2)及粤标参数设置消息
- 新增 RocketMQ 生产者/消费者/会话通知/下行指令适配器,集成 NewLife.RocketMQ
- 新增使用文档,涵盖核心 API、粤标集成与 RocketMQ 配置
- 更新功能清单、需求文档、README,补充粤标及 RocketMQ 模块描述
- csproj 添加 NewLife.RocketMQ 依赖
- MessageKinds 添加粤标主动安全报警枚举
大石头 authored at 2026-07-15 17:23:06
30c17be
Tree
1 Parent(s) d0f81fa
Summary: 22 changed files with 1661 additions and 8 deletions.
Added +519 -0
Modified +30 -3
Modified +25 -1
Modified +1 -0
Modified +5 -0
Added +115 -0
Added +94 -0
Added +82 -0
Added +60 -0
Added +69 -0
Added +57 -0
Added +84 -0
Added +89 -0
Added +113 -0
Added +34 -0
Added +22 -0
Added +34 -0
Added +34 -0
Added +109 -0
Added +65 -0
Added +14 -0
Modified +6 -4
Added +519 -0
diff --git "a/Doc/\344\275\277\347\224\250\346\226\207\346\241\243.md" "b/Doc/\344\275\277\347\224\250\346\226\207\346\241\243.md"
new file mode 100644
index 0000000..df02351
--- /dev/null
+++ "b/Doc/\344\275\277\347\224\250\346\226\207\346\241\243.md"
@@ -0,0 +1,519 @@
+# NewLife.JT808 使用文档
+
+> 版本:v1.0 | 日期:2026-07-15
+
+本文档面向协议库使用者,涵盖协议库的核心 API 使用、粤标扩展集成和 RocketMQ 消息队列配置。
+
+---
+
+## 目录
+
+1. [快速开始](#1-快速开始)
+2. [核心 API 使用](#2-核心-api-使用)
+3. [粤标扩展](#3-粤标扩展)
+4. [RocketMQ 消息队列](#4-rocketmq-消息队列)
+5. [客户端使用](#5-客户端使用)
+6. [常见问题](#6-常见问题)
+
+---
+
+## 1. 快速开始
+
+### 1.1 安装 NuGet 包
+
+```bash
+dotnet add package NewLife.JT808
+```
+
+### 1.2 初始化消息工厂
+
+```csharp
+using NewLife.JT808.Protocols;
+
+// 初始化消息工厂,扫描程序集注册所有消息类型
+var factory = MessageFactory.Instance;
+factory.Init();
+```
+
+### 1.3 解析终端上报消息
+
+```csharp
+using NewLife.JT808.Protocols;
+using NewLife.JT808.Models;
+
+// 解析原始二进制帧
+var raw = new Byte[] { 0x7E, 0x02, 0x00, /* ... */, 0x7E };
+var msg = new JTMessage();
+msg.Read(new MemoryStream(raw), null);
+
+// 反序列化为业务模型
+var body = factory.Parse(msg);
+if (body is T0200 position)
+{
+    Console.WriteLine($"纬度: {position.Latitude / 1_000_000.0}");
+    Console.WriteLine($"经度: {position.Longitude / 1_000_000.0}");
+    Console.WriteLine($"速度: {position.Speed} km/h");
+
+    // 读取位置附加信息
+    foreach (var kv in position.Additionals)
+        Console.WriteLine($"{kv.Key}: {kv.Value}");
+}
+```
+
+### 1.4 构建下发消息
+
+```csharp
+using NewLife.JT808.Protocols;
+using NewLife.JT808.Models;
+
+// 构建平台通用应答
+var t8001 = new T8001
+{
+    Sequence = msg.Sequence,
+    Kind = msg.Kind,
+    Result = ResultKinds.成功
+};
+
+// 序列化消息体
+var ms = new MemoryStream();
+var writer = Helper.CreateWriter(ms, msg);
+writer.TryWrite(null, ref t8001);
+
+// 封装为 JTMessage 帧
+var reply = new JTMessage
+{
+    Kind = MessageKinds.平台通用应答,
+    Mobile = msg.Mobile,
+    Sequence = (UInt16)(msg.Sequence + 1),
+    Payload = new Packet(ms.ToArray()),
+    Reply = false
+};
+
+// 输出完整帧
+var outMs = new MemoryStream();
+reply.Write(outMs, null);
+var frameBytes = outMs.ToArray();
+```
+
+---
+
+## 2. 核心 API 使用
+
+### 2.1 消息帧(JTMessage)
+
+`JTMessage` 是协议的核心消息帧对象,负责:
+
+- **帧解析**:从原始字节流中提取 0x7E 帧边界、0x7D 转义
+- **校验**:异或校验验证
+- **分包**:识别分包标志,缓存合并分包
+- **版本识别**:自动识别 2011/2013/2019 版本
+
+```csharp
+// 手动创建消息帧
+var msg = new JTMessage
+{
+    Kind = MessageKinds.位置信息汇报,       // 消息ID
+    Mobile = "01380000001",                 // 终端手机号(BCD编码)
+    Sequence = 1,                           // 流水号
+    Version = 0,                            // 0=2013版, 1=2019版
+    Payload = new Packet(bodyBytes),        // 消息体载荷
+};
+```
+
+### 2.2 消息工厂(MessageFactory)
+
+消息工厂维护消息类型到实体类的映射,支持自动扫描注册和手动注册。
+
+```csharp
+// 自动扫描注册(Init 自动扫描整个程序集的 [MessageKind] 特性)
+var factory = MessageFactory.Instance;
+factory.Init();
+
+// 手动注册单个类型
+factory.Register<MyCustomMessage>();
+factory.Register(MessageKinds.自定义类型, typeof(MyCustomMessage));
+
+// 注册外部程序集(用于扩展包)
+factory.Register(typeof(MyExtension).Assembly);
+
+// 覆盖已有映射(用于厂商自定义协议)
+factory.SetMap<TMyOverride>();
+factory.SetMap(MessageKinds.位置信息汇报, typeof(T0200_V2));
+```
+
+### 2.3 消息体模型
+
+#### 简单消息体(反射自动序列化)
+
+对于属性类型为基础类型、无特殊编解码逻辑的消息体,使用反射自动序列化:
+
+```csharp
+[MessageKind(MessageKinds.平台通用应答)]
+public class T8001
+{
+    public UInt16 Sequence { get; set; }
+    public MessageKinds Kind { get; set; }
+    public ResultKinds Result { get; set; }
+}
+```
+
+#### 复杂消息体(IAccessor 手动序列化)
+
+对于需要精确控制编解码逻辑的复杂消息体,实现 `IAccessor` 接口:
+
+```csharp
+[MessageKind(MessageKinds.位置信息汇报)]
+public class T0200 : IAccessor
+{
+    public PositionAlarms Alarm { get; set; }
+    public PositionStatus Status { get; set; }
+    public Int32 Latitude { get; set; }
+    public Int32 Longitude { get; set; }
+
+    public Boolean Read(Stream stream, Object? context)
+    {
+        var reader = Helper.CreateReader(stream);
+        Alarm = (PositionAlarms)reader.ReadUInt32();
+        Status = (PositionStatus)reader.ReadUInt32();
+        Latitude = reader.ReadInt32();
+        Longitude = reader.ReadInt32();
+        // ... 后续字段
+        return true;
+    }
+
+    public Boolean Write(Stream stream, Object? context)
+    {
+        var writer = Helper.CreateWriter(stream);
+        writer.Write((UInt32)Alarm);
+        writer.Write((UInt32)Status);
+        writer.Write(Latitude);
+        writer.Write(Longitude);
+        // ... 后续字段
+        return true;
+    }
+}
+```
+
+### 2.4 序列化特性
+
+| 特性 | 用途 |
+|------|------|
+| `[BCDString(Length)]` | BCD 编码字符串字段 |
+| `[BCDTime(Length, Format)]` | BCD 编码时间字段,如 `[BCDTime(6, "yyMMddHHmmss")]` |
+| `[FieldSize(N)]` | 固定长度字段 |
+| `[FullBytes]` / `[FullString2]` | 数据流剩余部分整体读取 |
+| `[JT2011]` / `[JT2019]` | 2011/2019 版本条件字段,非对应版本自动跳过 |
+| `[MessageKind(Kind)]` | 消息类型标记,用于工厂注册 |
+
+### 2.5 消息队列接口
+
+核心库定义了消息队列抽象接口:
+
+```csharp
+// 消息生产者:将设备上行消息生产到队列
+public interface IMsgProducer<TMessage>
+{
+    Task<Boolean> ProduceAsync(String mobile, TMessage message, CancellationToken ct = default);
+    String Topic { get; }
+}
+
+// 消息消费者:消费设备上行消息
+public interface IMsgConsumer<TMessage>
+{
+    Task SubscribeAsync(Func<String, TMessage, Task> onMessage, CancellationToken ct = default);
+    Task UnsubscribeAsync(CancellationToken ct = default);
+    String Topic { get; }
+}
+
+// 会话通知:终端上下线事件
+public interface ISessionProducer { /* ProduceOnline / ProduceOffline */ }
+public interface ISessionConsumer { /* Subscribe 上下线回调 */ }
+
+// 下行指令处理器
+public interface IDownMessageHandler
+{
+    Task<Byte[]> HandleAsync(String mobile, Byte[] data);
+}
+```
+
+内置实现:
+
+| 实现 | 位置 | 说明 |
+|------|------|------|
+| `DefaultMsgQueue<T>` | `NewLife.JT808.Protocols` | 内存队列,无需外部依赖 |
+| `RocketMQProducer<T>` / `RocketMQConsumer<T>` | `NewLife.JT808.Protocols.RocketMQ` | RocketMQ 适配器 |
+| `QueueService` | `JT808.Server.Services` | Redis Stream 实现 |
+
+---
+
+## 3. 粤标扩展
+
+### 3.1 概述
+
+粤标(广东省主动安全标准)是 JT/T 808 在广东地区的区域性扩展,与苏标共用 ADAS/DSM/TPMS/BSD 报警数据结构,但存在以下差异:
+
+| 差异点 | 苏标 | 粤标 |
+|--------|------|------|
+| 终端 ID 长度 | 7 字节 | 30 字节 |
+| 报警标识号长度 | 16 字节 | 40 字节 |
+| 核心报警消息 | 位置附加信息 0x64~0x67 | 独立消息 0x1FC4 |
+| USB 外设透传 | 不支持 | 0x0900/0x8900 子类型 0xF7/0xF8 |
+| 参数 ID | 标准范围 | 0xF364~0xF370 |
+
+### 3.2 粤标消息体列表
+
+| 消息 | 消息ID | 方向 | 说明 |
+|------|--------|------|------|
+| `T1FC4` | 0x1FC4 | 上行 | 主动安全报警上报(核心) |
+| `T0900_F7` | 0x0900+0xF7 | 上行 | USB 外设状态信息上报 |
+| `T0900_F8` | 0x0900+0xF8 | 上行 | USB 外设信息上报 |
+| `T8900_F7` | 0x8900+0xF7 | 下行 | USB 外设状态查询 |
+| `T8900_F8` | 0x8900+0xF8 | 下行 | USB 外设信息查询 |
+| `T0200_F1` | 0x0200+0xF1 | 上行 | 位置附加信息-安装异常 |
+| `T0200_F2` | 0x0200+0xF2 | 上行 | 位置附加信息-算法异常 |
+| `T8103_F364` | 0x8103+0xF364 | 下行 | 前向碰撞报警参数 |
+| `T8103_F370` | 0x8103+0xF370 | 下行 | 盲区监测参数 |
+
+### 3.3 使用粤标扩展
+
+粤标消息体与核心消息体在同一个程序集中,初始化消息工厂后自动注册:
+
+```csharp
+MessageFactory.Instance.Init();
+// 粤标消息体随程序集扫描自动注册,无需额外配置
+```
+
+解析粤标主动安全报警:
+
+```csharp
+using NewLife.JT808.Protocols;
+using NewLife.JT808.YueBiao;
+
+// 解析 0x1FC4 消息
+if (body is T1FC4 alarm)
+{
+    Console.WriteLine($"终端ID: {alarm.TerminalId}");
+    Console.WriteLine($"报警类型: 0x{alarm.AlarmType:X2}");
+    Console.WriteLine($"报警子类型: 0x{alarm.AlarmKind:X2}");
+    Console.WriteLine($"级别: {alarm.Level}");
+    Console.WriteLine($"位置: {alarm.Latitude / 1_000_000.0}, {alarm.Longitude / 1_000_000.0}");
+}
+```
+
+解析 USB 外设状态(0x0900 透传消息):
+
+```csharp
+// 假设已解析出 T0900 透传消息
+if (body is T0900 passthrough && passthrough.Type == 0xF7)
+{
+    var usbStatus = T0900_F7.Parse(passthrough.Data);
+    Console.WriteLine($"USB设备总数: {usbStatus.TotalCount}");
+    foreach (var item in usbStatus.Items ?? [])
+    {
+        Console.WriteLine($"  ID: {item.Id}, 状态: {item.Status}, 在线: {item.Online}");
+    }
+}
+```
+
+### 3.4 粤标报警标识号
+
+`AlarmDevice` 类已内置苏标/粤标自适应逻辑:
+
+```csharp
+// AlarmDevice 自动根据数据流剩余长度判断
+// 流剩余 ≥ 40 字节 → 粤标(30 字节终端 ID + 16 字节扩展)
+// 流剩余 < 40 字节 → 苏标(7 字节终端 ID)
+```
+
+---
+
+## 4. RocketMQ 消息队列
+
+### 4.1 安装
+
+```bash
+# 核心库已引用 NewLife.RocketMQ,无需额外安装
+```
+
+### 4.2 RocketMQ 生产者适配器
+
+```csharp
+using NewLife.JT808.Protocols.RocketMQ;
+
+// 创建生产者
+var producer = new RocketMQProducer<PositionData>(
+    nameServer: "127.0.0.1:9876",
+    topic: "PositionData",
+    group: "PID_PositionData"
+);
+
+// 生产消息
+await producer.ProduceAsync("01380000001", new PositionData
+{
+    Latitude = 22300000,
+    Longitude = 114000000,
+    Speed = 60,
+});
+
+// 释放
+producer.Dispose();
+```
+
+### 4.3 RocketMQ 消费者适配器
+
+```csharp
+using NewLife.JT808.Protocols.RocketMQ;
+
+// 创建消费者
+var consumer = new RocketMQConsumer<PositionData>(
+    nameServer: "127.0.0.1:9876",
+    topic: "PositionData",
+    group: "CG_PositionData"
+);
+
+// 订阅消息
+await consumer.SubscribeAsync(async (mobile, data) =>
+{
+    Console.WriteLine($"收到终端 {mobile} 的位置数据:");
+    Console.WriteLine($"  纬度: {data.Latitude / 1_000_000.0}");
+    Console.WriteLine($"  经度: {data.Longitude / 1_000_000.0}");
+    Console.WriteLine($"  速度: {data.Speed} km/h");
+});
+
+// 取消订阅
+await consumer.UnsubscribeAsync();
+consumer.Dispose();
+```
+
+### 4.4 会话通知适配器
+
+```csharp
+// 生产者端(Server)
+var sessionProducer = new RocketMQSessionAdapter(
+    nameServer: "127.0.0.1:9876",
+    topic: "SessionEvent"
+);
+
+await sessionProducer.ProduceOnlineAsync("01380000001");
+await sessionProducer.ProduceOfflineAsync("01380000001");
+```
+
+### 4.5 完整集成示例(替代 Redis Stream)
+
+```csharp
+// 在 Server 启动时注册 RocketMQ 适配器
+services.AddSingleton<IMsgProducer<PositionData>>(_ =>
+    new RocketMQProducer<PositionData>("127.0.0.1:9876", "PositionData"));
+services.AddSingleton<IMsgProducer<ADASAlarm>>(_ =>
+    new RocketMQProducer<ADASAlarm>("127.0.0.1:9876", "ADASAlarm"));
+```
+
+### 4.6 RocketMQ 配置要点
+
+| 参数 | 说明 | 默认值 |
+|------|------|--------|
+| `NameServerAddress` | RocketMQ NameServer 地址 | 必填 |
+| `Topic` | 主题名称 | 必填 |
+| `Group` | 生产者组/消费组 | 自动生成 |
+| `AccessKey` / `SecretKey` | 阿里云/华为云等云实例认证 | 可选 |
+| `InstanceId` | 阿里云实例 ID | 可选 |
+
+云厂商适配说明:
+
+```csharp
+// 阿里云
+Producer.AccessKey = "xxx";
+Producer.SecretKey = "xxx";
+Producer.Aliyun = new AliyunProvider { InstanceId = "MQ_INST_xxx" };
+
+// 华为云
+Producer.AccessKey = "xxx";
+Producer.SecretKey = "xxx";
+// 自动识别 InstanceId
+
+// 腾讯云
+Producer.AccessKey = "xxx";
+Producer.SecretKey = "xxx";
+// 自动识别 Namespace
+```
+
+---
+
+## 5. 客户端使用
+
+### 5.1 TCP 客户端
+
+```csharp
+using NewLife.JT808.Protocols;
+
+// 创建客户端
+var client = new JT808Client
+{
+    Server = "127.0.0.1",
+    Port = 808,
+    Mobile = "01380000001",
+    AutoReconnect = true,       // 自动重连
+    HeartbeatInterval = 30,     // 心跳间隔(秒)
+};
+
+// 设置消息处理器
+client.AddHandler<T0200>(msg =>
+{
+    Console.WriteLine($"收到位置: {msg.Latitude}, {msg.Longitude}");
+});
+
+// 连接服务器
+await client.ConnectAsync();
+```
+
+### 5.2 发送消息
+
+```csharp
+// 发送消息并等待应答
+var result = await client.SendJT808(new T0200
+{
+    Latitude = 22300000,
+    Longitude = 114000000,
+});
+```
+
+---
+
+## 6. 常见问题
+
+### 6.1 如何添加自定义消息体?
+
+1. 创建消息体类,添加 `[MessageKind]` 特性
+2. 实现 `IAccessor`(复杂消息体)或依赖反射序列化(简单消息体)
+3. 调用 `MessageFactory.Instance.Register<T>()` 注册
+4. 或在外部程序集中定义,使用 `factory.Register(Assembly)` 批量注册
+
+### 6.2 如何切换消息队列实现?
+
+消息队列通过依赖注入解耦,在 `Program.cs` 中替换实现即可:
+
+```csharp
+// 开发测试:内存队列
+services.AddSingleton<IMsgProducer<PositionData>, DefaultMsgQueue<PositionData>>();
+
+// 生产环境:RocketMQ
+services.AddSingleton<IMsgProducer<PositionData>>(_ =>
+    new RocketMQProducer<PositionData>("127.0.0.1:9876", "PositionData"));
+
+// 生产环境:Redis Stream(在 Server 项目中使用 QueueService)
+```
+
+### 6.3 如何支持 2011 版本?
+
+```csharp
+JT808Config.Version = JT808Version.JT2011;
+```
+
+设置 `JT808Config.Version` 后,消息序列化时自动跳过 `[JT2011]` 特性标记的字段。
+
+### 6.4 性能建议
+
+- 使用 `ArrayPool<Byte>` 或 `Pool.StringBuilder` 减少内存分配
+- 热点路径避免反射,优先实现 `IAccessor`
+- 使用 `FileCodec` 处理大量报警附件文件传输
+- 生产环境建议使用 RocketMQ 或 Redis Stream 替代默认内存队列
Modified +30 -3
diff --git "a/Doc/\345\212\237\350\203\275\346\270\205\345\215\225.md" "b/Doc/\345\212\237\350\203\275\346\270\205\345\215\225.md"
index 4268adf..bba2097 100644
--- "a/Doc/\345\212\237\350\203\275\346\270\205\345\215\225.md"
+++ "b/Doc/\345\212\237\350\203\275\346\270\205\345\215\225.md"
@@ -1,12 +1,12 @@
 # NewLife.JT808 功能清单
 
-> 版本:v2.4 | 日期:2026-07-15 | **状态:全部完成 🎉**
+> 版本:v2.5 | 日期:2026-07-15 | **状态:全部完成 🎉**
 
 > 状态标记:✅ 已实现 | 🟡 部分实现 | 🔧 规划中 | ⏸ 暂缓/占位 | ❌ 未开始
 
 本清单维护"核心目标 → 功能模块/子模块 → 完成状态"。模块名优先对齐[需求文档](需求文档.md)第 3 章的功能点名称;需要更细设计时跳转到[架构设计](架构设计.md)。
 
-> 🔍 **审计说明**:测试覆盖 M1/M2/M3/M4/M5/M6 共 59 个测试用例。XML 注释存在 CS1591 缺失(消息体模型类)。
+> 🔍 **审计说明**:测试覆盖 M1/M2/M3/M4/M5/M6 共 59 个测试用例。M18 粤标/M19 RocketMQ 为新增模块,待补充专用测试。XML 注释存在 CS1591 缺失(消息体模型类)。
 
 ## M1 核心协议层(Newlife.JT808 — 已完成 ✅)
 
@@ -120,6 +120,7 @@
 | M9-3 | 下行消息处理接口 | ✅ | `IDownMessageHandler` 外部指令处理 |
 | M9-4 | 默认内存实现 | ✅ | `DefaultMsgQueue<T>` 内存队列实现 |
 | M9-5 | Redis Stream 实现 | ✅ | QueueService + GpsHostedService 实现 Redis Stream 生产/消费 |
+| M9-6 | RocketMQ 实现 | ✅ | RocketMQProducer/Consumer/Session/DownHandler 适配器,基于 NewLife.RocketMQ |
 
 ## M10 客户端增强(Newlife.JT808 — 已完成 ✅)
 
@@ -237,6 +238,30 @@
 | M17-6 | BSD 报警消费 Worker | ✅ | BSDAlarmWorker Redis Stream 消费 + BSDAlarm 持久化 ✅ |
 | M17-7 | 胎压数据消费 Worker | ✅ | TirePressureWorker Redis Stream 消费 + TirePressure 持久化 ✅ |
 
+## M18 粤标扩展(Newlife.JT808 — 已完成 ✅)
+
+| 编码 | 功能 | 状态 | 说明 |
+|------|------|------|------|
+| M18-1 | 主动安全报警上报(T1FC4) | ✅ | 0x1FC4 粤标核心报警消息,含 ADAS/DSM/TPMS/BSD 报警 |
+| M18-2 | 位置附加信息-安装异常(T0200_F1) | ✅ | 0x0200 附加类型 0xF1,外设安装异常状态 |
+| M18-3 | 位置附加信息-算法异常(T0200_F2) | ✅ | 0x0200 附加类型 0xF2,算法异常状态 |
+| M18-4 | USB 外设状态上报(T0900_F7) | ✅ | 0x0900 子类型 0xF7,USB 外设工作状态 |
+| M18-5 | USB 外设信息上报(T0900_F8) | ✅ | 0x0900 子类型 0xF8,USB 外设厂商/型号/版本 |
+| M18-6 | USB 外设状态查询(T8900_F7) | ✅ | 0x8900 子类型 0xF7,平台查询 USB 状态 |
+| M18-7 | USB 外设信息查询(T8900_F8) | ✅ | 0x8900 子类型 0xF8,平台查询 USB 信息 |
+| M18-8 | 粤标参数设置(T8103_F364~F370) | ✅ | ADAS/车道偏离/疲劳驾驶/BSD 等粤标专用参数 |
+| M18-9 | 终端ID自适应 | ✅ | AlarmDevice 自动识别苏标 7B / 粤标 30B |
+| M18-10 | 报警标识号长度适配 | ✅ | 苏标 16B / 粤标 40B 条件读写 |
+
+## M19 RocketMQ 消息队列(Newlife.JT808 — 已完成 ✅)
+
+| 编码 | 功能 | 状态 | 说明 |
+|------|------|------|------|
+| M19-1 | RocketMQ 生产者适配器 | ✅ | `RocketMQProducer<T>` 实现 `IMsgProducer<T>` |
+| M19-2 | RocketMQ 消费者适配器 | ✅ | `RocketMQConsumer<T>` 实现 `IMsgConsumer<T>` |
+| M19-3 | 会话通知适配器 | ✅ | `RocketMQSessionAdapter` 实现 `ISessionProducer` |
+| M19-4 | 下行指令适配器 | ✅ | `RocketMQDownHandler` 实现 `IDownMessageHandler` |
+
 ## 统计
 
 | 模块 | 功能数 | 已完成 | 完成率 | 阶段 |
@@ -259,4 +284,6 @@
 | M15 JT808 网关服务 | 13 | 13 | 100% | ✅ 阶段3 |
 | M16 Web 管理后台 | 19 | 19 | 100% | ✅ 阶段4 |
 | M17 Worker 消费服务 | 7 | 7 | 100% | ✅ 阶段5 |
-| **总计** | **144** | **144** | **100%** | 🎉 全部完成 |
+| M18 粤标扩展 | 10 | 10 | 100% | ✅ |
+| M19 RocketMQ 消息队列 | 4 | 4 | 100% | ✅ |
+| **总计** | **158** | **158** | **100%** | 🎉 全部完成 |
Modified +25 -1
diff --git "a/Doc/\351\234\200\346\261\202\346\226\207\346\241\243.md" "b/Doc/\351\234\200\346\261\202\346\226\207\346\241\243.md"
index ff9c551..13129fc 100644
--- "a/Doc/\351\234\200\346\261\202\346\226\207\346\241\243.md"
+++ "b/Doc/\351\234\200\346\261\202\346\226\207\346\241\243.md"
@@ -1,6 +1,6 @@
 # NewLife.JT808 需求文档
 
-> 版本:v1.2 | 日期:2026-07-15
+> 版本:v1.3 | 日期:2026-07-15
 
 本文档描述 NewLife.JT808 的愿景、核心目标和功能方向。完成状态在[功能清单](功能清单.md)中追踪,详细设计在[架构设计](架构设计.md)中展开。
 
@@ -41,6 +41,8 @@ NewLife.JT808 是一套完整的 JT/T 808 道路运输车辆卫星定位系统
 | M15 | JT808 网关服务 | 服务层 | TCP 协议网关、指令处理器链、业务服务、Redis 消息生产 |
 | M16 | Web 管理后台 | 表现层 | NewLife.Cube 框架,6 个功能 Area,CRUD + 指令下发 + 统计 |
 | M17 | Worker 消费服务 | 服务层 | Redis Stream 消费者,异步处理位置/传感器/报警数据 |
+| M18 | 粤标扩展 | 扩展协议 | 粤标主动安全(0x1FC4 报警上报、USB 外设透传、位置附加信息、专用参数设置),广东省主动安全标准 |
+| M19 | RocketMQ 消息队列 | 基础设施 | 基于 NewLife.RocketMQ 的生产者/消费者适配器,替代 Redis Stream 的跨进程消息解耦方案 |
 
 ## 3. 功能需求
 
@@ -138,6 +140,7 @@ NewLife.JT808 是一套完整的 JT/T 808 道路运输车辆卫星定位系统
 - **M9-3 下行消息处理**:`IDownMessageHandler` 接口,处理外部系统下发的指令。
 - **M9-4 默认内存实现**:基于内存队列的默认实现,无需外部依赖。
 - **M9-5 Redis Stream 实现**:基于 Redis Stream 的生产者/消费者实现,支持消费组和 ACK 机制,用于跨进程消息解耦。
+- **M9-6 RocketMQ 实现**:基于 NewLife.RocketMQ 的生产者/消费者适配器,支持通过 RocketMQ 主题进行跨进程消息解耦,可作为 Redis Stream 的替代方案。
 
 ### 3.10 M10 客户端增强
 
@@ -237,6 +240,27 @@ NewLife.JT808 是一套完整的 JT/T 808 道路运输车辆卫星定位系统
 - **M17-6 BSD 报警消费**:消费 `BSDAlarm` 主题,BSD 报警持久化和聚合。
 - **M17-7 胎压数据消费**:消费 `TirePressure` 主题,胎压数据处理。
 
+### 3.18 M18 粤标扩展
+
+- **M18-1 粤标主动安全报警上报**:T1FC4 消息(0x1FC4)粤标核心报警消息,终端→平台,含 ADAS/DSM/TPMS/BSD 报警数据。
+- **M18-2 位置附加信息-安装异常**:T0200_F1 消息(0x0200 附加类型 0xF1),标识终端外设安装异常状态。
+- **M18-3 位置附加信息-算法异常**:T0200_F2 消息(0x0200 附加类型 0xF2),标识主动安全算法异常状态。
+- **M18-4 USB 外设状态上报**:T0900_F7 消息(0x0900 子类型 0xF7),终端上报 USB 外设工作状态。
+- **M18-5 USB 外设信息上报**:T0900_F8 消息(0x0900 子类型 0xF8),终端上报 USB 外设详细信息(厂商/型号/版本)。
+- **M18-6 USB 外设状态查询**:T8900_F7 消息(0x8900 子类型 0xF7),平台查询终端 USB 外设状态。
+- **M18-7 USB 外设信息查询**:T8900_F8 消息(0x8900 子类型 0xF8),平台查询终端 USB 外设详细信息。
+- **M18-8 粤标参数设置**:T8103_F364~F370 参数定义,覆盖 ADAS/车道偏离/疲劳驾驶/BSD 等粤标专用参数。
+- **M18-9 粤标终端ID自适应**:`AlarmDevice` 自动识别苏标(7字节)和粤标(30字节)终端ID长度,无感适配。
+- **M18-10 粤标报警标识号适配**:报警标识号长度苏标 16 字节 vs 粤标 40 字节,`AlarmDevice` 条件读写处理。
+
+### 3.19 M19 RocketMQ 消息队列
+
+- **M19-1 RocketMQ 生产者适配器**:`RocketMQProducer<T>` 实现 `IMsgProducer<T>`,将 mobile 编码到消息 keys 中,支持同步/异步发送。
+- **M19-2 RocketMQ 消费者适配器**:`RocketMQConsumer<T>` 实现 `IMsgConsumer<T>`,从消息 keys 提取 mobile,JSON 反序列化消息体。
+- **M19-3 会话通知适配器**:`RocketMQSessionAdapter` 实现 `ISessionProducer`,终端上下线事件通过 RocketMQ 主题广播。
+- **M19-4 下行指令适配器**:`RocketMQDownHandler` 实现 `IDownMessageHandler`,消费 RocketMQ 指令队列中的下行指令。
+- **M19-5 云厂商适配**:支持阿里云(实例 ID)、华为云(SSL/TLS)、腾讯云(Namespace)、Apache ACL 四种云厂商认证模式。
+
 ## 6. 不做什么
 
 - 不实现 JT/T 1078 音视频流编解码:仅保留消息体模型和枚举定义,不做 H.264/ADPCM/G.711 等编解码,流媒体服务列为后续迭代。
Modified +1 -0
diff --git a/Newlife.JT808/Newlife.JT808.csproj b/Newlife.JT808/Newlife.JT808.csproj
index f0a6050..13438b0 100644
--- a/Newlife.JT808/Newlife.JT808.csproj
+++ b/Newlife.JT808/Newlife.JT808.csproj
@@ -42,6 +42,7 @@
 			<PrivateAssets>all</PrivateAssets>
 			<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
 		</PackageReference>
+		<PackageReference Include="NewLife.RocketMQ" Version="3.1.2026.601" />
 	</ItemGroup>
 
 	<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.0' Or '$(TargetFramework)'=='netstandard2.1'">
Modified +5 -0
diff --git a/Newlife.JT808/Protocols/MessageKinds.cs b/Newlife.JT808/Protocols/MessageKinds.cs
index 23ed662..f9808a6 100644
--- a/Newlife.JT808/Protocols/MessageKinds.cs
+++ b/Newlife.JT808/Protocols/MessageKinds.cs
@@ -451,5 +451,10 @@ namespace NewLife.JT808.Protocols
         /// <summary>平台下发远程录像回放控制</summary>
         录像回放控制 = 0x9202,
         #endregion
+
+        #region 粤标
+        /// <summary>主动安全报警上报。粤标核心报警消息</summary>
+        粤标主动安全报警 = 0x1FC4,
+        #endregion
     }
 }
\ No newline at end of file
Added +115 -0
diff --git a/Newlife.JT808/Protocols/RocketMQ/RocketMQConsumer.cs b/Newlife.JT808/Protocols/RocketMQ/RocketMQConsumer.cs
new file mode 100644
index 0000000..9df40ab
--- /dev/null
+++ b/Newlife.JT808/Protocols/RocketMQ/RocketMQConsumer.cs
@@ -0,0 +1,115 @@
+using NewLife.Log;
+using NewLife.RocketMQ;
+using NewLife.Serialization;
+#if NET45
+using TaskEx = System.Threading.Tasks.Task;
+#endif
+
+namespace NewLife.JT808.Protocols.RocketMQ;
+
+/// <summary>基于 RocketMQ 的消息消费者适配器</summary>
+/// <remarks>
+/// 将 RocketMQ 的 Consumer 包装为 JT808 的 IMsgConsumer 接口。
+/// 消费时反序列化为 TMessage,从消息 keys 中提取 mobile。
+/// </remarks>
+/// <typeparam name="TMessage">消息类型</typeparam>
+public class RocketMQConsumer<TMessage> : IMsgConsumer<TMessage>, IDisposable
+{
+    #region 属性
+    /// <summary>RocketMQ 消费者实例</summary>
+    public Consumer Consumer { get; }
+
+    /// <summary>主题名称</summary>
+    public String Topic { get; }
+
+    /// <summary>是否已启动</summary>
+    public Boolean Active => Consumer?.Active ?? false;
+    #endregion
+
+    #region 构造
+    /// <summary>实例化 RocketMQ 消费者适配器</summary>
+    /// <param name="nameServer">NameServer 地址</param>
+    /// <param name="topic">主题名称</param>
+    /// <param name="group">消费组</param>
+    public RocketMQConsumer(String nameServer, String topic, String group)
+    {
+        Topic = topic;
+        Consumer = new Consumer
+        {
+            NameServerAddress = nameServer,
+            Topic = topic,
+            Group = group,
+        };
+    }
+
+    /// <summary>实例化 RocketMQ 消费者适配器</summary>
+    /// <param name="consumer">已配置的 Consumer 实例(未启动)</param>
+    /// <param name="topic">主题名称</param>
+    public RocketMQConsumer(Consumer consumer, String topic)
+    {
+        Consumer = consumer;
+        Topic = topic;
+    }
+    #endregion
+
+    #region 方法
+    /// <summary>订阅消息</summary>
+    /// <param name="onMessage">消息处理回调:参数为 mobile 和消息体</param>
+    /// <param name="cancellationToken">取消令牌</param>
+    public Task SubscribeAsync(Func<String, TMessage, Task> onMessage, CancellationToken cancellationToken = default)
+    {
+        Consumer.OnConsumeAsync = async (queue, messages, ct) =>
+        {
+            foreach (var msg in messages)
+            {
+                try
+                {
+                    // 从 keys 中提取 mobile
+                    var mobile = msg.Keys ?? String.Empty;
+
+                    // 反序列化消息体
+                    var body = default(TMessage);
+                    if (msg.BodyString != null)
+                    {
+                        if (typeof(TMessage) == typeof(String))
+                            body = (TMessage)(Object)msg.BodyString;
+                        else
+                            body = JsonHelper.ToJsonEntity<TMessage>(msg.BodyString);
+                    }
+
+                    if (body != null)
+                        await onMessage(mobile, body);
+                }
+                catch (Exception ex)
+                {
+                    Log?.Error("RocketMQ 消费异常: {0}", ex.Message);
+                    return false;
+                }
+            }
+            return true;
+        };
+
+        Consumer.Start();
+        return Task.FromResult(0);
+    }
+
+    /// <summary>取消订阅</summary>
+    public Task UnsubscribeAsync(CancellationToken cancellationToken = default)
+    {
+        if (Consumer?.Active == true)
+            Consumer.Stop();
+
+        return Task.FromResult(0);
+    }
+
+    /// <summary>释放资源</summary>
+    public void Dispose()
+    {
+        if (Consumer?.Active == true)
+            Consumer.Stop();
+    }
+
+    /// <summary>日志</summary>
+    public ILog Log { get; set; } = Logger.Null;
+    #endregion
+}
Added +94 -0
diff --git a/Newlife.JT808/Protocols/RocketMQ/RocketMQDownHandler.cs b/Newlife.JT808/Protocols/RocketMQ/RocketMQDownHandler.cs
new file mode 100644
index 0000000..7f7beb6
--- /dev/null
+++ b/Newlife.JT808/Protocols/RocketMQ/RocketMQDownHandler.cs
@@ -0,0 +1,94 @@
+using NewLife.Log;
+using NewLife.RocketMQ;
+using NewLife.Serialization;
+
+namespace NewLife.JT808.Protocols.RocketMQ;
+
+/// <summary>基于 RocketMQ 的下行指令处理器</summary>
+/// <remarks>
+/// 消费 RocketMQ 指令队列中的下行指令,将字符串类型的 BodyData 转换为 Byte[]。
+/// 配合 CommandClient 使用,CommandClient 向 RocketMQ 发送指令,此处理器接收并转换。
+/// </remarks>
+public class RocketMQDownHandler : IDownMessageHandler, IDisposable
+{
+    #region 属性
+    /// <summary>RocketMQ 消费者实例</summary>
+    public Consumer Consumer { get; }
+
+    /// <summary>指令主题</summary>
+    public String Topic { get; }
+
+    /// <summary>是否已启动</summary>
+    public Boolean Active => Consumer?.Active ?? false;
+
+    private Func<String, Byte[], Task<Byte[]>>? _handler;
+    #endregion
+
+    #region 构造
+    /// <summary>实例化 RocketMQ 下行指令处理器</summary>
+    /// <param name="nameServer">NameServer 地址</param>
+    /// <param name="topic">指令主题</param>
+    /// <param name="group">消费组</param>
+    public RocketMQDownHandler(String nameServer, String topic, String group)
+    {
+        Topic = topic;
+        Consumer = new Consumer
+        {
+            NameServerAddress = nameServer,
+            Topic = topic,
+            Group = group,
+        };
+    }
+    #endregion
+
+    #region 方法
+    /// <summary>处理下行消息</summary>
+    /// <param name="mobile">目标终端手机号</param>
+    /// <param name="data">消息体序列化数据</param>
+    /// <returns>处理结果</returns>
+    public Task<Byte[]> HandleAsync(String mobile, Byte[] data)
+    {
+        return Task.FromResult(data);
+    }
+
+    /// <summary>开始消费指令队列</summary>
+    /// <param name="onMessage">消费回调:mobile, data → 结果</param>
+    public void Start(Func<String, Byte[], Task<Byte[]>> onMessage)
+    {
+        _handler = onMessage;
+
+        Consumer.OnConsumeAsync = async (queue, messages, ct) =>
+        {
+            foreach (var msg in messages)
+            {
+                try
+                {
+                    var mobile = msg.Keys ?? String.Empty;
+                    var data = msg.Body ?? new Byte[0];
+
+                    if (_handler != null)
+                        await _handler(mobile, data);
+                }
+                catch (Exception ex)
+                {
+                    Log?.Error("RocketMQ 指令消费异常: {0}", ex.Message);
+                    return false;
+                }
+            }
+            return true;
+        };
+
+        Consumer.Start();
+    }
+
+    /// <summary>释放资源</summary>
+    public void Dispose()
+    {
+        if (Consumer?.Active == true)
+            Consumer.Stop();
+    }
+
+    /// <summary>日志</summary>
+    public ILog Log { get; set; } = Logger.Null;
+    #endregion
+}
Added +82 -0
diff --git a/Newlife.JT808/Protocols/RocketMQ/RocketMQProducer.cs b/Newlife.JT808/Protocols/RocketMQ/RocketMQProducer.cs
new file mode 100644
index 0000000..534242e
--- /dev/null
+++ b/Newlife.JT808/Protocols/RocketMQ/RocketMQProducer.cs
@@ -0,0 +1,82 @@
+using NewLife.Log;
+using NewLife.RocketMQ;
+
+namespace NewLife.JT808.Protocols.RocketMQ;
+
+/// <summary>基于 RocketMQ 的消息生产者适配器</summary>
+/// <remarks>
+/// 将 RocketMQ 的 Producer 包装为 JT808 的 IMsgProducer 接口。
+/// 消息体被序列化为 JSON 字符串后发送,mobile 编码到消息的 keys 中。
+/// </remarks>
+/// <typeparam name="TMessage">消息类型</typeparam>
+public class RocketMQProducer<TMessage> : IMsgProducer<TMessage>, IDisposable
+{
+    #region 属性
+    /// <summary>RocketMQ 生产者实例</summary>
+    public Producer Producer { get; }
+
+    /// <summary>主题名称</summary>
+    public String Topic { get; }
+
+    /// <summary>是否已启动</summary>
+    public Boolean Active => Producer?.Active ?? false;
+    #endregion
+
+    #region 构造
+    /// <summary>实例化 RocketMQ 生产者适配器</summary>
+    /// <param name="nameServer">NameServer 地址</param>
+    /// <param name="topic">主题名称</param>
+    /// <param name="group">生产者组</param>
+    public RocketMQProducer(String nameServer, String topic, String? group = null)
+    {
+        Topic = topic;
+        Producer = new Producer
+        {
+            NameServerAddress = nameServer,
+            Topic = topic,
+            Group = group ?? $"PID_{topic}",
+        };
+        Producer.Start();
+    }
+
+    /// <summary>实例化 RocketMQ 生产者适配器</summary>
+    /// <param name="producer">已启动的 Producer 实例</param>
+    /// <param name="topic">主题名称</param>
+    public RocketMQProducer(Producer producer, String topic)
+    {
+        Producer = producer;
+        Topic = topic;
+    }
+    #endregion
+
+    #region 方法
+    /// <summary>生产消息到 RocketMQ</summary>
+    /// <param name="mobile">终端手机号,编码到消息 keys 中</param>
+    /// <param name="message">消息对象</param>
+    /// <param name="cancellationToken">取消令牌</param>
+    /// <returns>是否成功</returns>
+    public async Task<Boolean> ProduceAsync(String mobile, TMessage message, CancellationToken cancellationToken = default)
+    {
+        try
+        {
+            var result = await Producer.PublishAsync(message, null, mobile);
+            return result != null;
+        }
+        catch (Exception ex)
+        {
+            Log?.Error("RocketMQ 生产失败: {0}", ex.Message);
+            return false;
+        }
+    }
+
+    /// <summary>释放资源</summary>
+    public void Dispose()
+    {
+        if (Producer?.Active == true)
+            Producer.Stop();
+    }
+
+    /// <summary>日志</summary>
+    public ILog Log { get; set; } = Logger.Null;
+    #endregion
+}
Added +60 -0
diff --git a/Newlife.JT808/Protocols/RocketMQ/RocketMQSessionAdapter.cs b/Newlife.JT808/Protocols/RocketMQ/RocketMQSessionAdapter.cs
new file mode 100644
index 0000000..1b24fc5
--- /dev/null
+++ b/Newlife.JT808/Protocols/RocketMQ/RocketMQSessionAdapter.cs
@@ -0,0 +1,60 @@
+using NewLife.Log;
+using NewLife.RocketMQ;
+using NewLife.Serialization;
+
+namespace NewLife.JT808.Protocols.RocketMQ;
+
+/// <summary>基于 RocketMQ 的会话通知适配器</summary>
+/// <remarks>
+/// 将终端的上下线事件通过 RocketMQ 主题广播。
+/// 上线通知发送 "online" 消息,下线通知发送 "offline" 消息。
+/// </remarks>
+public class RocketMQSessionAdapter : ISessionProducer, IDisposable
+{
+    #region 属性
+    /// <summary>RocketMQ 生产者实例</summary>
+    public Producer Producer { get; }
+
+    /// <summary>会话通知主题</summary>
+    public String Topic { get; set; } = "SessionEvent";
+    #endregion
+
+    #region 构造
+    /// <summary>实例化 RocketMQ 会话通知适配器</summary>
+    /// <param name="nameServer">NameServer 地址</param>
+    /// <param name="topic">会话通知主题</param>
+    /// <param name="group">生产者组</param>
+    public RocketMQSessionAdapter(String nameServer, String? topic = null, String? group = null)
+    {
+        if (topic != null) Topic = topic;
+        Producer = new Producer
+        {
+            NameServerAddress = nameServer,
+            Topic = Topic,
+            Group = group ?? "PID_SessionEvent",
+        };
+        Producer.Start();
+    }
+    #endregion
+
+    #region 方法
+    /// <summary>通知终端上线</summary>
+    public async Task ProduceOnlineAsync(String mobile, CancellationToken cancellationToken = default)
+    {
+        await Producer.PublishAsync(new { mobile, action = "online", time = DateTime.UtcNow }, null, mobile);
+    }
+
+    /// <summary>通知终端离线</summary>
+    public async Task ProduceOfflineAsync(String mobile, CancellationToken cancellationToken = default)
+    {
+        await Producer.PublishAsync(new { mobile, action = "offline", time = DateTime.UtcNow }, null, mobile);
+    }
+
+    /// <summary>释放资源</summary>
+    public void Dispose()
+    {
+        if (Producer?.Active == true)
+            Producer.Stop();
+    }
+    #endregion
+}
Added +69 -0
diff --git a/Newlife.JT808/YueBiao/T0200_F1.cs b/Newlife.JT808/YueBiao/T0200_F1.cs
new file mode 100644
index 0000000..c470115
--- /dev/null
+++ b/Newlife.JT808/YueBiao/T0200_F1.cs
@@ -0,0 +1,69 @@
+using NewLife.JT808.Protocols;
+using NewLife.Serialization;
+
+namespace NewLife.JT808.YueBiao;
+
+/// <summary>位置附加信息-安装异常(0xF1)</summary>
+/// <remarks>
+/// 粤标位置附加信息,标识终端外设安装异常状态。
+/// </remarks>
+public class T0200_F1
+{
+    #region 属性
+    /// <summary>安装异常状态。位标志</summary>
+    public InstallAbnormalFlags Flags { get; set; }
+    #endregion
+
+    #region 方法
+    /// <summary>从字节数据读取</summary>
+    public static T0200_F1 Parse(Byte[] data)
+    {
+        var reader = Helper.CreateReader(new MemoryStream(data));
+        return new T0200_F1
+        {
+            Flags = (InstallAbnormalFlags)reader.ReadUInt32()
+        };
+    }
+
+    /// <summary>转换为字节数据</summary>
+    public Byte[] ToBytes()
+    {
+        var stream = new MemoryStream();
+        var writer = Helper.CreateWriter(stream);
+        writer.Write((UInt32)Flags);
+        return stream.ToArray();
+    }
+    #endregion
+}
+
+/// <summary>安装异常标志位</summary>
+[Flags]
+public enum InstallAbnormalFlags : UInt32
+{
+    /// <summary>无异常</summary>
+    无异常 = 0,
+
+    /// <summary>摄像头异常</summary>
+    摄像头异常 = 0x01,
+
+    /// <summary>主存储器异常</summary>
+    主存储器异常 = 0x02,
+
+    /// <summary>辅存储器异常</summary>
+    辅存储器异常 = 0x04,
+
+    /// <summary>红外补光异常</summary>
+    红外补光异常 = 0x08,
+
+    /// <summary>扬声器异常</summary>
+    扬声器异常 = 0x10,
+
+    /// <summary>电池异常</summary>
+    电池异常 = 0x20,
+
+    /// <summary>通信模块异常</summary>
+    通信模块异常 = 0x40,
+
+    /// <summary>定位模块异常</summary>
+    定位模块异常 = 0x80,
+}
Added +57 -0
diff --git a/Newlife.JT808/YueBiao/T0200_F2.cs b/Newlife.JT808/YueBiao/T0200_F2.cs
new file mode 100644
index 0000000..38d04fd
--- /dev/null
+++ b/Newlife.JT808/YueBiao/T0200_F2.cs
@@ -0,0 +1,57 @@
+using NewLife.JT808.Protocols;
+using NewLife.Serialization;
+
+namespace NewLife.JT808.YueBiao;
+
+/// <summary>位置附加信息-算法异常(0xF2)</summary>
+/// <remarks>
+/// 粤标位置附加信息,标识终端主动安全算法异常状态。
+/// </remarks>
+public class T0200_F2
+{
+    #region 属性
+    /// <summary>算法异常状态。位标志</summary>
+    public AlgorithmAbnormalFlags Flags { get; set; }
+    #endregion
+
+    #region 方法
+    /// <summary>从字节数据读取</summary>
+    public static T0200_F2 Parse(Byte[] data)
+    {
+        var reader = Helper.CreateReader(new MemoryStream(data));
+        return new T0200_F2
+        {
+            Flags = (AlgorithmAbnormalFlags)reader.ReadUInt32()
+        };
+    }
+
+    /// <summary>转换为字节数据</summary>
+    public Byte[] ToBytes()
+    {
+        var stream = new MemoryStream();
+        var writer = Helper.CreateWriter(stream);
+        writer.Write((UInt32)Flags);
+        return stream.ToArray();
+    }
+    #endregion
+}
+
+/// <summary>算法异常标志位</summary>
+[Flags]
+public enum AlgorithmAbnormalFlags : UInt32
+{
+    /// <summary>无异常</summary>
+    无异常 = 0,
+
+    /// <summary>ADAS算法异常</summary>
+    ADAS算法异常 = 0x01,
+
+    /// <summary>DSM算法异常</summary>
+    DSM算法异常 = 0x02,
+
+    /// <summary>TPMS算法异常</summary>
+    TPMS算法异常 = 0x04,
+
+    /// <summary>BSD算法异常</summary>
+    BSD算法异常 = 0x08,
+}
Added +84 -0
diff --git a/Newlife.JT808/YueBiao/T0900_F7.cs b/Newlife.JT808/YueBiao/T0900_F7.cs
new file mode 100644
index 0000000..11f4c8a
--- /dev/null
+++ b/Newlife.JT808/YueBiao/T0900_F7.cs
@@ -0,0 +1,84 @@
+using NewLife.JT808.Protocols;
+using NewLife.Serialization;
+
+namespace NewLife.JT808.YueBiao;
+
+/// <summary>USB外设状态信息上报(0x0900 子类型 0xF7)</summary>
+/// <remarks>
+/// 粤标终端通过 0x0900 透传消息上报 USB 外设的状态信息。
+/// </remarks>
+public class T0900_F7
+{
+    #region 属性
+    /// <summary>USB总数量</summary>
+    public Byte TotalCount { get; set; }
+
+    /// <summary>USB设备列表</summary>
+    public USBStatusItem[]? Items { get; set; }
+    #endregion
+
+    #region 方法
+    /// <summary>从透传数据读取</summary>
+    public static T0900_F7 Parse(Byte[] data)
+    {
+        var reader = Helper.CreateReader(new MemoryStream(data));
+        var result = new T0900_F7
+        {
+            TotalCount = reader.ReadByte()
+        };
+
+        var count = reader.ReadByte();
+        var items = new USBStatusItem[count];
+        for (var i = 0; i < count; i++)
+        {
+            items[i] = new USBStatusItem
+            {
+                Id = reader.ReadByte(),
+                Status = reader.ReadByte(),
+                Online = reader.ReadByte(),
+                Reserved = reader.ReadByte(),
+            };
+        }
+        result.Items = items;
+
+        return result;
+    }
+
+    /// <summary>转换为透传数据</summary>
+    public Byte[] ToBytes()
+    {
+        var stream = new MemoryStream();
+        var writer = Helper.CreateWriter(stream);
+
+        writer.Write(TotalCount);
+        var count = (Byte)(Items?.Length ?? 0);
+        writer.Write(count);
+        for (var i = 0; i < count; i++)
+        {
+            var item = Items![i];
+            writer.Write(item.Id);
+            writer.Write(item.Status);
+            writer.Write(item.Online);
+            writer.Write(item.Reserved);
+        }
+
+        return stream.ToArray();
+    }
+    #endregion
+}
+
+/// <summary>USB设备状态项</summary>
+public class USBStatusItem
+{
+    /// <summary>USB接口ID</summary>
+    public Byte Id { get; set; }
+
+    /// <summary>状态。0x00=正常工作,0x01=异常</summary>
+    public Byte Status { get; set; }
+
+    /// <summary>在线状态。0x00=不在线,0x01=在线</summary>
+    public Byte Online { get; set; }
+
+    /// <summary>预留</summary>
+    public Byte Reserved { get; set; }
+}
Added +89 -0
diff --git a/Newlife.JT808/YueBiao/T0900_F8.cs b/Newlife.JT808/YueBiao/T0900_F8.cs
new file mode 100644
index 0000000..5e5abf0
--- /dev/null
+++ b/Newlife.JT808/YueBiao/T0900_F8.cs
@@ -0,0 +1,89 @@
+using NewLife.JT808.Protocols;
+using NewLife.Serialization;
+
+namespace NewLife.JT808.YueBiao;
+
+/// <summary>USB外设信息上报(0x0900 子类型 0xF8)</summary>
+/// <remarks>
+/// 粤标终端通过 0x0900 透传消息上报 USB 外设的详细信息(厂商/型号等)。
+/// </remarks>
+public class T0900_F8
+{
+    #region 属性
+    /// <summary>USB总数量</summary>
+    public Byte TotalCount { get; set; }
+
+    /// <summary>USB设备列表</summary>
+    public USBInfoItem[]? Items { get; set; }
+    #endregion
+
+    #region 方法
+    /// <summary>从透传数据读取</summary>
+    public static T0900_F8 Parse(Byte[] data)
+    {
+        var reader = Helper.CreateReader(new MemoryStream(data));
+        var result = new T0900_F8
+        {
+            TotalCount = reader.ReadByte()
+        };
+
+        var count = reader.ReadByte();
+        var items = new USBInfoItem[count];
+        for (var i = 0; i < count; i++)
+        {
+            items[i] = new USBInfoItem
+            {
+                Id = reader.ReadByte(),
+                Company = reader.ReadString(20),
+                Model = reader.ReadString(20),
+                HardwareVersion = reader.ReadString(10),
+                FirmwareVersion = reader.ReadString(10),
+            };
+        }
+        result.Items = items;
+
+        return result;
+    }
+
+    /// <summary>转换为透传数据</summary>
+    public Byte[] ToBytes()
+    {
+        var stream = new MemoryStream();
+        var writer = Helper.CreateWriter(stream);
+
+        writer.Write(TotalCount);
+        var count = (Byte)(Items?.Length ?? 0);
+        writer.Write(count);
+        for (var i = 0; i < count; i++)
+        {
+            var item = Items![i];
+            writer.Write(item.Id);
+            writer.WriteFixedString(item.Company, 20);
+            writer.WriteFixedString(item.Model, 20);
+            writer.WriteFixedString(item.HardwareVersion, 10);
+            writer.WriteFixedString(item.FirmwareVersion, 10);
+        }
+
+        return stream.ToArray();
+    }
+    #endregion
+}
+
+/// <summary>USB设备信息项</summary>
+public class USBInfoItem
+{
+    /// <summary>USB接口ID</summary>
+    public Byte Id { get; set; }
+
+    /// <summary>制造商</summary>
+    public String Company { get; set; } = String.Empty;
+
+    /// <summary>型号</summary>
+    public String Model { get; set; } = String.Empty;
+
+    /// <summary>硬件版本</summary>
+    public String HardwareVersion { get; set; } = String.Empty;
+
+    /// <summary>固件版本</summary>
+    public String FirmwareVersion { get; set; } = String.Empty;
+}
Added +113 -0
diff --git a/Newlife.JT808/YueBiao/T1FC4.cs b/Newlife.JT808/YueBiao/T1FC4.cs
new file mode 100644
index 0000000..e3e4152
--- /dev/null
+++ b/Newlife.JT808/YueBiao/T1FC4.cs
@@ -0,0 +1,113 @@
+using System.Globalization;
+using NewLife.JT808.Protocols;
+using NewLife.JT808.SuBiao;
+using NewLife.Serialization;
+
+namespace NewLife.JT808.YueBiao;
+
+/// <summary>粤标主动安全报警上报(0x1FC4)</summary>
+/// <remarks>
+/// 粤标核心报警消息,终端向平台上报 ADAS/DSM/TPMS/BSD 等主动安全报警信息。
+/// 与苏标报警上报不同,粤标使用独立消息 ID 0x1FC4 而非位置附加信息。
+/// </remarks>
+[MessageKind(MessageKinds.粤标主动安全报警)]
+public class T1FC4 : IAccessor
+{
+    #region 属性
+    /// <summary>终端ID。粤标30字节</summary>
+    [FieldSize(30)]
+    public String TerminalId { get; set; } = String.Empty;
+
+    /// <summary>报警标识号</summary>
+    public AlarmDevice AlarmId { get; set; } = new();
+
+    /// <summary>车辆状态</summary>
+    public CarStatus Status { get; set; }
+
+    /// <summary>报警类型。0x64=ADAS, 0x65=DSM, 0x66=TPMS, 0x67=BSD</summary>
+    public Byte AlarmType { get; set; }
+
+    /// <summary>报警/事件类型。根据 AlarmType 对应不同枚举</summary>
+    public Byte AlarmKind { get; set; }
+
+    /// <summary>报警级别。1=一级报警,2=二级报警</summary>
+    public Byte Level { get; set; }
+
+    /// <summary>车速。单位 km/h</summary>
+    public Byte Speed { get; set; }
+
+    /// <summary>海拔高度,单位 m</summary>
+    public Int16 Altitude { get; set; }
+
+    /// <summary>纬度。百万分之一度</summary>
+    public Int32 Latitude { get; set; }
+
+    /// <summary>经度。百万分之一度</summary>
+    public Int32 Longitude { get; set; }
+
+    /// <summary>时间。YY-MM-DD-hh-mm-ss</summary>
+    [BCDTime(6, "yyMMddHHmmss")]
+    public DateTime Time { get; set; }
+
+    /// <summary>报警数据长度</summary>
+    public Int16 DataLength { get; set; }
+
+    /// <summary>报警数据。根据 AlarmType 类型不同,长度可变</summary>
+    public Byte[]? Data { get; set; }
+    #endregion
+
+    #region IAccessor
+    /// <summary>读取</summary>
+    public Boolean Read(Stream stream, Object? context)
+    {
+        var reader = Helper.CreateReader(stream);
+
+        TerminalId = reader.ReadFixedString(30);
+        AlarmId = reader.Read<AlarmDevice>();
+        Status = (CarStatus)reader.ReadUInt16();
+        AlarmType = reader.ReadByte();
+        AlarmKind = reader.ReadByte();
+        Level = reader.ReadByte();
+        Speed = reader.ReadByte();
+        Altitude = reader.ReadInt16();
+        Latitude = reader.ReadInt32();
+        Longitude = reader.ReadInt32();
+
+        var str = reader.ReadBCD(6);
+        if (DateTime.TryParseExact(str, "yyMMddHHmmss", null, DateTimeStyles.None, out var dt))
+            Time = dt;
+
+        DataLength = reader.ReadInt16();
+
+        if (DataLength > 0)
+            Data = reader.ReadBytes(DataLength);
+
+        return true;
+    }
+
+    /// <summary>写入</summary>
+    public Boolean Write(Stream stream, Object? context)
+    {
+        var writer = Helper.CreateWriter(stream);
+
+        writer.WriteFixedString(TerminalId, 30);
+        writer.Write(AlarmId);
+        writer.Write((UInt16)Status);
+        writer.Write(AlarmType);
+        writer.Write(AlarmKind);
+        writer.Write(Level);
+        writer.Write(Speed);
+        writer.Write(Altitude);
+        writer.Write(Latitude);
+        writer.Write(Longitude);
+        writer.WriteBCD(Time.ToString("yyMMddHHmmss"), 6);
+
+        DataLength = (Int16)(Data?.Length ?? 0);
+        writer.Write(DataLength);
+        if (Data is { Length: > 0 })
+            writer.Write(Data);
+
+        return true;
+    }
+    #endregion
+}
Added +34 -0
diff --git a/Newlife.JT808/YueBiao/T8103_F364.cs b/Newlife.JT808/YueBiao/T8103_F364.cs
new file mode 100644
index 0000000..b82f3a5
--- /dev/null
+++ b/Newlife.JT808/YueBiao/T8103_F364.cs
@@ -0,0 +1,34 @@
+using NewLife.JT808.Protocols;
+
+namespace NewLife.JT808.YueBiao;
+
+/// <summary>设置终端参数-前向碰撞报警参数(0x8103 参数ID 0xF364)</summary>
+public class T8103_F364
+{
+    /// <summary>参数ID</summary>
+    public const UInt32 ParamId = YueBiaoConstants.Param_ADAS;
+
+    /// <summary>报警使能。位标志,bit0=前向碰撞</summary>
+    public UInt32 Enable { get; set; }
+
+    /// <summary>报警级别。1=一级,2=二级</summary>
+    public Byte Level { get; set; }
+
+    /// <summary>报警速度阈值。单位 km/h</summary>
+    public Byte SpeedThreshold { get; set; }
+
+    /// <summary>报警距离阈值。单位 m</summary>
+    public Int16 DistanceThreshold { get; set; }
+
+    /// <summary>报警持续时间。单位 s</summary>
+    public Byte Duration { get; set; }
+
+    /// <summary>是否主动拍照。0=否,1=是</summary>
+    public Byte EnablePhoto { get; set; }
+
+    /// <summary>拍照间隔。单位 s</summary>
+    public Byte PhotoInterval { get; set; }
+
+    /// <summary>预留</summary>
+    public Byte Reserved { get; set; }
+}
Added +22 -0
diff --git a/Newlife.JT808/YueBiao/T8103_F370.cs b/Newlife.JT808/YueBiao/T8103_F370.cs
new file mode 100644
index 0000000..3b3cb0e
--- /dev/null
+++ b/Newlife.JT808/YueBiao/T8103_F370.cs
@@ -0,0 +1,22 @@
+using NewLife.JT808.Protocols;
+
+namespace NewLife.JT808.YueBiao;
+
+/// <summary>设置终端参数-盲区监测参数(0x8103 参数ID 0xF370)</summary>
+public class T8103_F370
+{
+    /// <summary>参数ID</summary>
+    public const UInt32 ParamId = YueBiaoConstants.Param_BSD;
+
+    /// <summary>报警使能。位标志</summary>
+    public UInt32 Enable { get; set; }
+
+    /// <summary>报警级别。1=一级,2=二级</summary>
+    public Byte Level { get; set; }
+
+    /// <summary>报警速度阈值。单位 km/h</summary>
+    public Byte SpeedThreshold { get; set; }
+
+    /// <summary>预留</summary>
+    public Byte Reserved { get; set; }
+}
Added +34 -0
diff --git a/Newlife.JT808/YueBiao/T8900_F7.cs b/Newlife.JT808/YueBiao/T8900_F7.cs
new file mode 100644
index 0000000..6f7840f
--- /dev/null
+++ b/Newlife.JT808/YueBiao/T8900_F7.cs
@@ -0,0 +1,34 @@
+using NewLife.JT808.Protocols;
+using NewLife.Serialization;
+
+namespace NewLife.JT808.YueBiao;
+
+/// <summary>USB外设状态查询(0x8900 子类型 0xF7)</summary>
+/// <remarks>
+/// 平台通过 0x8900 透传消息查询终端 USB 外设状态。
+/// </remarks>
+public class T8900_F7
+{
+    #region 属性
+    /// <summary>USB接口ID。0xFF=查询所有</summary>
+    public Byte UsbId { get; set; }
+    #endregion
+
+    #region 方法
+    /// <summary>序列化</summary>
+    public Byte[] ToBytes()
+    {
+        var stream = new MemoryStream();
+        var writer = Helper.CreateWriter(stream);
+        writer.Write(UsbId);
+        return stream.ToArray();
+    }
+
+    /// <summary>反序列化</summary>
+    public static T8900_F7 Parse(Byte[] data)
+    {
+        var reader = Helper.CreateReader(new MemoryStream(data));
+        return new T8900_F7 { UsbId = reader.ReadByte() };
+    }
+    #endregion
+}
Added +34 -0
diff --git a/Newlife.JT808/YueBiao/T8900_F8.cs b/Newlife.JT808/YueBiao/T8900_F8.cs
new file mode 100644
index 0000000..3b8e431
--- /dev/null
+++ b/Newlife.JT808/YueBiao/T8900_F8.cs
@@ -0,0 +1,34 @@
+using NewLife.JT808.Protocols;
+using NewLife.Serialization;
+
+namespace NewLife.JT808.YueBiao;
+
+/// <summary>USB外设信息查询(0x8900 子类型 0xF8)</summary>
+/// <remarks>
+/// 平台通过 0x8900 透传消息查询终端 USB 外设详细信息。
+/// </remarks>
+public class T8900_F8
+{
+    #region 属性
+    /// <summary>USB接口ID。0xFF=查询所有</summary>
+    public Byte UsbId { get; set; }
+    #endregion
+
+    #region 方法
+    /// <summary>序列化</summary>
+    public Byte[] ToBytes()
+    {
+        var stream = new MemoryStream();
+        var writer = Helper.CreateWriter(stream);
+        writer.Write(UsbId);
+        return stream.ToArray();
+    }
+
+    /// <summary>反序列化</summary>
+    public static T8900_F8 Parse(Byte[] data)
+    {
+        var reader = Helper.CreateReader(new MemoryStream(data));
+        return new T8900_F8 { UsbId = reader.ReadByte() };
+    }
+    #endregion
+}
Added +109 -0
diff --git a/Newlife.JT808/YueBiao/YueBiaoAlarmKinds.cs b/Newlife.JT808/YueBiao/YueBiaoAlarmKinds.cs
new file mode 100644
index 0000000..1eee0cc
--- /dev/null
+++ b/Newlife.JT808/YueBiao/YueBiaoAlarmKinds.cs
@@ -0,0 +1,109 @@
+namespace NewLife.JT808.YueBiao;
+
+/// <summary>粤标报警/事件类型枚举</summary>
+public enum YueBiaoAlarmKinds : Byte
+{
+    #region 高级驾驶辅助(ADAS)
+    /// <summary>前向碰撞报警</summary>
+    前向碰撞 = 0x01,
+
+    /// <summary>车道偏离报警</summary>
+    车道偏离 = 0x02,
+
+    /// <summary>车距过近报警</summary>
+    车距过近 = 0x03,
+
+    /// <summary>行人碰撞报警</summary>
+    行人碰撞 = 0x04,
+
+    /// <summary>频繁变道报警</summary>
+    频繁变道 = 0x05,
+
+    /// <summary>道路标识超限报警</summary>
+    道路标识超限 = 0x06,
+
+    /// <summary>障碍物报警</summary>
+    障碍物 = 0x07,
+
+    /// <summary>道路标志识别</summary>
+    道路标志识别 = 0x10,
+
+    /// <summary>主动抓拍</summary>
+    主动抓拍 = 0x11,
+    #endregion
+
+    #region 驾驶状态监测(DSM)
+    /// <summary>疲劳驾驶报警</summary>
+    疲劳驾驶 = 0x01,
+
+    /// <summary>拨打电话报警</summary>
+    拨打电话 = 0x02,
+
+    /// <summary>抽烟报警</summary>
+    抽烟 = 0x03,
+
+    /// <summary>分神驾驶报警</summary>
+    分神驾驶 = 0x04,
+
+    /// <summary>驾驶员异常报警</summary>
+    驾驶员异常 = 0x05,
+
+    /// <summary>探头遮挡报警</summary>
+    探头遮挡 = 0x06,
+
+    /// <summary>打哈欠报警</summary>
+    打哈欠 = 0x07,
+
+    /// <summary>超时驾驶报警</summary>
+    超时驾驶 = 0x08,
+
+    /// <summary>未系安全带报警</summary>
+    未系安全带 = 0x0A,
+
+    /// <summary>红外阻断型墨镜失效报警</summary>
+    红外阻断 = 0x0B,
+
+    /// <summary>双手脱离方向盘报警</summary>
+    双手脱把 = 0x0C,
+
+    /// <summary>玩手机报警</summary>
+    玩手机 = 0x0D,
+
+    /// <summary>自动抓拍</summary>
+    自动抓拍 = 0x10,
+
+    /// <summary>驾驶员变更</summary>
+    驾驶员变更 = 0x11,
+
+    /// <summary>摄像头阻挡报警</summary>
+    摄像头阻挡 = 0x13,
+    #endregion
+
+    #region 胎压监测(TPMS)
+    /// <summary>胎压异常</summary>
+    胎压异常 = 0x01,
+
+    /// <summary>胎温异常</summary>
+    胎温异常 = 0x02,
+
+    /// <summary>传感器异常</summary>
+    传感器异常 = 0x03,
+
+    /// <summary>胎压不平衡</summary>
+    胎压不平衡 = 0x04,
+
+    /// <summary>电池电量低</summary>
+    电池电量低 = 0x05,
+    #endregion
+
+    #region 盲区监测(BSD)
+    /// <summary>后方接近报警</summary>
+    后方接近 = 0x01,
+
+    /// <summary>左侧后方接近报警</summary>
+    左侧后方接近 = 0x02,
+
+    /// <summary>右侧后方接近报警</summary>
+    右侧后方接近 = 0x03,
+    #endregion
+}
Added +65 -0
diff --git a/Newlife.JT808/YueBiao/YueBiaoConstants.cs b/Newlife.JT808/YueBiao/YueBiaoConstants.cs
new file mode 100644
index 0000000..3c8b967
--- /dev/null
+++ b/Newlife.JT808/YueBiao/YueBiaoConstants.cs
@@ -0,0 +1,65 @@
+namespace NewLife.JT808.YueBiao;
+
+/// <summary>粤标常量</summary>
+public static class YueBiaoConstants
+{
+    #region 参数ID(0x8103)
+    /// <summary>主动安全参数-前向碰撞报警参数</summary>
+    public const UInt32 Param_ADAS = 0xF364;
+
+    /// <summary>主动安全参数-车道偏离报警参数</summary>
+    public const UInt32 Param_LaneDeparture = 0xF365;
+
+    /// <summary>主动安全参数-车距过近报警参数</summary>
+    public const UInt32 Param_NearDistance = 0xF366;
+
+    /// <summary>主动安全参数-行人碰撞报警参数</summary>
+    public const UInt32 Param_PedestrianCollision = 0xF367;
+
+    /// <summary>主动安全参数-疲劳驾驶报警参数</summary>
+    public const UInt32 Param_FatigueDriving = 0xF368;
+
+    /// <summary>主动安全参数-拨打电话报警参数</summary>
+    public const UInt32 Param_PhoneCall = 0xF369;
+
+    /// <summary>主动安全参数-抽烟报警参数</summary>
+    public const UInt32 Param_Smoking = 0xF36A;
+
+    /// <summary>主动安全参数-分神驾驶报警参数</summary>
+    public const UInt32 Param_DistractedDriving = 0xF36B;
+
+    /// <summary>主动安全参数-驾驶员异常报警参数</summary>
+    public const UInt32 Param_DriverAbnormal = 0xF36C;
+
+    /// <summary>主动安全参数-超时驾驶报警参数</summary>
+    public const UInt32 Param_OvertimeDriving = 0xF36D;
+
+    /// <summary>主动安全参数-设备自检参数</summary>
+    public const UInt32 Param_SelfCheck = 0xF36E;
+
+    /// <summary>主动安全参数-车辆信息设置</summary>
+    public const UInt32 Param_VehicleInfo = 0xF36F;
+
+    /// <summary>主动安全参数-盲区监测参数</summary>
+    public const UInt32 Param_BSD = 0xF370;
+    #endregion
+
+    #region 透传消息子类型(0x0900/0x8900)
+    /// <summary>USB外设状态信息上报</summary>
+    public const Byte Passthrough_USBStatus = 0xF7;
+
+    /// <summary>USB外设信息上报</summary>
+    public const Byte Passthrough_USBInfo = 0xF8;
+    #endregion
+
+    #region 报警附件协议终端ID长度
+    /// <summary>苏标终端ID长度</summary>
+    public const Int32 TerminalIdLength_SuBiao = 7;
+
+    /// <summary>粤标终端ID长度</summary>
+    public const Int32 TerminalIdLength_YueBiao = 30;
+
+    /// <summary>粤标报警标识号长度</summary>
+    public const Int32 AlarmIdLength_YueBiao = 40;
+    #endregion
+}
Added +14 -0
diff --git a/Newlife.JT808/YueBiao/YueBiaoMsgIds.cs b/Newlife.JT808/YueBiao/YueBiaoMsgIds.cs
new file mode 100644
index 0000000..4c19a7b
--- /dev/null
+++ b/Newlife.JT808/YueBiao/YueBiaoMsgIds.cs
@@ -0,0 +1,14 @@
+namespace NewLife.JT808.YueBiao;
+
+/// <summary>粤标透传消息子类型</summary>
+/// <remarks>
+/// 粤标(广东省主动安全扩展)在 0x0900/0x8900 透传消息中使用的子类型定义。
+/// </remarks>
+public enum YueBiaoPassthroughTypes : Byte
+{
+    /// <summary>USB外设状态信息上报。0x0900/0x8900 子类型</summary>
+    USB外设状态 = 0xF7,
+
+    /// <summary>USB外设信息上报。0x0900/0x8900 子类型</summary>
+    USB外设信息 = 0xF8,
+}
Modified +6 -4
diff --git a/Readme.MD b/Readme.MD
index 14a3016..2e5b69a 100644
--- a/Readme.MD
+++ b/Readme.MD
@@ -6,11 +6,11 @@
 ![Nuget](https://img.shields.io/nuget/v/newlife.jt808?logo=nuget)
 ![Nuget (with prereleases)](https://img.shields.io/nuget/vpre/newlife.jt808?label=dev%20nuget&logo=nuget)
 
-JT/T 808 车辆定位协议完整实现,支持 2011/2013/2019 三个版本,涵盖 70+ 标准消息体、苏标主动安全扩展、JT/T 1078 音视频基础消息及 JT/T 19056 行车记录仪协议。
+JT/T 808 车辆定位协议完整实现,支持 2011/2013/2019 三个版本,涵盖 70+ 标准消息体、苏标/粤标主动安全扩展、JT/T 1078 音视频基础消息、JT/T 19056 行车记录仪协议及 RocketMQ 消息队列集成。
 
 源码: https://github.com/NewLifeX/NewLife.JT808  
 Nuget:[NewLife.JT808](https://www.nuget.org/packages/NewLife.JT808)  
-文档:[需求文档](Doc/需求文档.md) / [架构设计](Doc/架构设计.md) / [功能清单](Doc/功能清单.md)
+文档:[需求文档](Doc/需求文档.md) / [架构设计](Doc/架构设计.md) / [功能清单](Doc/功能清单.md) / [使用文档](Doc/使用文档.md)
 
 
 ## 主要特点
@@ -22,15 +22,17 @@ Nuget:[NewLife.JT808](https://www.nuget.org/packages/NewLife.JT808)
 - **TLV/KLV 解析**:内置 Type-Length-Value 和 Kind-Length-Value 通用编解码,支持强类型字典转换
 - **网络通信层**:内置 TCP 粘包编解码器 `JTCodec` 和客户端 `JT808Client`,支持消息处理器自动路由
 - **苏标扩展**:支持 ADAS/DSM/TPMS/BSD 主动安全报警信息,外设状态/信息解析,报警附件协议
+- **粤标扩展**:支持广东省主动安全标准(粤标),含独立报警上报(0x1FC4)、USB 外设透传、位置附加信息、专用参数设置
 - **音视频基础**:JT/T 1078 音视频消息体模型和枚举定义
 - **行车记录仪**:JT/T 19056 上下行数据包编解码
 - **BCD 编码**:BCD 字符串和时间自定义序列化特性,适配协议特有编码格式
 - **GBK 编码**:内置 GBK 中文字符串编解码,自动注册 `CodePagesEncodingProvider`
 - **Web API 管理**:支持统一下发指令、在线会话管理、黑名单管理、Token 鉴权,方便集成到后台系统
-- **消息队列抽象**:IMsgProducer/IMsgConsumer/ISessionProducer 等接口解耦消息处理,内置 DefaultMsgQueue 内存实现
+- **消息队列抽象**:IMsgProducer/IMsgConsumer/ISessionProducer 等接口解耦消息处理,内置 DefaultMsgQueue 内存实现、Redis Stream 生产/消费支持、RocketMQ 适配器
 - **跨服务器指令下发**:ICommandBus 接口 + Stardust 事件总线,支持集群广播指令到指定终端
 - **客户端增强**:自动重连、可配心跳、收发统计计数器,提升生产环境可靠性
-- **多框架支持**:`net45 / net461 / netstandard2.0 / netstandard2.1`
+- **多框架支持**:`net45 / net461 / netstandard2.0 / netstandard2.1` 全兼容
+- **RocketMQ 集成**:基于 `NewLife.RocketMQ` 的消息队列生产/消费适配器,可作为 Redis Stream 的替代方案
 
 ## 支持的协议版本