Bulletproof: messages novices, kiosk port auto, reset compteur, sync booth event_id
- Messages erreur camera/impression: texte novice ("Oups!", "Reessayez") au lieu de jargon technique
- kiosk-session.sh: lit le port depuis config.json (plus de http://localhost en dur), healthcheck /api/config, supprime git pull auto au boot
- Activer evenement: reset automatique du compteur photos
- Activer evenement: sync booth.event_id quand galerie live active
- Port par defaut backend: 80 → 8080
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -125,6 +125,10 @@ def activer_evenement(event_id: str) -> dict | None:
|
|||||||
event = obtenir_evenement(event_id)
|
event = obtenir_evenement(event_id)
|
||||||
if not event:
|
if not event:
|
||||||
return None
|
return None
|
||||||
|
config = charger_config()
|
||||||
|
booth = config.get("booth", {})
|
||||||
|
if booth.get("actif"):
|
||||||
|
booth["event_id"] = event_id
|
||||||
mettre_a_jour_config({
|
mettre_a_jour_config({
|
||||||
"evenement": {
|
"evenement": {
|
||||||
"event_id": event_id,
|
"event_id": event_id,
|
||||||
@@ -134,7 +138,8 @@ def activer_evenement(event_id: str) -> dict | None:
|
|||||||
"couleur_secondaire": event.get("couleur_secondaire", "#ffffff"),
|
"couleur_secondaire": event.get("couleur_secondaire", "#ffffff"),
|
||||||
"media_accueil": event.get("media_accueil"),
|
"media_accueil": event.get("media_accueil"),
|
||||||
"formats_actifs": event.get("formats_actifs", ["10x15", "15x20", "strip"]),
|
"formats_actifs": event.get("formats_actifs", ["10x15", "15x20", "strip"]),
|
||||||
}
|
},
|
||||||
|
"booth": booth,
|
||||||
})
|
})
|
||||||
log.info(f"Evenement active : {event['nom']} ({event_id})")
|
log.info(f"Evenement active : {event['nom']} ({event_id})")
|
||||||
return event
|
return event
|
||||||
|
|||||||
@@ -1736,6 +1736,8 @@ async def api_activer_evenement(event_id: str):
|
|||||||
event = activer_evenement(event_id)
|
event = activer_evenement(event_id)
|
||||||
if not event:
|
if not event:
|
||||||
return JSONResponse({"erreur": "Evenement introuvable"}, status_code=404)
|
return JSONResponse({"erreur": "Evenement introuvable"}, status_code=404)
|
||||||
|
reset_compteur()
|
||||||
|
log.info(f"Compteur photos remis a zero (activation evenement {event_id})")
|
||||||
await diffuser_ws({"type": "config_maj", "config": charger_config()})
|
await diffuser_ws({"type": "config_maj", "config": charger_config()})
|
||||||
return event
|
return event
|
||||||
|
|
||||||
@@ -2587,6 +2589,6 @@ if __name__ == "__main__":
|
|||||||
uvicorn.run(
|
uvicorn.run(
|
||||||
app,
|
app,
|
||||||
host=conf_srv.get("host", "0.0.0.0"),
|
host=conf_srv.get("host", "0.0.0.0"),
|
||||||
port=conf_srv.get("port", 80),
|
port=conf_srv.get("port", 8080),
|
||||||
log_level="info",
|
log_level="info",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ function afficherErreurPreview(visible) {
|
|||||||
const el = document.getElementById('preview-erreur-camera');
|
const el = document.getElementById('preview-erreur-camera');
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
if (visible) {
|
if (visible) {
|
||||||
el.querySelector('p').textContent = 'Appareil photo deconnecte';
|
el.querySelector('p').textContent = 'Un instant...';
|
||||||
el.querySelector('span').textContent = 'Reconnexion en cours...';
|
el.querySelector('span').textContent = 'L\'appareil photo se reconnecte';
|
||||||
el.classList.remove('cache');
|
el.classList.remove('cache');
|
||||||
} else {
|
} else {
|
||||||
el.classList.add('cache');
|
el.classList.add('cache');
|
||||||
@@ -194,7 +194,7 @@ wsOnMessage('camera_erreur', () => {
|
|||||||
if (!captureEnCours) {
|
if (!captureEnCours) {
|
||||||
captureAbortee = true;
|
captureAbortee = true;
|
||||||
if (ecranActuel === 'capture') {
|
if (ecranActuel === 'capture') {
|
||||||
afficherErreurCapture('Appareil photo déconnecté', 'Reconnexion en cours...');
|
afficherErreurCapture('Un instant...', 'L\'appareil photo se prepare');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -253,7 +253,7 @@ async function lancerCapture() {
|
|||||||
try {
|
try {
|
||||||
let statut = await apiGet('/api/camera/statut');
|
let statut = await apiGet('/api/camera/statut');
|
||||||
if ((!statut.connectee || statut.mode === 'erreur') && statut.reveil_en_cours) {
|
if ((!statut.connectee || statut.mode === 'erreur') && statut.reveil_en_cours) {
|
||||||
afficherStatut('Appareil photo en preparation...', 'succes');
|
afficherStatut('L\'appareil photo se prepare, un instant...', 'succes');
|
||||||
for (let att = 0; att < 30; att++) {
|
for (let att = 0; att < 30; att++) {
|
||||||
await pause(2000);
|
await pause(2000);
|
||||||
statut = await apiGet('/api/camera/statut');
|
statut = await apiGet('/api/camera/statut');
|
||||||
@@ -263,12 +263,12 @@ async function lancerCapture() {
|
|||||||
}
|
}
|
||||||
if (!statut.connectee || statut.mode === 'erreur') {
|
if (!statut.connectee || statut.mode === 'erreur') {
|
||||||
captureEnCours = false;
|
captureEnCours = false;
|
||||||
afficherErreurCapture('Appareil photo non disponible', 'Verifiez la connexion USB du DSLR');
|
afficherErreurCapture('Appareil photo indisponible', 'Reessayez dans quelques instants');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
captureEnCours = false;
|
captureEnCours = false;
|
||||||
afficherErreurCapture('Impossible de joindre le serveur', 'Verifiez que le photobooth est bien demarre');
|
afficherErreurCapture('Le photobooth demarre', 'Reessayez dans quelques instants');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,7 +304,7 @@ async function lancerCapture() {
|
|||||||
flash.classList.add('cache');
|
flash.classList.add('cache');
|
||||||
document.getElementById('capture-en-cours').classList.add('cache');
|
document.getElementById('capture-en-cours').classList.add('cache');
|
||||||
captureEnCours = false;
|
captureEnCours = false;
|
||||||
afficherErreurCapture('Erreur reseau', 'Le serveur ne repond pas — redemarrez le photobooth');
|
afficherErreurCapture('Oups !', 'La photo n\'a pas pu etre prise, reessayez');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,7 +313,7 @@ async function lancerCapture() {
|
|||||||
document.getElementById('capture-en-cours').classList.add('cache');
|
document.getElementById('capture-en-cours').classList.add('cache');
|
||||||
captureEnCours = false;
|
captureEnCours = false;
|
||||||
const msg = resultat.erreur;
|
const msg = resultat.erreur;
|
||||||
afficherErreurCapture('Echec de la capture', msg.includes('Echec') ? 'Verifiez le DSLR et reessayez' : msg);
|
afficherErreurCapture('Oups !', 'La photo n\'a pas pu etre prise, reessayez');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,7 +447,7 @@ let formatImpression = null; // Format CUPS à utiliser (ex: "10x15-2up")
|
|||||||
|
|
||||||
async function traiterCapture() {
|
async function traiterCapture() {
|
||||||
if (photosSession.length === 0) {
|
if (photosSession.length === 0) {
|
||||||
afficherErreurCapture('Aucune photo capturee', 'Une erreur inattendue s\'est produite');
|
afficherErreurCapture('Oups !', 'La photo n\'a pas pu etre prise, reessayez');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -461,7 +461,7 @@ async function traiterCapture() {
|
|||||||
if (mode === 'strip') {
|
if (mode === 'strip') {
|
||||||
resultat = await apiPost('/api/strip', { photos: photosSession });
|
resultat = await apiPost('/api/strip', { photos: photosSession });
|
||||||
if (resultat.erreur) {
|
if (resultat.erreur) {
|
||||||
afficherErreurCapture('Erreur creation de la planche', resultat.erreur);
|
afficherErreurCapture('Oups !', 'La planche n\'a pas pu etre creee, reessayez');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (resultat.impression) photoImpression = resultat.impression;
|
if (resultat.impression) photoImpression = resultat.impression;
|
||||||
@@ -469,12 +469,12 @@ async function traiterCapture() {
|
|||||||
} else {
|
} else {
|
||||||
resultat = await apiPost('/api/collage', { photos: photosSession });
|
resultat = await apiPost('/api/collage', { photos: photosSession });
|
||||||
if (resultat.erreur) {
|
if (resultat.erreur) {
|
||||||
afficherErreurCapture('Erreur creation du collage', resultat.erreur);
|
afficherErreurCapture('Oups !', 'Le collage n\'a pas pu etre cree, reessayez');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!resultat.nom) {
|
if (!resultat.nom) {
|
||||||
afficherErreurCapture('Erreur traitement des photos', 'Le fichier final n\'a pas ete genere');
|
afficherErreurCapture('Oups !', 'Un probleme est survenu, reessayez');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
photoFinale = resultat.nom;
|
photoFinale = resultat.nom;
|
||||||
|
|||||||
@@ -125,9 +125,9 @@ async function lancerImpression() {
|
|||||||
} else if (resultat.succes) {
|
} else if (resultat.succes) {
|
||||||
afficherStatut(`${nbExemplaires} exemplaire(s) envoye(s) a l'imprimante !`, 'succes');
|
afficherStatut(`${nbExemplaires} exemplaire(s) envoye(s) a l'imprimante !`, 'succes');
|
||||||
} else if (resultat.erreur === 'evenement_termine') {
|
} else if (resultat.erreur === 'evenement_termine') {
|
||||||
afficherStatut('Evenement termine — impression indisponible', 'erreur');
|
afficherStatut('L\'impression n\'est plus disponible pour cet evenement', 'erreur');
|
||||||
} else {
|
} else {
|
||||||
afficherStatut('Erreur d\'impression', 'erreur');
|
afficherStatut('L\'impression a rencontre un probleme, reessayez', 'erreur');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,7 +189,7 @@ async function envoyerEmail() {
|
|||||||
} else if (resultat.succes) {
|
} else if (resultat.succes) {
|
||||||
afficherStatut('Email envoyé !', 'succes');
|
afficherStatut('Email envoyé !', 'succes');
|
||||||
} else {
|
} else {
|
||||||
afficherStatut('Erreur d\'envoi email', 'erreur');
|
afficherStatut('L\'email n\'a pas pu etre envoye, reessayez', 'erreur');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,18 @@
|
|||||||
exec 9>/tmp/photobooth-kiosk.lock
|
exec 9>/tmp/photobooth-kiosk.lock
|
||||||
flock -n 9 || { echo "[kiosk] Déjà en cours, abandon."; exit 0; }
|
flock -n 9 || { echo "[kiosk] Déjà en cours, abandon."; exit 0; }
|
||||||
|
|
||||||
|
PHOTOBOOTH_DIR=/home/jules/photobooth
|
||||||
|
|
||||||
|
# Port du backend (lu depuis config.json, fallback 8080)
|
||||||
|
BACKEND_PORT=$(python3 -c "
|
||||||
|
import json, sys
|
||||||
|
try:
|
||||||
|
d = json.load(open('$PHOTOBOOTH_DIR/data/config.json'))
|
||||||
|
print(d.get('serveur', {}).get('port', 8080))
|
||||||
|
except: print(8080)
|
||||||
|
" 2>/dev/null)
|
||||||
|
BACKEND_URL="http://localhost:${BACKEND_PORT}"
|
||||||
|
|
||||||
# Tuer tout backend orphelin d'une session precedente
|
# Tuer tout backend orphelin d'une session precedente
|
||||||
pkill -f 'python.*backend.main' 2>/dev/null || true
|
pkill -f 'python.*backend.main' 2>/dev/null || true
|
||||||
sleep 1
|
sleep 1
|
||||||
@@ -23,8 +35,7 @@ pkill -f gvfs-gphoto2-volume-monitor 2>/dev/null || true
|
|||||||
_backend_loop() {
|
_backend_loop() {
|
||||||
while true; do
|
while true; do
|
||||||
while [ -f /tmp/photobooth-maintenance ]; do sleep 2; done
|
while [ -f /tmp/photobooth-maintenance ]; do sleep 2; done
|
||||||
cd /home/jules/photobooth
|
cd "$PHOTOBOOTH_DIR"
|
||||||
git pull --ff-only 2>&1 | logger -t photobooth-git
|
|
||||||
source .venv/bin/activate
|
source .venv/bin/activate
|
||||||
authbind --deep python -m backend.main 2>&1 | tee -a /tmp/photobooth-backend.log
|
authbind --deep python -m backend.main 2>&1 | tee -a /tmp/photobooth-backend.log
|
||||||
echo "[kiosk] backend terminé, redémarrage dans 3s..."
|
echo "[kiosk] backend terminé, redémarrage dans 3s..."
|
||||||
@@ -37,9 +48,9 @@ BACKEND_LOOP_PID=$!
|
|||||||
# Nettoyer le backend si le kiosk est tue
|
# Nettoyer le backend si le kiosk est tue
|
||||||
trap "kill $BACKEND_LOOP_PID 2>/dev/null; pkill -f 'python.*backend.main' 2>/dev/null" EXIT
|
trap "kill $BACKEND_LOOP_PID 2>/dev/null; pkill -f 'python.*backend.main' 2>/dev/null" EXIT
|
||||||
|
|
||||||
# Attendre que le backend soit pret (max 15s)
|
# Attendre que le backend soit pret (max 30s)
|
||||||
for i in $(seq 1 15); do
|
for i in $(seq 1 30); do
|
||||||
curl -sf http://localhost/ > /dev/null 2>&1 && break
|
curl -sf "${BACKEND_URL}/api/config" > /dev/null 2>&1 && break
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -64,7 +75,7 @@ while true; do
|
|||||||
--password-store=basic \
|
--password-store=basic \
|
||||||
--lang=fr \
|
--lang=fr \
|
||||||
--remote-debugging-port=9222 \
|
--remote-debugging-port=9222 \
|
||||||
http://localhost
|
"${BACKEND_URL}"
|
||||||
echo "[kiosk] Chromium terminé, redémarrage dans 2s..."
|
echo "[kiosk] Chromium terminé, redémarrage dans 2s..."
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
|
|||||||
Reference in New Issue
Block a user