init
This commit is contained in:
477
transport/docs/TECHNICAL_SPECIFICATION.md
Normal file
477
transport/docs/TECHNICAL_SPECIFICATION.md
Normal file
@@ -0,0 +1,477 @@
|
||||
# Техническое задание
|
||||
## Система мониторинга транспорта в реальном времени
|
||||
|
||||
---
|
||||
|
||||
## 1. Общие сведения
|
||||
|
||||
| Параметр | Значение |
|
||||
|----------|----------|
|
||||
| Название проекта | Transport Monitoring System |
|
||||
| Тип | Учебный проект |
|
||||
| Версия ТЗ | 1.0 |
|
||||
| Дата | 2025-12-18 |
|
||||
| Срок разработки | 2 недели |
|
||||
| Frontend фреймворк | Vue 3 (выбран) |
|
||||
|
||||
---
|
||||
|
||||
## 2. Цели и задачи проекта
|
||||
|
||||
### 2.1 Цель
|
||||
Разработка веб-системы для мониторинга местоположения транспортных средств в реальном времени с визуализацией на карте и хранением истории перемещений.
|
||||
|
||||
### 2.2 Задачи
|
||||
- Отображение текущего положения транспорта на интерактивной карте
|
||||
- Обновление позиций в реальном времени (WebSocket)
|
||||
- Хранение и просмотр истории перемещений
|
||||
- Генерация событий (остановки, превышение скорости)
|
||||
- Симуляция данных для демонстрации работы системы
|
||||
|
||||
---
|
||||
|
||||
## 3. Технологический стек
|
||||
|
||||
### 3.1 Backend
|
||||
| Компонент | Технология | Версия |
|
||||
|-----------|------------|--------|
|
||||
| Язык | Python | 3.11+ |
|
||||
| Фреймворк | FastAPI | 0.104+ |
|
||||
| ORM | SQLAlchemy | 2.0+ |
|
||||
| Миграции | Alembic | 1.12+ |
|
||||
| База данных | PostgreSQL | 15+ |
|
||||
| WebSocket | FastAPI WebSockets | встроено |
|
||||
|
||||
### 3.2 Frontend
|
||||
| Компонент | Технология | Версия |
|
||||
|-----------|------------|--------|
|
||||
| Фреймворк | Vue 3 | 3.4+ |
|
||||
| Сборщик | Vite | 5.0+ |
|
||||
| Карты | Leaflet | 1.9+ |
|
||||
| UI-компоненты | Naive UI | 2.35+ |
|
||||
| HTTP-клиент | Axios | 1.6+ |
|
||||
|
||||
### 3.3 Инфраструктура
|
||||
| Компонент | Технология |
|
||||
|-----------|------------|
|
||||
| Контейнеризация | Docker + Docker Compose |
|
||||
| Reverse Proxy | Nginx 1.25+ |
|
||||
| Тайлы карты | OpenStreetMap |
|
||||
|
||||
### 3.4 Nginx (Reverse Proxy)
|
||||
Nginx выступает единой точкой входа:
|
||||
- `/` → статика Vue (production) или проксирование на Vite (development)
|
||||
- `/api/*` → проксирование на FastAPI backend
|
||||
- `/ws/*` → проксирование WebSocket на backend
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Nginx (:80) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ / → Frontend (статика или Vite dev:5173) │
|
||||
│ /api/* → Backend (FastAPI :8000) │
|
||||
│ /ws/* → Backend WebSocket (:8000) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Функциональные требования
|
||||
|
||||
### 4.1 Модуль "Диспетчер" (главный экран)
|
||||
|
||||
#### FR-1.1 Карта
|
||||
- [ ] Отображение интерактивной карты на базе Leaflet + OSM
|
||||
- [ ] Маркеры транспортных средств с иконками по типу (автобус, грузовик, легковой)
|
||||
- [ ] Всплывающая подсказка при наведении на маркер (название, скорость)
|
||||
- [ ] Центрирование карты по выбранному объекту
|
||||
|
||||
#### FR-1.2 Список объектов
|
||||
- [ ] Боковая панель со списком всех транспортных средств
|
||||
- [ ] Поиск/фильтрация по названию
|
||||
- [ ] Индикатор статуса: движется (зелёный), стоит (жёлтый), нет связи (серый)
|
||||
- [ ] Клик по объекту — выделение на карте + открытие карточки
|
||||
|
||||
#### FR-1.3 Карточка объекта
|
||||
- [ ] Название и тип ТС
|
||||
- [ ] Текущие координаты (lat, lon)
|
||||
- [ ] Скорость (км/ч)
|
||||
- [ ] Направление движения (heading)
|
||||
- [ ] Время последней точки
|
||||
- [ ] Статус (движется/стоит)
|
||||
|
||||
### 4.2 Модуль "История движения"
|
||||
|
||||
#### FR-2.1 Запрос истории
|
||||
- [ ] Выбор временного диапазона: 30 мин / 1 час / 24 часа / произвольный
|
||||
- [ ] Кнопка "Показать трек"
|
||||
|
||||
#### FR-2.2 Отображение трека
|
||||
- [ ] Полилиния маршрута на карте
|
||||
- [ ] Цветовая индикация скорости (опционально)
|
||||
- [ ] Маркеры начала и конца маршрута
|
||||
|
||||
#### FR-2.3 Таблица точек
|
||||
- [ ] Список точек: время, координаты, скорость
|
||||
- [ ] Клик по строке — центрирование карты на точке
|
||||
- [ ] Экспорт в CSV (опционально)
|
||||
|
||||
### 4.3 Модуль "Реалтайм обновления"
|
||||
|
||||
#### FR-3.1 WebSocket соединение
|
||||
- [ ] Автоматическое подключение при загрузке страницы
|
||||
- [ ] Переподключение при обрыве связи
|
||||
- [ ] Индикатор статуса соединения в UI
|
||||
|
||||
#### FR-3.2 Обновление данных
|
||||
- [ ] Плавное перемещение маркеров при получении новых координат
|
||||
- [ ] Обновление данных в карточке объекта
|
||||
- [ ] Обновление статусов в списке объектов
|
||||
|
||||
### 4.4 Модуль "События"
|
||||
|
||||
#### FR-4.1 Типы событий
|
||||
- [ ] `LONG_STOP` — остановка более N минут (настраиваемый порог)
|
||||
- [ ] `OVERSPEED` — превышение скорости (порог настраивается)
|
||||
- [ ] `CONNECTION_LOST` — нет данных более 5 минут
|
||||
|
||||
#### FR-4.2 Лента событий
|
||||
- [ ] Панель с последними событиями (10-20 штук)
|
||||
- [ ] Фильтр по типу события
|
||||
- [ ] Клик по событию — переход к объекту на карте
|
||||
|
||||
### 4.5 Модуль "Симулятор"
|
||||
|
||||
#### FR-5.1 Генерация данных
|
||||
- [ ] Python-скрипт для имитации движения N объектов
|
||||
- [ ] Реалистичное движение по координатам (не телепортация)
|
||||
- [ ] Случайные остановки и изменения скорости
|
||||
- [ ] Отправка данных через REST API или WebSocket
|
||||
|
||||
---
|
||||
|
||||
## 5. Архитектура системы
|
||||
|
||||
### 5.1 Общая схема
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ │
|
||||
│ Nginx │ :80
|
||||
│ (reverse proxy)│
|
||||
│ │
|
||||
└────────┬────────┘
|
||||
│
|
||||
┌──────────────────┼──────────────────┐
|
||||
│ /api, /ws │ / │
|
||||
▼ │ ▼
|
||||
┌─────────────────┐ │ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ │ │ │ │ │ │
|
||||
│ Симулятор │────▶ Backend │ │ Frontend │
|
||||
│ (Python) │POST│ (FastAPI) │ │ (Vue 3) │
|
||||
│ │ │ :8000 │ │ :5173 (dev) │
|
||||
└─────────────────┘ └────────┬────────┘ └─────────────────┘
|
||||
│
|
||||
│ SQL
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ │
|
||||
│ PostgreSQL │ :5432
|
||||
│ │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
### 5.2 Структура проекта
|
||||
```
|
||||
transport/
|
||||
├── docker-compose.yml
|
||||
├── docs/
|
||||
│ └── TECHNICAL_SPECIFICATION.md
|
||||
├── nginx/
|
||||
│ ├── nginx.conf # Основной конфиг
|
||||
│ ├── conf.d/
|
||||
│ │ └── default.conf # Конфиг сервера
|
||||
│ └── Dockerfile # (опционально, для кастомизации)
|
||||
├── backend/
|
||||
│ ├── Dockerfile
|
||||
│ ├── requirements.txt
|
||||
│ ├── alembic/
|
||||
│ │ └── versions/
|
||||
│ ├── alembic.ini
|
||||
│ ├── app/
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── main.py # FastAPI приложение
|
||||
│ │ ├── config.py # Настройки
|
||||
│ │ ├── database.py # Подключение к БД
|
||||
│ │ ├── models/
|
||||
│ │ │ ├── __init__.py
|
||||
│ │ │ ├── vehicle.py
|
||||
│ │ │ ├── position.py
|
||||
│ │ │ └── event.py
|
||||
│ │ ├── schemas/
|
||||
│ │ │ ├── __init__.py
|
||||
│ │ │ ├── vehicle.py
|
||||
│ │ │ ├── position.py
|
||||
│ │ │ └── event.py
|
||||
│ │ ├── routers/
|
||||
│ │ │ ├── __init__.py
|
||||
│ │ │ ├── vehicles.py
|
||||
│ │ │ ├── positions.py
|
||||
│ │ │ └── events.py
|
||||
│ │ ├── services/
|
||||
│ │ │ ├── __init__.py
|
||||
│ │ │ ├── event_detector.py
|
||||
│ │ │ └── websocket_manager.py
|
||||
│ │ └── websocket.py # WS эндпоинт
|
||||
│ └── simulator/
|
||||
│ └── run.py # Симулятор данных
|
||||
├── frontend/
|
||||
│ ├── Dockerfile
|
||||
│ ├── package.json
|
||||
│ ├── vite.config.js
|
||||
│ ├── index.html
|
||||
│ └── src/
|
||||
│ ├── main.js
|
||||
│ ├── App.vue
|
||||
│ ├── components/
|
||||
│ │ ├── MapView.vue
|
||||
│ │ ├── VehicleList.vue
|
||||
│ │ ├── VehicleCard.vue
|
||||
│ │ ├── TrackHistory.vue
|
||||
│ │ └── EventFeed.vue
|
||||
│ ├── composables/
|
||||
│ │ ├── useWebSocket.js
|
||||
│ │ └── useVehicles.js
|
||||
│ └── stores/
|
||||
│ └── vehicles.js
|
||||
└── README.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. API спецификация
|
||||
|
||||
### 6.1 REST API
|
||||
|
||||
#### Транспортные средства
|
||||
|
||||
| Метод | Эндпоинт | Описание |
|
||||
|-------|----------|----------|
|
||||
| GET | `/api/vehicles` | Список всех ТС |
|
||||
| GET | `/api/vehicles/{id}` | Информация о ТС |
|
||||
| POST | `/api/vehicles` | Создать ТС |
|
||||
| PUT | `/api/vehicles/{id}` | Обновить ТС |
|
||||
| DELETE | `/api/vehicles/{id}` | Удалить ТС |
|
||||
|
||||
#### Позиции
|
||||
|
||||
| Метод | Эндпоинт | Описание |
|
||||
|-------|----------|----------|
|
||||
| GET | `/api/vehicles/{id}/positions` | История позиций ТС |
|
||||
| POST | `/api/ingest/position` | Принять новую позицию |
|
||||
| GET | `/api/vehicles/{id}/last-position` | Последняя позиция ТС |
|
||||
|
||||
**Query параметры для `/api/vehicles/{id}/positions`:**
|
||||
- `from` — начало периода (ISO 8601)
|
||||
- `to` — конец периода (ISO 8601)
|
||||
- `limit` — максимум записей (default: 1000)
|
||||
|
||||
#### События
|
||||
|
||||
| Метод | Эндпоинт | Описание |
|
||||
|-------|----------|----------|
|
||||
| GET | `/api/events` | Список событий |
|
||||
| GET | `/api/vehicles/{id}/events` | События конкретного ТС |
|
||||
|
||||
**Query параметры для `/api/events`:**
|
||||
- `type` — тип события (LONG_STOP, OVERSPEED, CONNECTION_LOST)
|
||||
- `from` / `to` — временной диапазон
|
||||
- `limit` — максимум записей
|
||||
|
||||
### 6.2 WebSocket API
|
||||
|
||||
#### Подключение
|
||||
```
|
||||
ws://localhost/ws/positions
|
||||
```
|
||||
*(Nginx проксирует на backend:8000)*
|
||||
|
||||
#### Формат сообщений (сервер → клиент)
|
||||
```json
|
||||
{
|
||||
"type": "position_update",
|
||||
"data": {
|
||||
"vehicle_id": 1,
|
||||
"lat": 55.7558,
|
||||
"lon": 37.6173,
|
||||
"speed": 45.5,
|
||||
"heading": 180,
|
||||
"timestamp": "2025-12-18T12:00:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "event",
|
||||
"data": {
|
||||
"id": 123,
|
||||
"vehicle_id": 1,
|
||||
"type": "OVERSPEED",
|
||||
"payload": {"speed": 95, "limit": 60},
|
||||
"timestamp": "2025-12-18T12:00:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Структура базы данных
|
||||
|
||||
### 7.1 Таблица `vehicles`
|
||||
| Поле | Тип | Описание |
|
||||
|------|-----|----------|
|
||||
| id | SERIAL PRIMARY KEY | Идентификатор |
|
||||
| name | VARCHAR(100) NOT NULL | Название/номер ТС |
|
||||
| type | VARCHAR(50) | Тип: bus, truck, car |
|
||||
| created_at | TIMESTAMP | Дата создания |
|
||||
|
||||
### 7.2 Таблица `positions`
|
||||
| Поле | Тип | Описание |
|
||||
|------|-----|----------|
|
||||
| id | SERIAL PRIMARY KEY | Идентификатор |
|
||||
| vehicle_id | INTEGER FK | Ссылка на vehicles |
|
||||
| timestamp | TIMESTAMP NOT NULL | Время фиксации |
|
||||
| lat | DOUBLE PRECISION | Широта |
|
||||
| lon | DOUBLE PRECISION | Долгота |
|
||||
| speed | REAL | Скорость (км/ч) |
|
||||
| heading | REAL | Направление (0-360) |
|
||||
|
||||
**Индексы:**
|
||||
- `idx_positions_vehicle_ts` ON (vehicle_id, timestamp DESC)
|
||||
|
||||
### 7.3 Таблица `events`
|
||||
| Поле | Тип | Описание |
|
||||
|------|-----|----------|
|
||||
| id | SERIAL PRIMARY KEY | Идентификатор |
|
||||
| vehicle_id | INTEGER FK | Ссылка на vehicles |
|
||||
| timestamp | TIMESTAMP NOT NULL | Время события |
|
||||
| type | VARCHAR(50) NOT NULL | Тип события |
|
||||
| payload | JSONB | Дополнительные данные |
|
||||
|
||||
**Индексы:**
|
||||
- `idx_events_vehicle_ts` ON (vehicle_id, timestamp DESC)
|
||||
- `idx_events_type` ON (type)
|
||||
|
||||
---
|
||||
|
||||
## 8. Нефункциональные требования
|
||||
|
||||
### 8.1 Производительность
|
||||
- Система должна поддерживать минимум 100 одновременных объектов
|
||||
- Частота обновления позиций: 1 раз в 1-2 секунды на объект
|
||||
- Время отклика API: < 500 мс для 95% запросов
|
||||
|
||||
### 8.2 Надёжность
|
||||
- WebSocket должен автоматически переподключаться при обрыве
|
||||
- При недоступности БД — graceful degradation с логированием ошибок
|
||||
|
||||
### 8.3 Развёртывание
|
||||
- Запуск всей системы одной командой: `docker-compose up`
|
||||
- Автоматическое применение миграций при старте
|
||||
|
||||
### 8.4 Безопасность (упрощённо для учебного проекта)
|
||||
- CORS настроен для локальной разработки
|
||||
- Валидация входных данных на уровне Pydantic-схем
|
||||
- (Опционально) Базовая авторизация через API-ключ
|
||||
|
||||
---
|
||||
|
||||
## 9. Этапы разработки
|
||||
|
||||
### Этап 1: Инфраструктура
|
||||
- [ ] Настройка Docker Compose (Nginx + PostgreSQL + backend + frontend)
|
||||
- [ ] Конфигурация Nginx (проксирование /api, /ws, статика)
|
||||
- [ ] Базовая структура FastAPI приложения
|
||||
- [ ] Подключение к БД, настройка Alembic
|
||||
- [ ] Базовая структура Vue-приложения
|
||||
|
||||
### Этап 2: CRUD и карта
|
||||
- [ ] Модели и миграции для vehicles, positions
|
||||
- [ ] REST API для vehicles
|
||||
- [ ] Endpoint POST /ingest/position
|
||||
- [ ] Фронт: отображение карты с маркерами
|
||||
- [ ] Фронт: список объектов + карточка
|
||||
|
||||
### Этап 3: Реалтайм
|
||||
- [ ] WebSocket manager на бэкенде
|
||||
- [ ] Broadcast новых позиций всем клиентам
|
||||
- [ ] Фронт: подключение к WS, обновление маркеров
|
||||
- [ ] Симулятор: базовая версия
|
||||
|
||||
### Этап 4: История и события
|
||||
- [ ] GET /vehicles/{id}/positions с фильтрами
|
||||
- [ ] Модель events + детектор событий
|
||||
- [ ] Фронт: отображение трека на карте
|
||||
- [ ] Фронт: таблица точек + лента событий
|
||||
|
||||
### Этап 5: Финализация
|
||||
- [ ] Улучшение UI/UX
|
||||
- [ ] Доработка симулятора (реалистичные маршруты)
|
||||
- [ ] Тестирование под нагрузкой (100 объектов)
|
||||
- [ ] Документация для запуска и демонстрации
|
||||
|
||||
---
|
||||
|
||||
## 10. Запуск проекта
|
||||
|
||||
### Требования
|
||||
- Docker 20.10+
|
||||
- Docker Compose 2.0+
|
||||
|
||||
### Команды
|
||||
```bash
|
||||
# Клонировать репозиторий
|
||||
git clone <repo-url>
|
||||
cd transport
|
||||
|
||||
# Запустить всё
|
||||
docker-compose up --build
|
||||
|
||||
# Доступ (всё через Nginx на порту 80)
|
||||
# Приложение: http://localhost
|
||||
# API: http://localhost/api
|
||||
# API Docs: http://localhost/api/docs
|
||||
# WebSocket: ws://localhost/ws/positions
|
||||
|
||||
# Запустить симулятор (в отдельном терминале)
|
||||
docker-compose exec backend python -m simulator.run
|
||||
```
|
||||
|
||||
### Docker Compose сервисы
|
||||
| Сервис | Порт (внутренний) | Порт (внешний) | Описание |
|
||||
|--------|-------------------|----------------|----------|
|
||||
| nginx | 80 | 80 | Reverse proxy, точка входа |
|
||||
| backend | 8000 | - | FastAPI, доступен только через nginx |
|
||||
| frontend | 5173 (dev) | - | Vue dev server, доступен только через nginx |
|
||||
| postgres | 5432 | 5432* | База данных |
|
||||
|
||||
*Порт PostgreSQL открыт наружу для удобства разработки (подключение через IDE/DBeaver)
|
||||
|
||||
---
|
||||
|
||||
## 11. Критерии приёмки
|
||||
|
||||
| № | Критерий | Приоритет |
|
||||
|---|----------|-----------|
|
||||
| 1 | Карта отображается с маркерами объектов | Обязательно |
|
||||
| 2 | Позиции обновляются в реальном времени (WS) | Обязательно |
|
||||
| 3 | История движения показывается на карте | Обязательно |
|
||||
| 4 | Система запускается через docker-compose up | Обязательно |
|
||||
| 5 | Симулятор генерирует тестовые данные | Обязательно |
|
||||
| 6 | Лента событий отображается | Желательно |
|
||||
| 7 | Поддержка 100+ объектов без лагов | Желательно |
|
||||
| 8 | Экспорт истории в CSV | Опционально |
|
||||
|
||||
---
|
||||
|
||||
*Документ составлен: 2025-12-18*
|
||||
Reference in New Issue
Block a user