Connecter une station

Guide d'intégration — API ingest NowYouSea

Sommaire

1. Vue d'ensemble

La station (Raspberry Pi, ESP32, laptop terrain) envoie ses données en HTTPS vers nowyousea.fr. Le modèle est PUSH uniquement : la station POST, le serveur stocke et diffuse en temps réel.

Station / Pi  →  POST HTTPS  →  nowyousea.fr  →  /live/

Quatre canaux de données disponibles : GPS, Audio, Power, System. Chaque canal est indépendant, vous pouvez n'en implémenter qu'un seul.

2. Authentification

Header Authorization Bearer

Toutes les requêtes ingest requièrent un token Bearer dans le header HTTP :

Authorization: Bearer <TON_TOKEN_INGEST>
Token : Demander à Flag pour obtenir un token valide. Ne jamais écrire le token en dur dans du code versionné — utiliser une variable d'environnement.

3. Endpoints ingest

GPS

POST
https://nowyousea.fr/api/ingest/gps
ChampTypeRequisDescription
rigstringOuiIdentifiant unique de la station
latfloatOuiLatitude décimale (WGS84)
lonfloatOuiLongitude décimale (WGS84)
altfloatNonAltitude en mètres
speedfloatNonVitesse en m/s
headingfloatNonCap en degrés (0–360)
satsintNonNombre de satellites utilisés
fixboolNonFix GPS valide (true/false)
tsintNonTimestamp epoch millisecondes (auto si absent)
curl -X POST https://nowyousea.fr/api/ingest/gps \
  -H "Authorization: Bearer <TON_TOKEN_INGEST>" \
  -H "Content-Type: application/json" \
  -d '{"rig":"rig-candoo","lat":47.65,"lon":-2.76,"alt":5.2,"sats":8,"fix":true}'
Réponse
{"status":"ok","rig":"rig-candoo","stored":1}

Audio

POST
https://nowyousea.fr/api/ingest/audio?rig=<rig>&format=wav|flac&ts=<ms?>

Le body est les bytes audio bruts. Le stream continu est supporté : envoyer des chunks de 2-3 secondes toutes les 2 secondes.

ParamètreTypeRequisDescription
rigstring (query)OuiIdentifiant unique de la station
formatstring (query)Ouiwav ou flac
tsint (query)NonTimestamp epoch ms du début du chunk
bodybytesOuiBytes audio bruts (WAV ou FLAC)
WAV : Utiliser PCM standard (format code 1). Le format WAVE_FORMAT_EXTENSIBLE n'est PAS supporté.
curl -X POST "https://nowyousea.fr/api/ingest/audio?rig=rig-candoo&format=wav" \
  -H "Authorization: Bearer <TON_TOKEN_INGEST>" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @chunk.wav
Réponse
{"status":"ok","samples":48000,"duration_s":1.0}

Power

POST
https://nowyousea.fr/api/ingest/power
ChampTypeRequisDescription
rigstringOuiIdentifiant unique de la station
voltagefloatOuiTension en volts (V)
currentfloatOuiCourant en ampères (A) — négatif=décharge, 0 accepté
powerfloatOuiPuissance en watts (W)
chipstringNonRéférence du capteur (ex: INA219)
tsintNonTimestamp epoch millisecondes (auto si absent)
curl -X POST https://nowyousea.fr/api/ingest/power \
  -H "Authorization: Bearer <TON_TOKEN_INGEST>" \
  -H "Content-Type: application/json" \
  -d '{"rig":"rig-candoo","voltage":12.4,"current":0.85,"power":10.5,"chip":"INA219"}'
Réponse
{"status":"ok","rig":"rig-candoo","stored":1}

System

POST
https://nowyousea.fr/api/ingest/system
ChampTypeRequisDescription
rigstringOuiIdentifiant unique de la station
cpu_pctfloatOuiUsage CPU en %
ram_pctfloatOuiUsage RAM en %
disk_pctfloatOuiUsage disque en %
temp_cfloatOuiTempérature CPU en °C
uptime_sintOuiUptime en secondes depuis boot
tsintNonTimestamp epoch millisecondes (auto si absent)
curl -X POST https://nowyousea.fr/api/ingest/system \
  -H "Authorization: Bearer <TON_TOKEN_INGEST>" \
  -H "Content-Type: application/json" \
  -d '{"rig":"rig-candoo","cpu_pct":12.5,"ram_pct":45.2,"disk_pct":62.0,"temp_c":48.3,"uptime_s":86400}'
Réponse
{"status":"ok","rig":"rig-candoo","stored":1}

4. Forwarder Python complet

Exemple complet pour Raspberry Pi avec requests et psutil. Adapter le RIG et les lectures capteurs réels.

import time, requests, psutil, socket

TOKEN = "<TON_TOKEN_INGEST>"
SERVER = "https://nowyousea.fr"
RIG = "rig-candoo"
HDR = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}

def push_gps(lat, lon, alt=None):
    d = {"rig": RIG, "lat": lat, "lon": lon}
    if alt is not None: d["alt"] = alt
    requests.post(f"{SERVER}/api/ingest/gps", json=d, headers=HDR, timeout=5)

def push_power(voltage, current, power, chip=None):
    d = {"rig": RIG, "voltage": voltage, "current": current, "power": power}
    if chip: d["chip"] = chip
    requests.post(f"{SERVER}/api/ingest/power", json=d, headers=HDR, timeout=5)

def push_system():
    d = {
        "rig": RIG,
        "cpu_pct": psutil.cpu_percent(),
        "ram_pct": psutil.virtual_memory().percent,
        "disk_pct": psutil.disk_usage("/").percent,
        "temp_c": psutil.sensors_temperatures().get("cpu_thermal", [{}])[0].get("current", 0),
        "uptime_s": int(time.time() - psutil.boot_time()),
    }
    requests.post(f"{SERVER}/api/ingest/system", json=d, headers=HDR, timeout=5)

def push_audio_chunk(wav_bytes):
    url = f"{SERVER}/api/ingest/audio?rig={RIG}&format=wav"
    requests.post(url, data=wav_bytes,
                  headers={"Authorization": f"Bearer {TOKEN}",
                           "Content-Type": "application/octet-stream"},
                  timeout=10)

if __name__ == "__main__":
    while True:
        push_gps(47.65, -2.76, alt=5.0)   # remplace par lecture GPS réelle
        push_power(12.4, 0.85, 10.5, chip="INA219")
        push_system()
        time.sleep(2)

5. Vérifier / debugger

Endpoints de lecture pour vérifier que les données arrivent correctement :

GET /api/rigs/live?window=5m
GET /api/gps/recent?range=15m&limit=
GET /api/power/recent
GET /api/system/recent
GET /api/audio/recent?limit=

Visualisation temps réel publique : https://nowyousea.fr/live/

6. Bonnes pratiques

  • rig : regex ^[A-Za-z0-9_-]{1,40}$ — unique par station physique
  • ts : epoch millisecondes. Si absent, le serveur l'auto-remplit en UTC
  • WAV : PCM format code 1 obligatoire — WAVE_FORMAT_EXTENSIBLE non supporté
  • Audio stream : chunks 2-3 secondes, POST toutes les 2 secondes
  • current : valeur signée — positif = charge, négatif = décharge. Valeur 0 acceptée
  • Rétention audio : 7 jours glissants
  • Modèle PUSH : la station POST vers le serveur — pas de polling entrant
  • Token : secret. Jamais en dur dans du code versionné. Utiliser variable d'environnement (NYS_TOKEN=...)