105 lines
2.3 KiB
Markdown
105 lines
2.3 KiB
Markdown
# aprs-collector
|
|
|
|
```
|
|
[Shack-LAN] [DMZ]
|
|
Direwolf AGW:8000
|
|
???
|
|
agw_forwarder.py ??????POST/Bearer????????? FastAPI :8080/ingest/rf ????????? TimescaleDB
|
|
???
|
|
rotate.aprs2.net??? (APRS-IS, outbound)
|
|
```
|
|
|
|
---
|
|
|
|
## DMZ ??? snabbstart
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
|
|
# Generera en API-nyckel
|
|
python3 -c "import secrets; print(secrets.token_hex(32))"
|
|
# Klistra in i .env som API_KEY
|
|
|
|
docker compose up -d
|
|
docker compose logs -f collector
|
|
```
|
|
|
|
S??tt en reverse proxy (Caddy/nginx) framf??r port 8080 om du vill ha TLS.
|
|
|
|
---
|
|
|
|
## Shack ??? agw-forwarder
|
|
|
|
Kopiera mappen `agw-forwarder/` till Direwolf-datorn.
|
|
|
|
```bash
|
|
pip3 install requests
|
|
|
|
export AGW_HOST=localhost
|
|
export AGW_PORT=8000
|
|
export COLLECTOR_URL=http://<dmz-ip>:8080
|
|
export API_KEY=<samma nyckel som i DMZ .env>
|
|
export STATION_CALL=SA6ANW-1
|
|
|
|
python3 agw_forwarder.py
|
|
```
|
|
|
|
### K??r som systemd-tj??nst
|
|
|
|
```bash
|
|
# Redigera agw-forwarder.service ??? fyll i COLLECTOR_URL och API_KEY
|
|
sudo cp agw-forwarder.service /etc/systemd/system/
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable --now agw-forwarder
|
|
journalctl -u agw-forwarder -f
|
|
```
|
|
|
|
---
|
|
|
|
## Resiliens
|
|
|
|
Forwardern har en intern k?? (2000 frames). Om DMZ ??r tillf??lligt on??bar buffras
|
|
frames i minnet och skickas n??r anslutningen ??terkommer. Vid omstart av forwardern
|
|
f??rsvinner buffrade frames ??? tillr??ckligt f??r de flesta avbrott.
|
|
|
|
---
|
|
|
|
## API
|
|
|
|
| Endpoint | Metod | Auth | Beskrivning |
|
|
|---|---|---|---|
|
|
| `/ingest/rf` | POST | Bearer | RF-frame fr??n forwarder |
|
|
| `/health` | GET | ??? | Liveness check |
|
|
|
|
Swagger UI: `http://<dmz-ip>:8080/docs`
|
|
|
|
---
|
|
|
|
## Nyttiga queries
|
|
|
|
```sql
|
|
-- Direkt-h??rda stationer senaste 7 dagarna
|
|
SELECT ts, src_call, lat, lon, path
|
|
FROM rf_frames
|
|
WHERE heard_direct = TRUE
|
|
AND ts > NOW() - INTERVAL '7 days'
|
|
ORDER BY ts DESC;
|
|
|
|
-- Digis som h??rts senaste 30 min (= "online")
|
|
SELECT src_call, MAX(ts) AS last_seen, COUNT(*) AS frames
|
|
FROM rf_frames
|
|
WHERE ts > NOW() - INTERVAL '30 minutes'
|
|
GROUP BY src_call
|
|
ORDER BY last_seen DESC;
|
|
|
|
-- T??ckningspunkter per rutn??tscell
|
|
SELECT
|
|
ROUND(lat::numeric, 2) AS grid_lat,
|
|
ROUND(lon::numeric, 2) AS grid_lon,
|
|
COUNT(*) AS hits
|
|
FROM rf_frames
|
|
WHERE heard_direct = TRUE
|
|
AND lat IS NOT NULL
|
|
GROUP BY grid_lat, grid_lon;
|
|
```
|