MySensors v2.3. Décoder et envoyer des messages avec Node-RED • Domotique et objets connectés à faire soi-même

Les objets MySensors communiquent entre eux sous la forme de petits messages envoyés par ondes radio. Il est très facile de décoder les messages en suivants les spécifications techniques de l’API série disponible sur le site officiel du projet

Dernière mise à jour : 25 mars 2020

La librairie MySensors permet de faciliter le développement d’applications en tout genre (mobile, robotique, domotique) sans avoir à gérer la couche de communication entre les appareils. Nous allons utiliser Node-RED pour décoder les messages reçus par une gateway réseau ou série. Pour vous connecter à un réseau d’objets MySensors, vous aurez besoin d’une Gateway réseau WiFi. Suivez ce tutoriel pour en fabriquer une avec un ESP8266 avant d’aller plus loin.

Pour en savoir plus sur la librairie MySensors, vous pouvez commencer par lire cet article.

Structure d’un message MySensors (API)

MySensors communique avec de petits messages de 32 bytes (la taille maximale des messages envoyés par une puce nRF24L01). L’entête (header) du message d’une taille de 7 bytes est constitué ainsi :

node-id ; child-sensor-id ; message-type ; ack ; sub-type ; payload \n

  • node-id : le numéro du noeud.
  • child-sensor-id : l’identifiant d’un enfant. Par exemple la température mesurée par un capteur DHT22.
  • message-type : type de message
    • 0. Présentation du noeud. Il est envoyé lors de l’exécution de la fonction presentation() au démarrage du noeud
    • 1. Set. Envoi de données par un capteur
    • 2. Req. Demande à un actionneur d’executer la commande demandée
    • 3. Internal. Message interne
    • 4. Stream. Utilisé pour la mise à jour sans fil (OTA)
  • ack : demande d’accusé réception (ou accusé reception)
  • sub-type : le sous-type dépend du message-type
  • payload : contenu du message. Il est limité à 25 bytes.

25 bytes peut sembler faible, mais le nRF24L01 n’est pas conçu pour transmettre de grands messages, plutôt des états ou des mesures physiques.

Cas des messages MQTT

Les messages MQTT ont une structure similaire. Le prefix peut être personnalisé dans le sketch Arduino.

prefix/node-id/child-sensor-id/message-type/ack/sub-type + payload

Comment se connecter à une gateway MySensors depuis Node-RED

On dispose de trois types de gateway MySensors. La serial gateway qui se branche sur le port USB d’un ordinateur ou d’un Raspberry. Elle est pratique pour débuter et lire les messages de debug envoyés sur le port série (par exemple avec le moniteur série de l’IDE Arduino). La passerelle réseau est maintenant très simple (et pas cher) à fabriquer à l’aide d’un ESP8266 (toutes les explications dans cet article). On peut l’installer (la cacher !) dans en endroit ou la réception radio est meilleure et on ne monopolise pas un port USB du Raspberry Pi.

Serial gateway, passerelle série connectée sur le port USB

Pour se connecter à une passerelle série, ajoutez un Node serial (dans Input)

Ouvrez le pour le configurer et appuyez sur le crayon pour configurer le port série. Appuyez sur la loupe et choisissez le port USB sur lequel est branché la gateway. Par exemple /dev/ttyUSB0.

Par défaut, la vitesse de communication avec la gateway est de 115200 bauds. Laissez la configuration par défaut. 8 bits Data, Parity None, Stop Bits 1.

Enregistrez la configuration en appuyant sur Done.

LAN Gateway, pour se connecter à une passerelle sur le réseau WiFi

Pour se connecter à une passerelle réseau, nous allons utiliser un Node TCP

Configurez la connexion ainsi :

  • Type : Connect to
  • Port : 5003 par défaut (à adapter à votre configuration)
  • at host : l’adresse ip de la gateway réseau
  • output : stream of … String
  • Donnez un nom
  • Enregistrez avec Done

Gateway MQTT

Dernière solution, utiliser un broker MQTT. Rien de bien compliqué ici, il suffit de se connecter au broker MQTT comme d’habitude.

Installer le plugin node-red-contrib-mysensors pour Node-RED

Le plugin node-red-contrib-mysensors développé par Thomas Mørch permet de décoder et d’envoyer des messages à un réseau d’objets MySensors. Le Plugin MySensors peut également d’enregistrer les états et les mesures dans une base de données sqlite.

Ouvrez le gestionnaire de palette de Node-RED

Faites une recherche sur le mot clé sqlite

