Flows
Automatisation visuelle avec un runtime Node-RED-like full-Rust
PNeX automatise les pipelines de données et les réactions avec des flows : des graphes visuels édités en glissant des nœuds sur un canvas et en les câblant — le modèle Node-RED, mais le runtime entier est Rust et supervisé par le serveur.
L’éditeur
L’éditeur est dessiné par l’app elle-même — un canvas WebAssembly pur avec drag & drop, pan/zoom, inspecteur par nœud, validation locale avant save et versionnage append-only avec rollback en un clic. Chaque save utilise la concurrence optimiste : une édition conflictuelle renvoie 409 et propose Recharger depuis le serveur ou Écraser avec ma version.
Les flows se trouvent sous Automatisation › Flows. Enregistrer crée une
nouvelle version sans jamais la déployer ; Déployer lance la version enregistrée,
Arrêter / Démarrer suspendent puis reprennent la version déployée, et
Historique recharge une version antérieure ou la redéploie (rollback). La pastille
« Déployé · à redéployer » signale que la version qui tourne est plus ancienne que la
version enregistrée. Le bouton Étiquettes de la barre d’outils étiquette le flow
(site:serre…), comme les appareils, les tableaux de bord et les médias.



Le runtime
Déployer un flow compile le graphe typé au format du runtime et hot-reloade un binaire Rust headless (EdgeLink vendored) supervisé par le serveur, avec restart automatique et backoff. La version déployée est celle qui tourne ; l’état de l’éditeur n’est pas le produit déployé.

