diff --git a/backend/api/webhooks.py b/backend/api/webhooks.py index f67087a..774b8ed 100644 --- a/backend/api/webhooks.py +++ b/backend/api/webhooks.py @@ -8,8 +8,6 @@ from fastapi import APIRouter, Request, Query logger = logging.getLogger(__name__) router = APIRouter() -DEFAULT_COUNTDOWN = 5.0 - @router.get("/webhook/photobooth") async def photobooth_webhook( @@ -20,19 +18,36 @@ async def photobooth_webhook( led = request.app.state.led_service btn = request.app.state.button_service ws = request.app.state.ws_manager + cfg = request.app.state.config.leds logger.info("Webhook photobooth: event=%s type=%s", event_key, mediaitem_type) await ws.broadcast({"type": "photobooth_event", "event": event_key, "media_type": mediaitem_type}) match event_key: case "counting": - led.play("countdown", countdown_duration=DEFAULT_COUNTDOWN) - if request.app.state.config.leds.auto_brightness: + led.play("countdown", countdown_duration=cfg.countdown_duration) + + # Annuler le pre-flash précédent si toujours en attente + prev = getattr(request.app.state, "pre_flash_task", None) + if prev and not prev.done(): + prev.cancel() + + # Déclencher le flash X secondes avant la fin du countdown + delay = max(0.0, cfg.countdown_duration - cfg.pre_flash_advance) + task = asyncio.create_task(_delayed_flash(led, delay)) + request.app.state.pre_flash_task = task + logger.info( + "Pre-flash schedulé dans %.2fs (countdown=%.1fs advance=%.1fs)", + delay, cfg.countdown_duration, cfg.pre_flash_advance, + ) + + if cfg.auto_brightness: pb = request.app.state.photobooth_service asyncio.create_task(_analyze_ambient_lux(led, pb)) case "capture": - led.play("capture") + # Flash déjà lancé par le pre-flash depuis counting ; ne pas redémarrer + logger.debug("Event capture recu (pre-flash déjà actif)") case "captured": led.play("captured") @@ -57,6 +72,14 @@ async def photobooth_webhook( return {"ok": True, "event": event_key} +async def _delayed_flash(led, delay: float): + """Attend `delay` secondes puis déclenche l'effet flash.""" + if delay > 0: + await asyncio.sleep(delay) + led.play("capture") + logger.info("Pre-flash déclenché (délai=%.2fs)", delay) + + async def _delayed_relay_on(btn, delay: float): await asyncio.sleep(delay) if btn: diff --git a/backend/services/config_service.py b/backend/services/config_service.py index 404a367..2cd5ba1 100644 --- a/backend/services/config_service.py +++ b/backend/services/config_service.py @@ -64,6 +64,8 @@ class LEDConfig: dma: int = 10 strip_type: str = "WS2812" effects: dict = field(default_factory=dict) + countdown_duration: float = 3.0 # Durée du countdown photobooth-app (secondes) + pre_flash_advance: float = 0.5 # Démarrer le flash X sec avant la fin du countdown def get_effect(self, name: str) -> LEDEffectConfig: raw = self.effects.get(name, {}) @@ -151,6 +153,8 @@ class ConfigService: dma=led_raw.get("dma", 10), strip_type=led_raw.get("strip_type", "WS2812"), effects=led_raw.get("effects", {}), + countdown_duration=led_raw.get("countdown_duration", 3.0), + pre_flash_advance=led_raw.get("pre_flash_advance", 0.5), ) if "print" in raw: diff --git a/config/settings.yaml b/config/settings.yaml index 16fb8a1..2cb714d 100644 --- a/config/settings.yaml +++ b/config/settings.yaml @@ -39,6 +39,7 @@ leds: auto_brightness: true brightness: 20 count: 35 + countdown_duration: 3.0 # Durée du countdown photobooth-app (secondes) dma: 10 effects: capture: @@ -46,7 +47,7 @@ leds: - 255 - 200 - 80 - flash_duration: 2.0 + flash_duration: 1.0 flashes: 1 mode: flash captured: @@ -97,6 +98,7 @@ leds: speed: 0.05 freq_hz: 800000 pin: 18 + pre_flash_advance: 0.5 # Démarrer le flash X secondes avant la fin du countdown strip_type: WS2812 photobooth: config_file: /home/pi/photobooth-data/config/config.json