zwavejs2mqtt <-> Node-RED pour l'allumage (rapide) / dz pour l’extinction qui a des règles plus complexes.
* L'architecture * Le fonctionnement
La partie Node-RED (NR) est déclenchée par les détecteurs de mouvement et allume les lumières.
La partie Domoticz (dz) gère l'extinction des lumières.
NR est plus réactif que dz et permet d'allumer les lumières plus rapidement que la gestion des événements de dz (qui pourrait être ralentie parfois avec la sauvegarde ou tout script long).
Peu de fonctions dans NR pour le garder léger et réactif.
La partie la plus délicate était les "ids" des "devices" (qui ne sont pas les mêmes dans zwavejs2mqtt et dz) que je voulais éviter de les dupliquer.
La translation est faite dans dz entre le sujet (mqtt de NR) et l'ID (dz Hardware).
Avec mes devices zwave, c'est le même devices pour l'interrupteur et la lumière (à adapter pour les lumières avec des interrupteurs séparés).
Un autre script calcule la valeur du rayonnement solaire (lux) à donner à NR : 0 = nuit ; 2 = jour ; 1 = jour pour les capteurs, nuit pour les lumières.
* Les règles
Plusieurs capteurs et plusieurs lumières, les lumières peuvent être allumées par leur interrupteur ou par les capteurs de mouvement assignés.
Après un délai, elles s'éteignent ; il y a un délai pour les détecteurs de mouvement (court) et un autre pour les interrupteurs (plus long).
Tout mouvement réinitialise le décompte du délai de l'extinction.
Un détecteur de mouvement peut allumer plusieurs lumières
Les lumières peuvent être allumées si c'est la nuit, le niveau n'est pas le même pour les détecteurs et les interrupteurs.
Une personne pourrait décider d'allumer la lumière même s'il n'y a pas assez de lumière pour permettre à un détecteur de mouvement de s'allumer.
Il faut plus de lumière pour lire que pour marcher

