|
[ |
|
{ |
|
"id": "ee00a260.25be4", |
|
"type": "tab", |
|
"label": "2share", |
|
"disabled": false, |
|
"info": "" |
|
}, |
|
{ |
|
"id": "bb9aa72f.f142b8", |
|
"type": "debug", |
|
"z": "ee00a260.25be4", |
|
"name": "watering", |
|
"active": true, |
|
"tosidebar": true, |
|
"console": true, |
|
"tostatus": false, |
|
"complete": "payload", |
|
"x": 770, |
|
"y": 300, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "3c42dbd2.1e05b4", |
|
"type": "ui_switch", |
|
"z": "ee00a260.25be4", |
|
"name": "", |
|
"label": "Water Lawn", |
|
"group": "97ade2e4.08d3a", |
|
"order": 2, |
|
"width": "5", |
|
"height": "1", |
|
"passthru": false, |
|
"decouple": "true", |
|
"topic": "shm/garden/water_lawn/state", |
|
"style": "", |
|
"onvalue": "on", |
|
"onvalueType": "str", |
|
"onicon": "local_florist", |
|
"oncolor": "green", |
|
"offvalue": "off", |
|
"offvalueType": "str", |
|
"officon": "local_florist", |
|
"offcolor": "grey", |
|
"x": 130, |
|
"y": 520, |
|
"wires": [ |
|
[ |
|
"8a84b5dd.ae4e58" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "6441aba8.d2b1b4", |
|
"type": "ui_numeric", |
|
"z": "ee00a260.25be4", |
|
"name": "", |
|
"label": "Adjustment, %", |
|
"group": "97ade2e4.08d3a", |
|
"order": 3, |
|
"width": 0, |
|
"height": 0, |
|
"passthru": true, |
|
"topic": "adjustment", |
|
"format": "{{value}}", |
|
"min": 0, |
|
"max": "300", |
|
"step": "10", |
|
"x": 260, |
|
"y": 180, |
|
"wires": [ |
|
[ |
|
"11bb8145.de1bcf", |
|
"3e2ee852.8125c8" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "6fa30bc9.05bbe4", |
|
"type": "ui_switch", |
|
"z": "ee00a260.25be4", |
|
"name": "enable_water", |
|
"label": "Enable Watering", |
|
"group": "97ade2e4.08d3a", |
|
"order": 1, |
|
"width": 0, |
|
"height": 0, |
|
"passthru": true, |
|
"decouple": "false", |
|
"topic": "shm/garden/water/enable", |
|
"style": "", |
|
"onvalue": "on", |
|
"onvalueType": "str", |
|
"onicon": "", |
|
"oncolor": "", |
|
"offvalue": "off", |
|
"offvalueType": "str", |
|
"officon": "", |
|
"offcolor": "", |
|
"x": 120, |
|
"y": 280, |
|
"wires": [ |
|
[ |
|
"488908dd.205d88" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "f31149a4.c48a68", |
|
"type": "ui_text", |
|
"z": "ee00a260.25be4", |
|
"group": "97ade2e4.08d3a", |
|
"order": 4, |
|
"width": "1", |
|
"height": "1", |
|
"name": "counter", |
|
"label": "", |
|
"format": "{{msg.payload}}", |
|
"layout": "row-right", |
|
"x": 360, |
|
"y": 560, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "c3fda280.7177b", |
|
"type": "trigger", |
|
"z": "ee00a260.25be4", |
|
"op1": "", |
|
"op2": "", |
|
"op1type": "nul", |
|
"op2type": "pay", |
|
"duration": "1", |
|
"extend": false, |
|
"units": "min", |
|
"reset": "", |
|
"bytopic": "all", |
|
"name": "", |
|
"x": 140, |
|
"y": 640, |
|
"wires": [ |
|
[ |
|
"8a84b5dd.ae4e58" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "fd6e73a0.acea9", |
|
"type": "inject", |
|
"z": "ee00a260.25be4", |
|
"name": "water_sch_on", |
|
"topic": "shm/garden/water/enable", |
|
"payload": "on", |
|
"payloadType": "str", |
|
"repeat": "", |
|
"crontab": "", |
|
"once": true, |
|
"onceDelay": 0.1, |
|
"x": 100, |
|
"y": 240, |
|
"wires": [ |
|
[ |
|
"6fa30bc9.05bbe4" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "72ae558b.45668c", |
|
"type": "exec", |
|
"z": "ee00a260.25be4", |
|
"command": "actuators/valve.py 1 ", |
|
"addpay": true, |
|
"append": "", |
|
"useSpawn": "false", |
|
"timer": "", |
|
"oldrc": false, |
|
"name": "", |
|
"x": 760, |
|
"y": 520, |
|
"wires": [ |
|
[ |
|
"bb9aa72f.f142b8" |
|
], |
|
[ |
|
"697816e4.cf9db8" |
|
], |
|
[] |
|
] |
|
}, |
|
{ |
|
"id": "bc7c106c.5fdf3", |
|
"type": "inject", |
|
"z": "ee00a260.25be4", |
|
"name": "init_off", |
|
"topic": "", |
|
"payload": "off", |
|
"payloadType": "str", |
|
"repeat": "", |
|
"crontab": "", |
|
"once": true, |
|
"onceDelay": "0.05", |
|
"x": 370, |
|
"y": 320, |
|
"wires": [ |
|
[ |
|
"72ae558b.45668c" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "cfe6eb07.872248", |
|
"type": "persist out", |
|
"z": "ee00a260.25be4", |
|
"name": "watering_cor", |
|
"storageNode": "2c5b61a9.137b0e", |
|
"x": 90, |
|
"y": 180, |
|
"wires": [ |
|
[ |
|
"6441aba8.d2b1b4" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "11bb8145.de1bcf", |
|
"type": "persist in", |
|
"z": "ee00a260.25be4", |
|
"name": "watering_cor", |
|
"storageNode": "2c5b61a9.137b0e", |
|
"x": 450, |
|
"y": 220, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "3e2ee852.8125c8", |
|
"type": "trigger", |
|
"z": "ee00a260.25be4", |
|
"op1": "", |
|
"op2": "", |
|
"op1type": "nul", |
|
"op2type": "payl", |
|
"duration": "2", |
|
"extend": true, |
|
"units": "min", |
|
"reset": "", |
|
"bytopic": "all", |
|
"name": "delay 2m", |
|
"x": 440, |
|
"y": 180, |
|
"wires": [ |
|
[ |
|
"3bfb0b7c.5ef504" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "d3f2a255.22a5c", |
|
"type": "comment", |
|
"z": "ee00a260.25be4", |
|
"name": "____________ Watering system description ____________", |
|
"info": "3 circuits: Lawn, Tree, Stone.\nControls:\n- Enable/disable scheduling.\n- Adjust irrigation time in %.\n- Control each circuit separately with timer or manually.\n\nShow the status of each circuit on dashboard.\nShow watering log in dashboard.\nKeep/restore watering adjustment and watering chart.\n\n100% time and days per circuit:\nLawn - 50 min - Mon, Wed, Fri.\nTrees - 70 min - Tue, Sat.\nStone - 60 min - Thu, Sun.\n\nTODO:\n1 - Revise flow.set() variable name in UI_to_flow_context.\n2 - Adapt number of outputs in calc_off_offset function to your needs.\n", |
|
"x": 450, |
|
"y": 40, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "488908dd.205d88", |
|
"type": "change", |
|
"z": "ee00a260.25be4", |
|
"name": "switch2timer", |
|
"rules": [ |
|
{ |
|
"t": "change", |
|
"p": "payload", |
|
"pt": "msg", |
|
"from": "off", |
|
"fromt": "str", |
|
"to": "suspended true", |
|
"tot": "str" |
|
}, |
|
{ |
|
"t": "change", |
|
"p": "payload", |
|
"pt": "msg", |
|
"from": "on", |
|
"fromt": "str", |
|
"to": "suspended false", |
|
"tot": "str" |
|
} |
|
], |
|
"action": "", |
|
"property": "", |
|
"from": "", |
|
"to": "", |
|
"reg": false, |
|
"x": 150, |
|
"y": 320, |
|
"wires": [ |
|
[ |
|
"4ff10be1.cd3d94" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "bf519293.47cdb", |
|
"type": "ui_slider", |
|
"z": "ee00a260.25be4", |
|
"name": "timeout", |
|
"label": "Stop in {{value}} min", |
|
"group": "97ade2e4.08d3a", |
|
"order": 5, |
|
"width": 0, |
|
"height": 0, |
|
"passthru": true, |
|
"topic": "/shm/garden/timeout", |
|
"min": 0, |
|
"max": "90", |
|
"step": 1, |
|
"x": 340, |
|
"y": 140, |
|
"wires": [ |
|
[ |
|
"cb50e867.521618" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "cb50e867.521618", |
|
"type": "function", |
|
"z": "ee00a260.25be4", |
|
"name": "UI_to_flow_context", |
|
"func": "flow.set(\"get_water_timeout\", msg.payload);\nreturn null;", |
|
"outputs": 1, |
|
"noerr": 0, |
|
"x": 630, |
|
"y": 140, |
|
"wires": [ |
|
[] |
|
] |
|
}, |
|
{ |
|
"id": "a63bdebb.14d08", |
|
"type": "inject", |
|
"z": "ee00a260.25be4", |
|
"name": "", |
|
"topic": "", |
|
"payload": "10", |
|
"payloadType": "num", |
|
"repeat": "", |
|
"crontab": "", |
|
"once": true, |
|
"onceDelay": 0.1, |
|
"x": 110, |
|
"y": 140, |
|
"wires": [ |
|
[ |
|
"bf519293.47cdb" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "e32111f3.5f18c", |
|
"type": "trigger", |
|
"z": "ee00a260.25be4", |
|
"op1": "", |
|
"op2": "", |
|
"op1type": "nul", |
|
"op2type": "pay", |
|
"duration": "2", |
|
"extend": false, |
|
"units": "s", |
|
"reset": "", |
|
"bytopic": "all", |
|
"name": "2sec delay", |
|
"x": 550, |
|
"y": 560, |
|
"wires": [ |
|
[ |
|
"2363bd12.6c9232", |
|
"72ae558b.45668c", |
|
"3c42dbd2.1e05b4", |
|
"b902888f.45f258" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "4ff10be1.cd3d94", |
|
"type": "schedex", |
|
"z": "ee00a260.25be4", |
|
"name": "LawnTimer", |
|
"suspended": false, |
|
"lat": "32", |
|
"lon": "34", |
|
"ontime": "goldenHourEnd", |
|
"ontopic": "shm/garden/water_lawn/state", |
|
"onpayload": "on", |
|
"onoffset": "-20", |
|
"onrandomoffset": 0, |
|
"offtime": "goldenHourEnd", |
|
"offtopic": "shm/garden/water_lawn/state", |
|
"offpayload": "off", |
|
"offoffset": "30", |
|
"offrandomoffset": false, |
|
"mon": true, |
|
"tue": false, |
|
"wed": true, |
|
"thu": false, |
|
"fri": true, |
|
"sat": false, |
|
"sun": false, |
|
"x": 360, |
|
"y": 600, |
|
"wires": [ |
|
[ |
|
"e32111f3.5f18c" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "8a84b5dd.ae4e58", |
|
"type": "function", |
|
"z": "ee00a260.25be4", |
|
"name": "parse_timeout", |
|
"func": "// Outputs:\n// Counter_to_display, GPIO control via BigTimer, Counter_to_process\n\n// This beautiful expression doesn't work, gets default 10 always.\n// var delay = typeof(context.get('get_water_timeout') == undefined) ? 10 : flow.get('get_water_timeout');\n// This ugly construction works. :(\ntry{\n var delay = flow.get('get_water_timeout');\n} catch (er) {\n var delay = 10;\n}\n\nvar state = context.get('state') || 'ignore';\nvar topic = context.get('topic') || msg.topic;\ncontext.set('topic', topic);\nnode.status({fill:\"yellow\",shape:\"ring\",text: delay+','+state+','+msg.payload});\n\n// Block loop of messages when off\nif ('off' == msg.payload && 'off' == state) return [null, null, null];\nnode.status({fill:\"yellow\",shape:\"dot\",text: delay+','+state+','+msg.payload});\n\n// Keep msg for next round\nif ('on' == msg.payload) {\n // Don't count/display if fully manual\n var m1 = (delay > 0) ? {payload: delay} : null; \n // Set delay, start countdown, on load\n context.set('state', 'on');\n node.status({fill:\"green\", shape:\"dot\", text: delay+','+context.get('state')+','+msg.payload});\n return [m1, msg, m1]; \n} else if (('off' == msg.payload) || (parseInt(msg.payload) <= 1)) {\n // off load, reset clear counter\n context.set('state', 'off');\n node.status({fill:\"red\",shape:\"dot\",text: delay+','+context.get('state')+','+msg.payload});\n return [{payload: ' '}, {payload: 'off'}, null];\n} else if (parseInt(msg.payload) > 1 && context.get('state') == 'on') {\n // decrement countdown\n var m1 = {payload: parseInt(msg.payload)-1};\n node.status({fill:\"blue\",shape:\"dot\",text: delay+'>'+m1.payload+','+state+','+msg.payload});\n return [m1, null, m1];\n}\n\n// Unexpected state: look for a bug in reached here.\nnode.status({fill:\"grey\",shape:\"ring\",text: delay+','+state+','+msg.payload+'???'});\nreturn [{payload: ' '}, {payload: 'off'}, null];\n", |
|
"outputs": 3, |
|
"noerr": 0, |
|
"x": 130, |
|
"y": 580, |
|
"wires": [ |
|
[ |
|
"f31149a4.c48a68" |
|
], |
|
[ |
|
"4ff10be1.cd3d94", |
|
"3c42dbd2.1e05b4" |
|
], |
|
[ |
|
"c3fda280.7177b" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "298bc26f.bd320e", |
|
"type": "persist out", |
|
"z": "ee00a260.25be4", |
|
"name": "cmd_garden_lawn", |
|
"storageNode": "fe86bf2f.158b3", |
|
"x": 390, |
|
"y": 520, |
|
"wires": [ |
|
[ |
|
"e32111f3.5f18c" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "2363bd12.6c9232", |
|
"type": "persist in", |
|
"z": "ee00a260.25be4", |
|
"name": "cmd_garden_lawn", |
|
"storageNode": "fe86bf2f.158b3", |
|
"x": 750, |
|
"y": 560, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "3bfb0b7c.5ef504", |
|
"type": "function", |
|
"z": "ee00a260.25be4", |
|
"name": "calc_off_offset", |
|
"func": "/*\nPer each watering circuit in dictionary:\nCalculate new offtime from input payload.\n*/\n\nconst MAP = [ // Circuit: total time\n 50, // 'LawnTimer':\n 70, // 'TreeTimer': \n 60, // 'StoneTimer': \n];\nvar res = [];\n\nfor (const value of MAP) {\n res.push({payload: 'offoffset ' + Math.round(value * parseInt(msg.payload) / 100 - 20)});\n}\n\nreturn res;", |
|
"outputs": 3, |
|
"noerr": 0, |
|
"x": 620, |
|
"y": 180, |
|
"wires": [ |
|
[ |
|
"4ff10be1.cd3d94" |
|
], |
|
[], |
|
[] |
|
] |
|
}, |
|
{ |
|
"id": "7dd7b92d.8645b8", |
|
"type": "comment", |
|
"z": "ee00a260.25be4", |
|
"name": "__________ Circuit specific nodes: duplicate these per circuit __________", |
|
"info": "TO DO:\n1 - Set your schedule in Schedex Timer.\n2 - Set persist storage to store and restore last command.\n3 - Tune/replace Exec node with your actuator.\n4 - Rename UI switch.\n5 - In parse_timeout function set the same name to flow.get() as in UI_to_flow_context flow.set().\n6 - Connect output of switch2timer function to Schedex timer of each circuit.\n", |
|
"x": 460, |
|
"y": 480, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "fe5728ae.eb12f8", |
|
"type": "comment", |
|
"z": "ee00a260.25be4", |
|
"name": "Connect init_off to each actuator in your scheme", |
|
"info": "", |
|
"x": 420, |
|
"y": 280, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "60e2ab39.9b5004", |
|
"type": "comment", |
|
"z": "ee00a260.25be4", |
|
"name": "___________________ Common part for all circuits ___________________", |
|
"info": "", |
|
"x": 450, |
|
"y": 100, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "71a6bee0.2a10d", |
|
"type": "comment", |
|
"z": "ee00a260.25be4", |
|
"name": "Logging", |
|
"info": "", |
|
"x": 790, |
|
"y": 220, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "697816e4.cf9db8", |
|
"type": "mqtt out", |
|
"z": "ee00a260.25be4", |
|
"name": "", |
|
"topic": "", |
|
"qos": "", |
|
"retain": "", |
|
"broker": "af8eb750.bd7d38", |
|
"x": 770, |
|
"y": 340, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "db907094.b56ba", |
|
"type": "ui_chart", |
|
"z": "ee00a260.25be4", |
|
"name": "", |
|
"group": "97ade2e4.08d3a", |
|
"order": 6, |
|
"width": "6", |
|
"height": "3", |
|
"label": "Watering Log", |
|
"chartType": "line", |
|
"legend": "true", |
|
"xformat": "dd HH:mm", |
|
"interpolate": "step", |
|
"nodata": "No data", |
|
"dot": false, |
|
"ymin": "0", |
|
"ymax": "1", |
|
"removeOlder": 1, |
|
"removeOlderPoints": "", |
|
"removeOlderUnit": "604800", |
|
"cutout": 0, |
|
"useOneColor": false, |
|
"colors": [ |
|
"#1f77b4", |
|
"#aec7e8", |
|
"#ff7f0e", |
|
"#2ca02c", |
|
"#98df8a", |
|
"#d62728", |
|
"#ff9896", |
|
"#9467bd", |
|
"#c5b0d5" |
|
], |
|
"useOldStyle": false, |
|
"x": 550, |
|
"y": 400, |
|
"wires": [ |
|
[ |
|
"a50ff488.45b088" |
|
], |
|
[] |
|
] |
|
}, |
|
{ |
|
"id": "b902888f.45f258", |
|
"type": "function", |
|
"z": "ee00a260.25be4", |
|
"name": "msg2digit", |
|
"func": "var old = msg.payload;\nnode.status({text: old + '???'});\nif (msg.payload == null) return;\n\nif (msg.payload === true || \n msg.payload.toLowerCase() == 'open' || \n msg.payload.toLowerCase() == 'on' ||\n parseInt(msg.payload) > 0) { msg.payload = 1 }\n else if (msg.payload === false || \n msg.payload.toLowerCase() == 'close' || \n msg.payload.toLowerCase() == 'off' ||\n parseInt(msg.payload) <= 0) { msg.payload = 0 }\n else return;\n\nnode.status({text: old + \">>\" + msg.payload});\n\ntry{\n // Get 2nd word from the end of topic\n msg.topic = msg.topic.split('/').slice(-2)[0].trim();\n} catch (er) {\n node.status({text: 'Topic error'});\n return null;\n}\nnode.status({text: msg.topic + '>>' + old + \",\" + msg.payload});\n\nreturn msg;", |
|
"outputs": 1, |
|
"noerr": 0, |
|
"x": 240, |
|
"y": 400, |
|
"wires": [ |
|
[ |
|
"db907094.b56ba" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "a50ff488.45b088", |
|
"type": "persist in", |
|
"z": "ee00a260.25be4", |
|
"name": "watering", |
|
"storageNode": "5a252273.7c18ac", |
|
"x": 700, |
|
"y": 400, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "e27e688e.50e1c8", |
|
"type": "persist out", |
|
"z": "ee00a260.25be4", |
|
"name": "watering", |
|
"storageNode": "5a252273.7c18ac", |
|
"x": 400, |
|
"y": 420, |
|
"wires": [ |
|
[ |
|
"db907094.b56ba" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "c42a5fb9.33de2", |
|
"type": "comment", |
|
"z": "ee00a260.25be4", |
|
"name": "Connect here outputs from all actuators", |
|
"info": "", |
|
"x": 790, |
|
"y": 260, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "35e88818.b547e8", |
|
"type": "comment", |
|
"z": "ee00a260.25be4", |
|
"name": "Log visualization", |
|
"info": "", |
|
"x": 400, |
|
"y": 380, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "97ade2e4.08d3a", |
|
"type": "ui_group", |
|
"z": "", |
|
"name": "Garden: Watering", |
|
"tab": "11bccf83.c6223", |
|
"order": 1, |
|
"disp": true, |
|
"width": "6", |
|
"collapse": false |
|
}, |
|
{ |
|
"id": "2c5b61a9.137b0e", |
|
"type": "persist-store", |
|
"z": "", |
|
"filename": "watering_cor.json", |
|
"interval": "3600" |
|
}, |
|
{ |
|
"id": "fe86bf2f.158b3", |
|
"type": "persist-store", |
|
"z": "", |
|
"filename": "cmd_garden_lawn.json", |
|
"interval": "600" |
|
}, |
|
{ |
|
"id": "af8eb750.bd7d38", |
|
"type": "mqtt-broker", |
|
"z": "", |
|
"name": "", |
|
"broker": "localhost", |
|
"port": "1883", |
|
"clientid": "", |
|
"usetls": false, |
|
"compatmode": true, |
|
"keepalive": "60", |
|
"cleansession": true, |
|
"birthTopic": "", |
|
"birthQos": "0", |
|
"birthPayload": "", |
|
"willTopic": "", |
|
"willQos": "0", |
|
"willPayload": "" |
|
}, |
|
{ |
|
"id": "5a252273.7c18ac", |
|
"type": "persist-store", |
|
"z": "", |
|
"filename": "watering.json", |
|
"interval": "3600" |
|
}, |
|
{ |
|
"id": "11bccf83.c6223", |
|
"type": "ui_tab", |
|
"z": "", |
|
"name": "2share", |
|
"icon": "home", |
|
"order": 1 |
|
} |
|
] |