Cursor on Target — це найменша схема, яка виконує найбільше роботи в сучасному тактичному програмному забезпеченні. Один XML-документ — кілька сотень байтів — несе позицію, ідентичність, достовірність і час життя, і цього документа достатньо, щоб поставити маркер на кожну мапу в mesh-мережі. Він виник як ініціатива MITRE, що дозволяла оператору передавати ціль з однієї системи в іншу буквально жестом курсора, і став спільною мовою екосистеми TAK. Це покроковий розбір формату Cursor on Target поле за полем: модель event, таксономія типів, геометрія point, контейнер detail і реалії його коректної генерації та валідації.

1. модель event у CoT

Кожне повідомлення CoT — це один елемент <event>. Немає ані конверта, ані заголовка, ані окремого реєстру типів повідомлень — кореневий елемент і є повідомленням. Це навмисний вибір дизайну, який робить CoT дешевим: одна рекурсивна схема несе дружнього солдата, ворожу машину, геозону, повідомлення чату, аварійний маяк і трек сенсора, без окремого шляху коду під кожен тип повідомлення на дроті.

Event містить рівно один дочірній елемент <point> (де знаходиться об'єкт) і необов'язковий дочірній <detail> (усе інше про нього). Семантика event повністю визначається його атрибутами плюс відкритим вмістом <detail>. Парсер, який розуміє чотири основні атрибути і point, може відрендерити будь-яке повідомлення CoT на мапі, не розуміючи жодного розширення detail — саме ця властивість плавної деградації пояснює, чому CoT масштабується між постачальниками, які ніколи не узгоджували нічого між собою.

Варто зупинитися на тому, чого в моделі немає. На рівні схеми немає різниці між підрозділом, маркером, повідомленням чату і треком сенсора — усе це events, що відрізняються лише своїм type і дочірніми елементами detail, які вони несуть. Немає підтверджень, немає порядкового номера, немає сесії. CoT працює за принципом fire-and-forget; надійність, упорядкування і доставка віддаються транспорту (TCP, TLS або multicast UDP) та застосунку над ним. Цей мінімалізм — визначальна властивість схеми: вона робить одну річ — каже, де щось знаходиться і що це таке, упродовж обмеженого часу — і відмовляється відрощувати власний стек протоколів.

2. атрибути event

Елемент <event> несе фіксований набір атрибутів. version — версія схеми, майже завжди 2.0. uid — глобально унікальний ідентифікатор об'єкта, який описується, — не повідомлення, а об'єкта. Повторне надсилання оновленої позиції для тієї самої сутності використовує той самий uid; саме так отримувач розуміє, що треба перемістити наявний маркер, а не породити новий. UID — це довільні рядки, але клієнти TAK за домовленістю використовують стабільний ідентифікатор на пристрій (наприклад, ANDROID-serial) для самозвітів.

type — рядок типу MITRE (розділ 3). how описує походження даних — як було отримано позицію. Поширені значення: h-g-i-g-o (людина, отримано з GPS, введено вручну) і m-g (машина, GPS). Поле how — це те, що дозволяє рушію злиття даних зважувати спот-репорт, введений вручну, інакше, ніж живий потік GPS.

Тріада життєвого циклу — це time, start і stale, усі — мітки часу ISO 8601 UTC. time — коли повідомлення було згенеровано. start — коли інформація стає чинною. stale — коли вона спливає. Вікно між start і stale — це час чинності event: після того як stale минув, відповідний стандарту отримувач має вважати event простроченим і прибрати чи приглушити маркер. Самозвіт про позицію від рухомого підрозділу може встановити stale на time + 75 секунд; статична геодезична точка може встановити його на години вперед. Правильно виставити цю тріаду — найпоширеніше джерело «маркерів-привидів»: встановіть stale надто далеко в майбутньому — і мертві треки затримуються; встановіть надто коротко — і живі треки мерехтять.

Ключова думка: у CoT немає явного повідомлення про видалення. Ви виводите трек з обігу, даючи йому застаріти, або надсилаючи одне останнє оновлення, чий час stale уже в минулому. Тож управління станом у мережі CoT — це проблема таймауту, а не проблема транзакції: кожен отримувач незалежно прибирає сміття за власним годинником, тому розбіжність годинників між вузлами — це операційна загроза, а не косметичний дрібниця.

3. ієрархія типів MITRE

Атрибут type кодує, чим є об'єкт, використовуючи крапкову, дефісну таксономію MITRE. Найважливіша родина — це atom-тип з префіксом a-. Atom-тип читається як послідовність розділених дефісами токенів: a-f-G-U-C.

Перший токен після a — належність: f свій, h ворожий, n нейтральний, u невідомий, p очікуваний, плюс варіанти «припущений/підозрюваний». Наступний токен — вимір бою: G наземний, A повітряний, S надводний (морський), U підводний, P космічний, F ССО. Решта токенів деталізують ієрархію символів MIL-STD-2525 — a-f-G-U-C — це свій наземний підрозділ, бойовий, і так далі. Підстановка a-f-G-* означає «свій наземний об'єкт, без подальшої конкретизації», і рендерери відкочуються до найближчого визначеного символу. Не-atom родини використовують інші префікси: b- для bits (дані сенсорів/геометрії, наприклад b-m-p-s-p-i для сенсорної точки інтересу), t- для tasking і y- для відповідей. Геніальність крапкової таксономії в тому, що вона декодується за префіксом: клієнт, який знає лише a-f-G, усе одно може поставити загальну іконку «свій наземний» і плавно деградувати на хвості, який він не розпізнає.

4. елемент point

Елемент <point> обов'язковий і несе п'ять атрибутів, усі обов'язкові. lat і lon — десяткові градуси WGS-84. hae — висота над еліпсоїдом у метрах — зверніть увагу: «над еліпсоїдом», а не над середнім рівнем моря; змішування HAE та ортометричної висоти (зміщення геоїда може перевищувати 30 м) — це класична помилка вертикальної похибки, коли CoT зустрічається із системою, що очікує MSL.

ce — кругова похибка — горизонтальний радіус невизначеності 1-сигма в метрах. le — лінійна похибка — вертикальна невизначеність у метрах. Разом вони дозволяють отримувачу намалювати кільце точності, а не оманливо точну позначку. Сторожове значення 9999999 (часто записується як 9999999.0) означає «невідомо» — це не реальний вимір, це null у схемі. Точка, поставлена вручну без виміряної точності, несе ce="9999999" le="9999999", і логіка злиття даних має окремо обробляти це значення, а не сприймати його як похибку в десять тисяч кілометрів.

Оскільки кожен атрибут обов'язковий, не існує point без висоти або без оцінки похибки — схема змушує продюсера зробити заяву, навіть якщо ця заява — «невідомо». Це тихо вдале дизайнерське рішення: отримувачу ніколи не доводиться вгадувати, чи означає відсутнє поле нуль, невідоме чи замовчування. Він або має реальне число, або має сторожове значення, і ці двоє однозначні. Ціна в тому, що ліниві кодери жорстко зашивають hae="0.0" для всього, що гірше за сторожове значення, бо виглядає як реальний вимір на рівні моря. Якщо ви не знаєте висоти, скажіть про це через 9999999; не стверджуйте нуль.

5. елемент detail

Елемент <detail> — це відкритий контейнер розширень, і саме тут насправді живе екосистема CoT. Схема не накладає жодних обмежень на його дочірні елементи — легальний будь-який коректний XML — і саме це дозволило TAK нашарувати багатий прикладний протокол поверх загального формату ситуаційної обізнаності, не форкаючи його.

Узвичаєні піделементи широко шануються. <contact> несе читабельний для людини callsign і, для TAK, адресацію кінцевих точок для прямого обміну повідомленнями. <track> несе course і speed для рухомих сутностей, перетворюючи статичну точку на вектор. <remarks> — вільний текст. <status> повідомляє про такі речі, як рівень заряду батареї. <__group> (подвійне підкреслення) призначає підрозділу колір і роль команди TAK — Cyan, Team Member — задаючи колір іконки на екрані кожного товариша по команді. <takv> повідомляє версію клієнта TAK, пристрій і платформу. Оскільки detail відкритий, отримувач просто пропускає дочірні елементи, які не розпізнає, і це — уся основа сумісності CoT і TAK між різнорідними клієнтами.

6. CoT проти Link 16 і VMF

CoT займає той самий концептуальний простір, що й J-серія та VMF, але з протилежними дизайнерськими пріоритетами. J-повідомлення Link 16 — це фіксованоформатні бітово-упаковані слова, розмірені під слот TDMA; VMF (MIL-STD-6017) — змінний, але щільно бітово-орієнтований формат для каналів з низькою пропускною здатністю. CoT — це багатослівний XML, побудований для IP-мереж, де байти дешеві, а час розробника — ні.

Відображення CoT на J-повідомлення втрачає дані в обох напрямках. Належність і вимір бою CoT чисто відображаються на поля треку J3.x і на поля ідентичності VMF, а lat/lon/hae перекладаються напряму. Неузгодженість живе в точності та семантиці: якість треку J-серії — це дискретне перелічуване значення, тоді як ce/le у CoT — неперервні метри; відкритий <detail> CoT не має фіксованоформатного аналога і повністю відкидається на шлюзі. Навпаки, поля J-серії на кшталт специфічних режимів IFF чи мережевої участі, отриманої з PPLI, не мають рідного слота в CoT і мають контрабандою перевозитися у власних розширеннях detail. Тож шлюзи, що з'єднують CoT і тактичні канали даних, несуть упереджену, вручну підтримувану карту полів — та сама проблема «перекладача з власною думкою», яка з'являється всюди в C2 НАТО.

7. потокова передача і TAK

У продакшені CoT — це потік, а не документ. Сервер TAK мультиплексує events CoT між клієнтами: самозвіт про позицію підрозділу йде вгору постійним з'єднанням TCP (часто TLS) із налаштовуваною частотою — зазвичай кожні 1–10 секунд залежно від руху та налаштування «динамічної звітності» — і сервер розгалужує його до підписників, за бажанням фільтруючи за місією, групою чи геозоною. Mesh SA, безсерверний режим, мультикастить ті самі events через UDP у локальній мережі, тож відділення працює без жодної інфраструктури.

Частота повідомлень визначає інженерію. Вправа на 200 вузлів, де кожен звітує кожні 2 секунди — це 100 events/секунду лише самопозиціонування, ще до треків сенсорів. Сервер не підтримує протоколу видалення для жодного з них; натомість кожен клієнт незалежно прибирає сміття за мітками stale, які він бачив. Прибирання сміття, кероване stale, елегантне — без лідера, без консенсусу — але це означає, що клієнт, який втрачає зв'язок, спостерігатиме, як уся його картина старіє і за розкладом зникає, що зазвичай є коректною поведінкою, а інколи — неприємним сюрпризом під час блекауту зв'язку.

8. валідація і генерація CoT

Дротовий формат поблажливий, через що легко видавати непомітно зламаний CoT. Валідуйте проти опублікованої схеми Event.xsd під час розробки, але знайте її межі: XSD перевіряє, що point існує і що атрибути життєвого циклу присутні та правильно типізовані, але вона не скаже вам, що ваш stale раніше за ваш start, що ваш токен type безглуздий, або що ваш hae — це висота над геоїдом, яка маскується під висоту над еліпсоїдом.

Повторювані помилки сформованих повідомлень передбачувані. Мітки часу без завершального Z або зі зміщеннями локального поясу — час CoT — це UTC, крапка, і пропущений Z відправляє маркери в минуле чи майбутнє. Інвертовані часи життя, де stale передує start, породжують events, мертві при надходженні. Повторне використання одного uid для різних сутностей, через що два реальні треки злипаються в один мерехтливий маркер. Видача реалістичного на вигляд ce замість сторожового 9999999 для невиміряної точки, що обманює злиття даних, змушуючи довіряти сміттю. Коли ви будуєте кодер CoT, зробіть тріаду життєвого циклу повноцінним типом, який забезпечує start ≤ stale і рендерить UTC із Z, генеруйте UID зі стабільного ключа сутності, а не з лічильника на повідомлення, і явно видавайте сторожове значення «невідомо». Виставте ці чотири інваріанти правильно — і ваш CoT взаємодіятиме з клієнтами, яких ви ніколи не бачили — а це і є вся суть формату.