Dashboard for IoT with Node-RED. Part 2: Gauges, Graphs, Notifications, HTML

Here is the second article about creating a dashboard for object connected using the Dashboard module for Node-RED. In this tutorial, we will be interested in adding graphic displays. The Dashboard module offers 4 types of display (gauge, charts, text field, notification), the ui-control component which allows to change tab programmatically, and finally a field that allows to display HTML (already seen in the 1st part). If you missed the first part, the catch-up session is here.

Preparation

MySensors DHT22 temperature probe for generating measurements to be displayed

To illustrate the operation of the various output components of the Dashboard module, I suggest using measurements from a DHT22 MySensors temperature probe. Everything is already explained in this article.

MySensors Page

Open the Dashboard tab and add a new Tab. Name the MySensors for example. Add 2 groups:

  • Measures
  • Graphics

The Dashboard looks like this now.

node-red dashboard tabs

Change page by programming (ui-control)

Now let’s add a ui-control component that allows you to change pages (tab) programmatically. It accepts as input a payload in 2 forms:

  • {Tab: “MySensors”}: give the name of the landing page. Attention, it will be necessary to report any change of name of the page in the dashboard.
  • {Tab: 1}: or give the number of the page. Same, if we reorder the pages, we will have to apply the new index in the code.

To do this, add a function and paste this code

var msg = {};
msg.payload = {tab:"MySensors"};    // or 1

return msg;

node-red-dashboard-payload-ui-control

You can trigger the switch to another page from a command button for example.

node-red-dashboard-ui-control

Connection and extraction of temperature and humidity measurements from the MySensors

Now, connect Node-RED to the MySensors gateway to retrieve the measurements. If you’re new to this topic, start by reading this article. This flow (code below) uses the decoding flow of MySensors messages. A first filter makes it possible to extract the temperature measurement of the node of interest to us. The second filter is used to extract the moisture measurement.

node-red dashboard connect mysensors gateway extract value

Code of flow of connection and extraction of measurements

