Files
wiki/tasks/flightradar24/docs/SYSTEM_OVERVIEW.md
2026-04-26 16:20:01 +03:00

291 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FR24 Noisemap — Полное описание системы
> Актуально на: 2026-04-26
## Назначение проекта
Система сбора, хранения и визуализации данных о воздушном движении над московскими аэропортами (SVO, DME, VKO, ZIA) для построения **карты шумового загрязнения** от авиации.
---
## Инфраструктура
**VM:** `fr24@192.168.2.67` (VM-FR24 в домашней сети, доступ через jump-host vpn-srv)
**Доступ:** `ssh -i ha_ssh_key -J vpn@185.130.212.192:3322 fr24@192.168.2.67`
**Docker Compose:** `/home/fr24/projects/fr24/compose/docker-compose.yml`
---
## Контейнеры (10 шт.)
### Слой хранения
| Контейнер | Порт | Назначение |
|---|---|---|
| `fr24-postgres` | 5432 | PostgreSQL 15 + PostGIS. Единая БД `fr24` со схемами: `fr24`, `fr24_ext`, `fr24_mart` |
| `fr24-backup` | — | Ежедневный pg_dump в `/backup/` |
### Слой сбора RTL-SDR
| Контейнер | Порт | Назначение |
|---|---|---|
| `fr24-capture` | — | Читает ADS-B поток с dump1090 (SBS port 30003). Пишет сырые пакеты в `fr24.raw_packets`. Retention 3 дня. |
| `fr24-preprocess` | — | Читает `fr24.raw_packets`, строит нормализованные `fr24.flights`, `fr24.tracks`, `fr24.track_points`. Поддерживает recovery после сбоя. **M4-фильтр выбросов координат** (26.04.2026). |
### Слой внешних треков
| Контейнер | Порт | Назначение |
|---|---|---|
| `fr24-tracks-fr24` | 8001 | Загрузка треков из FR24 API (AeroAPI). `POST /run?date=YYYY-MM-DD` — вручную. Пишет в `fr24_ext.flight_tracks_fr24` + `fr24_ext.track_points_fr24`. Стоимость: ~40 кредитов/рейс. |
| `fr24-tracks-fa` | 8002 | Загрузка треков из FlightAware AeroAPI. `POST /run?date=YYYY-MM-DD` — вручную. Пишет в `fr24_ext.flight_tracks_fa` + `fr24_ext.track_points_fa`. Стоимость: $0.01/запрос. |
### Слой расписания и витрины
| Контейнер | Порт | Назначение |
|---|---|---|
| `fr24-schedule` | 8000 | Загрузка расписания из Яндекс Расписаний API. Запускается по cron T-1. Пишет в `fr24_ext.schedule`. Rate limit: ~100 запросов/час. |
| `fr24-mart` | 8003 | ETL-витрина. Объединяет расписание + треки из всех источников. Запускается по расписанию каждый час (T-1) и вручную `POST /run?date=YYYY-MM-DD`. Пишет в `fr24_mart.*`. |
### Слой отдачи данных и мониторинга
| Контейнер | Порт | Назначение |
|---|---|---|
| `fr24-api` | 8080 | REST API для фронтенда. Читает из `fr24`, `fr24_ext`, `fr24_mart`. Эндпоинты: расписание, мониторинг, data-sources. |
| `fr24-monitoring` | — | Мониторинг системы. Раз в минуту логирует: disk%, db_size, capture_lag, throughput, unprocessed. Алерты при деградации. |
---
## Схема базы данных
### Схема `fr24` — RTL-SDR данные (real-time)
```
fr24.raw_packets — сырые SBS-пакеты от dump1090
fr24.aircraft — реестр воздушных судов (icao24, callsign, reg)
fr24.flights — рейсы (callsign, started_at, ended_at)
fr24.tracks — треки рейсов
fr24.track_points — точки трека (lat, lon, altitude_m, speed, heading)
fr24.processing_state — курсор обработки (для recovery)
fr24.noise_results — результаты расчёта шума (устаревшее, мигрировано в mart)
```
### Схема `fr24_ext` — внешние источники
```
fr24_ext.schedule — расписание (Яндекс). ~1400 рейсов/день на 4 аэропорта.
Ключевые поля: schedule_id, flight_date, airport_iata,
direction, flight_number, origin_iata, destination_iata,
scheduled_at, thread_title (маршрут из Яндекса)
fr24_ext.flight_tracks_fr24 — заголовки треков FR24 API
fr24_ext.track_points_fr24 — точки треков FR24 (altitude_ft, gspeed_kt)
fr24_ext.flight_tracks_fa — заголовки треков FlightAware
fr24_ext.track_points_fa — точки треков FA (altitude_ft, gspeed_kt)
fr24_ext.load_state — состояние загрузок (для идемпотентности)
```
### Схема `fr24_mart` — финальная витрина
```
fr24_mart.flights — объединённые рейсы. Один рейс = одна строка.
Флаги: has_rtlsdr, has_fr24, has_fa
track_source: 'rtlsdr' | 'fr24' | 'fa' | null
Ссылки: fr24_track_id, fa_track_id, rtlsdr_flight_id
fr24_mart.track_points — точки трека с noise_score (расчёт по шумовой модели)
fr24_mart.noise_grid — агрегат по ячейкам 0.01°×0.01° (~1 км). AVG(noise_score)
fr24_mart.source_coverage — покрытие по источникам (% рейсов с треком)
```
---
## ETL-процессы
### 1. RTL-SDR pipeline (real-time)
```
РТЛ-SDR RTL2838 (USB, 1090 МГц)
→ dump1090-fa (SBS-1 декодер)
→ TCP :30003
→ fr24-capture → fr24.captures + fr24.raw_packets (base64, partitioned/date)
→ fr24-preprocess → fr24.aircraft + fr24.flights + fr24.tracks + fr24.track_points
```
**Алгоритм preprocess:**
- MSG1 = callsign, MSG3 = позиция (lat/lon/alt), MSG4 = скорость/курс (кешируется 30 сек, обогащает MSG3)
- gap > 30 мин без точек → закрыть рейс, создать новый
- `onground=1` → точку пропустить
- **M4-фильтр (26.04.2026):** скорость между точками > 350 м/с (Mach 1) → выброс, точка не записывается
**Антенна:**
- Местоположение: д. Хоругвино, Солнечногорский р-н, МО
- Координаты: 56.121°N, 37.216°E
- Оборудование: RTL-SDR RTL2838 DVB-T
- **Покрытие:** ~230 рейсов/день (~9.6% от расписания)
- **Задержка:** 1-2 сек
- **Throughput:** ~3000 пакетов/5 мин
### 2. Schedule pipeline (ежедневно T-1)
```
Яндекс Расписания API → fr24-schedule → fr24_ext.schedule
```
- **4 аэропорта × 2 направления** = ~1400 рейсов/день
- **Rate limit:** ~100 запросов/час → ~30 запросов на один день
- **thread_title:** парсится из `thread.title` (маршрут "Москва → Санкт-Петербург")
### 3. FR24 tracks pipeline (по запросу)
```
FR24 AeroAPI → fr24-tracks-fr24 → fr24_ext.flight_tracks_fr24 + track_points_fr24
```
- Запуск: `POST http://fr24-tracks-fr24:8001/run?date=YYYY-MM-DD`
- **Лимит:** Explorer тариф, остаток ~50K кредитов (40 кредитов/рейс = ~1250 рейсов)
- **Хранится только по явной команде** (дорого)
### 4. FlightAware pipeline (по запросу)
```
FlightAware AeroAPI → fr24-tracks-fa → fr24_ext.flight_tracks_fa + track_points_fa
```
- Запуск: `POST http://fr24-tracks-fa:8002/run?date=YYYY-MM-DD`
- **Стоимость:** $0.01/запрос, ~$28/день при полной загрузке
- Rate limit: 429 после ~5-10 быстрых запросов, Retry-After 60с
### 5. Mart builder (каждый час автоматически, T-1)
```
fr24_ext.schedule + fr24.flights + fr24_ext.flight_tracks_fr24 + fr24_ext.flight_tracks_fa
→ build_mart.py → fr24_mart.flights + track_points + noise_grid + source_coverage
```
**Логика мэтчинга (приоритет RTL-SDR > FR24 > FA):**
1. **RTL-SDR:** `flight_number` (IATA `'SU 1057'`) → конвертируется в ICAO callsign (`'AFL1057'`) → поиск в `fr24.flights.callsign`
2. **FR24:** числовой номер рейса (`6807`) + маршрут (ICAO аэропортов → IATA через словарь) → поиск в `fr24_ext.flight_tracks_fr24`
3. **FA:** числовой номер рейса + маршрут → поиск в `fr24_ext.flight_tracks_fa`
**Проблема мэтчинга (⚠️ в работе):**
- RTL-SDR: требует словарь `AIRLINE_IATA_TO_ICAO` (AFL=SU, SDM=FV и т.д.)
- FA: хранит ICAO ident (`CSN342`), расписание IATA (`CZ 342`) → числовой матч
- Словарь аэропортов `ICAO_TO_IATA` неполный (~40 аэропортов)
### 6. Шумовая модель
```
track_points → altitude_to_noise_db(alt_ft, aircraft_type) → noise_score
→ AGG по ячейкам 0.01° → noise_grid
```
**Зоны:**
- 0-2 км: Критический (>75 dB)
- 2-5 км: Высокий (65-75 dB)
- 5-7 км: Средний (55-65 dB)
- 7-9 км: Низкий (45-55 dB)
- >9 км: Фоновый (<45 dB)
---
## UI (фронтенд)
Фронтенд: Flask + Leaflet.js, доступен через nginx reverse proxy.
### Страницы
#### `/` — Карта шумового загрязнения
- **Тепловая карта** (Leaflet heatmap layer) по данным `fr24_mart.noise_grid`
- **Аэропорты** SVO/DME/VKO/ZIA маркерами
- **Зоны влияния** 2/5/7/9 км (цветные круги)
- **Выбор даты** — слайдер или датепикер
- **Легенда** шума
#### `/schedule` — Расписание рейсов
- Таблица рейсов из `fr24_mart.flights` с маршрутами
- **Фильтры:** аэропорт, направление, дата
- Маршрут отображается из `thread_title` (Яндекс) — "Москва → Санкт-Петербург"
- **CSV экспорт** — выгрузка с городами вместо IATA-кодов
- Иконки источника трека (RTL/FR24/FA)
- **Тип ВС:** `COALESCE(mf.aircraft_type, s.aircraft_type)` — сначала из витрины `fr24_mart.flights` (если есть трек), иначе из расписания `fr24_ext.schedule`. Гарантирует заполненность колонки даже для дней без RTL-SDR данных.
#### `/monitoring` — Мониторинг системы
- Capture lag, throughput, unprocessed packets
- DB size, disk usage
- Статус контейнеров
- График активности за последние 24ч
#### `/data-sources` — Покрытие источниками
- Статистика по `fr24_mart.source_coverage`
- % рейсов с треком по каждому источнику
- Топ авиакомпаний, топ маршрутов
- Загрузка аэропортов
### API эндпоинты (fr24-api :8080)
```
GET /api/schedule/data?date_from=&date_to=&airport=&direction=
GET /api/monitoring
GET /api/data-sources/coverage
GET /api/data-sources/quality
GET /api/data-sources/top-airlines
GET /api/data-sources/top-routes
GET /api/data-sources/airport-load
```
---
## Текущий статус данных (на 26.04.2026)
| Что | Количество |
|---|---|
| Расписание в fr24_ext | 01.04 19.04.2026 (~26K рейсов) |
| FR24 треки | 1 рейс (FV6807, тест) |
| FA треки | 5 рейсов (CSN, тест) |
| RTL-SDR треки (ЗУП 35 км) | 879 треков, 74,747 точек, avg TQS=0.982 |
| RTL-SDR: dump1090 | ⚠️ нестабилен (rc=1 цикл), возможна проблема USB/прав |
| Витрина fr24_mart | 01.04 только (1399 рейсов, 1 с треком) |
| Noise grid | 688 ячеек за 01.04 |
---
## Метрики качества ADS-B захвата
Детали: `analysis/ZUP_DEFINITION.md`, SQL: `analysis/adsb_quality_metrics.sql`
**Зона уверенного приёма (ЗУП):** радиус **35 км** от антенны.
| Метрика | Описание | Значение в ЗУП |
|---|---|---|
| M1 — шаг между точками | Медианное расстояние между последовательными точками трека | 26 м |
| M2 — временной интервал | Медианный dt между точками; gap rate (gap>30 сек) | 0.8 сек; 2.2% |
| M3 — точек на трек | Кол-во точек трека в ЗУП | медиана ~85, всего 74,747 |
| M4 — выбросы координат | Доля точек со скоростью > 350 м/с | отфильтровано (пересчёт 26.04.2026) |
| TQS | Track Quality Score (0..1) | 0.982 среднее (после пересчёта 26.04.2026) |
**M4-фильтр** добавлен в `fr24-preprocess` 26.04.2026 — выбросы отсекаются до записи в БД.
---
## Известные ограничения и backlog
| # | Проблема | Приоритет |
|---|---|---|
| 1 | Мэтчинг RTL-SDR: IATA→ICAO конвертация авиакомпаний не реализована | 🔴 Высокий |
| 2 | Мэтчинг FA: ICAO ident в БД vs IATA в расписании | 🔴 Высокий |
| 3 | DDL: `origin_icao`/`destination_icao` VARCHAR(5) в flight_tracks_fa | 🔴 Высокий |
| 4 | Словарь ICAO_TO_IATA аэропортов неполный (~40 из нужных 200+) | 🟡 Средний |
| 5 | Яндекс backfill 0619.04 не завершён (rate limit 429) | 🟡 Средний |
| 6 | Витрина не содержит данных за 0219.04 | 🟡 Средний |
| 7 | Duration рейсов: только 6.6% заполнено | 🟢 Низкий |
---
## Ключи и конфиги
| Сервис | Переменная | Где |
|---|---|---|
| FR24 API | `FR24_API_KEY` | `.env` на VM |
| FlightAware | `FLIGHTAWARE_API_KEY` | `.env` на VM |
| Яндекс Расписания | `YANDEX_API_KEY` | `.env` на VM |
| PostgreSQL | `POSTGRES_PASSWORD=change-me` | docker-compose |
FR24 Explorer: остаток **~50 486 кредитов** из 120K (промо до 31.05.2026)
FlightAware: потрачено **$0.05** из pay-per-use
Яндекс: **rate limit** сбросится ~23:30 UTC 21.04