Fiabilite Canon : veille/reveil relais, sequence boot, stats diagnostic, fin evenement, compteur consommables
- Preview thread : poll uniquement quand ecran capture actif, keepalive 30s sinon - Sequence boot Canon : power cycle relais si absent USB au demarrage - Veille auto 30min : Canon coupe par relais apres inactivite, reveil au preview_start - Stats diagnostic /api/canon/stats : keepalive, preview, captures, connexions - Escalade reconnexion adoucie : pas d'USB reset les 2 premieres tentatives - Hard reset relais 10s (resistance decharge 990ohm sur dummy battery 8V) - Gestion fin evenement : date_fin + bouton terminer + guard 403 impression - Compteur base sur min(papier, ruban) avec cap evenement optionnel - Pre-eclairage countdown : projecteurs ON 3s avant capture pour mesure expo - Canon _configurer_init() : ISO 800, drivemode Single, viewfinder, EXIF preserve - Admin : detail evenement, compteur consommables, galerie impression Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WyN9xFp84P9VaWT3Qe2DXu
This commit is contained in:
@@ -88,11 +88,12 @@ class Camera:
|
||||
pass
|
||||
cam.init()
|
||||
self.camera = cam
|
||||
self._desactiver_veille_init()
|
||||
self._activer_viewfinder_init()
|
||||
time.sleep(1)
|
||||
self._configurer_init()
|
||||
self.connectee = True
|
||||
self.mode = "gphoto2"
|
||||
self.preview_dslr_ok = True
|
||||
self._log_reglages()
|
||||
log.info("Camera DSLR connectee (LiveView actif)")
|
||||
return True
|
||||
except Exception as e:
|
||||
@@ -190,23 +191,36 @@ class Camera:
|
||||
vf = cfg.get_child_by_name("viewfinder")
|
||||
vf.set_value(0)
|
||||
self.camera.set_config(cfg)
|
||||
time.sleep(0.8)
|
||||
except Exception:
|
||||
pass
|
||||
log.info(f"Déclenchement capture DSLR (tentative {attempt+1}/3)")
|
||||
t0 = time.time()
|
||||
chemin_camera = self.camera.capture(gp.GP_CAPTURE_IMAGE)
|
||||
t1 = time.time()
|
||||
fichier_camera = gp.CameraFile()
|
||||
self.camera.file_get(
|
||||
chemin_camera.folder, chemin_camera.name, gp.GP_FILE_TYPE_NORMAL, fichier_camera
|
||||
)
|
||||
t2 = time.time()
|
||||
tmp_path = str(chemin_dest) + ".tmp"
|
||||
fichier_camera.save(tmp_path)
|
||||
log.info(f"Capture: shutter={t1-t0:.1f}s download={t2-t1:.1f}s")
|
||||
threading.Thread(target=self._post_capture_warmup, daemon=True).start()
|
||||
from PIL import ImageOps as PILImageOps
|
||||
img = PILImageOps.exif_transpose(PILImage.open(tmp_path))
|
||||
t3 = time.time()
|
||||
pil_img = PILImage.open(tmp_path)
|
||||
exif_data = pil_img.info.get("exif")
|
||||
img = PILImageOps.exif_transpose(pil_img)
|
||||
if img.width > 4000:
|
||||
ratio = 4000 / img.width
|
||||
img = img.resize((4000, int(img.height * ratio)), PILImage.LANCZOS)
|
||||
img.save(str(chemin_dest), "JPEG", quality=92)
|
||||
img = img.resize((4000, int(img.height * ratio)), PILImage.BILINEAR)
|
||||
save_kwargs = {"quality": 92}
|
||||
if exif_data:
|
||||
save_kwargs["exif"] = exif_data
|
||||
img.save(str(chemin_dest), "JPEG", **save_kwargs)
|
||||
t4 = time.time()
|
||||
log.info(f"Post-process: {t4-t3:.1f}s")
|
||||
Path(tmp_path).unlink(missing_ok=True)
|
||||
log.info(f"Photo capturee (DSLR) : {chemin_dest} ({img.width}x{img.height})")
|
||||
return chemin_dest
|
||||
@@ -292,35 +306,48 @@ class Camera:
|
||||
except Exception as e:
|
||||
log.debug(f"configurer_flash : {e}")
|
||||
|
||||
def _desactiver_veille_init(self):
|
||||
"""Desactive la mise en veille auto du boitier (Canon : autopoweroff en minutes, 0=jamais).
|
||||
Sans ca, le DSLR s'eteint seul apres quelques minutes d'inactivite et apparait deconnecte."""
|
||||
candidats = ["autopoweroff", "auto_power_off", "/main/settings/autopoweroff"]
|
||||
try:
|
||||
cfg = self.camera.get_config()
|
||||
for nom in candidats:
|
||||
def _configurer_init(self):
|
||||
"""Configure le Canon : veille OFF, ISO, drivemode, viewfinder (appels séparés)."""
|
||||
reglages = [
|
||||
("autopoweroff", 0),
|
||||
("viewfinder", 1),
|
||||
("iso", "800"),
|
||||
("drivemode", "Single"),
|
||||
]
|
||||
for nom, valeur in reglages:
|
||||
for tentative in range(3):
|
||||
try:
|
||||
widget = cfg.get_child_by_name(nom)
|
||||
widget.set_value(0)
|
||||
cfg = self.camera.get_config()
|
||||
w = cfg.get_child_by_name(nom)
|
||||
w.set_value(valeur)
|
||||
self.camera.set_config(cfg)
|
||||
log.info(f"Mise en veille DSLR désactivée ({nom})")
|
||||
return
|
||||
log.info(f"Canon init: {nom} = {valeur}")
|
||||
break
|
||||
except gp.GPhoto2Error as e:
|
||||
if tentative < 2:
|
||||
time.sleep(0.5)
|
||||
else:
|
||||
log.warning(f"Canon init {nom}: {e}")
|
||||
except Exception:
|
||||
continue
|
||||
log.debug("Widget autopoweroff non trouvé sur ce modèle")
|
||||
except Exception as e:
|
||||
log.debug(f"_desactiver_veille_init : {e}")
|
||||
break
|
||||
|
||||
def _activer_viewfinder_init(self):
|
||||
"""Active le LiveView pendant l'init (pas de lock, appelé avant que le thread démarre)."""
|
||||
def _log_reglages(self):
|
||||
"""Log les réglages Canon actuels pour diagnostic."""
|
||||
try:
|
||||
cfg = self.camera.get_config()
|
||||
vf = cfg.get_child_by_name("viewfinder")
|
||||
vf.set_value(1)
|
||||
self.camera.set_config(cfg)
|
||||
log.info("Viewfinder activé (init)")
|
||||
except Exception as e:
|
||||
log.warning(f"Viewfinder non supporté : {e}")
|
||||
vals = {}
|
||||
for nom in ["autoexposuremode", "iso", "shutterspeed", "aperture", "meteringmode"]:
|
||||
try:
|
||||
w = cfg.get_child_by_name(nom)
|
||||
vals[nom] = w.get_value()
|
||||
log.info(f"Canon actuel: {nom} = {vals[nom]}")
|
||||
except Exception:
|
||||
pass
|
||||
mode = vals.get("autoexposuremode", "")
|
||||
if mode in ("Flash Off", "Auto", "Night Portrait", "Landscape", "Portrait", "Sports"):
|
||||
log.warning(f"Canon en mode scène '{mode}' — ISO/vitesse non modifiables. Tourner le dial sur M ou Av.")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def activer_viewfinder(self):
|
||||
"""Active le LiveView (miroir levé) depuis le thread — thread-safe."""
|
||||
|
||||
Reference in New Issue
Block a user