Skip to main content
Version: 2.8

TAK Protocol

The app implements three CoT (Cursor-on-Target) wire formats over LoRaLoRaA low-power, long-range wireless communication technology used by Meshtastic devices to enable communication over distances of several kilometers without the need for cellular, Wi-Fi, or other traditional network infrastructures.: two legacy V1 paths and one V2 path that uses the TAKPacket-SDK for zstd-dictionary compression and richer typed payloads. This page documents the choice of format, the receive dispatch, and the supporting infrastructure.

Wire Formats

FormatPortPayloadUsed when
V1 ATAK_PLUGIN72Bare TAKPacket protobufProtobuf (Protocol Buffers). A method developed by Google for serializing structured data, used in Meshtastic for efficient communication protocol between devices. (PLI / GeoChat only)Connected radio firmware < 2.8.0
V1 ATAK_FORWARDER257zlib-compressed CoT XML, optionally Fountain (LT) coded for multi-packet payloadsConnected radio firmware < 2.8.0, CoT type other than PLI / GeoChat (Apple-to-Apple only)
V2 ATAK_PLUGIN_V278TAKPacketV2 protobufProtobuf (Protocol Buffers). A method developed by Google for serializing structured data, used in Meshtastic for efficient communication protocol between devices., compressed with the TAKPacket-SDK zstd dictionaryConnected radio firmware ≥ 2.8.0

V2 carries the full typed CoT vocabulary: PLI, GeoChat, shapes, markers, routes, casevac, emergency, and task. V1 ATAK_PLUGIN carries PLI and GeoChat only; everything else falls back to the V1 ATAK_FORWARDER path.

Per-send Fork

TAKMeshtasticBridge.sendToMesh(_:clientInfo:) chooses the format on every send based on AccessoryManager.supportsTAKv2, which checks the connected radio's firmware version:

if accessoryManager.supportsTAKv2 {
// V2: SDK-driven path
let parser = MeshtasticTAK.CotXmlParser()
let packet = try parser.parse(strippedXml)
let compressor = MeshtasticTAK.TakCompressor()
// `compressWithRemarksFallback` returns `Data?` — `nil` means the
// payload is still over the LoRa MTU even after `<remarks>` are
// stripped. The real `sendCoTToMeshV2` translates that into a
// thrown `AccessoryError.ioFailed(...)` so the caller's `do/catch`
// doesn't treat the silent drop as a successful send.
guard let wire = try compressor.compressWithRemarksFallback(packet, maxWireBytes: 225) else {
throw AccessoryError.ioFailed("TAK V2 payload exceeds LoRa wire size limit")
}
try await sendTAKV2Packet(wire, channel: channel)
} else {
// V1: classify, then dispatch
switch GenericCoTHandler.shared.classifySendMethod(for: cot) {
case .takPacketPLI, .takPacketChat:
let pkt = convertToTAKPacket(cot: cot)
try await sendTAKPacket(pkt, channel: channel)
case .exiDirect, .exiFountain:
try await GenericCoTHandler.shared.sendGenericCoT(cot, channel: channel)
}
}

The fork is per-send (not per-session) so a radio that upgrades mid-session jumps to V2 immediately.

Receive Dispatch

AccessoryManager.swift's exhaustive portnum switch dispatches incoming TAKTAK (Team Awareness Kit). A situational awareness ecosystem. Meshtastic bridges to it by converting mesh messages to and from Cursor on Target format. packets to handlers in AccessoryManager+TAK.swift:

PortnumHandlerBehavior
.atakPlugin (72)handleATAKPluginPacket(_:)Decode bare TAKPacket protobufProtobuf (Protocol Buffers). A method developed by Google for serializing structured data, used in Meshtastic for efficient communication protocol between devices.; convert PLI / GeoChat to CoTMessage; forward to TAKTAK (Team Awareness Kit). A situational awareness ecosystem. Meshtastic bridges to it by converting mesh messages to and from Cursor on Target format. clients via TAKServerManager.shared.broadcast(_:).
.atakPluginV2 (78)handleATAKPluginV2Packet(_:)zstd-decompress with TakCompressor; rebuild CoT XML with CotXmlBuilder; strip the XML prologue and inter-tag whitespace; forward raw XML via broadcastRawXml(_:) so shape detail (<link point> vertices, colors, stroke) survives. Route CoT (b-m-r) triggers the route data package side-effect.
.atakForwarder (257)handleATAKForwarderPacket(_:)Hand off to GenericCoTHandler.handleIncomingForwarderPacket(_:), which reassembles Fountain fragments and zlib-decompresses the resulting CoT XML before broadcasting.

TAKPacket-SDK

The TAKPacket-SDK Swift Package is pinned in Meshtastic.xcworkspace/.../Package.resolved. The bridge uses three APIs:

  • MeshtasticTAK.CotXmlParser().parse(_:) — parses CoT XML into a TAKPacketV2 protobufProtobuf (Protocol Buffers). A method developed by Google for serializing structured data, used in Meshtastic for efficient communication protocol between devices.. throws; callers must try.
  • MeshtasticTAK.TakCompressor().compressWithRemarksFallback(_:maxWireBytes:) — picks the zstd dictionary best suited to the payload, attempts compression, and on overflow retries with <remarks> stripped. Returns nil if the payload is too large even without remarks; sendCoTToMeshV2 translates the nil into AccessoryError.ioFailed(...) so the caller's do/catch doesn't treat the drop as a successful send.
  • MeshtasticTAK.CotXmlBuilder().build(_:) — round-trips TAKPacketV2 back to CoT XML for forwarding to TAKTAK (Team Awareness Kit). A situational awareness ecosystem. Meshtastic bridges to it by converting mesh messages to and from Cursor on Target format. clients.

