Дані розвідки, спостереження та рекогносцирування надходять на командний пункт одночасно з десятків напрямків. Телеметрія UAV надходить через виділений радіоканал. Сенсори радіоелектронної боротьби передають перехоплені події через зашифрований TCP-потік. Артилерійські спостерігачі фіксують координати сітки голосом або цифровими повідомленнями. SIGINT-платформи виробляють збагачені звіти про об'єкти з нерівномірною частотою. Кожне з цих джерел має свій формат, свою частоту оновлення та свій профіль надійності. Проблема полягає не в отриманні даних — а в тому, щоб осмислити їх вчасно для прийняття рішень.

Corvus.Head — це оперативний розвідувальний дашборд Corvus Intelligence, призначений для консолідації саме такого роду багатоджерельних бойових даних в єдиний структурований інтерфейс для військового керівництва, розвідувальних груп та оперативних планувальників. Ця стаття є технічним описом архітектури системи: конвеєр прийому, що нормалізує різнорідні потоки; інтеграція PowerBI, що забезпечує аналітичну візуалізацію; геопросторовий рушій для рендерингу теплових карт і гарячих точок; шар прогнозування трендів; і топологія хостингу Azure, що утримує затримку в межах оперативних допусків.

Рівень прийому даних: нормалізація різнорідних потоків сенсорів

Перше архітектурне рішення в будь-якій багатоджерельній ISR-системі — як поглинути різноманіття форматів вхідних даних, не дозволяючи цьому різноманіттю поширюватися на рівні обробки та візуалізації. Corvus.Head використовує патерн адаптерів джерел: кожен тип сенсора або потоку отримує виділений адаптерний сервіс, єдина відповідальність якого — підключитися до джерела, розібрати його нативний формат і публікувати нормалізовані канонічні події на внутрішню шину повідомлень.

Канонічна схема подій навмисно мінімальна. Кожна подія містить: унікальний ідентифікатор об'єкта, тег типу джерела, широту та довготу в десяткових градусах WGS-84, висоту в метрах над середнім рівнем моря (null, якщо джерело не повідомляє висоту), курс і швидкість де доступні, мітку класифікації (свій, ворожий, невідомий, нейтральний, на розгляді), мітку часу UTC на місці виникнення події, та вільний об'єкт метаданих для специфічних полів джерела, що не відповідають основній схемі. Поля, які джерело не може надати, встановлюються як null, а не оцінюються — фабрикація даних на рівні нормалізації є більш небезпечною, ніж обробка null-значень на наступних рівнях.

Адаптери підключаються до своїх джерел через TCP-сокети, MQTT-підписки, цикли REST-опитування або спостерігачі за файловими папками залежно від того, що підтримує кожне джерело. Збій підключення обробляється всередині адаптера з експоненційним відкладом; несправний адаптер ніколи не блокує інші адаптери або шину повідомлень. Кожен адаптер публікує у свій власний іменований топік на шині, щоб споживачі нижче за потоком могли вибірково підписуватися за типом джерела. Технологія шини — Apache Kafka на Azure Event Hubs: семантика груп споживачів Kafka дозволяє рушієві злиття, конвеєру аналітики та геопросторовому рушієві кожному незалежно споживати один і той самий потік без координації.

Ключова думка: Нормалізація повинна відбуватися на межі адаптера — не в рушії злиття, не на рівні візуалізації. Кожен наступний рівень вважає, що отримує чисті, типізовані, схемно-валідні події. Порушення цього контракту спричиняє мовчазну деградацію якості даних, яку вкрай важко діагностувати в продакшні.

Інтеграція PowerBI: чому її обрали для оборонних дашбордів

Рівень аналітичної візуалізації Corvus.Head — графіки, лінії трендів, порівняння за періодами та розбивки за доменами — побудований на Microsoft PowerBI Embedded, що працює на Azure. Вибір PowerBI замість власного стека графіків є обдуманим і заслуговує пояснення, оскільки він суперечить інтуїції інженерів, які асоціюють PowerBI з бізнес-аналітикою, а не з оборонними застосунками.