Lorsque les lumières sont allumées par des capteurs, elles peuvent être éteintes par n'importe quel interrupteur avec la lumière allumée.
Il y a aussi un double contrôle pour être sûr que les lumières sont vraiment éteintes, en cas de perte de déclenchement ou autre problème (mais pas en cas de problèmes avec le réseau zwave).
Une autre partie délicate est que zwave donne plusieurs messages quand une lumière est allumée et éteinte,
une fonction spécifique a été faite pour filtrer les doublons (à accorder avec le réseau).
Node-RED
Code : Tout sélectionner
[
{
"id": "6262a545dc54b0c6",
"type": "tab",
"label": "Eclairage Extérieur",
"disabled": false,
"info": "",
"env": []
},
{
"id": "4d06b0e190e41b0f",
"type": "switch",
"z": "6262a545dc54b0c6",
"name": "Motions",
"property": "topic",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "zwave/99/113/0/Home_Security/Motion_sensor_status",
"vt": "str"
},
{
"t": "eq",
"v": "zwave/121/113/0/Home_Security/Motion_sensor_status",
"vt": "str"
},
{
"t": "eq",
"v": "zwave/80/113/0/Home_Security/Motion_sensor_status",
"vt": "str"
},
{
"t": "eq",
"v": "zwave/126/48/0/Motion",
"vt": "str"
}
],
"checkall": "false",
"repair": false,
"outputs": 4,
"x": 160,
"y": 160,
"wires": [
[
"9fd52e88907223f2"
],
[
"70ae0b14d4602f36"
],
[
"25c1793fe834d50e"
],
[
"051a58a323a529a8"
]
]
},
{
"id": "f774526cf796f4cf",
"type": "mqtt in",
"z": "6262a545dc54b0c6",
"name": "from zwave",
"topic": "zwave/#",
"qos": "2",
"datatype": "auto",
"broker": "35f3ae39d3073cb5",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 90,
"y": 360,
"wires": [
[
"9a94f9dc77ae1354",
"ea5b1323d1266075",
"279a24a53e1b9f3f"
]
]
},
{
"id": "b715c325798fbfd3",
"type": "mqtt out",
"z": "6262a545dc54b0c6",
"name": "to dz",
"topic": "domoticz/in",
"qos": "2",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "35f3ae39d3073cb5",
"x": 1010,
"y": 440,
"wires": []
},
{
"id": "f9359ae301fe4a01",
"type": "mqtt out",
"z": "6262a545dc54b0c6",
"name": "to zwave",
"topic": "",
"qos": "2",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "35f3ae39d3073cb5",
"x": 1020,
"y": 200,
"wires": []
},
{
"id": "411708a0e722d9a9",
"type": "mqtt in",
"z": "6262a545dc54b0c6",
"name": "dz Day or Night",
"topic": "domoticz/out/daynight",
"qos": "2",
"datatype": "utf8",
"broker": "35f3ae39d3073cb5",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 160,
"y": 680,
"wires": [
[
"5ee19e982756d0eb",
"e761a3000063ebd5"
]
]
},
{
"id": "172b53b872529718",
"type": "debug",
"z": "6262a545dc54b0c6",
"d": true,
"name": "No motion",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 830,
"y": 40,
"wires": []
},
{
"id": "9a94f9dc77ae1354",
"type": "switch",
"z": "6262a545dc54b0c6",
"name": "Lights",
"property": "topic",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "zwave/102/38/0/currentValue",
"vt": "str"
},
{
"t": "eq",
"v": "zwave/150/38/0/currentValue",
"vt": "str"
},
{
"t": "eq",
"v": "zwave/11/38/0/currentValue",
"vt": "str"
},
{
"t": "eq",
"v": "zwave/156/38/0/currentValue",
"vt": "str"
}
],
"checkall": "false",
"repair": false,
"outputs": 4,
"x": 150,
"y": 500,
"wires": [
[
"46b3cbd2ab75bd69"
],
[
"46b3cbd2ab75bd69"
],
[
"46b3cbd2ab75bd69"
],
[
"46b3cbd2ab75bd69"
]
]
},
{
"id": "446b6a41513f9c50",
"type": "function",
"z": "6262a545dc54b0c6",
"name": "Light w Motion",
"func": "// build the vars to get the state on the light and of the motion\nvar light_topic = msg.topic.split(\"/\")[0] +\n\"/\" + msg.topic.split(\"/\")[1] +\n\"/\" + msg.topic.split(\"/\")[2] + \n\"/\" + msg.topic.split(\"/\")[3] + \n\"/\";\n\n// state of the light\nvar var_lighttopic = light_topic + \"_on\";\n\n// state of the motion\n// 0 = no motion (not here)\n// 1 = motion to switch On the light (if Off = 0 ; <> 1) => to zwave\n// 2 = motion to keep the light On (if On = 1) => to dz only\nvar var_motion = light_topic + \"_motion\";\nvar motion_state = flow.get(var_motion);\nif (motion_state === 'undefined') {\n motion_state = 9\n}\n// motion topic to send to dz in order to find the motion idx\nvar var_motion_topic = light_topic + \"_motion_topic\";\nvar motion_topic = flow.get(var_motion_topic);\nif (motion_topic === 'undefined') {\n motion_topic = 0\n}\n\n// \nvar light_state;\nif (msg.payload.value === 0 || msg.payload.value === false) {\n light_state = 0;\n motion_state = 0;\n}\nelse {\n light_state = 1;\n}\n\nflow.set(var_lighttopic, light_state);\nflow.set(var_motion, 0);\n\nmsg.payload.light_state = light_state;\nmsg.payload.motion_state = motion_state;\nmsg.payload.light_topic = light_topic;\nmsg.payload.motion_topic = motion_topic;\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 580,
"y": 500,
"wires": [
[
"758a3a9697543029",
"da7c683e1802fdfa"
]
]
},
{
"id": "66796159fb3745f2",
"type": "function",
"z": "6262a545dc54b0c6",
"name": "Light to zwave",
"func": "// build the topic to zwavejs2mqtt\nmsg.topic = msg.payload.light_topic + \"targetValue/set\";\n\nmsg.payload = msg.payload.light_value\n\nreturn msg\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 820,
"y": 180,
"wires": [
[
"f9359ae301fe4a01",
"1e1fcae53b65176e"
]
]
},
{
"id": "758a3a9697543029",
"type": "debug",
"z": "6262a545dc54b0c6",
"d": true,
"name": "Light On / Off",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 830,
"y": 540,
"wires": []
},
{
"id": "9425bab3e2ae8d98",
"type": "debug",
"z": "6262a545dc54b0c6",
"d": true,
"name": "Motion w Light",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 820,
"y": 240,
"wires": []
},
{
"id": "25c1793fe834d50e",
"type": "json",
"z": "6262a545dc54b0c6",
"name": "Motion Portail",
"property": "payload",
"action": "obj",
"pretty": false,
"x": 360,
"y": 200,
"wires": [
[
"2a3ad179e42046b9",
"9362535c2cbdbc34"
]
]
},
{
"id": "9362535c2cbdbc34",
"type": "change",
"z": "6262a545dc54b0c6",
"name": "Light Terrasse",
"rules": [
{
"t": "set",
"p": "payload.light_topic",
"pt": "msg",
"to": "zwave/156/38/0/",
"tot": "str"
},
{
"t": "set",
"p": "payload.light_value",
"pt": "msg",
"to": "99",
"tot": "num"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 580,
"y": 240,
"wires": [
[
"9425bab3e2ae8d98",
"b93cb8c4baf8cfba"
]
]
},
{
"id": "1e1fcae53b65176e",
"type": "debug",
"z": "6262a545dc54b0c6",
"name": "to zwave",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1020,
"y": 140,
"wires": []
},
{
"id": "0252414ff9c0e132",
"type": "debug",
"z": "6262a545dc54b0c6",
"name": "to dz",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1010,
"y": 500,
"wires": []
},
{
"id": "0828a86f1ce9ce0d",
"type": "change",
"z": "6262a545dc54b0c6",
"name": "Light Allée",
"rules": [
{
"t": "set",
"p": "payload.light_topic",
"pt": "msg",
"to": "zwave/150/38/0/",
"tot": "str"
},
{
"t": "set",
"p": "payload.light_value",
"pt": "msg",
"to": "99",
"tot": "num"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 570,
"y": 160,
"wires": [
[
"9425bab3e2ae8d98",
"b93cb8c4baf8cfba"
]
]
},
{
"id": "2a3ad179e42046b9",
"type": "change",
"z": "6262a545dc54b0c6",
"name": "Light Portail",
"rules": [
{
"t": "set",
"p": "payload.light_topic",
"pt": "msg",
"to": "zwave/11/38/0/",
"tot": "str"
},
{
"t": "set",
"p": "payload.light_value",
"pt": "msg",
"to": "99",
"tot": "num"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 570,
"y": 200,
"wires": [
[
"9425bab3e2ae8d98",
"b93cb8c4baf8cfba"
]
]
},
{
"id": "249c24b97f469711",
"type": "change",
"z": "6262a545dc54b0c6",
"name": "Light Portillon",
"rules": [
{
"t": "set",
"p": "payload.light_topic",
"pt": "msg",
"to": "zwave/102/38/0/",
"tot": "str"
},
{
"t": "set",
"p": "payload.light_value",
"pt": "msg",
"to": "60",
"tot": "num"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 580,
"y": 120,
"wires": [
[
"9425bab3e2ae8d98",
"b93cb8c4baf8cfba"
]
]
},
{
"id": "9fd52e88907223f2",
"type": "json",
"z": "6262a545dc54b0c6",
"name": "Motion Portillon",
"property": "payload",
"action": "obj",
"pretty": false,
"x": 360,
"y": 120,
"wires": [
[
"249c24b97f469711",
"0828a86f1ce9ce0d"
]
]
},
{
"id": "70ae0b14d4602f36",
"type": "json",
"z": "6262a545dc54b0c6",
"name": "Motion Allée",
"property": "payload",
"action": "obj",
"pretty": false,
"x": 350,
"y": 160,
"wires": [
[
"0828a86f1ce9ce0d",
"249c24b97f469711"
]
]
},
{
"id": "051a58a323a529a8",
"type": "json",
"z": "6262a545dc54b0c6",
"name": "Motion Terrasse",
"property": "payload",
"action": "obj",
"pretty": false,
"x": 360,
"y": 240,
"wires": [
[
"9362535c2cbdbc34"
]
]
},
{
"id": "1428cc47125190b4",
"type": "debug",
"z": "6262a545dc54b0c6",
"d": true,
"name": "Day for Motion",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 360,
"y": 320,
"wires": []
},
{
"id": "ea5b1323d1266075",
"type": "switch",
"z": "6262a545dc54b0c6",
"name": "Night?",
"property": "dayNight",
"propertyType": "flow",
"rules": [
{
"t": "eq",
"v": "0",
"vt": "num"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 90,
"y": 300,
"wires": [
[
"4d06b0e190e41b0f"
],
[
"1428cc47125190b4"
]
]
},
{
"id": "b93cb8c4baf8cfba",
"type": "switch",
"z": "6262a545dc54b0c6",
"name": "Motion?",
"property": "payload.value",
"propertyType": "msg",
"rules": [
{
"t": "false"
},
{
"t": "eq",
"v": "0",
"vt": "num"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 3,
"x": 640,
"y": 60,
"wires": [
[
"172b53b872529718"
],
[
"172b53b872529718"
],
[
"abd5e88fe39240d3"
]
]
},
{
"id": "f94c8c2c1883bcf7",
"type": "debug",
"z": "6262a545dc54b0c6",
"d": true,
"name": "Light On",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1020,
"y": 60,
"wires": []
},
{
"id": "c055eaae780d191b",
"type": "debug",
"z": "6262a545dc54b0c6",
"d": true,
"name": "Light Off",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1020,
"y": 100,
"wires": []
},
{
"id": "46b3cbd2ab75bd69",
"type": "json",
"z": "6262a545dc54b0c6",
"name": "Lights On/Off",
"property": "payload",
"action": "obj",
"pretty": false,
"x": 350,
"y": 500,
"wires": [
[
"446b6a41513f9c50"
]
]
},
{
"id": "e27cb3182cb34645",
"type": "inject",
"z": "6262a545dc54b0c6",
"d": true,
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 200,
"y": 780,
"wires": [
[
"e984b358ca970466"
]
]
},
{
"id": "976d56f936e63feb",
"type": "debug",
"z": "6262a545dc54b0c6",
"name": "Day",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 810,
"y": 840,
"wires": []
},
{
"id": "1fc532434ca04cfc",
"type": "debug",
"z": "6262a545dc54b0c6",
"name": "Night",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 810,
"y": 760,
"wires": []
},
{
"id": "e984b358ca970466",
"type": "switch",
"z": "6262a545dc54b0c6",
"d": true,
"name": "Night?",
"property": "dayNight",
"propertyType": "flow",
"rules": [
{
"t": "eq",
"v": "0",
"vt": "num"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 485.9999885559082,
"y": 776.9999885559082,
"wires": [
[
"0570fe421e974355"
],
[
"073cc37e8c52fa95"
]
]
},
{
"id": "5ee19e982756d0eb",
"type": "debug",
"z": "6262a545dc54b0c6",
"d": true,
"name": "Day or Night",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 390,
"y": 700,
"wires": []
},
{
"id": "e761a3000063ebd5",
"type": "change",
"z": "6262a545dc54b0c6",
"name": "to flow Day or Night",
"rules": [
{
"t": "move",
"p": "payload",
"pt": "msg",
"to": "dayNight",
"tot": "flow"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 410,
"y": 660,
"wires": [
[
"e984b358ca970466"
]
]
},
{
"id": "da7c683e1802fdfa",
"type": "function",
"z": "6262a545dc54b0c6",
"name": "Light to dz",
"func": "// prepare payload to dz\nvar w_data =\nmsg.payload.light_topic\n+ '|'\n+ msg.payload.light_state\n+ '|' \n+ msg.payload.motion_topic\n+ '|'\n+ msg.payload.motion_state\n+ '|'\n+ msg.payload.time;\n\nvar w_payload = { \n command: 'customevent',\n event: 'LumNR',\n data: w_data\n };\n\nmsg.payload = w_payload;\n\nreturn msg",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 830,
"y": 460,
"wires": [
[
"b715c325798fbfd3",
"0252414ff9c0e132"
]
]
},
{
"id": "abd5e88fe39240d3",
"type": "function",
"z": "6262a545dc54b0c6",
"name": "Light Off?",
"func": "// flow var of the light state \nvar var_light_topic = msg.payload.light_topic + \"_on\";\n\n// get the state of the light (0 = Off ; 1 = On ; 9 = ?)\nvar light_state = flow.get(var_light_topic);\nif (light_state === 'undefined') {\n light_state = 9\n}\n\n// save of the light state to the payload\nmsg.payload.light_state = light_state;\n\nvar var_motion_topic = msg.payload.light_topic + \"_motion_topic\";\n\nvar motion_topic = msg.topic\n//var motion_topic = msg.topic.split(\"/\")[0] +\n\"/\" + msg.topic.split(\"/\")[1] +\n\"/\" + msg.topic.split(\"/\")[2] + \n\"/\" + msg.topic.split(\"/\")[3] + \n\"/\";\nflow.set(var_motion_topic, motion_topic);\nmsg.payload.motion_topic = motion_topic;\n\n// state of the motion\n// 0 = no motion (not here)\n// 1 = motion to switch On the light (if Off = 0 ; <> 1) => to zwave\n// 2 = motion to keep the light On (if On = 1) => to dz only\nvar var_motion = msg.payload.light_topic + \"_motion\";\n\nif (light_state == 1) {\n flow.set(var_motion, 2);\n msg.payload.motion_state = 2;\n return [msg, null];\n} else {\n flow.set(var_motion, 1);\n msg.payload.motion_state = 1;\n return [null, msg];\n}\n\n",
"outputs": 2,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 800,
"y": 100,
"wires": [
[
"f94c8c2c1883bcf7",
"da7c683e1802fdfa"
],
[
"c055eaae780d191b",
"66796159fb3745f2"
]
]
},
{
"id": "0570fe421e974355",
"type": "change",
"z": "6262a545dc54b0c6",
"name": "Night",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "Night",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 645.9999885559082,
"y": 756.9999885559082,
"wires": [
[
"1fc532434ca04cfc"
]
]
},
{
"id": "073cc37e8c52fa95",
"type": "change",
"z": "6262a545dc54b0c6",
"name": "Day",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "Day",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 645.9999885559082,
"y": 816.9999885559082,
"wires": [
[
"976d56f936e63feb"
]
]
},
{
"id": "f90f2b75ae58f99b",
"type": "debug",
"z": "6262a545dc54b0c6",
"name": "Motion Portillon",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 620,
"y": 380,
"wires": []
},
{
"id": "279a24a53e1b9f3f",
"type": "switch",
"z": "6262a545dc54b0c6",
"d": true,
"name": "Détecteur Portillon",
"property": "topic",
"propertyType": "msg",
"rules": [
{
"t": "cont",
"v": "zwave/99",
"vt": "str"
}
],
"checkall": "false",
"repair": false,
"outputs": 1,
"x": 390,
"y": 380,
"wires": [
[
"f90f2b75ae58f99b"
]
]
},
{
"id": "35f3ae39d3073cb5",
"type": "mqtt-broker",
"name": "local",
"broker": "host.docker.internal",
"port": "1883",
"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": {},
"sessionExpiry": ""
}
]
à suivre....