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>
This commit is contained in:
lingniu-dev
2026-04-15 16:08:57 +08:00
commit 064ecc479c
220 changed files with 11874 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
package com.lingniu.ingest.codec;
/** BCC异或校验。GB/T 32960 与 JT/T 808 都使用此方式做帧尾校验。 */
public final class BccChecksum {
private BccChecksum() {}
public static byte compute(byte[] data, int offset, int length) {
byte sum = 0;
for (int i = offset; i < offset + length; i++) {
sum ^= data[i];
}
return sum;
}
public static boolean verify(byte[] data, int offset, int length, byte expected) {
return compute(data, offset, length) == expected;
}
}

View File

@@ -0,0 +1,30 @@
package com.lingniu.ingest.codec;
/** BCD (Binary-Coded Decimal) 编解码。JT/T 808 的手机号、时间戳常用。 */
public final class BcdCodec {
private BcdCodec() {}
public static byte[] encode(String decimal) {
int len = (decimal.length() + 1) / 2;
byte[] out = new byte[len];
int idx = decimal.length() % 2;
if (idx == 1) {
out[0] = (byte) Character.digit(decimal.charAt(0), 10);
}
for (int i = idx; i < decimal.length(); i += 2) {
int hi = Character.digit(decimal.charAt(i), 10);
int lo = Character.digit(decimal.charAt(i + 1), 10);
out[(i + idx) / 2] = (byte) ((hi << 4) | lo);
}
return out;
}
public static String decode(byte[] bcd) {
StringBuilder sb = new StringBuilder(bcd.length * 2);
for (byte b : bcd) {
sb.append((b >> 4) & 0x0F).append(b & 0x0F);
}
return sb.toString();
}
}

View File

@@ -0,0 +1,34 @@
package com.lingniu.ingest.codec;
/** 位运算工具:从字节数组读写无符号整数。 */
public final class BitUtils {
private BitUtils() {}
public static int readUint8(byte[] buf, int offset) {
return buf[offset] & 0xFF;
}
public static int readUint16BE(byte[] buf, int offset) {
return ((buf[offset] & 0xFF) << 8) | (buf[offset + 1] & 0xFF);
}
public static long readUint32BE(byte[] buf, int offset) {
return ((long) (buf[offset] & 0xFF) << 24)
| ((long) (buf[offset + 1] & 0xFF) << 16)
| ((long) (buf[offset + 2] & 0xFF) << 8)
| (buf[offset + 3] & 0xFF);
}
public static void writeUint16BE(byte[] buf, int offset, int value) {
buf[offset] = (byte) ((value >> 8) & 0xFF);
buf[offset + 1] = (byte) (value & 0xFF);
}
public static void writeUint32BE(byte[] buf, int offset, long value) {
buf[offset] = (byte) ((value >> 24) & 0xFF);
buf[offset + 1] = (byte) ((value >> 16) & 0xFF);
buf[offset + 2] = (byte) ((value >> 8) & 0xFF);
buf[offset + 3] = (byte) (value & 0xFF);
}
}