diff --git a/DECISIONS.md b/DECISIONS.md index 1af8a3bd..24809262 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -32,7 +32,7 @@ - **Consequences**: 信达 Push 现在不属于默认生产面;模块仅保留在 `legacy-xinda` profile,后续优化优先投向 GB32960、JT808、宇通 MQTT、历史和统计链路。 ## ADR-005 JT1078 / JSATL12 进第一批 -- **Status**: Accepted +- **Status**: Superseded by ADR-012 - **Decision**: 第一批迁移即覆盖 JT1078 信令 + JSATL12 报警附件上传 - **Consequences**: Phase 2 工期相应拉长;JSATL12 需要对象存储后端(本地 / S3 / OSS) @@ -72,3 +72,12 @@ 2. Xinda Push 仅保留在 `legacy-xinda` profile,不进入默认 Maven reactor、Woodpecker 镜像发布和历史消费绑定。 3. `command-gateway` 和 JT1078 继续作为可选能力,通过 `optional-command-gateway` profile 显式启用。 - **Consequences**: 默认构建和部署保持精简;后续性能、可靠性、字段解析和存储优化都优先服务三条活跃协议链路。 + +## ADR-012 JSATL12 附件上传:Optional only +- **Status**: Accepted +- **Context**: 当前默认生产面只部署 GB32960、JT808、Yutong MQTT、vehicle-history-app、vehicle-analytics-app;JSATL12 附件上传没有独立生产 app,也不在 Portainer 和 Woodpecker 活跃镜像列表中。 +- **Decision**: + 1. `protocol-jsatl12` 不进入默认 Maven reactor。 + 2. JSATL12 仅保留在 `optional-attachments` profile,需要附件上传能力时显式构建。 + 3. 默认优化和验证优先覆盖活跃接入链路,附件上传能力保持源码可用但不增加默认构建面。 +- **Consequences**: 默认构建更轻,生产部署边界更清晰;附件上传相关测试需要通过 `-Poptional-attachments` 显式运行。 diff --git a/README.md b/README.md index 364721e6..046286f8 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## 设计目标 -- **协议接入统一抽象**:GB/T 32960、JT/T 808、JT/T 1078、JSATL12、MQTT 全部变成可插拔 Inbound Adapter;信达 Push 仅保留为废弃兼容模块 +- **协议接入统一抽象**:GB/T 32960、JT/T 808、Yutong MQTT 是默认生产接入;JT/T 1078、JSATL12 作为显式 profile 的可选能力;信达 Push 仅保留为废弃兼容模块 - **原子能力化**:每个协议一个独立 Maven 模块 + 独立 AutoConfiguration + 独立配置开关 - **业务 / 实时彻底解耦**:本服务只负责 **收 → 解析 → 校验 → 规整 → 投递 Kafka**,不碰业务库 - **高并发低延迟**:Netty + Disruptor + Java 25 虚拟线程;目标单节点 ≥ 5 万 msg/s,P99 < 50 ms @@ -43,7 +43,7 @@ lingniu-vehicle-ingest/ │ │ ├── protocol-gb32960/ GB/T 32960 │ │ ├── protocol-jt808/ JT/T 808(统一身份映射 + 事件 metadata 内部 VIN + 注册/鉴权/心跳/注销/位置/批量位置/参数/属性/媒体/透传/未知上行和坏帧兜底/断链清理会话/下行分包) │ │ ├── protocol-jt1078/ JT/T 1078(808 信令按需桥接 + 常用下行信令编码 + TCP/UDP RTP 媒体流分段归档 + 事件 metadata 内部 VIN + 坏 RTP 统一 RawArchive/Passthrough + 归档失败兜底 + SIM 身份映射) -│ │ └── protocol-jsatl12/ 苏标主动安全报警附件(真实 DataPacket 分帧 + 附件流归档 + T1210 文件清单身份继承 + 9212 补传应答 + MediaMeta 引用事件 + 坏帧/坏信令/归档失败兜底) +│ │ └── protocol-jsatl12/ 苏标主动安全报警附件(optional-attachments profile) │ ├── inbound/ │ │ ├── inbound-mqtt/ MQTT 接入(endpoint 生命周期 + profile 注册扩展 + 统一身份映射 + PEM 双向 TLS + 未知 profile/解析失败/profile异常/连接订阅失败兜底 + 统一 UNKNOWN 身份 metadata) │ │ └── inbound-xinda-push/ 信达 Push 接入(废弃兼容模块,仅 -Plegacy-xinda 显式构建) @@ -78,6 +78,8 @@ mvn -pl :jt808-ingest-app -am spring-boot:run 信达 Push 已废弃,不参与默认 Maven reactor、CI、Portainer 部署和历史消费链路;如需兼容排查,可显式使用 `-Plegacy-xinda` 构建。 +JSATL12 附件上传不在默认 Maven reactor 中;需要时使用 `-Poptional-attachments` 构建。 + ## 迁移说明 本项目是 `lingniu-vehicle-data-reception` 的 v2 重构,采用 strangler fig 渐进式迁移,旧项目保留只读参考。迁移路径与决策参见 `../REFRACTOR_PLAN.md`。 diff --git a/docs/module-data-flow.html b/docs/module-data-flow.html index 96b97ce8..3a68e195 100644 --- a/docs/module-data-flow.html +++ b/docs/module-data-flow.html @@ -257,8 +257,9 @@