Ensuite, vous pouvez installer le plugin mysensor. Vous trouverez 2 plugins :

  • node-red-contrib-mysensors, permet de décoder et d’envoyer des messages MySensors

  • node-red-contrib-virtual-mysensors, permet de créer des objets MySensors virtuels pour tester votre flow sans avoir d’objet à disposition

Vous disposer maintenant d’une nouvelle palette appelée mysensors. Elle est constituée de cinq Nodes

  • mysdecode : décode les messages MySensors
  • mysencode : encodeur un message MySensors
  • mysencap : prépare le message à envoyer au noeud
  • mysdebug : affiche le message MySensors brut
  • myscontroller : permet d’enregistrer dans une base de données sqlite l’activité des noeuds MySensors

Fonction mysdebug

Partons par la fin pour une fois. La fonction mysdebug permet de décoder et de rendre plus lisible les messages reçus en envoyés par la gateway. Chaque code est remplacé par sa signification.

Messages décodés affichés dans la console. Tout n’est pas correctement décodé (dans la version actuelle du plugin).

Comment utiliser la fonction mysdecode

Cette fonction permet de décoder les messages MySensors. Pour l’utiliser, il suffit de la brancher à une gateway (série, réseau ou MQTT). En sortie (payload), on récupère directement le payload de chaque message. Chaque information disponible est publiée sur un flux différent :

  • msg.payload : contenu du message (payload) envoyé par le noeud
  • msg.nodeId : noeud d’origine du message
  • msg.childSensorId : Id de l’enfant attaché au noeud
  • msg.messageType : type de message
  • msg.ack : demande d’accusé réception
  • msg.subType : sous-type de message

Cette architecture présente des avantages et des inconvénients. On récupère directement en sortie le payload de chaque message mais cela peut rapidement devenir compliqué pour filtrer les données de tel ou tel capteur.

Messages décodés affichés dans la console.

Code du flow

[{"id":"62351421.a2a7ec","type":"serial in","z":"eb4ead14.fd77f","name":"MySensors Serial Gateway","serial":"219cc581.f9b252","x":145.6666717529297,"y":134.66666412353516,"wires":[["2027984.714eb68","d8174c63.f752a"]]},{"id":"893c2411.1181e8","type":"debug","z":"eb4ead14.fd77f","name":"","active":false,"console":"false","complete":"payload","x":559,"y":35,"wires":[]},{"id":"d8174c63.f752a","type":"mysdecenc","z":"eb4ead14.fd77f","name":"","x":372.5,"y":36,"wires":[["893c2411.1181e8","80842fe1.74a72"]]},{"id":"80842fe1.74a72","type":"debug","z":"eb4ead14.fd77f","name":"","active":false,"console":"false","complete":"nodeId","x":559.5,"y":80,"wires":[]},{"id":"2027984.714eb68","type":"mysdebug","z":"eb4ead14.fd77f","name":"","x":374.5,"y":135,"wires":[["ed9596a0.eaa2b8"]]},{"id":"ed9596a0.eaa2b8","type":"debug","z":"eb4ead14.fd77f","name":"","active":false,"console":"false","complete":"false","x":561.5,"y":140,"wires":[]},{"id":"219cc581.f9b252","type":"serial-port","z":"","serialport":"/dev/ttyUSB0","serialbaud":"115200","databits":"8","parity":"none","stopbits":"1","newline":"\\n","bin":"false","out":"char","addchar":false}]

Fonction pour décoder un message (objet JSON) sans le plugin Node-RED

Le plugin contrib-mysensors est très efficace mais il ne permet (pour le moment du moins) que d’extraire le payload (contenu du message). Dans certains cas, il peut s’avérer nécessaire d’extraire des informations supplémentaire. Voici une petite fonction que vous pouvez ajouter à vos projets Node-RED. Elle remplace le plugin node-red-contrib-mysensors.

Pour une gateway Serial ou LAN

La fonction décode le message est décodé en renvoyant un objet JSON au format clé:valeur.

Elle renvoie un payload avec les informations suivantes :

  • nodeId : Id du noeud publiant le message
  • sensorId : Id de l’enfant
  • mode : presentation, set, req, internal, stream
  • type : numéro du sous-type de donnée (fonction du mode)
  • typeLabel : libellé du type de données correspondant
  • value : contenu du message (payload)

Vous pouvez également installer ce flow depuis le site officiel de Node-RED http://flows.nodered.org/flow/fa02078c160cb3e00e09f4980b534490

