Commit Graph

63 Commits

Author SHA1 Message Date
85f32c35bb Rapport email a contact@copydev.fr apres vidage du spool
Au demarrage, si le spool contient des emails en attente, les envoie
puis envoie un rapport recapitulatif (nb envoyes + liste destinataires)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-22 19:42:25 +02:00
9bdad23cf5 Spool email : envoi au demarrage uniquement, message 'dans la semaine'
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-22 19:34:26 +02:00
e47ff04933 Email spool : file d'attente quand envoi echoue, retry toutes les 60s
- Si l'envoi SMTP echoue (pas de connexion, config incomplete, etc.),
  l'email est stocke dans data/email_spool.json
- Tache asyncio periodique (60s) tente de vider le spool
- L'adresse est quand meme ajoutee a l'historique de suggestions
- Frontend affiche "Email en file d'attente" au lieu de "Erreur"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-22 19:17:58 +02:00
0b7b55f57b Email plein ecran avec suggestions d'adresses precedentes
- Formulaire email : overlay fullscreen au lieu d'inline (debordait de l'ecran)
- Historique emails : stocke chaque adresse dans data/emails_history.json
- Suggestions : affiche les emails deja saisis en pills cliquables,
  filtrees au fur et a mesure de la saisie
- API GET /api/emails/historique + DELETE pour reset

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-22 18:57:28 +02:00
e730b6bc8b Cadres : preview coin haut-gauche + compteur bloque impression pas capture
- Thumbnails cadres : positionnement coin haut-gauche au lieu du centre
  (le centre du cadre PNG est transparent = invisible)
- Compteur photos : ne bloque plus la capture quand limite atteinte,
  masque le bouton imprimer sur l'ecran partage a la place

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-22 09:03:26 +02:00
f49d5511ef Pellicule : marge de coupe plus large + warmup LiveView apres capture
La coupe physique du K60 n'est jamais parfaitement centree, donc une marge
noire trop fine fait perdre la pellicule d'un cote du strip dedouble. Marge
de coupe (perforations) elargie de 34 a 55px (~4.6mm) de chaque cote.

Ajoute aussi un warmup LiveView (_chauffer_liveview) juste apres la remontee
du miroir post-capture : consomme les ~1-2s de stabilisation pendant le
spinner de traitement plutot que de laisser le preview du countdown suivant
figé sur l'ancienne photo.
2026-06-21 23:47:06 +02:00
640715282c Fix impression pellicule : la feuille -div2 doit etre envoyee a taille pleine
La PageSize CUPS w288h432-div2 declare la meme taille de page que w288h432
(confirme par le PPD Mitsubishi) : le K60 coupe la feuille pleine apres
impression, il ne duplique pas une image fournie a taille reduite. On envoyait
la bande seule (600x1800) sous cette PageSize, donc CUPS l'etirait pour
remplir la feuille 1200x1800 puis le K60 la coupait en 2 — d'ou la photo
etiree et coupee au lieu de 2 bandes identiques.