一、系统定位

- 当前项目不是业务库写入服务。它的核心职责是把 GB/T 32960、JT/T 808、JT/T 1078、JSATL12、 - MQTT 等不同来源的车辆数据统一转换为 VehicleEvent 和全字段 TelemetrySnapshot, + 当前项目不是业务库写入服务。它的核心职责是把 GB/T 32960、JT/T 808、Yutong MQTT + 等默认生产来源的车辆数据统一转换为 VehicleEvent 和全字段 TelemetrySnapshot; + JT/T 1078、JSATL12 作为显式 profile 的可选能力保留, 再通过 Kafka、原始报文归档、TDengine 历史索引、Redis 热状态和独立统计模块交给下游业务。

@@ -564,7 +565,7 @@ flowchart LR modules/protocols/protocol-jsatl12 - 苏标主动安全报警附件接入。依赖 ArchiveStore 和 JT808 decoder;生产默认端口按旧接收服务对齐为 7612;附件 DataPacket 按旧服务真实布局 01cd + 50B文件名 + offset + length + data 分帧解析,不再把文件名前 4 字节误判为帧长;附件数据写 ArchiveStore 后通过 Dispatcher 产出 MediaMeta 引用事件,事件 metadata 保留 fileName、fileOffset、declaredChunkSizeBytes、archiveKey 和 archiveRef,便于附件明细查询、导出和补传诊断;内置附件状态机处理 T1210 文件清单、DataPacket 分块区间和 T1212 上传完成消息,数据分块会按 T1210 文件清单中的文件名继承手机号并通过共享身份解析器得到内部 VIN,入口 RawFrame、ArchivedChunk 和 MediaMeta 均保留 phone、vin、identityResolved、identitySource,只有找不到文件归属时才标记 UNKNOWN;按文件名合并无身份数据分块并返回 0x9212 完成/补传应答,补传应答包含缺失 offset/length 区间;附件归档失败会产出 JSATL12 Passthrough 错误事件并保留原始分块;JT_MESSAGE 信令复用 JT808 decoder 后进入 Dispatcher,桥接 RawFrame 使用共享身份解析后的内部 VIN并保留 phone、identityResolved、identitySource,坏 JT 信令入口 RawFrame 同样标记 UNKNOWN 身份;超长/畸形附件帧、未闭合超长 JT 信令和坏 JT 信令都以 JSATL12 Passthrough 兜底,附件帧异常同时标记 frameError 与统一 parseError/parseErrorMessage,保留原始字节、peer、长度和错误元数据,帧长和 worker 线程支持部署配置。 + 苏标主动安全报警附件接入(仅 optional-attachments profile 显式构建,不属于默认生产面)。依赖 ArchiveStore 和 JT808 decoder;端口按旧接收服务对齐为 7612;附件 DataPacket 按旧服务真实布局 01cd + 50B文件名 + offset + length + data 分帧解析,不再把文件名前 4 字节误判为帧长;附件数据写 ArchiveStore 后通过 Dispatcher 产出 MediaMeta 引用事件,事件 metadata 保留 fileName、fileOffset、declaredChunkSizeBytes、archiveKey 和 archiveRef,便于附件明细查询、导出和补传诊断;内置附件状态机处理 T1210 文件清单、DataPacket 分块区间和 T1212 上传完成消息,数据分块会按 T1210 文件清单中的文件名继承手机号并通过共享身份解析器得到内部 VIN,入口 RawFrame、ArchivedChunk 和 MediaMeta 均保留 phone、vin、identityResolved、identitySource,只有找不到文件归属时才标记 UNKNOWN;按文件名合并无身份数据分块并返回 0x9212 完成/补传应答,补传应答包含缺失 offset/length 区间;附件归档失败会产出 JSATL12 Passthrough 错误事件并保留原始分块;JT_MESSAGE 信令复用 JT808 decoder 后进入 Dispatcher,桥接 RawFrame 使用共享身份解析后的内部 VIN并保留 phone、identityResolved、identitySource,坏 JT 信令入口 RawFrame 同样标记 UNKNOWN 身份;超长/畸形附件帧、未闭合超长 JT 信令和坏 JT 信令都以 JSATL12 Passthrough 兜底,附件帧异常同时标记 frameError 与统一 parseError/parseErrorMessage,保留原始字节、peer、长度和错误元数据,帧长和 worker 线程支持部署配置。 主动安全附件流、JT808 信令帧。 归档文件、MediaMeta、JT808 统一事件、坏帧/坏信令/归档失败 Passthrough。 附件归档报警证据信令复用错误隔离 diff --git a/docs/target-architecture.md b/docs/target-architecture.md index 44d46692..c1faf46d 100644 --- a/docs/target-architecture.md +++ b/docs/target-architecture.md @@ -19,6 +19,10 @@ Xinda Push is legacy and is not part of the default production surface. It may remain in source for reference, but new optimization work should target the active protocols above. +JSATL12 attachment upload is also outside the default production reactor. Keep +it available through the `optional-attachments` profile until an attachment app +is explicitly deployed. + ## Goals - Keep protocol IO, raw archive, history, latest-state, and statistics as @@ -177,6 +181,8 @@ flowchart LR - Active production deployment contains GB32960, JT808, Yutong MQTT, vehicle-history, and vehicle-analytics apps. - Xinda Push is absent from default deployment and history consumer bindings. +- JSATL12 is absent from the default Maven reactor and available through + `optional-attachments`. - History APIs read from TDengine by default; Parquet/DuckDB is optional compatibility only. - Raw frame queries can return complete parsed JSON through `payloadJson.parsed`. diff --git a/modules/apps/vehicle-history-app/src/test/java/com/lingniu/ingest/historyapp/MavenModuleProfileTest.java b/modules/apps/vehicle-history-app/src/test/java/com/lingniu/ingest/historyapp/MavenModuleProfileTest.java index f51f6187..ae90f29d 100644 --- a/modules/apps/vehicle-history-app/src/test/java/com/lingniu/ingest/historyapp/MavenModuleProfileTest.java +++ b/modules/apps/vehicle-history-app/src/test/java/com/lingniu/ingest/historyapp/MavenModuleProfileTest.java @@ -30,6 +30,17 @@ class MavenModuleProfileTest { "modules/apps/command-gateway"); } + @Test + void jsatl12AttachmentProtocolIsOptionalAndOutsideDefaultProductionReactor() throws Exception { + Document pom = rootPom(); + + assertThat(defaultModules(pom)) + .doesNotContain("modules/protocols/protocol-jsatl12"); + + assertThat(profileModules(pom, "optional-attachments")) + .containsExactly("modules/protocols/protocol-jsatl12"); + } + @Test void xindaIsLegacyOnlyAndOutsideDefaultProductionReactor() throws Exception { Document pom = rootPom(); @@ -63,6 +74,7 @@ class MavenModuleProfileTest { .contains("Spring Boot " + projectProperty(pom, "spring-boot.version")) .contains("Netty " + projectProperty(pom, "netty.version")) .contains("Eclipse Paho " + projectProperty(pom, "paho-mqtt.version")) + .contains("protocol-jsatl12/ 苏标主动安全报警附件(optional-attachments profile)") .contains("event-file-store/ 可选兼容索引(旧 Parquet/DuckDB 路径)") .contains("vehicle-history-app/ TDengine 历史查询 + RAW JSON") .contains("vehicle-analytics-app/ JT808 每日里程指标消费") @@ -92,8 +104,10 @@ class MavenModuleProfileTest { assertThat(decisions) .contains("## ADR-004 信达 Push:Legacy only") .contains("## ADR-011 默认生产面:三协议接入 + 历史 + 统计") + .contains("## ADR-012 JSATL12 附件上传:Optional only") .contains("GB32960、JT808、Yutong MQTT、vehicle-history-app、vehicle-analytics-app") .contains("Xinda Push 仅保留在 `legacy-xinda` profile") + .contains("JSATL12 仅保留在 `optional-attachments` profile") .doesNotContain("## ADR-004 信达 Push:保留模块但彻底重写\n- **Status**: Accepted") .doesNotContain("Spring Boot 3.4.x"); } diff --git a/pom.xml b/pom.xml index 9ad6e409..2feb3a3e 100644 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,6 @@ modules/services/vehicle-stat-service modules/protocols/protocol-gb32960 modules/protocols/protocol-jt808 - modules/protocols/protocol-jsatl12 modules/inbound/inbound-mqtt modules/apps/gb32960-ingest-app modules/apps/jt808-ingest-app @@ -51,6 +50,12 @@ modules/apps/command-gateway + + optional-attachments + + modules/protocols/protocol-jsatl12 + + legacy-xinda