Les flows Node-RED Modbus sont l'un des moyens les plus rapides de sortir les données des compteurs, variateurs et automates qui ne parlent que Modbus pour les amener dans MQTT, où tableaux de bord, historiens et outils cloud peuvent les exploiter. Dans ce tutoriel, vous allez interroger des holding registers et des coils avec node-red-contrib-modbus, décoder correctement les entiers mis à l'échelle et les flottants 32 bits, et publier un JSON propre sur un broker uniquement lorsque les valeurs changent. Vous verrez aussi comment traiter les commandes d'écriture en toute sécurité et comment tout tester sans matériel réel.
Pourquoi relier Modbus à MQTT avec Node-RED
Modbus est un protocole requête/réponse datant de 1979 : un client (maître) demande un bloc de registres à un serveur (esclave) et reçoit en retour des nombres bruts de 16 bits. Pas d'unités, pas de noms, pas d'horodatage, pas de push. Chaque consommateur qui veut les données doit interroger lui-même l'équipement, et beaucoup d'équipements ne gèrent que quelques connexions simultanées.
MQTT inverse la logique. Une seule passerelle interroge l'équipement, donne un sens aux nombres et les publie une fois sur un broker. Un nombre illimité d'abonnés reçoit alors des valeurs nommées et mises à l'échelle dès qu'elles changent. Node-RED est une passerelle naturelle, car l'interrogation, le décodage, le filtrage et la publication tiennent chacun dans un nœud, et la logique reste visible pour l'équipe de maintenance. Pour une vue d'architecture plus large, le guide Modbus TCP vers MQTT compare Node-RED aux autres options de passerelle.
Installer node-red-contrib-modbus
Installez le paquet depuis Manage palette → Install ou en ligne de commande :
cd ~/.node-red
npm install node-red-contrib-modbus
# redémarrez Node-RED ensuite
Il fournit notamment les nœuds suivants :
| Nœud | Rôle |
|---|---|
| Modbus Read | Interroge un bloc fixe de registres selon une minuterie |
| Modbus Getter | Lit à la demande à l'arrivée d'un message |
| Modbus Flex Getter | Lit ce que précise le message entrant |
| Modbus Write | Écrit des coils ou des registres |
| Modbus Server | Un serveur Modbus TCP simple pour les tests |
| Modbus Client (config) | Connexion TCP ou série partagée par les nœuds |
Commencez par comprendre votre table de registres
Tout projet Modbus commence par la table de registres de l'équipement. Pour ce tutoriel, imaginez un contrôleur de pompe avec la table suivante :
| Donnée | Type | Adresse (base 0) | Notation classique | Mise à l'échelle |
|---|---|---|---|---|
| Température | Holding register, 16 bits signé | 0 | 40001 | valeur / 10, °C |
| Pression | Holding register, 16 bits non signé | 1 | 40002 | valeur / 100, bar |
| Débit | Holding registers, flottant 32 bits, big-endian | 2-3 | 40003-40004 | aucune, m³/h |
| Pompe en marche | Coil | 0 | 00001 | booléen |
L'erreur Node-RED Modbus la plus fréquente concerne l'adresse. Les fiches techniques utilisent souvent la notation « 40001 », qui commence à 1 et inclut un préfixe de type. L'adresse protocolaire, celle que vous saisissez dans Node-RED, commence à 0 et n'a pas de préfixe : 40001 devient le holding register d'adresse 0. Si vos valeurs semblent décalées d'un registre, voilà pourquoi.
Tester sans matériel : un serveur Modbus local
Vous pouvez suivre tout le tutoriel sans équipement en faisant tourner un serveur Modbus dans Node-RED.
- Faites glisser un nœud Modbus Server dans un onglet séparé. Réglez-le pour écouter sur
0.0.0.0, port10502(non privilégié, donc pas besoin de root). Déployez. - Créez un nœud de configuration Modbus Client : type TCP, hôte
127.0.0.1, port10502, unit ID1. - Ajoutez un nœud inject répété toutes les 2 secondes, un nœud function qui génère des valeurs de registres simulées et un nœud Modbus Write utilisant ce client avec le code fonction 16 (preset multiple registers), adresse
0, quantité4.
La fonction de simulation :
// Nœud function "simulate pump registers" -> Modbus Write (FC16, adresse 0, quantité 4)
const temperature = 40 + Math.random() * 5; // °C
const pressure = 3.2 + Math.random() * 0.3; // bar
const flowRate = 12 + Math.random() * 2; // m³/h
const buf = Buffer.alloc(4);
buf.writeFloatBE(flowRate, 0);
msg.payload = [
Math.round(temperature * 10), // registre 0
Math.round(pressure * 100), // registre 1
buf.readUInt16BE(0), // registre 2 : mot de poids fort du flottant
buf.readUInt16BE(2) // registre 3 : mot de poids faible du flottant
];
return msg;
Ajoutez un second nœud d'écriture sur le coil : code fonction 5 (force single coil), adresse 0, alimenté par true depuis un nœud inject. Votre faux contrôleur de pompe est maintenant en marche.
Construire le flow d'interrogation Node-RED Modbus
Étape 1 : interroger les registres
Ajoutez un nœud Modbus Read utilisant le même client :
- FC : 3, Read Holding Registers
- Adresse :
0, quantité :4 - Fréquence d'interrogation : 2 secondes
Sa première sortie émet msg.payload sous forme de tableau de quatre nombres bruts, par exemple [423, 334, 16708, 26214]. La seconde sortie transporte le buffer brut et les détails de la réponse, utiles pour déboguer l'ordre des octets.
Pour le coil, ajoutez un second nœud Modbus Read avec FC 1 (Read Coil Status), adresse 0, quantité 1, et une interrogation plus lente de 5 secondes.
Étape 2 : décoder les registres bruts en valeurs physiques
// Nœud function "decode pump registers"
const r = msg.payload;
if (!Array.isArray(r) || r.length < 4) {
node.warn("Unexpected register block");
return null;
}
// Conversion 16 bits signée pour la température
const int16 = v => (v > 32767 ? v - 65536 : v);
// Flottant 32 bits à partir de deux registres, ordre des mots big-endian
const buf = Buffer.alloc(4);
buf.writeUInt16BE(r[2], 0);
buf.writeUInt16BE(r[3], 2);
const flowRate = buf.readFloatBE(0);
const values = {
temperature: Math.round(int16(r[0])) / 10,
pressure: Math.round(r[1]) / 100,
flow: Math.round(flowRate * 100) / 100
};
// Stocker pour combiner avec la lecture du coil
flow.set("pump1_values", values);
msg.topic = "connectmq/demo/a7f3k2/plant1/utilities/pump1/telemetry";
msg.payload = {
...values,
running: flow.get("pump1_running") === true
};
return msg;
Reliez la lecture du coil à une petite fonction qui mémorise l'état : flow.set("pump1_running", msg.payload[0] === true); return null;. De nombreux équipements utilisent des flottants « word-swapped », où le mot de poids faible vient en premier. Si votre valeur de débit paraît absurde, comme 1.2e-38 ou -4.5e+12, inversez r[2] et r[3] et réessayez.
Étape 3 : publier uniquement en cas de changement
Interroger toutes les 2 secondes et publier chaque résultat gaspille de la bande passante et inonde les abonnés de données en double. Insérez un nœud filter (anciennement RBE) réglé sur « block unless value changes » sur msg.payload, ou utilisez une variante à bande morte sur les valeurs individuelles si elles fluctuent. Le filtre compare l'objet entier, c'est pourquoi la fonction de décodage n'ajoute pas d'horodatage. Après le filtre, ajoutez un nœud change qui définit msg.payload.ts avec un horodatage. La publication par exception est un modèle central de MQTT, mais un heartbeat périodique reste utile pour les valeurs qui évoluent lentement, afin que les abonnés distinguent un équipement silencieux d'un équipement hors service.
Étape 4 : publier sur MQTT
Ajoutez un nœud mqtt out avec un topic vide pour que msg.topic soit utilisé. Pour les tests, configurez le broker broker.connectmq.com, port 1883, avec un client ID unique : c'est le serveur MQTT public gratuit. Remplacez a7f3k2 par votre propre chaîne. Observez ensuite la sortie :
mosquitto_sub -h broker.connectmq.com -p 1883 -i sub-modbus-a7f3k2 -v \
-t 'connectmq/demo/a7f3k2/plant1/#'
Vous devriez voir des messages comme {"temperature":42.3,"pressure":3.34,"flow":12.81,"running":true,"ts":...}. N'envoyez pas de vraies données d'usine sur le broker public : n'importe qui peut s'y abonner. Il est réservé aux tests et aux prototypes.
Écrire dans Modbus depuis MQTT, en toute sécurité
Lire présente peu de risques ; écrire dans une pompe, si. Si vous acceptez des commandes depuis MQTT, ajoutez des garde-fous au flow :
- Abonnez-vous à un topic de commande dédié, comme
.../pump1/cmd, jamais à un wildcard. - Validez le payload dans un nœud function à l'aide d'une liste blanche d'actions autorisées et de plages de valeurs.
- Associez chaque action à un registre ou un coil fixe. Ne laissez jamais le message choisir l'adresse.
- Publiez le résultat sur un topic
.../pump1/cmd/ackpour que l'émetteur sache si l'écriture a eu lieu. - Utilisez un broker privé avec authentification pour tout topic capable de modifier l'état d'un équipement.
// Nœud function "validate pump command" -> Modbus Write (FC5, coil 0)
const cmd = String(msg.payload).trim().toUpperCase();
if (cmd !== "START" && cmd !== "STOP") {
node.warn("Rejected command: " + cmd);
return null;
}
msg.payload = cmd === "START";
return msg;
Modbus RTU sur RS-485
Pour les équipements série, seule la configuration du client change : type Serial, port tel que /dev/ttyUSB0, débit, parité et bits de stop correspondant à l'équipement (9600 8N1 est courant), et le type série RTU. Chaque équipement du bus possède son propre unit ID. Restez prudent sur les fréquences d'interrogation, car un même bus RS-485 dessert tous les équipements à tour de rôle, et un timeout sur l'un retarde les autres. Le guide Modbus RTU vers MQTT traite du câblage et de la terminaison.
Dépanner les flows Node-RED Modbus
| Symptôme | Cause probable | Solution |
|---|---|---|
| Erreurs de timeout | Mauvaise IP, mauvais port ou unit ID ; pare-feu | Vérifiez d'abord avec un outil Modbus de bureau |
| Illegal data address (exception 2) | Adresse décalée d'une unité ou mauvais code fonction | Utilisez des adresses en base 0 ; holding vs input registers |
| Valeurs décalées d'un registre | Notation 40001 saisie telle quelle | Soustrayez le décalage |
| Valeurs flottantes absurdes | Ordre des mots différent | Inversez les deux registres |
| Nombres négatifs affichés au-delà de 65 000 | Valeur signée lue comme non signée | Appliquez la conversion int16 |
| L'équipement ne répond plus sous charge | Trop de clients ou interrogation trop rapide | Une seule passerelle, interrogations plus lentes, lectures regroupées en blocs |
De la passerelle à la production
Une fois les valeurs en circulation, la passerelle ne vaut que par le broker sur lequel elle publie. Sur un site comptant plusieurs passerelles Node-RED, un client SCADA et un historien, tous devraient partager un même broker authentifié, accessible à la fois depuis le réseau de l'usine et celui des bureaux. Un broker MQTT cloud est un moyen simple d'y parvenir, car chaque passerelle se connecte en sortie sur le port 8883 et aucun port entrant n'est ouvert vers le réseau OT. ConnectMQ reconnaît en outre les topics de style ISA-95 comme plant1/utilities/pump1/telemetry et affiche les équipements selon ces niveaux dans son portail. Si vous préférez ne pas exploiter d'infrastructure de broker du tout, un broker MQTT managé vous décharge des mises à jour et de la supervision.
Les autres protocoles industriels suivent le même modèle : voyez Node-RED OPC UA vers MQTT pour les contrôleurs modernes et Node-RED avec Siemens S7 pour les automates S7. Pour la configuration du broker dans Node-RED, le tutoriel Node-RED MQTT présente les bases.
Connectez votre passerelle Modbus à ConnectMQ
Inscrivez-vous sur app.connectmq.com avec l'offre gratuite Serverless, sans carte bancaire. Créez un broker, collez le nom d'utilisateur, le mot de passe et le client ID générés dans le nœud de configuration Node-RED, activez TLS sur le port 8883, et vos valeurs Modbus sont publiées de façon privée et chiffrée. Utilisez l'explorateur de topics en direct de ConnectMQ pour vérifier chaque registre que vous avez décodé.
Questions fréquentes
node-red-contrib-modbus prend-il en charge Modbus TCP et RTU ?
Oui. Le nœud de configuration Modbus Client prend en charge les connexions TCP et série, y compris RTU via des adaptateurs RS-485. Les nœuds de lecture et d'écriture fonctionnent de la même façon dans les deux cas.
Pourquoi mon adresse Modbus est-elle décalée d'une unité dans Node-RED ?
Les fiches techniques utilisent souvent une numérotation de style 40001 commençant à 1, alors que Node-RED utilise des adresses protocolaires commençant à 0. Le holding register 40001 correspond à l'adresse 0 dans le nœud Modbus Read.
Comment lire un flottant 32 bits depuis Modbus dans Node-RED ?
Lisez deux registres consécutifs, écrivez-les dans un buffer de 4 octets et appelez readFloatBE. Si le résultat semble faux, inversez les deux mots, car certains équipements utilisent l'ordre inverse.
À quelle fréquence Node-RED doit-il interroger un équipement Modbus ?
Interrogez aussi lentement que votre cas d'usage le permet, souvent toutes les 1 à 10 secondes pour de la supervision. Regroupez les registres en blocs et publiez par exception pour ménager à la fois l'équipement et le broker.



