From 37012179cff48af6f3b72860ac0e1cab3adc0557 Mon Sep 17 00:00:00 2001 From: nicoboy Date: Mon, 1 Jun 2026 16:26:07 +0200 Subject: [PATCH] Fix saturation event loop : monitor_telemetry en polling 1s MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- wireclaw_core.py | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/wireclaw_core.py b/wireclaw_core.py index 5b05fd3..cc3237f 100644 --- a/wireclaw_core.py +++ b/wireclaw_core.py @@ -63,24 +63,27 @@ async def monitor_armed(drone): global drone_armed async for is_armed in drone.telemetry.armed(): drone_armed = is_armed + await asyncio.sleep(0) # cède le contrôle après chaque mise à jour async def monitor_telemetry(drone): - """Met à jour en continu batterie et mode de vol dans telemetry_cache.""" - async def watch_battery(): - async for bat in drone.telemetry.battery(): - raw = bat.remaining_percent - telemetry_cache["battery"] = abs(raw) * 100 if abs(raw) <= 1 else abs(raw) - - async def watch_mode(): - async for fm in drone.telemetry.flight_mode(): - telemetry_cache["mode"] = str(fm) - - async def watch_gps(): - async for gps in drone.telemetry.gps_info(): - telemetry_cache["gps_fix"] = str(gps.fix_type) - telemetry_cache["gps_sats"] = gps.num_satellites - - await asyncio.gather(watch_battery(), watch_mode(), watch_gps()) + """Sonde batterie, mode et GPS par polling — pause 1s entre chaque cycle + pour ne pas saturer l'event loop asyncio avec des streams gRPC continus.""" + while True: + try: + async for bat in drone.telemetry.battery(): + raw = bat.remaining_percent + telemetry_cache["battery"] = abs(raw) * 100 if abs(raw) <= 1 else abs(raw) + break + async for fm in drone.telemetry.flight_mode(): + telemetry_cache["mode"] = str(fm) + break + async for gps in drone.telemetry.gps_info(): + telemetry_cache["gps_fix"] = str(gps.fix_type) + telemetry_cache["gps_sats"] = gps.num_satellites + break + except Exception: + pass + await asyncio.sleep(1) async def interpret_command(text): response = client.models.generate_content( @@ -260,8 +263,8 @@ async def init(): drone_armed = is_armed print(f"Etat initial : {'arme' if drone_armed else 'desarme'}") break - asyncio.ensure_future(monitor_armed(drone)) - asyncio.ensure_future(monitor_telemetry(drone)) + asyncio.create_task(monitor_armed(drone)) + asyncio.create_task(monitor_telemetry(drone)) break async def main():