Node-RED (Tutorial): saving MySensors measurements on InfluxDB

In this tutorial we will see how to record measurements from a DHT22 probe sent via radio waves using the MySensors library using Node-RED in an InfluxDB database. If you discover the InfluxDB database, see the previous article, which explains how to install it on MacOS or Windows and (rather quickly) how to use it.

Installing the InfluxDB Module

There is a module to save or retrieve data on an InfluxDB database. Open the palette manager and run a search with the keyword influxdb.

Install and refresh the browser when installation is complete.

node-red influxdb install module

The palette contains 2 new Nodes in the Storage section.

node-red-influxdb-storage-palette

Note. It is also possible to use the HTTP API to register in InfluxDB.

Preparing tables on InfluxDB

Before you can save data in an influxDB database, you need to create the necessary databases and possibly add a user with the appropriate rights. If you with private use, this is not an obligation.

Open a Terminal and run the InfluxDB shell with the influx command.

We will create two bases. The first temperature will contain all the measurements of temperature and humidity, you have understood where I am coming from.

> CREATE DATABASE temperature
> CREATE DATABSE humidite
> SHOW DATABASES
name: databases
name
----
_internal
temperature
humidite

If you want, you can add a retention policy. For example, data is kept for 1 year.

> CREATE RETENTION POLICY "un_an" ON temperature DURATION 365d REPLICATION 1 DEFAULT
> CREATE RETENTION POLICY "un_an" ON humidite DURATION 365d REPLICATION 1 DEFAULT
>

Let’s see what happens.

> SHOW RETENTION POLICIES ON temperature
name	duration	shardGroupDuration	replicaN	default
----	--------	------------------	--------	-------
autogen	0s		168h0m0s		1		false
un_an	8760h0m0s	168h0m0s		1		true

> SHOW RETENTION POLICIES ON humidite
name	duration	shardGroupDuration	replicaN	default
----	--------	------------------	--------	-------
autogen	0s		168h0m0s		1		false
un_an	8760h0m0s	168h0m0s		1		true

>

All is ready !

Extraction of data from the DHT22 MySensors

The measurements that we are going to record come from a DHT22 MySensors probe developed in a previous tutorial as well as the Node of decoding messages MySensors. It is now enough to add a function that returns the value of the temperature (or the humidity in a second flow). The measurements come from node 3.

if (msg.payload.nodeId == 3 && msg.payload.type === 0) {
    msg.payload = msg.payload.value
    return msg;
}

Save the measurements in the InfluxDB database

Now we add a Node InfluxDB In. We start by configuring a connection.

node-red influxdb nouvelle connexion

It takes as parameters:

  • Host: The IP address of the InfluxDB server. 127.0.0.1 if it is on the same machine as Node-RED
  • Port: default is 8086
  • Database: here temperature or humidity
  • Username, Password: If you have defined a user for this database

node-red influxdb configuration connexion

Then it remains to define the name of the measurement.

node-red influxdb measurement

Once completed, this flow is obtained. It only remains to deploy it to start recording the measurements in the databases.

node-red influx db mysensors dht22

Flow code

Paste this flow to test this tutorial directly.

[{"id":"e8737ba4.f46b78","type":"tcp in","z":"adaea2ae.4fd6e","name":"MySensors Gateway","server":"client","host":"192.168.1.20","port":"5003","datamode":"stream","datatype":"utf8","newline":"","topic":"","base64":false,"x":537,"y":414,"wires":[["996a086d.8218e8"]]},{"id":"996a086d.8218e8","type":"function","z":"adaea2ae.4fd6e","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":722.6666717529297,"y":503.6278991699219,"wires":[["f9385244.3414c","ede1a3b3.dbe33","955ef8ed.fc3088"]]},{"id":"51b6aac6.edddb4","type":"influxdb out","z":"adaea2ae.4fd6e","influxdb":"aa489748.997028","name":"","measurement":"noeud3","x":1290,"y":440,"wires":[]},{"id":"f9385244.3414c","type":"function","z":"adaea2ae.4fd6e","name":"Filtre : temperature noeud 3","func":"if (msg.payload.nodeId == 3 && msg.payload.type === 0) {\n    msg.payload = msg.payload.value\n    return msg;\n}    ","outputs":1,"noerr":0,"x":1040,"y":500,"wires":[["51b6aac6.edddb4"]]},{"id":"c79e8371.aa2ed","type":"influxdb out","z":"adaea2ae.4fd6e","influxdb":"14487bde.9199c4","name":"","measurement":"noeud3","x":1290,"y":580,"wires":[]},{"id":"ede1a3b3.dbe33","type":"function","z":"adaea2ae.4fd6e","name":"Filtre : humidite noeud 3","func":"if (msg.payload.nodeId == 3 && msg.payload.type === 1) {\n    msg.payload = msg.payload.value\n    return msg;\n}    ","outputs":1,"noerr":0,"x":1030,"y":540,"wires":[["c79e8371.aa2ed"]]},{"id":"aa489748.997028","type":"influxdb","z":"","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"temperature","name":""},{"id":"14487bde.9199c4","type":"influxdb","z":"","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"humidite","name":""}]

In the next tutorial we will see how to create (very beautiful) graphics with Grafana.

Subscribe to the weekly newsletter

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

Tags:

We will be happy to hear your thoughts

Leave a Reply

DIY Projects
%d bloggers like this: