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.
Sommaire
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.
La palette contient 2 nouveaux Nodes dans la section Storage.
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
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
Puis il ne reste plus qu’à définir le nom de la mesure (measurement).
Une 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.
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.
|
Avez-vous aimé cet article ?