Contrôleur, GlobalDatastore et fichiers

Cette page décrit ce qui sort du schéma « modules → propriétés → éléments » des pages précédentes : les données du contrôleur, le module central GlobalDatastore et le système de fichiers du serveur. Un client qui se limite à afficher les modules n’en a pas besoin ; un client qui veut offrir ce que propose une page de paramètres globaux (configurations, drivers INDI, charge du serveur, équipement, images) doit les traiter.

Les données du contrôleur (controllerdata)

Le contrôleur est le composant du serveur qui charge les modules et pilote le serveur INDI embarqué. Il expose ses propres données dans le dump, sous la clé controllerdata (voir d), puis les tient à jour avec des messages uc.

CléContenu
availableconfsConfigurations de modules sauvegardées : objet nom de configuration → liste de {modulelabel, moduletype, profilename}
currentconfNom de la configuration courante
bannerBannière du serveur (texte libre, option --banner)
gitVersion du serveur : Gitdate, Githash, Gitmessage, Gittag
librariesBibliothèques de modules disponibles, un objet de métadonnées par bibliothèque
profilesProfils disponibles : objet nom de classe de module → liste de noms de profils
indiserver"Y" si le serveur INDI embarqué est activé, "N" sinon
indidriversCatalogue des drivers INDI installés : liste de {binary, family, label, mdpd}
indiactivedriversDrivers INDI actuellement lancés
systemwatcherCharge du serveur, voir plus bas
files, foldersCopie de d.files.files et d.files.folders, voir Système de fichiers
uc : une clé par message, valeur remplacée en bloc

Un message uc porte une seule clé de controllerdata, et sa valeur remplace entièrement l’ancienne (pas de fusion). Un client qui ne lit que la première clé du payload (comme le fait Rooster) est donc correct tant que le serveur n’envoie qu’une clé par message, ce qui est le cas aujourd’hui.

systemwatcher : charge du serveur

Le serveur mesure sa propre charge à intervalle régulier et la diffuse à tous les clients. L’intervalle se règle avec l’option --systemwatchinterval (secondes, 10 par défaut, 0 désactive). Le message est un uc ordinaire, et la dernière valeur est aussi présente dans controllerdata.systemwatcher du dump.

