Start point for first iteration
This commit is contained in:
parent
844652c756
commit
433664dd03
16 changed files with 1476 additions and 75 deletions
356
Docs/start.md
Normal file
356
Docs/start.md
Normal file
|
|
@ -0,0 +1,356 @@
|
|||
# Оффлайн-карта с треком по WebSocket
|
||||
|
||||
**Стек:** Python (FastAPI) + WebSocket + React (Leaflet + Tauri)
|
||||
**Цель:** хранить карту полностью локально на устройстве и в реальном времени отображать движение по координатам GNSS.
|
||||
|
||||
## 1. Цели и общие требования
|
||||
|
||||
### 1.1. Функциональные цели
|
||||
|
||||
1. Отображать карту местности **без доступа к интернету**.
|
||||
2. Получать от устройства GNSS координаты в реальном времени.
|
||||
3. Передавать координаты в клиентское приложение через **WebSocket**, без периодических запросов.
|
||||
4. В React-приложении:
|
||||
1. показывать текущую позицию на карте.
|
||||
2. рисовать трек движения (историю точек).
|
||||
3. при необходимости в будущем — отображать дополнительные слои (контуры поля, границы, маршруты).
|
||||
|
||||
### 1.2. Нефункциональные требования
|
||||
|
||||
1. **Полный оффлайн:**
|
||||
1. ни карта, ни координаты не должны требовать внешних сервисов.
|
||||
2. все файлы тайлов карты находятся локально на диске устройства.
|
||||
2. **Устойчивость:**
|
||||
1. временные потери GNSS-сигнала не должны ломать интерфейс.
|
||||
2. разрыв WebSocket-соединения не должен ломать отображение данных с фронта.
|
||||
3. **Расширяемость:**
|
||||
1. добавлять новые типы данных (например, скорость, курс, высоту).
|
||||
2. подключать реальные GNSS-устройства вместо генераторов.
|
||||
3. добавлять слои на карту: полигоны, точки, маршруты.
|
||||
4. **Простота развёртывания:**
|
||||
1. backend и frontend должны запускаться стандартными командами.
|
||||
2. конфигурация (путь к карте, параметры GNSS) выносится в настройки.
|
||||
## 2. Архитектура решения
|
||||
|
||||
### 2.1. Высокоуровневая схема
|
||||
|
||||
Система логически делится на три части:
|
||||
1. **Сервис получения GNSS-данных (внутри backend)**
|
||||
- модуль в Python, который:
|
||||
1. подключается к приёмнику GNSS.
|
||||
2. читает сырые данные.
|
||||
3. преобразует их в нормализованный формат (широта, долгота, метки времени).
|
||||
2. **Backend-сервер (FastAPI)**
|
||||
- HTTP-интерфейсы:
|
||||
1. выдача тайлов карты по пути вида `/tiles/zoom/x/y.png`.
|
||||
2. вспомогательные эндпоинты (health-check, конфигурация и т.п.).
|
||||
- WebSocket-интерфейс:
|
||||
1. постоянное соединение с клиентом.
|
||||
2. отправка координат в режиме “push”.
|
||||
- работа с файловой системой:
|
||||
1. поиск нужных тайлов.
|
||||
2. выдача заглушки при отсутствии тайла.
|
||||
3. **Клиент (React + Leaflet)**
|
||||
- модуль карты:
|
||||
1. инициализацирует Leaflet-карту.
|
||||
2. использует локальный URL тайлов (через backend).
|
||||
- модуль трека:
|
||||
1. поддерживает подключение по WebSocket.
|
||||
2. хранит массив полученных точек.
|
||||
3. обновляет отображение карты при получении новых данных.
|
||||
#### Связи:
|
||||
1. GNSS → модуль GNSS backend’а → WebSocket → React → Leaflet.
|
||||
2. React → HTTP (через Leaflet) → backend → файловая система с тайлами.
|
||||
### 2.2. Логические компоненты
|
||||
|
||||
**Backend:**
|
||||
1. Модуль инициализации приложения FastAPI.
|
||||
2. Модуль выдачи тайлов:
|
||||
1. логика построения пути к тайлу по `{zoom}/{x}/{y}`.
|
||||
2. проверка наличия файла.
|
||||
3. выдача или оригинального тайла, или заглушки.
|
||||
3. Модуль GNSS:
|
||||
1. абстракция источника координат.
|
||||
2. возможность переключить данный источник:
|
||||
1. на реальное устройство.
|
||||
4. Модуль WebSocket:
|
||||
1. управление подключениями клиентов.
|
||||
2. цикл отправки координат.
|
||||
3. обработка разрывов соединения и ошибок.
|
||||
**Frontend:**
|
||||
5. Модуль подключения WebSocket:
|
||||
1. открытие соединения.
|
||||
2. обработка входящих сообщений с координатами.
|
||||
3. восстановление соединения при разрыве.
|
||||
6. Модуль управления треком:
|
||||
1. добавление точки в список.
|
||||
7. Модуль карты:
|
||||
1. инициализация Leaflet-карты.
|
||||
2. настройка источника тайлов на локальный backend.
|
||||
3. отображение маркера последней точки.
|
||||
## 3. Оффлайн-карта: концепция и хранение
|
||||
|
||||
### 3.1. Формат карты
|
||||
|
||||
В начальной версии планируется использовать **растровые тайлы**:
|
||||
1. карта заранее разбивается на набор изображений (PNG или JPEG).
|
||||
2. тайлы организованы в структуре каталогов по схеме:
|
||||
1. уровень масштабирования (zoom).
|
||||
2. координаты тайла по X и Y.
|
||||
Преимущества:
|
||||
3. Leaflet “из коробки” умеет работать с тайлами такого формата.
|
||||
4. не требуется дополнительный сервер картографических данных — достаточно отдавать файлы по HTTP.
|
||||
5. относительно просто генерировать карту для нужного региона с помощью внешних инструментов (QGIS, GDAL и др.).
|
||||
|
||||
### 3.2. Структура хранения тайлов
|
||||
|
||||
На уровне файловой системы тайлы лежат в диапазоне, например:
|
||||
|
||||
1. `tiles/10/567/321.png` — тайл уровня зума 10, координаты X=567, Y=321.
|
||||
2. `tiles/11/1134/643.png` — тот же район на другом зуме.
|
||||
|
||||
Backend ничего не знает о том, как эти тайлы были созданы, он:
|
||||
|
||||
1. получает значение zoom, x и y из URL.
|
||||
2. строит путь к файлу.
|
||||
3. проверяет наличие файла.
|
||||
4. отдаёт файл, если он есть.
|
||||
5. если файлы нет — отдаёт заранее подготовленную картинку-заглушку.
|
||||
|
||||
Таким образом, карта является полностью статичной, а логика backend — максимально простой.
|
||||
|
||||
### 3.3. Генерация и обновление карты
|
||||
|
||||
Это отдельный процесс, который выполняется вне основной системы:
|
||||
1. Выбирается необходимый регион (поля, районы полётов).
|
||||
2. В GIS-инструменте формируется растровая подложка.
|
||||
3. Эта подложка нарезается в тайлы нужных уровней масштабирования.
|
||||
4. Готовый набор тайлов копируется на устройство в папку `tiles/`.
|
||||
|
||||
В дальнейшем можно:
|
||||
|
||||
1. обновлять карту, подменяя содержимое `tiles/`.
|
||||
2. хранить несколько наборов карт (например, по сезонам) и включать нужный через конфиг.
|
||||
|
||||
## 4. Работа с координатами и GNSS
|
||||
|
||||
### 4.1. Источник данных
|
||||
|
||||
Фактически координаты приходят либо:
|
||||
1. от реального GNSS-приёмника, подключённого по:
|
||||
1. последовательному порту.
|
||||
2. USB.
|
||||
3. сетевому протоколу.
|
||||
2. либо от программного симулятора, который генерирует “виртуальный маршрут”.
|
||||
|
||||
Задача backend — предоставить единый интерфейс, не зависящий от конкретного железа.
|
||||
|
||||
### 4.2. Нормализация координат
|
||||
|
||||
Сырые данные могут быть в формате NMEA или другом специфичном виде. Модуль GNSS:
|
||||
|
||||
1. парсит входные данные.
|
||||
2. приводит координаты к стандартной системе:
|
||||
1. широта (latitude) в градусах.
|
||||
2. долгота (longitude) в градусах.
|
||||
3. опционально — высота, скорость, курс.
|
||||
3. добавляет метку времени (например, UNIX timestamp или ISO-строку).
|
||||
4. формирует структуру, удобную для отправки на фронт.
|
||||
|
||||
Важно, чтобы координаты были в той системе, которую ожидает Leaflet (обычно WGS84).
|
||||
|
||||
### 4.3. Частота обновления
|
||||
|
||||
1. Модуль GNSS определяет:
|
||||
1. как часто появляются новые точки.
|
||||
2. как часто обновлять данные на фронте:
|
||||
3. возможен вариант “как пришло — так отправили”.
|
||||
4. либо накопление точек и отправка пачками (например, раз в секунду).
|
||||
|
||||
Частота обновления — важный параметр, влияющий на:
|
||||
1. плавность трека.
|
||||
2. нагрузку на канал связи.
|
||||
3. нагрузку на фронт.
|
||||
|
||||
## 5. Потоки данных и жизненный цикл приложения
|
||||
|
||||
### 5.1. Запуск backend
|
||||
|
||||
1. При старте FastAPI:
|
||||
1. инициализирует конфигурацию (настройки путей, порты, параметры GNSS).
|
||||
2. проверяет наличие базовых директорий (`tiles/`, заглушка тайла).
|
||||
3. при необходимости пробует подключиться к GNSS-источнику.
|
||||
2. Запускается HTTP-сервер:
|
||||
1. обслуживает выдачу тайлов.
|
||||
2. отвечает на запросы.
|
||||
|
||||
### 5.2. Запуск frontend
|
||||
|
||||
1. React-приложение загружается в оболочке Tauri (Бинарник)
|
||||
2. После инициализации:
|
||||
1. открывается WebSocket-соединение с backend.
|
||||
2. инициализируется карта:
|
||||
1. начальный центр (по умолчанию либо по первой полученной точке).
|
||||
2. указание backend-урла тайлов.
|
||||
3. При успешном подключении по WebSocket:
|
||||
1. приложение начинает получать координаты.
|
||||
2. каждая новая точка добавляется в список.
|
||||
3. карта обновляет положение маркера и линии трека.
|
||||
|
||||
### 5.3. Реакция на ошибки и разрывы
|
||||
|
||||
1. Если WebSocket-соединение закрывается:
|
||||
1. фронт может попытаться переподключиться через интервалы.
|
||||
2. на карте можно оставить последнюю известную позицию.
|
||||
2. Если нет GNSS-данных:
|
||||
1. backend может отправлять специальные сообщения о состоянии (например, “нет сигнала”).
|
||||
2. фронт может отображать статичную карту без движения или соответствующее уведомление.
|
||||
3. Если тайл для карты отсутствует:
|
||||
1. backend отдаёт заглушку.
|
||||
2. на карте вместо участка появляется условный “серый” квадрат, но интерфейс остаётся рабочим.
|
||||
|
||||
## 6. Основные этапы разработки
|
||||
|
||||
### Этап 1. Подготовка окружения и структуры проекта
|
||||
|
||||
1. Создать общий репозиторий с двумя основными директориями: `backend` и `frontend`.
|
||||
2. Настроить базовую систему сборки и запуска:
|
||||
- для backend — запуск FastAPI через Uvicorn.
|
||||
- для frontend — сборщик (Vite + Tauri).
|
||||
### Этап 2. Скелет backend-приложения
|
||||
|
||||
1. Инициализировать приложение FastAPI.
|
||||
2. Добавить endpoint для проверки, что сервер поднялся.
|
||||
3. Настроить CORS так, чтобы frontend мог связаться с backend в локальной разработке
|
||||
|
||||
На этом этапе можно убедиться, что базовая связка “frontend - backend по HTTP” работает.
|
||||
|
||||
### Этап 3. Механизм выдачи тайлов
|
||||
|
||||
1. Определить директорию хранения тайлов (`tiles/`).
|
||||
2. Реализовать логику извлечения тайла по запросу вида `/tiles/{zoom}/{x}/{y}.png`.
|
||||
3. Добавить заглушку для отсутствующих тайлов.
|
||||
4. Прогнать простой тест: вручную запросить существующий и несуществующий тайл и убедиться, что:
|
||||
1. первый отдаётся корректно.
|
||||
2. второй отдаёт заглушку.
|
||||
|
||||
### Этап 4. Проработка GNSS-абстракции
|
||||
|
||||
1. Определить интерфейс модуля “источник координат”:
|
||||
1. формат выдаваемых данных.
|
||||
2. тип возвращаемой структуры (координаты + время).
|
||||
2. На этом этапе использовать **симулятор** вместо реального устройства:
|
||||
1. сделать виртуальную траекторию (линия, круг, восьмёрка и т.п.).
|
||||
2. выдавать новые точки с заданным интервалом.
|
||||
3. Важно: модуль должен быть реализован так, чтобы позже его можно было легко заменить реализацией, работающей с реальным железом.
|
||||
|
||||
### Этап 5. Добавление WebSocket-эндпоинта в backend
|
||||
|
||||
1. Создать WebSocket-обработчик:
|
||||
1. принимать подключение от клиента.
|
||||
2. при подключении запускать цикл, в котором:
|
||||
1. берётся следующая точка из GNSS-источника.
|
||||
2. отправляется на клиента.
|
||||
2. Обработать возможные сценарии:
|
||||
1. разрыв соединения клиентом.
|
||||
2. ошибки в процессе отправки.
|
||||
3. отключение GNSS-источника.
|
||||
|
||||
На этом этапе backend уже умеет:
|
||||
|
||||
1. выдавать тайлы.
|
||||
2. в реальном времени отдавать поток координат любому подключенному клиенту по WebSocket.
|
||||
|
||||
### Этап 6. Скелет frontend-приложения
|
||||
|
||||
1. Инициализировать React-приложение.
|
||||
2. Подготовить базовую структуру компонентов:
|
||||
1. основной компонент приложения.
|
||||
2. компонент карты.
|
||||
3. будущий модуль для WebSocket.
|
||||
3. Настроить запуск фронта и убедиться, что базовый “каркас” работает.
|
||||
|
||||
### Этап 7. Интеграция Leaflet в frontend
|
||||
|
||||
1. Подключить Leaflet и его React-обёртку.
|
||||
2. Создать компонент карты, который:
|
||||
1. инициализирует карту с некоторым стартовым центром.
|
||||
2. использует URL `http://localhost:8000/tiles/{z}/{x}/{y}.png` в качестве источника тайлов.
|
||||
3. Проверить:
|
||||
1. что при старте приложение отображает карту (в рамках подготовленной области).
|
||||
2. что при перемещении и масштабировании запросы к тайлам уходят на backend.
|
||||
|
||||
На этом этапе карта уже отображается локально, без участия внешних сервисов.
|
||||
|
||||
### Этап 8. Подключение WebSocket на frontend
|
||||
|
||||
1. Создать модуль, который:
|
||||
1. открывает WebSocket-соединение с backend’ом по адресу `ws://localhost:8000/ws/track`.
|
||||
2. слушает сообщения и добавляет новые координаты в локальное состояние приложения.
|
||||
2. Реализовать простую логику:
|
||||
1. хранить массив точек.
|
||||
2. по каждой новой точке:
|
||||
1. добавлять её в массив.
|
||||
2. обновлять центр карты.
|
||||
3. Связать модуль WebSocket с компонентом карты:
|
||||
1. передавать массив точек как пропсы.
|
||||
2. отображать:
|
||||
1. маркер последней точки.
|
||||
2. линию, соединяющую все точки (трек).
|
||||
|
||||
### Этап 9. Обработка ошибок и повышение устойчивости
|
||||
|
||||
1. Добавить обработку ошибок WebSocket на frontend:
|
||||
1. логировать причины разрыва.
|
||||
2. реализовать простую стратегию повторного подключения (например, попытка подключиться раз в несколько секунд при разрыве).
|
||||
2. На backend:
|
||||
1. в явном виде логировать ошибки GNSS и WebSocket.
|
||||
2. при необходимости — реализовать таймауты и защиту от зависаний.
|
||||
|
||||
### Этап 10. Подключение реального GNSS-устройства
|
||||
|
||||
1. Вместо симулятора реализовать модуль чтения реальных данных:
|
||||
1. добавить конфиг с параметрами подключения: порт, скорость, протокол.
|
||||
2. реализовать парсинг данных.
|
||||
2. Убедиться, что внешний интерфейс модуля GNSS не изменился:
|
||||
1. по-прежнему выдаются координаты в ожидаемом формате.
|
||||
3. Протестировать работу системы “в поле”:
|
||||
1. убедиться, что карта и трек корректно отражают реальное движение.
|
||||
|
||||
### Этап 11. Оптимизация и подготовка к эксплуатации
|
||||
|
||||
1. Оптимизация производительности:
|
||||
1. ограничение длины трека, если ожидается очень длинное использование без перезапуска.
|
||||
2. настройка частоты обновления координат.
|
||||
2. Упаковка приложения:
|
||||
1. вариант 1: backend + frontend как отдельные пакеты.
|
||||
2. вариант 2: объединение фронта и бека в один пакет.
|
||||
3. Документация по развёртыванию:
|
||||
1. пошаговое руководство по установке зависимостей.
|
||||
2. инструкции по замене тайлов карты.
|
||||
3. инструкции по смене GNSS-источника.
|
||||
|
||||
## 7. Возможные дальнейшие расширения
|
||||
|
||||
После того как базовый функционал будет устойчиво работать, его можно расширять:
|
||||
|
||||
1. **Отображение контуров полей**
|
||||
1. загрузка контуров из локальных файлов (например, GeoJSON).
|
||||
2. визуализация границ поля поверх карты.
|
||||
2. **Планирование маршрута**
|
||||
1. формирование линии проходов (полос) по ширине захвата.
|
||||
2. привязка трека к этим линиям (показ отклонения).
|
||||
3. **Запись и экспорт данных**
|
||||
1. сохранение трека в файл (например, GeoJSON, GPX).
|
||||
2. экспорт для дальнейшего анализа.
|
||||
4. **Конфигурация через UI**
|
||||
1. настройка масштабов карты, уровней тайлов.
|
||||
2. переключение наборов карт (разные сезоны, регионы).
|
||||
|
||||
## 8. Итоговая сводка
|
||||
|
||||
Суть решения: на устройстве устанавливается локальный сервер на Python (FastAPI), который одновременно:
|
||||
1. отдаёт статические файлы тайлов карты с диска,
|
||||
2. и по WebSocket непрерывно передаёт координаты из приёмника ГЛОНАСС.
|
||||
|
||||
React-приложение с Leaflet открывает эту локальную карту (через HTTP) и подписывается на WebSocket, чтобы в реальном времени обновлять положение маркера и трек движения. Всё — от карты до координат — живёт локально, не зависит от интернета и может работать в любых условиях, где есть только устройство, приёмник и локальная сеть (или даже один компьютер).
|
||||
Loading…
Add table
Add a link
Reference in a new issue