Scénarios fonctionnels complets
Cette page décrit les parcours utilisateur et terrain de bout en bout. Elle sert de référence commune pour distinguer les moyens d’accès, le rôle du téléphone, le rôle du kiosque Raspberry et le rôle des ESP32.
Principes à retenir
La réservation reste la source métier de l’accès. Le backend Django décide si une charge peut démarrer. Le Raspberry exécute localement une décision validée : il lit le badge, affiche l’interface, relaie les appels terminal et publie les commandes MQTT vers l’ESP32.
Deux QR codes différents existent :
QR |
Moment de création |
Rôle |
|---|---|---|
QR de réservation |
Dès la création d’une réservation en mode QR. |
Identifie une réservation précise. L’utilisateur l’affiche sur son téléphone et une borne équipée d’un lecteur QR le scanne. |
QR de session mobile |
Quand l’utilisateur clique sur |
Lie temporairement le téléphone à cette borne. L’utilisateur scanne ce QR, se connecte à la PWA, choisit une réservation et autorise la borne. |
Le code SMS temporaire est lui aussi lié à la réservation. Le secret est généré
techniquement dès la réservation afin d’être synchronisable côté station, mais il
est envoyé à l’utilisateur plus tard, par exemple peu avant le créneau ou via le
bouton Recevoir le code SMS.
Scénario 1 : réservation avec QR de réservation
- Objectif
L’utilisateur réserve un créneau et choisit le mode
QR.- Préconditions
L’utilisateur est connecté à la PWA. Une station possède au moins une borne active avec un emplacement libre sur le créneau choisi.
- Déroulement
L’utilisateur ouvre la page de réservation.
Il choisit une station et un créneau.
Il choisit le mode d’accès
QR.Le backend attribue un emplacement disponible.
Le backend crée la réservation, génère le secret QR et stocke uniquement son hash.
Le QR devient consultable dans le dashboard ou la page des réservations.
Le backend envoie aussi un email contenant le QR, le code de réservation, la station, la borne, l’emplacement et le créneau.
- Résultat attendu
La réservation est confirmée. Le QR est affichable immédiatement, mais il n’est accepté à la borne que sur la bonne station, dans la fenêtre de réservation et tant qu’il n’a pas été révoqué. En environnement académique, l’email est capturé dans Mailpit et consultable sur
http://localhost:8025.- Cas d’erreur
Si aucun emplacement n’est disponible, la réservation est refusée. Si le QR est révoqué ou expiré, le terminal refuse l’accès.
Scénario 2 : accès avec QR de réservation scanné par la borne
- Objectif
Démarrer une charge avec le QR lié à une réservation.
- Préconditions
La borne possède un lecteur QR physique. La réservation est en mode
QRet son créneau est actif ou proche du début.- Déroulement
L’utilisateur affiche le QR de réservation sur son téléphone.
Sur le kiosque, il choisit
Scanner QRou présente le QR au lecteur.Le Raspberry reçoit le contenu scanné.
Le Raspberry appelle
POST /api/terminal/authenticate/avec le modeqr.Django vérifie le token, la réservation, la station, la borne, l’emplacement, la révocation et l’expiration.
Django crée ou retrouve la session de charge et passe
charge_stateàaccess_validated.Le Raspberry publie
STARTsurstation/<slot_id>/cmd.L’ESP32 acquitte la commande ; le backend passe la session à
waiting_plugouchargingselon l’ACK et la télémétrie.
- Résultat attendu
Le kiosque affiche une confirmation. L’ESP32 passe en état réservé ou charge selon sa logique locale. Un nouveau
STARTest refusé si la session est déjà engagée.- Cas d’erreur
Un QR d’une autre station ou d’une autre borne, un QR expiré, un QR révoqué ou un QR dont le mode ne correspond pas à la réservation est refusé.
Scénario 3 : accès avec bouton Téléphone et QR de session mobile
- Objectif
Autoriser la borne avec le téléphone sans lecteur QR physique sur la borne.
- Préconditions
La borne est connectée au backend. Le téléphone peut joindre la PWA depuis l’adresse locale ou publique configurée dans
FRONTEND_BASE_URL.- Déroulement
L’utilisateur clique sur
Téléphoneau kiosque.Le Raspberry appelle
POST /api/terminal/mobile-sessions/via son proxy local.Le backend crée une session mobile temporaire et renvoie une URL PWA.
Le kiosque affiche un QR contenant cette URL.
L’utilisateur scanne le QR avec son téléphone.
La PWA ouvre
mobile-session.html?token=<token>.Si l’utilisateur n’est pas connecté, la PWA l’envoie vers
login.html?next=/mobile-session.html?token=<token>.Après connexion, la PWA revient sur la session mobile.
La PWA liste les réservations actives ou proches du début pour ce compte.
L’utilisateur choisit une réservation compatible avec la station et la borne devant laquelle il se trouve.
La PWA appelle
POST /api/mobile-sessions/<token>/authorize/.Le kiosque interroge périodiquement le statut de la session.
Quand le statut devient
authorized, le kiosque consomme l’autorisation, crée ou retrouve la session de charge, puis publieSTARTvers l’ESP32.
- Résultat attendu
Le téléphone affiche que l’autorisation a été envoyée. Le kiosque affiche le démarrage ou la réussite de la charge.
- Cas d’erreur
Si le token expire, il faut rescanner un nouveau QR du kiosque. Si aucune réservation compatible n’existe, la PWA affiche une liste vide. Si la réservation appartient à une autre station ou une autre borne, l’autorisation est refusée.
- Important
Le QR affiché par le kiosque dans ce scénario n’est pas le QR de réservation. Il ne contient pas la réservation. Il contient seulement une session temporaire de borne.
Scénario 4 : accès avec code SMS temporaire
- Objectif
Démarrer une charge sans badge et sans QR, avec un code court reçu par SMS.
- Préconditions
La réservation est créée en mode
code. L’utilisateur possède un numéro de téléphone renseigné. En production, ce numéro est vérifié. Le code SMS a été envoyé avant le passage ou à la demande.- Politique du code
Le code SMS temporaire contient 8 caractères issus de l’alphabet
0123456789ABCD. Ce choix reste compatible avec un clavier matriciel 4x4 tout en offrant14^8combinaisons. Le backend limite les renvois SMS et verrouille le code après 5 mauvaises saisies.- Déroulement
L’utilisateur choisit
Code SMSsur le kiosque.Il saisit le code de réservation.
Il saisit le code SMS temporaire.
Il valide les codes.
Le Raspberry appelle
POST /api/terminal/authenticate/avec le modecode.Django vérifie la réservation, le hash du code SMS, la station, la borne et la fenêtre temporelle.
Si la validation réussit, le Raspberry publie
STARTvers l’ESP32.
- Résultat attendu
La charge démarre uniquement après validation serveur. Le bouton ou la touche de validation du clavier ne doit pas être présenté comme un démarrage direct : il valide l’authentification.
- Cas d’erreur
Une réservation en mode
codeest refusée si le profil n’a pas de téléphone. SiSMS_REQUIRE_VERIFIED_PHONEest activé, elle est aussi refusée si le téléphone n’est pas vérifié. Un renvoi trop rapproché retourne une erreur de limitation avec un délai d’attente. Un code SMS expiré, révoqué ou mal saisi est refusé. Après 5 mauvaises saisies, le code est verrouillé et doit être régénéré. Un code associé à une autre station ou une autre borne est refusé.
Scénario 5 : accès direct avec badge RFID
- Objectif
Démarrer une charge par présentation du badge RFID.
- Préconditions
Le badge RFID est associé au compte. La réservation active ou proche du début est en mode
RFIDet utilise ce badge.- Déroulement
L’utilisateur présente son badge ACR122U au lecteur de la borne.
Le Raspberry lit l’UID et le transmet au frontend kiosque.
Le kiosque appelle
POST /api/terminal/authenticate/avec le moderfid.Django retrouve le moyen d’accès RFID, l’utilisateur et la réservation active compatible.
Django vérifie la station, la borne, le créneau, l’état de la réservation et la révocation du badge.
Django crée ou retrouve la session de charge.
Le Raspberry publie
STARTvers l’ESP32.
- Résultat attendu
L’utilisateur n’a normalement rien à saisir sur la borne. Le badge est le parcours le plus rapide.
- Cas d’erreur
Un badge inconnu est refusé. Un badge révoqué est refusé. Si plusieurs réservations actives correspondent au même badge, le backend refuse l’authentification directe pour éviter une ambiguïté ; l’utilisateur doit utiliser le téléphone, le QR ou le code.
Scénario 6 : association d’un badge RFID
- Objectif
Associer un badge physique au compte utilisateur.
- Préconditions
L’utilisateur est connecté à la PWA et se trouve devant une borne avec lecteur RFID.
- Déroulement
Dans son profil, l’utilisateur demande un code d’association RFID.
Le backend génère un code court temporaire.
Sur le kiosque, l’utilisateur choisit
Associer un badge.Il saisit le code court.
Il présente le badge au lecteur.
Le Raspberry appelle
POST /api/terminal/link-rfid/avec le code et l’UID lu.Django vérifie le code, vérifie que le badge n’est pas déjà utilisé et rattache le badge au compte.
- Résultat attendu
Le badge devient utilisable pour les futures réservations en mode
RFID.- Cas d’erreur
Un code expiré ou déjà consommé est refusé. Un UID déjà associé à un autre compte est refusé. L’UID ne vient jamais de la PWA : il vient uniquement du lecteur RFID de la borne.
Scénario 7 : mauvaise station, mauvaise borne ou mauvais emplacement
- Objectif
Éviter qu’un utilisateur démarre une charge sur une station, une borne ou un emplacement non assigné.
- Déroulement
L’utilisateur tente de s’authentifier sur une borne.
Le kiosque transmet la station et la borne locales avec la demande terminal.
Django compare la station, la borne et l’emplacement avec ceux de la réservation.
- Résultat attendu
Si la réservation appartient à une autre station ou à une autre borne, l’accès est refusé. Le kiosque doit expliquer que la réservation est prévue ailleurs lorsque l’information est disponible.
Scénario 8 : backend indisponible et mode dégradé
- Objectif
Maintenir une continuité limitée si le backend tombe après synchronisation des autorisations.
- Préconditions
Le Raspberry a synchronisé le cache offline avant la panne. La réservation et le secret correspondant sont déjà connus du système.
- Déroulement
L’utilisateur présente un badge RFID ou saisit/scanne un accès QR/code.
Le kiosque tente l’appel nominal au backend.
Si l’API est indisponible, le kiosque appelle le cache local
/offline/authenticate.Le cache vérifie la station, la borne, le créneau, le mode d’accès et le hash du secret.
Si le cache valide l’accès, le Raspberry enregistre un événement offline et publie
STARTvers l’ESP32.Quand le backend revient, le Raspberry resynchronise les événements offline.
- Résultat attendu
Seules les autorisations déjà synchronisées peuvent fonctionner. Le cache ne crée jamais une nouvelle réservation, un nouveau badge ou un nouveau secret.
- Cas d’erreur
Si le cache est vide, expiré, ambigu ou associé à une autre station ou une autre borne, l’accès est refusé. La session mobile par téléphone n’est pas un bon candidat au mode dégradé complet, car elle nécessite une interaction backend pour associer le téléphone, l’utilisateur et la réservation.
Scénario 9 : commande ESP32 et télémétrie
- Objectif
Démarrer l’emplacement physique après validation métier.
- Déroulement
Le kiosque reçoit une validation d’accès du backend ou du cache offline.
Il extrait la borne et l’emplacement, puis construit
slot<numero>pour router la commande vers l’ESP32 concerné.Il publie une commande sur
station/<slot_id>/cmd.L’ESP32 reçoit
START.L’ESP32 répond sur
station/<slot_id>/ackavec le mêmecommand_id.L’ESP32 publie ensuite sa télémétrie sur
station/<slot_id>/telemetry.Le bridge MQTT backend ingère les mesures en base.
Grafana affiche température, humidité, courant, tension, énergie et état de l’emplacement.
- Résultat attendu
En développement,
MQTT_ACK_REQUIRED=Falsepermet de tester sans ESP32 physique. En borne réelle,MQTT_ACK_REQUIRED=Truedoit être activé afin de ne confirmer le démarrage que si l’emplacement répond.
Scénario 10 : interruption ou incident pendant la charge
- Objectif
Protéger l’utilisateur et l’équipement pendant la charge.
- Déroulement
L’ESP32 surveille ses capteurs locaux : DHT22, INA219, porte, câble et relais.
Il publie régulièrement la télémétrie.
Si une condition dangereuse apparaît, par exemple surchauffe, boîtier ouvert, câble retiré ou courant anormal, l’ESP32 doit couper localement la charge.
Il publie un statut ou une alerte MQTT.
Le backend et Grafana affichent l’incident.
Le technicien affecté à la station prend l’alerte en charge depuis son tableau de bord.
Après contrôle ou intervention, il résout l’alerte avec une note d’intervention.
- Résultat attendu
La sécurité locale ne dépend pas d’un aller-retour backend. L’ESP32 reste un exécutant local, mais il garde la responsabilité de couper la charge en cas de danger matériel. La partie métier trace qui a pris en charge l’incident, quand il a été résolu et avec quelle conclusion.
Scénario 11 : choix du moyen d’accès à la réservation
- Objectif
Créer une réservation avec le bon moyen d’accès selon le profil utilisateur.
- Déroulement
L’utilisateur choisit une station et un créneau.
Le backend calcule les bornes et emplacements disponibles, puis attribue un emplacement.
L’utilisateur choisit le moyen d’accès.
Le backend crée la réservation et prépare les secrets nécessaires.
- Cas
RFID L’utilisateur doit avoir un badge actif associé à son compte. La réservation est liée au compte et au mode RFID. À la borne, le badge permet de retrouver l’utilisateur, puis sa réservation compatible.
- Cas
QR Le backend génère un QR de réservation dès la création. Le QR est consultable dans la PWA et peut être scanné par une borne équipée d’un lecteur QR.
- Cas
code SMS L’utilisateur doit avoir un numéro de téléphone renseigné. Le secret est créé dès la réservation, stocké sans clair et envoyé plus tard par SMS. Si aucun téléphone n’est disponible, ce mode doit être bloqué avant la confirmation. En production, le numéro doit aussi être vérifié avant l’envoi.
- Cas d’erreur
Si aucun emplacement n’est libre, la réservation est refusée. Si le moyen choisi n’est pas compatible avec le compte, l’interface doit proposer un autre mode plutôt que créer une réservation inutilisable.
Scénario 12 : session mobile avec zéro, une ou plusieurs réservations
- Objectif
Décrire le comportement de la PWA après scan du QR de session mobile.
- Préconditions
Le QR affiché sur le kiosque est un QR de session mobile valide. L’utilisateur ouvre l’URL depuis son téléphone et se connecte à son compte.
- Cas aucune réservation compatible
La PWA affiche qu’aucune réservation ne peut être utilisée sur cette borne. Elle peut proposer de créer une réservation ou de vérifier la station prévue. Le kiosque reste en attente jusqu’à expiration de la session.
- Cas une réservation compatible
La PWA affiche la réservation avec la station, la borne, l’emplacement et le créneau. L’utilisateur confirme. Le backend marque la session de borne comme
authorizedet le kiosque peut démarrer le parcours physique.- Cas plusieurs réservations compatibles
La PWA liste les réservations utilisables. L’utilisateur en choisit une. Le backend associe uniquement cette réservation à la session de borne. Le kiosque ne doit jamais choisir seul en cas d’ambiguïté.
- Cas session expirée
La PWA affiche que la session est absente ou expirée. L’utilisateur doit revenir au kiosque et demander un nouveau QR de session.
Scénario 13 : annulation, révocation et support
- Objectif
Gérer les cas où un accès ne doit plus fonctionner.
- Annulation utilisateur
Si l’utilisateur annule la réservation avant le créneau, la réservation passe dans un état non utilisable. Les accès QR, SMS ou RFID associés à ce créneau doivent être refusés au terminal.
- Révocation admin
L’administration peut révoquer un QR, un code SMS temporaire ou un badge RFID. La révocation ne supprime pas la trace : elle désactive le moyen d’accès et alimente le journal de sécurité.
- Support terrain
Le code de réservation reste l’identifiant de support principal. Il permet de retrouver la réservation, la station prévue, la borne prévue, le mode choisi, l’état de l’authentification et les éventuelles erreurs terminal.
- Synchronisation offline
Une révocation récente doit être propagée au cache Raspberry. Tant que le backend est indisponible, le cache ne doit accepter que les droits encore valides dans sa dernière synchronisation et refuser les droits expirés.
Tableau de décision rapide
Situation |
Action utilisateur |
Décision système |
Résultat |
|---|---|---|---|
Badge connu, une réservation RFID active |
Présenter le badge |
Backend retrouve la réservation |
Démarrage possible |
Badge connu, plusieurs réservations actives |
Présenter le badge |
Backend refuse l’ambiguïté |
Utiliser téléphone, QR ou code |
Session mobile, une réservation compatible |
Scanner le QR de borne et confirmer sur le téléphone |
Backend autorise la session de borne |
Démarrage possible |
Session mobile, aucune réservation compatible |
Scanner le QR de borne |
Backend ne trouve aucun droit utilisable |
Refus ou création d’une réservation |
Session mobile, plusieurs réservations compatibles |
Choisir sur le téléphone |
Backend lie la réservation choisie à la session |
Démarrage possible |
Borne avec lecteur QR |
Montrer le QR de réservation à la borne |
Backend valide le token |
Démarrage possible |
Borne sans lecteur QR |
Scanner le QR de session affiché par la borne |
Téléphone choisit la réservation |
Borne autorisée |
Téléphone indisponible |
Saisir code réservation et code SMS |
Backend valide le secret temporaire |
Démarrage possible |
Mode SMS demandé sans téléphone |
Choisir code SMS à la réservation |
Backend bloque la création ou l’envoi |
Choisir RFID ou QR |
Mode SMS demandé avec téléphone non vérifié |
Choisir code SMS avec |
Backend refuse la création ou l’envoi |
Vérifier le téléphone ou choisir RFID/QR |
Backend indisponible |
Badge, QR ou code déjà synchronisé |
Cache local vérifie le hash |
Démarrage possible si cache valide |
Backend indisponible, cache absent |
N’importe quel moyen d’accès |
Aucun droit local fiable |
Refus |
Réservation sur autre station |
N’importe quel moyen d’accès |
Station locale incompatible |
Refus |
Réservation sur autre borne |
N’importe quel moyen d’accès |
Borne locale incompatible |
Refus |
Secret révoqué ou expiré |
N’importe quel moyen d’accès |
Authentification inactive |
Refus |