8.9 KiB
Triangulation Service
Сервис автоматически собирает RSSI-измерения с нескольких входных серверов (ресиверов), группирует данные по одинаковым частотам и рассчитывает 3D-положение источника через пересечение сфер (трилатерация).
Каждый ресивер задается:
- координатами
center(центр сферы), - измерениями
RSSI + частота(для расчета радиуса через модель распространения), - URL источника входных данных.
Сервис:
- ведет актуальную таблицу решений по каждой общей частоте,
- выбирает итоговое лучшее решение по минимальному
rmse_m, - отправляет компактный результат на один или несколько выходных серверов,
- отдает API + веб-интерфейс для мониторинга и настройки.
Ключевые возможности
- Автоматический polling входных серверов (
input.mode = "http_sources"). - Поддержка
N >= 3входных ресиверов. - Расчет по общим частотам, которые есть минимум у 3 ресиверов и разрешены в
input.receivers[].frequencies_mhz. - Поддержка общего фильтра входа
input.default_input_filterи override per-receiver (input_filter). - Поддержка нескольких выходных серверов
runtime.output_servers[]с настройкой по имени и IP. - Горячее применение нового конфига через
POST /config(без ручного рестарта процесса). - Защита write-endpoints токеном (
runtime.write_api_token). - Русскоязычный UI (
/ui) с вкладками: обзор, частоты, ресиверы, доставка, серверы, JSON-конфиг. - Интеграционные и юнит-тесты.
Структура проекта
- service.py — основной автосервис, API, статика UI.
- triangulation.py — математика трилатерации и сетевой отправки.
- config.template.json — шаблон основного конфига.
- web/index.html, web/app.js, web/styles.css — веб-интерфейс.
- docker-compose.yml — профили test/prod.
- docker/config.docker.test.json — тестовый docker-конфиг.
- docker/mock_receiver.py — генератор входных тестовых данных.
- docker/mock_output_sink.py — тестовый приемник выходных payload.
- test_service_integration.py, test_triangulation.py — тесты.
- docs/API.md — подробный API.
- docs/CONFIG_REFERENCE.md — справочник параметров конфига.
- docs/JSON_EXAMPLES.md — шаблоны JSON.
Быстрый старт
Вариант 1: Docker (рекомендуется)
Тестовый режим (все контейнеры: 3 mock-входа + сервис + mock-выход):
docker compose --profile test up --build -d
Проверить:
- UI:
http://127.0.0.1:38081/ui - Health:
http://127.0.0.1:38081/health - Result:
http://127.0.0.1:38081/result - Frequencies:
http://127.0.0.1:38081/frequencies
Остановить:
docker compose --profile test down
Прод-режим (ваш config.json):
- Создайте
config.jsonиз шаблона:
cp config.template.json config.json
- Заполните реальные URL/координаты/выходные серверы.
- Запустите:
docker compose --profile prod up --build -d
Доступ:
- UI:
http://127.0.0.1:38082/ui - API:
http://127.0.0.1:38082/*
Остановить:
docker compose --profile prod down
Вариант 2: Локальный запуск Python
Ubuntu:
bash setup.sh
source .venv/bin/activate
python service.py --config config.json
Windows PowerShell:
./setup.ps1
.\.venv\Scripts\Activate.ps1
python service.py --config config.json
Веб-интерфейс
Открыть: http://<host>:<port>/ui
Что доступно:
- обзор итоговой позиции,
- таблица всех частотных решений,
- просмотр сырых данных ресиверов и статуса доставки,
- настройка входных/выходных серверов (добавление/удаление, имена, URL, IP),
- редактирование сырого JSON-конфига,
- сохранение конфига в рантайме через API.
Примечание: после POST /config сервис применяет конфиг автоматически (applied: true, restart_required: false).
API (кратко)
GET /health— состояние сервиса.GET /result— последнее итоговое решение + delivery status.GET /frequencies— таблица решений по частотам + delivery status.POST /refresh— принудительное обновление.GET /config— текущий конфиг (с редактированием секрета токена).POST /config— валидация + применение + попытка сохранения в файл.
Полные примеры запросов/ответов: docs/API.md.
Конфигурация
Базовый шаблон: config.template.json
Ключевые блоки:
model— радиомодель (RSSI -> расстояние).solver— параметры решателя сфер.input— источники входных данных, фильтры, агрегация.runtime— HTTP сервис, polling, write token, выходные серверы.
Важно по частотам:
- для каждого входного сервера задайте
input.receivers[].frequencies_mhz; - сервис использует в расчёте только частоты из конфигурации ресиверов.
Полное описание параметров: docs/CONFIG_REFERENCE.md.
Форматы JSON
Поддерживаются:
- компактный формат входа (
samples+f_mhz/rssi), - legacy-алиасы полей (
measurements,data,frequency_hz,rssi_dbmи др.), - минимальный выходной payload на конечные серверы:
xyz
Готовые шаблоны: docs/JSON_EXAMPLES.md.
Безопасность write-endpoints
Чтобы ограничить изменение состояния, задайте:
{
"runtime": {
"write_api_token": "change-me"
}
}
Тогда POST /refresh и POST /config требуют один из заголовков:
X-API-Token: <token>Authorization: Bearer <token>
GET endpoints доступны без токена.
Тесты
Запуск:
pytest -q
Сценарии покрывают:
- корректность трилатерации и преобразования RSSI,
- валидацию payload и граничные случаи,
- ошибки некорректного контекста,
- output delivery,
- безопасность API,
- горячее применение конфига,
- multi-input/multi-output поведение.
Диагностика
Ошибка: port is already allocated
Значит локальный порт уже занят (например, 8080 или 38081).
Решения:
- остановить конфликтующий сервис,
- изменить публикацию порта в
docker-compose.yml.
Ошибка: Config file not found
Проверьте путь в аргументе --config и наличие файла внутри контейнера/хоста.
Лицензия
Если нужна отдельная лицензия, добавьте файл LICENSE и разделите условия использования.