Ajoute aussi le miroir horizontal sur le preview live (selfie) et un flou de
chargement pendant le bref delai de remontee du miroir DSLR apres capture,
pour eviter l'impression d'image figee sur la photo precedente.
2026-06-21 23:32:50 +02:00
a79762197d Fix impression pellicule : strip genere en paysage au lieu du portrait attendu
creer_strip() produisait une bande paysage (1800x595) alors que printer.py
('10x15-2up' -> PageSize ...-div2) et tous les cadres existants (assets/cadres/strip/*.png)
attendent une bande portrait fixe 600x1800 (5x15cm), dupliquee et coupee
automatiquement par l'imprimante. Le mismatch faisait pivoter/etirer
l'image a l'impression (StpiShrinkOutput=Crop sur un ratio incompatible),
d'ou le rendu deforme coupe en 2 mauvais morceaux au lieu de 2 pellicules
identiques.

- creer_strip() : bande 600x1800 portrait, photos empilees verticalement,
  perforations sur les cotes (au lieu de haut/bas)
- Cadre de visee live (camera.js) : formule de ratio mise a jour en
  consequence pour rester fidele au resultat final
2026-06-21 23:00:48 +02:00
b8f3bef852 DSLR : empecher la mise en veille (autopoweroff Canon + udev no-autosuspend)
Le boitier se mettait en veille apres quelques minutes d'inactivite et
apparaissait deconnecte. Deux causes possibles traitees :
- autopoweroff Canon desactive a la connexion (cote firmware)
- USB autosuspend du host desactive pour les peripheriques Canon (cote noyau)
2026-06-21 22:15:56 +02:00
fe0a559c85 Flash Canon configurable, choix de cadre a l'impression, fixes capture/reconnexion DSLR
- Flash integre Canon activable/desactivable depuis l'admin (configurer_flash)
- Popup de choix de cadre juste avant impression, layout sans defilement (flex nowrap + aspect-ratio)
- Capture : ignore camera_erreur pendant une capture en cours (laisse l'API trancher)
- surveiller_dslr : grace period preview augmentee a 2s, reapplique la config camera apres reconnexion
- start.sh simplifie (Chromium gere par kiosk-session.sh), remote debugging port 9222 active
2026-06-21 21:59:36 +02:00
c7225cc9f6 surveiller_dslr : retirer le reset USB automatique (contre-productif)
Les resets USB ioctl répétés en boucle aggravent l'état des appareils Canon
au lieu de les débloquer. La fonction _usb_reset_canon est conservée pour
usage manuel mais n'est plus appelée automatiquement.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 14:33:14 +02:00
f66f08da4e surveiller_dslr : pause 12s après reset USB Canon pour ré-énumération
Le reset USB ioctl prend ~10s sur le Canon EOS 6D pour que l'appareil
se ré-énumère sur le bus. Avec 3s on retombait en boucle de resets.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 14:04:23 +02:00
e4e5ee05d4 surveiller_dslr : reset USB automatique après 3 échecs de connexion Canon
Quand gphoto2 détecte le DSLR mais que camera.init() timeout répétitivement
(USB stall après kill -9 ou déconnexion brutale), on tente un reset USB ioctl
(USBDEVFS_RESET sur /dev/bus/usb/<bus>/<dev>) toutes les 3 tentatives (~15s).
Évite de rester bloqué indéfiniment sur "Timeout reading from or writing to the port".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 14:02:29 +02:00
4f12f77106 Capture : viewfinder=0 avant prise (AF phase-détection), timeout 20s, spinner UI
- camera.py : désactiver LiveView avant capture (viewfinder=0) → miroir abaissé →
  AF phase-détection Canon actif. Remplace _declencher_af_liveview (autofocusdrive=1
  pouvait bloquer sur certains corps Canon). activer_viewfinder() après la prise.
- main.py : fix bug global _preview_actif dans api_capturer (était variable locale,
  le global restait True). Timeout asyncio 20s sur run_in_executor pour éviter freeze
  permanent si capture bloque. Logs INFO avant/après capture.
- camera.js + index.html + style.css : spinner "Capture en cours..." entre le flash
  et l'affichage du résultat. Cacher le spinner dans afficherErreurCapture aussi.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 13:51:51 +02:00
d02cc90fee Bullet-proof caméra : reconnexion auto + fix crash capture + AF LiveView
backend:
- surveiller_dslr : fix condition qui court-circuitait le check santé
  quand mode==gphoto2 — watchdog surveille maintenant via preview_dslr_ok
  et reconnecte automatiquement après 15s d'échec (3x5s)
- _pusher_preview : ne pas envoyer camera_erreur pendant capture_en_cours
  (race condition HTTP/WS : le POST /capturer peut arriver avant preview_stop)
- api_capturer : force _preview_actif=False dès le début de la capture
- _capture_gphoto2 : déclenche autofocusdrive avant la prise en LiveView

frontend:
- websocket.js : support multi-callbacks par type (wsOnMessage ne remplace
  plus le callback précédent, tous s'exécutent)
- app.js : camera_erreur affiche bannière + reload dernier recours à 2min
  (plus 10s), camera_ok cache la bannière automatiquement
- camera.js : camera_erreur abort capture + arreterPreview(); camera_ok
  reset captureAbortee

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 12:11:33 +02:00
d3a71a9866 Fix caméra : gvfsd-gphoto2, race condition viewfinder, exif_transpose
- kiosk-session.sh : tue gvfsd-gphoto2 au démarrage (démon GNOME qui
  monopolisait le DSLR sur USB et bloquait gphoto2)
- camera.py : viewfinder activé AVANT mode="gphoto2" → le thread preview
  ne peut plus appeler capture_preview() avant que LiveView soit prêt
- _activer_viewfinder_init() sans lock pour l'init (thread pas encore actif)
- exif_transpose sur les captures DSLR → corrige l'orientation et les
  bandes blanches dues aux photos mal orientées

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 17:33:31 +02:00
0b4c5f9430 Fix strip (K60 coupe auto), diagnostic preview, nettoyage
Strip 10x15 :
- Envoie la strip simple avec format 10x15-2up (w288h432-div2)
  le K60 duplique et coupe automatiquement → plus de papier non coupé
- Supprime creer_impression_strip et le 2-up manuel avec marges blanches
- api/imprimer accepte format_papier depuis le frontend
- Frontend stocke formatImpression et le passe à l'impression

Diagnostic preview :
- GET /api/camera/debug : teste capture_preview(), liste les widgets
  config gphoto2, état du thread → permet de voir l'erreur exacte

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 16:52:13 +02:00
1364b62297 Fix preview + miroir : thread continu, grace period, lock gphoto2
- _thread_preview tourne TOUJOURS quand DSLR connecté (plus de condition
  _preview_actif) → capture_preview() appelé en continu → miroir reste levé
- Grace period 15 frames (~500ms) avant de signaler camera_erreur : évite
  la race condition qui tuait le preview avant la 1ère frame
- _preview_gphoto2 protégé par _gp_lock (accès concurrent safe)
- surveiller_dslr ne tourne plus quand le DSLR est en mode gphoto2 connecté

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 23:01:25 +02:00
0a918666b3 Camera : viewfinder permanent + preview live pendant compte à rebours
- activer_viewfinder() à la connexion DSLR (miroir levé dès le démarrage)
- activer_viewfinder() après chaque capture (certains Canon le désactivent)
- Suppression desactiver_viewfinder() — miroir ne redescend plus jamais
- lancerPreview() au début du compte à rebours, arreterPreview() juste avant la capture
- Preview live fonctionnel : l'utilisateur se voit pendant tout le compte à rebours

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 22:32:46 +02:00
0477831679 Imprimante : bouton Couper papier (micro-job blanc déclenche le cutter K60)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 21:19:27 +02:00
843762b6d7 Imprimante : bandeau erreur tous écrans + reset USB + statut détaillé
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 21:17:27 +02:00
2b204ddb5e Admin : statut détaillé imprimante + message erreur CUPS traduit
- GET /api/imprimante/statut-detail : statut + dernière erreur log
- Bouton évacuer retourne le vrai message (format papier, bourrage...)
- Bloc d'erreur affiché dans l'onglet Matériel si problème détecté

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 20:38:48 +02:00
3cd5525981 detecter_usb : 2 niveaux /media/<user>/<label> + filtre fstype 2026-06-04 13:53:05 +02:00
babd89425c Intégration station d'impression photo (photostation)
- Icône discrète coin bas-gauche, visible seulement si photostation installée
- Popup PIN (4 chiffres) avant lancement
- Backend : /api/photostation/disponible + /api/photostation/lancer
- kiosk-session.sh : Chromium attend le flag /tmp/photostation_running avant redémarrage
- Script install-photostation.sh pour déploiement sur la Surface

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 09:20:48 +02:00
e3d1d9cc07 Impression Mitsubishi K60 + cadres + interface admin distante
- Intégration selphy_print (backend CUPS dyesub Mitsubishi CP-K60DW-S)
- Formats impression : 15x20, 10x15, 10x15 2-strips avec cadre et orientation portrait/paysage
- Cadres d'impression par format (strip/10x15/15x20) : upload, sélection, aperçu live
- Cadres démo générés : pellicule noir/vintage/couleurs + bordures classique/doré/rose gold
- Écran de choix de cadre avant capture (clic direct, aperçu grand format)
- Filtres réduits à 3 (Couleur, N&B, Sépia) et appliqués sur tous les strips
- Port 80 via authbind, route /admin avec redirection auto depuis poste distant
- Autologin LightDM corrigé (pam-autologin-service)
- Bouton évacuer bourrage papier dans admin
- Fix : _gp_lock manquant dans Camera.__init__

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 21:38:31 +02:00
8ae42e1bc6 Backend: galerie session /s/{code} + upload API
Ajoute deux routes FastAPI :
- GET /s/{code} → galerie HTML mobile avec auto-refresh 15s
- POST /api/sessions/{code}/upload → stockage photo dans session_{code}/

Corrige layout admin : titre sm au lieu de lg, compteur sans chevauchement.
Wizard step 2 : code affiché en lg (96px) au lieu de xxl (300px).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 14:33:35 +02:00
19d1998704 Suppression preview pendant capture : plus de conflit gphoto2, capture propre 2026-04-09 11:25:17 +02:00
b4ec4dbf3f Fix race condition gphoto2 : lock non-bloquant preview cede la place a la capture 2026-04-09 07:28:33 +02:00
57ac16d366 Retrait viewfinder : priorite a la capture fonctionnelle 2026-04-09 02:05:32 +02:00
95f1a597e6 Fix critique : camera.capturer() dans run_in_executor pour ne pas bloquer asyncio 2026-04-09 02:03:58 +02:00
db751ca48c Retrait verrou camera et threading : revert approche simple sans deadlock 2026-04-09 02:00:11 +02:00
03102c803e Fix blocage asyncio viewfinder + bouton retour sur erreur camera 2026-04-09 01:54:46 +02:00
4273caf1ee Fix race condition gphoto2 : verrou camera sur preview et capture 2026-04-09 01:49:48 +02:00
076e6d0030 Canon LiveView : activer viewfinder gphoto2 avant capture_preview 2026-04-09 01:44:46 +02:00
a59f0ef766 Fix freeze liveview : bloquer surveiller_dslr pendant preview (conflit gphoto2) 2026-04-09 01:38:59 +02:00
94e3d68dd7 Preview DSLR : resize 960px + base64 hors asyncio pour fluidifier liveview 2026-04-09 01:36:20 +02:00
b871fc4c3b Preview push 30fps : thread de fond + diffusion WS sans polling
Avant : frontend poll WS toutes les 100ms -> gphoto2 bloquant -> lag
Apres : thread dedie capture en continu a 30fps, pusher asyncio
        diffuse a 20fps a tous les clients, frontend dit juste
        preview_start / preview_stop

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 22:21:29 +02:00
9a6ede02f6 Supprimer tout fallback webcam/simulation quand le DSLR est absent
- Preview gphoto2 echoue -> None direct, pas de webcam ni simulation
- Connexion sans DSLR -> mode erreur, camera non connectee
- Suppression _preview_webcam_fallback et _init_preview_fallback
- WS preview : appel direct camera.preview(), plus de logique speciale

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 22:17:20 +02:00
deca890b34 Admin: onglet Infos systeme (reseau, RAM, disque, temp, camera)
- Endpoint /api/systeme/info : IPs par interface, hostname, uptime,
  disque, RAM, temperature CPU, version Python, statut camera
- Onglet Infos dans le backoffice avec affichage visuel (barres, couleurs)
- Bouton Actualiser pour rafraichir les donnees en temps reel

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 20:55:34 +02:00
f9fd4c4f22 Fix erreur DSLR: detection immediate + message clair a l'ecran
- Backend: detecte quand le preview DSLR echoue (fallback silencieux)
  et envoie camera_erreur au frontend (debounce 5s)
- Frontend: overlay d'erreur avec message si preview DSLR indisponible
- Frontend: si capture echoue, affiche le motif 3s avant retour accueil
  au lieu de retourner silencieusement

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 20:46:46 +02:00
5de771b9f9 Erreur camera: overlay plein ecran + pas de fallback webcam
Page splash au boot pour eviter l'erreur Firefox

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 10:07:09 +02:00
d719f4c100 Fix surveillance DSLR: detecte perte de connexion et reconnecte
- Teste get_summary() pour verifier que le DSLR repond
- Reconnecte apres 2 echecs consecutifs
- Fallback webcam si DSLR plus disponible

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 10:05:20 +02:00
cb102c9e4b Preview webcam pendant capture DSLR (pas de freeze entre les poses)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 08:37:38 +02:00
7df190b5bc Preview: fallback webcam quand le DSLR ne supporte pas le live view
Le Canon 6D ne supporte pas capture_preview() via gphoto2.
Utilise la webcam embarquee pour le preview tout en gardant le DSLR pour la capture.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 08:33:59 +02:00
eababa9ec8 Photos DSLR: 4000px max, JPEG 92% (~1.5-2 Mo)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 08:30:44 +02:00
61b9749ab7 Reduire resolution max photos DSLR a 2000px (plus rapide)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 08:30:15 +02:00
8975b0392f Fix multi-shot: countdown entre chaque photo + vider apercu precedent
- Preview relancee avant chaque countdown (l'utilisateur se voit)
- Countdown 3-2-1 entre chaque photo de la serie
- Apercu precedent vide au debut d'une nouvelle session
- Surveillance DSLR pausee pendant les captures

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 20:06:52 +02:00
c2b6b01f4f Auto-detection DSLR: bascule automatique quand branche/rebranche
- Verification toutes les 5s si un DSLR est disponible
- Bascule auto de webcam/simulation vers DSLR
- Reconnexion auto si le DSLR est deconnecte

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 20:05:24 +02:00
3c308085af Redimensionner photos DSLR (max 3000px, JPEG 92%) pour affichage rapide
Les RAW du Canon 6D font 24Mo, trop lent pour le navigateur.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 19:29:31 +02:00
79b0084178 Fix capture DSLR: pause avant capture + retry si I/O in progress
- Frontend: arrete le preview 300ms avant la capture
- Backend: 3 tentatives avec 500ms entre chaque si DSLR occupe

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 19:27:54 +02:00