Files
nearxos 0af21f4dc3 Refactor room and light configurations for Node-RED integration
- Updated global variable lists in GVL_IO.gvl and GVL_NVL_placeholders.gvl to reflect new room naming conventions and structures.
- Revised PLC_App.st to map new room configurations for lighting control.
- Enhanced documentation in all-lights-and-rooms.md and ha-lights-and-rooms.md to align with updated room and light entity naming.
- Adjusted room-config.js and related Node-RED flows to support the new configuration structure.

This update improves the organization and clarity of room and light management within the Node-RED integration, ensuring consistency across the system.
2026-04-01 19:09:59 +03:00

15047 lines
420 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[
{
"id": "46892ced77481340",
"type": "tab",
"label": "Flow 1",
"disabled": false,
"info": "",
"env": []
},
{
"id": "7de41d810b04d992",
"type": "tab",
"label": "Living Room",
"disabled": false,
"info": "",
"env": []
},
{
"id": "480553bb6f5b2b51",
"type": "tab",
"label": "Notifications",
"disabled": false,
"info": "",
"env": []
},
{
"id": "f9a2fb576f0d360d",
"type": "tab",
"label": "Zigbee ",
"disabled": false,
"info": "",
"env": []
},
{
"id": "6722d185624fd57a",
"type": "tab",
"label": "Scheduler",
"disabled": false,
"info": "",
"env": []
},
{
"id": "7eef035843cf87db",
"type": "tab",
"label": "Flow 2",
"disabled": false,
"info": "",
"env": []
},
{
"id": "31693504fcbbd954",
"type": "tab",
"label": "Flow 3",
"disabled": false,
"info": "",
"env": []
},
{
"id": "50971c50479dfd7a",
"type": "tab",
"label": "Flow 4",
"disabled": false,
"info": "",
"env": []
},
{
"id": "a6a28d6b6c0b4f4a",
"type": "tab",
"label": "Flow 5",
"disabled": false,
"info": "",
"env": []
},
{
"id": "b673e10beab091ff",
"type": "tab",
"label": "Flow 6",
"disabled": false,
"info": "",
"env": []
},
{
"id": "24e9a56732cfa6f1",
"type": "tab",
"label": "Flow 7",
"disabled": false,
"info": "",
"env": []
},
{
"id": "57bd1b149526fcee",
"type": "subflow",
"name": "Room Lights",
"info": "",
"category": "",
"in": [
{
"x": 260,
"y": 220,
"wires": [
{
"id": "ee7c2a47d6441c26"
}
]
}
],
"out": [
{
"x": 560,
"y": 120,
"wires": [
{
"id": "ee7c2a47d6441c26",
"port": 0
}
]
},
{
"x": 560,
"y": 160,
"wires": [
{
"id": "ee7c2a47d6441c26",
"port": 1
}
]
},
{
"x": 560,
"y": 200,
"wires": [
{
"id": "ee7c2a47d6441c26",
"port": 2
}
]
},
{
"x": 560,
"y": 240,
"wires": [
{
"id": "ee7c2a47d6441c26",
"port": 3
}
]
},
{
"x": 560,
"y": 280,
"wires": [
{
"id": "ee7c2a47d6441c26",
"port": 4
}
]
},
{
"x": 560,
"y": 320,
"wires": [
{
"id": "ee7c2a47d6441c26",
"port": 5
}
]
}
],
"env": [
{
"name": "room_name",
"type": "str",
"value": ""
}
],
"meta": {},
"color": "#DDAA99"
},
{
"id": "d0de479f6b80ab6c",
"type": "subflow",
"name": "Subflow 1",
"info": "",
"in": [
{
"x": 60,
"y": 80,
"wires": [
{
"id": "f9557fd9a8b2eee2"
}
]
}
],
"out": [
{
"x": 340,
"y": 80,
"wires": [
{
"id": "f9557fd9a8b2eee2",
"port": 0
}
]
}
]
},
{
"id": "4dc13919bcc9d676",
"type": "subflow",
"name": "Room filter",
"info": "",
"category": "",
"in": [
{
"x": 60,
"y": 80,
"wires": [
{
"id": "d2a3760f36aa6f41"
}
]
}
],
"out": [
{
"x": 640,
"y": 100,
"wires": [
{
"id": "0ce841560c8c4087",
"port": 0
},
{
"id": "64b045db5a4541fa",
"port": 0
},
{
"id": "4a891a7505b5fd00",
"port": 0
},
{
"id": "258a84ec1d54a43a",
"port": 0
},
{
"id": "5532273136423869",
"port": 0
}
]
}
],
"env": [
{
"name": "switch_1",
"type": "str",
"value": ".sw_1"
},
{
"name": "switch_2",
"type": "str",
"value": ".sw_2"
},
{
"name": "switch_3",
"type": "str",
"value": ".sw_3"
},
{
"name": "switch_4",
"type": "str",
"value": ".sw_4"
},
{
"name": "single",
"type": "str",
"value": ".sw_1"
}
],
"meta": {},
"color": "#DDAA99"
},
{
"id": "664de832a54bc4e0",
"type": "group",
"z": "46892ced77481340",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"039e1be0cfe8e630",
"740b766e9bdc0d2a"
],
"x": 1934,
"y": 179,
"w": 292,
"h": 82
},
{
"id": "f27a48975d61e376",
"type": "group",
"z": "46892ced77481340",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"e37aa132859c1ea8",
"d3f0c80e0188aabf",
"1a534f2c5be60889"
],
"x": 2244,
"y": 179,
"w": 502,
"h": 152
},
{
"id": "9113c5ebf5c089e3",
"type": "group",
"z": "480553bb6f5b2b51",
"name": "Door Sensor Notifications",
"style": {
"fill": "#addb7b",
"fill-opacity": "0.89",
"label": true,
"stroke": "#ffffff",
"stroke-opacity": "0"
},
"nodes": [
"0385d24efa18d698",
"9d611c0ff2a0b1ca",
"10448f46514c1406",
"a9d786b1ba52704b",
"e250cc2f901bea9f",
"5e94eb39aec6e82d",
"8b8cce25637907b1",
"3f9797c13c3a11a1",
"7301d71523d87e94",
"4055425d6c42dd13",
"ada6fe8339eab29b",
"8e0d5ec04f029b9a",
"eb25ece689ea1045",
"63cb264d89898c6a",
"bd4b7dd437c1aaaf",
"f6adcaa35a793e58"
],
"x": 34,
"y": -1,
"w": 1562,
"h": 302
},
{
"id": "91b1f4cb0e1ffa84",
"type": "group",
"z": "480553bb6f5b2b51",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"d592161c8e50638a",
"2a218aee475ce267",
"f5ef8cb0a1bc7def"
],
"x": 2234,
"y": 39,
"w": 412,
"h": 122
},
{
"id": "d24bcb9ea3d9711c",
"type": "group",
"z": "46892ced77481340",
"name": "",
"style": {
"fill": "#ffdf7f",
"label": true
},
"nodes": [
"925b79f58f75e449",
"b88648a578b60cb8",
"4a9361ba088ba046",
"0271d58953459100",
"4b360c7d54e39e0a",
"62cc8431c77a4797",
"2d6eb3ac6de382be",
"af99b05ba44c6741",
"3c7f8838aa2349b9",
"0b0b27deacee2bfc"
],
"x": 38,
"y": 653,
"w": 1634,
"h": 684
},
{
"id": "7c29230c98070fd5",
"type": "group",
"z": "46892ced77481340",
"name": "",
"style": {
"fill": "#bfdbef",
"label": true,
"color": "#000000"
},
"nodes": [
"ff517137dc8eb4e5",
"2b9f0ac7a58d6e99",
"007a0818e00b6e8a",
"42040eb51b6909d2",
"888d856dae38ce27",
"2ba7fb1e189ec017",
"3cc3b21e7b1f7b13",
"f16b851b413f0d32",
"1a348789bcd14214",
"8044f4e5402ca464",
"f83a4ef2662f4f11",
"48b019b444db2a5a",
"639e1c2545c2de96"
],
"x": 48,
"y": 133,
"w": 1764,
"h": 494
},
{
"id": "41609eab5db77f0a",
"type": "group",
"z": "f9a2fb576f0d360d",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"36d1d2c1e10100e7",
"4c584ffba6a17ccb",
"c53543186fd45d8b",
"33eb6e0725214c0b",
"5df52e7f8217a6d9",
"6dd69a9285fc9583",
"3e5fabb6aa93449c",
"aadcf8d1921d77e6"
],
"x": 94,
"y": 2019,
"w": 1272,
"h": 162
},
{
"id": "b6271f4a3284f8d9",
"type": "group",
"z": "f9a2fb576f0d360d",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"46517eb4342b3d18",
"a3d5be29d6effa34",
"d23c32a704af639d",
"68f7d3015de2dbab",
"701c1cd70874e615"
],
"x": 94,
"y": 1879,
"w": 1272,
"h": 122
},
{
"id": "3db6f7ccc63a5f8b",
"type": "group",
"z": "f9a2fb576f0d360d",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"1633e8e6861be2e0",
"9c36d1335b0f8ebb",
"fe5612a41399f1f5",
"7f48ed25c8ec1fce",
"ab17cf6a7d65fcb9"
],
"x": 94,
"y": 1699,
"w": 1272,
"h": 162
},
{
"id": "5270af8a6312b29d",
"type": "group",
"z": "f9a2fb576f0d360d",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"25cf5d71108cbbb4",
"cbcd3d741247b12b",
"07e63813fb04b906",
"4d3d4a82a512ca10",
"0bf96ec77f6d1809"
],
"x": 94,
"y": 1459,
"w": 1272,
"h": 122
},
{
"id": "6809b1c79783ab0c",
"type": "group",
"z": "f9a2fb576f0d360d",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"a330bf2f4d26c536",
"398c06a48e4daa13"
],
"x": 94,
"y": 1599,
"w": 1272,
"h": 82
},
{
"id": "1166ae03751d953e",
"type": "group",
"z": "f9a2fb576f0d360d",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"ef6df11582a22110",
"774c15def7e6cf96"
],
"x": 94,
"y": 1359,
"w": 1272,
"h": 82
},
{
"id": "fb2d97888a83fc98",
"type": "group",
"z": "f9a2fb576f0d360d",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"6f028b285108ff17",
"82c1d5f7ae54b348"
],
"x": 94,
"y": 1259,
"w": 1272,
"h": 82
},
{
"id": "5b22d521e762f0da",
"type": "group",
"z": "f9a2fb576f0d360d",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"6e30880884a2cdb2",
"da7ab159be01b35c"
],
"x": 94,
"y": 1159,
"w": 1272,
"h": 82
},
{
"id": "74596bdef53b62cf",
"type": "group",
"z": "f9a2fb576f0d360d",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"0bd6051323b66072",
"6aac621e2a9acf79"
],
"x": 94,
"y": 1059,
"w": 1272,
"h": 82
},
{
"id": "5d202845936f0275",
"type": "group",
"z": "f9a2fb576f0d360d",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"becbc51cb810ff3d",
"4673e2e3f2c0626f"
],
"x": 94,
"y": 959,
"w": 1272,
"h": 82
},
{
"id": "68db2262f7c7313e",
"type": "group",
"z": "f9a2fb576f0d360d",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"675ba75711ef84e7",
"84272551b322cde2"
],
"x": 94,
"y": 859,
"w": 1272,
"h": 82
},
{
"id": "39f557d8eec2fbae",
"type": "group",
"z": "f9a2fb576f0d360d",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"a6cf1bd4ae01ee56",
"16eaca15570ff092",
"109c390c131b09a8",
"d02a9d4e0468bc67",
"2d6bcc49a2785fd6"
],
"x": 94,
"y": 379,
"w": 1272,
"h": 122
},
{
"id": "795d604329d51272",
"type": "group",
"z": "f9a2fb576f0d360d",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"1aa9e0ff37d1afee",
"b9c07d22cbaae6a2"
],
"x": 94,
"y": 279,
"w": 1272,
"h": 82
},
{
"id": "4b06cbc568091f6f",
"type": "group",
"z": "f9a2fb576f0d360d",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"6654c150377ed2bb",
"83bbabef65831016"
],
"x": 94,
"y": 179,
"w": 1272,
"h": 82
},
{
"id": "b5ffb4a4212da258",
"type": "group",
"z": "f9a2fb576f0d360d",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"ca1a1f7f8b90cfc9",
"b8f3d3242fb39bdd"
],
"x": 94,
"y": 79,
"w": 1272,
"h": 82
},
{
"id": "5c95d99a679a5e00",
"type": "group",
"z": "480553bb6f5b2b51",
"name": "Water Leak Notifications",
"style": {
"label": true,
"fill": "#0070c0",
"fill-opacity": "0.54",
"stroke": "#000000",
"color": "#000000"
},
"nodes": [
"8f42e8fdfef40579",
"58ee1ac91f379cb9",
"a1f1e1ea2cf90f61",
"3242605bce7f6f92",
"22740e52f6cc3399",
"53799a37bb6cf7c6",
"8b9761ea2f86b4f1",
"70f797398b0e6783",
"2157cdd444dfec91",
"8b2f06afcf0d773e",
"e31ec1ce332c4c99",
"1164cfc4fd2e5382",
"748c39a404648158",
"a73395db2426b4fc"
],
"x": 54,
"y": 379,
"w": 1562,
"h": 288
},
{
"id": "1c73b8aaec035f06",
"type": "group",
"z": "480553bb6f5b2b51",
"name": "Battery notifications",
"style": {
"fill": "#ffbfbf",
"label": true,
"color": "#000000"
},
"nodes": [
"eb721beae24b271b",
"41f1e9feaf1ea6aa",
"c60307d3b68ebe34",
"81d16e7a5307e9cc",
"209d79611a5414cc",
"e6a93b0cbc48af98",
"a9f755806e4e8a75",
"5c2272c244ffc8b0",
"6d60df5c0c6920d2"
],
"x": 54,
"y": 699,
"w": 1562,
"h": 162
},
{
"id": "bd16cebc90c528e9",
"type": "group",
"z": "46892ced77481340",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"b4e49387d80fa951",
"860779317fad91b5",
"2ae3fedce613ecfe",
"1a8d95afd537e151",
"d1c2e1ee1fba88c6"
],
"x": 1944,
"y": 319,
"w": 482,
"h": 232
},
{
"id": "507ca4f1b82ad9c2",
"type": "group",
"z": "46892ced77481340",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"66255b06a0d4a4c9",
"9c99ecea6e4aefd8"
],
"x": 1954,
"y": 559,
"w": 292,
"h": 82
},
{
"id": "cc230a0894b116d3",
"type": "group",
"z": "6722d185624fd57a",
"name": "",
"style": {
"fill": "#7fb7df",
"label": true
},
"nodes": [
"05ecf6f492d4a8cf",
"ad81a0918c31a862",
"7049d2e629127b0e",
"e44fa1b081b4aba7",
"532476a808456423",
"9e01966beafd582b",
"301e955ac79a9326",
"54161a78e09f85c3",
"0fdf497d70900d11",
"434ef7e821c63223"
],
"x": 134,
"y": 939,
"w": 992,
"h": 277
},
{
"id": "b73455843d7a5a9f",
"type": "group",
"z": "6722d185624fd57a",
"name": "Watering Schedule",
"style": {
"label": true,
"fill": "#b797cf"
},
"nodes": [
"905629455f4dd222",
"33e972f98673a6b6",
"ab7182ad5c37be48",
"d51ae77e82bb86f0",
"b43dc5183a67d128",
"2896d687417bbc1d",
"1199fd928d0abd32",
"86153b2dba01756f"
],
"x": 54,
"y": 379,
"w": 1432,
"h": 242
},
{
"id": "ef555db28dba4c46",
"type": "group",
"z": "f9a2fb576f0d360d",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"0b112f9f314fa0bb",
"a1f5a94baf1fbcd7",
"ae314d3d3457b679",
"0c35b08a3c7d347f",
"f0de9c882920d07c"
],
"x": 94,
"y": 519,
"w": 1272,
"h": 122
},
{
"id": "1756bd5d4ff2c23b",
"type": "group",
"z": "f9a2fb576f0d360d",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"310f749a07eded9d",
"d0febe343ef897ac",
"e1965a78e430acad",
"8cce4a0a7061ac87",
"d5cad6d8ca5fe08c"
],
"x": 94,
"y": 2199,
"w": 1272,
"h": 162
},
{
"id": "860e99939cf4fb5c",
"type": "group",
"z": "6722d185624fd57a",
"name": "Christmas Light",
"style": {
"label": true
},
"nodes": [
"d97b1b86e0e0040e",
"3737a8c897de2221",
"ca74d224370a0b5a",
"3a8262144b91d661",
"d20a28e1dea2fcde",
"01df5278eead8a98",
"1460ed0d062f8b73",
"6fdd0a95dd76a2e8",
"bb1639973b4a6a05",
"800cb2f6a21c882f",
"893d9228d166c0d2",
"be86177040153c9f"
],
"x": 654,
"y": 1679,
"w": 1272,
"h": 382
},
{
"id": "ce79bea4667a77e2",
"type": "group",
"z": "480553bb6f5b2b51",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"8656a450e0ae020d",
"7ff8359abb38dca4",
"doorbell_state_check",
"bd7fed2198a7b950",
"78a1c2a40934ef20",
"05f0d77a9b605f22",
"19d0e8d8c5addb1f",
"eff49303c6d84242",
"c74ddf6b84ef7a95",
"d496d62222d1a073",
"48bfe0ad8a973a84",
"88d855e525ab78f0",
"a4752681740af47e",
"7e88e31d094e343d",
"365adc2679063bc8",
"842a49fa21a0587a",
"bedee5f9397c27f1",
"3f9c2db4dfea3095",
"0446448ed8c8da8a",
"d241b1f4991cfc05"
],
"x": 14,
"y": 1129,
"w": 2362,
"h": 272
},
{
"id": "9da6393897881dca",
"type": "group",
"z": "46892ced77481340",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"5351a670ea3bcf15",
"8dd17125d6bb49f7",
"9b4f318fa5f438aa"
],
"x": 1764,
"y": 839,
"w": 522,
"h": 152
},
{
"id": "ff517137dc8eb4e5",
"type": "group",
"z": "46892ced77481340",
"g": "7c29230c98070fd5",
"name": "Office ",
"style": {
"label": true
},
"nodes": [
"a91dcb332bae2807",
"11f594c5b9f0fce8"
],
"x": 354,
"y": 379,
"w": 312,
"h": 102
},
{
"id": "2b9f0ac7a58d6e99",
"type": "group",
"z": "46892ced77481340",
"g": "7c29230c98070fd5",
"name": "Shower",
"style": {
"label": true
},
"nodes": [
"a2eceb1ef60667cb",
"102d7d54a45e3f18",
"a024d8a903074aa4",
"d680ff6c7ac109cf",
"9dc26f31e8b58f14"
],
"x": 1034,
"y": 259,
"w": 402,
"h": 222
},
{
"id": "007a0818e00b6e8a",
"type": "group",
"z": "46892ced77481340",
"g": "7c29230c98070fd5",
"name": "Master Bedroom",
"style": {
"label": true
},
"nodes": [
"67149a39f56c5694",
"d5dacec70d47b2e5",
"28d2293b97a7b72b",
"a6493ad8864f2b68"
],
"x": 354,
"y": 159,
"w": 312,
"h": 202
},
{
"id": "42040eb51b6909d2",
"type": "group",
"z": "46892ced77481340",
"g": "7c29230c98070fd5",
"name": "Kitchen",
"style": {
"label": true,
"fill": "#d1d1d1",
"color": "#000000"
},
"nodes": [
"e9aa8b33edf056f6",
"eda94d52e6cf650a",
"188a3b16710467e7",
"2dc64fabc1602ec8",
"a1f44cc63b77a2c3"
],
"x": 74,
"y": 159,
"w": 262,
"h": 422
},
{
"id": "888d856dae38ce27",
"type": "group",
"z": "46892ced77481340",
"g": "7c29230c98070fd5",
"name": "Veranda",
"style": {
"label": true
},
"nodes": [
"f714485f125865af",
"2565695beaa14d76",
"9594045be414b84c"
],
"x": 1434,
"y": 159,
"w": 352,
"h": 142
},
{
"id": "2ba7fb1e189ec017",
"type": "group",
"z": "46892ced77481340",
"g": "7c29230c98070fd5",
"name": "Living Room ",
"style": {
"label": true
},
"nodes": [
"58525896ff637a27",
"beeb512081d25291"
],
"x": 694,
"y": 379,
"w": 312,
"h": 82
},
{
"id": "3cc3b21e7b1f7b13",
"type": "group",
"z": "46892ced77481340",
"g": "7c29230c98070fd5",
"name": "Dining Room",
"style": {
"label": true
},
"nodes": [
"66cafcf3b261e8b5",
"04e183fcfe9e9f6d",
"1f3ba1a73e155da9",
"6190a90971a43aba"
],
"x": 694,
"y": 159,
"w": 312,
"h": 202
},
{
"id": "f16b851b413f0d32",
"type": "group",
"z": "46892ced77481340",
"g": "7c29230c98070fd5",
"name": "Guest WC",
"style": {
"label": true
},
"nodes": [
"f1cf19264e9957f3",
"0d7f6d11034f98ee"
],
"x": 1034,
"y": 499,
"w": 342,
"h": 82
},
{
"id": "1a348789bcd14214",
"type": "group",
"z": "46892ced77481340",
"g": "7c29230c98070fd5",
"name": "Back yard",
"style": {
"label": true
},
"nodes": [
"518a9fd6f52bfc23",
"839bb9d987729d16"
],
"x": 1434,
"y": 419,
"w": 352,
"h": 82
},
{
"id": "8044f4e5402ca464",
"type": "group",
"z": "46892ced77481340",
"g": "7c29230c98070fd5",
"name": "Master Bathroom",
"style": {
"label": true
},
"nodes": [
"0f93e95f3e92150a",
"ed3b84f4d63a8bd5"
],
"x": 1034,
"y": 159,
"w": 342,
"h": 82
},
{
"id": "f83a4ef2662f4f11",
"type": "group",
"z": "46892ced77481340",
"g": "7c29230c98070fd5",
"name": "Front Yard",
"style": {
"label": true
},
"nodes": [
"194c35655de1a128",
"45e37c698b0b2e5a"
],
"x": 1434,
"y": 319,
"w": 352,
"h": 82
},
{
"id": "48b019b444db2a5a",
"type": "group",
"z": "46892ced77481340",
"g": "7c29230c98070fd5",
"name": "Drive ways",
"style": {
"label": true
},
"nodes": [
"bbda8fd42d8aa120",
"01da9e8ebba7f592"
],
"x": 1434,
"y": 519,
"w": 352,
"h": 82
},
{
"id": "925b79f58f75e449",
"type": "group",
"z": "46892ced77481340",
"g": "d24bcb9ea3d9711c",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"40fd804bb4acf519",
"b9ab51a28b433f94",
"0d1a60ec03adac5c"
],
"x": 64,
"y": 999,
"w": 522,
"h": 152
},
{
"id": "b88648a578b60cb8",
"type": "group",
"z": "46892ced77481340",
"g": "d24bcb9ea3d9711c",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"1feb11ab8be3ef2e",
"01b4eb4b91f9c9e2",
"1ee2b22951639d6b"
],
"x": 64,
"y": 839,
"w": 522,
"h": 152
},
{
"id": "4a9361ba088ba046",
"type": "group",
"z": "46892ced77481340",
"g": "d24bcb9ea3d9711c",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"3c894953f414add5",
"7ec85095958da9f5",
"566e5b2ec261934f",
"89762968e1556a42"
],
"x": 64,
"y": 679,
"w": 522,
"h": 152
},
{
"id": "0271d58953459100",
"type": "group",
"z": "46892ced77481340",
"g": "d24bcb9ea3d9711c",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"af7220d8f5bb9bf2",
"b51586d393da96cd",
"e8db33fc81400531",
"e0739e7f8c82e487",
"1530556181903c3a"
],
"x": 624,
"y": 1099,
"w": 482,
"h": 202
},
{
"id": "4b360c7d54e39e0a",
"type": "group",
"z": "46892ced77481340",
"g": "d24bcb9ea3d9711c",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"53178ccb3f691dad",
"b2641f71595c1d2d",
"ba2859e1aa882eee"
],
"x": 624,
"y": 919,
"w": 482,
"h": 152
},
{
"id": "62cc8431c77a4797",
"type": "group",
"z": "46892ced77481340",
"g": "d24bcb9ea3d9711c",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"b664207011dd548a",
"39d435c6a32d4f09",
"5f7ffd82e5200d9a",
"f0bc3094d4af717e",
"0a4414fc667405b4",
"22c73018f4564256"
],
"x": 624,
"y": 679,
"w": 482,
"h": 262
},
{
"id": "2d6eb3ac6de382be",
"type": "group",
"z": "46892ced77481340",
"g": "d24bcb9ea3d9711c",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"e6e67dc471f2ecb3",
"fc5020edbd894baa",
"29af11e532f234d4"
],
"x": 1164,
"y": 839,
"w": 482,
"h": 152
},
{
"id": "af99b05ba44c6741",
"type": "group",
"z": "46892ced77481340",
"g": "d24bcb9ea3d9711c",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"b7e6812909ef1051",
"37cdfd56758051ef",
"280e6cc7a9de62b5"
],
"x": 1164,
"y": 679,
"w": 482,
"h": 152
},
{
"id": "3c7f8838aa2349b9",
"type": "group",
"z": "46892ced77481340",
"g": "d24bcb9ea3d9711c",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"806720bc7ab2d4e8",
"3b5e1f4f9ccd9c74",
"07bae699fea75512"
],
"x": 1164,
"y": 999,
"w": 482,
"h": 152
},
{
"id": "0b0b27deacee2bfc",
"type": "group",
"z": "46892ced77481340",
"g": "d24bcb9ea3d9711c",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"3ec8968914e324f5",
"2b29c71c180a50df",
"197fc35230069190"
],
"x": 64,
"y": 1159,
"w": 522,
"h": 152
},
{
"id": "639e1c2545c2de96",
"type": "group",
"z": "46892ced77481340",
"g": "7c29230c98070fd5",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"a8ac75d5944a28b9",
"f11fa2bedfc41e41"
],
"x": 354,
"y": 499,
"w": 292,
"h": 82
},
{
"id": "a73395db2426b4fc",
"type": "group",
"z": "480553bb6f5b2b51",
"g": "5c95d99a679a5e00",
"name": "Watering Schedule Notification",
"style": {
"label": true,
"fill": "#c8e7a7",
"color": "#000000"
},
"nodes": [
"c57ea029ee569428",
"fe7372c7f33d96f3",
"c1d2a4dc34b63730",
"141f635c6c9d380f",
"18454d6cad2042dc"
],
"x": 474,
"y": 499,
"w": 622,
"h": 142
},
{
"id": "4e20fc347c658518",
"type": "zigbee2mqtt-server",
"name": "",
"host": "mqtt.paraskeva.net",
"mqtt_port": 1883,
"mqtt_username": "nodered",
"mqtt_password": "sh1pb0x1",
"mqtt_qos": "0",
"tls": "",
"usetls": false,
"base_topic": "zigbee2mqtt"
},
{
"id": "29eb84a2708d96e0",
"type": "server",
"name": "Home Assistant",
"version": 6,
"addon": false,
"rejectUnauthorizedCerts": true,
"ha_boolean": [
"y",
"yes",
"true",
"on",
"home",
"open"
],
"connectionDelay": true,
"cacheJson": true,
"heartbeat": false,
"heartbeatInterval": 30,
"areaSelector": "friendlyName",
"deviceSelector": "friendlyName",
"entitySelector": "friendlyName",
"statusSeparator": ": ",
"statusYear": "hidden",
"statusMonth": "short",
"statusDay": "numeric",
"statusHourCycle": "default",
"statusTimeFormat": "h:m",
"enableGlobalContextStore": false
},
{
"id": "70fca1d2a3467c93",
"type": "ha-device-config",
"name": "Office",
"hwVersion": "",
"manufacturer": "Node-RED",
"model": "",
"swVersion": ""
},
{
"id": "7fe55db85a29f18c",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "70fca1d2a3467c93",
"name": "Office Light",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Office Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "4f23c8e7043f542b",
"type": "ha-device-config",
"name": "Master Bedroom",
"hwVersion": "",
"manufacturer": "Node-RED",
"model": "",
"swVersion": ""
},
{
"id": "5e7f6287035ecc94",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "4f23c8e7043f542b",
"name": "Master Bedroom Light",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Master Bedroom Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "b2c7564cfe776a2d",
"type": "nvl-datatypes",
"name": "Example types",
"datatypes": "//Structure definition\nTYPE ST_MyStruct:\nSTRUCT\n xBool: BOOL;\n bByte: BYTE;\nEND_STRUCT\nEND_TYPE\n\n//Enumeration definition\nTYPE ENUM_Light: (\n Red,\n Orange,\n Green := 10\n);\nEND_TYPE"
},
{
"id": "17b3adc633ee3394",
"type": "ha-device-config",
"name": "Shower",
"hwVersion": "",
"manufacturer": "Node-RED",
"model": "",
"swVersion": ""
},
{
"id": "88f51f9c233f4cc3",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "17b3adc633ee3394",
"name": "Shower Light",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Shower Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "3cec5437caacb905",
"type": "ha-device-config",
"name": "Kitchen",
"hwVersion": "",
"manufacturer": "Node-RED",
"model": "",
"swVersion": ""
},
{
"id": "29592d5555367344",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "3cec5437caacb905",
"name": "Kitchen Island",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Kitchen Island Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "cc2640502094371a",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "3cec5437caacb905",
"name": "Kitchen Main Light",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Kitchen Main Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "8e22cfb83ec013d1",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "3cec5437caacb905",
"name": "Fridge Light",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Fridge Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "085d42240f91eec2",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "3cec5437caacb905",
"name": "Pantry Light",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Pantry Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "451e5988101b1aac",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "4f23c8e7043f542b",
"name": "Master Bedroom Door Light",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Master Bedroom Door Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "c21001f594a359c9",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "4f23c8e7043f542b",
"name": "Master Bedroom Dresser Light",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Master Bedroom Dresser Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "29f5afd91874c0b8",
"type": "ha-device-config",
"name": "Veranda",
"hwVersion": "",
"manufacturer": "Node-RED",
"model": "",
"swVersion": ""
},
{
"id": "2a94bae266d9423d",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "29f5afd91874c0b8",
"name": "Veranda Light",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Veranda Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "d721225e966ecf1b",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "29f5afd91874c0b8",
"name": "Veranda BBQ Light",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Veranda BBQ Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "2380526f974b097d",
"type": "ha-device-config",
"name": "Living Room",
"hwVersion": "",
"manufacturer": "Node-RED",
"model": "",
"swVersion": ""
},
{
"id": "eca0cca02aabd143",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "2380526f974b097d",
"name": "Living Room Main Light",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Living Room Main Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "5d56cc73c39843cc",
"type": "ha-device-config",
"name": "Dining Room",
"hwVersion": "",
"manufacturer": "Node-RED",
"model": "",
"swVersion": ""
},
{
"id": "8c493a05a6971f90",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "5d56cc73c39843cc",
"name": "Dining Room Main Light",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Dining Room Main Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "9f0f51223282478b",
"type": "ha-device-config",
"name": "Guest WC",
"hwVersion": "",
"manufacturer": "Node-RED",
"model": "",
"swVersion": ""
},
{
"id": "85fe098bb4010c10",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "9f0f51223282478b",
"name": "Guest WC Light",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Guest WC Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "87957c9f7179fe85",
"type": "ha-device-config",
"name": "Master Bathroom",
"hwVersion": "",
"manufacturer": "Node-RED",
"model": "",
"swVersion": ""
},
{
"id": "ac7e5f5dfeb9ce54",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "87957c9f7179fe85",
"name": "Master Bathroom Main Light",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Master Bathroom Main Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "d46352482122dfe6",
"type": "ha-device-config",
"name": "Front Yard",
"hwVersion": "",
"manufacturer": "Node-RED",
"model": "",
"swVersion": ""
},
{
"id": "aa9cf2e1dc39616f",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "d46352482122dfe6",
"name": "Front Entrance Light",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Front Entrance Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "be89dbc3425f9cc0",
"type": "ha-device-config",
"name": "Back Yard",
"hwVersion": "",
"manufacturer": "Node-RED",
"model": "",
"swVersion": ""
},
{
"id": "a3fb2a27c9896974",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "be89dbc3425f9cc0",
"name": "Flood Light 1",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Flood Light 1"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "a1743637a1619654",
"type": "ha-device-config",
"name": "Driveways",
"hwVersion": "",
"manufacturer": "Node-RED",
"model": "",
"swVersion": ""
},
{
"id": "a97f2813611faac8",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "a1743637a1619654",
"name": "Driveway Flood Light",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Driveway Flood Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "f744459771e70676",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "70fca1d2a3467c93",
"name": "Office Light",
"version": 6,
"entityType": "binary_sensor",
"haConfig": [
{
"property": "name",
"value": "Office Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "2b453fcb286e51f5",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "4f23c8e7043f542b",
"name": "Master Bedroom Main Light",
"version": 6,
"entityType": "binary_sensor",
"haConfig": [
{
"property": "name",
"value": "Master Bedroom Main Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "edf39a33a28182ca",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "87957c9f7179fe85",
"name": "Master Bathroom Main Light",
"version": 6,
"entityType": "binary_sensor",
"haConfig": [
{
"property": "name",
"value": "Master Bathroom Main Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "16560fc93e9523d4",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "17b3adc633ee3394",
"name": "Shower Main Light",
"version": 6,
"entityType": "binary_sensor",
"haConfig": [
{
"property": "name",
"value": "Shower Main Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "9b2dc1266b7513da",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "17b3adc633ee3394",
"name": "Shower Fan",
"version": 6,
"entityType": "binary_sensor",
"haConfig": [
{
"property": "name",
"value": "Shower Fan"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "12e315808eced5db",
"type": "ha-device-config",
"name": "Bedroom",
"hwVersion": "",
"manufacturer": "Node-RED",
"model": "",
"swVersion": ""
},
{
"id": "ac2dba905819562f",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "17b3adc633ee3394",
"name": "Shower Fan Switch",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Shower Fan Switch"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "c494e187e88c3208",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "3cec5437caacb905",
"name": "Pantry Light",
"version": 6,
"entityType": "binary_sensor",
"haConfig": [
{
"property": "name",
"value": "Pantry Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "293fc06a888710c5",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "12e315808eced5db",
"name": "Bedroom Main Light",
"version": 6,
"entityType": "binary_sensor",
"haConfig": [
{
"property": "name",
"value": "Bedroom Main Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "1a22f89094ea7b38",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "29f5afd91874c0b8",
"name": "Veranda BBQ Light",
"version": 6,
"entityType": "binary_sensor",
"haConfig": [
{
"property": "name",
"value": "Veranda BBQ Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "8b4d5408fdcd8c0d",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "12e315808eced5db",
"name": "Bedroom Main Light",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Bedroom Main Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "f190a69cf72af140",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "5d56cc73c39843cc",
"name": "Dining Room Main",
"version": 6,
"entityType": "binary_sensor",
"haConfig": [
{
"property": "name",
"value": "Dining Room Main"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "b43c6846b0baeeec",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "2380526f974b097d",
"name": "Living Room Main",
"version": 6,
"entityType": "binary_sensor",
"haConfig": [
{
"property": "name",
"value": "Living Room Main"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "be947f3b20336437",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "3cec5437caacb905",
"name": "Kitchen Main",
"version": 6,
"entityType": "binary_sensor",
"haConfig": [
{
"property": "name",
"value": "Kitchen Main"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "9b99cd4af3bdb9a9",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "3cec5437caacb905",
"name": "Kitchen Island",
"version": 6,
"entityType": "binary_sensor",
"haConfig": [
{
"property": "name",
"value": "Kitchen Island"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "d75c31dd7a1edcbf",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "3cec5437caacb905",
"name": "Fridge Light",
"version": 6,
"entityType": "binary_sensor",
"haConfig": [
{
"property": "name",
"value": "Fridge Light"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "3dbb887330025103",
"type": "telegram bot",
"botname": "spito_robot",
"usernames": "nearxos",
"chatids": "4747176681",
"baseapiurl": "",
"testenvironment": false,
"updatemode": "polling",
"addressfamily": "0",
"pollinterval": 300,
"usesocks": false,
"sockshost": "",
"socksprotocol": "socks5",
"socksport": 6667,
"socksusername": "anonymous",
"sockspassword": "",
"bothost": "",
"botpath": "",
"localbothost": "0.0.0.0",
"localbotport": 8443,
"publicbotport": 8443,
"privatekey": "",
"certificate": "",
"useselfsignedcertificate": false,
"sslterminated": false,
"verboselogging": true
},
{
"id": "fe79cfd2fda112db",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "d46352482122dfe6",
"name": "Front Lights",
"version": 6,
"entityType": "binary_sensor",
"haConfig": [
{
"property": "name",
"value": "Front Lights"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "311d801ad1f1bc0f",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "d46352482122dfe6",
"name": "Front Lights",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Front Lights"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "a1235a09a8d34dea",
"type": "mqtt-broker",
"name": "",
"broker": "10.20.30.6",
"port": 1883,
"clientid": "",
"autoConnect": true,
"usetls": false,
"protocolVersion": 4,
"keepalive": 60,
"cleansession": true,
"autoUnsubscribe": true,
"birthTopic": "",
"birthQos": "0",
"birthRetain": "false",
"birthPayload": "",
"birthMsg": {},
"closeTopic": "",
"closeQos": "0",
"closeRetain": "false",
"closePayload": "",
"closeMsg": {},
"willTopic": "",
"willQos": "0",
"willRetain": "false",
"willPayload": "",
"willMsg": {},
"userProps": "",
"sessionExpiry": ""
},
{
"id": "telegram_bot_config",
"type": "telegram bot",
"botname": "Your Bot Name",
"usernames": "",
"chatids": "",
"baseapiurl": "",
"updatemode": "polling",
"pollinterval": "300",
"usesocks": false,
"sockshost": "",
"socksprotocol": "socks5",
"socksport": "6667",
"socksusername": "",
"sockspassword": "",
"bothost": "",
"botpath": "",
"localbotport": "8443",
"publicbotport": "8443",
"privatekey": "",
"certificate": "",
"useselfsignedcertificate": false,
"sslterminated": false,
"verboselogging": false
},
{
"id": "0d71a45029c6da27",
"type": "ui_tab",
"name": "Lights",
"icon": "dashboard",
"disabled": false,
"hidden": false
},
{
"id": "7df2b0bd19b6ef42",
"type": "ui_base",
"theme": {
"name": "theme-light",
"lightTheme": {
"default": "#0094CE",
"baseColor": "#0094CE",
"baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif",
"edited": true,
"reset": false
},
"darkTheme": {
"default": "#097479",
"baseColor": "#097479",
"baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif",
"edited": false
},
"customTheme": {
"name": "Untitled Theme 1",
"default": "#4B7930",
"baseColor": "#4B7930",
"baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif"
},
"themeState": {
"base-color": {
"default": "#0094CE",
"value": "#0094CE",
"edited": false
},
"page-titlebar-backgroundColor": {
"value": "#0094CE",
"edited": false
},
"page-backgroundColor": {
"value": "#fafafa",
"edited": false
},
"page-sidebar-backgroundColor": {
"value": "#ffffff",
"edited": false
},
"group-textColor": {
"value": "#1bbfff",
"edited": false
},
"group-borderColor": {
"value": "#ffffff",
"edited": false
},
"group-backgroundColor": {
"value": "#ffffff",
"edited": false
},
"widget-textColor": {
"value": "#111111",
"edited": false
},
"widget-backgroundColor": {
"value": "#0094ce",
"edited": false
},
"widget-borderColor": {
"value": "#ffffff",
"edited": false
},
"base-font": {
"value": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif"
}
},
"angularTheme": {
"primary": "indigo",
"accents": "blue",
"warn": "red",
"background": "grey",
"palette": "light"
}
},
"site": {
"name": "Node-RED Dashboard",
"hideToolbar": "false",
"allowSwipe": "false",
"lockMenu": "false",
"allowTempTheme": "true",
"dateFormat": "DD/MM/YYYY",
"sizes": {
"sx": 48,
"sy": 48,
"gx": 6,
"gy": 6,
"cx": 6,
"cy": 6,
"px": 0,
"py": 0
}
}
},
{
"id": "f0dee03e196ee8bc",
"type": "ui_group",
"name": "Default",
"tab": "0d71a45029c6da27",
"order": 1,
"disp": true,
"width": 6,
"collapse": false,
"className": ""
},
{
"id": "tab_masterBedroom",
"type": "ui_tab",
"name": "masterBedroom",
"icon": "dashboard",
"disabled": false,
"hidden": false
},
{
"id": "group_masterBedroom",
"type": "ui_group",
"name": "masterBedroom",
"tab": "tab_masterBedroom",
"order": 1,
"disp": true,
"width": 6,
"collapse": false,
"className": ""
},
{
"id": "tab_masterBathroom",
"type": "ui_tab",
"name": "masterBathroom",
"icon": "dashboard",
"disabled": false,
"hidden": false
},
{
"id": "group_masterBathroom",
"type": "ui_group",
"name": "masterBathroom",
"tab": "tab_masterBathroom",
"order": 1,
"disp": true,
"width": 6,
"collapse": false,
"className": ""
},
{
"id": "tab_bedroom_1",
"type": "ui_tab",
"name": "bedroom_1",
"icon": "dashboard",
"disabled": false,
"hidden": false
},
{
"id": "group_bedroom_1",
"type": "ui_group",
"name": "bedroom_1",
"tab": "tab_bedroom_1",
"order": 1,
"disp": true,
"width": 6,
"collapse": false,
"className": ""
},
{
"id": "tab_bedroom_2",
"type": "ui_tab",
"name": "bedroom_2",
"icon": "dashboard",
"disabled": false,
"hidden": false
},
{
"id": "group_bedroom_2",
"type": "ui_group",
"name": "bedroom_2",
"tab": "tab_bedroom_2",
"order": 1,
"disp": true,
"width": 6,
"collapse": false,
"className": ""
},
{
"id": "tab_bathroom",
"type": "ui_tab",
"name": "bathroom",
"icon": "dashboard",
"disabled": false,
"hidden": false
},
{
"id": "group_bathroom",
"type": "ui_group",
"name": "bathroom",
"tab": "tab_bathroom",
"order": 1,
"disp": true,
"width": 6,
"collapse": false,
"className": ""
},
{
"id": "tab_hallway",
"type": "ui_tab",
"name": "hallway",
"icon": "dashboard",
"disabled": false,
"hidden": false
},
{
"id": "group_hallway",
"type": "ui_group",
"name": "hallway",
"tab": "tab_hallway",
"order": 1,
"disp": true,
"width": 6,
"collapse": false,
"className": ""
},
{
"id": "tab_pantry",
"type": "ui_tab",
"name": "pantry",
"icon": "dashboard",
"disabled": false,
"hidden": false
},
{
"id": "group_pantry",
"type": "ui_group",
"name": "pantry",
"tab": "tab_pantry",
"order": 1,
"disp": true,
"width": 6,
"collapse": false,
"className": ""
},
{
"id": "tab_kitchen",
"type": "ui_tab",
"name": "kitchen",
"icon": "dashboard",
"disabled": false,
"hidden": false
},
{
"id": "group_kitchen",
"type": "ui_group",
"name": "kitchen",
"tab": "tab_kitchen",
"order": 1,
"disp": true,
"width": 6,
"collapse": false,
"className": ""
},
{
"id": "tab_livingRoom",
"type": "ui_tab",
"name": "livingRoom",
"icon": "dashboard",
"disabled": false,
"hidden": false
},
{
"id": "group_livingRoom",
"type": "ui_group",
"name": "livingRoom",
"tab": "tab_livingRoom",
"order": 1,
"disp": true,
"width": 6,
"collapse": false,
"className": ""
},
{
"id": "tab_dinningRoom",
"type": "ui_tab",
"name": "dinningRoom",
"icon": "dashboard",
"disabled": false,
"hidden": false
},
{
"id": "group_dinningRoom",
"type": "ui_group",
"name": "dinningRoom",
"tab": "tab_dinningRoom",
"order": 1,
"disp": true,
"width": 6,
"collapse": false,
"className": ""
},
{
"id": "tab_entrance",
"type": "ui_tab",
"name": "entrance",
"icon": "dashboard",
"disabled": false,
"hidden": false
},
{
"id": "group_entrance",
"type": "ui_group",
"name": "entrance",
"tab": "tab_entrance",
"order": 1,
"disp": true,
"width": 6,
"collapse": false,
"className": ""
},
{
"id": "tab_guestWc",
"type": "ui_tab",
"name": "guestWc",
"icon": "dashboard",
"disabled": false,
"hidden": false
},
{
"id": "group_guestWc",
"type": "ui_group",
"name": "guestWc",
"tab": "tab_guestWc",
"order": 1,
"disp": true,
"width": 6,
"collapse": false,
"className": ""
},
{
"id": "tab_outVeranda",
"type": "ui_tab",
"name": "outVeranda",
"icon": "dashboard",
"disabled": false,
"hidden": false
},
{
"id": "group_outVeranda",
"type": "ui_group",
"name": "outVeranda",
"tab": "tab_outVeranda",
"order": 1,
"disp": true,
"width": 6,
"collapse": false,
"className": ""
},
{
"id": "tab_outFront",
"type": "ui_tab",
"name": "outFront",
"icon": "dashboard",
"disabled": false,
"hidden": false
},
{
"id": "group_outFront",
"type": "ui_group",
"name": "outFront",
"tab": "tab_outFront",
"order": 1,
"disp": true,
"width": 6,
"collapse": false,
"className": ""
},
{
"id": "tab_outSide",
"type": "ui_tab",
"name": "outSide",
"icon": "dashboard",
"disabled": false,
"hidden": false
},
{
"id": "group_outSide",
"type": "ui_group",
"name": "outSide",
"tab": "tab_outSide",
"order": 1,
"disp": true,
"width": 6,
"collapse": false,
"className": ""
},
{
"id": "tab_outBack",
"type": "ui_tab",
"name": "outBack",
"icon": "dashboard",
"disabled": false,
"hidden": false
},
{
"id": "group_outBack",
"type": "ui_group",
"name": "outBack",
"tab": "tab_outBack",
"order": 1,
"disp": true,
"width": 6,
"collapse": false,
"className": ""
},
{
"id": "0c9a4c8d912d0a38",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "17b3adc633ee3394",
"name": "Water_boiler",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Water_boiler"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "8166d41aaab8a32a",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "17b3adc633ee3394",
"name": "Water_boiler",
"version": 6,
"entityType": "binary_sensor",
"haConfig": [
{
"property": "name",
"value": "Water_boiler"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "timer30min_config",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "17b3adc633ee3394",
"name": "Timer_30_Min",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Timer 30 Min"
},
{
"property": "icon",
"value": "mdi:timer"
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "timer1hour_config",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "17b3adc633ee3394",
"name": "Timer_1_Hour",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Timer 1 Hour"
},
{
"property": "icon",
"value": "mdi:timer"
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "timer2hours_config",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "17b3adc633ee3394",
"name": "Timer_2_Hours",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Timer 2 Hours"
},
{
"property": "icon",
"value": "mdi:timer"
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "timerstop_config",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "17b3adc633ee3394",
"name": "Stop_Timer",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Stop Timer"
},
{
"property": "icon",
"value": "mdi:timer-off"
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "timer_remaining_config",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "17b3adc633ee3394",
"name": "Timer_Remaining",
"version": 6,
"entityType": "sensor",
"haConfig": [
{
"property": "name",
"value": "Water Boiler Timer Remaining"
},
{
"property": "icon",
"value": "mdi:timer-sand"
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
},
{
"property": "unit_of_measurement",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "c5b6375b9e419298",
"type": "ha-device-config",
"name": "Entrance",
"hwVersion": "",
"manufacturer": "Node-RED",
"model": "",
"swVersion": ""
},
{
"id": "c1b8d65524acbab3",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "c5b6375b9e419298",
"name": "Entrance Mirror",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Entrance Mirror"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "72e9fc1709b9891c",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "c5b6375b9e419298",
"name": "Entrance Mirror",
"version": 6,
"entityType": "binary_sensor",
"haConfig": [
{
"property": "name",
"value": "Entrance Mirror"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "121b1dead369ae82",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "c5b6375b9e419298",
"name": "Entrance Light In",
"version": 6,
"entityType": "button",
"haConfig": [
{
"property": "name",
"value": "Entrance Light In"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "395ea43be3b0e20c",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "c5b6375b9e419298",
"name": "Entrance Light In",
"version": 6,
"entityType": "binary_sensor",
"haConfig": [
{
"property": "name",
"value": "Entrance Light In"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "3e00db06a8f6a759",
"type": "ha-device-config",
"name": "Living_Room_New",
"hwVersion": "",
"manufacturer": "Node-RED",
"model": "",
"swVersion": ""
},
{
"id": "6d1793815598b149",
"type": "ha-entity-config",
"server": "29eb84a2708d96e0",
"deviceConfig": "3e00db06a8f6a759",
"name": "Living_room_Lights",
"version": 6,
"entityType": "switch",
"haConfig": [
{
"property": "name",
"value": ""
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "ee7c2a47d6441c26",
"type": "function",
"z": "57bd1b149526fcee",
"name": "function 1",
"func": "// Get the room name from the environment variable\nconst roomName = env.get(\"room_name\");\n\n// Access Node-RED context for state storage\nlet contextState = context.get(roomName) || {};\n\n// Check if the payload contains the specified room\nif (msg.payload.hasOwnProperty(roomName)) {\n // Get the lights status for the specified room\n let lights = msg.payload[roomName];\n\n // Check if this is the first run (initial state)\n // Context is empty or missing expected light keys\n const expectedLights = ['l_1', 'l_2', 'l_3', 'l_4', 'l_5', 'l_6'];\n const isInitialState = Object.keys(contextState).length === 0 || \n expectedLights.some(light => !(light in contextState));\n\n // Create an output array for the 6 ports\n let outputs = [null, null, null, null, null, null];\n\n // Check each light status and detect changes\n for (let light in lights) {\n let lightStatus = lights[light];\n\n // On initial state, send ALL states to initialize binary sensors\n // Otherwise, only send changed states\n if (isInitialState || contextState[light] !== lightStatus) {\n // Update the context with the new status\n contextState[light] = lightStatus;\n\n // Create a new message preserving original metadata\n let newMsg = {\n payload: lightStatus,\n topic: msg.topic,\n _msgid: msg._msgid\n };\n\n // Assign the message to the correct output port\n switch (light) {\n case 'l_1':\n outputs[0] = newMsg;\n break;\n case 'l_2':\n outputs[1] = newMsg;\n break;\n case 'l_3':\n outputs[2] = newMsg;\n break;\n case 'l_4':\n outputs[3] = newMsg;\n break;\n case 'l_5':\n outputs[4] = newMsg;\n break;\n case 'l_6':\n outputs[5] = newMsg;\n break;\n default:\n // Ignore any unexpected light keys\n break;\n }\n }\n }\n\n // Store the updated state in context\n context.set(roomName, contextState);\n\n // Send states to the respective ports (all on initial, only changes otherwise)\n return outputs;\n\n} else {\n // If the specified room does not exist in the payload, clean up stored context\n context.set(roomName, null); // Remove stored state for the room\n return [null, null, null, null, null, null]; // Return array instead of null\n}\n\n",
"outputs": 6,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 400,
"y": 220,
"wires": [
[],
[],
[],
[],
[],
[]
]
},
{
"id": "f9557fd9a8b2eee2",
"type": "function",
"z": "d0de479f6b80ab6c",
"name": "function 2",
"func": "// Define the masterBedroom and sw_1 variables\nvar masterBedroom = \"bedroom_1\"; // Example variable for masterBedroom\nvar sw_1 = \"sw_1\"; // Example variable for sw_1\n\n// Create a message object to set the value to true\nvar msgTrue = {\n payload: {}\n};\nmsgTrue.payload[masterBedroom] = {};\nmsgTrue.payload[masterBedroom][sw_1] = true;\n\n// Create a message object to set the value to false\nvar msgFalse = {\n payload: {}\n};\nmsgFalse.payload[masterBedroom] = {};\nmsgFalse.payload[masterBedroom][sw_1] = false;\n\n// Send the message to set the value to true\nnode.send(msgTrue);\n\n// Delay for 1 second\nsetTimeout(function() {\n // Send the message to set the value to false after 1 second\n node.send(msgFalse);\n}, 1000); // 1000 milliseconds = 1 second\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 200,
"y": 80,
"wires": [
[]
]
},
{
"id": "d2a3760f36aa6f41",
"type": "switch",
"z": "4dc13919bcc9d676",
"name": "",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "1_single",
"vt": "str"
},
{
"t": "eq",
"v": "2_single",
"vt": "str"
},
{
"t": "eq",
"v": "3_single",
"vt": "str"
},
{
"t": "eq",
"v": "4_single",
"vt": "str"
},
{
"t": "eq",
"v": "single",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 5,
"x": 190,
"y": 80,
"wires": [
[
"0ce841560c8c4087"
],
[
"64b045db5a4541fa"
],
[
"4a891a7505b5fd00"
],
[
"258a84ec1d54a43a"
],
[
"5532273136423869"
]
]
},
{
"id": "0ce841560c8c4087",
"type": "function",
"z": "4dc13919bcc9d676",
"name": "Switch 1",
"func": "// Retrieve the combined device variable (e.g., \"bedroom_1.sw1\")\nvar switch_1 = env.get(\"switch_1\");\n\n// Split the string into room and switch name parts using the dot as a delimiter\nvar parts = switch_1.split(\".\");\nvar room = parts[0];\nvar switchName = parts[1];\n\n// Create a message object to set the switch to true\nvar msgTrue = {\n payload: {}\n};\nmsgTrue.payload[room] = {};\nmsgTrue.payload[room][switchName] = true;\n\n// Create a message object to set the switch to false\nvar msgFalse = {\n payload: {}\n};\nmsgFalse.payload[room] = {};\nmsgFalse.payload[room][switchName] = false;\n\n// Send the message to set the switch to true\nnode.send(msgTrue);\n\n// Delay for 1 second before setting the switch to false\nsetTimeout(function () {\n node.send(msgFalse);\n}, 1000);\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 380,
"y": 60,
"wires": [
[]
]
},
{
"id": "64b045db5a4541fa",
"type": "function",
"z": "4dc13919bcc9d676",
"name": "Switch 2",
"func": "// Retrieve the combined device variable (e.g., \"bedroom_1.sw1\")\nvar switch_2 = env.get(\"switch_2\");\n\n// Split the string into room and switch name parts using the dot as a delimiter\nvar parts = switch_2.split(\".\");\nvar room = parts[0];\nvar switchName = parts[1];\n\n// Create a message object to set the switch to true\nvar msgTrue = {\n payload: {}\n};\nmsgTrue.payload[room] = {};\nmsgTrue.payload[room][switchName] = true;\n\n// Create a message object to set the switch to false\nvar msgFalse = {\n payload: {}\n};\nmsgFalse.payload[room] = {};\nmsgFalse.payload[room][switchName] = false;\n\n// Send the message to set the switch to true\nnode.send(msgTrue);\n\n// Delay for 1 second before setting the switch to false\nsetTimeout(function () {\n node.send(msgFalse);\n}, 1000);\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 380,
"y": 100,
"wires": [
[]
]
},
{
"id": "4a891a7505b5fd00",
"type": "function",
"z": "4dc13919bcc9d676",
"name": "Switch 3",
"func": "// Retrieve the combined device variable (e.g., \"bedroom_1.sw1\")\nvar switch_3 = env.get(\"switch_3\");\n\n// Split the string into room and switch name parts using the dot as a delimiter\nvar parts = switch_3.split(\".\");\nvar room = parts[0];\nvar switchName = parts[1];\n\n// Create a message object to set the switch to true\nvar msgTrue = {\n payload: {}\n};\nmsgTrue.payload[room] = {};\nmsgTrue.payload[room][switchName] = true;\n\n// Create a message object to set the switch to false\nvar msgFalse = {\n payload: {}\n};\nmsgFalse.payload[room] = {};\nmsgFalse.payload[room][switchName] = false;\n\n// Send the message to set the switch to true\nnode.send(msgTrue);\n\n// Delay for 1 second before setting the switch to false\nsetTimeout(function () {\n node.send(msgFalse);\n}, 1000);\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 380,
"y": 140,
"wires": [
[]
]
},
{
"id": "258a84ec1d54a43a",
"type": "function",
"z": "4dc13919bcc9d676",
"name": "Switch 4",
"func": "// Retrieve the combined device variable (e.g., \"bedroom_1.sw1\")\nvar switch_4 = env.get(\"switch_4\");\n\n// Split the string into room and switch name parts using the dot as a delimiter\nvar parts = switch_4.split(\".\");\nvar room = parts[0];\nvar switchName = parts[1];\n\n// Create a message object to set the switch to true\nvar msgTrue = {\n payload: {}\n};\nmsgTrue.payload[room] = {};\nmsgTrue.payload[room][switchName] = true;\n\n// Create a message object to set the switch to false\nvar msgFalse = {\n payload: {}\n};\nmsgFalse.payload[room] = {};\nmsgFalse.payload[room][switchName] = false;\n\n// Send the message to set the switch to true\nnode.send(msgTrue);\n\n// Delay for 1 second before setting the switch to false\nsetTimeout(function () {\n node.send(msgFalse);\n}, 1000);\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 380,
"y": 180,
"wires": [
[]
]
},
{
"id": "5532273136423869",
"type": "function",
"z": "4dc13919bcc9d676",
"name": "Switch 4",
"func": "// Retrieve the combined device variable (e.g., \"bedroom_1.sw1\")\nvar single = env.get(\"single\");\n\n// Split the string into room and switch name parts using the dot as a delimiter\nvar parts = single.split(\".\");\nvar room = parts[0];\nvar switchName = parts[1];\n\n// Create a message object to set the switch to true\nvar msgTrue = {\n payload: {}\n};\nmsgTrue.payload[room] = {};\nmsgTrue.payload[room][switchName] = true;\n\n// Create a message object to set the switch to false\nvar msgFalse = {\n payload: {}\n};\nmsgFalse.payload[room] = {};\nmsgFalse.payload[room][switchName] = false;\n\n// Send the message to set the switch to true\nnode.send(msgTrue);\n\n// Delay for 1 second before setting the switch to false\nsetTimeout(function () {\n node.send(msgFalse);\n}, 1000);\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 380,
"y": 220,
"wires": [
[]
]
},
{
"id": "030bba61776bd099",
"type": "nvl-send",
"z": "46892ced77481340",
"name": "",
"definition": "VAR_GLOBAL\n\tmasterBedroom \t:\tstruct_switches;\n\tmasterBathroom\t:\tstruct_switches;\n\tbedroom_1\t\t:\tstruct_switches;\n\tbedroom_2\t\t:\tstruct_switches;\n\tbathroom\t\t:\tstruct_switches;\n\thallway\t\t\t:\tstruct_switches;\n\tpantry\t\t\t:\tstruct_switches;\n\tkitchen\t\t\t:\tstruct_switches;\n\tlivingRoom\t\t:\tstruct_switches;\n\tdinningRoom\t\t:\tstruct_switches;\n\tentrance\t\t:\tstruct_switches;\n\tguestWc\t\t\t:\tstruct_switches;\n\toutVeranda\t\t:\tstruct_switches;\n\toutFront\t\t:\tstruct_switches;\n\toutSide\t\t\t:\tstruct_switches;\n\toutBack\t\t\t:\tstruct_switches;\n\tcmd_livingroom\t:\tstruct_room_cmds;\nEND_VAR\n\nTYPE struct_switches :\nSTRUCT\n\tall_off:BOOL;\n\tall_on:BOOL;\t\n\tsw_1:BOOL;\n\tsw_2:BOOL;\n\tsw_3:BOOL;\n\tsw_4:BOOL;\n\tsw_5:BOOL;\n\tsw_6:BOOL;\t\nEND_STRUCT\nEND_TYPE\n\nTYPE struct_room_cmds :\nSTRUCT\n // Home Assistant Commands (set/reset)\n ha_l1_on: BOOL;\n ha_l1_off: BOOL;\n ha_l2_on: BOOL;\n ha_l2_off: BOOL;\n ha_l3_on: BOOL;\n ha_l3_off: BOOL;\n ha_l4_on: BOOL;\n ha_l4_off: BOOL;\n ha_l5_on: BOOL;\n ha_l5_off: BOOL;\n ha_l6_on: BOOL;\n ha_l6_off: BOOL;\n \n // Zigbee Switch Inputs (edge detection for toggle)\n zigbee_sw1: BOOL; \n zigbee_sw2: BOOL;\n zigbee_sw3: BOOL;\n zigbee_sw4: BOOL;\n zigbee_sw5: BOOL;\n zigbee_sw6: BOOL;\n \n // Global Commands\n ha_all_on: BOOL;\n ha_all_off: BOOL;\nEND_STRUCT\nEND_TYPE",
"listId": "3",
"globaltypes": "",
"pack": "true",
"port": "",
"x": 400,
"y": 40,
"wires": [
[
"040e9ff14df4a326",
"f48d2c10e183fb95"
]
]
},
{
"id": "a18b0ead6d0e88cb",
"type": "nvl-receive",
"z": "46892ced77481340",
"name": "",
"definition": "\nVAR_GLOBAL\n\n\tl_masterBedroom \t:\tstruct_lights;\n\tl_masterBathroom\t:\tstruct_lights;\n\tl_bedroom_1\t\t\t:\tstruct_lights;\n\tl_bedroom_2\t\t\t:\tstruct_lights;\n\tl_bathroom\t\t\t:\tstruct_lights;\n\tl_hallway\t\t\t:\tstruct_lights;\n\tl_pantry\t\t\t:\tstruct_lights;\n\tl_kitchen\t\t\t:\tstruct_lights;\n\tl_livingRoom\t\t:\tstruct_lights;\n\tl_dinningRoom\t\t:\tstruct_lights;\n\tl_entrance\t\t\t:\tstruct_lights;\n\tl_guestWc\t\t\t:\tstruct_lights;\n\tl_outVeranda\t\t:\tstruct_lights;\n\tl_outFront\t\t\t:\tstruct_lights;\n\tl_outSide\t\t\t:\tstruct_lights;\n\tl_outBack\t\t\t:\tstruct_lights;\n\tlight_livingRoom\t\t:\tstruct_room_outs;\nEND_VAR\n\n\nTYPE struct_lights:\nSTRUCT\n l_1 \t\t: BOOL;\n\tl_2 \t\t: BOOL;\n\tl_3 \t\t: BOOL;\n\tl_4 \t\t: BOOL;\n\tl_5 \t\t: BOOL;\n\tl_6 \t\t: BOOL;\t\nEND_STRUCT\nEND_TYPE\n\nTYPE struct_room_outs :\nSTRUCT\n l_1: BOOL; // Light 1 control output\n l_2: BOOL; // Light 2 control output\n l_3: BOOL; // Light 3 control output\n l_4: BOOL; // Light 4 control output\n l_5: BOOL; // Light 5 control output\n l_6: BOOL; // Light 6 control output\n \n // Status feedback (read from actual relay outputs)\n l_1_status: BOOL; // Actual relay 1 state\n l_2_status: BOOL; // Actual relay 2 state\n l_3_status: BOOL; // Actual relay 3 state\n l_4_status: BOOL; // Actual relay 4 state\n l_5_status: BOOL; // Actual relay 5 state\n l_6_status: BOOL; // Actual relay 6 state\nEND_STRUCT\nEND_TYPE",
"listId": "1",
"globaltypes": "",
"pack": "true",
"x": 990,
"y": 40,
"wires": [
[
"e059a9fd1da3c3fd",
"9672723b593ef966"
]
]
},
{
"id": "040e9ff14df4a326",
"type": "udp out",
"z": "46892ced77481340",
"name": "",
"addr": "plc.paraskeva.net",
"iface": "",
"port": "1202",
"ipv": "udp4",
"outport": "",
"base64": false,
"multicast": "false",
"x": 640,
"y": 40,
"wires": []
},
{
"id": "67f7ec38bbf87e95",
"type": "udp in",
"z": "46892ced77481340",
"name": "",
"iface": "",
"port": "1202",
"ipv": "udp4",
"multicast": "false",
"group": "",
"datatype": "buffer",
"x": 820,
"y": 40,
"wires": [
[
"a18b0ead6d0e88cb"
]
]
},
{
"id": "a91dcb332bae2807",
"type": "ha-button",
"z": "46892ced77481340",
"g": "ff517137dc8eb4e5",
"name": "Office",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "7fe55db85a29f18c",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "bedroom_1",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_1",
"valueType": "str"
}
],
"x": 430,
"y": 420,
"wires": [
[
"11f594c5b9f0fce8"
]
]
},
{
"id": "67149a39f56c5694",
"type": "ha-button",
"z": "46892ced77481340",
"g": "007a0818e00b6e8a",
"name": "Main Light",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "5e7f6287035ecc94",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "masterBedroom",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_1",
"valueType": "str"
}
],
"x": 440,
"y": 200,
"wires": [
[
"a6493ad8864f2b68"
]
]
},
{
"id": "40fd804bb4acf519",
"type": "subflow:57bd1b149526fcee",
"z": "46892ced77481340",
"g": "925b79f58f75e449",
"name": "Office",
"env": [
{
"name": "room_name",
"value": "l_bedroom_1",
"type": "str"
}
],
"x": 230,
"y": 1080,
"wires": [
[
"b9ab51a28b433f94"
],
[],
[],
[],
[],
[]
]
},
{
"id": "123bb560d193b3aa",
"type": "function",
"z": "46892ced77481340",
"name": "function 3",
"func": "// Retrieve room and switch from the input message\nvar room = msg.topic; // e.g., \"masterBedroom\"\nvar switchName = msg.payload; // e.g., \"sw_1\"\n\n// Create a message object to set the value to true\nvar msgTrue = {\n payload: {}\n};\nmsgTrue.payload[room] = {};\nmsgTrue.payload[room][switchName] = true;\n\n// Create a message object to set the value to false\nvar msgFalse = {\n payload: {}\n};\nmsgFalse.payload[room] = {};\nmsgFalse.payload[room][switchName] = false;\n\n// Send the message to set the value to true\nnode.send(msgTrue);\n\n// Delay for 1 second\nsetTimeout(function() {\n // Send the message to set the value to false after 1 second\n node.send(msgFalse);\n}, 1000); // 1000 milliseconds = 1 second\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 200,
"y": 40,
"wires": [
[
"030bba61776bd099",
"438b13c5cdbb5f1c"
]
]
},
{
"id": "c6162cb59e21491f",
"type": "link in",
"z": "46892ced77481340",
"name": "from zigbee",
"links": [
"629cbd7ce15bb9e3",
"6fb9cc41c7b14fac",
"74c2640db1c8bd3e",
"bcf5055c45c97cc3"
],
"x": 245,
"y": 100,
"wires": [
[
"030bba61776bd099"
]
]
},
{
"id": "a2eceb1ef60667cb",
"type": "ha-button",
"z": "46892ced77481340",
"g": "2b9f0ac7a58d6e99",
"name": "Shower Light",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "88f51f9c233f4cc3",
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "sw_1",
"valueType": "str"
},
{
"property": "topic",
"propertyType": "msg",
"value": "bathroom",
"valueType": "str"
}
],
"x": 1130,
"y": 300,
"wires": [
[
"102d7d54a45e3f18"
]
]
},
{
"id": "e9aa8b33edf056f6",
"type": "ha-button",
"z": "46892ced77481340",
"g": "42040eb51b6909d2",
"name": "Kitchen Island",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "29592d5555367344",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "kitchen",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_2",
"valueType": "str"
}
],
"x": 170,
"y": 220,
"wires": [
[
"a1f44cc63b77a2c3"
]
]
},
{
"id": "eda94d52e6cf650a",
"type": "ha-button",
"z": "46892ced77481340",
"g": "42040eb51b6909d2",
"name": "Main",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "cc2640502094371a",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "kitchen",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_1",
"valueType": "str"
}
],
"x": 150,
"y": 280,
"wires": [
[
"a1f44cc63b77a2c3"
]
]
},
{
"id": "188a3b16710467e7",
"type": "ha-button",
"z": "46892ced77481340",
"g": "42040eb51b6909d2",
"name": "Fridge",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "8e22cfb83ec013d1",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "kitchen",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_3",
"valueType": "str"
}
],
"x": 150,
"y": 340,
"wires": [
[
"a1f44cc63b77a2c3"
]
]
},
{
"id": "f714485f125865af",
"type": "ha-button",
"z": "46892ced77481340",
"g": "888d856dae38ce27",
"name": "outVeranda",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "2a94bae266d9423d",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "outVeranda",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_2",
"valueType": "str"
}
],
"x": 1530,
"y": 200,
"wires": [
[
"9594045be414b84c"
]
]
},
{
"id": "2dc64fabc1602ec8",
"type": "ha-button",
"z": "46892ced77481340",
"g": "42040eb51b6909d2",
"name": "Pantry",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "085d42240f91eec2",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "pantry",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_1",
"valueType": "str"
}
],
"x": 210,
"y": 540,
"wires": [
[
"a1f44cc63b77a2c3"
]
]
},
{
"id": "58525896ff637a27",
"type": "ha-button",
"z": "46892ced77481340",
"g": "2ba7fb1e189ec017",
"name": "Main",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "eca0cca02aabd143",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "livingRoom",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_1",
"valueType": "str"
}
],
"x": 770,
"y": 420,
"wires": [
[
"beeb512081d25291"
]
]
},
{
"id": "d5dacec70d47b2e5",
"type": "ha-button",
"z": "46892ced77481340",
"g": "007a0818e00b6e8a",
"name": "Door",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "451e5988101b1aac",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "masterBedroom",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_2",
"valueType": "str"
}
],
"x": 430,
"y": 260,
"wires": [
[
"a6493ad8864f2b68"
]
]
},
{
"id": "28d2293b97a7b72b",
"type": "ha-button",
"z": "46892ced77481340",
"g": "007a0818e00b6e8a",
"name": "Dresser",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "c21001f594a359c9",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "str"
}
],
"x": 430,
"y": 320,
"wires": [
[
"a6493ad8864f2b68"
]
]
},
{
"id": "2565695beaa14d76",
"type": "ha-button",
"z": "46892ced77481340",
"g": "888d856dae38ce27",
"name": "BBQ",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "d721225e966ecf1b",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "outSide",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_1",
"valueType": "str"
}
],
"x": 1510,
"y": 260,
"wires": [
[
"9594045be414b84c"
]
]
},
{
"id": "66cafcf3b261e8b5",
"type": "ha-button",
"z": "46892ced77481340",
"g": "3cc3b21e7b1f7b13",
"name": "Main",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "8c493a05a6971f90",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "dinningRoom",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_1",
"valueType": "str"
}
],
"x": 770,
"y": 200,
"wires": [
[
"04e183fcfe9e9f6d"
]
]
},
{
"id": "0bbcb269da9b75c7",
"type": "link in",
"z": "46892ced77481340",
"name": "From HA Entities",
"links": [
"11f594c5b9f0fce8",
"102d7d54a45e3f18",
"a6493ad8864f2b68",
"9594045be414b84c",
"beeb512081d25291",
"04e183fcfe9e9f6d",
"0d7f6d11034f98ee",
"839bb9d987729d16",
"ed3b84f4d63a8bd5",
"45e37c698b0b2e5a",
"01da9e8ebba7f592",
"740b766e9bdc0d2a",
"a1f44cc63b77a2c3",
"f11fa2bedfc41e41",
"33eb6e0725214c0b",
"9c99ecea6e4aefd8",
"e44fa1b081b4aba7",
"1d0a46b9d5255560"
],
"x": 75,
"y": 40,
"wires": [
[
"123bb560d193b3aa",
"e4d5c7b8295b4251"
]
]
},
{
"id": "11f594c5b9f0fce8",
"type": "link out",
"z": "46892ced77481340",
"g": "ff517137dc8eb4e5",
"name": "to PLC Function",
"mode": "link",
"links": [
"0bbcb269da9b75c7"
],
"x": 625,
"y": 440,
"wires": []
},
{
"id": "102d7d54a45e3f18",
"type": "link out",
"z": "46892ced77481340",
"g": "2b9f0ac7a58d6e99",
"name": "link out 2",
"mode": "link",
"links": [
"0bbcb269da9b75c7"
],
"x": 1335,
"y": 300,
"wires": []
},
{
"id": "a6493ad8864f2b68",
"type": "link out",
"z": "46892ced77481340",
"g": "007a0818e00b6e8a",
"name": "link out 3",
"mode": "link",
"links": [
"0bbcb269da9b75c7"
],
"x": 625,
"y": 200,
"wires": []
},
{
"id": "a1f44cc63b77a2c3",
"type": "link out",
"z": "46892ced77481340",
"g": "42040eb51b6909d2",
"name": "link out 4",
"mode": "link",
"links": [
"0bbcb269da9b75c7"
],
"x": 295,
"y": 200,
"wires": []
},
{
"id": "9594045be414b84c",
"type": "link out",
"z": "46892ced77481340",
"g": "888d856dae38ce27",
"name": "link out 5",
"mode": "link",
"links": [
"0bbcb269da9b75c7"
],
"x": 1745,
"y": 200,
"wires": []
},
{
"id": "beeb512081d25291",
"type": "link out",
"z": "46892ced77481340",
"g": "2ba7fb1e189ec017",
"name": "link out 6",
"mode": "link",
"links": [
"0bbcb269da9b75c7"
],
"x": 965,
"y": 420,
"wires": []
},
{
"id": "04e183fcfe9e9f6d",
"type": "link out",
"z": "46892ced77481340",
"g": "3cc3b21e7b1f7b13",
"name": "link out 7",
"mode": "link",
"links": [
"0bbcb269da9b75c7"
],
"x": 965,
"y": 200,
"wires": []
},
{
"id": "f1cf19264e9957f3",
"type": "ha-button",
"z": "46892ced77481340",
"g": "f16b851b413f0d32",
"name": "Guest WC Light",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "85fe098bb4010c10",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "guestWc",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_1",
"valueType": "str"
}
],
"x": 1140,
"y": 540,
"wires": [
[
"0d7f6d11034f98ee"
]
]
},
{
"id": "0d7f6d11034f98ee",
"type": "link out",
"z": "46892ced77481340",
"g": "f16b851b413f0d32",
"name": "link out 8",
"mode": "link",
"links": [
"0bbcb269da9b75c7"
],
"x": 1335,
"y": 540,
"wires": []
},
{
"id": "518a9fd6f52bfc23",
"type": "ha-button",
"z": "46892ced77481340",
"g": "1a348789bcd14214",
"name": "Flood Light 1",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "a3fb2a27c9896974",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "outBack",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "str"
}
],
"x": 1530,
"y": 460,
"wires": [
[
"839bb9d987729d16"
]
]
},
{
"id": "839bb9d987729d16",
"type": "link out",
"z": "46892ced77481340",
"g": "1a348789bcd14214",
"name": "link out 9",
"mode": "link",
"links": [
"0bbcb269da9b75c7"
],
"x": 1745,
"y": 460,
"wires": []
},
{
"id": "0f93e95f3e92150a",
"type": "ha-button",
"z": "46892ced77481340",
"g": "8044f4e5402ca464",
"name": "Main",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "ac7e5f5dfeb9ce54",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "masterBathroom",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_1",
"valueType": "str"
}
],
"x": 1110,
"y": 200,
"wires": [
[
"ed3b84f4d63a8bd5"
]
]
},
{
"id": "ed3b84f4d63a8bd5",
"type": "link out",
"z": "46892ced77481340",
"g": "8044f4e5402ca464",
"name": "link out 10",
"mode": "link",
"links": [
"0bbcb269da9b75c7"
],
"x": 1335,
"y": 200,
"wires": []
},
{
"id": "194c35655de1a128",
"type": "ha-button",
"z": "46892ced77481340",
"g": "f83a4ef2662f4f11",
"name": "Entrance Light out",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "aa9cf2e1dc39616f",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "outFront",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "str"
}
],
"x": 1550,
"y": 360,
"wires": [
[
"45e37c698b0b2e5a"
]
]
},
{
"id": "45e37c698b0b2e5a",
"type": "link out",
"z": "46892ced77481340",
"g": "f83a4ef2662f4f11",
"name": "link out 11",
"mode": "link",
"links": [
"0bbcb269da9b75c7"
],
"x": 1745,
"y": 360,
"wires": []
},
{
"id": "bbda8fd42d8aa120",
"type": "ha-button",
"z": "46892ced77481340",
"g": "48b019b444db2a5a",
"name": "Driveway Flood Light",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "a97f2813611faac8",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "str"
}
],
"x": 1560,
"y": 560,
"wires": [
[
"01da9e8ebba7f592"
]
]
},
{
"id": "01da9e8ebba7f592",
"type": "link out",
"z": "46892ced77481340",
"g": "48b019b444db2a5a",
"name": "link out 12",
"mode": "link",
"links": [
"0bbcb269da9b75c7"
],
"x": 1745,
"y": 560,
"wires": []
},
{
"id": "039e1be0cfe8e630",
"type": "ha-button",
"z": "46892ced77481340",
"d": true,
"g": "664de832a54bc4e0",
"name": "",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "str"
}
],
"x": 2010,
"y": 220,
"wires": [
[
"740b766e9bdc0d2a"
]
]
},
{
"id": "740b766e9bdc0d2a",
"type": "link out",
"z": "46892ced77481340",
"g": "664de832a54bc4e0",
"name": "link out 13",
"mode": "link",
"links": [
"0bbcb269da9b75c7"
],
"x": 2185,
"y": 220,
"wires": []
},
{
"id": "b9ab51a28b433f94",
"type": "ha-binary-sensor",
"z": "46892ced77481340",
"g": "925b79f58f75e449",
"name": "Office Light",
"entityConfig": "f744459771e70676",
"version": 0,
"state": "payload",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 490,
"y": 1040,
"wires": [
[]
]
},
{
"id": "e059a9fd1da3c3fd",
"type": "link out",
"z": "46892ced77481340",
"name": "from PLC states",
"mode": "link",
"links": [
"0d1a60ec03adac5c",
"01b4eb4b91f9c9e2",
"7ec85095958da9f5",
"b51586d393da96cd",
"b2641f71595c1d2d",
"39d435c6a32d4f09",
"fc5020edbd894baa",
"37cdfd56758051ef",
"d3f0c80e0188aabf",
"3b5e1f4f9ccd9c74",
"2b29c71c180a50df",
"860779317fad91b5",
"8dd17125d6bb49f7",
"7c4268195123e319",
"032f98ab9d5085b8"
],
"x": 1205,
"y": 100,
"wires": []
},
{
"id": "0d1a60ec03adac5c",
"type": "link in",
"z": "46892ced77481340",
"g": "925b79f58f75e449",
"name": "link in 1",
"links": [
"e059a9fd1da3c3fd"
],
"x": 105,
"y": 1080,
"wires": [
[
"40fd804bb4acf519"
]
]
},
{
"id": "1feb11ab8be3ef2e",
"type": "subflow:57bd1b149526fcee",
"z": "46892ced77481340",
"g": "b88648a578b60cb8",
"name": "Living Room",
"env": [
{
"name": "room_name",
"value": "l_livingRoom",
"type": "str"
}
],
"x": 250,
"y": 920,
"wires": [
[
"1ee2b22951639d6b"
],
[],
[],
[],
[],
[]
]
},
{
"id": "01b4eb4b91f9c9e2",
"type": "link in",
"z": "46892ced77481340",
"g": "b88648a578b60cb8",
"name": "link in 2",
"links": [
"e059a9fd1da3c3fd"
],
"x": 105,
"y": 920,
"wires": [
[
"1feb11ab8be3ef2e"
]
]
},
{
"id": "3c894953f414add5",
"type": "subflow:57bd1b149526fcee",
"z": "46892ced77481340",
"g": "4a9361ba088ba046",
"name": "Dining Room",
"env": [
{
"name": "room_name",
"value": "l_dinningRoom",
"type": "str"
}
],
"x": 250,
"y": 760,
"wires": [
[
"566e5b2ec261934f"
],
[],
[
"89762968e1556a42"
],
[],
[],
[]
]
},
{
"id": "7ec85095958da9f5",
"type": "link in",
"z": "46892ced77481340",
"g": "4a9361ba088ba046",
"name": "link in 3",
"links": [
"e059a9fd1da3c3fd"
],
"x": 105,
"y": 760,
"wires": [
[
"3c894953f414add5"
]
]
},
{
"id": "af7220d8f5bb9bf2",
"type": "subflow:57bd1b149526fcee",
"z": "46892ced77481340",
"g": "0271d58953459100",
"name": "Kitchen",
"env": [
{
"name": "room_name",
"value": "l_kitchen",
"type": "str"
}
],
"x": 800,
"y": 1180,
"wires": [
[
"e8db33fc81400531"
],
[
"e0739e7f8c82e487"
],
[
"1530556181903c3a"
],
[],
[],
[]
]
},
{
"id": "b51586d393da96cd",
"type": "link in",
"z": "46892ced77481340",
"g": "0271d58953459100",
"name": "link in 4",
"links": [
"e059a9fd1da3c3fd"
],
"x": 665,
"y": 1180,
"wires": [
[
"af7220d8f5bb9bf2"
]
]
},
{
"id": "53178ccb3f691dad",
"type": "subflow:57bd1b149526fcee",
"z": "46892ced77481340",
"g": "4b360c7d54e39e0a",
"name": "Bedroom",
"env": [
{
"name": "room_name",
"value": "l_bedroom_2",
"type": "str"
}
],
"x": 800,
"y": 1000,
"wires": [
[
"ba2859e1aa882eee"
],
[],
[],
[],
[],
[]
]
},
{
"id": "b2641f71595c1d2d",
"type": "link in",
"z": "46892ced77481340",
"g": "4b360c7d54e39e0a",
"name": "link in 5",
"links": [
"e059a9fd1da3c3fd"
],
"x": 665,
"y": 1000,
"wires": [
[
"53178ccb3f691dad"
]
]
},
{
"id": "b664207011dd548a",
"type": "subflow:57bd1b149526fcee",
"z": "46892ced77481340",
"g": "62cc8431c77a4797",
"name": "Shower",
"env": [
{
"name": "room_name",
"value": "l_bathroom",
"type": "str"
}
],
"x": 800,
"y": 760,
"wires": [
[
"5f7ffd82e5200d9a"
],
[
"f0bc3094d4af717e"
],
[],
[],
[],
[
"0a4414fc667405b4",
"22c73018f4564256"
]
]
},
{
"id": "39d435c6a32d4f09",
"type": "link in",
"z": "46892ced77481340",
"g": "62cc8431c77a4797",
"name": "link in 6",
"links": [
"e059a9fd1da3c3fd"
],
"x": 665,
"y": 760,
"wires": [
[
"b664207011dd548a"
]
]
},
{
"id": "1ee2b22951639d6b",
"type": "ha-binary-sensor",
"z": "46892ced77481340",
"g": "b88648a578b60cb8",
"name": "Living Room Main",
"entityConfig": "b43c6846b0baeeec",
"version": 0,
"state": "payload",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 470,
"y": 880,
"wires": [
[]
]
},
{
"id": "566e5b2ec261934f",
"type": "ha-binary-sensor",
"z": "46892ced77481340",
"g": "4a9361ba088ba046",
"name": "Dining Room Main",
"entityConfig": "f190a69cf72af140",
"version": 0,
"state": "payload",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 470,
"y": 720,
"wires": [
[]
]
},
{
"id": "5f7ffd82e5200d9a",
"type": "ha-binary-sensor",
"z": "46892ced77481340",
"g": "62cc8431c77a4797",
"name": "Main",
"entityConfig": "16560fc93e9523d4",
"version": 0,
"state": "payload",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1030,
"y": 720,
"wires": [
[]
]
},
{
"id": "ba2859e1aa882eee",
"type": "ha-binary-sensor",
"z": "46892ced77481340",
"g": "4b360c7d54e39e0a",
"name": "Main",
"entityConfig": "293fc06a888710c5",
"version": 0,
"state": "payload",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1030,
"y": 960,
"wires": [
[]
]
},
{
"id": "e8db33fc81400531",
"type": "ha-binary-sensor",
"z": "46892ced77481340",
"g": "0271d58953459100",
"name": "Kitchen Main",
"entityConfig": "be947f3b20336437",
"version": 0,
"state": "payload",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 990,
"y": 1140,
"wires": [
[]
]
},
{
"id": "e6e67dc471f2ecb3",
"type": "subflow:57bd1b149526fcee",
"z": "46892ced77481340",
"g": "2d6eb3ac6de382be",
"name": "Master Bathroom",
"env": [
{
"name": "room_name",
"value": "l_masterBathroom",
"type": "str"
}
],
"x": 1370,
"y": 920,
"wires": [
[
"29af11e532f234d4"
],
[],
[],
[],
[],
[]
]
},
{
"id": "fc5020edbd894baa",
"type": "link in",
"z": "46892ced77481340",
"g": "2d6eb3ac6de382be",
"name": "link in 7",
"links": [
"e059a9fd1da3c3fd"
],
"x": 1205,
"y": 920,
"wires": [
[
"e6e67dc471f2ecb3"
]
]
},
{
"id": "29af11e532f234d4",
"type": "ha-binary-sensor",
"z": "46892ced77481340",
"g": "2d6eb3ac6de382be",
"name": "Main",
"entityConfig": "edf39a33a28182ca",
"version": 0,
"state": "payload",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1570,
"y": 880,
"wires": [
[]
]
},
{
"id": "b7e6812909ef1051",
"type": "subflow:57bd1b149526fcee",
"z": "46892ced77481340",
"g": "af99b05ba44c6741",
"name": "Master Bedroom",
"env": [
{
"name": "room_name",
"value": "l_masterBedroom",
"type": "str"
}
],
"x": 1360,
"y": 760,
"wires": [
[
"280e6cc7a9de62b5"
],
[],
[],
[],
[],
[]
]
},
{
"id": "37cdfd56758051ef",
"type": "link in",
"z": "46892ced77481340",
"g": "af99b05ba44c6741",
"name": "link in 8",
"links": [
"e059a9fd1da3c3fd"
],
"x": 1205,
"y": 760,
"wires": [
[
"b7e6812909ef1051"
]
]
},
{
"id": "280e6cc7a9de62b5",
"type": "ha-binary-sensor",
"z": "46892ced77481340",
"g": "af99b05ba44c6741",
"name": "Main",
"entityConfig": "2b453fcb286e51f5",
"version": 0,
"state": "payload",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1570,
"y": 720,
"wires": [
[]
]
},
{
"id": "e0739e7f8c82e487",
"type": "ha-binary-sensor",
"z": "46892ced77481340",
"g": "0271d58953459100",
"name": "Kitchen Island",
"entityConfig": "9b99cd4af3bdb9a9",
"version": 0,
"state": "payload",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1000,
"y": 1200,
"wires": [
[]
]
},
{
"id": "1530556181903c3a",
"type": "ha-binary-sensor",
"z": "46892ced77481340",
"g": "0271d58953459100",
"name": "Fridge",
"entityConfig": "d75c31dd7a1edcbf",
"version": 0,
"state": "payload",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 970,
"y": 1260,
"wires": [
[]
]
},
{
"id": "e37aa132859c1ea8",
"type": "subflow:57bd1b149526fcee",
"z": "46892ced77481340",
"d": true,
"g": "f27a48975d61e376",
"name": "Bedroom",
"env": [
{
"name": "room_name",
"value": "l_bedroom_2",
"type": "str"
}
],
"x": 2420,
"y": 260,
"wires": [
[
"1a534f2c5be60889"
],
[],
[],
[],
[],
[]
]
},
{
"id": "d3f0c80e0188aabf",
"type": "link in",
"z": "46892ced77481340",
"g": "f27a48975d61e376",
"name": "link in 9",
"links": [
"e059a9fd1da3c3fd"
],
"x": 2285,
"y": 260,
"wires": [
[
"e37aa132859c1ea8"
]
]
},
{
"id": "1a534f2c5be60889",
"type": "ha-binary-sensor",
"z": "46892ced77481340",
"d": true,
"g": "f27a48975d61e376",
"name": "",
"entityConfig": "",
"version": 0,
"state": "payload",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 2640,
"y": 220,
"wires": [
[]
]
},
{
"id": "f0bc3094d4af717e",
"type": "ha-binary-sensor",
"z": "46892ced77481340",
"g": "62cc8431c77a4797",
"name": "Fan",
"entityConfig": "9b2dc1266b7513da",
"version": 0,
"state": "payload",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1030,
"y": 780,
"wires": [
[]
]
},
{
"id": "a024d8a903074aa4",
"type": "ha-button",
"z": "46892ced77481340",
"g": "2b9f0ac7a58d6e99",
"name": "Fan",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "ac2dba905819562f",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "bathroom",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_2",
"valueType": "str"
}
],
"x": 1110,
"y": 360,
"wires": [
[
"102d7d54a45e3f18"
]
]
},
{
"id": "07bae699fea75512",
"type": "ha-binary-sensor",
"z": "46892ced77481340",
"g": "3c7f8838aa2349b9",
"name": "Pantry",
"entityConfig": "c494e187e88c3208",
"version": 0,
"state": "payload",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1570,
"y": 1040,
"wires": [
[]
]
},
{
"id": "806720bc7ab2d4e8",
"type": "subflow:57bd1b149526fcee",
"z": "46892ced77481340",
"g": "3c7f8838aa2349b9",
"name": "Pantry",
"env": [
{
"name": "room_name",
"value": "l_pantry",
"type": "str"
}
],
"x": 1330,
"y": 1080,
"wires": [
[
"07bae699fea75512"
],
[],
[],
[],
[],
[]
]
},
{
"id": "3b5e1f4f9ccd9c74",
"type": "link in",
"z": "46892ced77481340",
"g": "3c7f8838aa2349b9",
"name": "link in 10",
"links": [
"e059a9fd1da3c3fd"
],
"x": 1205,
"y": 1080,
"wires": [
[
"806720bc7ab2d4e8"
]
]
},
{
"id": "9672723b593ef966",
"type": "debug",
"z": "46892ced77481340",
"name": "debug 1",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1340,
"y": 40,
"wires": []
},
{
"id": "3ec8968914e324f5",
"type": "subflow:57bd1b149526fcee",
"z": "46892ced77481340",
"g": "0b0b27deacee2bfc",
"name": "Bedroom",
"env": [
{
"name": "room_name",
"value": "l_outSide",
"type": "str"
}
],
"x": 240,
"y": 1240,
"wires": [
[
"197fc35230069190"
],
[],
[],
[],
[],
[]
]
},
{
"id": "2b29c71c180a50df",
"type": "link in",
"z": "46892ced77481340",
"g": "0b0b27deacee2bfc",
"name": "link in 11",
"links": [
"e059a9fd1da3c3fd"
],
"x": 105,
"y": 1240,
"wires": [
[
"3ec8968914e324f5"
]
]
},
{
"id": "197fc35230069190",
"type": "ha-binary-sensor",
"z": "46892ced77481340",
"g": "0b0b27deacee2bfc",
"name": "Veranda BBQ Light",
"entityConfig": "1a22f89094ea7b38",
"version": 0,
"state": "payload",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 470,
"y": 1200,
"wires": [
[]
]
},
{
"id": "a8ac75d5944a28b9",
"type": "ha-button",
"z": "46892ced77481340",
"g": "639e1c2545c2de96",
"name": "Baby Bedroom",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "8b4d5408fdcd8c0d",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "bedroom_2",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_1",
"valueType": "str"
}
],
"x": 460,
"y": 540,
"wires": [
[
"f11fa2bedfc41e41"
]
]
},
{
"id": "f11fa2bedfc41e41",
"type": "link out",
"z": "46892ced77481340",
"g": "639e1c2545c2de96",
"name": "link out 14",
"mode": "link",
"links": [
"0bbcb269da9b75c7"
],
"x": 605,
"y": 540,
"wires": []
},
{
"id": "f785dab1a0f37204",
"type": "comment",
"z": "46892ced77481340",
"name": "",
"info": "VAR_GLOBAL\n\tmasterBedroom \t:\tstruct_switches;\n\tmasterBathroom\t:\tstruct_switches;\n\tbedroom_1\t\t:\tstruct_switches;\n\tbedroom_2\t\t:\tstruct_switches;\n\tbathroom\t\t:\tstruct_switches;\n\thallway\t\t\t:\tstruct_switches;\n\tpantry\t\t\t:\tstruct_switches;\n\tkitchen\t\t\t:\tstruct_switches;\n\tlivingRoom\t\t:\tstruct_switches;\n\tdinningRoom\t\t:\tstruct_switches;\n\tentrance\t\t:\tstruct_switches;\n\tguestWc\t\t\t:\tstruct_switches;\n\toutVeranda\t\t:\tstruct_switches;\n\toutFront\t\t:\tstruct_switches;\n\toutSide\t\t\t:\tstruct_switches;\n\toutBack\t\t\t:\tstruct_switches;\nEND_VAR\n\nTYPE struct_switches :\nSTRUCT\n\tall_off:BOOL;\n\tall_on:BOOL;\t\n\tsw_1:BOOL;\n\tsw_2:BOOL;\n\tsw_3:BOOL;\n\tsw_4:BOOL;\n\tsw_5:BOOL;\n\tsw_6:BOOL;\t\nEND_STRUCT\nEND_TYPE",
"x": 1560,
"y": 40,
"wires": []
},
{
"id": "b4e49387d80fa951",
"type": "subflow:57bd1b149526fcee",
"z": "46892ced77481340",
"g": "bd16cebc90c528e9",
"name": "Out",
"env": [
{
"name": "room_name",
"value": "l_outVeranda",
"type": "str"
}
],
"x": 2110,
"y": 480,
"wires": [
[
"2ae3fedce613ecfe",
"d1c2e1ee1fba88c6"
],
[],
[],
[],
[],
[]
]
},
{
"id": "860779317fad91b5",
"type": "link in",
"z": "46892ced77481340",
"g": "bd16cebc90c528e9",
"name": "link in 12",
"links": [
"e059a9fd1da3c3fd"
],
"x": 1985,
"y": 480,
"wires": [
[
"b4e49387d80fa951",
"1a8d95afd537e151"
]
]
},
{
"id": "2ae3fedce613ecfe",
"type": "ha-binary-sensor",
"z": "46892ced77481340",
"g": "bd16cebc90c528e9",
"name": "Front Lights",
"entityConfig": "fe79cfd2fda112db",
"version": 0,
"state": "payload",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 2330,
"y": 440,
"wires": [
[]
]
},
{
"id": "66255b06a0d4a4c9",
"type": "ha-button",
"z": "46892ced77481340",
"g": "507ca4f1b82ad9c2",
"name": "Front Lights",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "311d801ad1f1bc0f",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "outVeranda",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_1",
"valueType": "str"
}
],
"x": 2050,
"y": 600,
"wires": [
[
"9c99ecea6e4aefd8"
]
]
},
{
"id": "9c99ecea6e4aefd8",
"type": "link out",
"z": "46892ced77481340",
"g": "507ca4f1b82ad9c2",
"name": "link out 20",
"mode": "link",
"links": [
"0bbcb269da9b75c7"
],
"x": 2205,
"y": 600,
"wires": []
},
{
"id": "f48d2c10e183fb95",
"type": "debug",
"z": "46892ced77481340",
"name": "debug 15",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 600,
"y": 80,
"wires": []
},
{
"id": "438b13c5cdbb5f1c",
"type": "debug",
"z": "46892ced77481340",
"name": "debug 16",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 380,
"y": 100,
"wires": []
},
{
"id": "d680ff6c7ac109cf",
"type": "ha-button",
"z": "46892ced77481340",
"g": "2b9f0ac7a58d6e99",
"name": "Water Boiler",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "0c9a4c8d912d0a38",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "bathroom",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_6",
"valueType": "str"
}
],
"x": 1130,
"y": 420,
"wires": [
[
"102d7d54a45e3f18",
"9dc26f31e8b58f14"
]
]
},
{
"id": "0a4414fc667405b4",
"type": "ha-binary-sensor",
"z": "46892ced77481340",
"g": "62cc8431c77a4797",
"name": "Water_boiler",
"entityConfig": "8166d41aaab8a32a",
"version": 0,
"state": "payload",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1010,
"y": 840,
"wires": [
[]
]
},
{
"id": "9dc26f31e8b58f14",
"type": "debug",
"z": "46892ced77481340",
"g": "2b9f0ac7a58d6e99",
"name": "debug 29",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1330,
"y": 440,
"wires": []
},
{
"id": "1a8d95afd537e151",
"type": "debug",
"z": "46892ced77481340",
"g": "bd16cebc90c528e9",
"name": "debug 31",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 2090,
"y": 360,
"wires": []
},
{
"id": "d1c2e1ee1fba88c6",
"type": "debug",
"z": "46892ced77481340",
"g": "bd16cebc90c528e9",
"name": "debug 32",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 2250,
"y": 400,
"wires": []
},
{
"id": "e4d5c7b8295b4251",
"type": "debug",
"z": "46892ced77481340",
"name": "debug 27",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 120,
"y": 100,
"wires": []
},
{
"id": "22c73018f4564256",
"type": "debug",
"z": "46892ced77481340",
"g": "62cc8431c77a4797",
"name": "debug 34",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 980,
"y": 900,
"wires": []
},
{
"id": "1f3ba1a73e155da9",
"type": "ha-button",
"z": "46892ced77481340",
"g": "3cc3b21e7b1f7b13",
"name": "Entrance Mirror",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "c1b8d65524acbab3",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "dinningRoom",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_3",
"valueType": "str"
}
],
"x": 800,
"y": 260,
"wires": [
[
"04e183fcfe9e9f6d"
]
]
},
{
"id": "89762968e1556a42",
"type": "ha-binary-sensor",
"z": "46892ced77481340",
"g": "4a9361ba088ba046",
"name": "Entrance Miror",
"entityConfig": "72e9fc1709b9891c",
"version": 0,
"state": "payload",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 460,
"y": 780,
"wires": [
[]
]
},
{
"id": "6190a90971a43aba",
"type": "ha-button",
"z": "46892ced77481340",
"g": "3cc3b21e7b1f7b13",
"name": "Entrance Light in",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "121b1dead369ae82",
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "entrance",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_1",
"valueType": "str"
}
],
"x": 800,
"y": 320,
"wires": [
[
"04e183fcfe9e9f6d"
]
]
},
{
"id": "5351a670ea3bcf15",
"type": "subflow:57bd1b149526fcee",
"z": "46892ced77481340",
"g": "9da6393897881dca",
"name": "Entrance",
"env": [
{
"name": "room_name",
"value": "l_entrance",
"type": "str"
}
],
"x": 1940,
"y": 920,
"wires": [
[
"9b4f318fa5f438aa"
],
[],
[],
[],
[],
[]
]
},
{
"id": "8dd17125d6bb49f7",
"type": "link in",
"z": "46892ced77481340",
"g": "9da6393897881dca",
"name": "link in 13",
"links": [
"e059a9fd1da3c3fd"
],
"x": 1805,
"y": 920,
"wires": [
[
"5351a670ea3bcf15"
]
]
},
{
"id": "9b4f318fa5f438aa",
"type": "ha-binary-sensor",
"z": "46892ced77481340",
"g": "9da6393897881dca",
"name": "Entrance Light In",
"entityConfig": "395ea43be3b0e20c",
"version": 0,
"state": "payload",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 2170,
"y": 880,
"wires": [
[]
]
},
{
"id": "61d0351b6a2d43cc",
"type": "link in",
"z": "46892ced77481340",
"name": "to UDP",
"links": [],
"x": 285,
"y": 20,
"wires": [
[
"040e9ff14df4a326"
]
]
},
{
"id": "4045239f675b77d2",
"type": "function",
"z": "7de41d810b04d992",
"name": "HA to NVL",
"func": "// Writes to state.rooms.<roomKey>. Room from entity_id via global roomConfig.entityToRoom. See /root/.node-red/room-config.js.\nconst entityId = (msg.topic || '').toString();\nconst config = global.get('roomConfig');\nconst entityToRoom = (config && config.entityToRoom) ? config.entityToRoom : { open_plan_living_room_main: 'open_plan_living_room' };\n// Parse entity_id e.g. input_boolean.open_plan_living_room_main_1 → base \"open_plan_living_room_main_1\", then room + light\nconst base = (entityId.split('.')[1] || '').replace(/\\s/g, '');\nconst numMatch = base.match(/_(\\d+)$/);\nconst lightNum = (numMatch && parseInt(numMatch[1], 10) >= 1) ? Math.min(6, parseInt(numMatch[1], 10)) : 1;\nconst baseWithoutNum = base.replace(/_?\\d+$/, '') || base;\nconst ROOM_NAME = entityToRoom[baseWithoutNum] || entityToRoom[base] || 'open_plan_living_room';\n\n// Normalize state: HA / trigger-state can send payload as string, object with .state, or data.new_state.state\nlet rawState = msg.payload;\nif (rawState !== null && typeof rawState === 'object' && rawState.state !== undefined) rawState = rawState.state;\nif (msg.data && msg.data.new_state && msg.data.new_state.state !== undefined) rawState = msg.data.new_state.state;\nconst isOn = (rawState === 'on' || rawState === true);\n\nnode.warn('[HA to NVL] topic=' + entityId + ' rawState=' + JSON.stringify(rawState) + ' → lightNum=' + lightNum + ' isOn=' + isOn);\n\nif (!flow.get('nvlInState')) flow.set('nvlInState', { rooms: {}, boiler: {} });\nconst state = flow.get('nvlInState');\nif (!state.rooms[ROOM_NAME]) state.rooms[ROOM_NAME] = {};\nconst r = state.rooms[ROOM_NAME];\nr['ha_l' + lightNum + '_on'] = false;\nr['ha_l' + lightNum + '_off'] = false;\nif (isOn) r['ha_l' + lightNum + '_on'] = true;\nelse r['ha_l' + lightNum + '_off'] = true;\nflow.set('nvlInState', state);\n\nnode.warn('[HA to NVL] set ' + ROOM_NAME + ' ha_l' + lightNum + '_' + (isOn ? 'on' : 'off') + '=true, buildAndSend');\n\n// PLC uses R_TRIG (rising edge). If \"off\" still doesnt work, add a flow: after this node, 80ms delay then clear ha_l*_off and buildAndSend again (pulse).\nmsg.payload = { buildAndSend: true };\nreturn msg;\n",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1170,
"y": 320,
"wires": [
[
"75212a4bc3d085db"
]
]
},
{
"id": "718ba68ae647874f",
"type": "function",
"z": "7de41d810b04d992",
"name": "Zigbee to NVL",
"func": "// Each button maps to (room, light) via global roomConfig.switchBindings. See /root/.node-red/room-config.js.\n// Supports single-device payload (action, friendly_name at top level) and multi-device payload (keyed by IEEE address).\nconst actionToSwitch = { single: 1, double: 2, hold: 3, release: 4, triple: 5, quad: 6 };\nconst config = global.get('roomConfig');\nconst switchBindings = (config && config.switchBindings) ? config.switchBindings : {};\nconst deviceToRoom = (config && config.deviceToRoom) ? config.deviceToRoom : { 'Office Switch': 'open_plan_living_room' };\n// Optional: map IEEE address to friendly name when multi-device node doesn't provide it. e.g. deviceIdToName: { '0xa4c138a5b9771b05': 'Office Switch' }\nconst deviceIdToName = (config && config.deviceIdToName) ? config.deviceIdToName : {};\n\nconst payload = msg.payload != null ? msg.payload : {};\n// Payload can be: single-device { action, friendly_name }, multi-device { \"0x...\": { ... } }, or plain action string \"1_single\"\nlet friendlyName = (typeof payload === 'object' && payload.friendly_name != null) ? payload.friendly_name.toString() : '';\nlet actionRaw = (typeof payload === 'string' ? payload : (payload.action || payload.click || msg.action || (payload && payload.action)) || '').toString().toLowerCase();\n\n// Multi-device payload: prefer the device that has an action AND a configured binding (so we don't pick another device's stale action)\nif (!actionRaw && typeof payload === 'object' && !Array.isArray(payload)) {\n const keys = Object.keys(payload);\n let fallback = null;\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n const v = payload[key];\n if (key && key.toLowerCase().indexOf('0x') === 0 && v && typeof v === 'object') {\n const inner = v.payload || v.message || v.state || v;\n const a = (inner.action || inner.click || v.action || v.click || '').toString().toLowerCase();\n if (!a) continue;\n const name = (v.friendly_name || v.name || (v.item && (v.item.friendly_name || v.item.name)) || deviceIdToName[key] || key).toString();\n if (switchBindings[name] || deviceToRoom[name]) {\n actionRaw = a;\n friendlyName = name;\n break;\n }\n if (!fallback) fallback = { actionRaw: a, friendlyName: name };\n }\n }\n if (!actionRaw && fallback) {\n actionRaw = fallback.actionRaw;\n friendlyName = fallback.friendlyName;\n }\n}\n// If still no action, try msg.data or msg.topic (some nodes put action in topic, e.g. \"1_single\")\nif (!actionRaw && msg.data && msg.data.action) actionRaw = msg.data.action.toString().toLowerCase();\nif (!actionRaw && typeof msg.topic === 'string' && /^\\d_[a-z_]+$/.test(msg.topic.trim())) actionRaw = msg.topic.trim().toLowerCase();\n// If payload was the action string, get friendly_name from topic e.g. zigbee2mqtt/Office Switch/action\nif (actionRaw && !friendlyName && typeof msg.topic === 'string') {\n const parts = msg.topic.split('/');\n if (parts.length >= 2) friendlyName = parts[1].trim(); // zigbee2mqtt/Office Switch/action → Office Switch\n}\n\nif (!actionRaw) {\n node.warn('[Zigbee to NVL] no action in payload. Keys: ' + (typeof payload === 'object' ? Object.keys(payload).join(', ') : 'n/a'));\n return null;\n}\n\nconst parts = actionRaw.split('_');\nlet buttonIndex = null;\nif (parts.length >= 2) {\n const n = parseInt(parts[0], 10);\n if (n >= 1 && n <= 6) buttonIndex = n;\n}\nif (buttonIndex == null) buttonIndex = actionToSwitch[actionRaw];\nif (buttonIndex == null && parts.length >= 2) buttonIndex = actionToSwitch[parts.slice(1).join('_')];\nif (buttonIndex == null) buttonIndex = actionToSwitch[parts[parts.length - 1]];\n\nif (buttonIndex == null) {\n node.warn('[Zigbee to NVL] unknown action: ' + JSON.stringify(actionRaw));\n return null;\n}\n\nnode.warn('[Zigbee to NVL] action=' + actionRaw + ' buttonIndex=' + buttonIndex + ' device=' + friendlyName);\n\n// Prefer switchBindings by friendly name; fallback by device ID (IEEE) if we have switchBindingsByDeviceId\nconst bindingByDeviceId = (config && config.switchBindingsByDeviceId) ? config.switchBindingsByDeviceId : null;\nlet targets = [];\nlet binding = switchBindings[friendlyName] && switchBindings[friendlyName][buttonIndex];\nif ((binding === undefined || binding === null) && bindingByDeviceId) {\n const deviceId = typeof payload === 'object' && Object.keys(payload).some(function (k) { return k.indexOf('0x') === 0; })\n ? Object.keys(payload).find(function (k) { return k.indexOf('0x') === 0; })\n : null;\n if (deviceId) binding = bindingByDeviceId[deviceId] && bindingByDeviceId[deviceId][buttonIndex];\n}\nif (binding !== undefined && binding !== null) {\n targets = Array.isArray(binding) ? binding : [binding];\n targets = targets.filter(function (t) { return t && t.room && t.light >= 1 && t.light <= 6; });\n}\nif (targets.length === 0) {\n const room = deviceToRoom[friendlyName] || 'open_plan_living_room';\n targets = [{ room: room, light: buttonIndex }];\n}\n\nif (!flow.get('nvlInState')) flow.set('nvlInState', { rooms: {}, boiler: {} });\nconst state = flow.get('nvlInState');\nconst clearList = [];\n\nfor (const t of targets) {\n const key = 'zigbee_sw' + t.light;\n if (!state.rooms[t.room]) state.rooms[t.room] = {};\n state.rooms[t.room][key] = true;\n clearList.push({ room: t.room, key: key });\n}\n\nflow.set('nvlInState', state);\n\nnode.warn('[Zigbee to NVL] ' + (friendlyName || 'device') + ' btn' + buttonIndex + ' → ' + targets.map(function (t) { return t.room + ' L' + t.light; }).join(', '));\n\nmsg.payload = { buildAndSend: true };\nmsg.zigbeeClear = clearList;\nreturn msg;\n",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1160,
"y": 380,
"wires": [
[
"886c1334e909e2cd",
"75212a4bc3d085db"
]
]
},
{
"id": "886c1334e909e2cd",
"type": "delay",
"z": "7de41d810b04d992",
"name": "80ms",
"pauseType": "delay",
"timeout": "80",
"timeoutUnits": "milliseconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "seconds",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": true,
"outputs": 1,
"x": 1350,
"y": 380,
"wires": [
[
"44822e048dbaee31"
]
]
},
{
"id": "44822e048dbaee31",
"type": "function",
"z": "7de41d810b04d992",
"name": "Clear zigbee edge",
"func": "// Paste into the \"Clear zigbee edge\" Function node (after 80 ms delay).\n// Clears zigbee_swN in nvlInState so the PLC sees one pulse. Supports one room or many (switchBindings).\n// msg.zigbeeClear can be: { room, key } or [ { room, key }, ... ]\n\nif (msg.zigbeeClear) {\n const state = flow.get('nvlInState') || { rooms: {}, boiler: {} };\n const list = Array.isArray(msg.zigbeeClear) ? msg.zigbeeClear : [msg.zigbeeClear];\n for (const item of list) {\n const r = state.rooms[item.room];\n if (r && item.key) r[item.key] = false;\n }\n flow.set('nvlInState', state);\n}\nmsg.payload = { buildAndSend: true };\nreturn msg;\n",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1550,
"y": 380,
"wires": [
[
"75212a4bc3d085db"
]
]
},
{
"id": "17814d6d1beda546",
"type": "zigbee2mqtt-in",
"z": "7de41d810b04d992",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "2 selected",
"device_id": [
"0xa4c138a5b9771b05",
"0xa4c138112a12d55f"
],
"state": null,
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": true,
"x": 680,
"y": 380,
"wires": [
[
"718ba68ae647874f",
"2edb29caf874a91e"
]
]
},
{
"id": "74c2640db1c8bd3e",
"type": "link out",
"z": "7de41d810b04d992",
"name": "link out 26",
"mode": "link",
"links": [
"c6162cb59e21491f"
],
"x": 1570,
"y": 320,
"wires": [],
"l": true
},
{
"id": "95b626ea6980446e",
"type": "trigger-state",
"z": "7de41d810b04d992",
"name": "",
"server": "29eb84a2708d96e0",
"version": 5,
"inputs": 1,
"outputs": 2,
"exposeAsEntityConfig": "",
"entities": {
"entity": [
"input_boolean.open_plan_living_room_main_1"
],
"substring": [],
"regex": []
},
"debugEnabled": true,
"constraints": [],
"customOutputs": [],
"outputInitially": false,
"stateType": "str",
"enableInput": true,
"x": 830,
"y": 320,
"wires": [
[
"4045239f675b77d2"
],
[]
]
},
{
"id": "75212a4bc3d085db",
"type": "function",
"z": "7de41d810b04d992",
"name": "STATE TO NVL",
"func": "// Build the payload for nvl-send from flow.nvlInState.\n// Room list comes from global roomConfig (single source of truth). See /root/.node-red/room-config.js.\n// Wire: HA to NVL / Zigbee to NVL → this function → nvl-send → udp out\n\nconst struct_room_cmds_default = {\n ha_l1_on: false, ha_l1_off: false, ha_l2_on: false, ha_l2_off: false,\n ha_l3_on: false, ha_l3_off: false, ha_l4_on: false, ha_l4_off: false,\n ha_l5_on: false, ha_l5_off: false, ha_l6_on: false, ha_l6_off: false,\n zigbee_sw1: false, zigbee_sw2: false, zigbee_sw3: false,\n zigbee_sw4: false, zigbee_sw5: false, zigbee_sw6: false,\n ha_all_on: false, ha_all_off: false\n};\n\nconst config = global.get('roomConfig');\nconst roomNames = (config && config.roomNames && config.roomNames.length) ? config.roomNames : ['open_plan_living_room'];\n\nconst state = flow.get('nvlInState') || { rooms: {}, boiler: {} };\nconst rooms = state.rooms || {};\nconst payload = {};\n\nfor (const name of roomNames) {\n const cmd = rooms[name] || {};\n payload[name] = { ...struct_room_cmds_default };\n for (const k of Object.keys(struct_room_cmds_default)) {\n if (cmd[k] !== undefined) payload[name][k] = !!cmd[k];\n }\n}\n\nmsg.payload = payload;\nreturn msg;\n",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1380,
"y": 320,
"wires": [
[
"74c2640db1c8bd3e",
"561398f1884392c1"
]
]
},
{
"id": "d5cdc38171230744",
"type": "function",
"z": "7de41d810b04d992",
"name": "NVL to HA Sync",
"func": "// Run this AFTER nvl-receive. Syncs all mapped lights from PLC state to HA entities.\n// Map comes from global roomConfig (single source of truth). See /root/.node-red/room-config.js.\n// Connect output 1 → Action node (turn_on), output 2 → Action node (turn_off).\n\nconst config = global.get('roomConfig');\nconst LIGHT_ENTITY_MAP = (config && config.lightEntityMap && config.lightEntityMap.length) ? config.lightEntityMap : [\n { room: 'l_open_plan_living_room', light: 1, entityId: 'input_boolean.open_plan_living_room_main_1' },\n];\n\nconst payload = msg.payload || {};\nconst onMsgs = [];\nconst offMsgs = [];\n\nfor (const entry of LIGHT_ENTITY_MAP) {\n const room = payload[entry.room] || {};\n const isOn = !!(room['l_' + entry.light] || room['l' + entry.light]);\n\n const flowKey = 'nvlToHa_' + entry.entityId.replace(/\\./g, '_');\n const last = flow.get(flowKey);\n if (last === isOn) continue;\n flow.set(flowKey, isOn);\n\n const domain = entry.entityId.split('.')[0] || 'input_boolean';\n const action = domain + '.' + (isOn ? 'turn_on' : 'turn_off');\n const out = { payload: { action: action, target: { entity_id: [entry.entityId] } } };\n if (isOn) onMsgs.push(out); else offMsgs.push(out);\n}\n\nif (onMsgs.length === 0 && offMsgs.length === 0) return null;\nreturn [onMsgs, offMsgs];\n",
"outputs": 2,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1240,
"y": 220,
"wires": [
[
"566f142b2e6e841f"
],
[
"5789f9ce23be8782"
]
]
},
{
"id": "7c4268195123e319",
"type": "link in",
"z": "7de41d810b04d992",
"name": "link in 14",
"links": [
"e059a9fd1da3c3fd"
],
"x": 1015,
"y": 220,
"wires": [
[
"d5cdc38171230744"
]
]
},
{
"id": "566f142b2e6e841f",
"type": "api-call-service",
"z": "7de41d810b04d992",
"name": "",
"server": "29eb84a2708d96e0",
"version": 7,
"debugenabled": false,
"action": "input_boolean.turn_on",
"floorId": [],
"areaId": [],
"deviceId": [],
"entityId": [
"input_boolean.living_room_new"
],
"labelId": [],
"data": "",
"dataType": "jsonata",
"mergeContext": "",
"mustacheAltTags": false,
"outputProperties": [],
"queue": "none",
"blockInputOverrides": false,
"domain": "input_boolean",
"service": "turn_on",
"x": 1540,
"y": 200,
"wires": [
[]
]
},
{
"id": "5789f9ce23be8782",
"type": "api-call-service",
"z": "7de41d810b04d992",
"name": "",
"server": "29eb84a2708d96e0",
"version": 7,
"debugenabled": false,
"action": "input_boolean.turn_off",
"floorId": [],
"areaId": [],
"deviceId": [],
"entityId": [
"input_boolean.living_room_new"
],
"labelId": [],
"data": "",
"dataType": "jsonata",
"mergeContext": "",
"mustacheAltTags": false,
"outputProperties": [],
"queue": "none",
"blockInputOverrides": false,
"domain": "input_boolean",
"service": "turn_off",
"x": 1540,
"y": 260,
"wires": [
[]
]
},
{
"id": "3b1ea5253e0fbf22",
"type": "function",
"z": "7de41d810b04d992",
"d": true,
"name": "HA to NVL",
"func": "// Writes to state.rooms.cmd_livingroom (NVL variable cmd_livingroom).\nconst ROOM_NAME = 'cmd_livingroom';\nconst entityId = (msg.topic || '').toString();\nconst parts = entityId.split('_');\nconst last = parts[parts.length - 1] || '';\nconst num = parseInt(last, 10);\nconst lightNum = (!isNaN(num) && num >= 1) ? Math.min(6, num) : 1;\n\n// Normalize state: HA / trigger-state can send payload as string, object with .state, or data.new_state.state\nlet rawState = msg.payload;\nif (rawState !== null && typeof rawState === 'object' && rawState.state !== undefined) rawState = rawState.state;\nif (msg.data && msg.data.new_state && msg.data.new_state.state !== undefined) rawState = msg.data.new_state.state;\nconst isOn = (rawState === 'on' || rawState === true);\n\nnode.warn('[HA to NVL] topic=' + entityId + ' rawState=' + JSON.stringify(rawState) + ' → lightNum=' + lightNum + ' isOn=' + isOn);\n\nif (!flow.get('nvlInState')) flow.set('nvlInState', { rooms: {}, boiler: {} });\nconst state = flow.get('nvlInState');\nif (!state.rooms[ROOM_NAME]) state.rooms[ROOM_NAME] = {};\nconst r = state.rooms[ROOM_NAME];\nr['ha_l' + lightNum + '_on'] = false;\nr['ha_l' + lightNum + '_off'] = false;\nif (isOn) r['ha_l' + lightNum + '_on'] = true;\nelse r['ha_l' + lightNum + '_off'] = true;\nflow.set('nvlInState', state);\n\nnode.warn('[HA to NVL] set cmd_livingroom ha_l' + lightNum + '_' + (isOn ? 'on' : 'off') + '=true, buildAndSend');\n\n// PLC uses R_TRIG (rising edge). If \"off\" still doesnt work, add a flow: after this node, 80ms delay then clear ha_l*_off and buildAndSend again (pulse).\nmsg.payload = { buildAndSend: true };\nreturn msg;\n",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1130,
"y": 740,
"wires": [
[
"3e962e16c44a4b8a"
]
]
},
{
"id": "1957eb3666681641",
"type": "function",
"z": "7de41d810b04d992",
"d": true,
"name": "Zigbee to NVL",
"func": "// Writes to state.rooms.cmd_livingroom (same as HA to NVL). Zigbee action → zigbee_sw1..6.\nconst ROOM_NAME = 'cmd_livingroom';\nconst actionToSwitch = { single: 1, double: 2, hold: 3, release: 4, triple: 5, quad: 6 };\nconst payload = msg.payload || {};\nconst actionRaw = (payload.action || payload.click || '').toLowerCase();\n// Support \"1_single\", \"2_double\" etc. (button_number + action) or plain \"single\", \"double\"\nconst parts = actionRaw.split('_');\nlet swIndex = null;\nif (parts.length >= 2) {\n const buttonNum = parseInt(parts[0], 10);\n if (buttonNum >= 1 && buttonNum <= 6) swIndex = buttonNum;\n}\nif (swIndex == null) swIndex = actionToSwitch[actionRaw];\nif (swIndex == null && parts.length >= 2) swIndex = actionToSwitch[parts.slice(1).join('_')];\nif (swIndex == null) swIndex = actionToSwitch[parts[parts.length - 1]];\n\nif (swIndex == null) {\n node.warn('[Zigbee to NVL] unknown action: ' + JSON.stringify(actionRaw) + ' payload=' + JSON.stringify(payload));\n return null;\n}\n\nif (!flow.get('nvlInState')) flow.set('nvlInState', { rooms: {}, boiler: {} });\nconst state = flow.get('nvlInState');\nif (!state.rooms[ROOM_NAME]) state.rooms[ROOM_NAME] = {};\nstate.rooms[ROOM_NAME]['zigbee_sw' + swIndex] = true;\nflow.set('nvlInState', state);\n\nnode.warn('[Zigbee to NVL] cmd_livingroom zigbee_sw' + swIndex + '=true (action=' + actionRaw + '), buildAndSend + zigbeeClear');\n\nmsg.payload = { buildAndSend: true };\nmsg.zigbeeClear = { room: ROOM_NAME, key: 'zigbee_sw' + swIndex };\nreturn msg;\n",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1120,
"y": 800,
"wires": [
[
"30fab57c9aad15eb",
"3e962e16c44a4b8a"
]
]
},
{
"id": "30fab57c9aad15eb",
"type": "delay",
"z": "7de41d810b04d992",
"d": true,
"name": "80ms",
"pauseType": "delay",
"timeout": "80",
"timeoutUnits": "milliseconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "seconds",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": true,
"outputs": 1,
"x": 1310,
"y": 800,
"wires": [
[
"ef18cce9c468177c"
]
]
},
{
"id": "ef18cce9c468177c",
"type": "function",
"z": "7de41d810b04d992",
"d": true,
"name": "Clear zigbee edge",
"func": "if (msg.zigbeeClear) {\n const state = flow.get('nvlInState') || { rooms: {}, boiler: {} };\n const r = state.rooms[msg.zigbeeClear.room];\n if (r) r[msg.zigbeeClear.key] = false;\n flow.set('nvlInState', state);\n}\nmsg.payload = { buildAndSend: true };\nreturn msg;",
"outputs": 1,
"x": 1510,
"y": 800,
"wires": [
[
"3e962e16c44a4b8a"
]
]
},
{
"id": "79c6501879706e27",
"type": "zigbee2mqtt-in",
"z": "7de41d810b04d992",
"d": true,
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Office Switch (TS0042)",
"device_id": "0xa4c138a5b9771b05",
"state": "0",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 900,
"y": 800,
"wires": [
[
"1957eb3666681641"
]
]
},
{
"id": "bcf5055c45c97cc3",
"type": "link out",
"z": "7de41d810b04d992",
"d": true,
"name": "link out 27",
"mode": "link",
"links": [
"c6162cb59e21491f"
],
"x": 1530,
"y": 740,
"wires": [],
"l": true
},
{
"id": "96ed40d44eeab413",
"type": "trigger-state",
"z": "7de41d810b04d992",
"d": true,
"name": "",
"server": "29eb84a2708d96e0",
"version": 5,
"inputs": 1,
"outputs": 2,
"exposeAsEntityConfig": "",
"entities": {
"entity": [
"input_boolean.living_room_new"
],
"substring": [],
"regex": []
},
"debugEnabled": true,
"constraints": [],
"customOutputs": [],
"outputInitially": false,
"stateType": "str",
"enableInput": true,
"x": 850,
"y": 740,
"wires": [
[
"3b1ea5253e0fbf22"
],
[]
]
},
{
"id": "3e962e16c44a4b8a",
"type": "function",
"z": "7de41d810b04d992",
"d": true,
"name": "NVL SEND",
"func": "// Build the payload for nvl-send from flow.nvlInState.\n// Redesign: all rooms use struct_room_cmds. Add more names to roomNames when you add rooms.\n// Wire: HA to NVL / Zigbee to NVL → this function → nvl-send → udp out\n\nconst struct_room_cmds_default = {\n ha_l1_on: false, ha_l1_off: false, ha_l2_on: false, ha_l2_off: false,\n ha_l3_on: false, ha_l3_off: false, ha_l4_on: false, ha_l4_off: false,\n ha_l5_on: false, ha_l5_off: false, ha_l6_on: false, ha_l6_off: false,\n zigbee_sw1: false, zigbee_sw2: false, zigbee_sw3: false,\n zigbee_sw4: false, zigbee_sw5: false, zigbee_sw6: false,\n ha_all_on: false, ha_all_off: false\n};\n\n// NVL variable names per room (struct_room_cmds). Add more when you add rooms.\nconst roomNames = ['open_plan_living_room'];\n\nconst state = flow.get('nvlInState') || { rooms: {}, boiler: {} };\nconst rooms = state.rooms || {};\nconst payload = {};\n\nfor (const name of roomNames) {\n const cmd = rooms[name] || {};\n payload[name] = { ...struct_room_cmds_default };\n for (const k of Object.keys(struct_room_cmds_default)) {\n if (cmd[k] !== undefined) payload[name][k] = !!cmd[k];\n }\n}\n\nmsg.payload = payload;\nreturn msg;\n",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1330,
"y": 740,
"wires": [
[
"bcf5055c45c97cc3"
]
]
},
{
"id": "747c5e9bf3763dac",
"type": "function",
"z": "7de41d810b04d992",
"d": true,
"name": "NVL to HA Sync",
"func": "// Run this AFTER nvl-receive. Syncs all mapped lights from PLC state to HA entities.\n// Connect output 1 → api-call-service (input_boolean.turn_on / light.turn_on), output 2 → api-call-service (turn_off).\n// Only outputs when state changed (per entity). Add more entries to LIGHT_ENTITY_MAP as you add rooms/lights.\n\n// Map: NVL room key (in payload) + light index 1..6 → HA entity_id\nconst LIGHT_ENTITY_MAP = [\n { room: 'l_open_plan_living_room', light: 1, entityId: 'input_boolean.open_plan_living_room_main_1' },\n // { room: 'l_open_plan_living_room', light: 2, entityId: 'input_boolean.open_plan_living_room_spots_1' },\n // { room: 'l_kitchen_kitchen', light: 1, entityId: 'input_boolean.kitchen_kitchen_main_1' },\n];\n\nconst payload = msg.payload || {};\nconst onMsgs = [];\nconst offMsgs = [];\n\nfor (const entry of LIGHT_ENTITY_MAP) {\n const room = payload[entry.room] || {};\n const isOn = !!(room['l_' + entry.light] || room['l' + entry.light]);\n\n const flowKey = 'nvlToHa_' + entry.entityId.replace(/\\./g, '_');\n const last = flow.get(flowKey);\n if (last === isOn) continue;\n flow.set(flowKey, isOn);\n\n const out = { payload: { entity_id: entry.entityId } };\n if (isOn) onMsgs.push(out); else offMsgs.push(out);\n}\n\nif (onMsgs.length === 0 && offMsgs.length === 0) return null;\nreturn [onMsgs, offMsgs];\n",
"outputs": 2,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1200,
"y": 640,
"wires": [
[
"320ececfad817f94"
],
[
"577d462afbb43835"
]
]
},
{
"id": "032f98ab9d5085b8",
"type": "link in",
"z": "7de41d810b04d992",
"d": true,
"name": "link in 15",
"links": [
"e059a9fd1da3c3fd"
],
"x": 975,
"y": 640,
"wires": [
[
"747c5e9bf3763dac"
]
]
},
{
"id": "320ececfad817f94",
"type": "api-call-service",
"z": "7de41d810b04d992",
"d": true,
"name": "",
"server": "29eb84a2708d96e0",
"version": 7,
"debugenabled": false,
"action": "input_boolean.turn_on",
"floorId": [],
"areaId": [],
"deviceId": [],
"entityId": [
"input_boolean.living_room_new"
],
"labelId": [],
"data": "",
"dataType": "jsonata",
"mergeContext": "",
"mustacheAltTags": false,
"outputProperties": [],
"queue": "none",
"blockInputOverrides": false,
"domain": "input_boolean",
"service": "turn_on",
"x": 1500,
"y": 620,
"wires": [
[]
]
},
{
"id": "577d462afbb43835",
"type": "api-call-service",
"z": "7de41d810b04d992",
"d": true,
"name": "",
"server": "29eb84a2708d96e0",
"version": 7,
"debugenabled": false,
"action": "input_boolean.turn_off",
"floorId": [],
"areaId": [],
"deviceId": [],
"entityId": [
"input_boolean.living_room_new"
],
"labelId": [],
"data": "",
"dataType": "jsonata",
"mergeContext": "",
"mustacheAltTags": false,
"outputProperties": [],
"queue": "none",
"blockInputOverrides": false,
"domain": "input_boolean",
"service": "turn_off",
"x": 1500,
"y": 680,
"wires": [
[]
]
},
{
"id": "9f25a0709e29f737",
"type": "function",
"z": "7de41d810b04d992",
"d": true,
"name": "Zigbee to NVL",
"func": "// Writes to state.rooms.<roomKey>. Room from Zigbee device via global roomConfig.deviceToRoom. See /root/.node-red/room-config.js.\nconst actionToSwitch = { single: 1, double: 2, hold: 3, release: 4, triple: 5, quad: 6 };\nconst config = global.get('roomConfig');\nconst deviceToRoom = (config && config.deviceToRoom) ? config.deviceToRoom : { 'Office Switch': 'cmd_livingroom' };\nconst friendlyName = (msg.payload && msg.payload.friendly_name) ? msg.payload.friendly_name : '';\nconst ROOM_NAME = deviceToRoom[friendlyName] || 'cmd_livingroom';\nconst payload = msg.payload || {};\nconst actionRaw = (payload.action || payload.click || '').toLowerCase();\n// Support \"1_single\", \"2_double\" etc. (button_number + action) or plain \"single\", \"double\"\nconst parts = actionRaw.split('_');\nlet swIndex = null;\nif (parts.length >= 2) {\n const buttonNum = parseInt(parts[0], 10);\n if (buttonNum >= 1 && buttonNum <= 6) swIndex = buttonNum;\n}\nif (swIndex == null) swIndex = actionToSwitch[actionRaw];\nif (swIndex == null && parts.length >= 2) swIndex = actionToSwitch[parts.slice(1).join('_')];\nif (swIndex == null) swIndex = actionToSwitch[parts[parts.length - 1]];\n\nif (swIndex == null) {\n node.warn('[Zigbee to NVL] unknown action: ' + JSON.stringify(actionRaw) + ' payload=' + JSON.stringify(payload));\n return null;\n}\n\nif (!flow.get('nvlInState')) flow.set('nvlInState', { rooms: {}, boiler: {} });\nconst state = flow.get('nvlInState');\nif (!state.rooms[ROOM_NAME]) state.rooms[ROOM_NAME] = {};\nstate.rooms[ROOM_NAME]['zigbee_sw' + swIndex] = true;\nflow.set('nvlInState', state);\n\nnode.warn('[Zigbee to NVL] ' + ROOM_NAME + ' zigbee_sw' + swIndex + '=true (action=' + actionRaw + '), buildAndSend + zigbeeClear');\n\nmsg.payload = { buildAndSend: true };\nmsg.zigbeeClear = { room: ROOM_NAME, key: 'zigbee_sw' + swIndex };\nreturn msg;\n",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1200,
"y": 540,
"wires": [
[]
]
},
{
"id": "a0b2279b89ef6f15",
"type": "function",
"z": "7de41d810b04d992",
"d": true,
"name": "Load room config",
"func": "// Paste this into a Function node named \"Load room config\".\n// Connect an Inject node (once after 0.5 s) to it so it runs at startup.\n//\n// Since functionExternalModules is true in settings.js, you can require files.\n// room-config.js must be on the Node-RED server at /root/.node-red/room-config.js\n\n// Delete cached version so changes to the file are picked up on redeploy\ndelete require.cache[require.resolve('/root/.node-red/room-config.js')];\nconst ROOM_CONFIG = require('/root/.node-red/room-config.js');\n\nglobal.set('roomConfig', ROOM_CONFIG);\nnode.warn('[Load room config] loaded: ' + ROOM_CONFIG.roomNames.length + ' rooms, ' + ROOM_CONFIG.lightEntityMap.length + ' light mappings');\nreturn null;\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 850,
"y": 140,
"wires": [
[
"8150e2ee9131f8b9"
]
]
},
{
"id": "7667d77649229573",
"type": "inject",
"z": "7de41d810b04d992",
"d": true,
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": "0.5",
"topic": "",
"payload": "",
"payloadType": "date",
"x": 650,
"y": 140,
"wires": [
[
"a0b2279b89ef6f15"
]
]
},
{
"id": "8150e2ee9131f8b9",
"type": "debug",
"z": "7de41d810b04d992",
"d": true,
"name": "debug 36",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1040,
"y": 140,
"wires": []
},
{
"id": "a4e26ffa4890dced",
"type": "watch",
"z": "7de41d810b04d992",
"name": "Watch room-config.js",
"files": "/root/.node-red/room-config.js",
"recursive": "",
"x": 780,
"y": 80,
"wires": [
[
"9b42b7c654e069ab",
"5f1f1b1d56c0c6cc"
]
]
},
{
"id": "9b42b7c654e069ab",
"type": "exec",
"z": "7de41d810b04d992",
"command": "node -e \"console.log(JSON.stringify(require('/root/.node-red/room-config.js')))\"",
"addpay": "payload",
"append": "",
"useSpawn": "false",
"timer": "",
"winHide": false,
"oldrc": false,
"name": "Read room-config as JSON",
"x": 1120,
"y": 80,
"wires": [
[
"8fcbcdbb7ce4c8e5",
"2744d5e479e716b2"
],
[
"c59934f4f1db0826"
],
[
"1b367a15a867effc"
]
]
},
{
"id": "8fcbcdbb7ce4c8e5",
"type": "function",
"z": "7de41d810b04d992",
"name": "Reload room config",
"func": "// Paste into a Function node named \"Reload room config from payload\".\n// Input: msg.payload = JSON string (from Exec node that runs the script below).\n// Sets global roomConfig so all flows see the new config without restarting Node-RED.\n\nconst raw = msg.payload;\nif (typeof raw !== 'string') {\n node.warn('[Reload config] expected string payload, got ' + typeof raw);\n return null;\n}\ntry {\n const config = JSON.parse(raw.trim());\n if (!config.roomNames || !Array.isArray(config.roomNames)) {\n node.error('[Reload config] invalid config: missing roomNames');\n return null;\n }\n global.set('roomConfig', config);\n node.warn('[Reload config] OK: ' + config.roomNames.length + ' rooms, ' + (config.lightEntityMap ? config.lightEntityMap.length : 0) + ' light mappings');\n return msg;\n} catch (e) {\n node.error('[Reload config] parse error: ' + e.message);\n return null;\n}\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1430,
"y": 80,
"wires": [
[]
]
},
{
"id": "5f1f1b1d56c0c6cc",
"type": "debug",
"z": "7de41d810b04d992",
"name": "debug 37",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 950,
"y": 40,
"wires": []
},
{
"id": "2744d5e479e716b2",
"type": "debug",
"z": "7de41d810b04d992",
"name": "debug 39",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1420,
"y": 40,
"wires": []
},
{
"id": "c59934f4f1db0826",
"type": "debug",
"z": "7de41d810b04d992",
"name": "debug 40",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1420,
"y": 120,
"wires": []
},
{
"id": "1b367a15a867effc",
"type": "debug",
"z": "7de41d810b04d992",
"name": "debug 41",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1350,
"y": 160,
"wires": []
},
{
"id": "561398f1884392c1",
"type": "debug",
"z": "7de41d810b04d992",
"name": "debug 42",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1710,
"y": 540,
"wires": []
},
{
"id": "2edb29caf874a91e",
"type": "debug",
"z": "7de41d810b04d992",
"name": "debug 43",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1070,
"y": 460,
"wires": []
},
{
"id": "d592161c8e50638a",
"type": "debug",
"z": "480553bb6f5b2b51",
"g": "91b1f4cb0e1ffa84",
"name": "debug 7",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 2540,
"y": 80,
"wires": []
},
{
"id": "2a218aee475ce267",
"type": "debug",
"z": "480553bb6f5b2b51",
"g": "91b1f4cb0e1ffa84",
"name": "debug 10",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 2540,
"y": 120,
"wires": []
},
{
"id": "f5ef8cb0a1bc7def",
"type": "telegram receiver",
"z": "480553bb6f5b2b51",
"g": "91b1f4cb0e1ffa84",
"name": "",
"bot": "3dbb887330025103",
"saveDataDir": "",
"filterCommands": false,
"inputs": 0,
"x": 2350,
"y": 80,
"wires": [
[
"d592161c8e50638a"
],
[
"2a218aee475ce267"
]
]
},
{
"id": "0385d24efa18d698",
"type": "zigbee2mqtt-in",
"z": "480553bb6f5b2b51",
"g": "9113c5ebf5c089e3",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Hallway Door Sensor (TS0203)",
"device_id": "0xa4c138eb9239e0de",
"state": "contact",
"outputAtStartup": true,
"filterChanges": true,
"enableMultiple": false,
"x": 190,
"y": 120,
"wires": [
[
"4055425d6c42dd13"
]
]
},
{
"id": "9d611c0ff2a0b1ca",
"type": "zigbee2mqtt-in",
"z": "480553bb6f5b2b51",
"g": "9113c5ebf5c089e3",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Basement Door Sensor (E2013)",
"device_id": "0x048727fffea28deb",
"state": "contact",
"outputAtStartup": true,
"filterChanges": true,
"enableMultiple": false,
"x": 190,
"y": 160,
"wires": [
[
"4055425d6c42dd13"
]
]
},
{
"id": "10448f46514c1406",
"type": "zigbee2mqtt-in",
"z": "480553bb6f5b2b51",
"g": "9113c5ebf5c089e3",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Front Door Sensor (TS0203)",
"device_id": "0xa4c138f4b1035c1d",
"state": "contact",
"outputAtStartup": true,
"filterChanges": true,
"enableMultiple": false,
"x": 180,
"y": 200,
"wires": [
[
"4055425d6c42dd13"
]
]
},
{
"id": "a9d786b1ba52704b",
"type": "function",
"z": "480553bb6f5b2b51",
"g": "9113c5ebf5c089e3",
"name": "Generate Message with snapshot",
"func": "let contact = msg.payload;\nlet topic = msg.topic || '';\nlet rawName = topic.split('/')[1] || 'Unknown';\nlet cleanName = rawName.replace(/sensor/i, '').trim();\n\n// Mapping between sensor names (or topic parts) and their camera IPs\nconst cameraMap = {\n \"Hallway\": \"10.20.30.33\",\n \"Basement\": \"10.20.30.30\",\n \"Front\": \"10.20.30.30\",\n \"Veranda\": \"10.20.30.32\"\n};\n\n// Find matching camera IP based on topic\nlet cameraIP = Object.keys(cameraMap).find(key => topic.includes(key));\nlet ip = cameraMap[cameraIP] || \"10.20.30.30\"; // fallback to Hallway if not matched\n\n// Construct URL\nmsg.url = `http://${ip}/cgi-bin/api.cgi?cmd=Snap&channel=0&rs=${Math.random().toString(36).substring(7)}&user=admin&password=sh1pb0x1`;\n\n// Final message structure\nmsg.payload = null; // clear previous payload\nmsg.friendly_name = cleanName;\nmsg.door_status = contact === true ? \"CLOSED\" : \"OPENED\";\n\nreturn msg;\n\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 920,
"y": 120,
"wires": [
[
"5e94eb39aec6e82d",
"8b8cce25637907b1"
]
]
},
{
"id": "e250cc2f901bea9f",
"type": "function",
"z": "480553bb6f5b2b51",
"g": "9113c5ebf5c089e3",
"name": "Send Message to group",
"func": "// Check that the snapshot came in as a binary buffer\nif (!Buffer.isBuffer(msg.payload)) {\n node.warn(\"❌ Snapshot fetch failed — not a binary image buffer\");\n return null;\n}\n\nmsg.payload = {\n chatId: -4747176681,\n type: 'photo',\n content: msg.payload, // this is the buffer\n caption: `🚪 ${msg.friendly_name} just ${msg.door_status}`\n};\n\nreturn msg;\n\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1410,
"y": 120,
"wires": [
[
"7301d71523d87e94"
]
]
},
{
"id": "5e94eb39aec6e82d",
"type": "debug",
"z": "480553bb6f5b2b51",
"g": "9113c5ebf5c089e3",
"name": "debug 6",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1160,
"y": 60,
"wires": []
},
{
"id": "8b8cce25637907b1",
"type": "http request",
"z": "480553bb6f5b2b51",
"g": "9113c5ebf5c089e3",
"name": "",
"method": "GET",
"ret": "bin",
"paytoqs": "query",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 1190,
"y": 120,
"wires": [
[
"e250cc2f901bea9f"
]
]
},
{
"id": "3f9797c13c3a11a1",
"type": "function",
"z": "480553bb6f5b2b51",
"d": true,
"g": "9113c5ebf5c089e3",
"name": "Door Status Message",
"func": "// Extract contact state and sensor name\nlet contact = msg.payload;\nlet topic = msg.topic || '';\nlet rawName = topic.split('/')[1] || 'Unknown';\nlet cleanName = rawName.replace(/sensor/i, '').trim();\n\n// Create message\nmsg.payload = {\n chatId: -4747176681,\n type: 'message',\n content: `🚪 ${cleanName} just ${contact === true ? \"CLOSED\" : \"OPENED\"}`\n};\n\nreturn msg;\n\n\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 940,
"y": 60,
"wires": [
[]
]
},
{
"id": "c57ea029ee569428",
"type": "zigbee2mqtt-in",
"z": "480553bb6f5b2b51",
"g": "a73395db2426b4fc",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Front Water Valve (SWV)",
"device_id": "0x0ceff6fffe84e4bc",
"state": "state",
"outputAtStartup": false,
"filterChanges": true,
"enableMultiple": false,
"x": 610,
"y": 540,
"wires": [
[
"fe7372c7f33d96f3"
]
]
},
{
"id": "fe7372c7f33d96f3",
"type": "function",
"z": "480553bb6f5b2b51",
"g": "a73395db2426b4fc",
"name": "Status Message",
"func": "let state = msg.payload;\nlet status = state === 'ON' ? \"OPENED\" : \"CLOSED\";\n\nmsg.payload = {\n chatId: -4747176681, // your group chat ID\n type: 'message',\n content: `💧 Front Water Valve is now ${status}`\n};\n\nreturn msg;\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 840,
"y": 540,
"wires": [
[
"18454d6cad2042dc"
]
]
},
{
"id": "c1d2a4dc34b63730",
"type": "zigbee2mqtt-in",
"z": "480553bb6f5b2b51",
"g": "a73395db2426b4fc",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Back Water Valve (SWV)",
"device_id": "0x7cc6b6fffe38a415",
"state": "state",
"outputAtStartup": false,
"filterChanges": true,
"enableMultiple": false,
"x": 610,
"y": 600,
"wires": [
[
"141f635c6c9d380f"
]
]
},
{
"id": "141f635c6c9d380f",
"type": "function",
"z": "480553bb6f5b2b51",
"g": "a73395db2426b4fc",
"name": "Status Message",
"func": "let state = msg.payload;\nlet status = state === 'ON' ? \"OPENED\" : \"CLOSED\";\n\nmsg.payload = {\n chatId: -4747176681, // your group chat ID\n type: 'message',\n content: `💧 Back Water Valve is now ${status}`\n};\n\nreturn msg;\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 840,
"y": 600,
"wires": [
[
"18454d6cad2042dc"
]
]
},
{
"id": "77f3053cbdcdb875",
"type": "debug",
"z": "480553bb6f5b2b51",
"name": "debug 9",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 2540,
"y": 260,
"wires": []
},
{
"id": "55c50c70b3d0a0bb",
"type": "telegram sender",
"z": "480553bb6f5b2b51",
"name": "",
"bot": "3dbb887330025103",
"haserroroutput": false,
"outputs": 1,
"x": 2330,
"y": 260,
"wires": [
[
"77f3053cbdcdb875"
]
]
},
{
"id": "41d29e978759e26e",
"type": "link in",
"z": "480553bb6f5b2b51",
"name": "telegram sender",
"links": [
"7301d71523d87e94",
"18454d6cad2042dc",
"70f797398b0e6783",
"81d16e7a5307e9cc",
"bd7fed2198a7b950",
"8f15067daf678e66",
"1ba4ee81e40e5c51"
],
"x": 2145,
"y": 260,
"wires": [
[
"55c50c70b3d0a0bb"
]
]
},
{
"id": "7301d71523d87e94",
"type": "link out",
"z": "480553bb6f5b2b51",
"g": "9113c5ebf5c089e3",
"name": "link out 16",
"mode": "link",
"links": [
"41d29e978759e26e"
],
"x": 1555,
"y": 120,
"wires": []
},
{
"id": "18454d6cad2042dc",
"type": "link out",
"z": "480553bb6f5b2b51",
"g": "a73395db2426b4fc",
"name": "link out 17",
"mode": "link",
"links": [
"41d29e978759e26e"
],
"x": 1055,
"y": 540,
"wires": []
},
{
"id": "4055425d6c42dd13",
"type": "api-current-state",
"z": "480553bb6f5b2b51",
"g": "9113c5ebf5c089e3",
"name": "",
"server": "29eb84a2708d96e0",
"version": 3,
"outputs": 2,
"halt_if": "home",
"halt_if_type": "str",
"halt_if_compare": "is",
"entity_id": "person.nearchos_paraskeva",
"state_type": "str",
"blockInputOverrides": false,
"outputProperties": [],
"for": "",
"forType": "num",
"forUnits": "seconds",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 570,
"y": 120,
"wires": [
[],
[
"a9d786b1ba52704b",
"f6adcaa35a793e58"
]
]
},
{
"id": "ada6fe8339eab29b",
"type": "zigbee2mqtt-in",
"z": "480553bb6f5b2b51",
"g": "9113c5ebf5c089e3",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Veranda Door Sensor (E2013)",
"device_id": "0x048727fffea287ba",
"state": "contact",
"outputAtStartup": true,
"filterChanges": true,
"enableMultiple": false,
"x": 180,
"y": 260,
"wires": [
[
"4055425d6c42dd13"
]
]
},
{
"id": "8f42e8fdfef40579",
"type": "zigbee2mqtt-in",
"z": "480553bb6f5b2b51",
"g": "5c95d99a679a5e00",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Pantry water leak Sensor (ZG-222ZA)",
"device_id": "0xa4c138aeed18e61c",
"state": "water_leak",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 230,
"y": 620,
"wires": [
[
"1164cfc4fd2e5382"
]
]
},
{
"id": "58ee1ac91f379cb9",
"type": "function",
"z": "480553bb6f5b2b51",
"g": "5c95d99a679a5e00",
"name": "Status Message",
"func": "let state = msg.payload;\n\nif (state === true) {\n msg.payload = {\n chatId: -4747176681, // your group chat ID\n type: 'animation',\n content: 'https://media0.giphy.com/media/v1.Y2lkPTc5MGI3NjExeWoxNjV6Z2Fna3MxMjcxd3RsaWxjMTA3cWhraW9kbGYzbGFtNzUzYiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/lVBtp4SRW6rvDHf1b6/giphy.gif', // Replace with your preferred GIF URL\n caption: '🚨 WATER LEAK DETECTED in Pantry Sink!'\n };\n return msg;\n}\n\nreturn null;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1000,
"y": 460,
"wires": [
[
"70f797398b0e6783"
]
]
},
{
"id": "a1f1e1ea2cf90f61",
"type": "inject",
"z": "480553bb6f5b2b51",
"g": "5c95d99a679a5e00",
"name": "Simulate Leak (true)",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "true",
"payloadType": "bool",
"x": 290,
"y": 420,
"wires": [
[
"22740e52f6cc3399"
]
]
},
{
"id": "3242605bce7f6f92",
"type": "inject",
"z": "480553bb6f5b2b51",
"g": "5c95d99a679a5e00",
"name": "Simulate No Leak (false)",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "false",
"payloadType": "bool",
"x": 270,
"y": 460,
"wires": [
[
"22740e52f6cc3399"
]
]
},
{
"id": "22740e52f6cc3399",
"type": "function",
"z": "480553bb6f5b2b51",
"g": "5c95d99a679a5e00",
"name": "Prepare trigger/reset",
"func": "// Pass through leak state\n// Add reset flag when false\n\nif (msg.payload === false) {\n msg.reset = true;\n}\n\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 560,
"y": 420,
"wires": [
[
"53799a37bb6cf7c6"
]
]
},
{
"id": "53799a37bb6cf7c6",
"type": "trigger",
"z": "480553bb6f5b2b51",
"g": "5c95d99a679a5e00",
"name": "Repeat every 1 min",
"op1": "true",
"op2": "true",
"op1type": "bool",
"op2type": "bool",
"duration": "1",
"extend": true,
"overrideDelay": false,
"units": "min",
"reset": "reset",
"bytopic": "all",
"topic": "topic",
"outputs": 1,
"x": 780,
"y": 420,
"wires": [
[
"8b9761ea2f86b4f1"
]
]
},
{
"id": "8b9761ea2f86b4f1",
"type": "function",
"z": "480553bb6f5b2b51",
"g": "5c95d99a679a5e00",
"name": "Status Message",
"func": "let state = msg.payload;\n\nif (state === true) {\n msg.payload = {\n chatId: -4747176681, // your group chat ID\n type: 'animation',\n content: 'https://media0.giphy.com/media/v1.Y2lkPTc5MGI3NjExeWoxNjV6Z2Fna3MxMjcxd3RsaWxjMTA3cWhraW9kbGYzbGFtNzUzYiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/lVBtp4SRW6rvDHf1b6/giphy.gif', // Replace with your preferred GIF URL\n caption: '🚨 WATER LEAK DETECTED in Kitchen Sink!'\n };\n return msg;\n}\n\nreturn null;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1000,
"y": 420,
"wires": [
[
"70f797398b0e6783"
]
]
},
{
"id": "70f797398b0e6783",
"type": "link out",
"z": "480553bb6f5b2b51",
"g": "5c95d99a679a5e00",
"name": "link out 19",
"mode": "link",
"links": [
"41d29e978759e26e"
],
"x": 1575,
"y": 440,
"wires": []
},
{
"id": "2157cdd444dfec91",
"type": "zigbee2mqtt-in",
"z": "480553bb6f5b2b51",
"g": "5c95d99a679a5e00",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "kitchen water leak sensor (E2202)",
"device_id": "0xf84477fffeec19e9",
"state": "water_leak",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 240,
"y": 500,
"wires": [
[
"22740e52f6cc3399"
]
]
},
{
"id": "8b2f06afcf0d773e",
"type": "inject",
"z": "480553bb6f5b2b51",
"g": "5c95d99a679a5e00",
"name": "Simulate Leak (true)",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "true",
"payloadType": "bool",
"x": 290,
"y": 540,
"wires": [
[
"1164cfc4fd2e5382"
]
]
},
{
"id": "e31ec1ce332c4c99",
"type": "inject",
"z": "480553bb6f5b2b51",
"g": "5c95d99a679a5e00",
"name": "Simulate No Leak (false)",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "false",
"payloadType": "bool",
"x": 270,
"y": 580,
"wires": [
[
"1164cfc4fd2e5382"
]
]
},
{
"id": "1164cfc4fd2e5382",
"type": "function",
"z": "480553bb6f5b2b51",
"g": "5c95d99a679a5e00",
"name": "Prepare trigger/reset",
"func": "// Pass through leak state\n// Add reset flag when false\n\nif (msg.payload === false) {\n msg.reset = true;\n}\n\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 560,
"y": 460,
"wires": [
[
"748c39a404648158"
]
]
},
{
"id": "748c39a404648158",
"type": "trigger",
"z": "480553bb6f5b2b51",
"g": "5c95d99a679a5e00",
"name": "Repeat every 1 min",
"op1": "true",
"op2": "true",
"op1type": "bool",
"op2type": "bool",
"duration": "1",
"extend": true,
"overrideDelay": false,
"units": "min",
"reset": "reset",
"bytopic": "all",
"topic": "topic",
"outputs": 1,
"x": 790,
"y": 460,
"wires": [
[
"58ee1ac91f379cb9"
]
]
},
{
"id": "eb721beae24b271b",
"type": "zigbee2mqtt-in",
"z": "480553bb6f5b2b51",
"g": "1c73b8aaec035f06",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "27 selected",
"device_id": [
"0xa4c138ff324b5b7e",
"0xa4c138a5b9771b05",
"0xa4c13873de3faa66",
"0xa4c138cc9b54cec9",
"0xa4c138112a12d55f",
"0xa4c13854734f3a20",
"0xa4c1387dd1c2d40e",
"0xa4c138332cc3da08",
"0xa4c1388b74d83cfa",
"0xa4c138c2ae9ed430",
"0xa4c1380bab38d546",
"0xa4c1383b7c24483a",
"0x8c65a3fffee879a6",
"0xa4c138ceaa5681d5",
"0xa4c138d65f53037c",
"0xa4c1383d7921827a",
"0xa4c138eb9239e0de",
"0xa4c13891821386eb",
"0xa4c138f4b1035c1d",
"0x0ceff6fffe84e4bc",
"0x7cc6b6fffe38a415",
"0x048727fffea28deb",
"0x6cfd22fffe2cc318",
"0x6cfd22fffe66db44",
"0xa4c138aeed18e61c",
"0xf84477fffeec19e9",
"0x048727fffea287ba"
],
"state": null,
"outputAtStartup": false,
"filterChanges": false,
"enableMultiple": true,
"x": 150,
"y": 820,
"wires": [
[
"41f1e9feaf1ea6aa",
"a9f755806e4e8a75"
]
]
},
{
"id": "41f1e9feaf1ea6aa",
"type": "function",
"z": "480553bb6f5b2b51",
"g": "1c73b8aaec035f06",
"name": "function 5",
"func": "let result = [];\nlet devices = msg.payload;\nlet now = Date.now();\nlet dayMs = 24 * 60 * 60 * 1000;\n\n// Use flow context to track last alerts\nlet lastAlerts = flow.get(\"battery_alerts\") || {};\n\nfor (let ieee in devices) {\n let dev = devices[ieee];\n let battery = dev.payload?.battery ?? dev.item?.current_values?.battery;\n let name = dev.item?.friendly_name || dev.topic || ieee;\n\n if (typeof battery === 'number' && battery < 15) {\n let lastAlert = lastAlerts[ieee];\n\n if (!lastAlert || now - lastAlert > dayMs) {\n result.push(`🔋 ${name} is at ${battery}%`);\n lastAlerts[ieee] = now; // update timestamp\n }\n }\n}\n\n// Save updated state\nflow.set(\"battery_alerts\", lastAlerts);\n\nif (result.length > 0) {\n let time = new Date().toLocaleString();\n msg.payload = `Low battery alert(s) [${time}]:\\n` + result.join('\\n');\n return msg;\n}\n\nreturn null;\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 600,
"y": 740,
"wires": [
[
"c60307d3b68ebe34",
"5c2272c244ffc8b0"
]
]
},
{
"id": "c60307d3b68ebe34",
"type": "function",
"z": "480553bb6f5b2b51",
"g": "1c73b8aaec035f06",
"name": "function 6",
"func": "let battery = msg.payload;\n\n\nmsg.payload = {\n chatId: -4747176681, // your group chat ID\n type: 'message',\n content: `${battery}`\n};\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1040,
"y": 740,
"wires": [
[
"81d16e7a5307e9cc",
"6d60df5c0c6920d2"
]
]
},
{
"id": "81d16e7a5307e9cc",
"type": "link out",
"z": "480553bb6f5b2b51",
"g": "1c73b8aaec035f06",
"name": "link out 18",
"mode": "link",
"links": [
"41d29e978759e26e"
],
"x": 1575,
"y": 740,
"wires": []
},
{
"id": "209d79611a5414cc",
"type": "function",
"z": "480553bb6f5b2b51",
"d": true,
"g": "1c73b8aaec035f06",
"name": "function 7",
"func": "let result = [];\nlet devices = msg.payload;\n\nfor (let ieee in devices) {\n let dev = devices[ieee];\n\n // Try to get battery from payload or fallback to item.current_values\n let battery = dev.payload?.battery ?? dev.item?.current_values?.battery;\n\n // Get friendly name or fallback to topic or IEEE\n let name = dev.item?.friendly_name || dev.topic || ieee;\n // if (typeof battery === 'number') {\n if (typeof battery === 'number' && battery < 15) {\n result.push(`🔋 ${name} is at ${battery}%`);\n }\n}\n\nif (result.length > 0) {\n msg.payload = `Low battery alert(s):\\n` + result.join('\\n');\n return msg;\n}\n\nreturn null;\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 600,
"y": 780,
"wires": [
[]
]
},
{
"id": "e6a93b0cbc48af98",
"type": "inject",
"z": "480553bb6f5b2b51",
"g": "1c73b8aaec035f06",
"name": "Test Device",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "zigbee2mqtt/Test Device",
"payload": "{\"0xdeadbeef00000001\":{\"item\":{\"friendly_name\":\"Low Battery Sensor\"},\"topic\":\"zigbee2mqtt/Low Battery Sensor\",\"payload\":{\"battery\":9}},\"0xdeadbeef00000002\":{\"item\":{\"friendly_name\":\"Good Battery Sensor\"},\"topic\":\"zigbee2mqtt/Good Battery Sensor\",\"payload\":{\"battery\":87}}}",
"payloadType": "json",
"x": 170,
"y": 740,
"wires": [
[
"41f1e9feaf1ea6aa",
"a9f755806e4e8a75"
]
]
},
{
"id": "a9f755806e4e8a75",
"type": "debug",
"z": "480553bb6f5b2b51",
"g": "1c73b8aaec035f06",
"name": "debug 2",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 160,
"y": 780,
"wires": []
},
{
"id": "5c2272c244ffc8b0",
"type": "debug",
"z": "480553bb6f5b2b51",
"g": "1c73b8aaec035f06",
"name": "debug 3",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 760,
"y": 760,
"wires": []
},
{
"id": "6d60df5c0c6920d2",
"type": "debug",
"z": "480553bb6f5b2b51",
"g": "1c73b8aaec035f06",
"name": "debug 4",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1200,
"y": 760,
"wires": []
},
{
"id": "8e0d5ec04f029b9a",
"type": "zigbee2mqtt-in",
"z": "480553bb6f5b2b51",
"g": "9113c5ebf5c089e3",
"name": "Door Sensors",
"server": "4e20fc347c658518",
"friendly_name": "4 selected",
"device_id": [
"0xa4c138eb9239e0de",
"0xa4c138f4b1035c1d",
"0x048727fffea28deb",
"0x048727fffea287ba"
],
"state": null,
"outputAtStartup": false,
"filterChanges": false,
"enableMultiple": true,
"x": 130,
"y": 80,
"wires": [
[
"eb25ece689ea1045",
"63cb264d89898c6a"
]
]
},
{
"id": "eb25ece689ea1045",
"type": "rbe",
"z": "480553bb6f5b2b51",
"g": "9113c5ebf5c089e3",
"name": "",
"func": "rbe",
"gap": "",
"start": "",
"inout": "out",
"septopics": true,
"property": "payload",
"topi": "topic",
"x": 350,
"y": 80,
"wires": [
[
"bd4b7dd437c1aaaf"
]
]
},
{
"id": "63cb264d89898c6a",
"type": "debug",
"z": "480553bb6f5b2b51",
"g": "9113c5ebf5c089e3",
"name": "debug 5",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 270,
"y": 40,
"wires": []
},
{
"id": "bd4b7dd437c1aaaf",
"type": "debug",
"z": "480553bb6f5b2b51",
"g": "9113c5ebf5c089e3",
"name": "debug 8",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 470,
"y": 60,
"wires": []
},
{
"id": "f6adcaa35a793e58",
"type": "debug",
"z": "480553bb6f5b2b51",
"g": "9113c5ebf5c089e3",
"name": "debug 11",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 850,
"y": 200,
"wires": []
},
{
"id": "8656a450e0ae020d",
"type": "mqtt in",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "",
"topic": "#",
"qos": "2",
"datatype": "auto-detect",
"broker": "a1235a09a8d34dea",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 150,
"y": 1200,
"wires": [
[
"7ff8359abb38dca4"
]
]
},
{
"id": "7ff8359abb38dca4",
"type": "switch",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "",
"property": "topic",
"propertyType": "msg",
"rules": [
{
"t": "cont",
"v": "zigbee2mqtt",
"vt": "str"
},
{
"t": "eq",
"v": "frigate/doorbell/person",
"vt": "str"
},
{
"t": "eq",
"v": "frigate/veranda_door/person",
"vt": "str"
},
{
"t": "eq",
"v": "frigate/basement_driveway/person",
"vt": "str"
},
{
"t": "cont",
"v": "frigate",
"vt": "str"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 6,
"x": 330,
"y": 1200,
"wires": [
[],
[
"doorbell_state_check"
],
[
"48bfe0ad8a973a84"
],
[
"365adc2679063bc8"
],
[],
[]
]
},
{
"id": "doorbell_state_check",
"type": "function",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "Check State Change",
"func": "// Get current payload value\nvar currentValue = parseInt(msg.payload);\n\n// Get previous state from context (default to 0 if not set)\nvar previousValue = context.get('previousDoorbellState') || 0;\n\n// Store current value for next comparison\ncontext.set('previousDoorbellState', currentValue);\n\n// Only proceed if current value is 1 AND previous value was 0\nif (currentValue === 1 && previousValue === 0) {\n msg.payload = \"🚪 Person detected at doorbell!\";\n return msg;\n}\n\n// Don't send message for other cases\nreturn null;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 700,
"y": 1200,
"wires": [
[
"78a1c2a40934ef20"
]
]
},
{
"id": "bd7fed2198a7b950",
"type": "link out",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "link out 22",
"mode": "link",
"links": [
"41d29e978759e26e"
],
"x": 2335,
"y": 1200,
"wires": []
},
{
"id": "78a1c2a40934ef20",
"type": "function",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "Generate Doorbell Camera URL",
"func": "// Hardcoded doorbell camera IP\nconst doorbellCameraIP = \"10.20.30.30\";\n\n// Generate random string for cache busting\nconst randomString = Math.random().toString(36).substring(7);\n\n// Construct camera snapshot URL\nmsg.url = `http://${doorbellCameraIP}/cgi-bin/api.cgi?cmd=Snap&channel=0&rs=${randomString}&user=admin&password=sh1pb0x1`;\n\n// Clear payload for HTTP request\nmsg.payload = null;\n\n// Add camera info to message\nmsg.camera_ip = doorbellCameraIP;\nmsg.camera_location = \"Doorbell Camera\";\n\nnode.status({fill:\"blue\", shape:\"dot\", text:`URL: ${doorbellCameraIP}`});\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 990,
"y": 1200,
"wires": [
[
"05f0d77a9b605f22"
]
]
},
{
"id": "05f0d77a9b605f22",
"type": "http request",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "Fetch Camera Snapshot",
"method": "GET",
"ret": "bin",
"paytoqs": "query",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 1270,
"y": 1200,
"wires": [
[
"19d0e8d8c5addb1f"
]
]
},
{
"id": "19d0e8d8c5addb1f",
"type": "function",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "Send Doorbell Alert to Telegram",
"func": "// Validate that we received a proper image buffer\nif (!Buffer.isBuffer(msg.payload)) {\n node.warn(\"❌ Doorbell snapshot fetch failed — not a binary image buffer\");\n node.status({fill:\"red\", shape:\"ring\", text:\"Snapshot failed\"});\n return null;\n}\n\n// Check if buffer has reasonable size (basic validation)\nif (msg.payload.length < 1000) {\n node.warn(\"❌ Doorbell snapshot too small — likely corrupted\");\n node.status({fill:\"red\", shape:\"ring\", text:\"Image too small\"});\n return null;\n}\n\n// Format timestamp for display\nconst timestamp = new Date(msg.timestamp).toLocaleString();\n\n// Prepare Telegram message payload\nmsg.payload = {\n chatId: -4747176681, // Telegram group chat ID\n type: 'photo',\n content: msg.payload, // Binary image buffer\n caption: `🔔 DOORBELL ALERT! 🔔\\n\\n📍 Someone is at the ${msg.location}\\n⏰ Time: ${timestamp}\\n📷 Camera: ${msg.camera_location} (${msg.camera_ip})`\n};\n\nnode.status({fill:\"green\", shape:\"dot\", text:\"Alert sent!\"});\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1540,
"y": 1200,
"wires": [
[
"bd7fed2198a7b950"
]
]
},
{
"id": "eff49303c6d84242",
"type": "function",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "Send Doorbell Alert to Telegram",
"func": "// Validate that we received a proper image buffer\nif (!Buffer.isBuffer(msg.payload)) {\n node.warn(\"❌ Doorbell snapshot fetch failed — not a binary image buffer\");\n node.status({fill:\"red\", shape:\"ring\", text:\"Snapshot failed\"});\n return null;\n}\n\n// Check if buffer has reasonable size (basic validation)\nif (msg.payload.length < 1000) {\n node.warn(\"❌ Doorbell snapshot too small — likely corrupted\");\n node.status({fill:\"red\", shape:\"ring\", text:\"Image too small\"});\n return null;\n}\n\n// Format timestamp for display\nconst timestamp = new Date(msg.timestamp).toLocaleString();\n\n// Prepare Telegram message payload\nmsg.payload = {\n chatId: -4747176681, // Telegram group chat ID\n type: 'photo',\n content: msg.payload, // Binary image buffer\n caption: `🔔 Veranda ALERT! 🔔\\n\\n📍 Someone is at the ${msg.location}\\n⏰ Time: ${timestamp}\\n📷 Camera: ${msg.camera_location} (${msg.camera_ip})`\n};\n\nnode.status({fill:\"green\", shape:\"dot\", text:\"Alert sent!\"});\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1550,
"y": 1260,
"wires": [
[
"bd7fed2198a7b950"
]
]
},
{
"id": "c74ddf6b84ef7a95",
"type": "http request",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "Fetch Camera Snapshot",
"method": "GET",
"ret": "bin",
"paytoqs": "query",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 1270,
"y": 1260,
"wires": [
[
"eff49303c6d84242",
"88d855e525ab78f0"
]
]
},
{
"id": "d496d62222d1a073",
"type": "function",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "Generate Doorbell Camera URL",
"func": "// Hardcoded doorbell camera IP\nconst CameraIP = \"10.20.30.33\";\n\n// Generate random string for cache busting\nconst randomString = Math.random().toString(36).substring(7);\n\n// Construct camera snapshot URL\nmsg.url = `http://${CameraIP}/cgi-bin/api.cgi?cmd=Snap&channel=0&rs=${randomString}&user=admin&password=sh1pb0x1`;\n\n// Clear payload for HTTP request\nmsg.payload = null;\n\n// Add camera info to message\nmsg.camera_ip = CameraIP;\nmsg.camera_location = \"Veranda Door Camera\";\n\nnode.status({fill:\"blue\", shape:\"dot\", text:`URL: ${CameraIP}`});\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 990,
"y": 1260,
"wires": [
[
"c74ddf6b84ef7a95"
]
]
},
{
"id": "48bfe0ad8a973a84",
"type": "function",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "Check State Change",
"func": "// Get current payload value\nvar currentValue = parseInt(msg.payload);\n\n// Get previous state from context (default to 0 if not set)\nvar previousValue = context.get('previousDoorbellState') || 0;\n\n// Store current value for next comparison\ncontext.set('previousDoorbellState', currentValue);\n\n// Only proceed if current value is 1 AND previous value was 0\nif (currentValue === 1 && previousValue === 0) {\n msg.payload = \"🚪 Person detected at Veranda Door!\";\n return msg;\n}\n\n// Don't send message for other cases\nreturn null;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 700,
"y": 1260,
"wires": [
[
"d496d62222d1a073"
]
]
},
{
"id": "88d855e525ab78f0",
"type": "function",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "function 8",
"func": "// Try decoding buffer into string so we can read JSON errors\ntry {\n msg.debug_text = msg.payload.toString();\n node.warn(\"Camera returned text: \" + msg.debug_text);\n} catch (e) {\n node.warn(\"Could not decode payload\");\n}\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1620,
"y": 1300,
"wires": [
[]
]
},
{
"id": "a4752681740af47e",
"type": "inject",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "Simulate Person Detected",
"props": [
{
"p": "payload",
"v": "1",
"vt": "num"
},
{
"p": "timestamp",
"v": "",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"x": 170,
"y": 1300,
"wires": [
[
"7e88e31d094e343d"
]
]
},
{
"id": "7e88e31d094e343d",
"type": "function",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "Add Current Timestamp",
"func": "// Add timestamp\nmsg.timestamp = Date.now();\nreturn msg;",
"outputs": 1,
"x": 170,
"y": 1360,
"wires": [
[
"365adc2679063bc8"
]
]
},
{
"id": "365adc2679063bc8",
"type": "function",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "Check Doorbell State",
"func": "// Get previous state from context\nvar prev = context.get('prev') || 0;\nvar curr = parseInt(msg.payload);\ncontext.set('prev', curr);\n\nif(curr===1 && prev===0){\n msg.payload = \"🚪 Person detected at Basement Driveway!\";\n return msg;\n}\nreturn null;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 700,
"y": 1360,
"wires": [
[
"842a49fa21a0587a"
]
]
},
{
"id": "842a49fa21a0587a",
"type": "function",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "Reolink Login",
"func": "const ip = '10.20.30.34';\nconst username = 'admin';\nconst password = 'sh1pb0x1';\nmsg.url = `http://${ip}/cgi-bin/api.cgi?cmd=Login&token=null`;\nmsg.method = 'POST';\nmsg.headers = { 'Content-Type': 'application/json' };\nmsg.payload = JSON.stringify([\n { cmd: 'Login', param: { User: { userName: username, password: password } } }\n]);\nmsg.camera_ip = ip;\nmsg.camera_location = 'Basement Driveway Camera';\nmsg.nextRandom = Math.random().toString(36).substring(7);\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 950,
"y": 1360,
"wires": [
[
"bedee5f9397c27f1"
]
]
},
{
"id": "bedee5f9397c27f1",
"type": "http request",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "Send Login Request",
"method": "use",
"ret": "obj",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"x": 1190,
"y": 1360,
"wires": [
[
"3f9c2db4dfea3095"
]
]
},
{
"id": "3f9c2db4dfea3095",
"type": "function",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "Fetch Snapshot",
"func": "// Extract token from login response\nif(!msg.payload || !msg.payload[0] || !msg.payload[0].value){\n node.error('Login failed');\n return null;\n}\nconst token = msg.payload[0].value.Token.name;\nif(!token){ node.error('Token missing'); return null; }\n\n// Build snapshot URL\nmsg.url = `http://${msg.camera_ip}/cgi-bin/api.cgi?cmd=Snap&channel=0&rs=${msg.nextRandom}&token=${token}`;\nmsg.method = 'GET';\nmsg.headers = {};\nmsg.payload = null;\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1430,
"y": 1360,
"wires": [
[
"0446448ed8c8da8a"
]
]
},
{
"id": "0446448ed8c8da8a",
"type": "http request",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "Get Camera Snapshot",
"method": "use",
"ret": "bin",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"x": 1670,
"y": 1360,
"wires": [
[
"d241b1f4991cfc05"
]
]
},
{
"id": "d241b1f4991cfc05",
"type": "function",
"z": "480553bb6f5b2b51",
"d": true,
"g": "ce79bea4667a77e2",
"name": "Send Doorbell Alert to Telegram",
"func": "// Validate that we received a proper image buffer\nif (!Buffer.isBuffer(msg.payload)) {\n node.warn(\"❌ Basement Driveway snapshot fetch failed — not a binary image buffer\");\n node.status({fill:\"red\", shape:\"ring\", text:\"Snapshot failed\"});\n return null;\n}\n\n// Check if buffer has reasonable size (basic validation)\nif (msg.payload.length < 1000) {\n node.warn(\"❌ Basement Driveway snapshot too small — likely corrupted\");\n node.status({fill:\"red\", shape:\"ring\", text:\"Image too small\"});\n return null;\n}\n\n// Format timestamp for display\nconst timestamp = new Date(msg.timestamp).toLocaleString();\n\n// Prepare Telegram message payload\nmsg.payload = {\n chatId: -4747176681, // Telegram group chat ID\n type: 'photo',\n content: msg.payload, // Binary image buffer\n caption: `🔔 Basement Driveway ALERT! 🔔\\n\\n📍 Someone is at the ${msg.location}\\n⏰ Time: ${timestamp}\\n📷 Camera: ${msg.camera_location} (${msg.camera_ip})`\n};\n\nnode.status({fill:\"green\", shape:\"dot\", text:\"Alert sent!\"});\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1950,
"y": 1360,
"wires": [
[
"bd7fed2198a7b950"
]
]
},
{
"id": "ca1a1f7f8b90cfc9",
"type": "zigbee2mqtt-in",
"z": "f9a2fb576f0d360d",
"d": true,
"g": "b5ffb4a4212da258",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Office Switch (TS0042)",
"device_id": "0xa4c138a5b9771b05",
"state": "action",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 220,
"y": 120,
"wires": [
[
"b8f3d3242fb39bdd"
]
]
},
{
"id": "b8f3d3242fb39bdd",
"type": "subflow:4dc13919bcc9d676",
"z": "f9a2fb576f0d360d",
"d": true,
"g": "b5ffb4a4212da258",
"name": "",
"env": [
{
"name": "switch_1",
"value": "bedroom_1.sw_1",
"type": "str"
}
],
"x": 1270,
"y": 120,
"wires": [
[
"629cbd7ce15bb9e3"
]
]
},
{
"id": "629cbd7ce15bb9e3",
"type": "link out",
"z": "f9a2fb576f0d360d",
"name": "link out 1",
"mode": "link",
"links": [
"c6162cb59e21491f"
],
"x": 1785,
"y": 1340,
"wires": []
},
{
"id": "6654c150377ed2bb",
"type": "zigbee2mqtt-in",
"z": "f9a2fb576f0d360d",
"g": "4b06cbc568091f6f",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Hallway Switch (TS0042)",
"device_id": "0xa4c13873de3faa66",
"state": "0",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 230,
"y": 220,
"wires": [
[
"83bbabef65831016"
]
]
},
{
"id": "1aa9e0ff37d1afee",
"type": "zigbee2mqtt-in",
"z": "f9a2fb576f0d360d",
"g": "795d604329d51272",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Hallway Door Switch (TS0042)",
"device_id": "0xa4c138112a12d55f",
"state": "action",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 250,
"y": 320,
"wires": [
[
"b9c07d22cbaae6a2"
]
]
},
{
"id": "a6cf1bd4ae01ee56",
"type": "zigbee2mqtt-in",
"z": "f9a2fb576f0d360d",
"g": "39f557d8eec2fbae",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Master Bedroom Switch (TS0044)",
"device_id": "0xa4c13854734f3a20",
"state": "action",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 260,
"y": 420,
"wires": [
[
"16eaca15570ff092",
"2d6bcc49a2785fd6"
]
]
},
{
"id": "675ba75711ef84e7",
"type": "zigbee2mqtt-in",
"z": "f9a2fb576f0d360d",
"g": "68db2262f7c7313e",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Master bathroom switch (TS0042)",
"device_id": "0xa4c1387dd1c2d40e",
"state": "action",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 260,
"y": 900,
"wires": [
[
"84272551b322cde2"
]
]
},
{
"id": "becbc51cb810ff3d",
"type": "zigbee2mqtt-in",
"z": "f9a2fb576f0d360d",
"g": "5d202845936f0275",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Pantry Switch (TS0042)",
"device_id": "0xa4c138c2ae9ed430",
"state": "action",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 220,
"y": 1000,
"wires": [
[
"4673e2e3f2c0626f"
]
]
},
{
"id": "0bd6051323b66072",
"type": "zigbee2mqtt-in",
"z": "f9a2fb576f0d360d",
"g": "74596bdef53b62cf",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Kitchen Switch (TS0044)",
"device_id": "0xa4c1380bab38d546",
"state": "action",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 230,
"y": 1100,
"wires": [
[
"6aac621e2a9acf79"
]
]
},
{
"id": "6e30880884a2cdb2",
"type": "zigbee2mqtt-in",
"z": "f9a2fb576f0d360d",
"g": "5b22d521e762f0da",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Kitchen Veranda Switch (TS0043)",
"device_id": "0xa4c1383b7c24483a",
"state": "action",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 250,
"y": 1200,
"wires": [
[
"da7ab159be01b35c"
]
]
},
{
"id": "83bbabef65831016",
"type": "subflow:4dc13919bcc9d676",
"z": "f9a2fb576f0d360d",
"g": "4b06cbc568091f6f",
"name": "",
"env": [
{
"name": "switch_1",
"value": "hallway.sw_2",
"type": "str"
},
{
"name": "switch_2",
"value": "hallway.sw_1",
"type": "str"
}
],
"x": 1270,
"y": 220,
"wires": [
[
"629cbd7ce15bb9e3"
]
]
},
{
"id": "b9c07d22cbaae6a2",
"type": "subflow:4dc13919bcc9d676",
"z": "f9a2fb576f0d360d",
"g": "795d604329d51272",
"name": "",
"env": [
{
"name": "switch_1",
"value": "outSide.sw_1",
"type": "str"
}
],
"x": 1270,
"y": 320,
"wires": [
[
"629cbd7ce15bb9e3"
]
]
},
{
"id": "16eaca15570ff092",
"type": "subflow:4dc13919bcc9d676",
"z": "f9a2fb576f0d360d",
"g": "39f557d8eec2fbae",
"name": "",
"env": [
{
"name": "switch_1",
"value": "masterBedroom.sw_1",
"type": "str"
},
{
"name": "switch_2",
"value": "",
"type": "str"
},
{
"name": "switch_3",
"value": "masterBathroom.sw_1",
"type": "str"
},
{
"name": "switch_4",
"value": "masterBedroom.sw_2",
"type": "str"
}
],
"x": 1270,
"y": 420,
"wires": [
[
"629cbd7ce15bb9e3"
]
]
},
{
"id": "84272551b322cde2",
"type": "subflow:4dc13919bcc9d676",
"z": "f9a2fb576f0d360d",
"g": "68db2262f7c7313e",
"name": "",
"env": [
{
"name": "switch_1",
"value": "masterBathroom.sw_1",
"type": "str"
},
{
"name": "switch_2",
"value": "masterBathroom.sw_2",
"type": "str"
}
],
"x": 1270,
"y": 900,
"wires": [
[
"629cbd7ce15bb9e3"
]
]
},
{
"id": "4673e2e3f2c0626f",
"type": "subflow:4dc13919bcc9d676",
"z": "f9a2fb576f0d360d",
"g": "5d202845936f0275",
"name": "",
"env": [
{
"name": "switch_1",
"value": "hallway.sw_1",
"type": "str"
},
{
"name": "switch_2",
"value": "pantry.sw_1",
"type": "str"
}
],
"x": 1270,
"y": 1000,
"wires": [
[
"629cbd7ce15bb9e3"
]
]
},
{
"id": "6aac621e2a9acf79",
"type": "subflow:4dc13919bcc9d676",
"z": "f9a2fb576f0d360d",
"g": "74596bdef53b62cf",
"name": "",
"env": [
{
"name": "switch_1",
"value": "kitchen.sw_1",
"type": "str"
},
{
"name": "switch_2",
"value": "kitchen.sw_2",
"type": "str"
},
{
"name": "switch_3",
"value": "kitchen.sw_3",
"type": "str"
}
],
"x": 1270,
"y": 1100,
"wires": [
[
"629cbd7ce15bb9e3"
]
]
},
{
"id": "da7ab159be01b35c",
"type": "subflow:4dc13919bcc9d676",
"z": "f9a2fb576f0d360d",
"g": "5b22d521e762f0da",
"name": "",
"env": [
{
"name": "switch_1",
"value": "livingRoom.sw_1",
"type": "str"
},
{
"name": "switch_3",
"value": "outVeranda.sw_2",
"type": "str"
}
],
"x": 1270,
"y": 1200,
"wires": [
[
"629cbd7ce15bb9e3"
]
]
},
{
"id": "6f028b285108ff17",
"type": "subflow:4dc13919bcc9d676",
"z": "f9a2fb576f0d360d",
"g": "fb2d97888a83fc98",
"name": "",
"env": [
{
"name": "switch_1",
"value": "bedroom_2.sw_1",
"type": "str"
}
],
"x": 1270,
"y": 1300,
"wires": [
[
"629cbd7ce15bb9e3"
]
]
},
{
"id": "ef6df11582a22110",
"type": "subflow:4dc13919bcc9d676",
"z": "f9a2fb576f0d360d",
"g": "1166ae03751d953e",
"name": "",
"env": [
{
"name": "switch_1",
"value": "bathroom.sw_1",
"type": "str"
},
{
"name": "single",
"value": "bathroom.sw_1",
"type": "str"
}
],
"x": 1270,
"y": 1400,
"wires": [
[
"629cbd7ce15bb9e3"
]
]
},
{
"id": "82c1d5f7ae54b348",
"type": "zigbee2mqtt-in",
"z": "f9a2fb576f0d360d",
"g": "fb2d97888a83fc98",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Bedroom (TS0042)",
"device_id": "0xa4c1388b74d83cfa",
"state": "action",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 210,
"y": 1300,
"wires": [
[
"6f028b285108ff17"
]
]
},
{
"id": "774c15def7e6cf96",
"type": "zigbee2mqtt-in",
"z": "f9a2fb576f0d360d",
"g": "1166ae03751d953e",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Shower Switch (TS0041)",
"device_id": "0xa4c138cc9b54cec9",
"state": "action",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 230,
"y": 1400,
"wires": [
[
"ef6df11582a22110"
]
]
},
{
"id": "25cf5d71108cbbb4",
"type": "subflow:4dc13919bcc9d676",
"z": "f9a2fb576f0d360d",
"g": "5270af8a6312b29d",
"name": "",
"env": [
{
"name": "switch_1",
"value": "dinningRoom.sw_1",
"type": "str"
},
{
"name": "switch_3",
"value": "entrance.sw_1",
"type": "str"
},
{
"name": "switch_4",
"value": "entrance.sw_2",
"type": "str"
}
],
"x": 1270,
"y": 1500,
"wires": [
[
"629cbd7ce15bb9e3"
]
]
},
{
"id": "a330bf2f4d26c536",
"type": "subflow:4dc13919bcc9d676",
"z": "f9a2fb576f0d360d",
"g": "6809b1c79783ab0c",
"name": "",
"env": [
{
"name": "single",
"value": "guestWc.sw_1",
"type": "str"
}
],
"x": 1270,
"y": 1640,
"wires": [
[
"629cbd7ce15bb9e3"
]
]
},
{
"id": "cbcd3d741247b12b",
"type": "zigbee2mqtt-in",
"z": "f9a2fb576f0d360d",
"g": "5270af8a6312b29d",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Entrance Switch (TS0044)",
"device_id": "0xa4c138ceaa5681d5",
"state": "action",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 230,
"y": 1500,
"wires": [
[
"25cf5d71108cbbb4",
"0bf96ec77f6d1809"
]
]
},
{
"id": "398c06a48e4daa13",
"type": "zigbee2mqtt-in",
"z": "f9a2fb576f0d360d",
"g": "6809b1c79783ab0c",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Guest WC Switch (TS0041)",
"device_id": "0xa4c138d65f53037c",
"state": "action",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 240,
"y": 1640,
"wires": [
[
"a330bf2f4d26c536"
]
]
},
{
"id": "1633e8e6861be2e0",
"type": "zigbee2mqtt-in",
"z": "f9a2fb576f0d360d",
"g": "3db6f7ccc63a5f8b",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Basement Switch (TS0043)",
"device_id": "0xa4c13891821386eb",
"state": "action",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 230,
"y": 1740,
"wires": [
[
"9c36d1335b0f8ebb",
"7f48ed25c8ec1fce"
]
]
},
{
"id": "9c36d1335b0f8ebb",
"type": "subflow:4dc13919bcc9d676",
"z": "f9a2fb576f0d360d",
"g": "3db6f7ccc63a5f8b",
"name": "",
"env": [
{
"name": "switch_1",
"value": "dinningRoom.sw_4",
"type": "str"
},
{
"name": "single",
"value": "guestWc.sw_1",
"type": "str"
}
],
"x": 1270,
"y": 1740,
"wires": [
[
"629cbd7ce15bb9e3"
]
]
},
{
"id": "36d1d2c1e10100e7",
"type": "zigbee2mqtt-in",
"z": "f9a2fb576f0d360d",
"g": "41609eab5db77f0a",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Master Bedroom RODRET (E2201)",
"device_id": "0x6cfd22fffe66db44",
"state": "action",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 260,
"y": 2060,
"wires": [
[
"4c584ffba6a17ccb"
]
]
},
{
"id": "4c584ffba6a17ccb",
"type": "switch",
"z": "f9a2fb576f0d360d",
"g": "41609eab5db77f0a",
"name": "",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "on",
"vt": "str"
},
{
"t": "eq",
"v": "off",
"vt": "str"
},
{
"t": "eq",
"v": "brightness_move_up",
"vt": "str"
},
{
"t": "eq",
"v": "brightness_move_down",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 4,
"x": 590,
"y": 2120,
"wires": [
[
"6dd69a9285fc9583"
],
[
"6dd69a9285fc9583"
],
[
"c53543186fd45d8b"
],
[
"aadcf8d1921d77e6"
]
]
},
{
"id": "c53543186fd45d8b",
"type": "change",
"z": "f9a2fb576f0d360d",
"g": "41609eab5db77f0a",
"name": "",
"rules": [
{
"t": "set",
"p": "topic",
"pt": "msg",
"to": "masterBedroom",
"tot": "str"
},
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "sw_1",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 920,
"y": 2100,
"wires": [
[
"33eb6e0725214c0b"
]
]
},
{
"id": "33eb6e0725214c0b",
"type": "link out",
"z": "f9a2fb576f0d360d",
"g": "41609eab5db77f0a",
"name": "link out 15",
"mode": "link",
"links": [
"0bbcb269da9b75c7"
],
"x": 1325,
"y": 2100,
"wires": []
},
{
"id": "5df52e7f8217a6d9",
"type": "zigbee2mqtt-out",
"z": "f9a2fb576f0d360d",
"g": "41609eab5db77f0a",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Master Bedroom Spots (GL-C-006P)",
"device_id": "0xa4c138883e5d795c",
"command": "brightness",
"commandType": "z2m_cmd",
"payload": "payload",
"payloadType": "msg",
"optionsValue": "",
"optionsType": "nothing",
"x": 1190,
"y": 2060,
"wires": []
},
{
"id": "6dd69a9285fc9583",
"type": "function",
"z": "f9a2fb576f0d360d",
"g": "41609eab5db77f0a",
"name": "function 4",
"func": "// Initialize the counter\nlet counter = context.get('counter') || 10;\n\nif (msg.payload === \"on\") {\n msg.payload = counter;\n counter += 10;\n context.set('counter', counter);\n return msg;\n}\n\nif (msg.payload === \"off\") {\n counter -= 10;\n msg.payload = counter;\n context.set('counter', counter);\n return msg;\n}\n\n// Ignore other payloads\nreturn null;\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 840,
"y": 2060,
"wires": [
[
"5df52e7f8217a6d9"
]
]
},
{
"id": "3e5fabb6aa93449c",
"type": "zigbee2mqtt-out",
"z": "f9a2fb576f0d360d",
"g": "41609eab5db77f0a",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Master Bedroom Spots (GL-C-006P)",
"device_id": "0xa4c138883e5d795c",
"command": "state",
"commandType": "z2m_cmd",
"payload": "payload",
"payloadType": "msg",
"optionsValue": "",
"optionsType": "nothing",
"x": 1190,
"y": 2140,
"wires": []
},
{
"id": "aadcf8d1921d77e6",
"type": "change",
"z": "f9a2fb576f0d360d",
"g": "41609eab5db77f0a",
"name": "",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "off",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 920,
"y": 2140,
"wires": [
[
"3e5fabb6aa93449c"
]
]
},
{
"id": "109c390c131b09a8",
"type": "change",
"z": "f9a2fb576f0d360d",
"g": "39f557d8eec2fbae",
"name": "",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "toggle",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 880,
"y": 460,
"wires": [
[
"d02a9d4e0468bc67"
]
]
},
{
"id": "d02a9d4e0468bc67",
"type": "zigbee2mqtt-out",
"z": "f9a2fb576f0d360d",
"g": "39f557d8eec2fbae",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Master Bedroom Spots (GL-C-006P)",
"device_id": "0xa4c138883e5d795c",
"command": "state",
"commandType": "z2m_cmd",
"payload": "payload",
"payloadType": "msg",
"optionsValue": "",
"optionsType": "nothing",
"x": 1190,
"y": 460,
"wires": []
},
{
"id": "07e63813fb04b906",
"type": "change",
"z": "f9a2fb576f0d360d",
"g": "5270af8a6312b29d",
"name": "",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "toggle",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 820,
"y": 1540,
"wires": [
[
"4d3d4a82a512ca10"
]
]
},
{
"id": "4d3d4a82a512ca10",
"type": "zigbee2mqtt-out",
"z": "f9a2fb576f0d360d",
"g": "5270af8a6312b29d",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Dining Room Spots (GL-C-009P)",
"device_id": "0xa4c138df201f25a1",
"command": "state",
"commandType": "z2m_cmd",
"payload": "payload",
"payloadType": "msg",
"optionsValue": "",
"optionsType": "nothing",
"x": 1200,
"y": 1540,
"wires": []
},
{
"id": "46517eb4342b3d18",
"type": "zigbee2mqtt-in",
"z": "f9a2fb576f0d360d",
"g": "b6271f4a3284f8d9",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Living Room Door Switch (TS0044)",
"device_id": "0xa4c1383d7921827a",
"state": "action",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 260,
"y": 1920,
"wires": [
[
"a3d5be29d6effa34",
"701c1cd70874e615"
]
]
},
{
"id": "a3d5be29d6effa34",
"type": "subflow:4dc13919bcc9d676",
"z": "f9a2fb576f0d360d",
"g": "b6271f4a3284f8d9",
"name": "",
"env": [
{
"name": "switch_1",
"value": "livingRoom.sw_1",
"type": "str"
},
{
"name": "switch_2",
"value": "",
"type": "str"
},
{
"name": "switch_3",
"value": "",
"type": "str"
},
{
"name": "switch_4",
"value": "",
"type": "str"
},
{
"name": "single",
"value": "",
"type": "str"
}
],
"x": 550,
"y": 1920,
"wires": [
[
"629cbd7ce15bb9e3"
]
]
},
{
"id": "d23c32a704af639d",
"type": "change",
"z": "f9a2fb576f0d360d",
"g": "b6271f4a3284f8d9",
"name": "",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "toggle",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 720,
"y": 1960,
"wires": [
[
"68f7d3015de2dbab"
]
]
},
{
"id": "68f7d3015de2dbab",
"type": "zigbee2mqtt-out",
"z": "f9a2fb576f0d360d",
"g": "b6271f4a3284f8d9",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Living Room Spots (GL-C-006P)",
"device_id": "0xa4c13837f72f43ab",
"command": "state",
"commandType": "z2m_cmd",
"payload": "payload",
"payloadType": "msg",
"optionsValue": "",
"optionsType": "nothing",
"x": 1210,
"y": 1960,
"wires": []
},
{
"id": "fe5612a41399f1f5",
"type": "api-call-service",
"z": "f9a2fb576f0d360d",
"g": "3db6f7ccc63a5f8b",
"name": "",
"server": "29eb84a2708d96e0",
"version": 7,
"debugenabled": false,
"action": "switch.toggle",
"floorId": [],
"areaId": [],
"deviceId": [],
"entityId": [
"switch.basement_lights_switch_1"
],
"labelId": [],
"data": "",
"dataType": "jsonata",
"mergeContext": "",
"mustacheAltTags": false,
"outputProperties": [],
"queue": "none",
"blockInputOverrides": true,
"domain": "switch",
"service": "toggle",
"x": 1270,
"y": 1780,
"wires": [
[]
]
},
{
"id": "7f48ed25c8ec1fce",
"type": "switch",
"z": "f9a2fb576f0d360d",
"g": "3db6f7ccc63a5f8b",
"name": "",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "2_single",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 850,
"y": 1780,
"wires": [
[
"fe5612a41399f1f5"
]
]
},
{
"id": "ab17cf6a7d65fcb9",
"type": "inject",
"z": "f9a2fb576f0d360d",
"g": "3db6f7ccc63a5f8b",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 840,
"y": 1820,
"wires": [
[
"fe5612a41399f1f5"
]
]
},
{
"id": "0bf96ec77f6d1809",
"type": "switch",
"z": "f9a2fb576f0d360d",
"g": "5270af8a6312b29d",
"name": "",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "2_single",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 550,
"y": 1540,
"wires": [
[
"07e63813fb04b906"
]
]
},
{
"id": "2d6bcc49a2785fd6",
"type": "switch",
"z": "f9a2fb576f0d360d",
"g": "39f557d8eec2fbae",
"name": "",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "2_single",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 630,
"y": 460,
"wires": [
[
"109c390c131b09a8"
]
]
},
{
"id": "701c1cd70874e615",
"type": "switch",
"z": "f9a2fb576f0d360d",
"g": "b6271f4a3284f8d9",
"name": "",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "2_single",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 530,
"y": 1960,
"wires": [
[
"d23c32a704af639d"
]
]
},
{
"id": "0b112f9f314fa0bb",
"type": "zigbee2mqtt-in",
"z": "f9a2fb576f0d360d",
"g": "ef555db28dba4c46",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "0xa4c138332cc3da08 (TS0044)",
"device_id": "0xa4c138332cc3da08",
"state": "action",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 250,
"y": 560,
"wires": [
[
"a1f5a94baf1fbcd7",
"f0de9c882920d07c"
]
]
},
{
"id": "a1f5a94baf1fbcd7",
"type": "subflow:4dc13919bcc9d676",
"z": "f9a2fb576f0d360d",
"g": "ef555db28dba4c46",
"name": "",
"env": [
{
"name": "switch_1",
"value": "masterBedroom.sw_1",
"type": "str"
},
{
"name": "switch_2",
"value": "",
"type": "str"
},
{
"name": "switch_3",
"value": "masterBedroom.sw_3",
"type": "str"
},
{
"name": "switch_4",
"value": "masterBedroom.sw_5",
"type": "str"
}
],
"x": 1270,
"y": 560,
"wires": [
[
"629cbd7ce15bb9e3"
]
]
},
{
"id": "ae314d3d3457b679",
"type": "change",
"z": "f9a2fb576f0d360d",
"g": "ef555db28dba4c46",
"name": "",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "toggle",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 880,
"y": 600,
"wires": [
[
"0c35b08a3c7d347f"
]
]
},
{
"id": "0c35b08a3c7d347f",
"type": "zigbee2mqtt-out",
"z": "f9a2fb576f0d360d",
"g": "ef555db28dba4c46",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Master Bedroom Spots (GL-C-006P)",
"device_id": [],
"command": "state",
"commandType": "z2m_cmd",
"payload": "payload",
"payloadType": "msg",
"optionsValue": "",
"optionsType": "nothing",
"x": 1190,
"y": 600,
"wires": []
},
{
"id": "f0de9c882920d07c",
"type": "switch",
"z": "f9a2fb576f0d360d",
"g": "ef555db28dba4c46",
"name": "",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "2_single",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 630,
"y": 600,
"wires": [
[
"ae314d3d3457b679"
]
]
},
{
"id": "310f749a07eded9d",
"type": "zigbee2mqtt-in",
"z": "f9a2fb576f0d360d",
"g": "1756bd5d4ff2c23b",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "basement_switch_2 (TS0043)",
"device_id": "0xa4c138a1968db065",
"state": "action",
"outputAtStartup": true,
"filterChanges": false,
"enableMultiple": false,
"x": 240,
"y": 2240,
"wires": [
[
"d0febe343ef897ac",
"8cce4a0a7061ac87"
]
]
},
{
"id": "d0febe343ef897ac",
"type": "subflow:4dc13919bcc9d676",
"z": "f9a2fb576f0d360d",
"g": "1756bd5d4ff2c23b",
"name": "",
"env": [
{
"name": "switch_1",
"value": "dinningRoom.sw_4",
"type": "str"
},
{
"name": "single",
"value": "guestWc.sw_1",
"type": "str"
}
],
"x": 1270,
"y": 2240,
"wires": [
[
"629cbd7ce15bb9e3"
]
]
},
{
"id": "e1965a78e430acad",
"type": "api-call-service",
"z": "f9a2fb576f0d360d",
"g": "1756bd5d4ff2c23b",
"name": "",
"server": "29eb84a2708d96e0",
"version": 7,
"debugenabled": false,
"action": "switch.toggle",
"floorId": [],
"areaId": [],
"deviceId": [],
"entityId": [
"switch.basement_lights_switch_1"
],
"labelId": [],
"data": "",
"dataType": "jsonata",
"mergeContext": "",
"mustacheAltTags": false,
"outputProperties": [],
"queue": "none",
"blockInputOverrides": true,
"domain": "switch",
"service": "toggle",
"x": 1270,
"y": 2280,
"wires": [
[]
]
},
{
"id": "8cce4a0a7061ac87",
"type": "switch",
"z": "f9a2fb576f0d360d",
"g": "1756bd5d4ff2c23b",
"name": "",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "2_single",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 850,
"y": 2280,
"wires": [
[
"e1965a78e430acad"
]
]
},
{
"id": "d5cad6d8ca5fe08c",
"type": "inject",
"z": "f9a2fb576f0d360d",
"g": "1756bd5d4ff2c23b",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 840,
"y": 2320,
"wires": [
[
"e1965a78e430acad"
]
]
},
{
"id": "05ecf6f492d4a8cf",
"type": "inject",
"z": "6722d185624fd57a",
"g": "cc230a0894b116d3",
"name": "ON",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "ON",
"payloadType": "str",
"x": 230,
"y": 1020,
"wires": [
[
"301e955ac79a9326"
]
]
},
{
"id": "ad81a0918c31a862",
"type": "inject",
"z": "6722d185624fd57a",
"g": "cc230a0894b116d3",
"name": "OFF",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "OFF",
"payloadType": "str",
"x": 230,
"y": 1140,
"wires": [
[
"301e955ac79a9326"
]
]
},
{
"id": "7049d2e629127b0e",
"type": "api-current-state",
"z": "6722d185624fd57a",
"g": "cc230a0894b116d3",
"name": "",
"server": "29eb84a2708d96e0",
"version": 3,
"outputs": 2,
"halt_if": "off",
"halt_if_type": "str",
"halt_if_compare": "is",
"entity_id": "binary_sensor.front_lights",
"state_type": "str",
"blockInputOverrides": true,
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "outVeranda",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_1",
"valueType": "str"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 840,
"y": 1040,
"wires": [
[
"e44fa1b081b4aba7"
],
[]
]
},
{
"id": "e44fa1b081b4aba7",
"type": "link out",
"z": "6722d185624fd57a",
"g": "cc230a0894b116d3",
"name": "link out 21",
"mode": "link",
"links": [
"0bbcb269da9b75c7"
],
"x": 1085,
"y": 1060,
"wires": []
},
{
"id": "532476a808456423",
"type": "api-current-state",
"z": "6722d185624fd57a",
"g": "cc230a0894b116d3",
"name": "",
"server": "29eb84a2708d96e0",
"version": 3,
"outputs": 2,
"halt_if": "on",
"halt_if_type": "str",
"halt_if_compare": "is",
"entity_id": "binary_sensor.front_lights",
"state_type": "str",
"blockInputOverrides": true,
"outputProperties": [
{
"property": "topic",
"propertyType": "msg",
"value": "outVeranda",
"valueType": "str"
},
{
"property": "payload",
"propertyType": "msg",
"value": "sw_1",
"valueType": "str"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 840,
"y": 1100,
"wires": [
[
"e44fa1b081b4aba7"
],
[]
]
},
{
"id": "9e01966beafd582b",
"type": "cronplus",
"z": "6722d185624fd57a",
"d": true,
"g": "cc230a0894b116d3",
"name": "",
"outputField": "payload",
"timeZone": "",
"storeName": "",
"commandResponseMsgOutput": "fanOut",
"defaultLocation": "",
"defaultLocationType": "default",
"outputs": 4,
"options": [
{
"name": "ON",
"topic": "topic1",
"payloadType": "str",
"payload": "on",
"expressionType": "cron",
"expression": "0 0 20 * * *",
"location": "",
"offset": "0",
"solarType": "all",
"solarEvents": "sunrise,sunset"
},
{
"name": "OFF",
"topic": "topic2",
"payloadType": "str",
"payload": "off",
"expressionType": "cron",
"expression": "0 0 00 * * *",
"location": "",
"offset": "0",
"solarType": "all",
"solarEvents": "sunrise,sunset"
}
],
"x": 400,
"y": 1160,
"wires": [
[],
[],
[],
[]
]
},
{
"id": "905629455f4dd222",
"type": "zigbee2mqtt-out",
"z": "6722d185624fd57a",
"g": "b73455843d7a5a9f",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Front Water Valve (SWV)",
"device_id": "0x0ceff6fffe84e4bc",
"command": "state",
"commandType": "z2m_cmd",
"payload": "payload",
"payloadType": "msg",
"optionsValue": "",
"optionsType": "nothing",
"x": 1350,
"y": 460,
"wires": []
},
{
"id": "33e972f98673a6b6",
"type": "cronplus",
"z": "6722d185624fd57a",
"g": "b73455843d7a5a9f",
"name": "Olive Trees every 2 days at 19:00",
"outputField": "payload",
"timeZone": "",
"storeName": "file",
"commandResponseMsgOutput": "fanOut",
"defaultLocation": "",
"defaultLocationType": "default",
"outputs": 4,
"options": [
{
"name": "ON",
"topic": "front",
"payloadType": "default",
"payload": "",
"expressionType": "cron",
"expression": "20 6 */7 * *",
"location": "",
"offset": "0",
"solarType": "all",
"solarEvents": "sunrise,sunset"
},
{
"name": "OFF",
"topic": "front",
"payloadType": "default",
"payload": "",
"expressionType": "cron",
"expression": "30 6 */7 * *",
"location": "",
"offset": "0",
"solarType": "all",
"solarEvents": "sunrise,sunset"
}
],
"x": 240,
"y": 440,
"wires": [
[
"ab7182ad5c37be48"
],
[
"d51ae77e82bb86f0"
],
[],
[]
]
},
{
"id": "ab7182ad5c37be48",
"type": "change",
"z": "6722d185624fd57a",
"g": "b73455843d7a5a9f",
"name": "on",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "on",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 690,
"y": 420,
"wires": [
[
"905629455f4dd222"
]
]
},
{
"id": "d51ae77e82bb86f0",
"type": "change",
"z": "6722d185624fd57a",
"g": "b73455843d7a5a9f",
"name": "off",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "off",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 690,
"y": 460,
"wires": [
[
"905629455f4dd222"
]
]
},
{
"id": "b43dc5183a67d128",
"type": "zigbee2mqtt-out",
"z": "6722d185624fd57a",
"g": "b73455843d7a5a9f",
"name": "",
"server": "4e20fc347c658518",
"friendly_name": "Back Water Valve (SWV)",
"device_id": "0x7cc6b6fffe38a415",
"command": "state",
"commandType": "z2m_cmd",
"payload": "payload",
"payloadType": "msg",
"optionsValue": "",
"optionsType": "nothing",
"x": 1350,
"y": 540,
"wires": []
},
{
"id": "2896d687417bbc1d",
"type": "cronplus",
"z": "6722d185624fd57a",
"g": "b73455843d7a5a9f",
"name": "Citrus Trees every 2 days at 06:00",
"outputField": "payload",
"timeZone": "",
"storeName": "file",
"commandResponseMsgOutput": "fanOut",
"defaultLocation": "",
"defaultLocationType": "default",
"outputs": 4,
"options": [
{
"name": "ON",
"topic": "front",
"payloadType": "default",
"payload": "",
"expressionType": "cron",
"expression": "0 6 */2 * *",
"location": "",
"offset": "0",
"solarType": "all",
"solarEvents": "sunrise,sunset"
},
{
"name": "OFF",
"topic": "front",
"payloadType": "default",
"payload": "",
"expressionType": "cron",
"expression": "15 6 */2 * *",
"location": "",
"offset": "0",
"solarType": "all",
"solarEvents": "sunrise,sunset"
}
],
"x": 240,
"y": 560,
"wires": [
[
"1199fd928d0abd32"
],
[
"86153b2dba01756f"
],
[],
[]
]
},
{
"id": "1199fd928d0abd32",
"type": "change",
"z": "6722d185624fd57a",
"g": "b73455843d7a5a9f",
"name": "on",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "on",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 690,
"y": 540,
"wires": [
[
"b43dc5183a67d128"
]
]
},
{
"id": "86153b2dba01756f",
"type": "change",
"z": "6722d185624fd57a",
"g": "b73455843d7a5a9f",
"name": "off",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "off",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 690,
"y": 580,
"wires": [
[
"b43dc5183a67d128"
]
]
},
{
"id": "301e955ac79a9326",
"type": "bigtimer",
"z": "6722d185624fd57a",
"g": "cc230a0894b116d3",
"outtopic": "",
"outpayload1": "",
"outpayload2": "",
"name": "Big Timer",
"comment": "",
"lat": "34.660694",
"lon": "32.964306",
"starttime": "5004",
"endtime": "60",
"starttime2": "0",
"endtime2": "0",
"startoff": 0,
"endoff": 0,
"startoff2": 0,
"endoff2": 0,
"offs": 0,
"outtext1": "ON",
"outtext2": "OFF",
"timeout": 1440,
"sun": true,
"mon": true,
"tue": true,
"wed": true,
"thu": true,
"fri": true,
"sat": true,
"jan": true,
"feb": true,
"mar": true,
"apr": true,
"may": true,
"jun": true,
"jul": true,
"aug": true,
"sep": true,
"oct": true,
"nov": true,
"dec": true,
"day1": 0,
"month1": 0,
"day2": 0,
"month2": 0,
"day3": 0,
"month3": 0,
"day4": 0,
"month4": 0,
"day5": 0,
"month5": 0,
"day6": 0,
"month6": 0,
"day7": 0,
"month7": 0,
"day8": 0,
"month8": 0,
"day9": 0,
"month9": 0,
"day10": 0,
"month10": 0,
"day11": 0,
"month11": 0,
"day12": 0,
"month12": 0,
"d1": 0,
"w1": 0,
"d2": 0,
"w2": 0,
"d3": 0,
"w3": 0,
"d4": 0,
"w4": 0,
"d5": 0,
"w5": 0,
"d6": 0,
"w6": 0,
"xday1": 0,
"xmonth1": 0,
"xday2": 0,
"xmonth2": 0,
"xday3": 0,
"xmonth3": 0,
"xday4": 0,
"xmonth4": 0,
"xday5": 0,
"xmonth5": 0,
"xday6": 0,
"xmonth6": 0,
"xday7": 0,
"xmonth7": 0,
"xday8": 0,
"xmonth8": 0,
"xday9": 0,
"xmonth9": 0,
"xday10": 0,
"xmonth10": 0,
"xday11": 0,
"xmonth11": 0,
"xday12": 0,
"xmonth12": 0,
"xd1": 0,
"xw1": 0,
"xd2": 0,
"xw2": 0,
"xd3": 0,
"xw3": 0,
"xd4": 0,
"xw4": 0,
"xd5": 0,
"xw5": 0,
"xd6": 0,
"xw6": 0,
"suspend": false,
"random": false,
"randon1": false,
"randoff1": false,
"randon2": false,
"randoff2": false,
"repeat": true,
"atstart": true,
"odd": false,
"even": false,
"x": 400,
"y": 1080,
"wires": [
[
"7049d2e629127b0e",
"532476a808456423",
"434ef7e821c63223"
],
[
"0fdf497d70900d11"
],
[
"54161a78e09f85c3",
"7049d2e629127b0e",
"532476a808456423"
]
]
},
{
"id": "54161a78e09f85c3",
"type": "debug",
"z": "6722d185624fd57a",
"g": "cc230a0894b116d3",
"name": "debug 14",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 560,
"y": 1140,
"wires": []
},
{
"id": "0fdf497d70900d11",
"type": "debug",
"z": "6722d185624fd57a",
"g": "cc230a0894b116d3",
"name": "debug 21",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 680,
"y": 980,
"wires": []
},
{
"id": "434ef7e821c63223",
"type": "debug",
"z": "6722d185624fd57a",
"g": "cc230a0894b116d3",
"name": "debug 22",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 450,
"y": 980,
"wires": []
},
{
"id": "d97b1b86e0e0040e",
"type": "zigbee2mqtt-get",
"z": "6722d185624fd57a",
"g": "860e99939cf4fb5c",
"name": "Get Current Plug State",
"server": "4e20fc347c658518",
"friendly_name": "Living Room Plug (TS011F_plug_3)",
"device_id": "0xa4c138c205230a46",
"state": "state",
"enableMultiple": false,
"x": 1080,
"y": 1860,
"wires": [
[
"6fdd0a95dd76a2e8",
"be86177040153c9f"
]
]
},
{
"id": "3737a8c897de2221",
"type": "function",
"z": "6722d185624fd57a",
"g": "860e99939cf4fb5c",
"name": "Compare Desired vs Actual",
"func": "let input = msg.input || null;\n\nif (input === 1) {\n // BigTimer sets desired state\n // Validate state value before storing\n if (msg.payload === \"ON\" || msg.payload === \"OFF\") {\n flow.set(\"desired_state\", msg.payload);\n node.status({fill:\"blue\", shape:\"dot\", text:`Desired: ${msg.payload}`});\n node.warn(`[BigTimer] Desired state set to: ${msg.payload}`);\n } else {\n node.error(`[BigTimer] Invalid state value: ${msg.payload}`);\n node.status({fill:\"red\", shape:\"ring\", text:\"Invalid state\"});\n }\n return null;\n}\n\nif (input === 2) {\n // Zigbee GET input - check and sync state\n let desired = flow.get(\"desired_state\");\n let current = msg.state || \n msg.payload || \n msg.payload?.state || \n msg.data?.state ||\n null;\n\n // Log current status\n node.warn(`[Zigbee Check] Desired: ${desired}, Current: ${current}`);\n\n // Check if states are available\n if (!desired) {\n node.warn(\"[Zigbee Check] No desired state set yet\");\n node.status({fill:\"yellow\", shape:\"ring\", text:\"No desired state\"});\n return null;\n }\n\n if (!current) {\n node.error(\"[Zigbee Check] Current state is undefined\");\n node.status({fill:\"red\", shape:\"ring\", text:\"No current state\"});\n return null;\n }\n\n // Check if sync is needed\n if (desired === \"ON\" && current !== \"ON\") {\n node.warn(`[Zigbee Check] State mismatch - sending ON command`);\n node.status({fill:\"green\", shape:\"dot\", text:\"Syncing → ON\"});\n return { payload: \"ON\" };\n }\n \n if (desired === \"OFF\" && current !== \"OFF\") {\n node.warn(`[Zigbee Check] State mismatch - sending OFF command`);\n node.status({fill:\"green\", shape:\"dot\", text:\"Syncing → OFF\"});\n return { payload: \"OFF\" };\n }\n\n // States match - no action needed\n node.status({fill:\"green\", shape:\"ring\", text:`Synced: ${current}`});\n node.warn(`[Zigbee Check] States match - no action needed`);\n return null;\n}\n\n// Invalid input\nnode.error(`Invalid input value: ${input}`);\nnode.status({fill:\"red\", shape:\"ring\", text:\"Invalid input\"});\nreturn null;\n",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1580,
"y": 1880,
"wires": [
[
"ca74d224370a0b5a",
"893d9228d166c0d2"
]
]
},
{
"id": "ca74d224370a0b5a",
"type": "zigbee2mqtt-out",
"z": "6722d185624fd57a",
"g": "860e99939cf4fb5c",
"name": "Set Plug State",
"server": "4e20fc347c658518",
"friendly_name": "Living Room Plug (TS011F_plug_3)",
"device_id": "0xa4c138c205230a46",
"command": "state",
"commandType": "z2m_cmd",
"payload": "payload",
"payloadType": "msg",
"optionsValue": "",
"optionsType": "nothing",
"x": 1820,
"y": 1880,
"wires": []
},
{
"id": "3a8262144b91d661",
"type": "inject",
"z": "6722d185624fd57a",
"g": "860e99939cf4fb5c",
"name": "OFF",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "OFF",
"payloadType": "str",
"x": 750,
"y": 1960,
"wires": [
[
"01df5278eead8a98"
]
]
},
{
"id": "d20a28e1dea2fcde",
"type": "inject",
"z": "6722d185624fd57a",
"g": "860e99939cf4fb5c",
"name": "ON",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "ON",
"payloadType": "str",
"x": 750,
"y": 1840,
"wires": [
[
"01df5278eead8a98"
]
]
},
{
"id": "01df5278eead8a98",
"type": "bigtimer",
"z": "6722d185624fd57a",
"g": "860e99939cf4fb5c",
"outtopic": "",
"outpayload1": "",
"outpayload2": "",
"name": "Big Timer",
"comment": "",
"lat": "34.660694",
"lon": "32.964306",
"starttime": "960",
"endtime": "60",
"starttime2": "0",
"endtime2": "0",
"startoff": 0,
"endoff": 0,
"startoff2": 0,
"endoff2": 0,
"offs": 0,
"outtext1": "ON",
"outtext2": "OFF",
"timeout": 1440,
"sun": true,
"mon": true,
"tue": true,
"wed": true,
"thu": true,
"fri": true,
"sat": true,
"jan": true,
"feb": true,
"mar": true,
"apr": true,
"may": true,
"jun": true,
"jul": true,
"aug": true,
"sep": true,
"oct": true,
"nov": true,
"dec": true,
"day1": 0,
"month1": 0,
"day2": 0,
"month2": 0,
"day3": 0,
"month3": 0,
"day4": 0,
"month4": 0,
"day5": 0,
"month5": 0,
"day6": 0,
"month6": 0,
"day7": 0,
"month7": 0,
"day8": 0,
"month8": 0,
"day9": 0,
"month9": 0,
"day10": 0,
"month10": 0,
"day11": 0,
"month11": 0,
"day12": 0,
"month12": 0,
"d1": 0,
"w1": 0,
"d2": 0,
"w2": 0,
"d3": 0,
"w3": 0,
"d4": 0,
"w4": 0,
"d5": 0,
"w5": 0,
"d6": 0,
"w6": 0,
"xday1": 0,
"xmonth1": 0,
"xday2": 0,
"xmonth2": 0,
"xday3": 0,
"xmonth3": 0,
"xday4": 0,
"xmonth4": 0,
"xday5": 0,
"xmonth5": 0,
"xday6": 0,
"xmonth6": 0,
"xday7": 0,
"xmonth7": 0,
"xday8": 0,
"xmonth8": 0,
"xday9": 0,
"xmonth9": 0,
"xday10": 0,
"xmonth10": 0,
"xday11": 0,
"xmonth11": 0,
"xday12": 0,
"xmonth12": 0,
"xd1": 0,
"xw1": 0,
"xd2": 0,
"xw2": 0,
"xd3": 0,
"xw3": 0,
"xd4": 0,
"xw4": 0,
"xd5": 0,
"xw5": 0,
"xd6": 0,
"xw6": 0,
"suspend": false,
"random": false,
"randon1": false,
"randoff1": false,
"randon2": false,
"randoff2": false,
"repeat": true,
"atstart": true,
"odd": false,
"even": false,
"x": 880,
"y": 1900,
"wires": [
[],
[],
[
"d97b1b86e0e0040e",
"1460ed0d062f8b73"
]
]
},
{
"id": "1460ed0d062f8b73",
"type": "change",
"z": "6722d185624fd57a",
"g": "860e99939cf4fb5c",
"name": "Tag BigTimer Input",
"rules": [
{
"t": "set",
"p": "input",
"pt": "msg",
"to": "1",
"tot": "num"
}
],
"x": 1310,
"y": 1900,
"wires": [
[
"3737a8c897de2221",
"bb1639973b4a6a05"
]
]
},
{
"id": "6fdd0a95dd76a2e8",
"type": "change",
"z": "6722d185624fd57a",
"g": "860e99939cf4fb5c",
"name": "Tag Zigbee Input",
"rules": [
{
"t": "set",
"p": "input",
"pt": "msg",
"to": "2",
"tot": "num"
}
],
"x": 1310,
"y": 1860,
"wires": [
[
"3737a8c897de2221",
"800cb2f6a21c882f"
]
]
},
{
"id": "bb1639973b4a6a05",
"type": "debug",
"z": "6722d185624fd57a",
"g": "860e99939cf4fb5c",
"name": "debug 23",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1560,
"y": 2020,
"wires": []
},
{
"id": "800cb2f6a21c882f",
"type": "debug",
"z": "6722d185624fd57a",
"g": "860e99939cf4fb5c",
"name": "debug 24",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1540,
"y": 1960,
"wires": []
},
{
"id": "893d9228d166c0d2",
"type": "debug",
"z": "6722d185624fd57a",
"g": "860e99939cf4fb5c",
"name": "debug 25",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1750,
"y": 1980,
"wires": []
},
{
"id": "be86177040153c9f",
"type": "debug",
"z": "6722d185624fd57a",
"g": "860e99939cf4fb5c",
"name": "debug 26",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1230,
"y": 1720,
"wires": []
},
{
"id": "6fb9cc41c7b14fac",
"type": "link out",
"z": "31693504fcbbd954",
"name": "link out 23",
"mode": "link",
"links": [
"c6162cb59e21491f"
],
"x": 2105,
"y": 880,
"wires": []
},
{
"id": "func_node",
"type": "function",
"z": "31693504fcbbd954",
"name": "Build JSON true/false",
"func": "let input = msg.payload;\nlet parts = input.split(\".\");\nif (parts.length !== 2) {\n node.error(\"Invalid input format. Expected room.switch\", msg);\n return null;\n}\n\nlet room = parts[0];\nlet sw = parts[1];\n\nlet onMsg = { payload: { [room]: { [sw]: true } } };\nnode.send(onMsg);\n\nlet offMsg = { payload: { [room]: { [sw]: false } } };\nsetTimeout(() => { node.send(offMsg); }, 1000);\n\nreturn null;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1920,
"y": 880,
"wires": [
[
"debug_node",
"6fb9cc41c7b14fac"
]
]
},
{
"id": "debug_node",
"type": "debug",
"z": "31693504fcbbd954",
"name": "Output",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"x": 2110,
"y": 920,
"wires": []
},
{
"id": "btn_masterBedroom_all_off",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "masterBedroom all_off",
"group": "group_masterBedroom",
"order": 1,
"width": 0,
"height": 0,
"label": "all_off",
"payload": "masterBedroom.all_off",
"payloadType": "str",
"topic": "",
"x": 140,
"y": 940,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_masterBedroom_all_on",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "masterBedroom all_on",
"group": "group_masterBedroom",
"order": 2,
"width": 0,
"height": 0,
"label": "all_on",
"payload": "masterBedroom.all_on",
"payloadType": "str",
"topic": "",
"x": 140,
"y": 980,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_masterBedroom_sw_1",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "masterBedroom sw_1",
"group": "group_masterBedroom",
"order": 3,
"width": 0,
"height": 0,
"label": "sw_1",
"payload": "masterBedroom.sw_1",
"payloadType": "str",
"topic": "",
"x": 140,
"y": 1020,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_masterBedroom_sw_2",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "masterBedroom sw_2",
"group": "group_masterBedroom",
"order": 4,
"width": 0,
"height": 0,
"label": "sw_2",
"payload": "masterBedroom.sw_2",
"payloadType": "str",
"topic": "",
"x": 140,
"y": 1060,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_masterBedroom_sw_3",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "masterBedroom sw_3",
"group": "group_masterBedroom",
"order": 5,
"width": 0,
"height": 0,
"label": "sw_3",
"payload": "masterBedroom.sw_3",
"payloadType": "str",
"topic": "",
"x": 140,
"y": 1100,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_masterBedroom_sw_4",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "masterBedroom sw_4",
"group": "group_masterBedroom",
"order": 6,
"width": 0,
"height": 0,
"label": "sw_4",
"payload": "masterBedroom.sw_4",
"payloadType": "str",
"topic": "",
"x": 140,
"y": 1140,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_masterBedroom_sw_5",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "masterBedroom sw_5",
"group": "group_masterBedroom",
"order": 7,
"width": 0,
"height": 0,
"label": "sw_5",
"payload": "masterBedroom.sw_5",
"payloadType": "str",
"topic": "",
"x": 140,
"y": 1180,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_masterBedroom_sw_6",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "masterBedroom sw_6",
"group": "group_masterBedroom",
"order": 8,
"width": 0,
"height": 0,
"label": "sw_6",
"payload": "masterBedroom.sw_6",
"payloadType": "str",
"topic": "",
"x": 140,
"y": 1220,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_masterBathroom_all_off",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "masterBathroom all_off",
"group": "group_masterBathroom",
"order": 1,
"width": 0,
"height": 0,
"label": "all_off",
"payload": "masterBathroom.all_off",
"payloadType": "str",
"topic": "",
"x": 390,
"y": 940,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_masterBathroom_all_on",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "masterBathroom all_on",
"group": "group_masterBathroom",
"order": 2,
"width": 0,
"height": 0,
"label": "all_on",
"payload": "masterBathroom.all_on",
"payloadType": "str",
"topic": "",
"x": 390,
"y": 980,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_masterBathroom_sw_1",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "masterBathroom sw_1",
"group": "group_masterBathroom",
"order": 3,
"width": 0,
"height": 0,
"label": "sw_1",
"payload": "masterBathroom.sw_1",
"payloadType": "str",
"topic": "",
"x": 380,
"y": 1020,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_masterBathroom_sw_2",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "masterBathroom sw_2",
"group": "group_masterBathroom",
"order": 4,
"width": 0,
"height": 0,
"label": "sw_2",
"payload": "masterBathroom.sw_2",
"payloadType": "str",
"topic": "",
"x": 380,
"y": 1060,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_masterBathroom_sw_3",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "masterBathroom sw_3",
"group": "group_masterBathroom",
"order": 5,
"width": 0,
"height": 0,
"label": "sw_3",
"payload": "masterBathroom.sw_3",
"payloadType": "str",
"topic": "",
"x": 380,
"y": 1100,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_masterBathroom_sw_4",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "masterBathroom sw_4",
"group": "group_masterBathroom",
"order": 6,
"width": 0,
"height": 0,
"label": "sw_4",
"payload": "masterBathroom.sw_4",
"payloadType": "str",
"topic": "",
"x": 380,
"y": 1140,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_masterBathroom_sw_5",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "masterBathroom sw_5",
"group": "group_masterBathroom",
"order": 7,
"width": 0,
"height": 0,
"label": "sw_5",
"payload": "masterBathroom.sw_5",
"payloadType": "str",
"topic": "",
"x": 380,
"y": 1180,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_masterBathroom_sw_6",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "masterBathroom sw_6",
"group": "group_masterBathroom",
"order": 8,
"width": 0,
"height": 0,
"label": "sw_6",
"payload": "masterBathroom.sw_6",
"payloadType": "str",
"topic": "",
"x": 380,
"y": 1220,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bedroom_1_all_off",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bedroom_1 all_off",
"group": "group_bedroom_1",
"order": 1,
"width": 0,
"height": 0,
"label": "all_off",
"payload": "bedroom_1.all_off",
"payloadType": "str",
"topic": "",
"x": 630,
"y": 940,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bedroom_1_all_on",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bedroom_1 all_on",
"group": "group_bedroom_1",
"order": 2,
"width": 0,
"height": 0,
"label": "all_on",
"payload": "bedroom_1.all_on",
"payloadType": "str",
"topic": "",
"x": 630,
"y": 980,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bedroom_1_sw_1",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bedroom_1 sw_1",
"group": "group_bedroom_1",
"order": 3,
"width": 0,
"height": 0,
"label": "sw_1",
"payload": "bedroom_1.sw_1",
"payloadType": "str",
"topic": "",
"x": 630,
"y": 1020,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bedroom_1_sw_2",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bedroom_1 sw_2",
"group": "group_bedroom_1",
"order": 4,
"width": 0,
"height": 0,
"label": "sw_2",
"payload": "bedroom_1.sw_2",
"payloadType": "str",
"topic": "",
"x": 630,
"y": 1060,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bedroom_1_sw_3",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bedroom_1 sw_3",
"group": "group_bedroom_1",
"order": 5,
"width": 0,
"height": 0,
"label": "sw_3",
"payload": "bedroom_1.sw_3",
"payloadType": "str",
"topic": "",
"x": 630,
"y": 1100,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bedroom_1_sw_4",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bedroom_1 sw_4",
"group": "group_bedroom_1",
"order": 6,
"width": 0,
"height": 0,
"label": "sw_4",
"payload": "bedroom_1.sw_4",
"payloadType": "str",
"topic": "",
"x": 630,
"y": 1140,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bedroom_1_sw_5",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bedroom_1 sw_5",
"group": "group_bedroom_1",
"order": 7,
"width": 0,
"height": 0,
"label": "sw_5",
"payload": "bedroom_1.sw_5",
"payloadType": "str",
"topic": "",
"x": 630,
"y": 1180,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bedroom_1_sw_6",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bedroom_1 sw_6",
"group": "group_bedroom_1",
"order": 8,
"width": 0,
"height": 0,
"label": "sw_6",
"payload": "bedroom_1.sw_6",
"payloadType": "str",
"topic": "",
"x": 630,
"y": 1220,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bedroom_2_all_off",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bedroom_2 all_off",
"group": "group_bedroom_2",
"order": 1,
"width": 0,
"height": 0,
"label": "all_off",
"payload": "bedroom_2.all_off",
"payloadType": "str",
"topic": "",
"x": 1050,
"y": 940,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bedroom_2_all_on",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bedroom_2 all_on",
"group": "group_bedroom_2",
"order": 2,
"width": 0,
"height": 0,
"label": "all_on",
"payload": "bedroom_2.all_on",
"payloadType": "str",
"topic": "",
"x": 1050,
"y": 980,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bedroom_2_sw_1",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bedroom_2 sw_1",
"group": "group_bedroom_2",
"order": 3,
"width": 0,
"height": 0,
"label": "sw_1",
"payload": "bedroom_2.sw_1",
"payloadType": "str",
"topic": "",
"x": 1050,
"y": 1020,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bedroom_2_sw_2",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bedroom_2 sw_2",
"group": "group_bedroom_2",
"order": 4,
"width": 0,
"height": 0,
"label": "sw_2",
"payload": "bedroom_2.sw_2",
"payloadType": "str",
"topic": "",
"x": 1050,
"y": 1060,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bedroom_2_sw_3",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bedroom_2 sw_3",
"group": "group_bedroom_2",
"order": 5,
"width": 0,
"height": 0,
"label": "sw_3",
"payload": "bedroom_2.sw_3",
"payloadType": "str",
"topic": "",
"x": 1050,
"y": 1100,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bedroom_2_sw_4",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bedroom_2 sw_4",
"group": "group_bedroom_2",
"order": 6,
"width": 0,
"height": 0,
"label": "sw_4",
"payload": "bedroom_2.sw_4",
"payloadType": "str",
"topic": "",
"x": 1050,
"y": 1140,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bedroom_2_sw_5",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bedroom_2 sw_5",
"group": "group_bedroom_2",
"order": 7,
"width": 0,
"height": 0,
"label": "sw_5",
"payload": "bedroom_2.sw_5",
"payloadType": "str",
"topic": "",
"x": 1050,
"y": 1180,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bedroom_2_sw_6",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bedroom_2 sw_6",
"group": "group_bedroom_2",
"order": 8,
"width": 0,
"height": 0,
"label": "sw_6",
"payload": "bedroom_2.sw_6",
"payloadType": "str",
"topic": "",
"x": 1050,
"y": 1220,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bathroom_all_off",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bathroom all_off",
"group": "group_bathroom",
"order": 1,
"width": 0,
"height": 0,
"label": "all_off",
"payload": "bathroom.all_off",
"payloadType": "str",
"topic": "",
"x": 1680,
"y": 940,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bathroom_all_on",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bathroom all_on",
"group": "group_bathroom",
"order": 2,
"width": 0,
"height": 0,
"label": "all_on",
"payload": "bathroom.all_on",
"payloadType": "str",
"topic": "",
"x": 1680,
"y": 980,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bathroom_sw_1",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bathroom sw_1",
"group": "group_bathroom",
"order": 3,
"width": 0,
"height": 0,
"label": "sw_1",
"payload": "bathroom.sw_1",
"payloadType": "str",
"topic": "",
"x": 1680,
"y": 1020,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bathroom_sw_2",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bathroom sw_2",
"group": "group_bathroom",
"order": 4,
"width": 0,
"height": 0,
"label": "sw_2",
"payload": "bathroom.sw_2",
"payloadType": "str",
"topic": "",
"x": 1680,
"y": 1060,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bathroom_sw_3",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bathroom sw_3",
"group": "group_bathroom",
"order": 5,
"width": 0,
"height": 0,
"label": "sw_3",
"payload": "bathroom.sw_3",
"payloadType": "str",
"topic": "",
"x": 1680,
"y": 1100,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bathroom_sw_4",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bathroom sw_4",
"group": "group_bathroom",
"order": 6,
"width": 0,
"height": 0,
"label": "sw_4",
"payload": "bathroom.sw_4",
"payloadType": "str",
"topic": "",
"x": 1680,
"y": 1140,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bathroom_sw_5",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bathroom sw_5",
"group": "group_bathroom",
"order": 7,
"width": 0,
"height": 0,
"label": "sw_5",
"payload": "bathroom.sw_5",
"payloadType": "str",
"topic": "",
"x": 1680,
"y": 1180,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_bathroom_sw_6",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "bathroom sw_6",
"group": "group_bathroom",
"order": 8,
"width": 0,
"height": 0,
"label": "sw_6",
"payload": "bathroom.sw_6",
"payloadType": "str",
"topic": "",
"x": 1680,
"y": 1220,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_hallway_all_off",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "hallway all_off",
"group": "group_hallway",
"order": 1,
"width": 0,
"height": 0,
"label": "all_off",
"payload": "hallway.all_off",
"payloadType": "str",
"topic": "",
"x": 840,
"y": 940,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_hallway_all_on",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "hallway all_on",
"group": "group_hallway",
"order": 2,
"width": 0,
"height": 0,
"label": "all_on",
"payload": "hallway.all_on",
"payloadType": "str",
"topic": "",
"x": 840,
"y": 980,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_hallway_sw_1",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "hallway sw_1",
"group": "group_hallway",
"order": 3,
"width": 0,
"height": 0,
"label": "sw_1",
"payload": "hallway.sw_1",
"payloadType": "str",
"topic": "",
"x": 830,
"y": 1020,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_hallway_sw_2",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "hallway sw_2",
"group": "group_hallway",
"order": 4,
"width": 0,
"height": 0,
"label": "sw_2",
"payload": "hallway.sw_2",
"payloadType": "str",
"topic": "",
"x": 830,
"y": 1060,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_hallway_sw_3",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "hallway sw_3",
"group": "group_hallway",
"order": 5,
"width": 0,
"height": 0,
"label": "sw_3",
"payload": "hallway.sw_3",
"payloadType": "str",
"topic": "",
"x": 830,
"y": 1100,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_hallway_sw_4",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "hallway sw_4",
"group": "group_hallway",
"order": 6,
"width": 0,
"height": 0,
"label": "sw_4",
"payload": "hallway.sw_4",
"payloadType": "str",
"topic": "",
"x": 830,
"y": 1140,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_hallway_sw_5",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "hallway sw_5",
"group": "group_hallway",
"order": 7,
"width": 0,
"height": 0,
"label": "sw_5",
"payload": "hallway.sw_5",
"payloadType": "str",
"topic": "",
"x": 830,
"y": 1180,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_hallway_sw_6",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "hallway sw_6",
"group": "group_hallway",
"order": 8,
"width": 0,
"height": 0,
"label": "sw_6",
"payload": "hallway.sw_6",
"payloadType": "str",
"topic": "",
"x": 830,
"y": 1220,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_pantry_all_off",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "pantry all_off",
"group": "group_pantry",
"order": 1,
"width": 0,
"height": 0,
"label": "all_off",
"payload": "pantry.all_off",
"payloadType": "str",
"topic": "",
"x": 1470,
"y": 940,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_pantry_all_on",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "pantry all_on",
"group": "group_pantry",
"order": 2,
"width": 0,
"height": 0,
"label": "all_on",
"payload": "pantry.all_on",
"payloadType": "str",
"topic": "",
"x": 1470,
"y": 980,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_pantry_sw_1",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "pantry sw_1",
"group": "group_pantry",
"order": 3,
"width": 0,
"height": 0,
"label": "sw_1",
"payload": "pantry.sw_1",
"payloadType": "str",
"topic": "",
"x": 1470,
"y": 1020,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_pantry_sw_2",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "pantry sw_2",
"group": "group_pantry",
"order": 4,
"width": 0,
"height": 0,
"label": "sw_2",
"payload": "pantry.sw_2",
"payloadType": "str",
"topic": "",
"x": 1470,
"y": 1060,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_pantry_sw_3",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "pantry sw_3",
"group": "group_pantry",
"order": 5,
"width": 0,
"height": 0,
"label": "sw_3",
"payload": "pantry.sw_3",
"payloadType": "str",
"topic": "",
"x": 1470,
"y": 1100,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_pantry_sw_4",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "pantry sw_4",
"group": "group_pantry",
"order": 6,
"width": 0,
"height": 0,
"label": "sw_4",
"payload": "pantry.sw_4",
"payloadType": "str",
"topic": "",
"x": 1470,
"y": 1140,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_pantry_sw_5",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "pantry sw_5",
"group": "group_pantry",
"order": 7,
"width": 0,
"height": 0,
"label": "sw_5",
"payload": "pantry.sw_5",
"payloadType": "str",
"topic": "",
"x": 1470,
"y": 1180,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_pantry_sw_6",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "pantry sw_6",
"group": "group_pantry",
"order": 8,
"width": 0,
"height": 0,
"label": "sw_6",
"payload": "pantry.sw_6",
"payloadType": "str",
"topic": "",
"x": 1470,
"y": 1220,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_kitchen_all_off",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "kitchen all_off",
"group": "group_kitchen",
"order": 1,
"width": 0,
"height": 0,
"label": "all_off",
"payload": "kitchen.all_off",
"payloadType": "str",
"topic": "",
"x": 1580,
"y": 580,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_kitchen_all_on",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "kitchen all_on",
"group": "group_kitchen",
"order": 2,
"width": 0,
"height": 0,
"label": "all_on",
"payload": "kitchen.all_on",
"payloadType": "str",
"topic": "",
"x": 1580,
"y": 620,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_kitchen_sw_1",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "kitchen sw_1",
"group": "group_kitchen",
"order": 3,
"width": 0,
"height": 0,
"label": "sw_1",
"payload": "kitchen.sw_1",
"payloadType": "str",
"topic": "",
"x": 1570,
"y": 660,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_kitchen_sw_2",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "kitchen sw_2",
"group": "group_kitchen",
"order": 4,
"width": 0,
"height": 0,
"label": "sw_2",
"payload": "kitchen.sw_2",
"payloadType": "str",
"topic": "",
"x": 1570,
"y": 700,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_kitchen_sw_3",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "kitchen sw_3",
"group": "group_kitchen",
"order": 5,
"width": 0,
"height": 0,
"label": "sw_3",
"payload": "kitchen.sw_3",
"payloadType": "str",
"topic": "",
"x": 1570,
"y": 740,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_kitchen_sw_4",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "kitchen sw_4",
"group": "group_kitchen",
"order": 6,
"width": 0,
"height": 0,
"label": "sw_4",
"payload": "kitchen.sw_4",
"payloadType": "str",
"topic": "",
"x": 1570,
"y": 780,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_kitchen_sw_5",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "kitchen sw_5",
"group": "group_kitchen",
"order": 7,
"width": 0,
"height": 0,
"label": "sw_5",
"payload": "kitchen.sw_5",
"payloadType": "str",
"topic": "",
"x": 1570,
"y": 820,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_kitchen_sw_6",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "kitchen sw_6",
"group": "group_kitchen",
"order": 8,
"width": 0,
"height": 0,
"label": "sw_6",
"payload": "kitchen.sw_6",
"payloadType": "str",
"topic": "",
"x": 1570,
"y": 860,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_livingRoom_all_off",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "livingRoom all_off",
"group": "group_livingRoom",
"order": 1,
"width": 0,
"height": 0,
"label": "all_off",
"payload": "livingRoom.all_off",
"payloadType": "str",
"topic": "",
"x": 1350,
"y": 580,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_livingRoom_all_on",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "livingRoom all_on",
"group": "group_livingRoom",
"order": 2,
"width": 0,
"height": 0,
"label": "all_on",
"payload": "livingRoom.all_on",
"payloadType": "str",
"topic": "",
"x": 1350,
"y": 620,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_livingRoom_sw_1",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "livingRoom sw_1",
"group": "group_livingRoom",
"order": 3,
"width": 0,
"height": 0,
"label": "sw_1",
"payload": "livingRoom.sw_1",
"payloadType": "str",
"topic": "",
"x": 1350,
"y": 660,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_livingRoom_sw_2",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "livingRoom sw_2",
"group": "group_livingRoom",
"order": 4,
"width": 0,
"height": 0,
"label": "sw_2",
"payload": "livingRoom.sw_2",
"payloadType": "str",
"topic": "",
"x": 1350,
"y": 700,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_livingRoom_sw_3",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "livingRoom sw_3",
"group": "group_livingRoom",
"order": 5,
"width": 0,
"height": 0,
"label": "sw_3",
"payload": "livingRoom.sw_3",
"payloadType": "str",
"topic": "",
"x": 1350,
"y": 740,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_livingRoom_sw_4",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "livingRoom sw_4",
"group": "group_livingRoom",
"order": 6,
"width": 0,
"height": 0,
"label": "sw_4",
"payload": "livingRoom.sw_4",
"payloadType": "str",
"topic": "",
"x": 1350,
"y": 780,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_livingRoom_sw_5",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "livingRoom sw_5",
"group": "group_livingRoom",
"order": 7,
"width": 0,
"height": 0,
"label": "sw_5",
"payload": "livingRoom.sw_5",
"payloadType": "str",
"topic": "",
"x": 1350,
"y": 820,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_livingRoom_sw_6",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "livingRoom sw_6",
"group": "group_livingRoom",
"order": 8,
"width": 0,
"height": 0,
"label": "sw_6",
"payload": "livingRoom.sw_6",
"payloadType": "str",
"topic": "",
"x": 1350,
"y": 860,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_dinningRoom_all_off",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "dinningRoom all_off",
"group": "group_dinningRoom",
"order": 1,
"width": 0,
"height": 0,
"label": "all_off",
"payload": "dinningRoom.all_off",
"payloadType": "str",
"topic": "",
"x": 1150,
"y": 580,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_dinningRoom_all_on",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "dinningRoom all_on",
"group": "group_dinningRoom",
"order": 2,
"width": 0,
"height": 0,
"label": "all_on",
"payload": "dinningRoom.all_on",
"payloadType": "str",
"topic": "",
"x": 1140,
"y": 620,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_dinningRoom_sw_1",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "dinningRoom sw_1",
"group": "group_dinningRoom",
"order": 3,
"width": 0,
"height": 0,
"label": "sw_1",
"payload": "dinningRoom.sw_1",
"payloadType": "str",
"topic": "",
"x": 1150,
"y": 660,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_dinningRoom_sw_2",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "dinningRoom sw_2",
"group": "group_dinningRoom",
"order": 4,
"width": 0,
"height": 0,
"label": "sw_2",
"payload": "dinningRoom.sw_2",
"payloadType": "str",
"topic": "",
"x": 1150,
"y": 700,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_dinningRoom_sw_3",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "dinningRoom sw_3",
"group": "group_dinningRoom",
"order": 5,
"width": 0,
"height": 0,
"passthru": false,
"label": "sw_3",
"tooltip": "",
"color": "",
"bgcolor": "",
"className": "",
"icon": "",
"payload": "dinningRoom.sw_3",
"payloadType": "str",
"topic": "",
"topicType": "str",
"x": 1150,
"y": 740,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_dinningRoom_sw_4",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "dinningRoom sw_4",
"group": "group_dinningRoom",
"order": 6,
"width": 0,
"height": 0,
"label": "sw_4",
"payload": "dinningRoom.sw_4",
"payloadType": "str",
"topic": "",
"x": 1150,
"y": 780,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_dinningRoom_sw_5",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "dinningRoom sw_5",
"group": "group_dinningRoom",
"order": 7,
"width": 0,
"height": 0,
"label": "sw_5",
"payload": "dinningRoom.sw_5",
"payloadType": "str",
"topic": "",
"x": 1150,
"y": 820,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_dinningRoom_sw_6",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "dinningRoom sw_6",
"group": "group_dinningRoom",
"order": 8,
"width": 0,
"height": 0,
"label": "sw_6",
"payload": "dinningRoom.sw_6",
"payloadType": "str",
"topic": "",
"x": 1150,
"y": 860,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_entrance_all_off",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "entrance all_off",
"group": "group_entrance",
"order": 1,
"width": 0,
"height": 0,
"label": "all_off",
"payload": "entrance.all_off",
"payloadType": "str",
"topic": "",
"x": 1300,
"y": 940,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_entrance_all_on",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "entrance all_on",
"group": "group_entrance",
"order": 2,
"width": 0,
"height": 0,
"label": "all_on",
"payload": "entrance.all_on",
"payloadType": "str",
"topic": "",
"x": 1300,
"y": 980,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_entrance_sw_1",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "entrance sw_1",
"group": "group_entrance",
"order": 3,
"width": 0,
"height": 0,
"label": "sw_1",
"payload": "entrance.sw_1",
"payloadType": "str",
"topic": "",
"x": 1300,
"y": 1020,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_entrance_sw_2",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "entrance sw_2",
"group": "group_entrance",
"order": 4,
"width": 0,
"height": 0,
"label": "sw_2",
"payload": "entrance.sw_2",
"payloadType": "str",
"topic": "",
"x": 1300,
"y": 1060,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_entrance_sw_3",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "entrance sw_3",
"group": "group_entrance",
"order": 5,
"width": 0,
"height": 0,
"label": "sw_3",
"payload": "entrance.sw_3",
"payloadType": "str",
"topic": "",
"x": 1300,
"y": 1100,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_entrance_sw_4",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "entrance sw_4",
"group": "group_entrance",
"order": 6,
"width": 0,
"height": 0,
"label": "sw_4",
"payload": "entrance.sw_4",
"payloadType": "str",
"topic": "",
"x": 1300,
"y": 1140,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_entrance_sw_5",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "entrance sw_5",
"group": "group_entrance",
"order": 7,
"width": 0,
"height": 0,
"label": "sw_5",
"payload": "entrance.sw_5",
"payloadType": "str",
"topic": "",
"x": 1300,
"y": 1180,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_entrance_sw_6",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "entrance sw_6",
"group": "group_entrance",
"order": 8,
"width": 0,
"height": 0,
"label": "sw_6",
"payload": "entrance.sw_6",
"payloadType": "str",
"topic": "",
"x": 1300,
"y": 1220,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_guestWc_all_off",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "guestWc all_off",
"group": "group_guestWc",
"order": 1,
"width": 0,
"height": 0,
"label": "all_off",
"payload": "guestWc.all_off",
"payloadType": "str",
"topic": "",
"x": 940,
"y": 580,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_guestWc_all_on",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "guestWc all_on",
"group": "group_guestWc",
"order": 2,
"width": 0,
"height": 0,
"label": "all_on",
"payload": "guestWc.all_on",
"payloadType": "str",
"topic": "",
"x": 940,
"y": 620,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_guestWc_sw_1",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "guestWc sw_1",
"group": "group_guestWc",
"order": 3,
"width": 0,
"height": 0,
"label": "sw_1",
"payload": "guestWc.sw_1",
"payloadType": "str",
"topic": "",
"x": 940,
"y": 660,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_guestWc_sw_2",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "guestWc sw_2",
"group": "group_guestWc",
"order": 4,
"width": 0,
"height": 0,
"label": "sw_2",
"payload": "guestWc.sw_2",
"payloadType": "str",
"topic": "",
"x": 940,
"y": 700,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_guestWc_sw_3",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "guestWc sw_3",
"group": "group_guestWc",
"order": 5,
"width": 0,
"height": 0,
"label": "sw_3",
"payload": "guestWc.sw_3",
"payloadType": "str",
"topic": "",
"x": 940,
"y": 740,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_guestWc_sw_4",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "guestWc sw_4",
"group": "group_guestWc",
"order": 6,
"width": 0,
"height": 0,
"label": "sw_4",
"payload": "guestWc.sw_4",
"payloadType": "str",
"topic": "",
"x": 940,
"y": 780,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_guestWc_sw_5",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "guestWc sw_5",
"group": "group_guestWc",
"order": 7,
"width": 0,
"height": 0,
"label": "sw_5",
"payload": "guestWc.sw_5",
"payloadType": "str",
"topic": "",
"x": 940,
"y": 820,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_guestWc_sw_6",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "guestWc sw_6",
"group": "group_guestWc",
"order": 8,
"width": 0,
"height": 0,
"label": "sw_6",
"payload": "guestWc.sw_6",
"payloadType": "str",
"topic": "",
"x": 940,
"y": 860,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outVeranda_all_off",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outVeranda all_off",
"group": "group_outVeranda",
"order": 1,
"width": 0,
"height": 0,
"label": "all_off",
"payload": "outVeranda.all_off",
"payloadType": "str",
"topic": "",
"x": 730,
"y": 580,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outVeranda_all_on",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outVeranda all_on",
"group": "group_outVeranda",
"order": 2,
"width": 0,
"height": 0,
"label": "all_on",
"payload": "outVeranda.all_on",
"payloadType": "str",
"topic": "",
"x": 730,
"y": 620,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outVeranda_sw_1",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outVeranda sw_1",
"group": "group_outVeranda",
"order": 3,
"width": 0,
"height": 0,
"label": "sw_1",
"payload": "outVeranda.sw_1",
"payloadType": "str",
"topic": "",
"x": 730,
"y": 660,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outVeranda_sw_2",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outVeranda sw_2",
"group": "group_outVeranda",
"order": 4,
"width": 0,
"height": 0,
"label": "sw_2",
"payload": "outVeranda.sw_2",
"payloadType": "str",
"topic": "",
"x": 730,
"y": 700,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outVeranda_sw_3",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outVeranda sw_3",
"group": "group_outVeranda",
"order": 5,
"width": 0,
"height": 0,
"label": "sw_3",
"payload": "outVeranda.sw_3",
"payloadType": "str",
"topic": "",
"x": 730,
"y": 740,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outVeranda_sw_4",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outVeranda sw_4",
"group": "group_outVeranda",
"order": 6,
"width": 0,
"height": 0,
"label": "sw_4",
"payload": "outVeranda.sw_4",
"payloadType": "str",
"topic": "",
"x": 730,
"y": 780,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outVeranda_sw_5",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outVeranda sw_5",
"group": "group_outVeranda",
"order": 7,
"width": 0,
"height": 0,
"label": "sw_5",
"payload": "outVeranda.sw_5",
"payloadType": "str",
"topic": "",
"x": 730,
"y": 820,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outVeranda_sw_6",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outVeranda sw_6",
"group": "group_outVeranda",
"order": 8,
"width": 0,
"height": 0,
"label": "sw_6",
"payload": "outVeranda.sw_6",
"payloadType": "str",
"topic": "",
"x": 730,
"y": 860,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outFront_all_off",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outFront all_off",
"group": "group_outFront",
"order": 1,
"width": 0,
"height": 0,
"label": "all_off",
"payload": "outFront.all_off",
"payloadType": "str",
"topic": "",
"x": 520,
"y": 580,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outFront_all_on",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outFront all_on",
"group": "group_outFront",
"order": 2,
"width": 0,
"height": 0,
"label": "all_on",
"payload": "outFront.all_on",
"payloadType": "str",
"topic": "",
"x": 520,
"y": 620,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outFront_sw_1",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outFront sw_1",
"group": "group_outFront",
"order": 3,
"width": 0,
"height": 0,
"label": "sw_1",
"payload": "outFront.sw_1",
"payloadType": "str",
"topic": "",
"x": 520,
"y": 660,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outFront_sw_2",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outFront sw_2",
"group": "group_outFront",
"order": 4,
"width": 0,
"height": 0,
"label": "sw_2",
"payload": "outFront.sw_2",
"payloadType": "str",
"topic": "",
"x": 520,
"y": 700,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outFront_sw_3",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outFront sw_3",
"group": "group_outFront",
"order": 5,
"width": 0,
"height": 0,
"label": "sw_3",
"payload": "outFront.sw_3",
"payloadType": "str",
"topic": "",
"x": 520,
"y": 740,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outFront_sw_4",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outFront sw_4",
"group": "group_outFront",
"order": 6,
"width": 0,
"height": 0,
"label": "sw_4",
"payload": "outFront.sw_4",
"payloadType": "str",
"topic": "",
"x": 520,
"y": 780,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outFront_sw_5",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outFront sw_5",
"group": "group_outFront",
"order": 7,
"width": 0,
"height": 0,
"label": "sw_5",
"payload": "outFront.sw_5",
"payloadType": "str",
"topic": "",
"x": 520,
"y": 820,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outFront_sw_6",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outFront sw_6",
"group": "group_outFront",
"order": 8,
"width": 0,
"height": 0,
"label": "sw_6",
"payload": "outFront.sw_6",
"payloadType": "str",
"topic": "",
"x": 520,
"y": 860,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outSide_all_off",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outSide all_off",
"group": "group_outSide",
"order": 1,
"width": 0,
"height": 0,
"label": "all_off",
"payload": "outSide.all_off",
"payloadType": "str",
"topic": "",
"x": 340,
"y": 580,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outSide_all_on",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outSide all_on",
"group": "group_outSide",
"order": 2,
"width": 0,
"height": 0,
"label": "all_on",
"payload": "outSide.all_on",
"payloadType": "str",
"topic": "",
"x": 340,
"y": 620,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outSide_sw_1",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outSide sw_1",
"group": "group_outSide",
"order": 3,
"width": 0,
"height": 0,
"label": "sw_1",
"payload": "outSide.sw_1",
"payloadType": "str",
"topic": "",
"x": 340,
"y": 660,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outSide_sw_2",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outSide sw_2",
"group": "group_outSide",
"order": 4,
"width": 0,
"height": 0,
"label": "sw_2",
"payload": "outSide.sw_2",
"payloadType": "str",
"topic": "",
"x": 340,
"y": 700,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outSide_sw_3",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outSide sw_3",
"group": "group_outSide",
"order": 5,
"width": 0,
"height": 0,
"label": "sw_3",
"payload": "outSide.sw_3",
"payloadType": "str",
"topic": "",
"x": 340,
"y": 740,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outSide_sw_4",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outSide sw_4",
"group": "group_outSide",
"order": 6,
"width": 0,
"height": 0,
"label": "sw_4",
"payload": "outSide.sw_4",
"payloadType": "str",
"topic": "",
"x": 340,
"y": 780,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outSide_sw_5",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outSide sw_5",
"group": "group_outSide",
"order": 7,
"width": 0,
"height": 0,
"label": "sw_5",
"payload": "outSide.sw_5",
"payloadType": "str",
"topic": "",
"x": 340,
"y": 820,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outSide_sw_6",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outSide sw_6",
"group": "group_outSide",
"order": 8,
"width": 0,
"height": 0,
"label": "sw_6",
"payload": "outSide.sw_6",
"payloadType": "str",
"topic": "",
"x": 340,
"y": 860,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outBack_all_off",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outBack all_off",
"group": "group_outBack",
"order": 1,
"width": 0,
"height": 0,
"label": "all_off",
"payload": "outBack.all_off",
"payloadType": "str",
"topic": "",
"x": 120,
"y": 580,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outBack_all_on",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outBack all_on",
"group": "group_outBack",
"order": 2,
"width": 0,
"height": 0,
"label": "all_on",
"payload": "outBack.all_on",
"payloadType": "str",
"topic": "",
"x": 120,
"y": 620,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outBack_sw_1",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outBack sw_1",
"group": "group_outBack",
"order": 3,
"width": 0,
"height": 0,
"label": "sw_1",
"payload": "outBack.sw_1",
"payloadType": "str",
"topic": "",
"x": 120,
"y": 660,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outBack_sw_2",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outBack sw_2",
"group": "group_outBack",
"order": 4,
"width": 0,
"height": 0,
"label": "sw_2",
"payload": "outBack.sw_2",
"payloadType": "str",
"topic": "",
"x": 120,
"y": 700,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outBack_sw_3",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outBack sw_3",
"group": "group_outBack",
"order": 5,
"width": 0,
"height": 0,
"label": "sw_3",
"payload": "outBack.sw_3",
"payloadType": "str",
"topic": "",
"x": 120,
"y": 740,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outBack_sw_4",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outBack sw_4",
"group": "group_outBack",
"order": 6,
"width": 0,
"height": 0,
"label": "sw_4",
"payload": "outBack.sw_4",
"payloadType": "str",
"topic": "",
"x": 120,
"y": 780,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outBack_sw_5",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outBack sw_5",
"group": "group_outBack",
"order": 7,
"width": 0,
"height": 0,
"label": "sw_5",
"payload": "outBack.sw_5",
"payloadType": "str",
"topic": "",
"x": 120,
"y": 820,
"wires": [
[
"func_node"
]
]
},
{
"id": "btn_outBack_sw_6",
"type": "ui_button",
"z": "31693504fcbbd954",
"name": "outBack sw_6",
"group": "group_outBack",
"order": 8,
"width": 0,
"height": 0,
"label": "sw_6",
"payload": "outBack.sw_6",
"payloadType": "str",
"topic": "",
"x": 120,
"y": 860,
"wires": [
[
"func_node"
]
]
},
{
"id": "timer30min_btn",
"type": "ha-button",
"z": "50971c50479dfd7a",
"name": "Timer 30 Min",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "timer30min_config",
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "30",
"valueType": "num"
}
],
"x": 630,
"y": 680,
"wires": [
[
"260bf6fdd821f1b9"
]
]
},
{
"id": "timer1hour_btn",
"type": "ha-button",
"z": "50971c50479dfd7a",
"name": "Timer 1 Hour",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "timer1hour_config",
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "60",
"valueType": "num"
}
],
"x": 790,
"y": 680,
"wires": [
[
"260bf6fdd821f1b9"
]
]
},
{
"id": "timer2hours_btn",
"type": "ha-button",
"z": "50971c50479dfd7a",
"name": "Timer 2 Hours",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "timer2hours_config",
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "120",
"valueType": "num"
}
],
"x": 990,
"y": 680,
"wires": [
[
"260bf6fdd821f1b9"
]
]
},
{
"id": "timerstop_btn",
"type": "ha-button",
"z": "50971c50479dfd7a",
"name": "Stop Timer",
"version": 0,
"debugenabled": false,
"outputs": 1,
"entityConfig": "timerstop_config",
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "stop",
"valueType": "str"
}
],
"x": 980,
"y": 740,
"wires": [
[
"a57a98c852762ebf"
]
]
},
{
"id": "water_boiler_timer_handler",
"type": "function",
"z": "50971c50479dfd7a",
"name": "Water Boiler Timer Handler",
"func": "// Helper function to format remaining time\nfunction formatTime(remainingMs) {\n if (remainingMs <= 0) return '0m 0s';\n const totalSeconds = Math.floor(remainingMs / 1000);\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n const hours = Math.floor(minutes / 60);\n const mins = minutes % 60;\n \n let timeStr = '';\n if (hours > 0) timeStr += hours + 'h ';\n if (mins > 0 || hours === 0) timeStr += mins + 'm ';\n timeStr += seconds + 's';\n return timeStr.trim();\n}\n\n// Check if this is a timer command (numeric payload or \"stop\")\nconst payload = msg.payload;\nconst isTimerCommand = typeof payload === 'number' || payload === 'stop';\n\nif (isTimerCommand) {\n // Cancel any existing timer and interval\n const existingTimer = flow.get('water_boiler_timer');\n if (existingTimer) {\n clearTimeout(existingTimer);\n flow.set('water_boiler_timer', null);\n }\n \n const existingInterval = flow.get('water_boiler_timer_interval');\n if (existingInterval) {\n clearInterval(existingInterval);\n flow.set('water_boiler_timer_interval', null);\n }\n \n if (payload === 'stop') {\n // Stop command - turn off water boiler immediately\n const msgFalse = {\n topic: \"bathroom\",\n payload: \"sw_6\",\n value: false\n };\n \n // Send 0 remaining time\n const msgTime = {\n payload: '0m 0s'\n };\n \n node.status({fill:\"yellow\", shape:\"dot\", text:\"Timer stopped\"});\n return [msgFalse, null, msgTime];\n } else {\n // Timer duration in minutes - convert to milliseconds\n const durationMs = payload * 60 * 1000;\n const startTime = Date.now();\n \n // Store start time and duration\n flow.set('water_boiler_timer_start', startTime);\n flow.set('water_boiler_timer_duration', durationMs);\n \n // Turn ON water boiler first\n const msgTrue = {\n topic: \"bathroom\",\n payload: \"sw_6\",\n value: true\n };\n \n // Function to send remaining time\n const sendRemainingTime = function() {\n const elapsed = Date.now() - startTime;\n const remaining = Math.max(0, durationMs - elapsed);\n const timeStr = formatTime(remaining);\n \n const msgTime = {\n payload: timeStr\n };\n node.send([null, null, msgTime]);\n \n // Update status\n node.status({fill:\"blue\", shape:\"dot\", text:`Timer: ${timeStr}`});\n \n // Clear interval if timer expired\n if (remaining <= 0) {\n const intervalId = flow.get('water_boiler_timer_interval');\n if (intervalId) {\n clearInterval(intervalId);\n flow.set('water_boiler_timer_interval', null);\n }\n }\n };\n \n // Send initial remaining time\n sendRemainingTime();\n \n // Set up interval to update remaining time every second (live refresh)\n const intervalId = setInterval(sendRemainingTime, 1000);\n flow.set('water_boiler_timer_interval', intervalId);\n \n // Set timer to turn OFF after duration\n const timerId = setTimeout(function() {\n const msgOff = {\n topic: \"bathroom\",\n payload: \"sw_6\",\n value: false\n };\n \n // Send final time (0m 0s)\n const msgTime = {\n payload: '0m 0s'\n };\n \n node.send([msgOff, null, msgTime]);\n flow.set('water_boiler_timer', null);\n flow.set('water_boiler_timer_start', null);\n flow.set('water_boiler_timer_duration', null);\n \n // Clear interval\n const intervalId = flow.get('water_boiler_timer_interval');\n if (intervalId) {\n clearInterval(intervalId);\n flow.set('water_boiler_timer_interval', null);\n }\n \n node.status({fill:\"green\", shape:\"ring\", text:\"Timer completed\"});\n }, durationMs);\n \n // Store timer ID\n flow.set('water_boiler_timer', timerId);\n \n const minutes = payload;\n const hours = Math.floor(minutes / 60);\n const mins = minutes % 60;\n let timeStr = '';\n if (hours > 0) timeStr += hours + 'h ';\n if (mins > 0 || hours === 0) timeStr += mins + 'm';\n \n // Return ON command on output 1, nothing on output 2, initial time on output 3\n const msgTime = {\n payload: formatTime(durationMs)\n };\n return [msgTrue, null, msgTime];\n }\n} else {\n // Regular button press - pass through to existing function on output 2\n return [null, msg, null];\n}\n\n",
"outputs": 3,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1620,
"y": 680,
"wires": [
[
"1d0a46b9d5255560"
],
[],
[
"timer_remaining_sensor"
]
]
},
{
"id": "1d0a46b9d5255560",
"type": "link out",
"z": "50971c50479dfd7a",
"name": "link out 24",
"mode": "link",
"links": [
"0bbcb269da9b75c7"
],
"x": 1845,
"y": 560,
"wires": []
},
{
"id": "timer_remaining_sensor",
"type": "ha-sensor",
"z": "50971c50479dfd7a",
"name": "Timer Remaining",
"entityConfig": "timer_remaining_config",
"version": 1,
"state": "payload",
"stateType": "msg",
"attributes": [],
"x": 1890,
"y": 620,
"wires": [
[]
]
},
{
"id": "a57a98c852762ebf",
"type": "api-current-state",
"z": "50971c50479dfd7a",
"name": "",
"server": "29eb84a2708d96e0",
"version": 3,
"outputs": 2,
"halt_if": "on",
"halt_if_type": "str",
"halt_if_compare": "is",
"entity_id": "binary_sensor.water_boiler",
"state_type": "str",
"blockInputOverrides": false,
"outputProperties": [],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 1280,
"y": 740,
"wires": [
[
"water_boiler_timer_handler"
],
[]
]
},
{
"id": "260bf6fdd821f1b9",
"type": "api-current-state",
"z": "50971c50479dfd7a",
"name": "",
"server": "29eb84a2708d96e0",
"version": 3,
"outputs": 2,
"halt_if": "off",
"halt_if_type": "str",
"halt_if_compare": "is",
"entity_id": "binary_sensor.water_boiler",
"state_type": "str",
"blockInputOverrides": false,
"outputProperties": [],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 1280,
"y": 680,
"wires": [
[
"water_boiler_timer_handler"
],
[]
]
},
{
"id": "0ad5d7e5c99c2675",
"type": "poll-state",
"z": "50971c50479dfd7a",
"name": "",
"server": "29eb84a2708d96e0",
"version": 3,
"exposeAsEntityConfig": "",
"updateInterval": "30",
"updateIntervalType": "num",
"updateIntervalUnits": "seconds",
"outputInitially": true,
"outputOnChanged": true,
"entityId": "binary_sensor.water_boiler",
"stateType": "str",
"ifState": "on",
"ifStateType": "str",
"ifStateOperator": "is",
"outputs": 2,
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
},
{
"property": "data",
"propertyType": "msg",
"value": "",
"valueType": "entity"
},
{
"property": "topic",
"propertyType": "msg",
"value": "",
"valueType": "triggerId"
}
],
"x": 1070,
"y": 600,
"wires": [
[
"2472daff4bc82fb2",
"f12fa3448a1b5872"
],
[]
]
},
{
"id": "2472daff4bc82fb2",
"type": "function",
"z": "50971c50479dfd7a",
"name": "Safety Check Function",
"func": "// Safety Check Function\n// This function checks the water boiler state on Node-RED startup ONLY\n// It's connected to the poll-state node which outputs initially when Node-RED starts\n// If the boiler is ON, it turns it off and clears timer state\n// Uses a flag to ensure it only runs once on startup, not on every poll\n\n// Check if safety check has already been performed (only runs once on startup)\nconst safetyCheckDone = flow.get('water_boiler_safety_check_done');\nif (safetyCheckDone === true) {\n // Safety check already performed, ignore this message (from periodic polls)\n // Return nothing to both outputs\n return [null, null];\n}\n\n// Mark safety check as done (so it won't run again until Node-RED restarts)\nflow.set('water_boiler_safety_check_done', true);\n\n// Get the current state from the poll-state node\nconst currentState = msg.payload; // 'on' or 'off'\n\n// Clear any timer state (safety measure on restart)\nflow.set('water_boiler_timer', null);\nflow.set('water_boiler_timer_interval', null);\nflow.set('water_boiler_timer_start', null);\nflow.set('water_boiler_timer_duration', null);\n\n// Only turn off if the boiler is currently ON\nif (currentState === 'on') {\n // Boiler is ON - turn it off for safety\n const msgOff = {\n topic: \"bathroom\",\n payload: \"sw_6\",\n value: false\n };\n \n const msgTime = {\n payload: '0m 0s'\n };\n \n node.status({fill:\"red\", shape:\"ring\", text:\"Safety: Boiler was ON, turned off\"});\n return [msgOff, msgTime];\n} else {\n // Boiler is already off, just reset timer display\n const msgTime = {\n payload: '0m 0s'\n };\n \n node.status({fill:\"green\", shape:\"ring\", text:\"Safety: Boiler already off\"});\n return [null, msgTime];\n}\n\n",
"outputs": 2,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1600,
"y": 620,
"wires": [
[
"1d0a46b9d5255560"
],
[
"timer_remaining_sensor"
]
]
},
{
"id": "f96bf3ff41b2e8f7",
"type": "server-state-changed",
"z": "50971c50479dfd7a",
"d": true,
"name": "Monitor Boiler (3h Safety)",
"server": "29eb84a2708d96e0",
"version": 6,
"outputs": 1,
"exposeAsEntityConfig": "",
"entities": {
"entity": [
"binary_sensor.water_boiler"
],
"substring": [],
"regex": []
},
"outputInitially": true,
"stateType": "str",
"ifState": "",
"ifStateType": "str",
"ifStateOperator": "is",
"outputOnlyOnStateChange": true,
"for": "0",
"forType": "num",
"forUnits": "minutes",
"ignorePrevStateNull": true,
"ignorePrevStateUnknown": true,
"ignorePrevStateUnavailable": false,
"ignoreCurrentStateUnknown": false,
"ignoreCurrentStateUnavailable": false,
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
},
{
"property": "data",
"propertyType": "msg",
"value": "",
"valueType": "eventData"
},
{
"property": "topic",
"propertyType": "msg",
"value": "",
"valueType": "triggerId"
}
],
"x": 1030,
"y": 560,
"wires": [
[
"3hour_safety_function_events"
]
]
},
{
"id": "3hour_safety_function_events",
"type": "function",
"z": "50971c50479dfd7a",
"d": true,
"name": "3-Hour Safety Timer",
"func": "// Water Boiler 3-Hour Safety Timer\n// Uses server-state-changed node which provides old_state and new_state in event data\n// Event-driven (real-time) - no polling needed!\n\n// Get state information from server-state-changed node\n// msg.data contains the full event object with old_state and new_state\nconst eventData = msg.data;\nconst newState = eventData.new_state ? eventData.new_state.state : msg.payload;\nconst oldState = eventData.old_state ? eventData.old_state.state : 'unknown';\n\n// Get existing safety timer if any\nconst safetyTimer = flow.get('water_boiler_3hour_timer');\n\n// Check if state changed from off/unknown to on\nif (newState === 'on' && oldState !== 'on') {\n // Boiler just turned ON - start 3-hour safety timer\n \n // Cancel any existing timer (safety measure)\n if (safetyTimer) {\n clearTimeout(safetyTimer);\n flow.set('water_boiler_3hour_timer', null);\n }\n \n // Start 3-hour timer (3 hours = 3 * 60 * 60 * 1000 milliseconds)\n const threeHours = 3 * 60 * 60 * 1000;\n const timerId = setTimeout(function() {\n // 3 hours elapsed - turn off boiler for safety\n const msgOff = {\n topic: \"bathroom\",\n payload: \"sw_6\",\n value: false\n };\n \n // Clear timer state\n flow.set('water_boiler_3hour_timer', null);\n flow.set('water_boiler_3hour_start_time', null);\n \n // Send turn-off command\n node.send(msgOff);\n node.status({fill:\"red\", shape:\"ring\", text:\"Safety: 3h limit reached, turned off\"});\n node.warn(\"Water boiler has been ON for 3 hours - automatically turned off for safety\");\n }, threeHours);\n \n // Store timer ID and start time\n flow.set('water_boiler_3hour_timer', timerId);\n flow.set('water_boiler_3hour_start_time', Date.now());\n \n // Update status\n node.status({fill:\"yellow\", shape:\"dot\", text:\"3h safety timer: 3h remaining\"});\n node.log(\"Water boiler turned ON - 3-hour safety timer started\");\n \n // Don't send any message (just monitoring)\n return null;\n \n} else if (newState === 'off' && oldState === 'on') {\n // Boiler just turned OFF - cancel safety timer\n \n if (safetyTimer) {\n clearTimeout(safetyTimer);\n flow.set('water_boiler_3hour_timer', null);\n \n const startTime = flow.get('water_boiler_3hour_start_time');\n if (startTime) {\n const runtime = Math.floor((Date.now() - startTime) / 1000 / 60); // minutes\n node.log(`Water boiler turned OFF - 3-hour safety timer cancelled (was on for ${runtime} minutes)`);\n }\n \n flow.set('water_boiler_3hour_start_time', null);\n node.status({fill:\"green\", shape:\"ring\", text:\"3h safety timer cancelled\"});\n } else {\n node.status({fill:\"grey\", shape:\"ring\", text:\"Boiler off\"});\n }\n \n // Don't send any message\n return null;\n \n} else {\n // Other state changes (on->on, off->off, initial state, etc.) - ignore\n return null;\n}",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1600,
"y": 560,
"wires": [
[
"1d0a46b9d5255560"
]
]
},
{
"id": "f12fa3448a1b5872",
"type": "debug",
"z": "50971c50479dfd7a",
"name": "debug 28",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1290,
"y": 460,
"wires": []
},
{
"id": "inject-person",
"type": "inject",
"z": "a6a28d6b6c0b4f4a",
"name": "Simulate Person Detected",
"props": [
{
"p": "payload",
"v": "1",
"vt": "num"
},
{
"p": "timestamp",
"v": "",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"x": 410,
"y": 860,
"wires": [
[
"function-add-timestamp"
]
]
},
{
"id": "function-add-timestamp",
"type": "function",
"z": "a6a28d6b6c0b4f4a",
"name": "Add Current Timestamp",
"func": "// Add timestamp\nmsg.timestamp = Date.now();\nreturn msg;",
"outputs": 1,
"x": 670,
"y": 860,
"wires": [
[
"function-check-state"
]
]
},
{
"id": "function-check-state",
"type": "function",
"z": "a6a28d6b6c0b4f4a",
"name": "Check Doorbell State",
"func": "// Get previous state from context\nvar prev = context.get('prev') || 0;\nvar curr = parseInt(msg.payload);\ncontext.set('prev', curr);\n\nif(curr===1 && prev===0){\n msg.payload = \"🚪 Person detected at Basement Driveway!\";\n return msg;\n}\nreturn null;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 910,
"y": 860,
"wires": [
[
"function-login"
]
]
},
{
"id": "function-login",
"type": "function",
"z": "a6a28d6b6c0b4f4a",
"name": "Reolink Login",
"func": "const ip = '10.20.30.34';\nconst username = 'admin';\nconst password = 'sh1pb0x1';\nmsg.url = `http://${ip}/cgi-bin/api.cgi?cmd=Login&token=null`;\nmsg.method = 'POST';\nmsg.headers = { 'Content-Type': 'application/json' };\nmsg.payload = JSON.stringify([\n { cmd: 'Login', param: { User: { userName: username, password: password } } }\n]);\nmsg.camera_ip = ip;\nmsg.camera_location = 'Basement Driveway Camera';\nmsg.nextRandom = Math.random().toString(36).substring(7);\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1150,
"y": 860,
"wires": [
[
"http-login"
]
]
},
{
"id": "http-login",
"type": "http request",
"z": "a6a28d6b6c0b4f4a",
"name": "Send Login Request",
"method": "use",
"ret": "obj",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"x": 1390,
"y": 860,
"wires": [
[
"function-snap"
]
]
},
{
"id": "function-snap",
"type": "function",
"z": "a6a28d6b6c0b4f4a",
"name": "Fetch Snapshot",
"func": "// Extract token from login response\nif(!msg.payload || !msg.payload[0] || !msg.payload[0].value){\n node.error('Login failed');\n return null;\n}\nconst token = msg.payload[0].value.Token.name;\nif(!token){ node.error('Token missing'); return null; }\n\n// Build snapshot URL\nmsg.url = `http://${msg.camera_ip}/cgi-bin/api.cgi?cmd=Snap&channel=0&rs=${msg.nextRandom}&token=${token}`;\nmsg.method = 'GET';\nmsg.headers = {};\nmsg.payload = null;\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1630,
"y": 860,
"wires": [
[
"http-snap"
]
]
},
{
"id": "http-snap",
"type": "http request",
"z": "a6a28d6b6c0b4f4a",
"name": "Get Camera Snapshot",
"method": "use",
"ret": "bin",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"x": 1870,
"y": 860,
"wires": [
[
"b95aab8dab0c2fb4"
]
]
},
{
"id": "b95aab8dab0c2fb4",
"type": "function",
"z": "a6a28d6b6c0b4f4a",
"name": "Send Doorbell Alert to Telegram",
"func": "// Validate that we received a proper image buffer\nif (!Buffer.isBuffer(msg.payload)) {\n node.warn(\"❌ Basement Driveway snapshot fetch failed — not a binary image buffer\");\n node.status({fill:\"red\", shape:\"ring\", text:\"Snapshot failed\"});\n return null;\n}\n\n// Check if buffer has reasonable size (basic validation)\nif (msg.payload.length < 1000) {\n node.warn(\"❌ Basement Driveway snapshot too small — likely corrupted\");\n node.status({fill:\"red\", shape:\"ring\", text:\"Image too small\"});\n return null;\n}\n\n// Format timestamp for display\nconst timestamp = new Date(msg.timestamp).toLocaleString();\n\n// Prepare Telegram message payload\nmsg.payload = {\n chatId: -4747176681, // Telegram group chat ID\n type: 'photo',\n content: msg.payload, // Binary image buffer\n caption: `🔔 Basement Driveway ALERT! 🔔\\n\\n📍 Someone is at the ${msg.location}\\n⏰ Time: ${timestamp}\\n📷 Camera: ${msg.camera_location} (${msg.camera_ip})`\n};\n\nnode.status({fill:\"green\", shape:\"dot\", text:\"Alert sent!\"});\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 2150,
"y": 860,
"wires": [
[
"8f15067daf678e66"
]
]
},
{
"id": "8f15067daf678e66",
"type": "link out",
"z": "a6a28d6b6c0b4f4a",
"name": "link out 25",
"mode": "link",
"links": [
"41d29e978759e26e"
],
"x": 2365,
"y": 860,
"wires": []
},
{
"id": "dbea7ee9936e4747",
"type": "mqtt in",
"z": "b673e10beab091ff",
"name": "MQTT Input",
"topic": "#",
"qos": "2",
"datatype": "auto-detect",
"broker": "a1235a09a8d34dea",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 330,
"y": 1040,
"wires": [
[
"b10d3c44bca37652"
]
]
},
{
"id": "b10d3c44bca37652",
"type": "function",
"z": "b673e10beab091ff",
"name": "Camera Config & Topic Parser",
"func": "// Camera configuration - Add/remove cameras here\n// authMethod: 'url' for URL-based auth, 'reolink' for Reolink API login\nconst cameras = [\n {\n name: \"Doorbell Camera\",\n ip: \"10.20.30.30\",\n mqttTopic: \"frigate/doorbell/person\",\n username: \"admin\",\n password: \"sh1pb0x1\",\n authMethod: \"url\"\n },\n {\n name: \"Veranda Door Camera\",\n ip: \"10.20.30.33\",\n mqttTopic: \"frigate/veranda_door/person\",\n username: \"admin\",\n password: \"sh1pb0x1\",\n authMethod: \"url\"\n },\n {\n name: \"Basement Driveway Camera\",\n ip: \"10.20.30.34\",\n mqttTopic: \"frigate/basement_driveway/person\",\n username: \"admin\",\n password: \"sh1pb0x1\",\n authMethod: \"reolink\"\n }\n];\n\n// Find matching camera based on MQTT topic\nconst topic = msg.topic;\nconst camera = cameras.find(cam => topic === cam.mqttTopic);\n\n// Only process if it's a person detection topic for a known camera\nif (!camera) {\n return null; // Not a camera we care about\n}\n\n// Store camera config in message\nmsg.camera_name = camera.name;\nmsg.camera_ip = camera.ip;\nmsg.camera_username = camera.username;\nmsg.camera_password = camera.password;\nmsg.camera_location = camera.name;\nmsg.authMethod = camera.authMethod;\n\n// Add timestamp if not present\nif (!msg.timestamp) {\n msg.timestamp = Date.now();\n}\n\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 670,
"y": 1040,
"wires": [
[
"a1e7837147954108",
"50b554a0642ab4e4"
]
]
},
{
"id": "a1e7837147954108",
"type": "function",
"z": "b673e10beab091ff",
"name": "Check State Change",
"func": "// Get current payload value\nvar currentValue = parseInt(msg.payload);\n\n// Use camera name as unique key for state tracking\nvar stateKey = 'previousState_' + msg.camera_name.replace(/\\s+/g, '_');\n\n// Get previous state from context (default to 0 if not set)\nvar previousValue = context.get(stateKey) || 0;\n\n// Store current value for next comparison\ncontext.set(stateKey, currentValue);\n\n// Only proceed if current value is 1 AND previous value was 0\nif (currentValue === 1 && previousValue === 0) {\n node.status({fill:\"blue\", shape:\"dot\", text:`${msg.camera_name}: Person detected!`});\n return msg;\n}\n\n// Don't send message for other cases\nreturn null;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 930,
"y": 1040,
"wires": [
[
"90f6a26b7b04cc23",
"ec7ded527bfe8ef2"
]
]
},
{
"id": "90f6a26b7b04cc23",
"type": "switch",
"z": "b673e10beab091ff",
"name": "Route by Auth Method",
"property": "authMethod",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "url",
"vt": "str"
},
{
"t": "eq",
"v": "reolink",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 1180,
"y": 1040,
"wires": [
[
"d723df03bdda6ca5",
"43983177055e72b1"
],
[
"0339e277385e3213",
"6cafa4c162199702"
]
]
},
{
"id": "d723df03bdda6ca5",
"type": "function",
"z": "b673e10beab091ff",
"name": "URL Auth Snapshot",
"func": "// Validate camera info\nif (!msg.camera_ip || !msg.camera_username || !msg.camera_password) {\n node.error(`Missing camera credentials for ${msg.camera_name || 'unknown'}`);\n node.status({fill:\"red\", shape:\"ring\", text:\"Missing credentials\"});\n return null;\n}\n\n// Generate random string for cache busting\nconst randomString = Math.random().toString(36).substring(7);\n\n// URL encode credentials to handle special characters safely\nconst encodedUser = encodeURIComponent(msg.camera_username);\nconst encodedPassword = encodeURIComponent(msg.camera_password);\n\n// Construct camera snapshot URL with credentials\nmsg.url = `http://${msg.camera_ip}/cgi-bin/api.cgi?cmd=Snap&channel=0&rs=${randomString}&user=${encodedUser}&password=${encodedPassword}`;\nmsg.method = 'GET';\nmsg.headers = {};\nmsg.payload = null;\n\nnode.status({fill:\"blue\", shape:\"dot\", text:`Fetching ${msg.camera_name}...`});\n\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1450,
"y": 960,
"wires": [
[
"267ea942b61eb093",
"7b685fbbf92cce4f"
]
]
},
{
"id": "0339e277385e3213",
"type": "function",
"z": "b673e10beab091ff",
"name": "Reolink Login",
"func": "// Prepare login request for Reolink API\nconst ip = msg.camera_ip;\nconst username = msg.camera_username;\nconst password = msg.camera_password;\n\n// Build login URL\nmsg.url = `http://${ip}/cgi-bin/api.cgi?cmd=Login&token=null`;\nmsg.method = 'POST';\nmsg.headers = { 'Content-Type': 'application/json' };\nmsg.payload = JSON.stringify([\n { cmd: 'Login', param: { User: { userName: username, password: password } } }\n]);\n\n// Generate random string for cache busting (for snapshot request)\nmsg.nextRandom = Math.random().toString(36).substring(7);\n\n// Preserve camera info\n// msg.camera_ip, msg.camera_name, msg.camera_location already set\n\nnode.status({fill:\"yellow\", shape:\"dot\", text:`Logging in to ${msg.camera_name}...`});\n\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1290,
"y": 1160,
"wires": [
[
"36ef8809abd6c068",
"ad8ae18947a58945"
]
]
},
{
"id": "36ef8809abd6c068",
"type": "http request",
"z": "b673e10beab091ff",
"name": "Send Login Request",
"method": "use",
"ret": "obj",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"senderr": true,
"x": 1450,
"y": 1040,
"wires": [
[
"e24c5bb10ec49f08"
]
]
},
{
"id": "e24c5bb10ec49f08",
"type": "function",
"z": "b673e10beab091ff",
"name": "Fetch Snapshot",
"func": "// Check for HTTP errors first\nif (msg.statusCode && msg.statusCode !== 200) {\n node.error(`HTTP ${msg.statusCode} - Login failed for ${msg.camera_name}`);\n node.status({fill:\"red\", shape:\"ring\", text:\"HTTP Error\"});\n return null;\n}\n\n// Extract token from login response\nif(!msg.payload || !msg.payload[0] || !msg.payload[0].value){\n node.error('Login failed for ' + msg.camera_name + ' - Invalid response');\n node.status({fill:\"red\", shape:\"ring\", text:\"Login failed\"});\n return null;\n}\n\nconst token = msg.payload[0].value.Token.name;\nif(!token){ \n node.error('Token missing for ' + msg.camera_name); \n node.status({fill:\"red\", shape:\"ring\", text:\"Token missing\"});\n return null; \n}\n\n// Build snapshot URL\nmsg.url = `http://${msg.camera_ip}/cgi-bin/api.cgi?cmd=Snap&channel=0&rs=${msg.nextRandom}&token=${token}`;\nmsg.method = 'GET';\nmsg.headers = {};\nmsg.payload = null;\n\nnode.status({fill:\"blue\", shape:\"dot\", text:`Fetching snapshot from ${msg.camera_name}...`});\n\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1660,
"y": 1040,
"wires": [
[
"267ea942b61eb093"
]
]
},
{
"id": "267ea942b61eb093",
"type": "http request",
"z": "b673e10beab091ff",
"name": "Get Camera Snapshot",
"method": "use",
"ret": "bin",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"senderr": true,
"x": 1910,
"y": 1040,
"wires": [
[
"c52d97f3e3de82d8"
]
]
},
{
"id": "b9939417e38d7ffa",
"type": "function",
"z": "b673e10beab091ff",
"name": "Error Handler",
"func": "// Handle HTTP errors\nconst cameraName = msg.camera_name || 'Unknown Camera';\nconst errorMsg = msg.error || msg.statusCode || msg.message || 'Unknown error';\n\n// Check if it's a timeout\nif (msg.error && (msg.error.message && msg.error.message.includes('timeout') || msg.error.code === 'ETIMEDOUT')) {\n node.error(`⏱️ ${cameraName} request timed out`);\n node.status({fill:\"red\", shape:\"ring\", text:\"Timeout\"});\n} else {\n node.error(`❌ ${cameraName} error: ${errorMsg}`);\n node.status({fill:\"red\", shape:\"ring\", text:\"Error\"});\n}\n\n// Pass error info to debug\nmsg.error_details = {\n camera: cameraName,\n error: errorMsg,\n statusCode: msg.statusCode,\n url: msg.url,\n timestamp: new Date().toISOString()\n};\n\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1700,
"y": 1200,
"wires": [
[
"df63eb3ba1bbfb73"
]
]
},
{
"id": "df63eb3ba1bbfb73",
"type": "debug",
"z": "b673e10beab091ff",
"name": "Error Debug",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "error_details",
"statusVal": "",
"statusType": "auto",
"x": 1910,
"y": 1200,
"wires": []
},
{
"id": "c52d97f3e3de82d8",
"type": "function",
"z": "b673e10beab091ff",
"name": "Send Alert to Telegram",
"func": "// Validate that we received a proper image buffer\nif (!Buffer.isBuffer(msg.payload)) {\n node.warn(`❌ ${msg.camera_name} snapshot fetch failed — not a binary image buffer`);\n node.status({fill:\"red\", shape:\"ring\", text:\"Snapshot failed\"});\n return null;\n}\n\n// Check if buffer has reasonable size (basic validation)\nif (msg.payload.length < 1000) {\n node.warn(`❌ ${msg.camera_name} snapshot too small — likely corrupted`);\n node.status({fill:\"red\", shape:\"ring\", text:\"Image too small\"});\n return null;\n}\n\n// Format timestamp for display\nconst timestamp = new Date(msg.timestamp).toLocaleString();\n\n// Prepare Telegram message payload\nmsg.payload = {\n chatId: -4747176681, // Telegram group chat ID\n type: 'photo',\n content: msg.payload, // Binary image buffer\n caption: `🔔 ${msg.camera_name.toUpperCase()} ALERT! 🔔\\n\\n📍 Someone detected at ${msg.camera_location}\\n⏰ Time: ${timestamp}\\n📷 Camera: ${msg.camera_name} (${msg.camera_ip})`\n};\n\nnode.status({fill:\"green\", shape:\"dot\", text:\"Alert sent!\"});\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 2190,
"y": 1040,
"wires": [
[
"1ba4ee81e40e5c51",
"8df5c69617ed9e92"
]
]
},
{
"id": "1ba4ee81e40e5c51",
"type": "link out",
"z": "b673e10beab091ff",
"name": "link out 22",
"mode": "link",
"links": [
"41d29e978759e26e"
],
"x": 2325,
"y": 860,
"wires": []
},
{
"id": "8df5c69617ed9e92",
"type": "debug",
"z": "b673e10beab091ff",
"name": "debug 12",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 2330,
"y": 1120,
"wires": []
},
{
"id": "50b554a0642ab4e4",
"type": "debug",
"z": "b673e10beab091ff",
"name": "debug 13",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 830,
"y": 1160,
"wires": []
},
{
"id": "ad8ae18947a58945",
"type": "debug",
"z": "b673e10beab091ff",
"name": "debug 17",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1430,
"y": 1260,
"wires": []
},
{
"id": "9618c8df3ea2d338",
"type": "inject",
"z": "b673e10beab091ff",
"name": "Test Veranda Door",
"props": [
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "frigate/veranda_door/person",
"x": 210,
"y": 1180,
"wires": [
[
"498fac7ac1d2e87b"
]
]
},
{
"id": "43983177055e72b1",
"type": "debug",
"z": "b673e10beab091ff",
"name": "debug 18",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1300,
"y": 880,
"wires": []
},
{
"id": "7b685fbbf92cce4f",
"type": "debug",
"z": "b673e10beab091ff",
"name": "debug 19",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1700,
"y": 880,
"wires": []
},
{
"id": "6cafa4c162199702",
"type": "debug",
"z": "b673e10beab091ff",
"name": "debug 20",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1100,
"y": 1240,
"wires": []
},
{
"id": "ec7ded527bfe8ef2",
"type": "debug",
"z": "b673e10beab091ff",
"name": "debug 30",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1080,
"y": 960,
"wires": []
},
{
"id": "498fac7ac1d2e87b",
"type": "function",
"z": "b673e10beab091ff",
"name": "function 9",
"func": "// Send payload 0 first, then payload 1 after a short delay\n// This tests the state change detection (0 -> 1)\n\n// Get topic from incoming message (set in inject node)\nconst topic = msg.topic;\n\n// Send payload 0 immediately\nconst msg0 = {\n topic: topic,\n payload: 0,\n timestamp: Date.now()\n};\n\n// Send payload 1 after 500ms delay\nsetTimeout(() => {\n const msg1 = {\n topic: topic,\n payload: 1,\n timestamp: Date.now()\n };\n node.send(msg1);\n}, 500);\n\n// Return the first message (payload 0)\nreturn msg0;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 420,
"y": 1180,
"wires": [
[
"b10d3c44bca37652"
]
]
},
{
"id": "85ca22727431531a",
"type": "inject",
"z": "b673e10beab091ff",
"name": "Test Veranda Door",
"props": [
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "frigate/basement_driveway/person",
"x": 210,
"y": 1220,
"wires": [
[
"498fac7ac1d2e87b"
]
]
},
{
"id": "lr-ha-to-nvl",
"type": "function",
"z": "24e9a56732cfa6f1",
"name": "HA to NVL",
"func": "const ROOM_NAME = 'livingRoom';\nconst entityId = (msg.topic || '').toString();\nconst parts = entityId.split('_');\nconst last = parts[parts.length - 1] || '';\nconst num = parseInt(last, 10);\nconst lightNum = (!isNaN(num) && num >= 1) ? Math.min(6, num) : 1;\nconst isOn = (msg.payload === 'on' || msg.payload === true);\nif (!flow.get('nvlInState')) flow.set('nvlInState', { rooms: {}, boiler: {} });\nconst state = flow.get('nvlInState');\nif (!state.rooms[ROOM_NAME]) state.rooms[ROOM_NAME] = {};\nconst r = state.rooms[ROOM_NAME];\nr['ha_l' + lightNum + '_on'] = false;\nr['ha_l' + lightNum + '_off'] = false;\nif (isOn) r['ha_l' + lightNum + '_on'] = true;\nelse r['ha_l' + lightNum + '_off'] = true;\nflow.set('nvlInState', state);\nmsg.payload = { buildAndSend: true };\nreturn msg;",
"outputs": 1,
"x": 540,
"y": 220,
"wires": [
[
"lr-build-nvl",
"59ce11298eda23b6"
]
]
},
{
"id": "lr-zigbee-to-nvl",
"type": "function",
"z": "24e9a56732cfa6f1",
"name": "Zigbee to NVL",
"func": "const ROOM_NAME = 'livingRoom';\nconst actionToSwitch = { single: 1, double: 2, hold: 3, release: 4, triple: 5, quad: 6 };\nconst payload = msg.payload || {};\nconst action = (payload.action || payload.click || '').toLowerCase();\nconst swIndex = actionToSwitch[action];\nif (swIndex == null) return null;\nif (!flow.get('nvlInState')) flow.set('nvlInState', { rooms: {}, boiler: {} });\nconst state = flow.get('nvlInState');\nif (!state.rooms[ROOM_NAME]) state.rooms[ROOM_NAME] = {};\nstate.rooms[ROOM_NAME]['zigbee_sw' + swIndex] = true;\nflow.set('nvlInState', state);\nmsg.payload = { buildAndSend: true };\nmsg.zigbeeClear = { room: ROOM_NAME, key: 'zigbee_sw' + swIndex };\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 540,
"y": 320,
"wires": [
[
"lr-build-nvl",
"lr-delay"
]
]
},
{
"id": "lr-delay",
"type": "delay",
"z": "24e9a56732cfa6f1",
"name": "80ms",
"pauseType": "delay",
"timeout": "80",
"timeoutUnits": "milliseconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "seconds",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": true,
"outputs": 1,
"x": 760,
"y": 320,
"wires": [
[
"lr-clear-zigbee"
]
]
},
{
"id": "lr-clear-zigbee",
"type": "function",
"z": "24e9a56732cfa6f1",
"name": "Clear zigbee edge",
"func": "if (msg.zigbeeClear) {\n const state = flow.get('nvlInState') || { rooms: {}, boiler: {} };\n const r = state.rooms[msg.zigbeeClear.room];\n if (r) r[msg.zigbeeClear.key] = false;\n flow.set('nvlInState', state);\n}\nmsg.payload = { buildAndSend: true };\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 970,
"y": 320,
"wires": [
[
"lr-build-nvl"
]
]
},
{
"id": "lr-build-nvl",
"type": "function",
"z": "24e9a56732cfa6f1",
"name": "Build NVL_In",
"func": "const roomSize = 20;\nconst roomNames = ['masterBedroom','masterBathroom','bedroom_1','bedroom_2','bathroom','guestWc','kitchen','pantry','livingRoom','dinningRoom','entrance','hallway','outVeranda','outFront','outBack','outSide'];\nconst state = flow.get('nvlInState') || { rooms: {}, boiler: {} };\nconst rooms = state.rooms || {};\nconst boiler = state.boiler || {};\nconst buf = Buffer.alloc(328);\nfor (let r = 0; r < 16; r++) {\n const c = rooms[roomNames[r]] || {};\n const base = r * roomSize;\n buf[base+0]=c.ha_l1_on?1:0;buf[base+1]=c.ha_l1_off?1:0;buf[base+2]=c.ha_l2_on?1:0;buf[base+3]=c.ha_l2_off?1:0;buf[base+4]=c.ha_l3_on?1:0;buf[base+5]=c.ha_l3_off?1:0;buf[base+6]=c.ha_l4_on?1:0;buf[base+7]=c.ha_l4_off?1:0;buf[base+8]=c.ha_l5_on?1:0;buf[base+9]=c.ha_l5_off?1:0;buf[base+10]=c.ha_l6_on?1:0;buf[base+11]=c.ha_l6_off?1:0;\n for (let i = 0; i < 6; i++) buf[base+12+i] = c['zigbee_sw'+(i+1)] ? 1 : 0;\n buf[base+18]=c.ha_all_on?1:0;buf[base+19]=c.ha_all_off?1:0;\n}\nconst bo = 320;\nbuf[bo+0]=boiler.ha_on?1:0;buf[bo+1]=boiler.ha_off?1:0;buf[bo+2]=boiler.schedule_on?1:0;buf[bo+3]=boiler.schedule_off?1:0;buf[bo+4]=boiler.emergency_stop?1:0;buf.writeInt16LE(boiler.max_on_time_minutes??480,bo+6);\nmsg.payload = buf;\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 790,
"y": 260,
"wires": [
[
"9d20e54acf4079aa"
]
]
},
{
"id": "59ce11298eda23b6",
"type": "debug",
"z": "24e9a56732cfa6f1",
"name": "debug 33",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 730,
"y": 200,
"wires": []
},
{
"id": "9d20e54acf4079aa",
"type": "debug",
"z": "24e9a56732cfa6f1",
"name": "debug 35",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 950,
"y": 200,
"wires": []
},
{
"id": "5925b9fedc7dc1e1",
"type": "debug",
"z": "24e9a56732cfa6f1",
"name": "debug 38",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 560,
"wires": []
},
{
"id": "ed2071aadf923b50",
"type": "inject",
"z": "24e9a56732cfa6f1",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 140,
"y": 520,
"wires": [
[]
]
}
]