Je vous partage un flow Node-Red pour mesurer le temps de réception du signal d’un capteur zigbee.
Si le temps entre chaque réception du signal est supérieur à 24H (paramètrable) alors une alerte avec Telegram est envoyée.
Je réalisé cette fonction car l’indication de batterie des capteurs zigbee n’est pas fiable et plusieurs fois je me suis fait avoir sur une température alors que le capteur ne fonctionnait plus. Ce qui peux être embêtant quand on a besoin de cette valeur dans une scène.
Maintenant je sais si un de mes capteurs n’envoi plus de données au bout de 24H. Et cela en boucle toutes les 24H.
Testé avec capteur d’ouverture, température/humidité, switch, capteur vibration, capteur de mouvement.
La demande de fonctionnalité dans Gladys
Pour l’installation de NODE-RED, vous connaissez déjà tous le tuto vidéo de @pierre-gilles. https://www.youtube.com/watch?v=bpmHzR8_S5g .
Pré-requis:
-
configurer le broker mqtt pour se connecter au broker zigbee2mqtt
Le mot de passe est généré par Gladys, vous pouvez le retrouver dans la db.
-
installer dans Node-Red : « node-red–contrib-telegrambot »
-
configurer un bot telegram pour Node-Red
-
récuperer un numéro ChatId pour pouvoir envoyer des messages avec Télégram dans Node-Red (j’ajouterais par la suite comment récupérer ce numéro ci besoin)
Cette partie Telegram est optionnel, vous pouvez aussi renvoyer un état dans un fake device mqtt à Gladys. Et ensuite faire l’alerte Telegram avec Gladys. -
configuration de Node-Red pour ecrire/lire des fichiers:
Editer le fichier /var/lib/node-red/settings.js (voir la vidéo de @pierre-gilles pour l’installation de Node-Red il explique comment éditer ce fichier)
Ajouter les lignes ci dessous:
contextStorage: {
default: "memoryOnly",
memoryOnly: { module: 'memory' },
file: { module: 'localfilesystem' }
},
Voici un aperçu du flow dans Node-red d’un de mes capteurs:
Voici le flow à importer dans Node-Red: j’ai modifié un de mes flows pour qu’il soit générique et que mes données de connexion soit effacées
[
{
"id": "d5482843ef207659",
"type": "function",
"z": "d76f072c1559266b",
"g": "87c2f560ca6c5a98",
"name": "send msg to telegram",
"func": "msg.payload={};\nmsg.payload.chatId =\"******\";\nmsg.payload.content = \"[ALERTE] Perte de la communication avec le thermomètre! Vérifier la pile de ce device!\";\nmsg.payload.type = \"message\";\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1180,
"y": 120,
"wires": [
[
"f57a85488266a794"
]
]
},
{
"id": "2c780ff8e1b28a9e",
"type": "mqtt in",
"z": "d76f072c1559266b",
"g": "87c2f560ca6c5a98",
"name": "Thermomètre",
"topic": "zigbee2mqtt/Thermomètre",
"qos": "2",
"datatype": "auto",
"broker": "2a159ac23236c7e2",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 150,
"y": 120,
"wires": [
[
"47ee6c1dd9132535"
]
]
},
{
"id": "47ee6c1dd9132535",
"type": "change",
"z": "d76f072c1559266b",
"g": "87c2f560ca6c5a98",
"name": "",
"rules": [
{
"t": "set",
"p": "topic",
"pt": "msg",
"to": "sensor",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 490,
"y": 120,
"wires": [
[
"147c4e952052bad4"
]
]
},
{
"id": "cfd94c8353c2c6f9",
"type": "inject",
"z": "d76f072c1559266b",
"g": "87c2f560ca6c5a98",
"name": "Task 1000",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "60",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "task",
"payload": "",
"payloadType": "date",
"x": 490,
"y": 80,
"wires": [
[
"147c4e952052bad4"
]
]
},
{
"id": "147c4e952052bad4",
"type": "function",
"z": "d76f072c1559266b",
"g": "87c2f560ca6c5a98",
"name": "TimeOut",
"func": "/*\n * Time-out capteur\n */\n\n\nconst TIME_OUT = 1440; /* 24 heures */\n\n/*\n * Sortie time out\n */\nvar msg_TimeOut = null;\n\n/*\n * delai avant time out capteur entre 2 réceptions\n */\nvar delayTimeOut = context.get(\"delayTimeOut\", \"file\") || TIME_OUT; // initialize variables\n\n\nif (msg.topic === \"sensor\") // initialisation compteur a chaque réception capteur\n{\n delayTimeOut = TIME_OUT;\n context.set(\"delayTimeOut\", delayTimeOut, \"file\"); // save last value in local context\n\n node.status({ fill: \"green\", shape: \"ring\", text: \"Remaining: \" + delayTimeOut + \" minutes\" });\n\n //msg_TimeOut = { topic: \"temp\", payload: delayTimeOut };\n}\n\nif (msg.topic === \"task\") // mise à jour toutes les minutes\n{\n if (delayTimeOut > 0)\n {\n delayTimeOut--;\n context.set(\"delayTimeOut\", delayTimeOut, \"file\"); // save last value in local context\n \n node.status({ fill: \"green\", shape: \"ring\", text: \"Remaining: \" + delayTimeOut + \" minutes\" });\n\n }\n\n if (delayTimeOut === 0)\n {\n delayTimeOut = 0; \n context.set(\"delayTimeOut\", delayTimeOut, \"file\"); // save last value in local context\n\n node.status({ fill: \"red\", shape: \"ring\", text: \"TIME OUT\" });\n\n msg_TimeOut = { topic: \"timeout\", payload: \"TIME OUT\" };\n }\n \n} \n\nreturn msg_TimeOut;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 900,
"y": 120,
"wires": [
[
"d5482843ef207659"
]
],
"outputLabels": [
"TimeOut"
]
},
{
"id": "f57a85488266a794",
"type": "telegram sender",
"z": "d76f072c1559266b",
"g": "87c2f560ca6c5a98",
"name": "",
"bot": "e1f028778559de40",
"haserroroutput": false,
"outputs": 1,
"x": 1510,
"y": 120,
"wires": [
[]
]
},
{
"id": "2a159ac23236c7e2",
"type": "mqtt-broker",
"name": "zigbee2mqtt2",
"broker": "192.168.*.*",
"port": "1884",
"clientid": "",
"autoConnect": true,
"usetls": false,
"protocolVersion": "4",
"keepalive": "60",
"cleansession": true,
"birthTopic": "",
"birthQos": "0",
"birthPayload": "",
"birthMsg": {},
"closeTopic": "",
"closeQos": "0",
"closePayload": "",
"closeMsg": {},
"willTopic": "",
"willQos": "0",
"willPayload": "",
"willMsg": {},
"userProps": "",
"sessionExpiry": "",
"credentials": {}
},
{
"id": "e1f028778559de40",
"type": "telegram bot",
"botname": "******",
"usernames": "",
"chatids": "",
"baseapiurl": "",
"updatemode": "polling",
"pollinterval": "300",
"usesocks": false,
"sockshost": "",
"socksprotocol": "socks5",
"socksport": "6667",
"socksusername": "anonymous",
"sockspassword": "",
"bothost": "",
"botpath": "",
"localbotport": "8443",
"publicbotport": "8443",
"privatekey": "",
"certificate": "",
"useselfsignedcertificate": false,
"sslterminated": false,
"verboselogging": false
}
]
1. mqtt in : Configuration capteur zigbee
Mettre un objet mqtt in
Indiquez dans serveur votre broker zigbee2mqtt
Indiquez dans Topic le topic de votre capteur (vous pouvez vous aider d’une application comme MQTT Explorer pour explorer votre réseau et retrouver le topic). En général le topic est zigbee2mqtt/nomdevotrecapteur
2. change: transformation topic
Mettre un objet change pour modifier le topic et ainsi éviter de modifier le topic pour chaque capteur ensuite dans la fonction qui viens après.
3. function : calcul du temps entre 2 envois du signal zigbee du capteur
Mettre un objet function
Dans le code ci dessous vous pouvez modifier la constante TIME_OUT (en minutes). Moi j’ai mis 1440 minutes (24H)
/*
* Time-out capteur
*/
const TIME_OUT = 1440; /* 24 heures */
/*
* Sortie time out
*/
var msg_TimeOut = null;
/*
* delai avant time out capteur entre 2 réceptions
*/
var delayTimeOut = context.get("delayTimeOut", "file") || TIME_OUT; // initialize variables
if (msg.topic === "sensor") // initialisation compteur a chaque réception capteur
{
delayTimeOut = TIME_OUT;
context.set("delayTimeOut", delayTimeOut, "file"); // save last value in local context
node.status({ fill: "green", shape: "ring", text: "Remaining: " + delayTimeOut + " minutes" });
//msg_TimeOut = { topic: "temp", payload: delayTimeOut };
}
if (msg.topic === "task") // mise à jour toutes les minutes
{
if (delayTimeOut > 0)
{
delayTimeOut--;
context.set("delayTimeOut", delayTimeOut, "file"); // save last value in local context
node.status({ fill: "green", shape: "ring", text: "Remaining: " + delayTimeOut + " minutes" });
}
if (delayTimeOut === 0)
{
delayTimeOut = 0;
context.set("delayTimeOut", delayTimeOut, "file"); // save last value in local context
node.status({ fill: "red", shape: "ring", text: "TIME OUT" });
msg_TimeOut = { topic: "timeout", payload: "TIME OUT" };
}
}
return msg_TimeOut;
J’ai ajouter le temps restant dans la fonction avant que l’alerte soit envoyée
4. inject: envoie d’un payload toutes les minutes pour recalculer le temps dans la fonction
Mettre un objet inject
Mettre en topic task. Ce topic est utilisé dans la fonction. Si vous le modifier il faudra modifier le code de la fonction.
Indiquez ensuite un interval chaque minute
5. function: création du texte pour telegram
Mettre un objet function
Il faudra insérer votre numéro chatId et vous pouvez personnaliser votre message
msg.payload={};
msg.payload.chatId ="******";
msg.payload.content = "[ALERTE] Perte de la communication avec le thermomètre! Vérifier la pile de ce device!";
msg.payload.type = "message";
return msg;
6. sender telegram: envoie du message
Ajouter un objet telegram sender
Indiquez votre bot telegram pour nodered