Практичний аргумент зводиться до трьох можливостей. По-перше, рушій DAX PowerBI надає зрілий, добре протестований рівень обчислень для розрахункових метрик: частоти подій на комірку сітки на годину, оцінки надійності джерела, зміни у відсотках від одного до іншого, та ковзні середні. Відтворення семантики обчислень рівня DAX у власному стеку графіків на JavaScript — це кількарічна інженерна робота, що відволікає ресурси від інтеграції сенсорів, яка насправді диференціює платформу.

По-друге, PowerBI Embedded підтримує режим DirectQuery проти Azure Synapse Analytics, що означає, що дашборд може запитувати попередньо агреговані аналітичні таблиці без завантаження необроблених даних подій у браузер. Це утримує час відгуку запитів нижче 1,5 секунди для 90-денних аналітичних вікон на мільйонах подій — продуктивність, для досягнення якої власним підходом знадобилися б значні інфраструктурні інвестиції.

По-третє, версіонування моделі даних PowerBI та шлях оновлення звітів зрозумілі менеджерам оборонних програм, яким необхідно підтримувати аналітичні звіти протягом багаторічних контрактів. Визначення звіту PowerBI (.pbix) стає артефактом під контролем версій, який можна оновлювати, переглядати та затверджувати без повторного розгортання базового програмного забезпечення платформи.

Архітектура інтеграції використовує PowerBI Embedded JavaScript SDK для рендерингу звітів всередині iframe у оболонці Corvus.Head. Фільтри безпеки на рівні рядків застосовуються під час вбудовування з використанням атрибутів допуску користувача з токену сесії, що гарантує: звіти PowerBI показують лише ті дані, які має право бачити запитуючий користувач, — навіть якщо набір даних PowerBI містить повний корпус.

Ключова думка: Режим PowerBI DirectQuery усуває необхідність окремої бази даних для звітності або конвеєру попереднього обчислення для більшості аналітичних запитів. Компроміс полягає в тому, що звіти DirectQuery не можуть кешуватися на рівні браузера — кожна зміна фільтра ініціює живий запит Synapse. Спланіруйте стратегію партиціонування таблиць Synapse до першого звіту, а не після.

Геопросторовий рушій: теплові карти, гарячі точки та щільність подій

Геопросторовий рівень відображення слугує іншій меті, ніж аналітичні графіки. Тоді як PowerBI показує агреговані закономірності з часом, картографічний рівень показує, де речі відбуваються прямо зараз і де активність концентрувалася протягом останнього чергування. Corvus.Head відображає три типи геопросторових накладок поверх базового картографічного шару: треки позицій об'єктів (оновлення через WebSocket push), теплові карти щільності подій та дискретні маркери гарячих точок.

Теплові карти щільності подій обчислюються на стороні сервера за допомогою просторового хеш-масиву з конфігурованим розміром комірки (за замовчуванням 500 метрів). Кожна подія, що надходить через конвеєр прийому, збільшує показник щільності комірки, що містить її місцезнаходження, зважений на функцію загасання актуальності — події старші шести годин вносять експоненційно менший внесок у оцінку комірки. Загасання запобігає постійному зміщенню теплової карти через минулу активність та гарантує, що візуалізація відображає поточну оперативну картину, а не кумулятивну історичну.

Сітка теплової карти перераховується за конфігурованим розкладом (за замовчуванням кожні 60 секунд) і надсилається клієнтам як GeoJSON FeatureCollection багатокутників комірок із атрибутами щільності. Браузер рендерить це за допомогою WebGL-шару карти з п'ятиточковою кольоровою шкалою від темно-синього (низька щільність) через бурштиновий до червоного (висока щільність). Оператори можуть застосовувати доменні фільтри — показувати лише EW-події або лише спостереження UAV — що ініціює перерахунок сітки на стороні сервера, відфільтрований за вибраними типами джерел. Це дозволяє уникнути повного браузерного перерендерингу базової геометрії карти.

