225 lines
16 KiB
Markdown
225 lines
16 KiB
Markdown
# Пункт управления NODE.DC
|
||
|
||
Универсальный браузерный пункт управления NODE.DC на React 19, TypeScript и
|
||
Vite. Приложение задаёт общую операторскую оболочку для аппаратов, сенсоров,
|
||
наблюдения, миссий и записей. XGRIDS/LixelKity K1 является первым реальным
|
||
device adapter, но структура интерфейса от него не зависит.
|
||
|
||
Внутри пространственной рабочей поверхности встроен открытый Rerun Web Viewer.
|
||
Это self-hosted frontend-компонент из npm-пакета `@rerun-io/web-viewer`, а не
|
||
переход во внешний облачный интерфейс. Сам браузерный компонент, однако, должен
|
||
получить совместимый источник RRD или Rerun gRPC.
|
||
|
||
## Текущее состояние
|
||
|
||
| Контур | Состояние | Что это означает |
|
||
| --- | --- | --- |
|
||
| NODE.DC fixed shell | Реализован | Header, навигация по разделам, рабочая поверхность, окна и инспекторы работают в одном приложении. |
|
||
| Локальный control plane | Реализован | React получает состояние и выполняет операции через FastAPI REST и WebSocket на loopback. |
|
||
| K1 BLE → Wi-Fi | Реализован | Реальный BLE-поиск всех видимых устройств и одна подтверждённая provisioning-запись выбранному устройству. |
|
||
| K1 live/replay MQTT | Реализован | Read-only приём, raw-first сохранение, декодирование облака точек и позы, реальные метрики. |
|
||
| Legacy Foxglove adapter | Реализован | Текущий Python runtime публикует декодированные K1 данные в локальный Foxglove WebSocket. Это проверенный диагностический backend, а не продуктовый UI. |
|
||
| Встроенный Rerun Viewer | Реализован | Открывает назначенный RRD по HTTP(S) или совместимый Rerun gRPC/proxy source внутри Control Station. |
|
||
| Автоматический MQTT → Rerun | **Не реализован** | Запуск K1 live/replay пока не создаёт RRD и не подаёт данные во встроенный Rerun viewport. Нужен отдельный stream adapter. |
|
||
| Контролы сцены → Rerun Blueprint | **Не реализованы** | Размер точек, палитра, накопление, слои, проекция, timeline и компоновка пока являются честным UI-контрактом и состоянием текущего сеанса. |
|
||
| Камеры, карты и миссии | Интерфейс готов | Серверная логика и реальные каналы для этих рабочих поверхностей ещё не подключены. |
|
||
|
||
Приложение не генерирует демонстрационное облако, траекторию, кадры или
|
||
метрики. Если реальных данных нет, область сцены остаётся пустой, а числовые поля
|
||
показывают `—`.
|
||
|
||
## Архитектура данных
|
||
|
||
```text
|
||
NODE.DC Control Station в браузере
|
||
├── control plane
|
||
│ └── REST /api/* + WebSocket /api/events
|
||
│ └── FastAPI на 127.0.0.1:8000
|
||
│ ├── CoreBluetooth: discovery и reviewed Wi-Fi provisioning
|
||
│ └── live/replay session runtime
|
||
│
|
||
├── текущий K1 preview path — legacy adapter
|
||
│ └── K1 MQTT :1883, read-only
|
||
│ ├── raw .k1mqtt + metadata + SHA-256 сохраняются первыми
|
||
│ └── protobuf/LZ4 decoder
|
||
│ └── Foxglove bridge → локальный WebSocket
|
||
│
|
||
└── продуктовая пространственная сцена
|
||
└── встроенный @rerun-io/web-viewer
|
||
└── RRD URL или Rerun gRPC/proxy source
|
||
```
|
||
|
||
Между декодером K1 и Rerun Viewer сейчас нет автоматической стрелки. Поля
|
||
`foxglove_ws_url` и `foxglove_viewer_url` ещё присутствуют в API только потому,
|
||
что Python runtime продолжает поднимать проверенный legacy adapter. Пункт
|
||
управления не использует их как основную поверхность визуализации.
|
||
|
||
## Фиксированная оболочка
|
||
|
||
Shell собран из локальных NODE.DC UI packages и сохраняет одну структуру для
|
||
всех функциональных модулей:
|
||
|
||
1. `AppHeader` — марка NODE.DC, выбор архитектурного раздела и состояние
|
||
локального backend.
|
||
2. `AdminNavigationPanel` — контекст аппарата и список рабочих поверхностей
|
||
выбранного раздела.
|
||
3. `LandingStage` — стартовая ситуационная поверхность и быстрые переходы.
|
||
4. `ApplicationPanel` — единый контейнер активной рабочей поверхности.
|
||
5. `Window` и `Inspector` — источник, отображение, слои и компоновка без
|
||
раскрытия внутренних панелей визуального движка.
|
||
|
||
Встроенный Rerun Viewer работает как canvas внутри этой оболочки. Его верхняя,
|
||
blueprint-, selection- и time-панели скрыты, чтобы продуктовые действия жили в
|
||
Control Station. Это ещё не означает, что все продуктовые контролы уже связаны
|
||
с API Rerun: текущая граница явно показана статусом `Интерфейс готов`.
|
||
|
||
## Архитектурные разделы
|
||
|
||
Навигация описана данными в `src/productModel.ts`, а не зашита в разметку каждой
|
||
страницы.
|
||
|
||
| Раздел | Назначение |
|
||
| --- | --- |
|
||
| Центр | Оперативный обзор, состояние контура и активность оператора. |
|
||
| Парк | Аппараты, текущее устройство, сенсоры и конфигурации борта. |
|
||
| Наблюдение | Пространственная сцена, камеры, карта, объекты, телеметрия и время. |
|
||
| Миссии | Планировщик, маршруты, сценарии и исполнение. Командный backend отключён. |
|
||
| Данные | Сессии, потоки, сущности, playback и экспорт доказательств. |
|
||
| Система | Модули, интеграции, сеть, аудит и настройки платформы. |
|
||
|
||
Карточки возможностей имеют четыре честных уровня: работает сейчас, готово к
|
||
источнику, интерфейсный контракт и последующий этап. Каталог не следует читать
|
||
как утверждение, что для каждой карточки уже существует backend.
|
||
|
||
## Установка, проверка, сборка и запуск
|
||
|
||
Требуются Node.js 20 или новее, `uv` и соседний checkout
|
||
`NODEDC_DESIGN_GUIDELINE`: зависимости `@nodedc/*` подключены к нему через
|
||
локальные `file:` пути. Python устанавливается только в `.venv` репозитория.
|
||
|
||
Канонический путь от корня репозитория:
|
||
|
||
```bash
|
||
cd /Users/dcconstructions/Downloads/mnt/NODEDC/NDC_xgrids-k1-connector
|
||
uv sync --group dev
|
||
|
||
cd apps/k1-viewer
|
||
npm install
|
||
npm run typecheck
|
||
npm run build
|
||
|
||
cd ../..
|
||
uv run k1link serve
|
||
```
|
||
|
||
Открыть `http://127.0.0.1:8000`. Команда `serve` отдаёт собранный `dist/` и
|
||
локальный API. Она намеренно привязана только к `127.0.0.1`; LAN bind не
|
||
предусмотрен, потому что endpoint подключения кратковременно принимает пароль
|
||
Wi-Fi.
|
||
|
||
Для разработки интерфейса после запуска backend:
|
||
|
||
```bash
|
||
cd apps/k1-viewer
|
||
npm run dev
|
||
```
|
||
|
||
Vite слушает `http://127.0.0.1:5173` и проксирует `/api` и `/api/events` на
|
||
`http://127.0.0.1:8000`. Другой локальный backend можно указать переменной
|
||
`VITE_API_TARGET`. Preview production-сборки запускается командой
|
||
`npm run preview` на `http://127.0.0.1:4173`.
|
||
|
||
## Операторский путь для текущего K1 adapter
|
||
|
||
1. Запустить `uv run k1link serve` и открыть Control Station.
|
||
2. Выбрать **Парк → Локальное устройство**.
|
||
3. Включить K1, дождаться стабильного индикатора и подтвердить это в форме.
|
||
4. Нажать **Показать все BLE-устройства**. Интерфейс показывает полный результат
|
||
шестисекундного поиска; метка совместимости является подсказкой, выбор делает
|
||
оператор.
|
||
5. Ввести SSID и пароль существующей сети и явно запустить подключение. Это одна
|
||
reviewed provisioning-запись без автоматических повторов.
|
||
6. Запустить live-приём по определённому адресу K1 либо replay локального
|
||
`.k1mqtt`/проверенного TSV. Физическое сканирование K1 запускается и
|
||
останавливается подтверждённым двойным нажатием кнопки устройства.
|
||
7. Состояние, частота, число точек, задержка и пропуски preview появятся только
|
||
после прихода реальных данных.
|
||
|
||
Этот путь запускает существующий MQTT/Foxglove runtime. Чтобы увидеть тот же
|
||
живой K1 поток во встроенной пространственной сцене, нужно сначала реализовать и
|
||
запустить MQTT→Rerun stream adapter; одного запуска live-сессии сейчас
|
||
недостаточно.
|
||
|
||
## Источники Rerun
|
||
|
||
В **Наблюдение → Пространственная сцена → Источник** принимается URL, который
|
||
понимает `@rerun-io/web-viewer` версии, зафиксированной в `package.json`:
|
||
|
||
```text
|
||
rerun+http://127.0.0.1:9876/proxy
|
||
http://127.0.0.1:8080/recording.rrd
|
||
https://example.internal/recording.rrd
|
||
```
|
||
|
||
- `rerun+http://…/proxy` — живой Rerun gRPC source через доступный браузеру
|
||
proxy;
|
||
- `http(s)://…/recording.rrd` — RRD-запись по HTTP(S);
|
||
- версия RRD должна быть совместима с версией Web Viewer;
|
||
- URL хранится только в состоянии текущей страницы;
|
||
- ошибка запуска показывается в viewport, без подстановки фиктивных данных.
|
||
|
||
После готовности Viewer выбор Rerun entity возвращает `entityPath` и имя view в
|
||
оболочку. Продуктовые настройки отображения, custom timeline, переключатель
|
||
2D/3D/карты и сохранение RBL пока не вызывают Blueprint/playback API. Черновик
|
||
компоновки фиксируется только в памяти текущей страницы и не записывается на
|
||
диск.
|
||
|
||
## Контракт локального API
|
||
|
||
| Метод | Route | Тело / назначение |
|
||
| --- | --- | --- |
|
||
| `GET` | `/api/health` | Проверка локального сервиса. |
|
||
| `GET` | `/api/state` | Авторитетный snapshot состояния. |
|
||
| `POST` | `/api/ble/scan` | `{ "duration_seconds": 6 }`. |
|
||
| `POST` | `/api/connect` | `{ "device_id", "ssid", "password" }`. |
|
||
| `POST` | `/api/session/live` | Опционально `{ "host", "duration_seconds" }`. |
|
||
| `POST` | `/api/session/replay` | `{ "path", "speed", "loop" }`. |
|
||
| `POST` | `/api/session/stop` | Остановка активного источника. |
|
||
| `WS` | `/api/events` | Периодические snapshots для live UI. |
|
||
|
||
`/api/state` и изменяющие состояние ответы могут вернуть snapshot напрямую или
|
||
как `{ "state": { ... } }`. Текущие поля включают `phase`, `message`, `devices`,
|
||
`selected_device_id`, `k1_ip`, `source_mode`, `metrics` и legacy-поля
|
||
`foxglove_ws_url`/`foxglove_viewer_url`. OpenAPI доступен по `/api/docs`.
|
||
|
||
## Карта исходников frontend
|
||
|
||
| Файл | Ответственность |
|
||
| --- | --- |
|
||
| `src/App.tsx` | Fixed shell, выбор разделов и окна source/display/layers/layout. |
|
||
| `src/productModel.ts` | Архитектурные разделы, рабочие поверхности и уровни готовности. |
|
||
| `src/workspaces/DeviceWorkspace.tsx` | Реальный K1 BLE/Wi-Fi/live/replay adapter UI. |
|
||
| `src/workspaces/Workspaces.tsx` | Оперативный обзор, spatial viewport и остальные продуктовые поверхности. |
|
||
| `src/components/RerunViewport.tsx` | Жизненный цикл встроенного Rerun Web Viewer и selection events. |
|
||
| `src/api.ts` | REST/WebSocket контракт с FastAPI. |
|
||
| `src/useK1Console.ts` | Состояние backend, polling, события и действия оператора. |
|
||
| `src/sceneSettings.ts` | Типизированный UI-профиль пространственной сцены. |
|
||
| `src/presentation.ts` | Русские подписи фаз и форматирование реальных метрик. |
|
||
| `src/messages.ts` | Обезличивание и локализация технических сообщений в пользовательском интерфейсе. |
|
||
| `src/styles.css`, `src/styles/*` | Компоновка shell и рабочих поверхностей. |
|
||
|
||
## Safety и чувствительные данные
|
||
|
||
- Control Station и credential endpoint доступны только на loopback.
|
||
- Пароль Wi-Fi находится только в React memory, передаётся в JSON POST body,
|
||
очищается после успешного ответа и не сохраняется в URL/local storage.
|
||
- BLE-подключение выполняет только отдельно рассмотренную provisioning-запись;
|
||
случайные GATT writes и автоматические повторы запрещены.
|
||
- MQTT live/replay не публикует команды устройству. Запуск и остановка
|
||
физического сканирования остаются за кнопкой K1.
|
||
- Live-сессии сначала сохраняют сырые сообщения, затем формируют preview. При
|
||
перегрузке preview может быть отброшен, raw evidence сохраняется.
|
||
- `sessions/` игнорируется Git и может содержать адреса, идентификаторы,
|
||
траекторию и карту помещения. В репозиторий попадают только redacted manifests
|
||
и безопасная документация.
|