[{"id":"3d21e1ce.01afee","type":"tcp in","z":"df9159f.e304ea8","name":"MySensors Gateway","server":"client","host":"192.168.1.20","port":"5003","datamode":"stream","datatype":"utf8","newline":"","topic":"","base64":false,"x":210,"y":640,"wires":[["4fc18f88.1911"]]},{"id":"4fc18f88.1911","type":"function","z":"df9159f.e304ea8","name":"Decode MySensor Message","func":"/* MySensors v2 Message Decoder\n*  Payload : JSON object\n*  www.projetsdiy.fr - oct. 2016\n*/\nvar mySensorsMessage = {}\nvar newPayload = {};\nvar timestamp = new Date();\nvar message = msg.payload.toString();\nmessage = message.replace(/(\\r\\n|\\n|\\r)/gm, \"\");\nvar tokens = message.split(\";\")\nif(tokens.length == 6)\n{\n    mySensorsMessage.nodeId =       parseInt(tokens[0]);\n    mySensorsMessage.childSensorId= parseInt(tokens[1]);\n    mySensorsMessage.messageType =  parseInt(tokens[2]);\n    mySensorsMessage.ack =          parseInt(tokens[3]);\n    mySensorsMessage.subType =      parseInt(tokens[4]);\n    mySensorsMessage.value =        Number(tokens[5]);\n\n    var messageType = mySensorsMessage.messageType;\n    var subType = mySensorsMessage.subType;\n    var labelPresentation = [\"S_DOOR\",\"S_MOTION\",\"S_SMOKE\",\"S_LIGHT\",\"S_BINARY\",\"S_DIMMER\",\"S_COVER\",\"S_TEMP\",\"S_HUM\",\"S_BARO\",\"S_WIND\",\"S_RAIN\",\"S_UV\",\"S_WEIGHT\",\"S_POWER\",\"S_HEATER\",\"S_DISTANCE\",\"S_LIGHT_LEVEL\",\"S_ARDUINO_NODE\",\"S_ARDUINO_REPEATER_NODE\",\"S_LOCK\",\"S_IR\",\"S_WATER\",\"S_AIR_QUALITY\",\"S_CUSTOM\",\"S_DUST\",\"S_SCENE_CONTROLLER\",\"S_RGB_LIGHT\",\"S_RGBW_LIGHT\",\"S_COLOR_SENSOR\",\"S_HVAC\",\"S_MULTIMETER\",\"S_SPRINKLER\",\"S_WATER_LEAK\",\"S_SOUND\",\"S_VIBRATION\",\"S_MOISTURE\",\"S_INFO\",\"S_GAS\",\"S_GPS\",\"S_WATER_QUALITY\"];\n    var labelSet = [\"V_TEMP\",\"V_HUM\",\"V_STATUS\",\"V_LIGHT\",\"V_PERCENTAGE\",\"V_DIMMER\",\"V_PRESSURE\",\"V_FORECAST\",\"V_RAIN\",\"V_RAINRATE\",\"V_WIND\",\"V_GUST\",\"V_DIRECTION\",\"V_UV\",\"V_WEIGHT\",\"V_DISTANCE\",\"V_IMPEDANCE\",\"V_ARMED\",\"V_TRIPPED\",\"V_WATT\",\"V_KWH\",\"V_SCENE_ON\",\"V_SCENE_OFF\",\"V_HVAC_FLOW_STATE\",\"V_HVAC_SPEED\",\"V_LIGHT_LEVEL\",\"V_VAR1\",\"V_VAR2\",\"V_VAR3\",\"V_VAR4\",\"V_VAR5\",\"V_UP\",\"V_DOWN\",\"V_STOP\",\"V_IR_SEND\",\"V_IR_RECEIVE\",\"V_FLOW\",\"V_VOLUME\",\"V_LOCK_STATUS\",\"V_LEVEL\",\"V_VOLTAGE\",\"V_CURRENT\",\"V_RGB\",\"V_RGBW\",\"V_ID\",\"V_UNIT_PREFIX\",\"V_HVAC_SETPOINT_COOL\",\"V_HVAC_SETPOINT_HEAT\",\"V_HVAC_FLOW_MODE\",\"V_TEXT\",\"V_CUSTOM\",\"V_POSITION\",\"V_IR_RECORD\",\"V_PH\",\"V_ORP\",\"V_EC\",\"V_VAR\",\"V_VA\",\"V_POWER_FACTOR\"]\n    var labelInternal = [\"I_BATTERY_LEVEL\",\"I_TIME\",\"I_VERSION\",\"I_ID_REQUEST\",\"I_ID_RESPONSE\",\"I_INCLUSION_MODE\",\"I_CONFIG\",\"I_FIND_PARENT\",\"I_FIND_PARENT_RESPONSE\",\"I_LOG_MESSAGE\",\"I_CHILDREN\",\"I_SKETCH_NAME\",\"I_SKETCH_VERSION\",\"I_REBOOT\",\"I_GATEWAY_READY\",\"I_REQUEST_SIGNING\",\"I_GET_NONCE\",\"I_GET_NONCE_RESPONSE\",\"I_HEARTBEAT\",\"I_PRESENTATION\",\"I_DISCOVER\",\"I_DISCOVER_RESPONSE\",\"I_HEARTBEAT_RESPONSE\",\"I_LOCKED\",\"I_PING\",\"I_PONG\",\"I_REGISTRATION_REQUEST\",\"I_REGISTRATION_RESPONSE\",\"I_DEBUG\"]\n    \n    switch (messageType) {\n        case 0:     // Presentation\n            newPayload.timestamp = timestamp;\n            newPayload.mode =       \"Presentation\";\n            newPayload.type =       labelPresentation[subType];\n            break;\n        case 1:     // Set\n            newPayload.timestamp = timestamp;\n            newPayload.nodeId=      mySensorsMessage.nodeId;\n            newPayload.sensorId=    mySensorsMessage.childSensorId;\n            newPayload.mode=        \"Set\";\n            newPayload.type=        subType;\n            newPayload.typeLabel=   labelSet[subType];\n            newPayload.value=       mySensorsMessage.value;\n            break;\n        case 2:     // Req\n            newPayload.timestamp = timestamp;\n            newPayload.nodeId=      mySensorsMessage.nodeId;\n            newPayload.sensorId=    mySensorsMessage.childSensorId;\n            newPayload.mode=        \"Req\";\n            newPayload.type=        subType;\n            newPayload.typeLabel=   labelSet[subType];\n            newPayload.value=       mySensorsMessage.value;\n            break;  \n        case 3:     // Internal\n            newPayload.timestamp = timestamp;\n            newPayload.nodeId=      mySensorsMessage.nodeId;\n            newPayload.sensorId=    mySensorsMessage.childSensorId;\n            newPayload.mode=        \"Internal\";\n            newPayload.type=        subType;\n            newPayload.typeLabel=   labelInternal[subType];\n            newPayload.value=       mySensorsMessage.value;\n            break;    \n        case 4:     // Stream - OTA firmware update\n            newPayload.timestamp = timestamp;\n            newPayload.nodeId=      mySensorsMessage.nodeId;\n            newPayload.mode=        \"stream\";\n            break;\n        default:\n            break;\n    }\n\n    msg.payload = newPayload; \n} else {\n    msg.payload = \"Error! Nothing to decode\"\n}  \n\nreturn msg;","outputs":1,"noerr":0,"x":360,"y":560,"wires":[["e32665a5.08e548","ff9b32b9.a232c"]]},{"id":"e32665a5.08e548","type":"function","z":"df9159f.e304ea8","name":"Filtre : température noeud 3","func":"if (msg.payload.nodeId == 3 && msg.payload.type === 0) {\n    var msg;\n    msg.payload = msg.payload.value;\n    msg.topic = \"temperature\"\n    return msg;\n}    ","outputs":1,"noerr":0,"x":640,"y":620,"wires":[["f80bd8b2.372db8","3f202da1.ad8562","a1e15601.1df708"]]},{"id":"ff9b32b9.a232c","type":"function","z":"df9159f.e304ea8","name":"Filtre : humidité noeud 3","func":"if (msg.payload.nodeId == 3 && msg.payload.type === 1) {\n    var msg;\n    msg.payload = msg.payload.value;\n    msg.topic = \"humidity\"\n    return msg;\n}    ","outputs":1,"noerr":0,"x":630,"y":660,"wires":[["cdcc69de.3c1538","5e7f2a5b.57ba14","a1e15601.1df708"]]}]