Маркери гарячих точок — це дискретні точки, що автоматично генеруються, коли кластер подій в одній комірці сітки перевищує конфігурований поріг у ковзному часовому вікні. Детектор гарячих точок працює як окремий мікросервіс, що підписується на канонічну шину подій і оцінює DBSCAN-подібний алгоритм кластеризації в ковзному 30-хвилинному вікні подій. Коли кластер перетинає поріг, запис гарячої точки записується до бази даних і транслюється підключеним клієнтам дашборду через WebSocket push-канал. Гарячі точки автоматично застарівають, коли активність кластера падає нижче порогу протягом тривалого часу.

Прогнозування трендів: щоденні, тижневі та місячні періоди

Прогнозування трендів дає командирам кількісну основу для передбачення оперативного темпу, а не реагування на нього. Corvus.Head відображає прогнози активності подій за трьома періодами — щоденними, тижневими та місячними — обчисленими за допомогою моделі сезонного розкладання, застосованої до часових рядів даних за кожною коміркою.

Конвеєр прогнозування запускається на Azure Databricks за розкладом (щогодини для щоденних прогнозів, щоночі для тижневих і місячних). Він отримує дані за останні 90 днів кількості подій, агрегованих за коміркою сітки та часовим відрізком з Azure Synapse, застосовує STL-розкладання (Seasonal-Trend decomposition using LOESS) для виділення сезонних та трендових компонентів, і генерує прогнози з довірчими інтервалами, похідними від дисперсії залишків. Результати записуються назад у Synapse як попередньо обчислені стовпці прогнозу, які PowerBI може запитувати через DirectQuery без виконання розкладання в реальному часі.

Вибір попереднього обчислення замість обчислення на вимогу є обдуманим. STL-розкладання за 90 днів даних по тисячах комірок сітки є обчислювально дорогим — виконання його на вимогу у відповідь на запит дашборду призвело б до неприйнятної затримки. Попереднє обчислення переносить витрати на заплановану пакетну задачу та утримує час відгуку запитів дашборду нижче 1,5 секунди для будь-якого прогнозного запиту від користувача.

Архітектура фільтрації: деталізація за доменом та часовим діапазоном

Дашборд, що показує все, є оперативно таким самим марним, як і дашборд, що не показує нічого. Архітектура фільтрації визначає, чи можуть командири швидко виокремити сигнал, релевантний для поточного рішення, з оточуючого шуму повної багатоджерельної картини.

