132 lines
8.4 KiB
Markdown
132 lines
8.4 KiB
Markdown
# telemetry-dashboard
|
||
|
||
Одностраничный дэшборд телеметрии стратосферного зонда. Подключается к
|
||
WebSocket бэкенда stratoflights и отображает все поля MSG_BEACON в реальном
|
||
времени. Запускается рядом с leaflet_svelte (карта — там, здесь — приборы).
|
||
|
||
## Быстрый старт
|
||
|
||
```bash
|
||
npm install
|
||
|
||
# дев-сервер
|
||
npm run dev
|
||
|
||
# type-check + продакшн-сборка (статика в ./build)
|
||
npm run check
|
||
npm run build
|
||
```
|
||
|
||
Деплой идентичен leaflet_svelte: `build/` раздаётся любым статическим
|
||
сервером, fallback — `index.html`.
|
||
|
||
## Использование
|
||
|
||
В шапке указывается полный адрес WS-эндпоинта:
|
||
|
||
```
|
||
ws://<host>/api/ws/satellite/<satellite-uuid>/telemetry/
|
||
```
|
||
|
||
Адрес сохраняется в localStorage (дефолт можно задать через
|
||
`VITE_DEFAULT_WS_URL`, см. `.env.example`). Если URL совпадает с известным
|
||
шаблоном stratoflights, перед подключением подтягивается история по REST
|
||
(`/api/<uuid>/telemetry/`); для любого другого ws-адреса дэшборд просто
|
||
слушает поток. При обрыве связи — автопереподключение с экспоненциальным
|
||
бэкоффом (до 30 с), данные не сбрасываются, плитки затемняются, возраст
|
||
последнего пакета подсвечивается (янтарный > 15 с, красный > 60 с).
|
||
|
||
## Тестовый сервер
|
||
|
||
```bash
|
||
pip install websockets
|
||
python3 test_server.py --interval 1 --speedup 20 # полный полёт за ~9 минут
|
||
python3 test_server.py --speedup 200 --start 5900 # сразу перед разрывом шара
|
||
```
|
||
|
||
Эмулирует полный профиль полёта (подъём 5 м/с → разрыв на 30 км → спуск) в
|
||
точном формате пакетов бэкенда. Подключаться на `ws://localhost:8765/`.
|
||
|
||
## Демо бок-о-бок с leaflet_svelte (через Django, как в проде)
|
||
|
||
```bash
|
||
scripts/demo-stack.sh # Django :8000 + leaflet :5173 + дэшборд :5174 + станция
|
||
scripts/demo-stack.sh restart-flight # полёт заново: рестарт станции + чистка истории в БД
|
||
scripts/demo-stack.sh stop
|
||
```
|
||
|
||
Станция летит по `mock_prediction.json` из корня репозиториев (реальный
|
||
предикт) со случайным дрейфом до ±5 км. Каждый запуск/`restart-flight`
|
||
начинает полёт с нуля; после него нажми «Отключиться/Подключиться» в обоих
|
||
окнах, чтобы сбросить старые графики. Темп: `SPEEDUP=60 scripts/demo-stack.sh`.
|
||
|
||
Скрипт также поднимает **фейковый predictor на :8080** (захардкоженный адрес
|
||
`TawhiriClient` в Django), который отдаёт тот же `mock_prediction.json` —
|
||
поэтому «Рассчитать» в leaflet возвращает ровно ту траекторию, по которой
|
||
летит станция. Порядок для оверлея прогноза в слежении: `/predict` →
|
||
«Рассчитать» → перейти на «Слежение» **кликом в навбаре** (результат прогноза
|
||
живёт в памяти SPA и не переживает перезагрузку страницы) → выбрать рабочую
|
||
область в «Сравнении с прогнозом». Если на :8080 уже работает настоящий
|
||
predictor — скрипт его не трогает и прогнозы идут через него.
|
||
|
||
График отклонений сопоставляет точки по времени: при ускоренном полёте
|
||
(speedup > 1) времена телеметрии и прогноза расходятся — для честного
|
||
сравнения ставь дату запуска в форме «сейчас» и `SPEEDUP=1`.
|
||
|
||
Скрипт (адаптация leaflet_svelte/scripts/run-stack.sh под новые пути) сам
|
||
создаёт спутник и токен, запускает `test_server.py --push` как наземную
|
||
станцию и печатает UUID спутника. Дальше:
|
||
|
||
- **leaflet**: http://localhost:5173/track → логин demo/demo → вставить UUID →
|
||
«Подключиться»;
|
||
- **дэшборд**: http://localhost:5174/ → адрес
|
||
`ws://localhost:8000/api/ws/satellite/<UUID>/telemetry/` → «Подключиться»
|
||
(адрес запоминается в localStorage; история за прошедший полёт подтянется
|
||
по REST автоматически).
|
||
|
||
Оба окна читают один и тот же поток из Django. Если фронты уже запущены
|
||
руками — скрипт их не трогает, просто вставь UUID в оба окна.
|
||
|
||
## Пре-флайт аудит форматов
|
||
|
||
```bash
|
||
python3 field_audit.py # из корня telemetry-dashboard
|
||
```
|
||
|
||
Исполняемая сверка всей цепочки: математика firmware против контрольных
|
||
примеров из даташитов (MS5611, SHT4x), бит-точный round-trip
|
||
beacon → PN9/CRC → Deframer → parse → webclient, совпадение ключей payload и
|
||
имён флагов с нашим парсером. 9 групп проверок; любое расхождение — assert.
|
||
|
||
## Устройство
|
||
|
||
- **SvelteKit + adapter-static** (Svelte 5 runes, TypeScript) — тот же стек и
|
||
процесс сборки, что у leaflet_svelte; тот же брендовый Bootstrap
|
||
(`static/css/bootstrap.min.css`).
|
||
- **uPlot** для графиков — им же рендерит time series Grafana; ~22 КБ gzip,
|
||
потоковые обновления через `setData()`, курсор синхронизирован между всеми
|
||
графиками (`cursor.sync`).
|
||
- `src/lib/telemetry.ts` — чистый домен: парсинг пакета, производная
|
||
вертикальная скорость (окно 30 с, как у SondeHub), колонки для uPlot с
|
||
разрывами линий при пропаже связи > 60 с.
|
||
- `src/lib/store.svelte.ts` — WebSocket + реконнект + массив сэмплов.
|
||
- Пороги (батарея, спутники, возраст пакета, быстрый спуск) — константы в
|
||
начале `src/routes/+page.svelte`.
|
||
|
||
## Выбор визуализаций (по итогам ресёрча SondeHub/SatNOGS/Grafana-практик)
|
||
|
||
| Показатель | Форма |
|
||
|---|---|
|
||
| Возраст пакета | stat-плитка, верхний левый угол, порог 15/60 с |
|
||
| Высота GPS + баро | hero-график (две серии; баро выявляет отказ MS5611) + плитка |
|
||
| Верт. скорость | производная по GPS-высоте; плитка ▲/▼ + график с нулевой линией |
|
||
| Давление | график, лог-шкала (экспонента → прямая), гПа |
|
||
| Температуры ×3 | один график, три серии с прямой подписью |
|
||
| Влажность | график с фиксированной шкалой 0–100 % |
|
||
| Батарея | плитка + спарклайн, порог 3,5/3,3 В (3,3 = BATT_LOW_MV firmware) |
|
||
| Спутники | плитка + спарклайн, порог 4/6 |
|
||
| Координаты | моноширинная плитка, 5 знаков |
|
||
| 13 флагов | лампы с семантикой: OK-флаги зелёный/красный, состояния синий/серый, LOW_BATT/PYRO_ARMED — тревожные только когда взведены |
|
||
|
||
Радиальных gauge нет намеренно: ни один осмотренный боевой дэшборд
|
||
(sonik.space, SondeHub, SatNOGS) их не использует.
|