478 lines
20 KiB
Markdown
478 lines
20 KiB
Markdown
# Техническое задание
|
||
## Система мониторинга транспорта в реальном времени
|
||
|
||
---
|
||
|
||
## 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*
|