It is very easy to create its own connected Arduino-based objects that communicate by radio waves using the library MySensors v2 and to use them in a project Node-RED. For this tutorial, we will use a simple probe temperature and humidity (DHT22). We will post the measures temperature and humidity using the Dashboard module.
Prepare a DHT22 MySensors temperature probe
I took the code and the wiring of the previous project. You also need a network gateway (follow this previous tutorial to prepare one) or a serial gateway.
List of components
Arduino Nano (advice) | |
nRF24L01 radio module | |
3V3 plate adapter with tension regulater (for nRF24L01 or nRF24L01+PA+LNA module) | |
Temperature and humidity sensor | |
Jumper Dupont | |
Breadboard |
Circuit : nRF24L01 and DHT22
Code
Create a new Arduino project and download the following code in the Arduino Nano.
/** * The MySensors Arduino library handles the wireless radio link and protocol * between your home built sensors/actuators and HA controller of choice. * The sensors forms a self healing radio network with optional repeaters. Each * repeater and gateway builds a routing tables in EEPROM which keeps track of the * network topology allowing messages to be routed to nodes. * * Created by Henrik Ekblad <henrik.ekblad@mysensors.org> * Copyright (C) 2013-2015 Sensnology AB * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors * * Documentation: http://www.mysensors.org * Support Forum: http://forum.mysensors.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * ******************************* * * REVISION HISTORY * Version 1.0 - PROJETS DIY * * DESCRIPTION * Example sketch showing how to measue light level using a LM393 photo-resistor * http://www.mysensors.org/build/light */ // Enable debug prints to serial monitor #define MY_DEBUG // Mode Radio / Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 #define MY_RF24_PA_LEVEL RF24_PA_LOW // Object Node #define MY_NODE_ID 3 #include <SPI.h> #include <MySensors.h> #include <DHT.h> #define CHILD_ID_TEMP 0 #define CHILD_ID_HUM 1 #define SLEEP_NODE true // True to activate Sleep Mode unsigned long SLEEP_TIME = 10 * 1000; // Sleep time between reads (in milliseconds) #define DHTPIN 3 // what pin we're connected to #define DHTTYPE DHT22 // DHT 22 (AM2302), DHT11 float lastTemp; float lastHum; boolean metric = true; MyMessage msgHum(CHILD_ID_HUM, V_HUM); MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP); void setup() { } void presentation() { /Send the sketch version information to the gateway and Controller sendSketchInfo("Sonde Temp/Hum DHT22", "1.0"); // Declare sensors attached to the node present(CHILD_ID_TEMP, S_TEMP); present(CHILD_ID_HUM, S_HUM); } void loop() { DHT dht(DHTPIN, DHTTYPE,3); float temperature = dht.readTemperature(); float humidity = dht.readHumidity(); if (isnan(temperature)) { Serial.println("Impossible to read temperature on DHT"); } else { if (temperature != lastTemp) { lastTemp = temperature; if (!metric) { temperature = dht.readTemperature(true); } Serial.print("T: "); Serial.print(temperature); Serial.print(" | H: "); Serial.println(humidity); send(msgTemp.set(temperature, 1)); send(msgHum.set(humidity, 1)); } else { Serial.println("Same Temperature => force send"); Serial.print("T: "); Serial.print(temperature); Serial.print(" | H: "); Serial.println(humidity); send(msgTemp.set(temperature, 1)); send(msgHum.set(humidity, 1)); } } if (SLEEP_NODE) { Serial.println("Sleep"); sleep(SLEEP_TIME); } else { delay (SLEEP_TIME); } }
Integrate a MySensors object into a Node-RED flow
There is an official plugin MySensor ( http://flows.nodered.org/node/node-red-contrib-mysensors ). For this project, I suggest you use the flow that I developed and published on the Node-RED online bookshop (http://flows.nodered.org/flow/fa02078c160cb3e00e09f4980b534490 ). He is responsible for decoding the messages MySensors and referral output a JSON object. It is easier to filter values you want for a given node.
Code of the flow MySensors Decoder
[{"id":"f4fd4940.32ba8","type":"function","z":"eb4ead14.fd77f","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 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 \n newPayload.mode = \"Presentation\";\n newPayload.type = labelPresentation[subType];\n break;\n case 1: // Set\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.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.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.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":394.5555419921875,"y":279.5555725097656,"wires":[["22cb3401.ef7e24","2d12c5a2.7304aa","fd30fa09.244ce8"]]}]
Connect Node-RED to a MySensors network gateway
To connect to a network MySensors gateway, we will use the Protocol tcp (filed in Input).
Set up the Node like this:
- Type: Connect To
- Port: 5003 (by default, otherwise the port you configured for your gateway)
- At host : ip address of the gateway
- Output : stream of / string
- You can also change the name displayed on the flow.
- Click Done to save the configuration
You can now connect the bridge to message decoder. By plugging a debug Node, you can read very easily all the (decoded) messages that pass over the network MySensors!
Use log to watch the measures, it is good, but there for to be a little better! Let’s add a GUI to our project Node-RED. Open the palette Manager. It opens to the left of the screen. Go to the Install tab and install the Dashboard module. Refresh browser at the end of the installation page that the palette is displayed (bottom).
Now let’s add a function that filters as you want to display from the DHT22 node. Paste this code
if (msg.payload.nodeId == 3 & msg.payload.type = 0) {var msg;} Msg.payload = msg.payload.value; return msg; }
In this case, we don’t reference the value (value) that if the message comes from the node 3 (nodeId == 3) and that it is a type 0 (temperature, V_TEMP) or 1 (moisture, V_HUM).
From the palette dashboard drop one gauge and set up like this.
Must be already created one Tab . It is a WEB page. Moving from one page to the other from the menu in the upper left corner.
Then one Group. Can be grouped views (switches, gauge, graph, form…) by (Group).
Finally you can adjust the display settings of the gauge. There are 4 types of display:
- Gauge
- Donut
- Compass
- Level
Also add a chart. It works on the same principle. It must associate it with the Group a Tab
Do the same for moisture measurement. Here is the completed flow.
Now, to open a new page in the browser and enter the following address
http://IP_NODE_RED:1880/ui
And so, now you have a graphical display of your DHT22 MySensors probe in a few minutes!
You don’t like blue, no problem. Turn on Node-RED. Go to the dashboard tab located next to the debug tab. In the Theme list, choose Dark and deploy the project.
Return to the UI page for your project!
You can also directly import this flow if you do not complete all the steps of this tutorial.
[{"id":"4c979a2.0f86f64","type":"tcp in","z":"5c2ea4a9.8713cc","name":"MySensors Gateway","server":"client","host":"192.168.1.20","port":"5003","datamode":"stream","datatype":"utf8","newline":"","topic":"","base64":false,"x":154.00001525878906,"y":296,"wires":[["7710e899.e4b198"]]},{"id":"7710e899.e4b198","type":"function","z":"5c2ea4a9.8713cc","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 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 \n newPayload.mode = \"Presentation\";\n newPayload.type = labelPresentation[subType];\n break;\n case 1: // Set\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.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.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.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":291.66668701171875,"y":424.6278991699219,"wires":[["f10887ac.6a2f28","e4304f11.8e755","3c923a76.ea6cb6"]]},{"id":"f10887ac.6a2f28","type":"function","z":"5c2ea4a9.8713cc","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 return msg;\n} ","outputs":1,"noerr":0,"x":574.5,"y":394,"wires":[["7a1e3f92.b811d","f8fdeb6d.dcb858"]]},{"id":"7a1e3f92.b811d","type":"ui_gauge","z":"5c2ea4a9.8713cc","name":"Température","group":"febe591f.8ca1f8","order":0,"width":0,"height":0,"gtype":"gage","title":"Température DHT22","label":"MySensors v2","format":"{{value}}°C","min":0,"max":"50","colors":["#00b500","#e6e600","#ca3838"],"x":825.5,"y":358,"wires":[]},{"id":"e4304f11.8e755","type":"function","z":"5c2ea4a9.8713cc","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 return msg;\n} ","outputs":1,"noerr":0,"x":564.8888549804688,"y":455.92767333984375,"wires":[["8e065da0.32b5f","e22f8ceb.eecbb"]]},{"id":"8e065da0.32b5f","type":"ui_gauge","z":"5c2ea4a9.8713cc","name":"Humidité","group":"febe591f.8ca1f8","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":811.8888549804688,"y":466.92767333984375,"wires":[]},{"id":"f8fdeb6d.dcb858","type":"ui_chart","z":"5c2ea4a9.8713cc","name":"Température","group":"45ccf5ba.b188ac","order":0,"width":0,"height":0,"label":"Température","chartType":"line","legend":"false","xformat":"%H:%M","interpolate":"linear","nodata":"","ymin":"0","ymax":"50","removeOlder":1,"removeOlderUnit":"3600","x":827.5,"y":413,"wires":[[],[]]},{"id":"e22f8ceb.eecbb","type":"ui_chart","z":"5c2ea4a9.8713cc","name":"Humidité","group":"45ccf5ba.b188ac","order":0,"width":0,"height":0,"label":"Humidité","chartType":"line","legend":"false","xformat":"%H:%M","interpolate":"linear","nodata":"","ymin":"0","ymax":"100","removeOlder":1,"removeOlderUnit":"3600","x":808,"y":514,"wires":[[],[]]},{"id":"3c923a76.ea6cb6","type":"debug","z":"5c2ea4a9.8713cc","name":"Message décodé","active":true,"console":"false","complete":"payload","x":484.5,"y":295,"wires":[]},{"id":"febe591f.8ca1f8","type":"ui_group","z":"","name":"Mesures","tab":"99f501d2.56c31","disp":true,"width":"6"},{"id":"45ccf5ba.b188ac","type":"ui_group","z":"","name":"Graphiques","tab":"99f501d2.56c31","disp":true,"width":"6"},{"id":"99f501d2.56c31","type":"ui_tab","z":"","name":"Salon","icon":"dashboard"}]
Node-RED is really magical, nothing prevents you from designing your own home automation software and much more!
- Xiaomi Mijia Honeywell Smoke Detector Test with Domoticz, Emergency Notification with PushOver
- Test Zigbee2MQTT gateway. Part 2, include Xiaomi Aqara or Mijia accessories to Domoticz with Node-RED
- #Test Zigbee2MQTT project, hack of the Xiaomo Aqara Smart Home Gateway. Part 1: assembly, demo with Node-RED, 3D printed case [update]
- Install Node-RED on Raspbian Jessie Lite on a Raspberry Pi Zero W
- Node-RED + MQTT + ESP8266: how to drive an articulated PTZ system in WiFi
- Orange Pi: test of the OPI.GPIO package for Node-Red (node-red-contrib-opi-gpio)