Display a gauge (or donut, compass, level)

All that remains is to display the measurements in a gauge. Add a gauge component to the flow. There are 4 types of presentation:

  • Gauge: Suitable for displaying a measurement on a dial. For example, all the physical measurements in a known range (temperature, humidity, atmospheric pressure, wind speed …)
  • Donut: suitable for displaying several values. For example a distribution of power consumed by different devices
  • Compass: Suitable for indicating a direction. For example, the wind direction measured by a connected wind vane.
  • Level: suitable for displaying a level. For example the level of filling of a tank (water, domestic fuel oil …)

Here we will choose the type gauge. Other important parameters are:

  • Value format: This string defines how to display the measure. You can add text before and after. The variable is in the form {{value}}. Node-RED will replace this variable with the value contained in the input msg.payload. For example, for temperature, you will specify {{value}} ° C to add the unit after the measurement.
  • Label: a label placed below the value
  • Range: range of minimum and maximum value of the display
  • Color gradient (only for gauge and donut): we can define 3 colors, for example cold (blue), tepid (orange), warm (red).

node-red dashboard gauge donut compass level.

What gives this

node-red-dashboard-gauge-dht22-mysensors

Display a chart

The dashboard module offers 2 types of graphics:

  • Line Chart. It is very well suited to display real-time measurement
  • Bar Chart. Like the Donut, it is well suited to compare measurements. For example, the temperature in several rooms

It is possible to have several data on the same graph. Simply “plug in” the flows on the Node Chart. The Dashboard module is responsible for creating data for each incoming payload. We must try to put measurements with a beach close enough (or better still of the same nature) so that the rendering is correct.

The other parameters of the Node Chart:

  • Size: we can adapt the size to have a homogeneous display
  • Label: label of the graphic that will be displayed above it
  • Type: online or in bar
  • X-axis (only for Line Chart): time base of the abscissa scale in seconds, hours, days, week. You can customize the display, for example H: M, H: M: S …
  • Y-axis: minimum and maximum scale of the Y-axis
    Interpolate: interpolation method between two points. This is useful if the measurements are widely spaced over time.
  • Legend: Display or not the legend. Convenient when displaying multiple measurements on a single graph. The Dashboard automatically assigns a color
  • Blank label: text displayed if there is nothing to trace on the graph