/* MySensors v2 Message Decoder
*  Payload : JSON object
*  www.projetsdiy.fr - oct. 2016
*/
var mySensorsMessage = {}
var newPayload = {};
var message = msg.payload.toString();
message = message.replace(/(\r\n|\n|\r)/gm, "");
var tokens = message.split(";")
if(tokens.length == 6)
{
    mySensorsMessage.nodeId =       parseInt(tokens[0]);
    mySensorsMessage.childSensorId= parseInt(tokens[1]);
    mySensorsMessage.messageType =  parseInt(tokens[2]);
    mySensorsMessage.ack =          parseInt(tokens[3]);
    mySensorsMessage.subType =      parseInt(tokens[4]);
    mySensorsMessage.value =        Number(tokens[5]);

    var messageType = mySensorsMessage.messageType;
    var subType = mySensorsMessage.subType;
    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"];
    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"]
    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"]
    
    switch (messageType) {
        case 0:     // Presentation
            newPayload.mode =       "Presentation";
            newPayload.type =       labelPresentation[subType];
            newPayload.value =      mySensorsMessage.value;
            break;
        case 1:     // Set
            newPayload.nodeId =     mySensorsMessage.nodeId;
            newPayload.sensorId =   mySensorsMessage.childSensorId;
            newPayload.mode=        "Set";
            newPayload.type=        subType;
            newPayload.typeLabel=   labelSet[subType];
            newPayload.value=       mySensorsMessage.value;
            break;
        case 2:     // Req
            newPayload.nodeId=      mySensorsMessage.nodeId;
            newPayload.sensorId=    mySensorsMessage.childSensorId;
            newPayload.mode=        "Req";
            newPayload.type=        subType;
            newPayload.typeLabel=   labelSet[subType];
            newPayload.value=       mySensorsMessage.value;
            break;  
        case 3:     // Internal
            newPayload.nodeId=      mySensorsMessage.nodeId;
            newPayload.sensorId=    mySensorsMessage.childSensorId;
            newPayload.mode=        "Internal";
            newPayload.type=        subType;
            newPayload.typeLabel=   labelInternal[subType];
            newPayload.value=       mySensorsMessage.value;
            break;    
        case 4:     // Stream - OTA firmware update
            newPayload.nodeId=      mySensorsMessage.nodeId;
            newPayload.mode=        "stream";
            break;
        default:
            break;
    }
    msg.payload = newPayload; 
} else {
    msg.payload = "Error! Nothing to decode"
}  

return msg;

Voici ce que vous obtiendrez avec la fonction. Chaque message est maintenant explicite et formaté sous la forme d’un objet JSON plus facile à exploiter dans un projet.

Libre à vous de la modifier en fonction de vos besoins.

Pour une gateway MQTT

Si vous utilisez une gateway MQTT, utilisez ce Flow pour décoder les messages

/* MySensors v2.3.x Message Decoder
*  Payload : JSON object
*  www.projetsdiy.fr - 03/2020
*/
var mySensorsMessage = {}
var newPayload = {};
var tokens = msg.topic.split("/")
console.log(msg.topic, "|", tokens);
if(tokens.length == 6) {
    //  0       1         2                 3       4    5
    // prefix/node-id/child-sensor-id/message-type/ack/sub-type
    mySensorsMessage.nodeId =       parseInt(tokens[1]);
    mySensorsMessage.childSensorId= parseInt(tokens[2]);
    mySensorsMessage.messageType =  parseInt(tokens[3]);
    mySensorsMessage.ack =          parseInt(tokens[3]);
    mySensorsMessage.subType =      parseInt(tokens[5]);
    mySensorsMessage.value =        msg.payload;

    var messageType = mySensorsMessage.messageType;
    var subType = mySensorsMessage.subType;
    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"];
    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"]
    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"]
    
    newPayload.topic = tokens[0]
    switch (messageType) {
        case 0:     // Presentation
            newPayload.mode =       "Presentation";
            newPayload.type =       labelPresentation[subType];
            newPayload.value=       mySensorsMessage.value;      
            break;
        case 1:     // Set
            newPayload.nodeId=      mySensorsMessage.nodeId;
            newPayload.sensorId=    mySensorsMessage.childSensorId;
            newPayload.mode=        "Set";
            newPayload.type=        subType;
            newPayload.typeLabel=   labelSet[subType];
            newPayload.value=       mySensorsMessage.value;
            break;
        case 2:     // Req
            newPayload.nodeId=      mySensorsMessage.nodeId;
            newPayload.sensorId=    mySensorsMessage.childSensorId;
            newPayload.mode=        "Req";
            newPayload.type=        subType;
            newPayload.typeLabel=   labelSet[subType];
            newPayload.value=       mySensorsMessage.value;
            break;  
        case 3:     // Internal
            newPayload.nodeId=      mySensorsMessage.nodeId;
            newPayload.sensorId=    mySensorsMessage.childSensorId;
            newPayload.mode=        "Internal";
            newPayload.type=        subType;
            newPayload.typeLabel=   labelInternal[subType];
            newPayload.value=       mySensorsMessage.value;
            break;    
        case 4:     // Stream - OTA firmware update
            newPayload.nodeId=      mySensorsMessage.nodeId;
            newPayload.mode=        "stream";
            break;
        default:
            break;
    }

    msg.payload = newPayload; 
} else {
    msg.payload = "Error! Nothing to decode. Lenght =" + tokens.length
}  