Catalogue de nœuds
Le bouton + (Ajouter un nœud) de l’éditeur ouvre la palette. Les nœuds y sont rangés par catégorie, dans l’ordre d’un flow (source, traitement, sortie), et désignés ici par leur libellé dans la palette.
Déclencheurs
| Nœud | Rôle |
|---|---|
| Inject | Déclencheur : Intervalle (s), Cron (5 ou 6 champs), ou un tir unique après un Délai initial (s) |
| Source de contrôle | Émet quand un interrupteur, un curseur ou un bouton d’un tableau ou d’une annotation est actionné — voir Contrôles |
| Déclencheur d'action | Émet quand un utilisateur lance une action de l’ontologie depuis la page d’un objet |
| Source caméra | Un message par image d’un appareil caméra ou de la piste vidéo d’un flux (une référence, jamais les octets) — voir Caméras & vision |
| Source média | Un message par segment transcrit des flux audio choisis — voir Flux audio |
| Météo | Conditions actuelles et prévisions d’un lieu (MET Norway ou Open-Meteo) — voir Cartes maison |
Devices
| Nœud | Rôle |
|---|---|
| Appareil (lecture) | Dernières valeurs des pins d’un appareil, voir plus bas |
| Appareil (écriture) | Pins de sortie digital/PWM et commandes de firmware custom, voir plus bas |
| Display | Sonde transparente affichée en live sous le nœud dans l’éditeur |
Régulation
| Nœud | Rôle |
|---|---|
| Régulation TT chauffage / Régulation TT clim / Régulation PID | Cartes de régulation castées sur les appareils autonomes — voir plus bas |
Données & calcul
| Nœud | Rôle |
|---|---|
| Json Values | Émission d’un payload fixe ou aléatoire |
| Calcul | Évaluation d’expressions sur les clés du payload |
| JSON Split / Merge to JSON | Split et merge structurels du JSON, ports nommés |
| Classifieur de sujets | Étiquette un texte avec les sujets d’une taxonomie versionnée — voir Flux audio |
| CoolProp | Propriétés thermophysiques de fluides et mélanges, in-process — voir Thermo |
Code
| Nœud | Rôle |
|---|---|
| Fonction | Exécute une fonction utilisateur versionnée (JavaScript ou Starlark) — voir Fonctions |
| Node-RED brut | Porte de secours pour un builtin Node-RED non modélisé, voir plus bas |
Stockage & séries
| Nœud | Rôle |
|---|---|
| Métrique | Écrit le résultat comme métrique de télémétrie |
| Écriture mémoire / Lecture mémoire | Mémoire partagée de l’organisation, voir plus bas |
| Enregistrement vidéo | Enregistre les images en segments MJPEG-AVI — voir Caméras & vision |
| Écriture de plages | Range le message comme plage horaire (une émission, un poste, un lot) d’un flux — voir Flux audio |
| Écrire une page | Écrit du Markdown dans une page de l’organisation et fige une version nommée |
| PDF d'une page | Rend une version de page en PDF rangé dans la médiathèque ; une version écrite par l’IA attend d’abord l’approbation d’une personne |
| Journal d'événements | Stocke le payload comme événement JSON cherchable — voir Événements |
IA & prédictif
| Nœud | Rôle |
|---|---|
| Détection d'objets | Détection d’objets avec un modèle ONNX du registre, calque de détection et file de revue du Vision Lab en option |
| Suivi d'objets / Zones d'image | Identifiant stable pour chaque objet détecté, événements d’entrée et de sortie sur des zones dessinées sur l’image — voir Caméras & vision |
| Description d'image / Description vidéo | Légendes d’images et descriptions horodatées d’une scène, écrites par le modèle de l’organisation — voir Caméras & vision |
| Texte IA | Rédige un texte (rapport, résumé, classement) avec le LLM de l’organisation, à partir d’une consigne et des données reçues |
| Décision sur texte | Répond à des questions typées sur un texte, avec une probabilité par réponse, sans générer de texte ; le modèle tourne sur le serveur |
| Détection d'anomalie | Détection d’anomalie par série (z-score robuste, bande de prévision, changement de régime) — voir Maintenance prédictive |
| Prévision | Prévision d’une série et date de franchissement d’un seuil |
Intégrations
| Nœud | Rôle |
|---|---|
| Notification | Notification multi-canaux depuis un modèle, avec un PDF en pièce jointe si besoin — voir Notifications |
| Requête HTTP | Client HTTP avec auth et proxy, voir plus bas |
Debug
| Nœud | Rôle |
|---|---|
| Debug | Capture des messages dans le feed de debug |
Les nœuds d’IA (Description d'image, Description vidéo, Texte IA) passent par le fournisseur LLM configuré par l’organisation ; PNeX n’en fournit aucun. Leur sortie est marquée comme générée par IA : on la stocke, on l’affiche ou on la soumet à une personne, jamais elle ne pilote un appareil. Chaîne type d’un rapport : Inject (cron) → données → Texte IA → Écrire une page → PDF d'une page → Notification.
Lire et écrire un appareil
- Appareil (lecture) lit un seul appareil par nœud : un port de sortie par pin
cochée, dans l’ordre, plus un dernier port « tout » qui porte toutes les pins
dans un objet (pratique pour un Calcul qui combine plusieurs pins). On peut aussi
cocher les métriques publiées par un firmware custom (
temperature…). La Fenêtre de fraîcheur (s) va de 1 à 3600 s (60 par défaut) : sans donnée assez récente, le payload est{}, jamais un zéro inventé. Le cache live est lu d’abord. - Appareil (écriture) écrit les sorties d’un seul appareil (digital
1/0, PWM 0–100) et envoie aussi les Commandes du firmware qu’un firmware custom annonce (pnex.onCommand). La valeur câblée sur une ligne de commande arrive au firmware dansargs["value"]; un contrôle couleur, une liste de choix ou une consigne ne peut viser qu’une commande. Une pin de sortie n’a qu’un seul écrivain (une pin déjà écrite par un autre flow déployé est refusée au déploiement) ; les commandes n’ont pas cette règle.
Mémoire partagée
Écriture mémoire garde le payload sous une clé (cycle.p1…) avec une durée de vie
(1 h par défaut) ; la valeur disparaît si elle n’est pas réécrite. Lecture mémoire
relit ces clés depuis n’importe quel flow de l’organisation (un port par clé, avec une
fraîcheur maximale optionnelle), et les tableaux de bord affichent leurs champs
numériques (source « Mémoire »). C’est une valeur live, sans historique : pour garder
une courbe, ajoutez une Métrique.
Requête HTTP
La réponse remplace msg.payload (JSON analysé si le type de contenu est JSON) et
msg.statusCode est renseigné. Deux protections côté serveur :
- Garde de sortie : les cibles qui pointent vers le serveur ou ses services internes sont refusées — loopback, link-local, métadonnées cloud, noms d’hôte d’un seul mot. Les adresses du réseau local restent joignables, sauf si la plateforme tourne en mode public.
- Secrets : mots de passe basic et proxy, jeton bearer et valeur d’en-tête de clé sont déplacés dans le coffre de secrets de l’organisation à l’enregistrement du flow ; le graphe ne garde qu’une référence.
Node-RED brut
Node-RED brut n’accepte qu’une liste blanche de builtins de pure transformation :
change, switch, range, rbe, delay, trigger, json, csv, yaml, split,
join, sort, batch, link in/out/call, catch, status, complete, comment,
junction, inject, debug. Tout ce qui touche à l’hôte, aux fichiers ou au réseau est
refusé.
Trois façons de piloter les appareils
| Mode | Fonctionnement | Si le serveur tombe | État |
|---|---|---|---|
| Connecté | Un flow lit un appareil, décide sur le serveur, écrit sur un appareil (appareil → serveur → appareil) | La logique s’arrête ; les appareils gardent leur dernière sortie | Disponible — pour les usages non critiques |
| Autonome | Les cartes de régulation (pnex-reg-tt-heat, pnex-reg-tt-cool, pnex-reg-pid) sont authorées dans un flow, puis leur config est castée sur l’appareil, qui régule seul depuis sa flash | Continue de réguler et garde ses métriques jusqu’au retour du serveur | À venir |
| Mesh (M2M) | La topologie est configurée dans PNeX ; les appareils se parlent directement | Le mesh continue de tourner entre appareils | Plus tard, en conception |
Voir la roadmap pour les dates.
Gates de déploiement : un pin déjà assigné à un autre flow est refusé (409), et le serveur ne pousse jamais une écriture de pin de sa propre initiative — seul le flow ou l’opérateur écrit.



