20 KiB
20 KiB
Техническое задание
Система мониторинга транспорта в реальном времени
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)
Формат сообщений (сервер → клиент)
{
"type": "position_update",
"data": {
"vehicle_id": 1,
"lat": 55.7558,
"lon": 37.6173,
"speed": 45.5,
"heading": 180,
"timestamp": "2025-12-18T12:00:00Z"
}
}
{
"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_tsON (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_tsON (vehicle_id, timestamp DESC)idx_events_typeON (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+
Команды
# Клонировать репозиторий
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