You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6.7 KiB

Triangulation Service

Сервис решает 3D-трилатерацию по 3 ресиверам:

  • центры сфер: координаты ресиверов;
  • радиусы сфер: расстояния, оцененные из RSSI с учетом частоты;
  • расчет идет по одинаковым частотам, которые есть у всех 3 ресиверов;
  • формируется таблица frequency_table (по каждой частоте отдельное решение);
  • выбирается итоговая частота selected_frequency_hz по минимальному rmse_m.

Что реализовано

  • Автоматический polling 3 входных серверов (http_sources).
  • Валидация входных payload с подробными ошибками.
  • API:
    • GET /health
    • GET /result
    • GET /frequencies
    • POST /refresh
    • GET /config
    • POST /config
  • UI (/ui) с:
    • входными данными ресиверов;
    • таблицей пересечений по частотам;
    • итоговой позицией;
    • статусом отправки на конечный сервер.
  • Опциональный push результата на внешний сервер (runtime.output_server).

Структура проекта

Docker Compose: test/prod режимы

docker-compose.yml разделен на профили:

  • test:

    • triangulation-test
    • receiver-r0, receiver-r1, receiver-r2
    • output-sink
  • prod:

    • triangulation-prod (читает ваш ./config.json)

Это позволяет легко отключить тестовый режим и перейти на реальные сервера.

Быстрый старт: Test Mode

Поднимает все контейнеры для end-to-end проверки:

  • 3 входных mock сервера с random данными;
  • основной сервис;
  • output-sink, принимающий отправленные результаты.
docker compose --profile test up --build

Открыть:

  • UI: http://localhost:8081/ui
  • Полный результат: http://localhost:8081/result
  • Частоты: http://localhost:8081/frequencies
  • Полученные output-sink данные: http://localhost:8080/latest

Остановить:

docker compose --profile test down

Быстрый старт: Prod Mode

  1. Создайте config.json из шаблона:
cp config.template.json config.json
  1. Заполните ваши реальные:
  • input.receivers[].source_url
  • input.receivers[].center
  • runtime.output_server
  1. Запустите:
docker compose --profile prod up --build

Остановить:

docker compose --profile prod down

Как проверить, что данные приходят и отправляются

В UI (/ui) видно:

  • блок Ресиверы: входящие samples;
  • таблица Таблица пересечений по частотам: решения по каждой общей частоте;
  • блок Отправка на конечный сервер: статус доставки (ok/error), HTTP-код, время, target.

Дополнительно:

  • GET /result возвращает output_delivery.
  • GET /frequencies тоже возвращает output_delivery.
  • GET http://localhost:8080/latest показывает, что именно принял output-sink.

Конфиг (основные поля)

Пример: config.template.json

Критичные поля:

  • input.mode: только "http_sources" для автосервиса.
  • input.receivers: ровно 3 ресивера.
  • input.aggregation: "median" или "mean".
  • runtime.poll_interval_s: период опроса.
  • runtime.output_server.enabled: push во внешний сервер.

Формат входных payload

Поддержка:

  • объект с measurements/samples/data;
  • или сразу массив измерений.

Измерение:

  • frequency_hz (или freq_hz/frequency/freq)
  • amplitude_dbm (или rssi_dbm/amplitude/rssi)

Пример:

{
  "receiver_id": "r0",
  "measurements": [
    { "frequency_hz": 433920000, "rssi_dbm": -61.5 },
    { "frequency_hz": 868100000, "rssi_dbm": -67.2 }
  ]
}

Если receiver_id передан, сервис сверяет его с ожидаемым receiver из конфига.

Валидация и ошибки некорректного контекста

Проверяется:

  • тип payload;
  • наличие измерений;
  • числовые и конечные значения;
  • frequency_hz > 0;
  • соответствие receiver_id при наличии;
  • наличие общих частот у всех 3 ресиверов.

Ошибки содержат:

  • source_url=...
  • номер строки row #...
  • проблемное поле.

Тесты

Запуск:

pytest -q

Покрытие:

  • математика триангуляции;
  • влияние частоты на RSSI->distance;
  • интеграция AutoService.refresh_once();
  • валидационные сценарии;
  • ошибки контекста (нет общих частот, bad field, receiver mismatch, network error, output reject).

Файл интеграционных тестов:

Локальный запуск без Docker

python service.py --config config.json

UI:

  • http://127.0.0.1:8081/ui