feat(atak): CasevacReport / EmergencyAlert / TaskRequest + 43 CoT types

Expand the TAKPacketV2 payload_variant with three new typed messages at
tags 38/39/40, extend GeoChat with receipt fields, add 43 new CotType
enum entries (82-124), and add 3 DrawnShape.Kind / 5 Marker.Kind values
for types the previous rollout left on the cot_type_str fallback path.

- CasevacReport (tag 38): 9-line MEDEVAC with Precedence / HlzMarking /
  Security enums and equipment_flags / terrain_flags bitfields. Mirrors
  ATAK's <_medevac_> detail element; captures what the raw-detail
  fallback would otherwise drop (patient counts, zone marker, freq).
- EmergencyAlert (tag 39): typed record for b-a-o-* / b-a-g alerts,
  carries authoring_uid and cancel_reference_uid so modern receivers
  can handle the alert chain without XML parsing.
- TaskRequest (tag 40): t-s engagement / tasking record with Priority /
  Status enums, task_type / target_uid / assignee_uid / note fields.
  All strings capped tight so the worst case fits under the LoRa MTU.
- GeoChat (tag 31): append receipt_for_uid + receipt_type for b-t-f-d
  (delivered) and b-t-f-r (read) receipts riding on the existing chat
  slot — no new oneof case needed.
- CotType: +43 values covering a-f-G-E-V-A self PLI, the neutral-
  aircraft affiliation, the full 2525 quick-drop set (artillery /
  building / mine / ship / sniper / tank / troops / vehicle) across
  unknown / neutral / hostile / friendly affiliations, mission points
  (GOTO / IP / CP / OP), vehicle shapes, ellipse drawing, image
  marker, chat receipts, custom emergency, and tasking.
- DrawnShape.Kind: +Ellipse (8) / Vehicle2D (9) / Vehicle3D (10).
- Marker.Kind: +GoToPoint (8) / InitialPoint (9) / ContactPoint (10)
  / ObservationPost (11) / ImageMarker (12).
- atak.options: pool sizing for every new field. int_size:8 for byte
  counts and bitfields, max_size:12-48 for strings to keep the worst-
  case wire size under 237B.

All additions are append-only — proto3 unknown-field semantics
preserve wire compatibility for pre-update receivers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ben Meadors 2026-04-09 17:23:23 -05:00
parent 01d2901266
commit 10a86bf0b9
2 changed files with 431 additions and 2 deletions

View file

@ -76,4 +76,35 @@
*Route.stroke_weight_x10 int_size:16
*Route.Link.uid max_size:48
*Route.Link.callsign max_size:16
*Route.Link.link_type int_size:8
*Route.Link.link_type int_size:8
# GeoChat receipt extension. receipt_for_uid matches TAKPacketV2.uid caps.
*GeoChat.receipt_for_uid max_size:48
# CasevacReport pool sizing. All numeric fields are small (0..255 for
# patient counts, 1 byte for flags bitfields); strings are short.
*CasevacReport.equipment_flags int_size:8
*CasevacReport.terrain_flags int_size:8
*CasevacReport.litter_patients int_size:8
*CasevacReport.ambulatory_patients int_size:8
*CasevacReport.us_military int_size:8
*CasevacReport.us_civilian int_size:8
*CasevacReport.non_us_military int_size:8
*CasevacReport.non_us_civilian int_size:8
*CasevacReport.epw int_size:8
*CasevacReport.child int_size:8
*CasevacReport.zone_marker max_size:16
*CasevacReport.frequency max_size:16
# EmergencyAlert pool sizing. UIDs match TAKPacketV2.uid caps (48).
*EmergencyAlert.authoring_uid max_size:48
*EmergencyAlert.cancel_reference_uid max_size:48
# TaskRequest pool sizing. All four strings are capped tight so the
# worst-case wire size stays under the LoRa MTU with headroom. task_type
# is a short category tag; target_uid/assignee_uid match TAKPacketV2.uid
# conventions; note is the one user-entered field.
*TaskRequest.task_type max_size:12
*TaskRequest.target_uid max_size:32
*TaskRequest.assignee_uid max_size:32
*TaskRequest.note max_size:48

View file

