Files
docs/wiki/concepts/position-record.md
T
julian 22b1b069df Bootstrap LLM-maintained wiki with TRM architecture knowledge
Initialize CLAUDE.md schema, index, and log; ingest three architecture
sources (system overview, Teltonika ingestion design, official Teltonika
data-sending protocols) into 7 entity pages, 8 concept pages, and 3
source pages with wikilink cross-references.
2026-04-30 13:20:17 +02:00

63 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: Position Record
type: concept
created: 2026-04-30
updated: 2026-04-30
sources: [gps-tracking-architecture, teltonika-ingestion-architecture, teltonika-data-sending-protocols]
tags: [data-model, boundary-contract]
---
# Position Record
The normalized record produced by [[tcp-ingestion]] and consumed by [[processor]]. The boundary contract between vendor adapters and the rest of the system.
## Shape (Teltonika reference)
```ts
type Position = {
device_id: string // IMEI from the handshake
timestamp: Date // from the AVL record's GPS timestamp
latitude: number
longitude: number
altitude: number
angle: number // heading, 0-360
speed: number // km/h
satellites: number
priority: 0 | 1 | 2 // 0=Low, 1=High, 2=Panic (Teltonika spec)
attributes: {
[io_id: string]: number | bigint | Buffer
}
}
```
The system architecture doc lists a slimmer canonical form — `device_id`, `timestamp`, `lat`, `lon`, `speed`, `heading`, plus an attribute bag — and the Teltonika doc extends it with `altitude`, `satellites`, `priority`. Treat the Teltonika shape as the current concrete contract.
## The `attributes` bag — pass through unchanged
The Ingestion service does **not** name, interpret, filter, or unit-convert IO elements. `attributes` is a verbatim representation of the IO element bag from the AVL record, keyed by the numeric IO element ID **as a string**.
Two reasons:
- **Model-specific interpretation belongs where the model is known.** The [[processor]] configures per-model IO mappings; doing this in the parser would couple Ingestion to a registry of every device model in the fleet.
- **A new model never breaks Ingestion.** A packet with `IO 1234` from a device whose config we have not yet imported gets stored under `"1234"` and the position is still useful; the attribute is recoverable later.
This is the property that makes the [[protocol-adapter]] model-agnostic.
## What's codec-defined vs. model-defined
For [[teltonika]]:
- **Codec-defined** (always present, same shape per codec): timestamp, lat/lon/alt, angle, satellites, speed, priority. These fill out the typed fields above.
- **Model-defined** (varies between models, opaque to parser): everything in the IO bag.
### Codec-specific quirks
- **Speed = `0x0000` means GPS data is invalid**, not "stationary." The parser preserves this verbatim (speed = 0); the [[processor]] decides whether to surface it as "no GPS fix" or coalesce with the stationary case.
- **Lat/Lon are two's complement** signed integers — first bit = sign. Parsing must be sign-aware.
- **Codec 16 carries a Generation Type** (07: On Exit, On Entrance, On Both, Reserved, Hysteresis, On Change, Eventual, Periodical) that is codec-defined but not currently in the Position shape. Open question on whether to promote it to a typed field. See [[avl-data-format]].
- **Codec 8 Extended NX section** carries variable-length IO values — these land in `attributes` as `Buffer`, alongside the fixed-width N1/N2/N4/N8 entries.
## Downstream contract
[[processor]] is responsible for naming IO elements (e.g. `"16"``"odometer_km"`), unit conversions, and any filtering. It writes the typed fields to the positions hypertable and may write derived/named attributes to other tables.