node-red dashboard chart

What gives this

node-red dashboard chart temperature humidite

Text area and stealth notification

We will finish the presentation of the Dashboard module with the display of a text in a field and in a furtive notification. Let’s start by preparing the string to display

Assembling several payloads in a string

Node-RED is an asynchronous system, that is, operations do not necessarily end at the same time. In this case (yes I could have done it differently, but it’s a recurring problem with Node-RED), I extracted the temperature and humidity separately. This is necessary to simply display the measurement in a gauge, but it does not suit us to display it in a notification. Here’s how.

In each filter, I added a topic (eg temperature and humidity). A context variable is created; Each time a payload appears in the Node, we test the topic and store the value in the context object. Then we test if the context contains a value for temperature and humidity (and if it is not undefined). If this is the case, a correctly formatted string will be constructed, which will be enough to display. For example Temperature: 21.4 ° C – Humidity: 52.3%.

context.data = context.data || new Object();

switch (msg.topic) {
    case "Temperature":
        context.data.temperature = msg.payload;
        msg = null;
        break;
    case "Humidity":
        context.data.humidity = msg.payload;
        msg = null;
        break;
    default:
        msg = null;
    	break;

}

if(context.data.temperature !== null && context.data.humidity !== null && context.data.temperature !== undefined && context.data.humidity !== undefined) {
    msgOut = ""; //new Object();
    msgOut = "Température : " 
    msgOut += context.data.temperature.toString(); 
    msgOut+= "°C - Humidité : "; 
    msgOut+= context.data.humidity.toString();
    msgOut+= "%";
    context.data=null;
    var msg = {};
    msg.payload = msgOut;
    return msg;
}

Display text on the Dashboard

The Node Text makes it easy to display text in a payload. It is configured like this:

  • Size: the size of the field
  • Label: The label of the field.
  • Value format: you can customize the value display. For example, if you want to add a unit or a prefix. One could also display the topic (msg.topic) or directly access an element of a JSON object, for example msg.payload.data.value. In this case, we will not change anything.
  • Layout: allows you to choose a display mode. The label pasted to the left, the value to the right or another combination of position.

node-red dashboard text node

What gives this

node-red dashboard text node

Display a furtive notification

We will finish this tutorial by stealth notification. You can choose from 4 positions:

  • Upper right corner (Top Right)
  • Bottom Right
  • Top left corner (Top Left)
  • Lower right corner (Bottom Left)

Note. On tablet, smartphone or if the browser window is reduced, the message is displayed at the bottom of the screen (across the width).

The duration of the stealth message is also defined. By default, 3 seconds.

node-red dashboard mysensors dht22

What gives this

node-red dashboard module mysensors dht22

Flow code

Simply import this code into a flow if you do not want to complete all the steps. This flow also contains the first part of this tutorial.

node-red dashboard test complet toutes fonctions

