42ba6feed478101b7e5a45f780f9d83b87ccca79
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
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.
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
# 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
-- 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;
Description
Languages
Python
54.9%
HTML
44.8%
Dockerfile
0.3%