return msg;

Code du flow

[{"id":"61bbd468.bddf9c","type":"tcp in","z":"eb4ead14.fd77f","name":"MySensors Gateway","server":"client","host":"192.168.1.20","port":"5003","datamode":"stream","datatype":"utf8","newline":"","topic":"","base64":false,"x":169.88886260986328,"y":226.92767333984375,"wires":[["f4fd4940.32ba8"]]},{"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"]]},{"id":"fd30fa09.244ce8","type":"debug","z":"eb4ead14.fd77f","name":"","active":true,"console":"false","complete":"false","x":628.5,"y":235,"wires":[]}]

La fonction mysencap

La dernière fonction mysencap proposée par le plugin permet de formater un message avant de le publier sur un noeud du réseau MySensors. On peut envoyer ce que l’on veut dans la limite de 25 bytes. Il faut également ajouter un retour à la ligne (\n) avant de l’injecter dans la fonction. Par exemple, on peut récupérer l’état d’un switch créé avec le plugin node-red-contrib-ui pour allumer ou éteindre une Led (ou une lampe via un relai). Nous verrons en détail ce plugin dans un prochain tutoriel.

Ajoutez un Node switch

Donnez lui un nom. Pour la valeur de sortie, indiquez 1 et 0 pour Off. Ce n’est pas très important, on peut très bien laisser True/False. Il faudra juste tester la bonne valeur dans le code Arduino du noeud MySensors.

Allez sur la page d’interface à l’adresse

http://IP_NODE-RED:1880/ui

Vous disposer maintenant d’un interrupteur à deux états.

Il ne reste plus qu’à préparer le message. Ajoutez une fonction et coller ce code pour ajouter un retour à la ligne.

msg.payload = msg.payload + "\n"
return msg;

Ensuite ajoutez un Node mysencap et indiquez les paramètres du noeud de destination du message. Le type de message doit être Request. Voici un exemple :

Il ne reste plus qu’à injecter dans un Node mysdecenc avant d’envoyer le message sur une gateway (série ou réseau) MySensors.

Ajoutez ce code sur le noeud MySensor pour intercepter les messages envoyés à cet objet.

void receive(const MyMessage &message) {
     Serial.print("Message recu pour le capteur :");
     Serial.print(message.sensor);
     Serial.print(", Nouveau statut : ");
     Serial.println(message.getBool()); 
}

Et voilà, si on appuie sur l’interrupteur, on reçoit bien les messages sur le noeud en provenance du flow Node-RED.

Code du flow

[{"id":"f34523e0.fa94a","type":"mysdecenc","z":"e1e0f04d.8c404","name":"","x":546.388916015625,"y":276,"wires":[["a9d71461.a61de8"]]},{"id":"45e9c56a.b8cdec","type":"mysencap","z":"e1e0f04d.8c404","name":"","nodeid":"3","childid":"0","subtype":"2","internal":0,"ack":false,"msgtype":"2","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":400,"y":220.3333282470703,"wires":[["f34523e0.fa94a"]]},{"id":"a9d71461.a61de8","type":"tcp out","z":"e1e0f04d.8c404","host":"192.168.1.20","port":"5003","beserver":"client","base64":false,"end":false,"name":"to MySensors","x":738,"y":232.3333282470703,"wires":[]},{"id":"d253489c.087998","type":"function","z":"e1e0f04d.8c404","name":"slash n","func":"msg.payload = msg.payload + \"\\n\"\nreturn msg;","outputs":1,"noerr":0,"x":274,"y":276.3333282470703,"wires":[["45e9c56a.b8cdec"]]},{"id":"af4ddcee.88eaf","type":"ui_switch","z":"e1e0f04d.8c404","tab":"6df01db6.d8538c","name":"Switch","topic":"","group":"","order":1,"onvalue":"1","offvalue":"0","x":149,"y":224.3333282470703,"wires":[["d253489c.087998"]]},{"id":"6df01db6.d8538c","type":"ui_tab","z":"","name":"Salon","icon":"store","order":"1"}]

Mises à jour

[25/03/2020] Se connecter et décoder les messages MySensors MQTT

Avez-vous aimé cet article ?