Implement Phase 1 tasks 1.5-1.7 + 1.9 (Codec 8/8E/16 parsers + fixture suite)

- Codec 8 parser (1-byte IO IDs, no NX/Generation Type)
- Codec 8 Extended parser (2-byte IO IDs + variable-length NX section)
- Codec 16 parser (mixed widths + Generation Type, supports IO IDs > 255)
- Shared GPS element / timestamp helpers in gps-element.ts
- Fixture loader with bigint/Buffer sentinel encoding and auto-discovery
- 12 fixture pairs across codec8/8E/16 (canonical doc + synthetic edge cases)
- Cross-checked Codec 8 against Traccar's TeltonikaProtocolDecoder (no discrepancies)

26 new tests. Total 62 passing across 10 test files.
typecheck/lint/test/build all clean.
This commit is contained in:
2026-04-30 16:15:27 +02:00
parent 1e9219d14a
commit 381287bacc
34 changed files with 1672 additions and 1 deletions
+11 -1
View File
@@ -5,6 +5,9 @@ import { AllowAllAuthority } from './device-authority.js';
import { readImeiHandshake, HandshakeError } from './handshake.js';
import { BufferedReader, readNextFrame, FrameDropError } from './frame.js';
import { CodecRegistry } from './codec/registry.js';
import { codec8Handler } from './codec/data/codec8.js';
import { codec8eHandler } from './codec/data/codec8e.js';
import { codec16Handler } from './codec/data/codec16.js';
export type TeltonikaAdapterOptions = {
readonly port: number;
@@ -26,7 +29,14 @@ export type TeltonikaAdapterOptions = {
export function createTeltonikaAdapter(options: TeltonikaAdapterOptions): Adapter {
const authority: DeviceAuthority = options.deviceAuthority ?? new AllowAllAuthority();
const strictDeviceAuth = options.strictDeviceAuth ?? false;
const codecRegistry = options.codecRegistry ?? new CodecRegistry();
// Build default registry with all three Phase 1 data codecs registered.
// Callers can pass their own registry (e.g. in tests) to override.
const defaultRegistry = new CodecRegistry();
defaultRegistry.register(codec8Handler);
defaultRegistry.register(codec8eHandler);
defaultRegistry.register(codec16Handler);
const codecRegistry = options.codecRegistry ?? defaultRegistry;
return {
name: 'teltonika',