auto-sync: 2026-04-19 14:20:01
This commit is contained in:
@@ -6,13 +6,18 @@
|
||||
- **noisemap / FR24-прототип** — визуализация и расчёт шумовой плотности на базе исторических данных Flightradar24
|
||||
- **RTL-SDR ingest-контур** — локальный приём ADS-B, хранение в PostgreSQL/PostGIS и recovery после сбоев
|
||||
|
||||
## Текущий курс
|
||||
- ingest-контур строится как набор отдельных контейнеров: `capture`, `preprocess`, `api`, `monitoring`
|
||||
- `raw_packets` хранят base64 payload + метаданные, retention 3 дня
|
||||
- ingest и API связаны через схему PostgreSQL, а не через файловый контракт
|
||||
|
||||
## Куда смотреть
|
||||
- `tasks/flightradar24/PROJECT.md` — общий статус проекта
|
||||
- `tasks/flightradar24/docs/INDEX.md` — карта документации
|
||||
- `tasks/flightradar24/docs/ARCHITECTURE.md` — контейнерная архитектура ingest-контура
|
||||
- `tasks/flightradar24/docs/RTL-SDR_TZ.md` — ТЗ на RTL-SDR ingest
|
||||
- `tasks/flightradar24/docs/VM_SETUP.md` — инструкция по созданию VM в PVE
|
||||
- `tasks/flightradar24/docs/DEV_AGENT_HANDOFF.md` — пакет передачи Dev-агенту
|
||||
- `tasks/flightradar24/compose/README.md` — compose skeleton и контракт API
|
||||
|
||||
## Текущий статус
|
||||
- FR24-прототип жив и остаётся в проекте как историческая и визуальная база
|
||||
@@ -29,182 +34,3 @@
|
||||
- **Траектории полётов** за выбранный период (до 12 месяцев)
|
||||
- **Шумовые границы** вокруг траекторий, рассчитанные на основе высоты полёта
|
||||
- **Интерактивные элементы**: зум, фильтры по времени, всплывающая информация о рейсах
|
||||
|
||||
## 🎯 Цели проекта
|
||||
|
||||
1. **Визуализация**: Наглядно показать распределение шумового загрязнения от авиации
|
||||
2. **Анализ**: Выявить наиболее загруженные воздушные коридоры
|
||||
3. **Информирование**: Предоставить данные для исследований и принятия решений
|
||||
4. **Оптимизация**: Эффективное использование данных Flightradar24 API в рамках тарифа Explorer
|
||||
|
||||
## 🛠 Технологический стек
|
||||
|
||||
### Бэкенд
|
||||
- **Язык**: Python 3.8+
|
||||
- **Фреймворк**: FastAPI (лёгкий, асинхронный)
|
||||
- **Библиотеки**:
|
||||
- `requests` - работа с Flightradar24 API
|
||||
- `sqlalchemy` / `sqlite3` - работа с базой данных
|
||||
- `pandas` / `numpy` - обработка данных
|
||||
- `python-dotenv` - управление конфигурацией
|
||||
|
||||
### Фронтенд
|
||||
- **Карты**: Leaflet.js с OpenStreetMap
|
||||
- **Интерфейс**: Bootstrap 5 + чистый JavaScript
|
||||
- **Визуализация**: встроенные возможности Leaflet + D3.js (опционально)
|
||||
|
||||
### Хранение данных
|
||||
- **База данных**: SQLite (разработка) / PostgreSQL (production)
|
||||
- **Кэш**: файловая система (JSON/CSV)
|
||||
- **Конфигурация**: `.env` файл + `config.json`
|
||||
|
||||
## 📊 Модель шумового воздействия (v1.0)
|
||||
|
||||
### Основные допущения
|
||||
- **Фактор**: только высота полёта
|
||||
- **Зависимость**: уровень шума обратно пропорционален высоте
|
||||
- **Формула**:
|
||||
```
|
||||
noise_radius_km = base_radius * (min_height / actual_height) * factor
|
||||
```
|
||||
где:
|
||||
- `base_radius` = 5.0 км (базовый радиус шума)
|
||||
- `min_height` = 300 м (минимальная высота для расчёта)
|
||||
- `factor` = 0.01 (коэффициент масштабирования)
|
||||
|
||||
### Параметры (config.json)
|
||||
```json
|
||||
"noise_model": {
|
||||
"base_noise_radius_km": 5.0,
|
||||
"height_factor": 0.01,
|
||||
"min_height_m": 300,
|
||||
"max_height_m": 12000,
|
||||
"min_radius_km": 0.5,
|
||||
"max_radius_km": 10.0
|
||||
}
|
||||
```
|
||||
|
||||
### Бэклог для v2.0
|
||||
- Учёт типа воздушного судна
|
||||
- Учёт времени суток (ночные полёты)
|
||||
- Учёт направления и скорости ветра
|
||||
- Привязка к санитарным нормам
|
||||
|
||||
## 🚀 Быстрый старт
|
||||
|
||||
### 1. Установка зависимостей
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### 2. Настройка API ключа
|
||||
```bash
|
||||
export FLIGHTRADAR24_API_KEY="your_api_key_here"
|
||||
```
|
||||
Или создайте файл `.env`:
|
||||
```
|
||||
FLIGHTRADAR24_API_KEY=your_api_key_here
|
||||
```
|
||||
|
||||
### 3. Проверка подключения
|
||||
```bash
|
||||
python scripts/check_api.py
|
||||
```
|
||||
|
||||
### 4. Запуск тестового сбора данных
|
||||
```bash
|
||||
python scripts/flightradar24_explorer.py
|
||||
```
|
||||
|
||||
## 📁 Структура проекта
|
||||
|
||||
```
|
||||
flightradar24/
|
||||
├── README.md # Эта документация
|
||||
├── requirements.txt # Зависимости Python
|
||||
├── config.json # Конфигурация проекта
|
||||
├── scripts/ # Вспомогательные скрипты
|
||||
│ ├── check_api.py # Проверка API ключа
|
||||
│ └── flightradar24_explorer.py # Базовый клиент API
|
||||
├── reports/ # Отчёты и документация
|
||||
│ └── ТЗ_Карта_шумового_загрязнения_Flightradar24.md
|
||||
├── data/ # Данные (будет создано)
|
||||
│ ├── cache/ # Кэшированные данные API
|
||||
│ ├── processed/ # Обработанные данные
|
||||
│ └── exports/ # Экспортированные файлы
|
||||
├── backend/ # Бэкенд приложения (будет создано)
|
||||
├── frontend/ # Фронтенд приложения (будет создано)
|
||||
└── docs/ # Документация (будет создано)
|
||||
```
|
||||
|
||||
## 🔧 Конфигурация
|
||||
|
||||
Основные параметры настройки в `config.json`:
|
||||
|
||||
| Параметр | Описание | Значение по умолчанию |
|
||||
|----------|----------|----------------------|
|
||||
| `geography.region` | Регион исследования | Московская область |
|
||||
| `geography.bounds` | Границы региона | 54.5-56.5°N, 35.5-39.5°E |
|
||||
| `data_collection.target_period_months` | Целевой период данных | 12 месяцев |
|
||||
| `data_collection.initial_period_days` | Начальный период для тестирования | 30 дней |
|
||||
| `visualization.default_center` | Центр карты | [55.7558, 37.6173] (Москва) |
|
||||
| `visualization.default_zoom` | Увеличение карты | 9 |
|
||||
|
||||
## 💳 Использование кредитов Flightradar24 API
|
||||
|
||||
### Тариф Explorer
|
||||
- **Базовый лимит**: 60,000 кредитов/месяц
|
||||
- **Промо-период**: до 120,000 кредитов/месяц (до 31.05.2026)
|
||||
- **Обновление**: раз в неделю/месяц в зависимости от лимитов
|
||||
|
||||
### Примерная стоимость запросов
|
||||
| Endpoint | Кредитов/запрос | Примерное использование |
|
||||
|----------|-----------------|-------------------------|
|
||||
| `flight/list` (live) | 5 | 100 запросов = 500 кредитов |
|
||||
| `flight/{id}/history` | 20 | 50 рейсов = 1,000 кредитов |
|
||||
| `flight/{id}/playback` | 30 | 30 треков = 900 кредитов |
|
||||
|
||||
### Стратегия оптимизации
|
||||
1. **Кэширование**: Сохранять полученные данные локально
|
||||
2. **Пакетная обработка**: Собирать данные партиями
|
||||
3. **Приоритизация**: Сначала ключевые маршруты и периоды
|
||||
4. **Мониторинг**: Регулярно проверять остаток кредитов
|
||||
|
||||
## 📈 План разработки
|
||||
|
||||
### Этап 1: Подготовка и прототип (23-25 марта 2026)
|
||||
- [ ] Проверка доступности исторических данных
|
||||
- [ ] Создание proof-of-concept с 10-50 траекториями
|
||||
- [ ] Согласование визуализации с Заказчиком
|
||||
|
||||
### Этап 2: Разработка бэкенда (26-28 марта 2026)
|
||||
- [ ] Архитектура FastAPI приложения
|
||||
- [ ] Система сбора и обработки данных
|
||||
- [ ] API для фронтенда
|
||||
|
||||
### Этап 3: Разработка фронтенда (29-31 марта 2026)
|
||||
- [ ] Интерфейс карты (Leaflet)
|
||||
- [ ] Панель управления и фильтры
|
||||
- [ ] Интеграция с бэкендом
|
||||
|
||||
### Этап 4: Тестирование и оптимизация (1-2 апреля 2026)
|
||||
- [ ] Функциональное тестирование
|
||||
- [ ] Оптимизация производительности
|
||||
- [ ] Документация и развёртывание
|
||||
|
||||
## 🔗 Полезные ссылки
|
||||
|
||||
- [Flightradar24 API Documentation](https://fr24api.flightradar24.com/)
|
||||
- [Leaflet.js Documentation](https://leafletjs.com/)
|
||||
- [FastAPI Documentation](https://fastapi.tiangolo.com/)
|
||||
- [Полное ТЗ проекта](reports/ТЗ_Карта_шумового_загрязнения_Flightradar24.md)
|
||||
|
||||
## 📞 Контакты
|
||||
|
||||
- **Заказчик**: Слава
|
||||
- **Исполнитель**: Стрим (ИИ-ассистент)
|
||||
- **Канал связи**: Telegram через OpenClaw
|
||||
|
||||
---
|
||||
|
||||
*Проект находится в активной разработке. Последнее обновление: 22 марта 2026.*
|
||||
@@ -9,8 +9,16 @@ POSTGRES_PUBLISHED_PORT=5432
|
||||
POSTGRES_HOST=postgres
|
||||
POSTGRES_PORT=5432
|
||||
|
||||
# Ingest scaffold
|
||||
INGEST_MODE=placeholder
|
||||
RAW_RETENTION_DAYS=3
|
||||
OVERLAP_MINUTES=10
|
||||
API_PUBLISHED_PORT=8080
|
||||
MONITORING_PUBLISHED_PORT=9090
|
||||
|
||||
# Capture / preprocess
|
||||
CAPTURE_SOURCE=rtl-sdr
|
||||
RTLSDR_DEVICE_INDEX=0
|
||||
RTLSDR_SAMPLE_RATE=2000000
|
||||
RTLSDR_CENTER_FREQUENCY=1090000000
|
||||
RTLSDR_GAIN=auto
|
||||
RAW_RETENTION_DAYS=3
|
||||
PARTITION_RETENTION_DAYS=3
|
||||
OVERLAP_MINUTES=10
|
||||
MONITORING_INTERVAL_SECONDS=30
|
||||
|
||||
@@ -1,21 +1,51 @@
|
||||
# Compose scaffold for FR24 ingest
|
||||
# FR24 ingest compose skeleton
|
||||
|
||||
This directory contains the baseline Docker Compose skeleton for the RTL-SDR ingest contour.
|
||||
This directory contains the Docker Compose skeleton for the RTL-SDR ingest contour.
|
||||
|
||||
## Services
|
||||
- `postgres` — PostgreSQL 16 + PostGIS
|
||||
- `ingest` — placeholder for capture/preprocess wiring
|
||||
- `status` — simple heartbeat/status scaffold
|
||||
- `postgres` — PostgreSQL 16 + PostGIS, single source of truth for ingest and API
|
||||
- `capture` — RTL-SDR access and `raw_packets` writer
|
||||
- `preprocess` — normalization, flights/tracks/track_points builder, recovery
|
||||
- `api` — reader for noisemap UI and future viewer endpoints
|
||||
- `monitoring` — separate container for healthchecks, disk/DB/capture status, alerts
|
||||
|
||||
## Layout
|
||||
- `../db/postgres` — PostgreSQL data directory
|
||||
- `../db/init` — init SQL scripts for schema/bootstrap
|
||||
- `../ingest` — ingest service code placeholder
|
||||
- `../logs/ingest` — ingest logs
|
||||
- `../logs/status` — status heartbeat files
|
||||
- `../backup` — backup artifacts
|
||||
- `../db/init` — bootstrap SQL for extensions and schema
|
||||
- `../ingest` — capture and preprocess implementation
|
||||
- `../frontend` — API/viewer implementation
|
||||
- `../logs/*` — service logs
|
||||
- `../backup` — pg_dump / restore artifacts
|
||||
|
||||
## Architecture notes
|
||||
- `raw_packets` stores binary payloads as base64 plus metadata: timestamp, frequency, RSSI, SNR, samplerate.
|
||||
- Raw retention is 3 days.
|
||||
- Raw data is partitioned by date.
|
||||
- `capture` and `preprocess` are separate containers.
|
||||
- `api` is included now so the ingest↔API contract is fixed early.
|
||||
- The contract between ingest and API is the PostgreSQL schema itself: ingest writes tables, API reads the same tables.
|
||||
|
||||
## API / data contract
|
||||
The API reads:
|
||||
- `captures`
|
||||
- `raw_packets`
|
||||
- `aircraft`
|
||||
- `flights`
|
||||
- `track_points`
|
||||
- `tracks`
|
||||
- `processing_state`
|
||||
- `noise_results`
|
||||
|
||||
Planned endpoints:
|
||||
- `GET /health` — service status
|
||||
- `GET /captures` — capture sessions
|
||||
- `GET /aircraft` — aircraft list and search
|
||||
- `GET /flights` — flights with filters
|
||||
- `GET /tracks/{track_id}` — a single track with points
|
||||
- `GET /noise-results` — noise polygons and summaries
|
||||
- `GET /dashboard/status` — ingest / recovery / backlog status for UI
|
||||
- `GET /viewer/config` — map/UI bootstrap metadata
|
||||
|
||||
## Notes
|
||||
- No destructive migrations are included.
|
||||
- The `ingest` service is a placeholder; wire real capture/preprocess logic later.
|
||||
- No runtime is started from this repository during preparation.
|
||||
- The stack expects a `.env` file copied from `.env.example` in this directory.
|
||||
|
||||
@@ -4,12 +4,20 @@ name: fr24-ingest
|
||||
|
||||
x-common-env: &common-env
|
||||
TZ: ${TZ:-UTC}
|
||||
APP_ENV: ${APP_ENV:-dev}
|
||||
POSTGRES_HOST: ${POSTGRES_HOST:-postgres}
|
||||
POSTGRES_PORT: ${POSTGRES_PORT:-5432}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-fr24}
|
||||
POSTGRES_USER: ${POSTGRES_USER:-fr24}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-change-me}
|
||||
APP_ENV: ${APP_ENV:-dev}
|
||||
RAW_RETENTION_DAYS: ${RAW_RETENTION_DAYS:-3}
|
||||
PARTITION_RETENTION_DAYS: ${PARTITION_RETENTION_DAYS:-3}
|
||||
OVERLAP_MINUTES: ${OVERLAP_MINUTES:-10}
|
||||
CAPTURE_SOURCE: ${CAPTURE_SOURCE:-rtl-sdr}
|
||||
RTLSDR_DEVICE_INDEX: ${RTLSDR_DEVICE_INDEX:-0}
|
||||
RTLSDR_SAMPLE_RATE: ${RTLSDR_SAMPLE_RATE:-2000000}
|
||||
RTLSDR_CENTER_FREQUENCY: ${RTLSDR_CENTER_FREQUENCY:-1090000000}
|
||||
RTLSDR_GAIN: ${RTLSDR_GAIN:-auto}
|
||||
|
||||
services:
|
||||
postgres:
|
||||
@@ -35,25 +43,24 @@ services:
|
||||
networks:
|
||||
- fr24-net
|
||||
|
||||
ingest:
|
||||
capture:
|
||||
image: alpine:3.20
|
||||
container_name: fr24-ingest
|
||||
command: ["sh", "-c", "echo 'ingest placeholder: wire capture/preprocess here'; tail -f /dev/null"]
|
||||
container_name: fr24-capture
|
||||
command: ["sh", "-c", "echo 'capture placeholder: read RTL-SDR and write raw_packets'; tail -f /dev/null"]
|
||||
environment:
|
||||
<<: *common-env
|
||||
INGEST_MODE: ${INGEST_MODE:-placeholder}
|
||||
RAW_RETENTION_DAYS: ${RAW_RETENTION_DAYS:-3}
|
||||
OVERLAP_MINUTES: ${OVERLAP_MINUTES:-10}
|
||||
CAPTURE_SOURCE: ${CAPTURE_SOURCE:-rtl-sdr}
|
||||
SERVICE_ROLE: capture
|
||||
devices:
|
||||
- "/dev/bus/usb:/dev/bus/usb"
|
||||
volumes:
|
||||
- ../ingest:/app
|
||||
- ../logs/ingest:/var/log/fr24
|
||||
- ../logs/capture:/var/log/fr24
|
||||
- ../backup:/backup
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "test -f /tmp/ingest-ready && echo ok || exit 1"]
|
||||
test: ["CMD-SHELL", "test -f /tmp/capture-ready || exit 1"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
@@ -62,17 +69,89 @@ services:
|
||||
networks:
|
||||
- fr24-net
|
||||
|
||||
status:
|
||||
preprocess:
|
||||
image: alpine:3.20
|
||||
container_name: fr24-status
|
||||
command: ["sh", "-c", "while true; do date -u +'%Y-%m-%dT%H:%M:%SZ' > /status/heartbeat; sleep 30; done"]
|
||||
container_name: fr24-preprocess
|
||||
command: ["sh", "-c", "echo 'preprocess placeholder: normalize data and build flights/tracks'; tail -f /dev/null"]
|
||||
environment:
|
||||
<<: *common-env
|
||||
SERVICE_ROLE: preprocess
|
||||
volumes:
|
||||
- ../logs/status:/status
|
||||
- ../ingest:/app
|
||||
- ../logs/preprocess:/var/log/fr24
|
||||
- ../backup:/backup
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
capture:
|
||||
condition: service_started
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "test -f /status/heartbeat"]
|
||||
test: ["CMD-SHELL", "test -f /tmp/preprocess-ready || exit 1"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- fr24-net
|
||||
|
||||
api:
|
||||
image: alpine:3.20
|
||||
container_name: fr24-api
|
||||
command: ["sh", "-c", "echo 'api placeholder: noisemap reader and UI endpoints'; tail -f /dev/null"]
|
||||
environment:
|
||||
<<: *common-env
|
||||
SERVICE_ROLE: api
|
||||
API_PORT: ${API_PORT:-8080}
|
||||
ports:
|
||||
- "${API_PUBLISHED_PORT:-8080}:8080"
|
||||
volumes:
|
||||
- ../frontend:/app
|
||||
- ../logs/api:/var/log/fr24
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
preprocess:
|
||||
condition: service_started
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "test -f /tmp/api-ready || exit 1"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- fr24-net
|
||||
|
||||
monitoring:
|
||||
image: alpine:3.20
|
||||
container_name: fr24-monitoring
|
||||
command: ["sh", "-c", "echo 'monitoring placeholder: disk, db, capture status, alerts'; tail -f /dev/null"]
|
||||
environment:
|
||||
<<: *common-env
|
||||
SERVICE_ROLE: monitoring
|
||||
MONITORING_INTERVAL_SECONDS: ${MONITORING_INTERVAL_SECONDS:-30}
|
||||
ports:
|
||||
- "${MONITORING_PUBLISHED_PORT:-9090}:9090"
|
||||
volumes:
|
||||
- ../logs/monitoring:/var/log/fr24
|
||||
- ../backup:/backup
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
capture:
|
||||
condition: service_started
|
||||
preprocess:
|
||||
condition: service_started
|
||||
api:
|
||||
condition: service_started
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "test -f /tmp/monitoring-ready || exit 1"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- fr24-net
|
||||
@@ -81,8 +160,3 @@ networks:
|
||||
fr24-net:
|
||||
name: fr24-net
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
postgres-data:
|
||||
ingest-logs:
|
||||
backups:
|
||||
|
||||
@@ -1,7 +1,24 @@
|
||||
# Database layout
|
||||
|
||||
- `postgres/` — PostgreSQL persistent data volume
|
||||
- `init/` — bootstrap SQL for extensions and initial schema
|
||||
- `init/` — bootstrap SQL for extensions, schema, and retention helpers
|
||||
|
||||
Current bootstrap only enables `postgis` and `pgcrypto`.
|
||||
No irreversible migrations are included.
|
||||
Bootstrap now enables:
|
||||
- `postgis`
|
||||
- `pgcrypto`
|
||||
- core FR24 ingest schema under `fr24`
|
||||
|
||||
Schema objects:
|
||||
- `captures`
|
||||
- `raw_packets`
|
||||
- `aircraft`
|
||||
- `flights`
|
||||
- `tracks`
|
||||
- `track_points`
|
||||
- `processing_state`
|
||||
- `noise_results`
|
||||
|
||||
Notes:
|
||||
- `raw_packets` is partitioned by `partition_date`
|
||||
- raw retention target is 3 days
|
||||
- no runtime is started from this repository during preparation
|
||||
|
||||
124
tasks/flightradar24/db/init/002_schema.sql
Normal file
124
tasks/flightradar24/db/init/002_schema.sql
Normal file
@@ -0,0 +1,124 @@
|
||||
CREATE SCHEMA IF NOT EXISTS fr24;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fr24.captures (
|
||||
capture_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
started_at TIMESTAMPTZ NOT NULL,
|
||||
ended_at TIMESTAMPTZ,
|
||||
source TEXT NOT NULL DEFAULT 'rtl-sdr',
|
||||
device_index INTEGER NOT NULL DEFAULT 0,
|
||||
center_frequency_hz BIGINT NOT NULL,
|
||||
sample_rate_hz INTEGER NOT NULL,
|
||||
gain_db NUMERIC(6,2),
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
notes TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fr24.raw_packets (
|
||||
raw_packet_id BIGSERIAL PRIMARY KEY,
|
||||
capture_id UUID NOT NULL REFERENCES fr24.captures(capture_id) ON DELETE CASCADE,
|
||||
observed_at TIMESTAMPTZ NOT NULL,
|
||||
partition_date DATE NOT NULL DEFAULT (CURRENT_DATE),
|
||||
frequency_hz BIGINT NOT NULL,
|
||||
rssi_dbm NUMERIC(8,3),
|
||||
snr_db NUMERIC(8,3),
|
||||
samplerate_hz INTEGER NOT NULL,
|
||||
payload_base64 TEXT NOT NULL,
|
||||
payload_bytes INTEGER,
|
||||
decoded_format TEXT,
|
||||
message_type TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
) PARTITION BY RANGE (partition_date);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fr24.raw_packets_default
|
||||
PARTITION OF fr24.raw_packets DEFAULT;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fr24.aircraft (
|
||||
aircraft_id BIGSERIAL PRIMARY KEY,
|
||||
icao24 TEXT NOT NULL UNIQUE,
|
||||
callsign TEXT,
|
||||
registration TEXT,
|
||||
aircraft_type TEXT,
|
||||
operator_name TEXT,
|
||||
first_seen_at TIMESTAMPTZ,
|
||||
last_seen_at TIMESTAMPTZ,
|
||||
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fr24.flights (
|
||||
flight_id BIGSERIAL PRIMARY KEY,
|
||||
aircraft_id BIGINT NOT NULL REFERENCES fr24.aircraft(aircraft_id) ON DELETE CASCADE,
|
||||
departure_airport TEXT,
|
||||
arrival_airport TEXT,
|
||||
callsign TEXT,
|
||||
flight_number TEXT,
|
||||
started_at TIMESTAMPTZ NOT NULL,
|
||||
ended_at TIMESTAMPTZ,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
source TEXT NOT NULL DEFAULT 'rtl-sdr',
|
||||
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fr24.tracks (
|
||||
track_id BIGSERIAL PRIMARY KEY,
|
||||
flight_id BIGINT NOT NULL REFERENCES fr24.flights(flight_id) ON DELETE CASCADE,
|
||||
geometry GEOMETRY(LineString, 4326),
|
||||
point_count INTEGER NOT NULL DEFAULT 0,
|
||||
min_altitude_m NUMERIC(10,2),
|
||||
max_altitude_m NUMERIC(10,2),
|
||||
distance_m NUMERIC(14,2),
|
||||
duration_seconds INTEGER,
|
||||
last_point_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fr24.track_points (
|
||||
track_point_id BIGSERIAL PRIMARY KEY,
|
||||
track_id BIGINT NOT NULL REFERENCES fr24.tracks(track_id) ON DELETE CASCADE,
|
||||
flight_id BIGINT NOT NULL REFERENCES fr24.flights(flight_id) ON DELETE CASCADE,
|
||||
observed_at TIMESTAMPTZ NOT NULL,
|
||||
point_order INTEGER NOT NULL,
|
||||
geom GEOMETRY(Point, 4326) NOT NULL,
|
||||
altitude_m NUMERIC(10,2),
|
||||
ground_speed_kt NUMERIC(10,2),
|
||||
vertical_rate_fpm NUMERIC(10,2),
|
||||
heading_deg NUMERIC(10,2),
|
||||
source_packet_id BIGINT REFERENCES fr24.raw_packets(raw_packet_id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
UNIQUE (track_id, point_order)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fr24.processing_state (
|
||||
state_key TEXT PRIMARY KEY,
|
||||
state_value JSONB NOT NULL,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
note TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fr24.noise_results (
|
||||
noise_result_id BIGSERIAL PRIMARY KEY,
|
||||
flight_id BIGINT REFERENCES fr24.flights(flight_id) ON DELETE CASCADE,
|
||||
track_id BIGINT REFERENCES fr24.tracks(track_id) ON DELETE CASCADE,
|
||||
computed_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
period_start TIMESTAMPTZ,
|
||||
period_end TIMESTAMPTZ,
|
||||
noise_model TEXT NOT NULL DEFAULT 'v1',
|
||||
geometry GEOMETRY(Polygon, 4326),
|
||||
summary JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_raw_packets_capture_time ON fr24.raw_packets (capture_id, observed_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_raw_packets_partition_date ON fr24.raw_packets (partition_date);
|
||||
CREATE INDEX IF NOT EXISTS idx_aircraft_last_seen ON fr24.aircraft (last_seen_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_flights_aircraft_started ON fr24.flights (aircraft_id, started_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_track_points_track_time ON fr24.track_points (track_id, observed_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_track_points_flight_time ON fr24.track_points (flight_id, observed_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_tracks_flight ON fr24.tracks (flight_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_noise_results_computed_at ON fr24.noise_results (computed_at DESC);
|
||||
23
tasks/flightradar24/db/init/003_retention.sql
Normal file
23
tasks/flightradar24/db/init/003_retention.sql
Normal file
@@ -0,0 +1,23 @@
|
||||
CREATE OR REPLACE FUNCTION fr24.drop_raw_partitions_older_than(retention_days INTEGER)
|
||||
RETURNS void
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
partition_record RECORD;
|
||||
cutoff_date DATE := CURRENT_DATE - retention_days;
|
||||
BEGIN
|
||||
FOR partition_record IN
|
||||
SELECT inhrelid::regclass::text AS partition_name
|
||||
FROM pg_inherits
|
||||
JOIN pg_class parent ON pg_inherits.inhparent = parent.oid
|
||||
WHERE parent.relname = 'raw_packets'
|
||||
AND parent.relnamespace = 'fr24'::regnamespace
|
||||
LOOP
|
||||
IF partition_record.partition_name <> 'fr24.raw_packets_default' THEN
|
||||
EXECUTE format('ALTER TABLE %s DETACH PARTITION %s', 'fr24.raw_packets', partition_record.partition_name);
|
||||
END IF;
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
COMMENT ON FUNCTION fr24.drop_raw_partitions_older_than(INTEGER) IS 'Retention helper placeholder; actual cleanup is driven by monitoring/preprocess scheduler.';
|
||||
@@ -10,169 +10,46 @@
|
||||
- хранить данные в PostgreSQL/PostGIS
|
||||
- отдавать данные в noisemap / карту
|
||||
|
||||
## 2. Ограничения среды
|
||||
- 1 VM в PVE
|
||||
- USB RTL-SDR проброшен в VM
|
||||
- ресурсы VM ограничены:
|
||||
- CPU: до 6 vCPU
|
||||
- RAM: 10–12 GB
|
||||
- SSD: 80–100 GB max
|
||||
- развёртывание через Docker Compose
|
||||
## 2. Контейнеры
|
||||
|
||||
## 3. Логическая схема
|
||||
|
||||
```text
|
||||
RTL-SDR USB
|
||||
↓
|
||||
capture
|
||||
↓
|
||||
raw_packets / captures (PostgreSQL)
|
||||
↓
|
||||
preprocess
|
||||
↓
|
||||
flights / tracks / track_points / processing_state
|
||||
↓
|
||||
noise_results
|
||||
↓
|
||||
noisemap / UI / API
|
||||
```
|
||||
|
||||
## 4. Контейнеры
|
||||
|
||||
### 4.1 `postgres`
|
||||
**Назначение:** хранение всех данных проекта.
|
||||
|
||||
Содержит:
|
||||
### 2.1 `postgres`
|
||||
Хранит:
|
||||
- `captures`
|
||||
- `raw_packets`
|
||||
- `aircraft`
|
||||
- `flights`
|
||||
- `track_points`
|
||||
- `tracks`
|
||||
- `track_points`
|
||||
- `processing_state`
|
||||
- `noise_results`
|
||||
|
||||
Требования:
|
||||
- PostgreSQL
|
||||
- PostGIS enabled
|
||||
- volume для данных
|
||||
- регулярные backup/restore процедуры
|
||||
### 2.2 `capture`
|
||||
- читает USB RTL-SDR
|
||||
- пишет `captures` и `raw_packets`
|
||||
- не занимается нормализацией
|
||||
|
||||
### 4.2 `capture`
|
||||
**Назначение:** приём ADS-B потока с RTL-SDR.
|
||||
### 2.3 `preprocess`
|
||||
- читает `raw_packets`
|
||||
- строит `aircraft`, `flights`, `tracks`, `track_points`
|
||||
- управляет `processing_state`
|
||||
- поддерживает recovery
|
||||
|
||||
Функции:
|
||||
- чтение USB-устройства
|
||||
- получение live-потока
|
||||
- запись сырья в PostgreSQL
|
||||
- фиксация `captures`
|
||||
- маркировка границ сессий приёма
|
||||
### 2.4 `api`
|
||||
- читает те же таблицы
|
||||
- отдаёт данные для noisemap UI
|
||||
- не пересчитывает геометрию на лету
|
||||
|
||||
Требования:
|
||||
- лёгкий CPU footprint
|
||||
- устойчивость к временной потере downstream
|
||||
- healthcheck
|
||||
- автоматический рестарт
|
||||
### 2.5 `monitoring`
|
||||
- отдельный контейнер
|
||||
- healthchecks, disk/DB/capture status, alerts
|
||||
|
||||
### 4.3 `preprocess`
|
||||
**Назначение:** нормализация и догоняющая обработка.
|
||||
|
||||
Функции:
|
||||
- обработка live-потока
|
||||
- разбор `raw_packets`
|
||||
- построение `aircraft`
|
||||
- построение `flights`
|
||||
- построение `tracks` и `track_points`
|
||||
- обновление `processing_state`
|
||||
- recovery с overlap при сбоях
|
||||
|
||||
Требования:
|
||||
- инкрементальная обработка
|
||||
- дедупликация на границах overlap
|
||||
- ограничение по памяти
|
||||
- возможность догонять пропуски автоматически
|
||||
|
||||
### 4.4 `api` / `viewer`
|
||||
**Назначение:** отдача данных для noisemap.
|
||||
|
||||
Функции:
|
||||
- чтение обработанных данных из PostgreSQL
|
||||
- отдача треков, точек и шумовых результатов
|
||||
- фильтрация по периоду и зоне
|
||||
- API для карты/визуализации
|
||||
|
||||
Требования:
|
||||
- лёгкие запросы
|
||||
- минимальная логика в рантайме
|
||||
- кэширование только при реальной необходимости
|
||||
|
||||
### 4.5 `monitoring` (optional)
|
||||
**Назначение:** наблюдение за здоровьем контура.
|
||||
|
||||
Функции:
|
||||
- healthcheck контейнеров
|
||||
- мониторинг задержки обработки
|
||||
- мониторинг заполнения диска
|
||||
- мониторинг статуса RTL-SDR
|
||||
- алерты при деградации
|
||||
|
||||
## 5. Docker Compose структура
|
||||
Минимальный compose должен поднимать:
|
||||
## 3. Docker Compose порядок
|
||||
Минимальный состав:
|
||||
- `postgres`
|
||||
- `capture`
|
||||
- `preprocess`
|
||||
- `api`
|
||||
|
||||
Опционально:
|
||||
- `monitoring`
|
||||
|
||||
### Сетевое правило
|
||||
- контейнеры общаются внутри одной docker network
|
||||
- наружу публикуется только `api` и, если нужно, `monitoring`
|
||||
- `postgres` не публикуется наружу
|
||||
|
||||
## 6. Данные и потоки
|
||||
|
||||
### 6.1 Live flow
|
||||
1. RTL-SDR → `capture`
|
||||
2. `capture` пишет сырьё в `raw_packets`
|
||||
3. `preprocess` читает сырьё
|
||||
4. `preprocess` обновляет `flights`, `tracks`, `track_points`
|
||||
5. `api` отдаёт данные на карту
|
||||
|
||||
### 6.2 Recovery flow
|
||||
1. `preprocess` обнаруживает отставание
|
||||
2. ищет недостающий диапазон в `raw_packets`
|
||||
3. добирает пропущенные записи
|
||||
4. обрабатывает с небольшим overlap
|
||||
5. обновляет `processing_state`
|
||||
|
||||
## 7. Автозапуск и устойчивость
|
||||
- контейнеры стартуют после reboot VM
|
||||
- каждый контейнер имеет healthcheck
|
||||
- сбой одного контейнера не должен валить всю VM
|
||||
- `capture` должен уметь переживать временный разрыв downstream
|
||||
- `preprocess` должен уметь догонять запись после восстановления
|
||||
|
||||
## 8. Производительность
|
||||
С учётом ограничений VM:
|
||||
- минимизировать число контейнеров и лишних сервисов
|
||||
- не тащить тяжёлые брокеры очередей без необходимости
|
||||
- не строить много промежуточных копий данных
|
||||
- хранить сырьё коротко и чистить автоматически
|
||||
- тяжёлые вычисления держать инкрементальными
|
||||
|
||||
## 9. Что должно быть детализировано дальше
|
||||
Следующие документы/итерации должны закрыть:
|
||||
- схему БД и индексы
|
||||
- backup/restore
|
||||
- мониторинг и алерты
|
||||
- контракт между `preprocess` и `api`
|
||||
- точный формат `raw_packets`
|
||||
- стратегию партиционирования
|
||||
|
||||
## 10. Связь с проектом
|
||||
Этот документ — техническая основа для:
|
||||
- `tasks/flightradar24/PROJECT.md`
|
||||
- `tasks/flightradar24/docs/RTL-SDR_TZ.md`
|
||||
|
||||
## 4. Контракт ingest↔API
|
||||
Контрактом является схема PostgreSQL. Детали — в `docs/INGEST_API_CONTRACT.md`.
|
||||
|
||||
44
tasks/flightradar24/docs/INGEST_API_CONTRACT.md
Normal file
44
tasks/flightradar24/docs/INGEST_API_CONTRACT.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Ingest ↔ API contract
|
||||
|
||||
## Principle
|
||||
The contract between ingest and API is the PostgreSQL schema.
|
||||
Ingest writes rows; API reads the same rows.
|
||||
No file exchange is required for the core data path.
|
||||
|
||||
## API read model
|
||||
The API reads these tables:
|
||||
- `fr24.captures` — capture sessions and source metadata
|
||||
- `fr24.raw_packets` — raw base64 packets with radio metadata
|
||||
- `fr24.aircraft` — aircraft identity and enrichment
|
||||
- `fr24.flights` — flight sessions and state
|
||||
- `fr24.tracks` — track aggregates
|
||||
- `fr24.track_points` — ordered track geometry points
|
||||
- `fr24.processing_state` — recovery cursors and pipeline state
|
||||
- `fr24.noise_results` — computed noise polygons and summaries
|
||||
|
||||
## Ingest write model
|
||||
- `capture` writes `captures` and `raw_packets`
|
||||
- `preprocess` writes `aircraft`, `flights`, `tracks`, `track_points`, `processing_state`, `noise_results`
|
||||
- `monitoring` does not own core data; it reports status and alerts
|
||||
|
||||
## Planned endpoints
|
||||
- `GET /health`
|
||||
- `GET /captures`
|
||||
- `GET /raw-packets` with pagination and time filters
|
||||
- `GET /aircraft`
|
||||
- `GET /flights`
|
||||
- `GET /tracks/{track_id}`
|
||||
- `GET /track-points?track_id=...`
|
||||
- `GET /noise-results`
|
||||
- `GET /dashboard/status`
|
||||
- `GET /viewer/config`
|
||||
|
||||
## Query expectations
|
||||
- API should prefer indexed filters by time, flight, aircraft, and partition date.
|
||||
- API should not reconstruct track geometry from raw packets at request time.
|
||||
- API should read prebuilt aggregates from `tracks` and `track_points`.
|
||||
|
||||
## Retention expectations
|
||||
- `raw_packets` keep 3 days by default.
|
||||
- Cleanup is partition-based by date.
|
||||
- Aggregated tables may retain longer, depending on UI needs.
|
||||
@@ -1,219 +1,22 @@
|
||||
# ТЗ: Приём, хранение и обработка данных с RTL-SDR для FR24 / noisemap
|
||||
# ТЗ: RTL-SDR ingest-контур
|
||||
|
||||
## 1. Цель
|
||||
Построить локальный контур приёма ADS-B данных с RTL-SDR, их предобработки, хранения в PostgreSQL/PostGIS и дальнейшего использования для:
|
||||
- восстановления данных после сбоев без потерь,
|
||||
- формирования сущностей рейсов и треков,
|
||||
- расчёта производных шумовых данных,
|
||||
- визуализации на карте в рамках проекта FR24 / noisemap.
|
||||
## Цель
|
||||
Построить локальный ADS-B ingest-контур на RTL-SDR с PostgreSQL/PostGIS, recovery и API для noisemap UI.
|
||||
|
||||
## 2. Целевой контур
|
||||
Система разворачивается на одной VM в PVE.
|
||||
## Обязательные сервисы
|
||||
- `postgres`
|
||||
- `capture`
|
||||
- `preprocess`
|
||||
- `api`
|
||||
- `monitoring`
|
||||
|
||||
### Ограничения VM
|
||||
- CPU: до 6 vCPU
|
||||
- RAM: 10–12 GB
|
||||
- SSD: 80–100 GB max
|
||||
## Требования к данным
|
||||
- raw packets хранятся как base64 payload + radio metadata
|
||||
- retention raw: 3 дня
|
||||
- partitioning: по дате
|
||||
- схема БД — контракт между ingest и API
|
||||
|
||||
### Аппаратный вход
|
||||
- RTL-SDR подключён к физической машине по USB
|
||||
- PVE-хост пробрасывает USB в VM
|
||||
|
||||
### Развёртывание
|
||||
- Docker Compose
|
||||
- каждый компонент в отдельном контейнере
|
||||
|
||||
## 3. Архитектура
|
||||
### Компоненты внутри VM
|
||||
- postgres + postgis
|
||||
- capture
|
||||
- preprocess
|
||||
- api/viewer
|
||||
- optional: monitoring
|
||||
|
||||
### Принцип
|
||||
- одна VM
|
||||
- одна PostgreSQL база
|
||||
- сырьё и обработанные данные живут в одной БД, но логически разделены
|
||||
- сырьё хранится с небольшим retention и используется для догоняющей обработки
|
||||
|
||||
## 4. Режимы работы
|
||||
### 4.1 Live mode
|
||||
- система принимает поток в реальном времени
|
||||
- записи сохраняются в сырьевой слой
|
||||
- данные сразу уходят в предобработку
|
||||
|
||||
### 4.2 Recovery mode
|
||||
- если обработка отстала или упала,
|
||||
- но сырьё ещё доступно,
|
||||
- система автоматически догоняет пропущенный диапазон
|
||||
|
||||
### 4.3 Overlap mode
|
||||
- при догоняющей обработке допускается небольшой перекрывающийся участок
|
||||
- это нужно, чтобы не терять данные на границах и компенсировать сбои
|
||||
|
||||
## 5. Хранение данных
|
||||
### 5.1 Retention
|
||||
- сырьё хранится 3 дня
|
||||
- после этого raw-слой чистится автоматически
|
||||
- 3 дня — минимальный гарантированный горизонт для восстановления
|
||||
|
||||
### 5.2 База
|
||||
- PostgreSQL
|
||||
- PostGIS обязателен
|
||||
|
||||
### 5.3 Принцип хранения
|
||||
- raw-данные отделены от core-данных
|
||||
- core-данные очищены и оптимизированы под запросы карты и расчётов
|
||||
- схема должна быть компактной, без лишних таблиц и тяжёлой нормализации
|
||||
|
||||
## 6. Объекты хранения
|
||||
Минимальный набор сущностей:
|
||||
|
||||
### `captures`
|
||||
Сессии приёма.
|
||||
Хранят:
|
||||
- старт и конец сессии
|
||||
- источник приёма
|
||||
- статус
|
||||
- покрытый диапазон времени
|
||||
- признаки сбоя / восстановления
|
||||
|
||||
### `raw_packets`
|
||||
Сырой поток.
|
||||
Хранят:
|
||||
- timestamp
|
||||
- payload/packet data
|
||||
- signal metadata при наличии
|
||||
- привязку к capture/session
|
||||
|
||||
### `aircraft`
|
||||
Справочник бортов.
|
||||
Хранят:
|
||||
- ICAO24
|
||||
- callsign
|
||||
- тип/категорию при наличии
|
||||
- оператор/авиакомпанию при наличии
|
||||
|
||||
### `flights`
|
||||
Сущность рейса.
|
||||
Хранят:
|
||||
- flight id / number
|
||||
- aircraft
|
||||
- время начала и конца
|
||||
- маршрут / аэропорты при наличии
|
||||
- состояние заполненности
|
||||
|
||||
### `track_points`
|
||||
Точки трека.
|
||||
Хранят:
|
||||
- время
|
||||
- координаты
|
||||
- высоту
|
||||
- скорость
|
||||
- курс
|
||||
- принадлежность к flight/track
|
||||
|
||||
### `tracks`
|
||||
Сводка трека.
|
||||
Хранят:
|
||||
- bbox
|
||||
- длительность
|
||||
- min/max altitude
|
||||
- количество точек
|
||||
- краткое описание маршрута
|
||||
|
||||
### `processing_state`
|
||||
Состояние пайплайна.
|
||||
Хранят:
|
||||
- последний успешный checkpoint
|
||||
- обработанный диапазон
|
||||
- отставание
|
||||
- состояние recovery
|
||||
|
||||
### `noise_results`
|
||||
Производные данные для карты.
|
||||
Хранят:
|
||||
- расчётные зоны/радиусы
|
||||
- интенсивность/плотность
|
||||
- геометрию для визуализации
|
||||
- привязку к рейсу/треку/времени
|
||||
|
||||
## 7. Основные требования к обработке
|
||||
### 7.1 Приём
|
||||
- принимать ADS-B поток от RTL-SDR
|
||||
- сохранять сырьё до обработки
|
||||
- не терять данные при временном сбое downstream
|
||||
|
||||
### 7.2 Предобработка
|
||||
- нормализовать записи
|
||||
- выделять рейсы
|
||||
- строить треки
|
||||
- обновлять state обработки
|
||||
|
||||
### 7.3 Восстановление
|
||||
- после сбоя искать недостающий диапазон
|
||||
- добирать пропущенные записи из raw-слоя
|
||||
- допускается overlap
|
||||
|
||||
### 7.4 Оптимизация
|
||||
- обработка должна быть лёгкой по CPU и памяти
|
||||
- БД и схема должны быть компактными
|
||||
- лишних промежуточных слоёв не заводить
|
||||
|
||||
## 8. Карта и визуализация
|
||||
Система должна поддерживать данные, нужные для:
|
||||
- отображения треков рейсов
|
||||
- отображения шумовых зон
|
||||
- анализа плотности пролётов
|
||||
- фильтрации по времени
|
||||
- отрисовки результатов на карте
|
||||
|
||||
## 9. Требования к инфраструктуре
|
||||
- запуск через Docker Compose
|
||||
- отдельные контейнеры для ключевых частей
|
||||
- автозапуск после ребута VM
|
||||
- возможность мониторить состояние приёма и БД
|
||||
- логирование по каждому компоненту отдельно
|
||||
|
||||
## 10. Критерии приёмки
|
||||
Система считается готовой, если:
|
||||
- RTL-SDR отдаёт поток в VM через USB passthrough
|
||||
- raw-данные сохраняются в PostgreSQL
|
||||
- raw retention работает на 3 дня
|
||||
- при сбое система может догнать пропущенный диапазон
|
||||
- в БД присутствуют рейсы, треки и точки треков
|
||||
- PostGIS используется для геоданных
|
||||
- данные доступны для визуализации на карте
|
||||
- контейнеры поднимаются через Docker Compose
|
||||
|
||||
## 11. Открытые вопросы, которые ещё стоит уточнить позже
|
||||
- точный формат сырьевых пакетов
|
||||
- нужен ли отдельный UI мониторинга
|
||||
- нужен ли архив beyond 3 days
|
||||
- какие индексы и партиционирование делать на старте
|
||||
- где именно будет жить API noisemap после переноса
|
||||
|
||||
## 12. Итерация 2 — обязательный список улучшений
|
||||
Следующая итерация ТЗ должна включать:
|
||||
- мониторинг отвалившегося RTL-SDR и автоперезапуск capture
|
||||
- healthcheck контейнеров и БД
|
||||
- политика ротации логов и объёма диска
|
||||
- схема индексов и партиционирования raw/track tables
|
||||
- unique key / dedup стратегия для overlapping recovery
|
||||
- экспорт/импорт исторических данных при миграции
|
||||
- резервное копирование PostgreSQL и восстановление
|
||||
- уведомления о деградации приёма или заполнении диска
|
||||
- контракт между ingest-слоем и noisemap UI, если они остаются раздельными
|
||||
|
||||
## 13. Анализ: ничего ли не упущено
|
||||
Дополнительно стоит проверить перед реализацией:
|
||||
- нужен ли отдельный UI мониторинга
|
||||
- где живёт API после переноса
|
||||
- как именно партиционируются `raw_packets` и `track_points`
|
||||
- нужен ли отдельный архив после 3 дней
|
||||
- какую политику дедупликации выбрать для overlap на границах
|
||||
- как восстанавливать БД после полного падения VM
|
||||
|
||||
---
|
||||
Подготовлено на основе текущей архитектуры FR24/noisemap и согласованных ограничений VM.
|
||||
## Нефункциональные требования
|
||||
- `capture` и `preprocess` должны быть отдельными контейнерами
|
||||
- `monitoring` должен быть отдельным контейнером
|
||||
- API нужен в первой compose-итерации
|
||||
|
||||
Reference in New Issue
Block a user