[{"id":"6eecf682.454f38","type":"ui_button","z":"df9159f.e304ea8","name":"Bouton","group":"2a5abbd3.afa284","order":0,"width":0,"height":0,"label":"Bouton","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":240,"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":"<ul>\n <li ng-repeat=\"x in msg.payload\">\n <font color=\"red\">{{x.topic}}</font>\n    <ul>\n        <li>{{x.payload}}</li>\n    </ul>\n </li>\n</ul>","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":"baf63f2d.83977","type":"ui_text","z":"df9159f.e304ea8","group":"67f72709.c415f8","order":0,"width":0,"height":0,"name":"","label":"Dernière mesure","format":"{{msg.payload}}","layout":"row-spread","x":1140,"y":820,"wires":[]},{"id":"1d7d4ce7.8a5523","type":"ui_toast","z":"df9159f.e304ea8","position":"top right","displayTime":"5","name":"Notification","x":1130,"y":780,"wires":[]},{"id":"5e686a19.a16694","type":"ui_ui_control","z":"df9159f.e304ea8","name":"ui control","x":900,"y":500,"wires":[[]]},{"id":"4bb4277.686a0d8","type":"ui_button","z":"df9159f.e304ea8","name":"","group":"2a5abbd3.afa284","order":0,"width":0,"height":0,"label":"Aller aux capteurs MySensors","color":"","icon":"","payload":"","payloadType":"str","topic":"Vers Tab capteurs MySensors","x":310,"y":500,"wires":[["1e96adb5.fd25e2","ae9daf53.dbc43"]]},{"id":"ae9daf53.dbc43","type":"function","z":"df9159f.e304ea8","name":"Aller à MySensors","func":"var msg = {};\nmsg.payload = {tab:\"MySensors\"};    // ou/or 1\n\n\nreturn msg;","outputs":1,"noerr":0,"x":630,"y":500,"wires":[["5e686a19.a16694"]]},{"id":"3d21e1ce.01afee","type":"tcp in","z":"df9159f.e304ea8","name":"MySensors Gateway","server":"client","host":"192.168.1.20","port":"5003","datamode":"stream","datatype":"utf8","newline":"","topic":"","base64":false,"x":190,"y":640,"wires":[["4fc18f88.1911"]]},{"id":"4fc18f88.1911","type":"function","z":"df9159f.e304ea8","name":"Decode MySensor Message","func":"/* MySensors v2 Message Decoder\n*  Payload : JSON object\n*  www.projetsdiy.fr - oct. 2016\n*/\nvar mySensorsMessage = {}\nvar newPayload = {};\nvar timestamp = new Date();\nvar message = msg.payload.toString();\nmessage = message.replace(/(\\r\\n|\\n|\\r)/gm, \"\");\nvar tokens = message.split(\";\")\nif(tokens.length == 6)\n{\n    mySensorsMessage.nodeId =       parseInt(tokens[0]);\n    mySensorsMessage.childSensorId= parseInt(tokens[1]);\n    mySensorsMessage.messageType =  parseInt(tokens[2]);\n    mySensorsMessage.ack =          parseInt(tokens[3]);\n    mySensorsMessage.subType =      parseInt(tokens[4]);\n    mySensorsMessage.value =        Number(tokens[5]);\n\n    var messageType = mySensorsMessage.messageType;\n    var subType = mySensorsMessage.subType;\n    var labelPresentation = [\"S_DOOR\",\"S_MOTION\",\"S_SMOKE\",\"S_LIGHT\",\"S_BINARY\",\"S_DIMMER\",\"S_COVER\",\"S_TEMP\",\"S_HUM\",\"S_BARO\",\"S_WIND\",\"S_RAIN\",\"S_UV\",\"S_WEIGHT\",\"S_POWER\",\"S_HEATER\",\"S_DISTANCE\",\"S_LIGHT_LEVEL\",\"S_ARDUINO_NODE\",\"S_ARDUINO_REPEATER_NODE\",\"S_LOCK\",\"S_IR\",\"S_WATER\",\"S_AIR_QUALITY\",\"S_CUSTOM\",\"S_DUST\",\"S_SCENE_CONTROLLER\",\"S_RGB_LIGHT\",\"S_RGBW_LIGHT\",\"S_COLOR_SENSOR\",\"S_HVAC\",\"S_MULTIMETER\",\"S_SPRINKLER\",\"S_WATER_LEAK\",\"S_SOUND\",\"S_VIBRATION\",\"S_MOISTURE\",\"S_INFO\",\"S_GAS\",\"S_GPS\",\"S_WATER_QUALITY\"];\n    var labelSet = [\"V_TEMP\",\"V_HUM\",\"V_STATUS\",\"V_LIGHT\",\"V_PERCENTAGE\",\"V_DIMMER\",\"V_PRESSURE\",\"V_FORECAST\",\"V_RAIN\",\"V_RAINRATE\",\"V_WIND\",\"V_GUST\",\"V_DIRECTION\",\"V_UV\",\"V_WEIGHT\",\"V_DISTANCE\",\"V_IMPEDANCE\",\"V_ARMED\",\"V_TRIPPED\",\"V_WATT\",\"V_KWH\",\"V_SCENE_ON\",\"V_SCENE_OFF\",\"V_HVAC_FLOW_STATE\",\"V_HVAC_SPEED\",\"V_LIGHT_LEVEL\",\"V_VAR1\",\"V_VAR2\",\"V_VAR3\",\"V_VAR4\",\"V_VAR5\",\"V_UP\",\"V_DOWN\",\"V_STOP\",\"V_IR_SEND\",\"V_IR_RECEIVE\",\"V_FLOW\",\"V_VOLUME\",\"V_LOCK_STATUS\",\"V_LEVEL\",\"V_VOLTAGE\",\"V_CURRENT\",\"V_RGB\",\"V_RGBW\",\"V_ID\",\"V_UNIT_PREFIX\",\"V_HVAC_SETPOINT_COOL\",\"V_HVAC_SETPOINT_HEAT\",\"V_HVAC_FLOW_MODE\",\"V_TEXT\",\"V_CUSTOM\",\"V_POSITION\",\"V_IR_RECORD\",\"V_PH\",\"V_ORP\",\"V_EC\",\"V_VAR\",\"V_VA\",\"V_POWER_FACTOR\"]\n    var labelInternal = [\"I_BATTERY_LEVEL\",\"I_TIME\",\"I_VERSION\",\"I_ID_REQUEST\",\"I_ID_RESPONSE\",\"I_INCLUSION_MODE\",\"I_CONFIG\",\"I_FIND_PARENT\",\"I_FIND_PARENT_RESPONSE\",\"I_LOG_MESSAGE\",\"I_CHILDREN\",\"I_SKETCH_NAME\",\"I_SKETCH_VERSION\",\"I_REBOOT\",\"I_GATEWAY_READY\",\"I_REQUEST_SIGNING\",\"I_GET_NONCE\",\"I_GET_NONCE_RESPONSE\",\"I_HEARTBEAT\",\"I_PRESENTATION\",\"I_DISCOVER\",\"I_DISCOVER_RESPONSE\",\"I_HEARTBEAT_RESPONSE\",\"I_LOCKED\",\"I_PING\",\"I_PONG\",\"I_REGISTRATION_REQUEST\",\"I_REGISTRATION_RESPONSE\",\"I_DEBUG\"]\n    \n    switch (messageType) {\n        case 0:     // Presentation\n            newPayload.timestamp = timestamp;\n            newPayload.mode =       \"Presentation\";\n            newPayload.type =       labelPresentation[subType];\n            break;\n        case 1:     // Set\n            newPayload.timestamp = timestamp;\n            newPayload.nodeId=      mySensorsMessage.nodeId;\n            newPayload.sensorId=    mySensorsMessage.childSensorId;\n            newPayload.mode=        \"Set\";\n            newPayload.type=        subType;\n            newPayload.typeLabel=   labelSet[subType];\n            newPayload.value=       mySensorsMessage.value;\n            break;\n        case 2:     // Req\n            newPayload.timestamp = timestamp;\n            newPayload.nodeId=      mySensorsMessage.nodeId;\n            newPayload.sensorId=    mySensorsMessage.childSensorId;\n            newPayload.mode=        \"Req\";\n            newPayload.type=        subType;\n            newPayload.typeLabel=   labelSet[subType];\n            newPayload.value=       mySensorsMessage.value;\n            break;  \n        case 3:     // Internal\n            newPayload.timestamp = timestamp;\n            newPayload.nodeId=      mySensorsMessage.nodeId;\n            newPayload.sensorId=    mySensorsMessage.childSensorId;\n            newPayload.mode=        \"Internal\";\n            newPayload.type=        subType;\n            newPayload.typeLabel=   labelInternal[subType];\n            newPayload.value=       mySensorsMessage.value;\n            break;    \n        case 4:     // Stream - OTA firmware update\n            newPayload.timestamp = timestamp;\n            newPayload.nodeId=      mySensorsMessage.nodeId;\n            newPayload.mode=        \"stream\";\n            break;\n        default:\n            break;\n    }\n\n    msg.payload = newPayload; \n} else {\n    msg.payload = \"Error! Nothing to decode\"\n}  \n\nreturn msg;","outputs":1,"noerr":0,"x":360,"y":560,"wires":[["e32665a5.08e548","ff9b32b9.a232c"]]},{"id":"e32665a5.08e548","type":"function","z":"df9159f.e304ea8","name":"Filtre : température noeud 3","func":"if (msg.payload.nodeId == 3 && msg.payload.type === 0) {\n    var msg;\n    msg.payload = msg.payload.value;\n    msg.topic = \"Temperature\"\n    return msg;\n}    ","outputs":1,"noerr":0,"x":640,"y":620,"wires":[["3f202da1.ad8562","a1e15601.1df708","f89448e5.9519d8"]]},{"id":"3f202da1.ad8562","type":"ui_gauge","z":"df9159f.e304ea8","name":"Gauge : Température","group":"67f72709.c415f8","order":0,"width":0,"height":0,"gtype":"gage","title":"Température DHT22","label":"MySensors v2","format":"{{value}}°C","min":0,"max":"50","colors":["#66ccff","#ff8000","#ca3838"],"x":940,"y":600,"wires":[]},{"id":"ff9b32b9.a232c","type":"function","z":"df9159f.e304ea8","name":"Filtre : humidité noeud 3","func":"if (msg.payload.nodeId == 3 && msg.payload.type === 1) {\n    var msg;\n    msg.payload = msg.payload.value;\n    msg.topic = \"Humidity\"\n    return msg;\n}    ","outputs":1,"noerr":0,"x":630,"y":660,"wires":[["cdcc69de.3c1538","a1e15601.1df708","f89448e5.9519d8"]]},{"id":"cdcc69de.3c1538","type":"ui_gauge","z":"df9159f.e304ea8","name":"Gauge : Humidité","group":"67f72709.c415f8","order":0,"width":"0","height":"0","gtype":"gage","title":"Humidité DHT22","label":"MySensors v2","format":"{{value}}%","min":0,"max":"100","colors":["#1a25ab","#e6e600","#ca3838"],"x":930,"y":640,"wires":[]},{"id":"a1e15601.1df708","type":"function","z":"df9159f.e304ea8","name":"Attendre temperature & humidité","func":"context.data = context.data || new Object();\n\nswitch (msg.topic) {\n    case \"Temperature\":\n        context.data.temperature = msg.payload;\n        msg = null;\n        break;\n    case \"Humidity\":\n        context.data.humidity = msg.payload;\n        msg = null;\n        break;\n    default:\n        msg = null;\n    \tbreak;\n\n}\n\nif(context.data.temperature !== null && context.data.humidity !== null && context.data.temperature !== undefined && context.data.humidity !== undefined) {\n\tmsgOut = \"\"; //new Object();\n    msgOut = \"Température : \" \n    msgOut += context.data.temperature.toString(); \n    msgOut+= \"°C - Humidité : \"; \n    msgOut+= context.data.humidity.toString();\n    msgOut+= \"%\";\n    context.data=null;\n    var msg = {};\n    msg.payload = msgOut;\n\treturn msg;\n} \n//else return msg;","outputs":1,"noerr":0,"x":980,"y":720,"wires":[["1d7d4ce7.8a5523","baf63f2d.83977"]]},{"id":"f89448e5.9519d8","type":"ui_chart","z":"df9159f.e304ea8","name":"Graph : Température & Humidité","group":"45ccf5ba.b188ac","order":0,"width":"6","height":"9","label":"Température & Humidité","chartType":"line","legend":"true","xformat":"%H:%M","interpolate":"linear","nodata":"Rien à afficher","ymin":"0","ymax":"80","removeOlder":"12","removeOlderUnit":"3600","x":970,"y":680,"wires":[[],[]]},{"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":"67f72709.c415f8","type":"ui_group","z":"","name":"Mesures","tab":"70b0ee04.be689","order":1,"disp":true,"width":"6"},{"id":"45ccf5ba.b188ac","type":"ui_group","z":"","name":"Graphiques","tab":"70b0ee04.be689","order":2,"disp":true,"width":"6"},{"id":"99f501d2.56c31","type":"ui_tab","z":"","name":"Ecran Principal","icon":"home","order":2},{"id":"70b0ee04.be689","type":"ui_tab","z":"","name":"MySensors","icon":"dashboard","order":3}]

Subscribe to the weekly newsletter

No spam and no other use will be made of your email. You can unsubscribe anytime.

DIY Projects