Converts ATAK Cursor-on-Target (CoT) XML into Meshtastic's TAKPacketV2
protobuf and compresses it with zstd dictionary compression for transport
over a LoRa mesh (237-byte MTU, Meshtastic port 78 / ATAK_PLUGIN_V2).
Frames emitted by this binding are cross-decodable with the Kotlin, Swift,
Python, and C# bindings of the same SDK.
Remarks
The pipeline has three stages, each exposed as a standalone entry point so
callers can compose them or use them independently:
Type/dictionary classification — the CotTypeMapper helpers map CoT
type strings to/from the CotType enum and decide aircraft vs.
non-aircraft; the DictionaryProvider helpers load the matching zstd
dictionary.
Supporting modules: the AtakPalette helpers (ARGB ↔ Team color enum) and
the CotMeshSanitizer helpers (pre-parse CoT-XML hygiene for mesh transport).
Wire format. Every payload is [1 byte flags][N bytes body], total ≤ 237
bytes. Flags bits 0–5 carry the dictionary ID (0 = non-aircraft, 1 =
aircraft); the special flags value 0xFF means the body is raw,
uncompressed protobuf. The 4-byte zstd magic number is stripped on encode and
re-prepended on decode to save bytes.
Resilience invariant. Every packet is fully and independently decodable
from its own bytes plus the static shipped dictionary — there is zero
cross-packet state, and only the one-shot zstd API is used (never streaming).
A position report carrying no payload variant with an a-f-* CoT type is an
implicit PLI (there is no pli boolean on the wire).
TAKPacket-SDK — TypeScript binding.
Converts ATAK Cursor-on-Target (CoT) XML into Meshtastic's
TAKPacketV2protobuf and compresses it with zstd dictionary compression for transport over a LoRa mesh (237-byte MTU, Meshtastic port 78 /ATAK_PLUGIN_V2). Frames emitted by this binding are cross-decodable with the Kotlin, Swift, Python, and C# bindings of the same SDK.Remarks
The pipeline has three stages, each exposed as a standalone entry point so callers can compose them or use them independently:
CotTypeMapperhelpers map CoT type strings to/from theCotTypeenum and decide aircraft vs. non-aircraft; theDictionaryProviderhelpers load the matching zstd dictionary.[flags][zstd body]payload and TakCompressor.decompress reverses it.Supporting modules: the
AtakPalettehelpers (ARGB ↔ Team color enum) and theCotMeshSanitizerhelpers (pre-parse CoT-XML hygiene for mesh transport).Wire format. Every payload is
[1 byte flags][N bytes body], total ≤ 237 bytes. Flags bits 0–5 carry the dictionary ID (0 = non-aircraft, 1 = aircraft); the special flags value0xFFmeans the body is raw, uncompressed protobuf. The 4-byte zstd magic number is stripped on encode and re-prepended on decode to save bytes.Resilience invariant. Every packet is fully and independently decodable from its own bytes plus the static shipped dictionary — there is zero cross-packet state, and only the one-shot zstd API is used (never streaming). A position report carrying no payload variant with an
a-f-*CoT type is an implicit PLI (there is nopliboolean on the wire).