diff --git a/backend/camera.py b/backend/camera.py index 2e9f1c6..94f1917 100644 --- a/backend/camera.py +++ b/backend/camera.py @@ -330,6 +330,18 @@ class Camera: except Exception as e: log.warning(f"Viewfinder non supporté : {e}") + def keepalive(self) -> bool: + """Envoie une commande legere au Canon pour empecher l'auto power off. + Utilise get_config qui declenche internement ptp_canon_eos_keepdeviceon.""" + if self.mode != "gphoto2" or not self.connectee or not self.camera: + return False + try: + with self._gp_lock: + self.camera.get_config() + return True + except Exception: + return False + def _preview_gphoto2(self) -> bytes | None: try: with self._gp_lock: diff --git a/backend/main.py b/backend/main.py index 10a8a12..725393f 100644 --- a/backend/main.py +++ b/backend/main.py @@ -61,10 +61,13 @@ _preview_none_count = 0 _PREVIEW_GRACE_FRAMES = 40 # 40 x 50ms = 2s avant de declarer une erreur (Canon LiveView peut être lent à démarrer) +_derniere_keepalive = 0.0 + def _thread_preview(): """Thread de fond : capture les frames DSLR en continu. - Tourne TOUJOURS quand le DSLR est connecte pour maintenir le miroir leve.""" - global _derniere_frame_preview + Tourne TOUJOURS quand le DSLR est connecte pour maintenir le miroir leve. + Envoie un keepalive PTP toutes les 30s meme quand le preview n'est pas actif.""" + global _derniere_frame_preview, _derniere_keepalive while True: try: if capture_en_cours or camera.mode != "gphoto2" or not camera.connectee: @@ -74,9 +77,14 @@ def _thread_preview(): donnees = camera.preview() with _preview_lock: _derniere_frame_preview = donnees + _derniere_keepalive = time.time() except Exception: with _preview_lock: _derniere_frame_preview = None + # Preview echoue → keepalive de secours via get_config + if time.time() - _derniere_keepalive > 10: + camera.keepalive() + _derniere_keepalive = time.time() time.sleep(0.033) # ~30 fps max except Exception as e: log.error(f"_thread_preview crash: {e}")