Files
LoraMapTester/server/README.md
T
2026-06-11 08:38:08 +03:00

152 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# LoraTester Server
Единый HTTP-сервер для телеметрии LoRa, GPS устройств, истории статистики, треков и чата.
## Быстрый старт
```bash
cd server
python -m venv .venv
.venv\Scripts\activate # Windows
pip install -r requirements.txt
python flask_app.py
```
Откройте http://localhost:7634
## Переменные окружения
| Переменная | По умолчанию |
|------------|----------------|
| `LORATESTER_HOST` | `0.0.0.0` |
| `LORATESTER_PORT` | `7634` |
| `LORATESTER_DB` | `./loratester.db` |
| `LORATESTER_TELEMETRY_LIMIT` | `5000` (записей истории на устройство) |
| `LORATESTER_TRACK_POINTS_LIMIT` | `10000` (точек на один трек) |
| `LORATESTER_ELEVATION_URL` | `http://192.168.1.109:8085/v1/elevation` |
| `LORATESTER_ELEVATION_PROBE_TTL` | `60` (сек, кэш проверки доступности) |
| `LORATESTER_ELEVATION_TIMEOUT` | `8` (сек, таймаут HTTP к сервису высот) |
## Docker Compose
```bash
cd server
docker compose up -d --build
```
Проверка:
```bash
curl http://127.0.0.1:7634/api/health | jq
```
Ожидается `"elevation_ok": true` если локальный Open-Meteo доступен с хоста/контейнера.
Переопределить URL высот (`.env` рядом с `docker-compose.yml`):
```env
LORATESTER_ELEVATION_URL=http://192.168.1.109:8085/v1/elevation
```
БД хранится в volume `loratester-data` (`/data/loratester.db` внутри контейнера).
## Деплой (grigowashere.ru:7634)
```bash
cd /srv/storage/disk2/services/LoraTester/server
docker compose up -d --build
```
Или без Docker:
```bash
cd /srv/storage/disk2/services/LoraTester/server
pip install -r requirements.txt
export LORATESTER_DB=/srv/storage/disk2/services/LoraTester/loratester.db
export LORATESTER_ELEVATION_URL=http://192.168.1.109:8085/v1/elevation
uvicorn fastapi_app:app --host 0.0.0.0 --port 7634
```
После обновления кода **обязательно перезапустите** сервис. При старте выполняются миграции SQLite (`devices`, `telemetry.meta`, таблицы `tracks`).
Проверка:
```bash
curl http://127.0.0.1:7634/api/health
```
Ожидается `"db_ok": true`, `"schema_version": 4`, `"elevation_ok": true`.
Если БД создана вручную и схема битая (`no such table: devices` / `no such column: t.meta`):
1. Остановить сервис
2. `cp loratester.db loratester.db.bak`
3. Удалить `loratester.db` (или оставить бэкап и дать миграциям дописать колонки после рестарта с новым кодом)
4. Запустить снова — `init_db()` создаст полную схему
## API
### Телеметрия (только Android, заголовок `X-Lora-Client: android`)
- `POST /api/telemetry``{device_id, lat?, lon?, rssi?, meta?, fields?, role?, ts?}`
- `GET /api/devices` — последнее состояние устройств
- `GET /api/telemetry?device_id=&limit=&since=&until=&role=` — история (без `raw_frame`)
- `GET /api/stats/history?device_id=` — то же, alias
### Треки (запись с Android)
- `POST /api/tracks/start``{device_id}``{track_id}`
- `POST /api/tracks/{id}/points``{points: [{ts, lat, lon, altitude_gps?, rssi?, role?, meta?}]}`
- `POST /api/tracks/{id}/finish`
- `GET /api/tracks?device_id=`
- `GET /api/tracks/{id}` — метаданные + точки (высота terrain через локальный Open-Meteo)
### Команды (очередь на устройство)
- `POST /api/commands``{from_device_id, to_device_id, kind, payload?}`
`kind`: `at` (`payload.line` — одна строка, или `payload.lines` — массив макроса), `mode` (`payload.role`: TX/RX), `stats_push` (снимок meta/rssi/role/sf/bw)
`from_device_id`: `web` или `android-xxxxxxxx`
Макрос обычно: `S` (стоп TX/RX), затем `AT+FQ=`, `AT+PW=`, `AT+SF=`, `AT+BW=`, `AT+CR=`, `AT+PL=`, `AT+TM=`, при необходимости `AT+TX` / `AT+RX`.
### Профиль высот (веб, треки)
- `POST /api/elevation/profile``{points: [{lat, lon}], step_m?: 10}` → срез рельефа (локальный Open-Meteo)
- `GET /api/tracks/{id}/elevation-profile?step_m=10` — то же по сохранённому треку
- `GET /api/commands/pending?device_id=` — Android, доставка + `delivered_at`
- `GET /api/commands?to_device_id=&limit=` — история (веб)
### Синхронный трек (два устройства)
- `POST /api/paired-tracks/start``{device_ids?: [a,b], initiator?, device_id?}` → сессия `armed`, `start_at = now+3s`
- `GET /api/paired-tracks/active``{active, session?}`
- `POST /api/paired-tracks/ack` — Android: `{session_id, device_id, track_id}`
- `POST /api/paired-tracks/cancel``{session_id?}`
### Прочее
- `POST /api/chat``{device_id, text}`
- `GET /api/chat?since=0`
- `GET /api/health``{ok, db_ok, schema_version, database_path, elevation_ok, elevation_url, elevation_error}`
## FastAPI (прод)
```bash
uvicorn fastapi_app:app --host 0.0.0.0 --port 7634
```
Flask (`flask_app.py`) — тот же API для локальной разработки.
## Тесты
```bash
cd server
pip install httpx pytest
python -m pytest tests/ -v
```
## Android
URL: `http://grigowashere.ru:7634`. На карте: **Начать/Остановить трекинг пути** — точки с GPS, статистикой приёма и высотой (локальный Open-Meteo на сервере). Вкладка **Статистика** — история с сервера.
Telnet: `127.0.0.1:2727` — мост COM→telnet на устройстве.