diff --git a/tasks/flightradar24/docs/STEP1_EXTERNAL_DATA.md b/tasks/flightradar24/docs/STEP1_EXTERNAL_DATA.md new file mode 100644 index 0000000..51ebacd --- /dev/null +++ b/tasks/flightradar24/docs/STEP1_EXTERNAL_DATA.md @@ -0,0 +1,120 @@ +# Шаг 1: Внешние источники данных — FR24 API + онлайн табло + +## Статус +🔲 Не начат + +## Цель +Развернуть отдельный контейнер для сбора данных из внешних источников: +1. **FR24 API** — исторические и live треки (как в прототипе noisemap) +2. **Онлайн табло** — расписание рейсов по аэропортам Москвы (SVO, DME, VKO, ZIA) + +Данные сохранять в PostgreSQL в отдельной схеме `fr24_ext` — не пересекаться со схемой `fr24` (RTL-SDR ingest). + +--- + +## Бизнес-требования + +### BR-1: Сбор данных FR24 API +- Загружать треки рейсов над Московской областью через FR24 API +- Покрытие: bbox ~54.5–57.0°N, 35.5–40.5°E (Московская область) +- Исторические данные: последние 7 дней (при наличии кредитов) +- Live данные: обновление каждые 5 минут +- Хранить: icao24, callsign, координаты трека, высота, скорость, время + +### BR-2: Сбор данных онлайн табло +- Аэропорты: SVO (Шереметьево), DME (Домодедово), VKO (Внуково), ZIA (Жуковский) +- Данные: номер рейса, авиакомпания, направление, время вылета/прилёта, статус +- Источник: Яндекс.Расписания API или открытые табло аэропортов +- Обновление: каждые 15 минут +- Хранить историю за 30 дней + +### BR-3: Хранение +- Схема `fr24_ext` в существующей PostgreSQL БД +- Не влиять на схему `fr24` (RTL-SDR данные) +- Retention: треки FR24 — 30 дней, табло — 30 дней + +--- + +## Технические требования + +### Контейнер `fr24-external` +- Python 3.11-slim +- Отдельный сервис в docker-compose.yml +- Переменные окружения: FR24_API_KEY, YANDEX_RASP_API_KEY +- Два независимых воркера: fr24_worker и rasp_worker +- Логирование в /var/log/fr24/external.log + +### Схема БД `fr24_ext` +```sql +-- Рейсы из FR24 API +fr24_ext.flights_ext ( + flight_ext_id, source, fr24_id, icao24, callsign, + origin_iata, destination_iata, aircraft_type, + fetched_at, flight_date +) + +-- Треки из FR24 API +fr24_ext.track_points_ext ( + point_id, flight_ext_id, observed_at, + lat, lon, altitude_ft, speed_kt, heading_deg +) + +-- Табло аэропортов +fr24_ext.schedule ( + schedule_id, airport_iata, direction, + flight_number, airline_iata, aircraft_type, + scheduled_at, estimated_at, actual_at, + status, fetched_at +) +``` + +--- + +## ТЗ для Dev-агента + +### Файлы для создания +``` +tasks/flightradar24/ingest/external/ + Dockerfile + main.py # точка входа, запускает оба воркера + fr24_worker.py # загрузка из FR24 API + rasp_worker.py # загрузка из Яндекс.Расписания + requirements.txt +tasks/flightradar24/db/init/003_schema_ext.sql # DDL схемы fr24_ext +``` + +### Обновить +- `tasks/flightradar24/compose/docker-compose.yml` — добавить сервис `external` + +--- + +## Тест-кейсы + +### TC-1: FR24 API подключение +- [ ] Контейнер стартует без ошибок +- [ ] FR24 API возвращает данные для bbox Москвы +- [ ] Треки сохраняются в `fr24_ext.track_points_ext` + +### TC-2: Табло аэропортов +- [ ] Данные по SVO загружаются корректно +- [ ] Статусы рейсов обновляются при повторном запросе +- [ ] Дубликаты не создаются (upsert по flight_number + scheduled_at) + +### TC-3: Изоляция схем +- [ ] Запросы к `fr24_ext` не влияют на `fr24` +- [ ] При падении external контейнера остальные работают + +### TC-4: Retention +- [ ] Данные старше 30 дней удаляются автоматически + +--- + +## Зависимости +- Существующая PostgreSQL (fr24-postgres) +- FR24_API_KEY в ~/.openclaw/.env +- YANDEX_RASP_API_KEY в ~/.openclaw/.env (или альтернативный источник табло) + +## Оценка объёма +- ~500 рейсов/день над Москвой из FR24 +- ~800 записей/день в табло (4 аэропорта × ~200 рейсов) +- Объём БД: ~50 MB/месяц diff --git a/tasks/flightradar24/docs/STEP2_DATA_MART.md b/tasks/flightradar24/docs/STEP2_DATA_MART.md new file mode 100644 index 0000000..2c643cb --- /dev/null +++ b/tasks/flightradar24/docs/STEP2_DATA_MART.md @@ -0,0 +1,137 @@ +# Шаг 2: Витрина данных — объединение FR24 API + табло + RTL-SDR + +## Статус +🔲 Не начат (зависит от Шага 1) + +## Цель +Спроектировать и реализовать витрину данных (data mart) которая объединяет три источника: +1. **FR24 API** — треки и рейсы из внешнего API (схема `fr24_ext`) +2. **Онлайн табло** — расписание и статусы рейсов (схема `fr24_ext`) +3. **RTL-SDR dongle** — локально принятые ADS-B треки (схема `fr24`) + +Витрина — это набор материализованных представлений и таблиц в схеме `fr24_mart`, которые склеивают данные из всех источников в единую модель для визуализации и анализа. + +--- + +## Бизнес-требования + +### BR-1: Единая модель рейса +- Рейс идентифицируется по callsign + дата +- Один рейс может иметь данные из нескольких источников одновременно +- Приоритет данных: RTL-SDR (наиболее точный) > FR24 API > табло +- Витрина должна показывать из какого источника взяты данные + +### BR-2: Обогащение данных +- К треку из RTL-SDR добавлять данные из табло (авиакомпания, маршрут, тип ВС) +- К треку из FR24 API добавлять данные из табло (статус, фактическое время) +- Если рейс есть в табло но нет трека — показывать как "нет данных о треке" + +### BR-3: Покрытие источников +- Метрика: % рейсов из табло для которых есть трек (RTL-SDR или FR24) +- Метрика: % рейсов с треком из RTL-SDR vs только FR24 +- Метрика: среднее качество трека (кол-во точек, покрытие маршрута) + +### BR-4: Шумовая модель +- Витрина должна содержать поле `noise_score` для каждой точки трека +- Расчёт: на основе высоты, скорости, типа ВС (упрощённая модель из прототипа) +- Агрегация: суммарный шум по сетке 0.01° × 0.01° за период + +--- + +## Технические требования + +### Схема `fr24_mart` + +```sql +-- Единая таблица рейсов (объединение источников) +fr24_mart.flights_unified ( + unified_id, callsign, flight_date, + origin_iata, destination_iata, airline_iata, aircraft_type, + scheduled_dep, actual_dep, status, + has_rtlsdr_track BOOL, has_fr24_track BOOL, + rtlsdr_points INT, fr24_points INT, + source_priority TEXT, -- 'rtlsdr' | 'fr24' | 'schedule_only' + updated_at +) + +-- Единые точки трека (лучший доступный источник) +fr24_mart.track_points_unified ( + point_id, unified_id, observed_at, + lat, lon, altitude_m, speed_kt, heading_deg, + source TEXT, -- 'rtlsdr' | 'fr24' + noise_score FLOAT +) + +-- Шумовая сетка (агрегат) +fr24_mart.noise_grid ( + grid_id, grid_lat FLOAT, grid_lon FLOAT, + period_date DATE, + flight_count INT, total_noise_score FLOAT, + avg_altitude_m FLOAT, + updated_at +) + +-- Покрытие источников (метрики) +fr24_mart.source_coverage ( + coverage_date DATE, + total_schedule INT, + with_rtlsdr INT, with_fr24 INT, schedule_only INT, + rtlsdr_pct FLOAT, fr24_pct FLOAT +) +``` + +### Обновление витрины +- Отдельный контейнер `fr24-mart` или cron внутри существующего +- Обновление каждые 10 минут +- Инкрементальное (только новые данные) + +--- + +## ТЗ для Dev-агента + +### Файлы для создания +``` +tasks/flightradar24/ingest/mart/ + Dockerfile + main.py # планировщик обновления витрины + build_unified.py # логика объединения источников + noise_model.py # расчёт noise_score (перенос из прототипа) + requirements.txt +tasks/flightradar24/db/init/004_schema_mart.sql # DDL схемы fr24_mart +``` + +### Обновить +- `tasks/flightradar24/compose/docker-compose.yml` — добавить сервис `mart` + +--- + +## Тест-кейсы + +### TC-1: Объединение источников +- [ ] Рейс с треком из RTL-SDR и записью в табло — объединяется корректно +- [ ] Рейс только в табло — создаётся запись с `source_priority = 'schedule_only'` +- [ ] Рейс только в RTL-SDR (нет в табло) — создаётся с `source_priority = 'rtlsdr'` + +### TC-2: Приоритет источников +- [ ] При наличии RTL-SDR трека — используется он, не FR24 +- [ ] При отсутствии RTL-SDR — используется FR24 + +### TC-3: Шумовая модель +- [ ] noise_score рассчитывается для каждой точки трека +- [ ] noise_grid обновляется после добавления новых точек +- [ ] Агрегация по сетке 0.01° корректна + +### TC-4: Метрики покрытия +- [ ] source_coverage обновляется ежедневно +- [ ] % покрытия считается корректно + +### TC-5: Производительность +- [ ] Обновление витрины за 10 минут занимает < 60 сек +- [ ] Запрос noise_grid за 1 день < 500 мс + +--- + +## Зависимости +- Шаг 1 (схема fr24_ext должна быть заполнена) +- Схема fr24 (RTL-SDR данные) +- Модель шума из прототипа (tasks/flightradar24/prototype/docs/NOISE_MODEL.md)