The wire MTU constant maxWirePayloadBytes = 225 reflects the LoRaLoRaA low-power, long-range wireless communication technology used by Meshtastic devices to enable communication over distances of several kilometers without the need for cellular, Wi-Fi, or other traditional network infrastructures. frame budget after the Meshtastic envelope.

Identity Admin

TAKIdentitySection (embedded in TAKServerConfig) reads node.takConfig for the current team and role values. When the node has no TAKTAK (Team Awareness Kit). A situational awareness ecosystem. Meshtastic bridges to it by converting mesh messages to and from Cursor on Target format. config cached, requestTakConfigIfNeeded() fires an admin request via AccessoryManager.requestTAKModuleConfig(fromUser:toUser:) so first-time users don't see a perma-spinner.

Saving the identity dispatches AccessoryManager.saveTAKModuleConfig(config:fromUser:toUser:), which packages a ModuleConfig.TAKConfig inside an AdminMessage and ships it on the admin port.

Offline Queue

TAKServerManager buffers outgoing CoT for delivery when a TAKTAK (Team Awareness Kit). A situational awareness ecosystem. Meshtastic bridges to it by converting mesh messages to and from Cursor on Target format. client reconnects:

private enum QueuedPayload {
case message(CoTMessage)
case rawXml(String)
}

broadcast(_:) enqueues .message payloads; broadcastRawXml(_:) enqueues .rawXml so V2 shapes / routes / markers retain their detail elements. The queue has a 5-minute TTL and a 50-entry cap. drainOfflineQueue() dispatches the right path per payload variant when a client (re)connects.

Route Data Packages

RouteDataPackageGenerator (in Meshtastic/Helpers/TAK/) converts route CoT (b-m-r) into KML-inside-zip ATAKATAK (Android Team Awareness Kit). The Android TAK client. An official Meshtastic plugin forwards its Cursor on Target traffic over the mesh. data packages that the user can sideload into iTAK (which silently ignores route CoT received over its TCPTCP (Transmission Control Protocol). One of the three ways a client reaches a node, alongside serial and Bluetooth. Clients connect over TCP on port 4403. streaming connection).

The pipeline:

  1. generateKml(routeXml:) extracts <event uid>, <contact callsign>, and every <link point="lat,lon,hae"> waypoint via attributeValue(in:on:named:), which supports both single- and double-quoted attributes.
  2. sanitizeForFilename(_:) strips path separators, control chars, and .. sequences from the route UID so it's safe to use in file names and the temp directory path. escapeXml(_:) separately escapes the value before interpolation into the manifest's value="..." attribute.
  3. generateDataPackage(routeXml:) writes the KML and manifest.xml to a temp directory and zips them with NSFileCoordinator(readingItemAt:options:.forUploading).
  4. saveToDocuments(fileName:zipData:) writes the zip to Documents/TAK Routes/<sanitizedUid>.zip (creating the directory on first use).
  5. AccessoryManager+TAK.handleATAKPluginV2Packet(_:) posts a Notification titled Route Received with the route callsign as subtitle and body Saved to Files → Meshtastic → TAKTAK (Team Awareness Kit). A situational awareness ecosystem. Meshtastic bridges to it by converting mesh messages to and from Cursor on Target format. Routes. Open in iTAK to import.

Capabilities

AccessoryManager.supportsTAKv2 is the canonical gate. It enables V2 only when the active radio reports a supported, well-formed version; an unavailable, malformed, or older version uses V1.

var supportsTAKv2: Bool { Self.isTAKv2Supported(firmwareVersion: connectedVersion) }

The capability parser accepts numeric major.minor.patch versions and an optional hexadecimal build suffix, such as 2.8.0.3a0c08b. Use this property (rather than parsing the firmware version inline) anywhere a V1/V2 decision is needed. Future TAKTAK (Team Awareness Kit). A situational awareness ecosystem. Meshtastic bridges to it by converting mesh messages to and from Cursor on Target format. SDK features that require a higher firmware version should add a sibling property with a clear cut-off so the bridge stays declarative.

  • Meshtastic/Helpers/TAK/TAKMeshtasticBridge.swift — V1/V2 fork in sendToMesh.
  • Meshtastic/Accessory/Accessory Manager/AccessoryManager+TAK.swift — send and receive handlers.
  • Meshtastic/Helpers/TAK/TAKServerManager.swiftTCPTCP (Transmission Control Protocol). One of the three ways a client reaches a node, alongside serial and Bluetooth. Clients connect over TCP on port 4403. server, offline queue, certificate management.
  • Meshtastic/Helpers/TAK/GenericCoTHandler.swift — V1 ATAK_FORWARDER classification and Fountain reassembly.
  • Meshtastic/Helpers/TAK/RouteDataPackageGenerator.swift — KML data package writer.
  • Meshtastic/Views/Settings/TAKServerConfig.swift — combined TAKTAK (Team Awareness Kit). A situational awareness ecosystem. Meshtastic bridges to it by converting mesh messages to and from Cursor on Target format. Server settings screen with the embedded TAKIdentitySection.

See also Transport Layer for the AccessoryManager extension map.