Premiers pas avec MQTT Node Red
MQTT.fx un outil pour analyser les données qui transitent sur le serveurD'autres apps existent:- MQTT.fx : https://mqttfx.jensd.de/- MQTT : http://tvaira.free.fr/mqtt/mqtt.htmlAvec un scan on peut apercevoir les topics disponible sur le serveur:
Topic et Payload Topic et Payload , sujet et charge utile(contenu utile) en français Les topics peuvent être constituées d'un ou plusieurs niveaux (topic levels), chacun d'eux séparés par une barre oblique; exemple : zigbee2mqtt/temp_ext. Le payload est souvent au format json mais ce n'est pas une obligation. L'installation de Node-red sur le PC est intéressante car Node-red offre deux nœuds MQTT intégrés - mqtt in - mqtt outIl est alors simple de recevoir et envoyer des messages sur le serveur MQTT.
Publier un message Mosquitto est le serveur pour le protocole MQTT Il est la passerelle entre les dispositifs et le serveur domotiqueun lien intéressant : http://stevesnoderedguide.com/configuring-the-mqtt-publish-nodeLorsqu'un client publie un message à un courtier(ou serveur), il doit envoyer:
• Le sujet du message • La qualité de service QoS • Indique si le message doit être conservé - Retain Flag
Qualité de service: QoS 0 - au plus une fois : ce niveau de service garantit une livraison au mieux. Il n'y a aucune garantie de livraison QoS 1 - au moins une fois : garantit qu'un message est délivré au moins une fois au récepteur; l'expéditeur stocke le message jusqu'à ce qu'il reçoive un paquet PUBACK du destinataire qui accuse réception du message. QoS 2 - exactement une fois : ce niveau garantit que chaque message n'est reçu qu'une seule fois par les destinataires prévus. c'est le niveau de qualité de service le plus sûr mais le plus lent.
Script node-red Avec MQTT.fx on a pu apercevoir les différents topics auxquels on peut s'abonner; pour cet exemple je choisi "zigbee2mqtt/temp_cave"temp_cave est l'un des dispositifs zigbee inclus dans zigbee2mqtt.
Le but de ce script est de récupérer la température pour l'envoyer à un capteur virtuel de Domoticz.
Pour cela :- on utilise mqtt in, mqtt out et function avec laquelle on formatera le json pour qu'il soit accepté par Domoticz:
Accès aux propriétés de msg :de la même façon que pour n'importe quel objet JavaScript.exemples:
var payload = msg.payload ;msg.payload = contenu;var topic = msg.topic ;msg.topic = sujet;
Le nœud de fonction est utilisé pour exécuter du code JavaScript sur l'objet msg.Pour faciliter la rédaction du script on peut utiliser Debug afin d'éditer le message en entrée et celui en sortie après l'éxécution de la fonction. le nouveau schéma:
on peut commencer notre script par :
Rappel sur le json de Domoticz:
mise à jour à jour des appareils et des capteurs capteur de température
{ "command": "udevice", "idx" : 65, "nvalue" : 0, "svalue" : temperature ………string }
En javascipt (donc pour node-red) pour convertir un nombre en chaine : temperature=temp.toString() ;
Le script final de la fonction pour publier sur Domoticz: , le topic est : domoticz/in
var contenu = msg.payload ; var temp=contenu['temperature']; var temperature=temp.toString(); msg.payload = { "command": "udevice", "idx" : 65, "nvalue" : 0, "svalue" : temperature }; return msg;
Affichage debug:
Affichage log Domoticz:
Application avec plusieurs capteurs de températurele topic sera alors : zignee2mqtt/+le + est l'équivalent de * pour le dos , linux ,...
Le script de function:
Démarrage automatique de node-redInstallé par défaut sur PI , ce n'est pas le cas sur ma distribution debian 10.9.le fichier nodered.service:
sudo nano /etc/systemd/system/nodered.service
[Unit] Description=Nodered After=syslog.target network.target [Service] ExecStart=/usr/local/bin/node-red --max-old-space-size=128 -v Restart=on-failure KillSignal=SIGINT # log output to syslog as 'node-red' SyslogIdentifier=node-red StandardOutput=syslog # non-root user to run as WorkingDirectory=/home/michel/ User=michel Group=sudo [Install] WantedBy=multi-user.target
Apès modification du fichier nodered.service, il faut relancer le daemon:
sudo systemctl daemon-reload sudo systemctl start nodered
Démarrage automatique au démarrage de debian:
sudo systemctl enable zigbee2mqtt.service
Quelques scriptsZigbee2mqtt/NOM DISPOSITIF vers domoticz/in
function capteur(id,data){ msg.payload = { "command": "udevice", "idx" : id, "nvalue" : 0, "svalue" : data } } function inter(id,data){ msg.payload = { "command": "switchlight", "idx" : id, "switchcmd" : data } } switch (msg.topic){ case "zigbee2mqtt/temp_cave": contenu = msg.payload ; data=contenu['temperature'].toString(); capteur(65,data); break; case "zigbee2mqtt/temp_cellier": var contenu = msg.payload ; data=contenu['temperature'].toString(); capteur(74,data); break; case "zigbee2mqtt/temp_cuis_ete": contenu = msg.payload ; data=contenu['temperature'].toString(); capteur(75,data); break; case "zigbee2mqtt/eclairage_ext": contenu = msg.payload ; data1=contenu['state_l2']; if (data1=="ON") data="On" if (data1=="OFF") data="Off" inter(76,data); break; case "zigbee2mqtt/eclairage_ext_ouest": contenu = msg.payload ; data=contenu['state']; if (data=="ON") data="On" if (data=="OFF") data="Off" inter(77,data); break; default: } return msg;
de domoticz/out vers zigbee2mqtt/NOM DISPOSITIF/setdans ce script le topic est fourni par le script, laisser vierge la config "mosquitto"
if (msg.topic=="domoticz/out") { var m = JSON.parse(msg.payload); switch (m.idx){ case 76 : var valeur=m.nvalue ; if(m.nvalue==1)msg.payload= {"state_l2":"ON"}; if(m.nvalue==0)msg.payload= {"state_l2":"OFF"}; msg.topic = "zigbee2mqtt/eclairage_ext/set"; break; default: } return msg; }
De Zigbee2mqtt vers Domoticz avec plusieurs valeurs pour un dispositif Avec uniquement un payload vers domoticz/in ce n'est pas possible , seulement la valeur "svalue" est prise en compte; il faut utiliser un script dz qui fera la mise à jour avec l'api json ........mode d'emploi:schéma node-red:
la fonction :
function vers_dz(id,temp,hum,batt){ msg.payload = {"command":"customevent", "event":"separation_valeurs", "data": "{'idx':"+id+",'humidity':"+hum+",'batteryLevel':"+batt+",'temperature':"+temp+" }" } } switch (msg.topic){ case "zigbee2mqtt/temp_cave": contenu = msg.payload ; temp=contenu['temperature'].toString(); hum=contenu['humidity'].toString(); batt=Math.round(contenu['battery']); vers_dz(78,temp,hum,batt); msg break; case "zigbee2mqtt/temp_cellier": contenu = msg.payload ; temp=contenu['temperature'].toString(); hum=contenu['humidity'].toString(); batt=Math.round(contenu['battery']); vers_dz(74,temp,hum,batt); break; case "zigbee2mqtt/temp_cuis_ete": contenu = msg.payload ; temp=contenu['temperature'].toString(); hum=contenu['humidity'].toString(); batt=Math.round(contenu['battery']); vers_dz(75,temp,hum,batt); break; default : return; } return msg;
le script dz , inspiré de Waren (https://en.domoticz.cn/forum/viewtopic.php?p=244743) : Après la mise à jour de Domoticz 2021.1 , j'ai du utiliser la fonction "dz.utils.fromJSON() intégée à Domoticz
Rappel sur l'api: - maj Temp : /json.htm?type=command¶m=udevice&idx=IDX&nvalue=0&svalue=TEMP IDX = id de votre appareil (Ce numéro se trouve dans l'onglet Appareils dans la colonne "IDX") TEMP = température -maj Temp + Humidity :/json.htm?type=command¶m=udevice&idx=IDX&nvalue=0&svalue=TEMP;HUM;HUM_STAT IDX = id de votre appareil (Ce numéro se trouve dans l'onglet Appareils dans la colonne "IDX") TEMP = température HUM = Humidité (0-100)% HUM_STAT = Statut d'humidité(0à3)
-- maj temp hum battery -- Humidity_status peut être l'un des suivants: --0 = normal --1 = confortable --2 = sec --3 = mouillé local scriptVar = 'separation_valeurs' return { on = { customEvents = { scriptVar, }, httpResponses = { scriptVar, }, }, logging = { level = domoticz.LOG_DEBUG, -- LOG_ERROR marker = scriptVar, }, execute = function(dz, item) lodash = dz.utils._ local function sendURL(idx, temperature,batteryLevel) --CAPTEURS TEMPERATURE: svalue=temp battery= volts battery local url = dz.settings['Domoticz url'] .. '/json.htm?type=command¶m=udevice&idx=' .. idx .. '&nvalue=0&svalue=' .. temperature .. '&battery=' .. batteryLevel; dz.openURL( { url = url, callback = scriptVar, }) end local function sendURL1(idx, temperature,humidity,confort,batteryLevel) --CAPTEURS TEMPERATURE+HUMIDITE : svalue=temp;hum;Humidity_status battery=volts battery local url = dz.settings['Domoticz url'] .. '/json.htm?type=command¶m=udevice&idx=' .. idx .. '&nvalue=0&svalue=' .. temperature ..';'.. humidity ..';' .. confort .. '&battery=' .. batteryLevel; dz.openURL( { url = url, callback = scriptVar, }) end if item.isCustomEvent then mqtt = item.data mqtt = dz.utils.fromJSON(mqtt) local batteryLevel = mqtt.batteryLevel local temperature = mqtt.temperature local humidity = mqtt.humidity local humidity_status=tonumber(humidity); if (humidity_status<30) then confort = "2" ; elseif (humidity_status>39 and humidity_status<60) then confort = "1" ; elseif (humidity_status>59 and humidity_status<80) then confort = "0" ; elseif (humidity_status>79) then confort = "3"; else confort = "3" end local idx = mqtt.idx; local type=dz.devices(idx).deviceType;print("type" .. tostring(type) .. ' , humidity_status : ' .. tostring(confort)); if (type=='Temp') then sendURL(idx, temperature, batteryLevel); elseif (type=='Temp + Humidity') then sendURL1(idx, temperature, humidity, confort, batteryLevel); else print("pas de dispositif trouvé"); end elseif not item.ok then dz.log('Problèm avec l\'envoi de la temperature ou batteryLevel' .. lodash.str(item), dz.LOG_ERROR) else dz.log('All ok \n' .. lodash.str(item.data) .. '\n', dz.LOG_DEBUG) end end }
Ne pas oublier :
log domoticz :