Corvus.Head реалізує фільтрацію за двома осями: домен (тип джерела або класифікація об'єкта) та часовий діапазон (остання година, останні 6 годин, останні 24 години, останні 7 днів або власний діапазон). Фільтри застосовуються на трьох рівнях: рівень API-запиту (який отримує лише відповідні події з Synapse), рівень підписки на шину повідомлень (який підписується лише на топіки відповідних типів джерел для живого WebSocket-потоку) та рівень звіту PowerBI (який застосовує контекст фільтра DAX до всіх заходів). Цей трирівневий підхід гарантує, що зміни фільтрів відображаються узгоджено на всіх візуальних компонентах без браузерного постобробки повного набору даних.

Стан фільтра підтримується в оболонці дашборду як об'єкт стану, що серіалізується в URL, що дозволяє командирам зберігати та ділитися конкретними відфільтрованими представленнями зі своїм персоналом. Офіцер бригадної розвідки може надіслати конкретне відфільтроване представлення — EW-події, останні 6 годин, північний сектор — підлеглим як URL, і отримувачі побачать ідентичне відфільтроване представлення, коли відкриють посилання.

Ключова думка: Застосовуйте фільтри на рівні отримання даних, а не на рівні відображення. Отримання всіх подій і фільтрація в JavaScript дає неправильні результати, коли обсяги даних перевищують ліміти пам'яті браузера, і відкриває дані користувачам, які не мають права їх бачити, навіть якщо інтерфейс їх не відображає.

Топологія хостингу Azure та міркування щодо затримки

Corvus.Head розміщений на Azure Government Cloud (Azure for Government у США, еквівалентні суверенні хмарні регіони для країн-партнерів). Топологія хостингу спроектована навколо трьох бюджетів затримки: майже реального часу для оновлень позицій об'єктів (ціль: менше 3 секунд наскрізно), відгуку на аналітичний запит (ціль: менше 1,5 секунди для попередньо агрегованих запитів) та доставки картографічних тайлів (ціль: менше 500 мс для кешованих тайлів).

Адаптери прийому та шина повідомлень (Azure Event Hubs у режимі сумісності з Kafka) працюють в тому ж регіоні Azure, що й класифіковані джерела даних, мінімізуючи мережевий перехід між сенсорними системами та рівнем нормалізації. Рушій злиття та WebSocket-шлюз розгорнуті як робочі навантаження Azure Kubernetes Service в тому ж регіоні. Ємність PowerBI Embedded та робочий простір Azure Synapse Analytics виділяються в тому ж регіоні, щоб уникнути затримки міжрегіональної передачі даних при викликах DirectQuery.

Доставка картографічних тайлів використовує Azure Blob Storage з прискоренням Azure CDN для некласифікованих тайлів базового шару. Класифіковані тайли накладок — шари анотацій розвідки, накладки диспозиції дружніх сил — обслуговуються з виділеного тайлового сервера всередині захищеного периметра, що не використовує CDN. Цільовий час відгуку тайлового сервера контролюється монітором стану, який оповіщає операційну команду, якщо p95 доставки тайлів перевищує 800 мс.

Для конфігурацій передового розгортання, де підключення до Azure недоступне або ненадійне, Corvus.Head підтримує контейнеризований режим розгортання на одному сервері за допомогою Docker Compose. У цьому режимі повний стек — адаптери прийому, рушій злиття, тайловий сервер, локальний брокер Kafka та база даних PostgreSQL замість Synapse — працює на захищеному сервері всередині тактичної мережі. PowerBI замінюється легким аналітичним рушієм із готовими специфікаціями графіків Vega-Lite, що підкріплені локальним REST API. Профіль затримки в цьому режимі суттєво змінюється: без керованих сервісів Azure, операційна команда відповідає за моніторинг і масштабування локальної інфраструктури, і деякі аналітичні функції з 90-денною історичною глибиною скорочуються до 30-денного локального кешу.

Покрокова інструкція: інтеграція нового джерела даних у Corvus.Head

Архітектура адаптерів робить підключення нових типів сенсорів повторюваним інженерним процесом, а не унікальним інтеграційним проектом щоразу. Наступні кроки описують стандартний шлях інтеграції.

Крок 1 — Визначити схему джерела та частоту оновлення. Задокументувати формат даних (CoT XML, JSON, двійковий протокол), очікувану частоту оновлення в повідомленнях на секунду, та авторитетні назви полів для позиції, часу, типу об'єкта та класифікації. Це визначення схеми стає контрактом для адаптера.

Крок 2 — Реалізувати адаптер прийому даних. Написати адаптер, специфічний для джерела, який підключається до потоку та публікує нормалізовані канонічні події на шину повідомлень. Адаптер обробляє повторні підключення, повторне складання часткових повідомлень та автентифікацію, специфічну для джерела. Він ніколи не повинен блокувати шину при збої підключення.

Крок 3 — Зіставити поля з канонічною схемою подій. Перетворити кожне вхідне повідомлення у канонічний формат події Corvus.Head. Поля, що не мають відповідності, відкидаються на рівні адаптера. Поля, які джерело не може надати, встановлюються як null, а не вигадуються.

Крок 4 — Налаштувати правила асоціації рушія злиття. Додати новий тип джерела до таблиці правил асоціації рушія злиття. Вказати поріг просторової близькості та часове вікно для асоціації звітів із цього джерела з існуючими треками, і встановити вагу точності джерела для оцінювача позиції.

Крок 5 — Зареєструвати джерело в моделі даних PowerBI. Додати новий тип джерела як значення виміру в таблиці SourceType. Перевірити, що існуючі зрізи та заходи DAX обробляють нове значення без порушення існуючих звітів.

Крок 6 — Перевірити затримку та пропускну здатність на staging-стенді. Запустити адаптер на відтворенні історичних даних джерела зі швидкістю 2x від реального часу. Виміряти наскрізну затримку від отримання повідомлення до відображення на дашборді. Підтвердити, що затримка p99 не перевищує 3 секунди, а глибина черги шини повідомлень не зростає необмежено під час тривалого навантаження.

Крок 7 — Увімкнути та моніторити в продакшні. Розгорнути адаптер з керуванням через feature-flag, щоб його можна було вимкнути без відкату у разі виникнення проблем. Відстежувати чергу мертвих листів, частоту подій за джерелом та швидкість асоціації треків і звітів рушія злиття. Падіння швидкості асоціації нижче 80% зазвичай свідчить про невідповідність схеми, спричинену оновленням мікропрограми джерела.

Часті запитання

+Чому Corvus.Head використовує PowerBI, а не власну бібліотеку графіків?

PowerBI на Azure надає корпоративне моделювання даних, розраховані заходи на основі DAX та зрілий шлях DirectQuery, що дозволяє використовувати візуалізацію майже в реальному часі без попередньої агрегації даних у окрему звітну базу даних. Побудова рівноцінних можливостей за допомогою власної бібліотеки графіків потребувала б відтворення рушія DAX, системи версіонування моделі даних та інфраструктури експорту/вбудовування — це кількарічна інженерна робота, яка відволікає ресурси від критично важливої для місії роботи з інтеграцією сенсорів.

+Як Corvus.Head обробляє дані з джерел з різними частотами оновлення?

Кожен тип джерела має зареєстровану частоту оновлення на рівні прийому даних. Повільні джерела (SIGINT, логістика) надсилаються до окремого топіку з довшим вікном зберігання. Швидкі джерела (телеметрія UAV, радар) обробляються через пріоритетний шлях шини повідомлень. Рушій злиття підтримує мітку застарілості на кожне джерело для кожного треку та позначає треки як деградовані, коли джерело не надавало звітів протягом 2x від очікуваної частоти.

+Яка наскрізна затримка для появи події сенсора на дашборді?

За нормальних мережевих умов у розгортанні на Azure типова наскрізна затримка від отримання повідомлення сенсора до оновлення пікселя на дашборді становить менше 2 секунд. Розбивка: нормалізація адаптера (50–150 мс), транзит шиною повідомлень (менше 50 мс), обробка рушієм злиття (100–300 мс), оновлення PowerBI DirectQuery (500–1200 мс) та рендеринг браузера (менше 100 мс). Геопросторовий картографічний шар оновлюється швидше — зміни позиції треку через WebSocket push-шар з'являються протягом 300–500 мс незалежно від циклу оновлення PowerBI.

+Як генеруються теплові карти з багатоджерельних даних подій?

Геопросторовий рушій агрегує події в конфігурований сітчастий масив (за замовчуванням комірки 500 м) за допомогою просторового хешу. Кожна комірка накопичує зважений показник щільності подій: події зважуються за актуальністю (експоненційне загасання з напівперіодом 6 годин) та надійністю джерела. Сітка щільності рендериться як WebGL шар теплової карти з конфігурованою кольоровою шкалою. Доменні фільтри (лише EW або лише UAV) перераховують сітку на стороні сервера та надсилають оновлений тайл клієнту — уникаючи повного перерендерингу базової карти.

+Як працює рушій прогнозування трендів для щоденних, тижневих та місячних періодів?

Рушій прогнозування застосовує модель сезонного розкладання (STL — Seasonal-Trend decomposition using LOESS) до часових рядів кількості подій, агрегованих за коміркою сітки. Добові, тижневі та місячні компоненти сезонності виділяються пакетною задачею Azure Databricks. Довірчі інтервали прогнозу обчислюються з дисперсії залишків. Результати попередньо обчислюються як стовпці в Azure Synapse, щоб модель PowerBI могла запитувати їх через DirectQuery без виконання розкладання в реальному часі — зберігаючи час відгуку нижче 1,5 секунди навіть для горизонтів прогнозу на 90 днів.