auto-sync: 2026-04-20 10:20:01
This commit is contained in:
120
tasks/flightradar24/docs/STEP1_EXTERNAL_DATA.md
Normal file
120
tasks/flightradar24/docs/STEP1_EXTERNAL_DATA.md
Normal file
@@ -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/месяц
|
||||
137
tasks/flightradar24/docs/STEP2_DATA_MART.md
Normal file
137
tasks/flightradar24/docs/STEP2_DATA_MART.md
Normal file
@@ -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)
|
||||
Reference in New Issue
Block a user