ttn_fetch.py
Côté serveur, ce script Python interroge l'API The Things Network v3 pour récupérer les derniers uplinks d'une MKR WAN 1310 : horodatage, RSSI vu par la passerelle et charge utile base64. La brique de base d'un tableau de bord ou d'une alerte e-mail.
Matériel requis
Une Arduino MKR WAN 1310 (microcontrôleur SAMD21, modem LoRa piloté par un ESP32 embarqué qui expose aussi le Wi-Fi, antenne LoRa et antenne Wi-Fi). Un compte TTN, une application avec device jointe, un token API (CLI ttn-lvc ou clé d'intégration).
Câblage
Aucun ; la carte n'est même pas nécessaire pour tester — utilisez des uplinks déjà reçus.
Fonctionnement
GET /as/applications/{app}/devices/{dev}/uplinks renvoie les trames déchiffrées par le serveur. Le champ frm_payload est en base64 : décodez-le avec base64.b64decode pour retrouver vos octets.
Exécution
Installez Arduino SAMD Boards et la bibliothèque MKRWAN 2.x (MKRWAN1310), sélectionnez la carte, téléversez. La 1310 se pilote par commandes AT via l'ESP32 interne ; pour LoRa, prévoyez une seconde carte LoRa en face.
Variantes
Passez en MQTT (mqtt.ttn.cloud) pour du temps réel sans polling, ou planifiez le script en cron pour un enregistrement quotidien.
ttn_fetch.py
#!/usr/bin/env python3
"""Uplinks TTN v3 d'une application via l'API HTTP.
Usage : TTN_TOKEN=xxx python ttn_fetch.py [app] [device]
Le token doit etre une cle d'integration "Link API".
"""
import os
import sys
import requests
BASE = "https://eu1.cloud.thethings.network/api/v3"
APP = sys.argv[1] if len(sys.argv) > 1 else "mon-app"
DEV = sys.argv[2] if len(sys.argv) > 2 else "mon-device"
HEADERS = {"Authorization": f"Bearer {os.environ['TTN_TOKEN']}"}
def principal() -> None:
url = f"{BASE}/as/applications/{APP}/devices/{DEV}/uplinks"
r = requests.get(url, params={"limit": 10, "order": "DESC"},
headers=HEADERS, timeout=15)
r.raise_for_status()
for up in reversed(r.json().get("uplinks", [])):
t = up.get("received_at", "?")[:19]
meta = up.get("received_at_metadata", {})
rssi = meta.get("lorawan_metadata", {}).get(
"received_signal_strength", "?")
print(f"{t} rssi={rssi} b64={up.get('frm_payload', '')}")
if __name__ == "__main__":
principal()