Architecture¶
Cette page décrit le fonctionnement interne de Fliphetic. Elle est utile pour étendre le système ou diagnostiquer un comportement inhabituel.
Composants¶
Fliphetic est une seule application Python. À l'intérieur :
| Module | Responsabilité |
|---|---|
| Dashboard | Une application FastAPI : l'interface web et l'API HTTP. |
| Orchestrator | Effectue le chargement, l'arrêt et le statut. Le seul endroit qui pilote Docker, esptool et les kiosques. |
| Watchdog | Une tâche asynchrone qui interroge les dépôts enregistrés pour détecter de nouvelles références. |
| Kiosk | Écrit les fichiers d'URL par écran et contrôle les services de kiosque Chromium. |
| Storage | Une fine couche SQLite pour le registre, l'historique d'exécution, les utilisateurs, les écrans et les périphériques ESP32. |
| Manifest | Analyse et valide fliphetic.toml. |
Le tableau de bord s'exécute en tant que service système fliphetic.service.
Chaque écran exécute une fenêtre Chromium en tant que service utilisateur
fliphetic-kiosk@<role>.service.
Le cycle de vie du chargement¶
Charger une application est l'opération centrale. Dans l'ordre :
- Écran d'accueil. Chaque écran est dirigé vers une page d'accueil interne afin que l'utilisateur ait un retour immédiat.
- Récupération. Le dépôt de l'application est récupéré et basculé sur la référence cible (la tête de branche ou le tag correspondant le plus récent).
- Manifeste.
fliphetic.tomlest lu. Le nom d'affichage stocké est synchronisé depuisapp.name. - Arrêt du précédent. Les services Docker de l'application précédemment chargée sont arrêtés.
- Flashage. Chaque bloc
[esp32.<name>]est flashé avec esptool. Un périphérique requis manquant interrompt le chargement. - Compose up. Les variables d'environnement définies dans le tableau de bord sont écrites dans un fichier de surcharge Compose généré, puis les services Docker de l'application sont démarrés et disposent d'un délai pour passer leurs tests de santé.
- Résolution des écrans. Chaque cible d'écran est transformée en une URL
atteignable depuis l'hôte. Les cibles
servicesont résolues viadocker compose port; chaque service et port distinct est interrogé une seule fois. - Bascule des kiosques. Les URL résolues sont écrites dans les fichiers par écran et les services de kiosque sont redémarrés.
- Enregistrement. L'exécution est sauvegardée avec son journal complet, et l'application devient l'application courante.
Si une étape échoue, l'exécution est marquée comme échouée, l'application partiellement démarrée est arrêtée, et l'application précédemment sélectionnée demeure.
Sérialisation¶
load() et stop() sont sérialisés avec un verrou. Des appelants concurrents
(le chargement automatique au démarrage qui entre en concurrence avec un clic
sur le tableau de bord, ou deux opérateurs qui cliquent sur Charger en même
temps) entrelaceraient sinon les opérations Docker et de kiosque et laisseraient
la borne dans un état incohérent. Avec le verrou, une seconde requête attend que
la première se termine, puis s'exécute.
Stockage¶
L'état réside dans une seule base de données SQLite, par défaut
/var/lib/fliphetic/state.sqlite. Les principales tables sont :
| Table | Contenu |
|---|---|
apps |
Applications enregistrées : id, nom, URL git, stratégie de déploiement, SHA courant et le plus récent, propriétaire. |
runs |
Historique des chargements, arrêts et flashages avec les journaux complets. |
users |
Comptes : nom d'utilisateur, empreinte scrypt du mot de passe, rôle. |
screens |
Rôle d'écran, sortie et géométrie. |
esp32_devices |
Nom du périphérique, port, puce, débit en bauds. |
app_env |
Variables d'environnement par application : application, conteneur, nom, valeur. |
cab_state |
Paires clé / valeur : l'application courante, la valeur par défaut au démarrage, le paramètre d'inscription, le secret de session. |
Les dépôts clonés résident sous /var/lib/fliphetic/apps/<app-id>/. Un lien
symbolique current pointe vers l'application chargée. Les fichiers de surcharge
Compose générés, un par application ayant des variables d'environnement,
résident sous apps/.env-overrides/.
L'approche kiosque¶
Chaque écran exécute une fenêtre Chromium indépendante. Le service de kiosque
d'un rôle lit le fichier d'URL de ce rôle et lance Chromium avec --app=<url>,
ce qui supprime tout l'habillage du navigateur.
La fenêtre est ensuite placée et passée en plein écran par le gestionnaire de
fenêtres via wmctrl, plutôt que par le mode kiosque propre à Chromium. C'est
délibéré :
- L'option
--kioskde Chromium ne respecte pas de manière fiable un moniteur cible sur un bureau GNOME multi-écrans, si bien que les fenêtres peuvent se rabattre sur l'écran principal. - Laisser le gestionnaire de fenêtres passer la fenêtre en plein écran évite la notification de Chromium « appuyez sur une touche pour quitter le plein écran », car Chromium lui-même n'entre jamais dans son état plein écran.
Une courte routine d'arrière-plan attend l'apparition de la fenêtre, puis la positionne et la passe en plein écran sur la bonne sortie.
Le service de surveillance¶
Le service de surveillance est une tâche asynchrone dans le processus du tableau de bord. Environ une fois par minute, pour chaque application enregistrée, il récupère le dépôt et résout la référence cible. Si cette référence diffère de ce qui a été vu la dernière fois, l'application est signalée par un badge de mise à jour. Le service de surveillance ne charge jamais rien ; c'est un opérateur qui décide quand appliquer une mise à jour.
Réseau et démarrage¶
Le tableau de bord ne se lie qu'à l'adresse Tailscale de la borne. Le service attend que cette adresse existe avant de démarrer. Au démarrage, une fois le tableau de bord disponible, il charge automatiquement une application : la valeur par défaut au démarrage si elle est définie, sinon l'application qui était chargée avant l'arrêt.
Authentification¶
Le tableau de bord exige une connexion. Les sessions sont des cookies signés ;
le secret de signature est généré une fois par borne et stocké dans
cab_state. Les mots de passe sont hachés avec scrypt. Il existe deux rôles,
admin et user, plus une relation de propriétaire par application. Voir
Configuration pour savoir ce que chacun peut faire.