{
  "uc-update controller data": {
    "systemwatcher": {
      "cpu": { "load_1m": 10.42, "load_5m": 9.79, "load_15m": 4.51 },
      "ram": { "used_mb": 12194, "total_mb": 31941 },
      "disks": [
        { "device": "/dev/nvme0n1p2", "mountpoint": "/", "used_gb": 789.4, "total_gb": 915.3 }
      ],
      "network": [
        { "iface": "enp4s0", "rx_kbps": 16.27, "tx_kbps": 448.8 }
      ],
      "temperatures": [
        { "type": "Tctl", "temp_c": 75.375 }
      ]
    }
  }
}
ChampSignification
cpu.load_1m / load_5m / load_15mCharge moyenne du système (comme /proc/loadavg), pas un pourcentage d’utilisation : 1.0 = un cœur saturé en moyenne
ram.used_mb / total_mbMémoire utilisée (total − disponible) et totale, en Mo
disks[]Un élément par périphérique de stockage monté (/dev/*, hors loop) : device, mountpoint, used_gb, total_gb
network[]Un élément par interface (hors lo) : débits rx_kbps / tx_kbps mesurés entre deux messages ; la première mesure d’une interface vaut 0
temperatures[]Capteurs matériels du processeur : type, temp_c. La liste peut être vide selon la machine (seuls les capteurs de type Intel coretemp et AMD k10temp sont lus)
Ne pas supposer que les tableaux sont remplis

disks, network et surtout temperatures peuvent être vides. Un client doit masquer la section correspondante plutôt que d’afficher un tableau vide. Le protocole ne donne pas le nombre de cœurs du serveur : une jauge de CPU ne peut donc pas être un vrai pourcentage, il faut afficher la valeur comme une charge.

Configurations et cycle de vie des modules

Une configuration est un ensemble nommé de modules (bibliothèque, libellé, profil) que le serveur peut recharger d’un coup. La liste est dans controllerdata.availableconfs, la configuration active dans controllerdata.currentconf.

ActionCommandeDétail
Charger une configurationCLCharge tous les modules de la configuration
Sauvegarder la configuration couranteCSSous le nom donné
Charger un moduleMLBibliothèque, libellé, profil optionnel
Décharger un moduleMKPar nom de module

Les modules effectivement chargés sont ceux du dump (d.m) ; ils apparaissent et disparaissent par aa et dm. La configuration ne contient jamais GlobalDatastore (voir ci-dessous), qui est toujours présent.

Serveur INDI et drivers

Si controllerdata.indiserver vaut "Y", le serveur pilote une instance INDI embarquée. Les commandes YA/YZ/YL/YR/YS la démarrent, l’arrêtent et gèrent les drivers ; controllerdata.indidrivers donne le catalogue disponible et controllerdata.indiactivedrivers ce qui tourne. binary est la valeur à passer comme driver dans YL, YR et YS.

Le module GlobalDatastore

GlobalDatastore est un module comme les autres dans le dump (d.m.GlobalDatastore, avec propriétés, éléments, grilles, profils), mais son rôle est central :

  • il est créé par le serveur avant tous les autres modules et toujours présent : MK sur lui est refusé, et il n’est jamais inclus dans une configuration ;
  • il porte le référentiel partagé de l’équipement, que tous les autres modules consultent : optiques, emplacements, équipements (jeux d’appareils) et serveurs INDI.

Ses grilles servent de source à des listes de choix (LOV) du même nom, présentes dans d.lovs (optics, locations, equipments, servers) et reconstruites à chaque modification de la grille. Les autres modules s’en servent ainsi : choisir une optique remplit la focale et le diamètre, choisir un emplacement remplit latitude, longitude et altitude, choisir un jeu d’équipements résout les appareils (caméra, monture, focuser, roue à filtres, caméra de guidage, GPS, dôme, météo) et le serveur INDI à contacter.

Propriétés exposées :

PropriétéRôle
devicesJeu d’équipements et GPS sélectionnés (equipments, gps)
devicesactionsBoutons : connecter/déconnecter les appareils, charger les configurations (condevs, discondevs, loadconfs)
serverHôte et port du serveur INDI (host, port)
serveractionsBoutons : connecter/déconnecter le serveur INDI (conserv, disconserv)
startupCases à cocher de démarrage automatique (indiatstart, devatstart, confsatstart)
equipmentsGrille des jeux d’équipements
locationsGrille des emplacements (icônes refresh = lire le GPS, add = ajouter la ligne courante)
opticsGrille des optiques
serversGrille des serveurs INDI

Toutes ses propriétés se manipulent avec les messages standard (SV, SA, GC…, I3/I4 sur locations) ; un client générique les affiche comme n’importe quel module. Rooster les présente dans un onglet dédié de sa page de paramètres, en retenant les propriétés qui ont un profil (hasprofile) et en les regroupant par level1/level2.

Système de fichiers

Le serveur publie la liste des fichiers produits (images, séquences, archives) dans le dossier --webroot, sans que le client ait à les interroger. Ce mécanisme est indépendant des modules.

Dans le dump : d.files

"files": {
  "folders": ["", "/Allsky", "/Sequencer/gam Cyg/LIGHT/Luminance"],
  "files": ["/image1.jpeg", "/rapport.txt"],
  "selectedfolder": "/home/gilles/ostmedia"
}
ChampContenu
foldersTous les sous-dossiers du webroot, récursivement, chemins relatifs au webroot commençant par /. La racine est la chaîne vide "". Non trié.
filesLes fichiers du seul dossier sélectionné (pas récursif), chemins relatifs au webroot commençant par /. Tous les fichiers, sans filtre d’extension.
selectedfolderLe dossier sélectionné, en chemin absolu du système de fichiers du serveur (et non relatif).

Il n’y a ni pagination ni limite de taille : sur un webroot très rempli, la liste peut être longue.

Choisir le dossier : FS

FS désigne le dossier dont on veut la liste de fichiers. Le serveur ne surveille qu’un seul dossier à la fois.

Le dossier sélectionné est global au serveur

Il n’y a pas de dossier par client : un FS change la liste de fichiers vue par tous les clients connectés (les événements ci-dessous sont diffusés à tous). Un client ne doit pas s’en servir pour une simple navigation « locale » si d’autres clients sont susceptibles d’être connectés.

Le serveur ne valide pas le chemin : un dossier inexistant renvoie simplement une liste vide, sans erreur.

Mises à jour : evt

Quand le contenu du dossier sélectionné change (fichier créé, supprimé ou renommé), ou après un FS, le serveur envoie des événements de premier niveau evt :

{ "evt": "fileadd", "fileevent": ["/Sequencer/gam Cyg/LIGHT/Luminance/img_001.FITS"] }
{ "evt": "filedel", "fileevent": ["/rapport.txt"] }
Valeur de evtSignification
fileaddFichier(s) apparu(s) dans le dossier sélectionné
filedelFichier(s) disparu(s) du dossier sélectionné
folderadd / folderdelSous-dossier créé / supprimé dans le webroot (même forme, fileevent contient les chemins de dossiers)

fileevent est toujours un tableau ; aujourd’hui il contient un seul chemin par message (N fichiers = N messages). Après un FS, le client reçoit un filedel pour chaque fichier de l’ancien dossier puis un fileadd pour chaque fichier du nouveau : il n’y a pas de message annonçant le nouveau selectedfolder, qui n’existe que dans le dump.

Le serveur envoie en plus, à chaque passage, des messages uc files et folders contenant les listes complètes : un client peut donc soit appliquer les événements evt un par un, soit simplement remplacer ses listes avec ces uc.

Piège : evt commence par ev

La règle habituelle est de comparer les 1 ou 2 premiers caractères de la clé. Or evt commence par ev, le type des mises à jour d’élément avec métadonnées, dont le payload est un objet et non une chaîne. Un client qui dispatche sur le préfixe doit tester l’égalité exacte avec evt avant de tester ev, sinon il prendra un événement de fichier pour une mise à jour d’élément.

Construire l’URL d’un fichier

Les chemins de files sont relatifs au webroot et commencent par /. L’URL d’un fichier est l’URL de base des médias du serveur (http(s)://hostname/ostmedia/, voir la note « URLs media » du Modèle de données) suivie du chemin. Attention au / initial : le concaténer à une base qui se termine déjà par / donne un double //.

Ce que ne fait pas l’événement

Le serveur détecte l’ajout, la suppression et le renommage de fichiers, pas la modification du contenu d’un fichier existant : une image réécrite sous le même nom ne produit aucun événement. C’est le cas des images de prévisualisation des modules, dont l’URL reste identique à chaque prise de vue : un client doit ajouter un paramètre de cache-busting (?t= + horodatage) quand il recharge une image après une mise à jour de sa propriété.