docs: add CHANGELOG for v0.1.0 baseline

Captures the themed work that was rolled into the initial import commit
(login-ack time fix, idle handler, parser package split, removal of the
non-standard V2016 0x30 fuel cell stack registration, body-dump diagnostic
enhancement) so the history exists somewhere even though git can't carry
the per-theme commits.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
lingniu-dev
2026-04-15 16:11:27 +08:00
parent 064ecc479c
commit 3b52e6a617

75
CHANGELOG.md Normal file
View File

@@ -0,0 +1,75 @@
# Changelog
本文件记录本仓库的显著变更。日期使用 `YYYY-MM-DD` 格式。
格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),版本遵循 [SemVer](https://semver.org/lang/zh-CN/)。
> 说明v0.1.0 为本仓库 git 初始化时的基线快照。下面列出的"主题改动"实际上都被压在
> `chore: initial import of lingniu-vehicle-ingest` 这一个 commit 里——这是 git
> 初始化前已经完成的工作,无法事后拆分。从下一次提交开始走"小步分主题提交"流程。
---
## [0.1.0] — 2026-04-15
初始基线。多模块 Spring Boot 车辆遥测接入服务。
### Added
- **GB/T 32960.3 接入**`protocol-gb32960`Netty server、帧分帧器、消息解码器、
V2016/V2025 双版本信息体 parser、平台登入鉴权、VIN 白名单、读空闲告警。
- **JT/T 808 / JT/T 1078 / JSATL12 接入**`protocol-jt808` / `protocol-jt1078` /
`protocol-jsatl12`)。
- **MQTT 入站**与**信达平台 push 接入**`inbound-mqtt` / `inbound-xinda-push`)。
- **Disruptor 事件总线**`ingest-core`):高吞吐解耦解码与下游 sink。
- **Sink**:本地归档(`sink-archive`、Kafka`sink-mq`,含 protobuf envelope
- **会话状态**`session-core`)。
- **可观测性**Micrometer/Actuator 装配(`observability`)。
- **终端控制命令网关**`command-gateway`)。
### Fixed —— GB/T 32960 应答帧时间字段
- `Gb32960MessageDecoder``VEHICLE_LOGIN` / `VEHICLE_LOGOUT` /
`PLATFORM_LOGIN` / `PLATFORM_LOGOUT` 命令预解析 body 首 6B 采集时间,写入
`header.eventTime`。修复前 handler 回 ACK 时落到 `Instant.now()`,导致应答时间与原
报文时间不一致,违反 §6.3.2 应答规则。
### Added —— Netty 读空闲告警
- 配置项 `lingniu.ingest.gb32960.idle-read-seconds`(默认 60s0 禁用)。
- pipeline 注入 `IdleStateHandler(idleReadSeconds, 0, 0)`,仅打 WARN 日志不断链,
用于排查"对端登入成功后长时间不推数据"场景。
### Changed —— GB32960 信息体 parser 包结构重构
-`codec/parser/` 下的 16 个共用类按版本严格拆分到 `parser/v2016/`10 类)
`parser/v2025/`11 类)两个独立子包。
- 取消 `Vehicle/DriveMotor/Engine/Position``v2016()/v2025()` 工厂方法,每个
版本独立类,零代码共用。
- `Alarm` 解析中跨版本静态调用 `readFaultList` 也已改为各版本类内部私有方法。
- `Gb32960AutoConfiguration` 同步更新所有 import 与 `@Bean` 工厂。
### Removed —— 违反 2016 标准的 typeCode 注册
- 经核对 GB/T 32960.3-2016 附录 B 表 B.3`0x30~0x7F` 整段为预留区,
**2016 标准里没有 0x30 / 0x31 / 0x32 任何字段定义**
- 删除 `FuelCellStackV2016BlockParser`(曾把 V2025 字段布局硬套到 V2016 帧的 0x30 段,
解出来的电压/电流远超规范上限,是非物理值)。
- `Gb32960AutoConfiguration` 移除 `gb32960V2016FuelCellStack` bean。
- `Gb32960DecoderGoldenTest` 中 749B 真实生产帧的断言由
"`isEmpty()`(不应有 Raw 兜底)"翻转为 "`isPresent()`peer 越界使用 0x30+ 预留
typeCode应有 Raw 兜底)"。这才是符合 2016 国标的正确预期。
### Diagnostics —— BodyParser hex dump 增强
- `Gb32960BodyParser` 在遇到未知 typeCode 触发 unknown 路径时,额外打一条 WARN
内容为整段 info-block 区域的 16 字节/行 hex dump并在 `typeStartPos` 字节后插入
`<` 标记,便于人工反查上一个块的字段对齐。
### Notes —— 待办
- peer 在 V2016 帧(`2323` 起始)里下发 0x30/0x31/0x32 是越界使用 2016 预留区段。
建议推动对端:
1. 切换到 V2025 帧头(`2424`
2. 或迁移到 `0x80~0xFE` 用户自定义区段;
3. 或提供私有协议文档,再决定是否实现 vendor-specific parser。
- `Gb32960BodyParser` 当前对 unknown 块的策略是"吞掉剩余所有字节为单个 Raw 后终止
循环",未做单块异常隔离。后续可改为对每个 parser.parse 调用加 try/catch +
position 回滚,实现单块失败不拖垮整帧。
- `platformAuthorizer.authenticate` 是 EventLoop 同步调用,存在 worker 阻塞风险,
建议挪到独立业务线程池(与 0x30 议题无关,但属于同模块潜在风险)。
[0.1.0]: #010--2026-04-15