Node-RED. Créer un dashboard pour objet connecté. Bouton, liste, interrupteur, slider, formulaire (Partie 1) • Domotique et objets connectés à faire soi-même

Le module Dashboard permet d’ajouter très facilement une (très belle) interface graphique à un projet Node-RED. Le module Dashboard succède au module UI. Dans ce premier tutoriel, nous allons apprendre comment installer le plugin et utiliser les commandes bouton, liste, interrupteur, slider, formulaire, champ de saisie

Tutoriel actualisé le 28 juillet 2020

Avec ce module on peut ajouter des afficheurs pour visualiser sous différentes formes des mesures : gauges, graphique, texte, notification, ou du code HTML libre. On peut aussi ajouter des champs permettant de interactions : bouton, interrupteur, slider (potentiomètre linéaire), champ de saisie (texte ou numérique), liste de choix et des formulaires.

La seconde partie est consacré à l’utilisation des jauges, graphiques, notifications, template pour créer des widgets personnalisés avec du code HTML ou Angular.

Installer le module Dashboard pour Node-RED


Ouvrez le gestionnaire de palette et cherchez le module à l’aide du mot clé dashboard.

Puis cliquez sur install pour installer le module. A la fin de l’installation, actualisez l’affichage du navigateur.

Eléments graphiques proposés par le plugin Dashboard

Le module Dashboard propose les commandes graphiques suivantes (entrées) :

  • Bouton (button)
  • Liste de choix (dropdown)
  • Interrupteur à 2 états (switch)
  • Potentiomètre horizontal (slider)
  • Sélecteur numérique (numeric)
  • Champ de saisie de texte (text input)
  • Sélecteur de date (date picker)
  • Sélecteur de couleur (colour picker)
  • Formulaire (form)

Ainsi que les afficheurs suivants (sorties) :

  • Texte (text)
  • Gauge (gauge)
  • Graphique (chart)
  • Sortie audio (audio out)
  • Notification furtive (notification)
  • Changer de page (tab) (ui control)
  • Affichage de code HTML (template)

On accède à l’interface graphique par l’URL

http://IP_NODERED:1880/dashboard

Comment personnaliser les icônes ?

Avant de rentrer dans le vif du sujet, voyons d’abord comment utiliser des icônes. Plusieurs librairies d’icônes Open Source peuvent être utilisées pour personnaliser l’affichage des composants.

