Initial commit: adacam-api v1.0.0
Clean Python Flask replacement for odc-api (434k lines Node.js → ~350 lines Python)
- GET /api/1/landmarks/last/{N} - last N detections from SQLite
- POST /api/1/landmarks - ingest detections + forward to AdaMaps
- GET /api/1/gnssConcise/latestValid - GPS fix from Redis
- GET /api/1/status - device status
- GET /api/1/deviceinfo - device identity
- GET /api/1/recording/frames/latest - latest frame path
No /api/1/cmd - that's the CVE, it's gone.
Includes:
- SQLite for local storage + offline queue
- Background thread for AdaMaps retry
- systemd service unit
- install.sh for device deployment
This commit is contained in:
parent
5dd91b0b15
commit
7acc5ab088
17 changed files with 507 additions and 1 deletions
83
adacam_api/forwarder.py
Normal file
83
adacam_api/forwarder.py
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
"""AdaMaps forwarding with offline queue."""
|
||||
import threading
|
||||
import time
|
||||
import requests
|
||||
from . import config, db
|
||||
|
||||
_thread = None
|
||||
_running = False
|
||||
|
||||
|
||||
def forward_detection(data):
|
||||
"""Forward a detection to AdaMaps, queue if offline."""
|
||||
api_url = config.get("adamaps_api", "https://api.adamaps.org")
|
||||
api_key = config.get("adamaps_key", "")
|
||||
device_id = config.get("device_id", "unknown")
|
||||
|
||||
payload = {
|
||||
"device_id": device_id,
|
||||
"detection": data,
|
||||
}
|
||||
|
||||
try:
|
||||
resp = requests.post(
|
||||
f"{api_url}/api/ingest",
|
||||
json=payload,
|
||||
headers={"X-AdaMaps-Key": api_key},
|
||||
timeout=10,
|
||||
)
|
||||
if resp.status_code == 200:
|
||||
return True
|
||||
except requests.RequestException:
|
||||
pass
|
||||
|
||||
# Queue for retry
|
||||
db.queue_forward(payload)
|
||||
return False
|
||||
|
||||
|
||||
def _retry_loop():
|
||||
"""Background thread to retry queued forwards."""
|
||||
global _running
|
||||
while _running:
|
||||
try:
|
||||
items = db.pop_queue(limit=20)
|
||||
if not items:
|
||||
time.sleep(30)
|
||||
continue
|
||||
|
||||
api_url = config.get("adamaps_api", "https://api.adamaps.org")
|
||||
api_key = config.get("adamaps_key", "")
|
||||
|
||||
for _, payload in items:
|
||||
try:
|
||||
resp = requests.post(
|
||||
f"{api_url}/api/ingest",
|
||||
json=payload,
|
||||
headers={"X-AdaMaps-Key": api_key},
|
||||
timeout=10,
|
||||
)
|
||||
if resp.status_code != 200:
|
||||
db.queue_forward(payload)
|
||||
except requests.RequestException:
|
||||
db.queue_forward(payload)
|
||||
time.sleep(5)
|
||||
|
||||
time.sleep(5)
|
||||
except Exception:
|
||||
time.sleep(30)
|
||||
|
||||
|
||||
def start_retry_thread():
|
||||
"""Start the background retry thread."""
|
||||
global _thread, _running
|
||||
if _thread is None or not _thread.is_alive():
|
||||
_running = True
|
||||
_thread = threading.Thread(target=_retry_loop, daemon=True)
|
||||
_thread.start()
|
||||
|
||||
|
||||
def stop_retry_thread():
|
||||
"""Stop the background retry thread."""
|
||||
global _running
|
||||
_running = False
|
||||
Loading…
Add table
Add a link
Reference in a new issue