Commit Graph

5 Commits

Author SHA1 Message Date
lingniu-dev
982272460a feat(gb32960): wire vendor parser profile selector into decoder pipeline
Final piece that lets the vendor extension framework introduced in
0e6f120 actually take effect on real frames.

Decoder (Gb32960MessageDecoder):
- Adds an overload decode(ByteBuffer, String platformAccount) alongside
  the existing decode(ByteBuffer). Realtime/resend frames build a
  Gb32960ParserContext(version, vin, platformAccount) and pass it to
  bodyParser.parse(ctx, body) so the selector can pick a vendor profile.
- The legacy decode(ByteBuffer) delegates with a null account and is
  preserved for tests and any caller that doesn't care about routing.

Channel handler (Gb32960ChannelHandler):
- Defines AttributeKey<String> PLATFORM_ACCOUNT_ATTR.
- On a successful 0x05 PLATFORM_LOGIN, stores the authenticated username
  on ctx.channel().attr(PLATFORM_ACCOUNT_ATTR).
- On every channelRead0, reads the attribute (null for vehicle-direct
  connections) and passes it to decoder.decode(buffer, account).

Autoconfig (Gb32960AutoConfiguration):
- Replaces the old single-registry wiring with three new beans:
    * VendorExtensionCatalog with the built-in `guangdong-fc` entry
      (the 6 GdFc* parsers from 957a86d)
    * Gb32960ProfileRegistry, built from the union of all standard
      InfoBlockParser beans plus, for each entry referenced in
      lingniu.ingest.gb32960.vendor-extensions, a per-extension registry
      that adds the catalog parsers on top of the defaults
    * VendorExtensionSelector — RuleBasedVendorExtensionSelector when
      vendor-extensions is non-empty, otherwise VendorExtensionSelector.NONE
- gb32960BodyParser now takes (Gb32960ProfileRegistry, VendorExtensionSelector).

Net effect: with the following yml fragment, lingniu account or any VIN
starting with LNVFC routes to the guangdong-fc profile and the previously
"unknown 0x30+" warns become real GdFc* InfoBlock entries:

  lingniu.ingest.gb32960.vendor-extensions:
    - name: guangdong-fc
      match:
        platform-accounts: [lingniu]
        vin-prefixes: [LNVFC, LZG]

All existing 18 tests + 12 new tests (selector + vendor parsers) pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 16:38:31 +08:00
lingniu-dev
957a86d581 feat(gb32960/vendor): implement Guangdong fuel-cell extension parsers
Adds 6 vendor parsers under codec/parser/vendor/guangdong/ implementing the
Guangdong "燃料电池汽车数据接入技术规范 v1.0" extension typeCodes that the
city's data ingestion platform sends inside V2016 frames:

  0x30  GdFcStackBlockParser           §7.2.3.4 表 13/14  fuel-cell stack
  0x31  GdFcAuxiliaryBlockParser       §7.2.3.5 表 15/16  auxiliary system
  0x32  GdFcDcDcBlockParser            §7.2.3.6 表 17     DC/DC
  0x33  GdFcAirConditionerBlockParser  §7.2.3.7 表 18     air conditioner
  0x34  GdFcVehicleInfoBlockParser     §7.2.3.8 表 19     vehicle info
  0x80  GdFcDemoExtensionBlockParser   §7.2.3.14 表 27    demo data extension

Each parser uses ProtocolVersion.V2016 + its respective typeCode and is
strictly Guangdong-spec layout, not the GB/T 32960.3-2025 fuel-cell stack
layout (the two share typeCode 0x30 but have different field orders and
extra cell-voltage statistics in the Guangdong variant).

Field model in InfoBlock.java gains:
- GdFcStack(stackCount, stacks: Stack(workState, waterTempC,
  h2InletPressureKpa, airInletPressureKpa, airInletTempC, max/min/avg cell
  voltage ids and values, cellCount, frameCellStart, frameCellCount,
  frameCellVoltagesV))
- GdFcAuxiliary(subSystemCount, subsystems: Subsystem with air compressor,
  hydrogen pump, water pump, PTC, low-voltage battery)
- GdFcDcDc, GdFcAirConditioner, GdFcVehicleInfo, GdFcDemoExtension
InfoBlockType enum gains the matching GD_FC_* constants.

Tests:
- GdFcParserTest covers the 4 fixed-length parsers (0x32/0x33/0x34/0x80)
  with hand-crafted bytes asserting field-by-field decoded values.
- 0x30/0x31 are variable-length and will be exercised end-to-end via the
  body parser integration test in a follow-up.

Spec doc: adds reference/广东燃料电池汽车示范应用城市群综合监管平台-...pdf
(v1.0.220822) used as the source of truth for these parsers.

These parsers exist as classes only; no Spring beans are wired yet.
Wiring + decoder context plumbing land in the next commit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 16:37:53 +08:00
lingniu-dev
0e6f120ca9 feat(gb32960): introduce parser profile registry and rule-based vendor selector
Adds a per-context routing layer for InfoBlock parsers, so different
peers can be routed to different parser sets (e.g. standard GB/T 32960
vs. a vendor extension that adds blocks in the 0x30~0x7F reserved range).

New types in protocol-gb32960:
- Gb32960ParserContext (record): version + vin + platformAccount tuple
- codec/profile/VendorExtensionCatalog: name -> list of vendor parsers
- codec/profile/Gb32960ProfileRegistry: name -> InfoBlockParserRegistry,
  with a default registry built from the standard parsers and one extra
  registry per enabled vendor extension (default + vendor parsers)
- codec/profile/VendorExtensionSelector: interface returning the matching
  extension name (or null) for a given context
- codec/profile/RuleBasedVendorExtensionSelector: top-down first-match
  scan over Gb32960Properties.vendorExtensions with a (account,vin)
  cache keyed on case-insensitive normalized form

Gb32960Properties gains a `vendorExtensions` list with per-entry
`name` + `match` (platformAccounts / vins / vinPrefixes). All matching
fields are OR'd within an entry; entries are scanned top-down with
first-match-wins as documented.

Gb32960BodyParser keeps its legacy single-registry constructor for
back-compat (used by existing tests) and adds a new constructor that
takes the profile registry + selector. The parse loop now lives under
parse(Gb32960ParserContext, ByteBuffer); the legacy parse(version,body)
delegates to it with a minimal context (selector returns null -> default).

This commit only introduces the framework. Vendor parsers, autoconfig
wiring, and decoder/handler context plumbing land in follow-ups.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 16:37:15 +08:00
lingniu-dev
3b52e6a617 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>
2026-04-15 16:11:27 +08:00
lingniu-dev
064ecc479c chore: initial import of lingniu-vehicle-ingest
Multi-module Spring Boot ingest service for vehicle telemetry. Modules:

- ingest-api / ingest-core / ingest-codec-common: shared SPI, dispatcher,
  Disruptor event bus, BCC/BCD codec helpers
- protocol-gb32960: GB/T 32960.3 inbound (Netty + per-version parser
  packages v2016/v2025), platform login auth, VIN whitelist, idle handler
- protocol-jt808 / protocol-jt1078 / protocol-jsatl12: JT/T inbound
- inbound-mqtt / inbound-xinda-push: alternative ingest channels
- session-core: per-channel session state
- sink-archive / sink-mq: persistence sinks (local file / Kafka)
- command-gateway: terminal control command gateway
- bootstrap-all: aggregator Spring Boot app
- observability: Micrometer / Actuator wiring

Includes hex-dump golden samples under protocol-gb32960/src/test/resources
and the GB/T 32960.3-2016 / 2025 reference PDFs under reference/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 16:08:57 +08:00