Commit Graph

43 Commits

Author SHA1 Message Date
e0fd4a64bf Ajouter overlay RSSI (pyramide inversée) au flux MJPEG
- Thread rssi_loop() : lecture API JSON locale (127.0.0.1:8103), parse flux video rx pour extraire RSSI moyen des antennes
- Fonction draw_rssi_pyramid() : pyramide inversée (base large en haut, pointe en bas), 10 segments, remplissage proportionnel au RSSI
- Code couleur : vert (RSSI > -60 dBm), cyan (-60 à -70 dBm), rouge (< -70 dBm)
- Positionnement : haut à droite du frame
- Reconnexion automatique en cas de redémarrage wfb-server-gs
- Intégration dans capture_loop après draw_overlay()

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VmaVcCrWp2QG7hkEDk15Cv
2026-07-19 21:54:37 +02:00
bae1ae2130 Ajout install_wfb_gs_fr.sh — protège wifi_region contre l'écrasement BO du script officiel 2026-07-18 19:26:43 +02:00
5e937d468d docs: corriger CLAUDE.md sur l'état réel des règles pare-feu (5600/5601/5602), ignorer *.bak 2026-07-18 15:51:41 +02:00
b472c70ea2 fix: MJPEG server threaded (evite le blocage mono-client, backlog TCP) 2026-07-18 15:37:28 +02:00
0620d9a8a7 fix: sideband socket IPv4 pur (tunnel WFB-NG point-a-point, dual-stack peu fiable) 2026-07-18 15:35:06 +02:00
b2fe3d5195 Actualiser README.txt
V2
2026-07-15 16:18:58 +00:00
caf142ba4d Ajouter README.txt
premiere version
2026-07-15 16:17:45 +00:00
24ae29b0d7 fix: socket sideband UDP 5602 en dual-stack IPv4+IPv6
Le socket AF_INET seul ne recevait pas les stats Pi Zero envoyées en IPv6
via Mycelium. Passage en AF_INET6 + IPV6_V6ONLY=0 pour accepter les deux
familles sur un seul socket (Freebox IPv4 en dev, Mycelium IPv6 en prod).
2026-07-01 16:56:20 +02:00
a9e4f913ec fix: reconnexion continue au flux GStreamer au lieu d'un timeout fixe
L'ancienne sonde abandonnait définitivement après 15s et restait bloquée
en mode synthétique même quand le flux réel arrivait juste après (latence
Mycelium variable, attente du premier keyframe H.264). Remplacé par un
thread de fond (gstreamer_watcher) qui retente en continu et bascule la
source active dès qu'une frame valide est lue, y compris après une perte
de flux en cours de route. Démarrage MJPEG immédiat, plus d'attente bloquante.
2026-07-01 16:18:38 +02:00
1c945fc921 fix: augmenter le timeout de sonde GStreamer à 15s (4s insuffisant)
Le décodeur H.264 a besoin du temps d'attendre le premier keyframe/SPS-PPS,
surtout via Mycelium où la latence est plus élevée qu'en local. 4s faisait
parfois basculer en mode synthétique alors que le flux réel arrivait juste après.
2026-07-01 15:56:27 +02:00
4857adb8da fix: pipeline GStreamer dual-stack IPv4+IPv6 pour réception flux Pi Zero
Le flux RTP arrive maintenant via Mycelium en IPv6, mais udpsrc bindé
sur "::" seul ne reçoit pas les paquets IPv4 (pas de dual-stack sur ce
Jetson, IPV6_V6ONLY actif). Fusion de deux udpsrc (0.0.0.0 + ::) via
funnel pour accepter Freebox (dev, IPv4) et Mycelium (prod, IPv6).
2026-07-01 15:36:11 +02:00
822367ada8 fix: drain pymavlink directement dans monitor_telemetry et dans status
La tâche drain_pymavlink() séparée ne tournait jamais car input()
bloque l'event loop. Drain et lecture du HEARTBEAT directement dans
monitor_telemetry() et en fallback dans l'action status pour garantir
la lecture du custom_mode ArduCopter.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 17:29:27 +02:00
1b47ce124d fix: drainer pymavlink dans le thread principal sans run_in_executor
run_in_executor + blocking=False retournait None dans un thread
séparé sans rien peupler dans mav.messages. Drain direct dans
la boucle asyncio avec while recv_match() pour vider tout le
buffer à chaque tick de 50ms.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 17:26:37 +02:00
7979619c38 fix: drain pymavlink en tâche de fond pour que mav.messages soit peuplé
recv_match(blocking=False) ponctuel ratait les heartbeats car aucun
appel continu ne drainait le buffer pymavlink. Ajout d'une tâche
drain_pymavlink() qui appelle recv_match() toutes les 50ms pour
remplir mav.messages, et lecture du mode via mav.messages.get()
qui retourne le dernier heartbeat reçu.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 17:24:49 +02:00
943aa3d70e fix: lire le mode de vol via pymavlink (custom_mode ArduCopter) au lieu de MAVSDK
MAVSDK flight_mode() retourne UNKNOWN pour les modes ArduCopter non
mappés dans son enum PX4. Lecture directe du champ custom_mode depuis
les HEARTBEAT pymavlink avec dictionnaire de mapping ArduCopter complet.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 17:20:39 +02:00
8ce340a573 fix: heartbeat GCS initial pour enregistrer l'adresse pymavlink auprès de mavp2p
En udpout, mavp2p (udps) ignore le client tant qu'aucun paquet
n'a été émis depuis lui. L'envoi d'un heartbeat GCS dès la
connexion force mavp2p à mémoriser l'adresse de retour et à
relayer le flux H743 vers pymavlink.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 16:49:19 +02:00
9e26727e51 fix: passer MAVSDK et pymavlink en mode client UDP vers mavp2p
mavp2p tourne en serveur (udps) sur 14551 et 14552.
Les anciens bind serveur (udp://:14551, udpin:0.0.0.0:14552)
causaient "Address already in use". Les deux connexions
passent maintenant en mode client vers 127.0.0.1.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 16:43:17 +02:00
09a789f20c fix: clés JSON sideband alignées sur payload Pi Zero
temp → temp_c, cpu → cpu_pct pour correspondre exactement
au format {ts, width, height, fps, encoder, bitrate_kbps,
temp_c, cpu_pct, throttled, uptime_s} émis par le Pi Zero.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 18:10:13 +02:00
74aa62b1cc feat: thread sideband UDP 5602 + overlay stats Pi Zero sur MJPEG
Reçoit JSON Pi Zero (width, height, fps, encoder, temp, cpu, throttled)
toutes les secondes via UDP 5602. Affiche un overlay cv2 semi-transparent
(fond noir 55%) en haut à gauche de chaque frame MJPEG :
  ligne 1 : "1280x720 | 15fps | hw | 56.2C"
  ligne 2 : "CPU 42% | ok / THROTTLED"
Variable globale _pi_stats protégée par _stats_lock (threading.Lock).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 17:47:40 +02:00
c119879abd feat: receive_cam.py YOLOv8 MJPEG port 5601 validé
- receive_cam.py : YOLOv8n + MJPEG annoté 5601 opérationnel
- Fallback frame synthétique numpy (aucun download)
- Port 5601 TCP ouvert iptables (persistant)
- .gitignore : exclusion *.pt *.onnx
- CLAUDE.md : état du jour mis à jour

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 08:46:18 +02:00
0d628d0431 feat: YOLOv8 + MJPEG dans receive_cam.py, fallback synthétique numpy
- Inférence yolov8n.pt sur chaque frame GStreamer
- Fallback frame noir numpy si Pi Zero absent (pas de download)
- Timeout 4s sur sonde GStreamer via thread dédié
- MJPEG annoté exposé sur port 5601

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 20:08:54 +02:00
34d1d69500 docs: YOLOv8 + PyTorch CUDA installés sur Jetson Orin
torch 2.8.0 depuis pypi.jetson-ai-lab.io/jp6/cu126, CUDA 12.6 confirmé.
numpy épinglé <2 (incompatible torch 2.8), opencv-python pip retiré (cv2 système).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 19:47:07 +02:00
772236dee6 docs: port 5600 UDP ouvert iptables (persistant)
Règle iptables ACCEPT udp dpt:5600 ajoutée et sauvegardée via netfilter-persistent.
sudoers mis à jour : nicoboy peut gérer iptables sans mot de passe.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 18:54:35 +02:00
2dda633412 feat: réception flux H.264 Pi Zero → MJPEG Jetson
- receive_cam.py : pipeline GStreamer UDP 5600 → MJPEG HTTP 5601
- CLAUDE.md : Pi Zero IP, ports 5600/5601, commandes de session caméra

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 18:50:59 +02:00
9db1897af7 fix: chemin absolu uvicorn pour systemd
systemd n'inclut pas ~/.local/bin dans PATH, uvicorn non trouvé (exit 127).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 18:32:58 +02:00
a6abcb7d9d Hotspot WireClaw, iptables ports MAVLink, modèle Gemini 2.5-flash 2026-06-01 19:12:32 +02:00
6306e823f4 start.sh : kill uvicorn et web_server au nettoyage
Sans ça, un ancien processus uvicorn reste en écoute sur 8765
entre deux lancements et répond à la place du nouveau.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 16:32:28 +02:00
37012179cf Fix saturation event loop : monitor_telemetry en polling 1s
3 streams gRPC infinis en asyncio.gather() saturaient l'event
loop et empêchaient uvicorn d'accepter des connexions HTTP.
- monitor_telemetry : boucle while + async for...break + sleep(1)
  au lieu de 3 streams continus en gather
- monitor_armed : await sleep(0) pour céder après chaque update
- ensure_future → create_task (API recommandée Python 3.7+)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 16:26:07 +02:00
24100aea4d SYSTEM_PROMPT : descriptions des actions pour guider Gemini
Sans description, Gemini mappait "position gps" sur position
au lieu de position_gps. Chaque action a maintenant un libellé
explicite, position_gps précise horodatage + fix + satellites.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 15:09:51 +02:00
579bec5abd Fix : get_running_loop() au lieu de get_event_loop() (déprécié Python 3.10)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 15:04:38 +02:00
0d2f485c57 Fix position_gps : GPS info en cache, plus de blocage async
- gps_fix et gps_sats ajoutés à telemetry_cache
- monitor_telemetry surveille aussi gps_info() en continu
- position_gps lit depuis le cache (comme battery/mode)
  et ne risque plus de bloquer sur async for ... break

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 15:00:30 +02:00
1d095cd233 Fix TypeError altitude null + erreurs affichées dans l'UI
- float(cmd.get("altitude") or 15) : gère altitude=null retourné
  par Gemini pour les commandes sans altitude (land, rtl, status…)
- /command attrape les exceptions et retourne JSON 500 avec le
  message d'erreur, évite le "Erreur réseau" opaque dans la page

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 14:49:22 +02:00
f7a096c6a7 Fix langue et altitude relative dans SYSTEM_PROMPT
- Ajout instruction explicite : message toujours en français
- Nouveau champ delta dans le schéma JSON : "monte de 5m" → delta=5,
  "descend de 3m" → delta=-3, null pour altitude absolue
- takeoff et altitude calculent target_alt = current_alt + delta
  quand delta est présent, sinon utilisent altitude absolue

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 14:46:28 +02:00
f019470749 Ajout commandes altitude et position_gps
- altitude : change la hauteur en vol via goto_location,
  ou décollage depuis le sol si alt < 2m
- position_gps : position complète avec horodatage HH:MM:SS,
  fix GPS et nombre de satellites via telemetry.gps_info()
- SYSTEM_PROMPT et message d'accueil mis à jour

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 14:31:32 +02:00
6024655a50 Fix event loop bloqué + /status non-bloquant
- init_pymavlink() passe en run_in_executor : ne bloque plus
  l'event loop asyncio pendant le démarrage de uvicorn
- Ajout monitor_telemetry() : batterie et mode mis à jour en
  continu en cache (même logique que monitor_armed)
- /status et action status lisent telemetry_cache directement,
  plus aucun async for bloquant dans les route handlers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 14:22:02 +02:00
7264bd1d3d start.sh : remplace python3 wireclaw_core.py par uvicorn web_server
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 14:11:59 +02:00
bcda9cf334 Ajout serveur web FastAPI sur port 8765
- wireclaw_core : expose drone comme global, extrait init()
  depuis main() pour permettre l'import par web_server.py ;
  corrige aussi le bug drone_armed manquant global dans init
- web_server.py : FastAPI avec process(text) générique
  (interpret_command → execute_command), routes GET / POST /command
  GET /status, page HTML sobre avec statut temps réel (2s)
  et historique des commandes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 13:54:54 +02:00
66f7149d60 Gitignore : exclure les artefacts de session SITL
Ajout de eeprom.bin, logs/, terrain/, mav.tlog.raw générés
automatiquement par ArduPilot/MAVProxy à chaque session.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 13:49:53 +02:00
32a9713e36 Fix takeoff en vol : changer l'altitude au lieu de bloquer
Quand Gemini mappe "monte à Xm" sur takeoff et que le drone est
déjà en vol, on recalcule l'altitude absolue MSL et on utilise
goto_location pour atteindre la nouvelle altitude à position fixe.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 13:08:31 +02:00
f7c4a7221b Fix takeoff : vérifier l'altitude réelle au lieu de drone_armed
drone_armed reste True après une session précédente même si le drone
est au sol. Le guard utilise désormais current_pos["alt"] < 2.0
comme goto et orbit, avec un refresh_position préalable.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 13:03:29 +02:00
93a7013ad0 Add commande position GPS 2026-06-01 10:29:26 +02:00
7e2b253e97 Add Claude Code context file 2026-05-31 07:01:18 +02:00
17c2ae5ce8 Initial commit — WireClaw SITL fonctionnel 2026-05-30 10:35:15 +02:00