La plus connue, Font Awesome (http://fontawesome.io/icons/). Les versions les plus récentes ne sont pas supportées (4.7 et 5), mais il en reste beaucoup d’autres ! Pour utilisez une fonte Awesome, ajoutez fa- devant le nom de l’icône. Par exemple fa-fire.


Material Design (https://material.io/icons/) est un projet Open Source soutenu par Google. Pour utiliser une icône, remplacez les espaces par _, par exemple pour “account balance wallet”, saisissez “account_balance_wallet”.

Enfin, vous pouvez utiliser la librairie d’icônes Open Source pour projets AngularJS de Klarsys (https://klarsys.github.io/angular-material-icons/). Utilisez le nom icon.

Organiser les écrans. Préparer les pages (tabs) et les groupes (groups)

La première chose à faire est de créer les groupes dans lesquels on souhaite placer les composants du dashboard. Les groupes (de composants) sont regroupés en Tab (onglets). Chaque Tab s’ajoute automatique au menu latéral (sidemenu)

La palette du Dashboard est directement accessible en dessous du menu Deploy.

Sur l’onglet Layout, commencez par ajouter un onglet (Tab)

Donnez un libellé. Il est possible de personnaliser l’icône qui sera placée juste devant le libellé dans le sidemenu. Le node supporte les icônes Material Design icon, Font Awesome icon ou Weather icon.

Placez le curseur sur la ligne de l’onglet que vous venez de créer pour faire apparaître la barre d’outils. Cliquer sur + group pour ajouter un groupe.

Configurer comme ceci :

  • Name donner un nom au groupe
  • Tab  sélectionner l’onglet (Tab)
  • Display group name cocher pour afficher le nom du groupe dans l’entête du widget
  • Allow group to be collapsed cocher pour pouvoir replier le contenu du widget

On peut laisser la taille de chaque widget être réglée automatiquement mais dans certains cas vous devrez la changer à la main avec le paramètre Width (largeur).

Réglages généraux

L’onglet Site permet de configurer plusieurs paramètres d’affichage

  • Title le titre affiché
  • Options
    • Afficher (ou pas) le titre
    • Afficher (ou pas) le menu latéral (sidemenu)
    • Autoriser (ou pas) de glisser pour passer d’une tab à l’autre
  • Format de date
  • Size permet de personnaliser les principales dimensions

Modifier le thème

L’onglet Theme permet de choisir le thème sombre (dark) ou clair (light). Il est également possible de choisir la couleur du thème ainsi que la police d’affichage (font).

Ré-organiser les onglets et groupes

Il est possible de ré-ordonner les groupes dans une Tab, les déplacer d’une Tab à une autre et réordonner les Tab et utilisant la poignée.

Accéder rapidement au Dashboard

Utiliser le bouton d’accès rapide pour accéder au Dashboard.

L’autre solution consiste à saisir cette adresse

http://IP_NODE_RED:1880/ui

Bouton (Button)

Paramètres du bouton

  • Group : groupe d’affichage.
  • Size : taille de l’élément. Auto par défaut
  • Icon : permet d’afficher un icône à gauche du libellé
  • Label : libellé du bouton
  • Colour : couleur du libellé (en hexa, par exemple #8000ff)
  • Payload : valeur de sortie lorsqu’on presse sur le bouton (true, false)
  • Topic : étiquette
  • Name : nom du Node affiché sur le flow Node-RED

Le bouton obtenu

Liste de choix (dropdown)

L’élément Dropdown (liste de choix) permet à l’utilisateur de renvoyer 3 types de données :

  • Une chaine de caractère
  • Une valeur numérique entière
  • Un booléen

Le Node peut aussi être transparent et laisser passer un message entrant. Pour cela, il faut cocher la case “If msg arrives on input, pass trough to output”.

La liste de choix obtenue

Interrupteur (switch)

L’interrupteur horizontal permet de renvoyer un booléen lorsqu’il change d’état. Il est possible d’inverser la valeur du booléen en sélectionnant en inversant les valeur de sortie en fonction de l’état On et Off.

Il est également possible d’avoir d’autres types de sortie (autre que le payload) :

  • Un Flow
  • Stocker l’état dans une variable globale (Global)
  • Une chaîne de caractères (String)
  • Un nombre (Number)
  • Un objet JSON
  • La date et l’heure de l’action (timestamp)

Le switch obtenu

Potentiomètre linéaire (Slider)

Tout comme le switch, le slider peut laisser passer un message entrant en toute transparence (cocher if msg arrives…).

Le slider prend comme paramètre la valeur minimum (min), maximum (max) et le pas (step).

Le slider obtenu

Champ de saisie numérique (Numeric)

On doit définir une gamme de saisie (min, max).

Le champ numérique obtenu

Champ de saisie texte (Text) :

Ce champ propose 4 masques de saisie. Si un délai (delay) est indiqué (par défaut 300ms), le Node renvoie la valeur saisie automatiquement. C’est pratique pour un usage sur tablette. Si le délai est nul (0), il faudra valider la saisie par un appui sur la touche Enter.

Texte

Rien de plus à dire dessus.

Mot de passe (password)

Dans ce cas les caractères sont masqués.

Sélecteur de couleur (color picker)

Il renvoie le code couleur au format hexadecimal. Il utilise le sélecteur de couleur du système.

Adresse Email

Pratique, ce champ vérifie que l’email saisi est correct.

Formulaire (form)

Dernier gros morceau du Dashbord, le formulaire. C’est un composant vraiment très puissant et très simple à mettre en oeuvre.

Comme d’habitude, un libellé (Label) permet de lui donner un type qui sera affiché en entête. On ’empile’ ensuite les éléments dans le formulaire (Form elements). On dispose des choix suivants :

  • Texte (text)
  • Nombre (Number)
  • Email (E-mail)
  • Mot de passe (Password)
  • Case à cocher (Checkbox)
  • Interrupteur (Switch)

On peut rendre chaque élément obligatoire (Required) avant la sortie du formulaire.

Voici le formulaire obtenu.

Exemple, comment créer un journal d’événements

Voyons maintenant à quoi ça ressemble. Je vous propose un petit morceau de code qui stocke dans une variable globale tous les événements et les affiches sous la forme d’un journal d’événement (log).

Ajoutez un Node function et collez ce code. On stocke dans une variable globale les événements sur l’interface. On supprime les messages au delà de 20 enregistrements.

// Créé une variable pour stocker le journal du dashboard si inexistante
// initialise the counter to 0 if it doesn't exist already
var dashboardLog = context.get('dashboardLog')|| [];

dashboardLog.push(msg);
if (dashboardLog.length > 20){
    // Supprime le plus anciens message si > 20
    // Delete oldest message if > 20
    dashboardLog.shift();
    dashboardLog.length = 20;
} 

// Enregistre les messages du dashboard pour le prochain affichage
// store the value back
context.set('dashboardLog',dashboardLog);

// Affiche le journal des messages
// make it part of the outgoing msg object
msg = {};
msg.payload = dashboardLog;
return msg;

Ajoutez ensuite un Node HTML et collez ce code. On utilise la classe AngularJS ng-repeat pour parcourir le tableau renvoyé par la fonction précédente. On créé un libellé en rouge à l’aide du topic. A coté d’une puce (ul), on affiche la valeur renvoyée par l’événement du Dashboard.

  • {{x.topic}}
    • {{x.payload}}

Maintenant, vous pouvez allez sur le Dashboard en saisissant l’adresse http://IP_NODERED:1880/ui

A vous de tester maintenant !

Code du flow Node-RED

Coller le code de ce flow pour tester rapidement cet exemple.

[{"id":"6eecf682.454f38","type":"ui_button","z":"df9159f.e304ea8","name":"Boutton","group":"2a5abbd3.afa284","order":0,"width":0,"height":0,"label":"Boutton","color":"#fffff","icon":"fa-star","payload":"true","payloadType":"bool","topic":"Button","x":360,"y":100,"wires":[["1e96adb5.fd25e2"]]},{"id":"2a0c052c.dfe4ca","type":"ui_dropdown","z":"df9159f.e304ea8","name":"Liste de choix","label":"Choisissez ce que vous voulez","group":"2a5abbd3.afa284","order":0,"width":0,"height":0,"passthru":true,"options":[{"label":"Choix 1 : chaine","value":"Choix1","type":"str"},{"label":"Choix 2 : numérique","value":4,"type":"num"},{"label":"Choix 3 : bool","value":true,"type":"bool"}],"payload":"","topic":"Liste de choix","x":340,"y":140,"wires":[["1e96adb5.fd25e2"]]},{"id":"61be9b53.3a5ff4","type":"debug","z":"df9159f.e304ea8","name":"Dashboard Log","active":true,"console":"false","complete":"payload","x":900,"y":220,"wires":[]},{"id":"e7869632.cb19b8","type":"ui_switch","z":"df9159f.e304ea8","name":"Interrupteur","label":"switch","group":"2a5abbd3.afa284","order":0,"width":0,"height":0,"passthru":true,"topic":"Interrupteur","style":"","onvalue":"true","onvalueType":"bool","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","x":350,"y":180,"wires":[["1e96adb5.fd25e2"]]},{"id":"6f4d5597.73fb0c","type":"ui_slider","z":"df9159f.e304ea8","name":"Slider","label":"slider","group":"2a5abbd3.afa284","order":0,"width":0,"height":0,"passthru":true,"topic":"Slider","min":0,"max":10,"step":1,"x":370,"y":220,"wires":[["1e96adb5.fd25e2"]]},{"id":"93c06deb.61b61","type":"ui_numeric","z":"df9159f.e304ea8","name":"","label":"numeric","group":"2a5abbd3.afa284","order":0,"width":0,"height":0,"passthru":true,"topic":"Numérique","format":"{{value}}","min":0,"max":10,"x":360,"y":260,"wires":[["1e96adb5.fd25e2"]]},{"id":"8f5cb4d9.8208a8","type":"ui_text_input","z":"df9159f.e304ea8","name":"","label":"Champ saisie de Texte","group":"2a5abbd3.afa284","order":0,"width":0,"height":0,"passthru":true,"mode":"text","delay":"0","topic":"Champ saisie de Texte","x":320,"y":300,"wires":[["1e96adb5.fd25e2"]]},{"id":"3375a2e.57b475e","type":"ui_form","z":"df9159f.e304ea8","name":"","label":"Un formulaire Node-RED","group":"febe591f.8ca1f8","order":0,"width":0,"height":0,"options":[{"label":"Du texte","value":"Texte","type":"text","required":true},{"label":"Un nombre","value":"Nombre","type":"number","required":false},{"label":"Un email","value":"email","type":"email","required":false},{"label":"Un mot de passe","value":"Mot de passe","type":"password","required":false},{"label":"Une case à cocher","value":"Case à cocher","type":"checkbox","required":false},{"label":"Un interrupteur","value":"Interrupteur","type":"switch","required":false}],"formValue":{"Texte":"","Nombre":"","email":"","Mot de passe":"","Case à cocher":false,"Interrupteur":false},"payload":"","topic":"Formulaire","x":310,"y":460,"wires":[["1e96adb5.fd25e2"]]},{"id":"1e96adb5.fd25e2","type":"function","z":"df9159f.e304ea8","name":"Enregistre les événements","func":"// Créé une variable pour stocker le journal du dashboard si inexistante\n// initialise the counter to 0 if it doesn't exist already\nvar dashboardLog = context.get('dashboardLog')|| [];\n\ndashboardLog.push(msg);\nif (dashboardLog.length > 20){\n    // Supprime le plus anciens message si > 20\n    // Delete oldest message if > 20\n    dashboardLog.shift();\n    dashboardLog.length = 20;\n} \n\n// Enregistre les messages du dashboard pour le prochain affichage\n// store the value back\ncontext.set('dashboardLog',dashboardLog);\n\n// Affiche le journal des messages\n// make it part of the outgoing msg object\nmsg = {};\nmsg.payload = dashboardLog;\nreturn msg;\n","outputs":1,"noerr":0,"x":660,"y":280,"wires":[["61be9b53.3a5ff4","7a421874.47f638"]]},{"id":"7a421874.47f638","type":"ui_template","z":"df9159f.e304ea8","group":"842b8d23.22294","name":"Journal des événement du Dashboard","order":1,"width":"8","height":"10","format":"
    \n

  • \n {{x.topic}}\n
      \n

    • {{x.payload}}
    • \n

    \n

  • \n

","storeOutMessages":true,"fwdInMessages":true,"x":970,"y":320,"wires":[[]]},{"id":"87bf88d.1fbd678","type":"ui_text_input","z":"df9159f.e304ea8","name":"","label":"Champ saisie email","group":"2a5abbd3.afa284","order":0,"width":0,"height":0,"passthru":true,"mode":"email","delay":300,"topic":"Champ saisie email","x":330,"y":340,"wires":[["1e96adb5.fd25e2"]]},{"id":"55e7b58f.cafe6c","type":"ui_text_input","z":"df9159f.e304ea8","name":"","label":"Champ saisie mot de passe","group":"2a5abbd3.afa284","order":0,"width":0,"height":0,"passthru":true,"mode":"password","delay":300,"topic":"Champ saisie mot de passe","x":300,"y":380,"wires":[["1e96adb5.fd25e2"]]},{"id":"21feb1b7.018a5e","type":"ui_text_input","z":"df9159f.e304ea8","name":"","label":"Sélecteur de couleur","group":"2a5abbd3.afa284","order":0,"width":0,"height":0,"passthru":true,"mode":"color","delay":300,"topic":"Sélecteur de couleur","x":320,"y":420,"wires":[["1e96adb5.fd25e2"]]},{"id":"2a5abbd3.afa284","type":"ui_group","z":"","name":"Eléments d'entrée","tab":"99f501d2.56c31","order":1,"disp":true,"width":"8"},{"id":"febe591f.8ca1f8","type":"ui_group","z":"","name":"Formulaire","tab":"99f501d2.56c31","order":2,"disp":true,"width":"8"},{"id":"842b8d23.22294","type":"ui_group","z":"df9159f.e304ea8","name":"Journal des événements du Dashboard","tab":"99f501d2.56c31","order":3,"disp":true,"width":"8"},{"id":"99f501d2.56c31","type":"ui_tab","z":"","name":"Ecran Principal","icon":"home","order":2}]

Lisez la seconde partie consacrée à l’utilisation des jauges, graphiques, notifications, template pour créer des widgets personnalisés avec du code HTML ou Angular.

Mises à jour

28/07/2020 Actualisation du paragraphe expliquant comment préparer le Dasboard (tab et groups)

Avez-vous aimé cet article ?