@ -55,7 +55,21 @@ message TAKPacket {
*/
message GeoChat {
/*
* The text message
* Receipt discriminator. Set alongside cot_type_id = b-t-f-d (delivered)
* or b-t-f-r (read). ReceiptType_None is the default for a normal chat
* message (cot_type_id = b-t-f).
*
* Receivers can detect a receipt by checking receipt_type != None without
* re-parsing the envelope cot_type_id.
*/
enum ReceiptType {
ReceiptType_None = 0; // normal chat message
ReceiptType_Delivered = 1; // b-t-f-d delivered receipt
ReceiptType_Read = 2; // b-t-f-r read receipt
}
/*
* The text message. Empty for receipts.
*/
string message = 1;
@ -68,6 +82,20 @@ message GeoChat {
* Callsign of the recipient for the message
*/
optional string to_callsign = 3;
/*
* UID of the chat message this event is acknowledging. Empty for a
* normal chat message; set for delivered / read receipts. Paired with
* receipt_type so receivers can match the ack back to the original
* outbound GeoChat by its event uid.
*/
string receipt_for_uid = 4;
/*
* Receipt kind discriminator. See ReceiptType doc. Default ReceiptType_None
* means this is a regular chat message, not a receipt.
*/
ReceiptType receipt_type = 5;
}
/*
@ -700,6 +728,136 @@ enum CotType {
* reference (magnetic / true / grid).
*/
CotType_u_r_b_bullseye = 81;
// ======================================================================
// Expanded coverage from the ATAK-CIV quick-drop pallet (values 82-124).
// ======================================================================
//
// All of these types existed as cot_type_str strings; promoting them to
// enum values turns a ~10-byte string into a 1-byte varint on the wire
// for every event that uses them. Grouped below by pallet section.
// --- PLI self-reporting (1) ------------------------------------------
/*
* a-f-G-E-V-A: Friendly armored vehicle, user-selectable self PLI.
*/
CotType_a_f_G_E_V_A = 82;
// --- 2525 quick-drop: basic affiliation gaps -------------------------
/*
* a-n-A: Neutral aircraft (friendly/hostile/unknown already present).
*/
CotType_a_n_A = 83;
// --- 2525 quick-drop: artillery (4) ----------------------------------
CotType_a_u_G_U_C_F = 84;
CotType_a_n_G_U_C_F = 85;
CotType_a_h_G_U_C_F = 86;
CotType_a_f_G_U_C_F = 87;
// --- 2525 quick-drop: building (4) -----------------------------------
CotType_a_u_G_I = 88;
CotType_a_n_G_I = 89;
CotType_a_h_G_I = 90;
CotType_a_f_G_I = 91;
// --- 2525 quick-drop: mine (4) ---------------------------------------
CotType_a_u_G_E_X_M = 92;
CotType_a_n_G_E_X_M = 93;
CotType_a_h_G_E_X_M = 94;
CotType_a_f_G_E_X_M = 95;
// --- 2525 quick-drop: ship (3; a-f-S already at 17) ------------------
CotType_a_u_S = 96;
CotType_a_n_S = 97;
CotType_a_h_S = 98;
// --- 2525 quick-drop: sniper (4) -------------------------------------
CotType_a_u_G_U_C_I_d = 99;
CotType_a_n_G_U_C_I_d = 100;
CotType_a_h_G_U_C_I_d = 101;
CotType_a_f_G_U_C_I_d = 102;
// --- 2525 quick-drop: tank (4) ---------------------------------------
CotType_a_u_G_E_V_A_T = 103;
CotType_a_n_G_E_V_A_T = 104;
CotType_a_h_G_E_V_A_T = 105;
CotType_a_f_G_E_V_A_T = 106;
// --- 2525 quick-drop: troops (3; a-f-G-U-C-I already at 2) -----------
CotType_a_u_G_U_C_I = 107;
CotType_a_n_G_U_C_I = 108;
CotType_a_h_G_U_C_I = 109;
// --- 2525 quick-drop: generic vehicle (3; a-u-G-E-V already at 69) ---
CotType_a_n_G_E_V = 110;
CotType_a_h_G_E_V = 111;
CotType_a_f_G_E_V = 112;
// --- Mission-specific points (4) -------------------------------------
/*
* b-m-p-w-GOTO: Go To / bloodhound navigation target.
*/
CotType_b_m_p_w_GOTO = 113;
/*
* b-m-p-c-ip: Initial point (mission planning).
*/
CotType_b_m_p_c_ip = 114;
/*
* b-m-p-c-cp: Contact point (mission planning).
*/
CotType_b_m_p_c_cp = 115;
/*
* b-m-p-s-p-op: Observation post.
*/
CotType_b_m_p_s_p_op = 116;
// --- Vehicle drawings (2) --------------------------------------------
/*
* u-d-v: 2D vehicle outline drawn on the map.
*/
CotType_u_d_v = 117;
/*
* u-d-v-m: 3D vehicle model reference.
*/
CotType_u_d_v_m = 118;
// --- Drawing shapes (1) ----------------------------------------------
/*
* u-d-c-e: Non-circular ellipse (circle with distinct major/minor axes).
*/
CotType_u_d_c_e = 119;
// --- Image / media marker (1) ----------------------------------------
/*
* b-i-x-i: Quick Pic geotagged image marker. The image itself does not
* ride on LoRa; this event references the image via iconset metadata.
*/
CotType_b_i_x_i = 120;
// --- GeoChat receipts (2) --------------------------------------------
/*
* b-t-f-d: GeoChat delivered receipt. Carried on the existing `chat`
* payload_variant via GeoChat.receipt_for_uid + receipt_type.
*/
CotType_b_t_f_d = 121;
/*
* b-t-f-r: GeoChat read receipt. Same wire slot as b-t-f-d.
*/
CotType_b_t_f_r = 122;
// --- Custom emergency (1) --------------------------------------------
/*
* b-a-o-c: Custom / generic emergency beacon.
*/
CotType_b_a_o_c = 123;
// --- Tasking (1) -----------------------------------------------------
/*
* t-s: Task / engage request. Structured payload carried via the new
* TaskRequest typed variant.
*/
CotType_t_s = 124;
}
/*
@ -850,6 +1008,22 @@ message DrawnShape {
* u-r-b-bullseye: Bullseye ring with range rings and bearing reference
*/
Kind_Bullseye = 7;
/*
* u-d-c-e: Ellipse with distinct major/minor axes (same storage as
* Kind_Circle uses major_cm/minor_cm/angle_deg but receivers
* render it as a non-circular ellipse rather than a round circle).
*/
Kind_Ellipse = 8;
/*
* u-d-v: 2D vehicle outline drawn on the map. Vertices carry the
* outline polygon; receivers draw it as a filled polygon.
*/
Kind_Vehicle2D = 9;
/*
* u-d-v-m: 3D vehicle model reference. Same vertex polygon as
* Kind_Vehicle2D; receivers that support 3D rendering extrude it.
*/
Kind_Vehicle3D = 10;
}
/*
* Explicit stroke/fill/both discriminator.
@ -1014,6 +1188,28 @@ message Marker {
* Custom icon set (UUID/GroupName/filename.png)
*/
Kind_CustomIcon = 7;
/*
* b-m-p-w-GOTO: Go To / bloodhound navigation waypoint.
*/
Kind_GoToPoint = 8;
/*
* b-m-p-c-ip: Initial point (mission planning control point).
*/
Kind_InitialPoint = 9;
/*
* b-m-p-c-cp: Contact point (mission planning control point).
*/
Kind_ContactPoint = 10;
/*
* b-m-p-s-p-op: Observation post.
*/
Kind_ObservationPost = 11;
/*
* b-i-x-i: Quick Pic geotagged image marker. iconset carries the
* image reference (local filename or remote URL); the image itself
* does not ride on the LoRa wire.
*/
Kind_ImageMarker = 12;
}
/*
* Marker kind
@ -1199,6 +1395,196 @@ message Route {
bool truncated = 6;
}
/*
* 9-line MEDEVAC request (CoT type b-r-f-h-c).
*
* Mirrors the ATAK MedLine tool's <_medevac_> detail element. Every field
* is optional (proto3 default); senders omit lines they don't have. The
* envelope (TAKPacketV2.uid, cot_type_id=b-r-f-h-c, latitude_i/longitude_i,
* altitude, callsign) carries Line 1 (location) and Line 2 (callsign).
*
* All numeric fields are tight varints so a complete 9-line request fits
* in well under 100 bytes of proto on the wire.
*/
message CasevacReport {
/*
* Line 3: precedence / urgency.
*/
enum Precedence {
Precedence_Unspecified = 0;
Precedence_Urgent = 1; // A - immediate, life-threatening
Precedence_UrgentSurgical = 2; // B - needs surgery
Precedence_Priority = 3; // C - within 4 hours
Precedence_Routine = 4; // D - within 24 hours
Precedence_Convenience = 5; // E - convenience
}
/*
* Line 7: HLZ marking method.
*/
enum HlzMarking {
HlzMarking_Unspecified = 0;
HlzMarking_Panels = 1;
HlzMarking_PyroSignal = 2;
HlzMarking_Smoke = 3;
HlzMarking_None = 4;
HlzMarking_Other = 5;
}
/*
* Line 6: security situation at the pickup zone.
*/
enum Security {
Security_Unspecified = 0;
Security_NoEnemy = 1; // N - no enemy activity
Security_PossibleEnemy = 2; // P - possible enemy
Security_EnemyInArea = 3; // E - enemy, approach with caution
Security_EnemyInArmedContact = 4; // X - armed escort required
}
/*
* Line 3: precedence / urgency.
*/
Precedence precedence = 1;
/*
* Line 4: special equipment required, as a bitfield.
* bit 0: none
* bit 1: hoist
* bit 2: extraction equipment
* bit 3: ventilator
* bit 4: blood
*/
uint32 equipment_flags = 2;
/*
* Line 5: number of litter (stretcher-bound) patients.
*/
uint32 litter_patients = 3;
/*
* Line 5: number of ambulatory (walking-wounded) patients.
*/
uint32 ambulatory_patients = 4;
/*
* Line 6: security situation at the PZ.
*/
Security security = 5;
/*
* Line 7: HLZ marking method.
*/
HlzMarking hlz_marking = 6;
/*
* Line 7 supplementary: short free-text describing the zone marker
* (e.g. "Green smoke", "VS-17 panel west"). Capped tight in options.
*/
string zone_marker = 7;
// --- Line 8: patient nationality counts ---
uint32 us_military = 8;
uint32 us_civilian = 9;
uint32 non_us_military = 10;
uint32 non_us_civilian = 11;
uint32 epw = 12; // enemy prisoner of war
uint32 child = 13;
/*
* Line 9: terrain and obstacles at the PZ, as a bitfield.
* bit 0: slope
* bit 1: rough
* bit 2: loose
* bit 3: trees
* bit 4: wires
* bit 5: other
*/
uint32 terrain_flags = 14;
/*
* Line 2: radio frequency / callsign metadata (e.g. "38.90 Mhz" or
* "Victor 6"). Capped tight in options.
*/
string frequency = 15;
}
/*
* Emergency alert / 911 beacon (CoT types b-a-o-tbl, b-a-o-pan, b-a-o-opn,
* b-a-o-can, b-a-o-c, b-a-g).
*
* Small, high-priority structured record. The CoT type string is still set
* on cot_type_id so receivers that ignore payload_variant can still display
* the alert from the enum alone; the typed fields let modern receivers show
* the authoring unit and handle cancel-referencing without XML parsing.
*/
message EmergencyAlert {
enum Type {
Type_Unspecified = 0;
Type_Alert911 = 1; // b-a-o-tbl
Type_RingTheBell = 2; // b-a-o-pan
Type_InContact = 3; // b-a-o-opn
Type_GeoFenceBreached = 4; // b-a-g
Type_Custom = 5; // b-a-o-c
Type_Cancel = 6; // b-a-o-can
}
/*
* Alert discriminator.
*/
Type type = 1;
/*
* UID of the unit that raised the alert. Often the same as
* TAKPacketV2.uid but can be a parent device uid when a tracker raises
* an alert on behalf of a dismount.
*/
string authoring_uid = 2;
/*
* For Type_Cancel: the uid of the alert being cancelled. Empty for
* non-cancel alert types.
*/
string cancel_reference_uid = 3;
}
/*
* Task / engage request (CoT type t-s).
*
* Mirrors ATAK's TaskCotReceiver / CotTaskBuilder workflow. The envelope
* carries the task's originating uid (implicit requester), position, and
* creation time; the fields below carry structured metadata the raw-detail
* fallback currently loses.
*
* Fields are deliberately lean this variant is closer to the MTU ceiling
* than the others, so every string is capped in options.
*/
message TaskRequest {
enum Priority {
Priority_Unspecified = 0;
Priority_Low = 1;
Priority_Normal = 2;
Priority_High = 3;
Priority_Critical = 4;
}
enum Status {
Status_Unspecified = 0;
Status_Pending = 1; // assigned, not yet acknowledged
Status_Acknowledged = 2; // assignee has seen it
Status_InProgress = 3; // assignee is working it
Status_Completed = 4; // task done
Status_Cancelled = 5; // cancelled before completion
}
/*
* Short tag for the task category (e.g. "engage", "observe", "recon",
* "rescue"). Free text on the wire so ATAK-specific task taxonomies
* don't need proto coordination; capped tight in options.
*/
string task_type = 1;
/*
* UID of the target / map item being tasked.
*/
string target_uid = 2;
/*
* UID of the assigned unit. Empty = unassigned / broadcast task.
*/
string assignee_uid = 3;
Priority priority = 4;
Status status = 5;
/*
* Optional short note (reason, constraints, grid reference). Capped
* tight in options to keep the worst-case under the LoRa MTU.
*/
string note = 6;
}
/*
* ATAK v2 packet with expanded CoT field support and zstd dictionary compression.
* Sent on ATAK_PLUGIN_V2 port. The wire payload is:
@ -1339,5 +1725,17 @@ message TAKPacketV2 {
* Named route with ordered waypoints and control points. See Route.
*/
Route route = 37;
/*
* 9-line MEDEVAC request. See CasevacReport.
*/
CasevacReport casevac = 38;
/*
* Emergency beacon / 911 alert. See EmergencyAlert.
*/
EmergencyAlert emergency = 39;
/*
* Task / engage request. See TaskRequest.
*/
TaskRequest task = 40;
}
}