Skip to content

Detail Helpers

Stefan Gofferje edited this page Aug 26, 2026 · 1 revision

Detail Helpers

Raw XML access is nice for fidelity, tedious for daily work. The helper layer gives you typed access for the blocks that matter — without giving up the lossless detail tree underneath.

Three layers:

  1. Setters — upsert a known block into detail
  2. Factories — create a complete event for a common use case in one call
  3. Predicates — quick "what am I looking at" checks

Setters

All setters return the event, so they chain. They upsert: an existing block gets its mentioned attributes replaced, unmentioned ones kept, and any unknown sibling blocks are never touched.

Setter Writes
set_contact(callsign, endpoint=None, phone=None) <contact>
set_group(name, role) <__group> team membership
set_track(speed=..., course=...) <track> movement vector
set_remarks(text) <remarks> free text
set_status(readiness=True, battery=None) <status>
set_precision_location(geopointsrc=None, altsrc=None) <precisionlocation>
set_color(argb) <color> signed ARGB (-65536 = red)
event.set_contact("MYCALL").set_group("Cyan", "Team Member").set_color(-16711936)

Important

Team names and roles have a limited set of valid values. set_group() validates both and raises ValueError listing the valid options. See takstream.cot.VALID_TEAMS / VALID_ROLES.

Factories

Marker

marker = CotEvent.marker(
    48.208, 16.373,
    callsign="PIT",
    remarks="landmark",        # optional
    color_argb=-65536,         # optional
)

Produces type b-m-p-s-m with contact/remarks/color detail blocks.

SA position report

sa = CotEvent.sa_report(
    48.208, 16.373,
    callsign="MYCALL",
    team="Cyan",
    role="Team Member",
    speed=5.0, course=90.0,    # optional
    battery=88,                # optional
)

Produces type a-f-G-U-C with contact/group and optional track/status.

GeoChat message

chat = CotEvent.chat_message(
    "roger that",
    sender_callsign="ALPHA",
    sender_uid="ANDROID-123",
    chatroom="All Chat Rooms",  # default
)

Produces type b-t-f — the current ATAK 5.8 wire format, where the text travels in <remarks> and <__chat> carries the routing metadata with a nested <chatgrp>. Do not copy examples using b-a-o-t with a msg attribute; that is ancient history.

Chat receipts

delivery = CotEvent.chat_receipt(chat, receipt_type="b-t-f-d", responder_callsign="BRAVO")
read = CotEvent.chat_receipt(chat, receipt_type="b-t-f-r", responder_callsign="BRAVO")

Mirrors the routing metadata of the original message so the server routes the receipt back to the sender. Event uid and __chatreceipt/@messageId reference the original message.

Emergency

alert = CotEvent.emergency_alert(48.2, 16.3, callsign="MYCALL")
cancel = CotEvent.emergency_cancel(uid=alert.uid, callsign="MYCALL")

Alert produces type b-a-o-tif, cancel produces b-a-o-can.

Predicates

Predicate True for
is_sa() Position reports (a-f-, a-u-, a-n-)
is_marker() User-placed markers (b-m-)
is_chat() GeoChat messages and receipts (b-t-f*)
is_emergency() Alerts (b-a-o-tif) and cancellations (b-a-o-can)
is_stale() Events past their stale time

Every factory output round-trips through the wire format — covered by tests, not by optimism.

Clone this wiki locally