Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b2d3bb1833 | |||
| fc9e9c7def | |||
| bc5f9213ec |
@@ -190,25 +190,60 @@ class LEDService:
|
|||||||
step += 1
|
step += 1
|
||||||
|
|
||||||
def _effect_countdown(self, duration: float = 5.0):
|
def _effect_countdown(self, duration: float = 5.0):
|
||||||
cfg = self._cfg.get_effect("countdown")
|
|
||||||
c = cfg.color
|
|
||||||
n = self._cfg.count
|
n = self._cfg.count
|
||||||
blank = WS_Color(0, 0, 0)
|
blank = WS_Color(0, 0, 0)
|
||||||
color = WS_Color(c[0], c[1], c[2])
|
|
||||||
|
|
||||||
self._fill(blank)
|
# Mode sombre : rampe progressive avec couleur flash pour stabiliser AWB caméra
|
||||||
|
lux = self._ambient_lux
|
||||||
|
dark_mode = self._cfg.auto_brightness and lux >= 0 and lux < 50
|
||||||
|
|
||||||
|
if dark_mode:
|
||||||
|
flash_cfg = self._cfg.get_effect("capture")
|
||||||
|
fc = flash_cfg.color
|
||||||
|
color = WS_Color(fc[0], fc[1], fc[2])
|
||||||
|
# Brightness cible du flash
|
||||||
|
target_br = 255 if lux < 50 else (int(255 - (lux - 50) / 130 * 135) if lux < 180 else 80)
|
||||||
|
# Rampe : atteindre target_br quand il reste pre_flash_advance secondes
|
||||||
|
ramp_duration = max(0.1, duration - self._cfg.pre_flash_advance)
|
||||||
|
orig_br = self._cfg.brightness
|
||||||
|
logger.info("Countdown mode sombre: rampe 0→%d sur %.1fs puis stable", target_br, ramp_duration)
|
||||||
|
if HAS_WS281X and self._strip:
|
||||||
|
self._strip.setBrightness(0)
|
||||||
|
self._fill(color)
|
||||||
|
else:
|
||||||
|
cfg = self._cfg.get_effect("countdown")
|
||||||
|
c = cfg.color
|
||||||
|
color = WS_Color(c[0], c[1], c[2])
|
||||||
|
self._fill(blank)
|
||||||
|
|
||||||
t_start = time.time()
|
t_start = time.time()
|
||||||
while not self._cmd_event.is_set() and not self._stop_event.is_set():
|
while not self._cmd_event.is_set() and not self._stop_event.is_set():
|
||||||
elapsed = time.time() - t_start
|
elapsed = time.time() - t_start
|
||||||
ratio = min(elapsed / duration, 1.0)
|
ratio = min(elapsed / duration, 1.0)
|
||||||
leds_on = int(ratio * n)
|
|
||||||
for i in range(n):
|
if dark_mode:
|
||||||
self._strip.setPixelColor(i, color if i < leds_on else blank)
|
# Rampe de 0 → target_br jusqu'à ramp_duration, puis stable à target_br
|
||||||
self._strip.show()
|
if elapsed < ramp_duration:
|
||||||
|
br = int(target_br * elapsed / ramp_duration)
|
||||||
|
else:
|
||||||
|
br = target_br
|
||||||
|
if HAS_WS281X and self._strip:
|
||||||
|
self._strip.setBrightness(br)
|
||||||
|
self._strip.show()
|
||||||
|
else:
|
||||||
|
leds_on = int(ratio * n)
|
||||||
|
for i in range(n):
|
||||||
|
self._strip.setPixelColor(i, color if i < leds_on else blank)
|
||||||
|
self._strip.show()
|
||||||
|
|
||||||
if ratio >= 1.0:
|
if ratio >= 1.0:
|
||||||
break
|
break
|
||||||
time.sleep(0.04)
|
time.sleep(0.04)
|
||||||
|
|
||||||
|
# En mode sombre, restaurer brightness normale (capture le fera aussi, mais par sécurité)
|
||||||
|
if dark_mode and HAS_WS281X and self._strip:
|
||||||
|
self._strip.setBrightness(orig_br)
|
||||||
|
|
||||||
def _effect_capture(self):
|
def _effect_capture(self):
|
||||||
"""Flash photo.
|
"""Flash photo.
|
||||||
|
|
||||||
@@ -241,15 +276,22 @@ class LEDService:
|
|||||||
if HAS_WS281X and self._strip:
|
if HAS_WS281X and self._strip:
|
||||||
self._strip.setBrightness(flash_brightness)
|
self._strip.setBrightness(flash_brightness)
|
||||||
|
|
||||||
|
# Le flash démarre pre_flash_advance secondes AVANT la photo.
|
||||||
|
# La durée ON doit couvrir ce délai + la durée d'exposition.
|
||||||
|
# Sinon les LEDs s'éteignent avant que la photo soit prise.
|
||||||
|
effective_on_time = self._cfg.pre_flash_advance + cfg.flash_duration
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for _ in range(cfg.flashes):
|
for i in range(cfg.flashes):
|
||||||
if self._cmd_event.is_set():
|
if self._cmd_event.is_set():
|
||||||
break
|
break
|
||||||
self._fill(flash_color)
|
self._fill(flash_color)
|
||||||
time.sleep(cfg.flash_duration)
|
# Premier flash : durée étendue pour couvrir le délai + expo
|
||||||
|
# Flashs suivants : durée normale (décoratif post-capture)
|
||||||
|
on_time = effective_on_time if i == 0 else cfg.flash_duration
|
||||||
|
time.sleep(on_time)
|
||||||
self._fill(off)
|
self._fill(off)
|
||||||
# Pause inter-flash plus courte que le flash lui-meme
|
if i < cfg.flashes - 1:
|
||||||
if _ < cfg.flashes - 1:
|
|
||||||
time.sleep(cfg.flash_duration * 0.4)
|
time.sleep(cfg.flash_duration * 0.4)
|
||||||
finally:
|
finally:
|
||||||
# Toujours restaurer la luminosite normale meme en cas d'erreur
|
# Toujours restaurer la luminosite normale meme en cas d'erreur
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ leds:
|
|||||||
auto_brightness: true
|
auto_brightness: true
|
||||||
brightness: 20
|
brightness: 20
|
||||||
count: 35
|
count: 35
|
||||||
countdown_duration: 3.0 # Durée du countdown photobooth-app (secondes)
|
countdown_duration: 5.0 # Durée du countdown photobooth-app (secondes)
|
||||||
dma: 10
|
dma: 10
|
||||||
effects:
|
effects:
|
||||||
capture:
|
capture:
|
||||||
@@ -98,7 +98,7 @@ leds:
|
|||||||
speed: 0.05
|
speed: 0.05
|
||||||
freq_hz: 800000
|
freq_hz: 800000
|
||||||
pin: 18
|
pin: 18
|
||||||
pre_flash_advance: 0.5 # Démarrer le flash X secondes avant la fin du countdown
|
pre_flash_advance: 2.5 # Démarrer le flash X secondes avant la fin du countdown
|
||||||
strip_type: WS2812
|
strip_type: WS2812
|
||||||
photobooth:
|
photobooth:
|
||||||
config_file: /home/pi/photobooth-data/config/config.json
|
config_file: /home/pi/photobooth-data/config/config.json
|
||||||
|
|||||||
@@ -852,6 +852,18 @@ async function previewFlash() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setFlashPreset(r, g, b, duration, flashes) {
|
||||||
|
document.getElementById('flash-r').value = r;
|
||||||
|
document.getElementById('flash-g').value = g;
|
||||||
|
document.getElementById('flash-b').value = b;
|
||||||
|
document.getElementById('flash-duration').value = duration;
|
||||||
|
document.getElementById('flash-dur-val').textContent = duration.toFixed(2);
|
||||||
|
document.getElementById('flash-count').value = flashes;
|
||||||
|
document.getElementById('flash-preview').style.background = `rgb(${r},${g},${b})`;
|
||||||
|
const hex = '#' + [r,g,b].map(v => v.toString(16).padStart(2,'0')).join('');
|
||||||
|
document.getElementById('flash-colorpicker').value = hex;
|
||||||
|
}
|
||||||
|
|
||||||
async function saveFlash() {
|
async function saveFlash() {
|
||||||
const r = parseInt(document.getElementById('flash-r').value) || 255;
|
const r = parseInt(document.getElementById('flash-r').value) || 255;
|
||||||
const g = parseInt(document.getElementById('flash-g').value) || 200;
|
const g = parseInt(document.getElementById('flash-g').value) || 200;
|
||||||
|
|||||||
Reference in New Issue
Block a user