Enregistrer les mesures d’un objet connecté MySensors vers InfluxDB à l’aide de Node-RED [Màj]

Node-RED est une solution très simple pour collecter les mesures et les états d’objets connectés. On pourra très simplement utiliser Node-RED pour ensuite stocker les mesures dans une base de données InfluxDB. InfluxDB est une base de données adaptée au stockage de mesures qui dépendent du temps, pour en savoir plus sur InfluxDB, je vous conseille de commencer par lire cet article. Dans ce tutoriel, nous allons récupérer les mesures d’une sonde DHT22 transmises par ondes radio à l’aide de la librairie MySensors.

 

Si vous découvrez la base de données InfluxDB, lisez l’article précédent, qui explique comment l’installer sur macOS ou Windows et (assez rapidement) comment l’utiliser.

Installation du module InfluxDB pour Node-RED

Il existe un module pour enregistrer ou récupérer des données sur une base InfluxDB. Ouvrez le gestionnaire de palette et lancez une recherche avec le mot clé influxdb.

Installez le et rafraichissez le navigateur lorsque l’installation est terminée.

node-red influxdb install module

La palette contient 2 nouveaux Nodes dans la section Storage.

node-red-influxdb-storage-palette

Remarque. Il est aussi possible d’utiliser l’API HTTP pour enregistrer dans InfluxDB mais c’est moins facile car il faut “fabriquer” ses propres requêtes. Avec le plugin, le travail est pré-maché.

Préparation des tables sur InfluxDB

Avant de pouvoir enregistrer des données dans une base influxDB, il est nécessaire de créer les bases nécessaires et éventuellement ajouter un utilisateur avec les droits adéquats. Si vous avec un usage privé, ce n’est pas une obligation.

Ouvrez un Terminal et lancez le shell InfluxDB avec la commande influx.

Nous allons créer deux bases. La première temperature contiendra toutes les mesures de température et humidite.

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

Si on veut, on peut ajouter une politique de rétention. Par exemple, on garde les données pendant 1 an

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

Vérifions ce que ça donne.

> 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

>

Parfait, tout est prêt.

Extraction des données de la sonde DHT22 MySensors

Les mesures que nous allons enregistrer proviennent d’une sonde DHT22 MySensors développée dans un précédent tutoriel ainsi que le Node de décodage de messages MySensors développé pour ce tutoriel. Il suffit maintenant d’ajouter une fonction qui renvoi la valeur de la température (ou de l’humidité dans un second flow). Les mesures proviennent du noeud 3.

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

Enregistrez les mesures dans la base InfluxDB

Maintenant, on ajoute un Node InfluxDB In. On commence par configurer une connexion

node-red influxdb nouvelle connexion

Elle prend comme paramètres :

  • Host : l’adresse IP du serveur InfluxDB. 127.0.0.1 si elle est sur la même machine que Node-RED
  • Port : par défaut c’est le 8086
  • Database : ici temperature ou humidité
  • Username, Password : si vous avez définit un utilisateur pour cette base de données

node-red influxdb configuration connexion

Puis il ne reste plus qu’à définir le nom de la mesure (measurement).

node-red influxdb measurementUne fois terminé, on obtient ce flow. Il ne reste plus qu’à le déployer pour commencer à enregistrer les mesures dans les bases de données.
node-red influx db mysensors dht22

 

Code du flow

Collez ce flow pour tester directement ce tutoriel.

[{"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":""}]

Maintenant, il ne vous reste plus qu’à lire le prochain tutoriel qui explique comment tracer des (très beaux) graphiques avec Grafana.

grafana graph dashboard mysensors dht22 temperature humidite

Print Friendly, PDF & Email

Inscrivez-vous à la newsletter hebdomadaire

Aucun spam et aucun autre usage ne sera fait de votre email. Vous pouvez vous désinscrire à tout moment.

Comparateur de prix

Bons plans

Les offres suivantes se terminent bientôt. Utilisez le coupon indiqué pour profiter du prix promo

Tags:

Domotique et objets connectés à faire soi-même