Aperçu
Un capteur — réel sur Raspberry Pi 5 ou simulé sous QEMU — est décrit dans un fichier, découvert, calibré, publié dans l'arborescence du système avec horodatage à la source, et sa latence de publication est mesurée et bornée, sans écrire un gestionnaire de ressources à la main.
Le framework existe, l'écosystème n'existe pas
QNX livre un mécanisme de publication de périphériques et un
seul publisher (usblauncher_otg, orienté
USB/stockage/média). Rien pour les capteurs. Glane ne réinvente pas le
mécanisme : il fournit ce qui manque pour s'en servir.
Tout doit être simulable
Aucune simulation sans matériel n'est documentée. Le publisher virtuel est à la fois l'outil de démonstration, le harnais de test en CI, et la raison pour laquelle le projet est vérifiable avant d'avoir une carte.
Mesurer plutôt qu'affirmer
Rien n'est dit sur la latence de publication. Le banc horodaté
(source → livraison → abonné) transforme une affirmation en chiffre.
Aucun chiffre n'est publié sans sortir de glat.
Les trous exploités (tous sourcés dans la documentation QNX)
Démo live — publisher virtuel
Portage fidèle en JavaScript du générateur synthétique
(core/src/virtuel.c) et de la calibration entière
(core/src/calib.c, en BigInt). Même table
sinusoïdale Q15, même hachage de bruit, même Horner : ce que vous voyez est
ce que produit le C, à la mesure près.
Capteur
Calibration
Livraison
Mesures
Qualité
Latence source → livraison (comme glat)
Déterminisme
Empreinte FNV-1a du journal :
Journal (format CONTRACT §7)
Émulateur QNX 8.0 — preuve réelle
Glane compile et s'exécute sur la cible réelle.
Le socle core/ (C11 pur) et glaned sont compilés avec
qcc (QNX SDP 8.0, variante gcc_ntox86_64), sans aucun
warning. Puis une image QNX 8.0 minimale est amorcée dans
qemu-system-x86_64 (via -kernel, sans disque ni
réseau) et glaned y publie réellement ses mesures :
des objets value, quality, seq,
ts_ns, unit, info écrits dans l'espace de
noms de l'invité, puis relus par ls/cat.
L'invité affiche son vrai uname (QNX 8.0), la vraie liste de
processus (pidin), et laisse un shell ksh
interactif.
C'est la « preuve d'usage QNX » exigée par le règlement : du code qui
construit et tourne vraiment sur QNX 8.0, pas un simple nom dans le
README — et la commande d'amorçage est reproduite ci-dessous.
Preuve de compilation (qcc, QNX SDP 8.0)
L'invité QNX 8.0, en direct (vitrine web)
Sur le poste de travail pc, un invité QNX 8.0
réel tourne sous QEMU : glaned y publie ses mesures dans
/dev/shmem, un gestionnaire de ressources QNX les réexpose dans
/dev/sensors, et un shell ksh attend les touches
envoyées par les boutons ci-dessous. La capture de gauche est la console VGA
de l'invité ; à droite, la console série où se déroule la publication.
connexion…
Vitrine : baptiste-ms-7d18.tail3a8bdf.ts.net:10000 — invite amorcée par
-kernel sur l'IFS build-qnx/glane-vitrine-ifs.bin,
sans disque ni réseau. Dans l'invité :
ls /dev/shmem, cat /dev/shmem/temp-chassis.info.
Fonctionnalités
Tout ce que le dépôt contient aujourd'hui, groupé par nature.
Chaque carte cite les exigences (GLA-xx) qu'elle couvre.
Preuves
Chiffres produits en exécutant le code du dépôt
(site/gen_data.py), pas recopiés à la main.
Vérifications C par module
Journaux réels (sortie de glaned-sim)
Latences mesurées (sortie de glat)
Test de mutation (glane_mutate.py)
Test différentiel C ↔ Python (GLA-05)
Contrat gelé
CONTRACT.md fait foi. Les en-têtes de
core/include/glane/ fixent les signatures. Ni les agents ni les
contributeurs ne le modifient : ils l'implémentent.
ABI de la mesure — 24 octets
typedef struct {
uint32_t sensor_id; /* identifiant issu de la description */
uint32_t seq; /* séquence monotone, jamais réinitialisée */
int64_t ts_ns; /* horodatage à la source (CLOCK_MONOTONIC) */
int32_t value_milli; /* valeur en milli-unités (jamais de flottant) */
uint16_t unit; /* GLANE_UNIT_* : C, K, V, mA, deg/s, g, rpm… */
uint8_t quality; /* OK | STALE | SATURATED | FAULT | UNCERTAIN */
uint8_t flags; /* FIRST | CALIBRATED | INJECTED | SIMULATED */
} glane_sample; /* 24 octets, aucun pointeur */
quality décrit la mesure ;
flags décrit son origine. Les mélanger rendrait
le rejeu ambigu. L'échelle entière en milli-unités permet au jumeau Python de
rejouer la calibration bit à bit.
Arborescence publiée
/dev/sensors/<name>/{value,quality,seq,ts_ns,unit,info}
/dev/sensors/<name>/command/{period,calibrate,inject,selftest}
Nom de capteur : non vide, ≤ 63 octets, charset
[a-z0-9._-], sans point initial ou final. Validé côté C
(schema.c) avant publication et côté hôte
(gschema.py) sur une arborescence réelle — même contrat.
Journal de mesures
ts_ns = horodatage à la source ;
d_ns = horodatage de livraison. La latence est
d_ns − ts_ns : c'est ce que mesure glat.
Calibration
Polynôme de degré ≤ 3, coefficients entiers échelle
10^6, accumulateur __int128. Le terme constant
a0 est en milli-unités, a1 est un gain sans
dimension. Bornes validées à l'analyse : |x| ≤ 1 048 575,
|coef[i]| ≤ 1 048 575 — aucun terme de degré 3 ne déborde.
Outils
Tout est en C11 (socle + outils hôte) ou en Python 3 stdlib uniquement. Aucune dépendance externe.
Exigences (GLA-01 … GLA-24)
Trois niveaux d'ambition : S socle (indispensable à une soumission), C complet (la version visée), X extrême. L'état est dérivé de la matrice de traçabilité.
Matrice de traçabilité
Générée par scripts/glane_trace.py : chaque
exigence est reliée aux fichiers et aux tests qui la citent.
100 idées pour aller plus loin
4 lots de 25, sans doublon avec le cahier des charges ni les 25 leviers déjà publiés. Les idées marquées ⭐ sont implémentées. Filtrez par direction ou par lot.