[
{
"id": "158e314c.71084f",
"type": "tab",
"label": "Main Flow",
"disabled": false,
"info": ""
},
{
"id": "3df81f27.d1f76",
"type": "subflow",
"name": "Read Config File",
"info": "",
"in": [
{
"x": 40,
"y": 100,
"wires": [
{
"id": "102caa65.5e8136"
}
]
}
],
"out": [
{
"x": 1100,
"y": 160,
"wires": [
{
"id": "19817ca3.d71323",
"port": 0
}
]
},
{
"x": 780,
"y": 220,
"wires": [
{
"id": "abdf15f5.da7a88",
"port": 1
}
]
}
]
},
{
"id": "ff451553.56fdc8",
"type": "subflow",
"name": "Pulse Output",
"info": "",
"in": [
{
"x": 40,
"y": 40,
"wires": [
{
"id": "41047203.dfad6c"
},
{
"id": "79351d76.b04894"
}
]
}
],
"out": [
{
"x": 960,
"y": 40,
"wires": [
{
"id": "3793de77.f6cbe2",
"port": 1
}
]
}
]
},
{
"id": "81a5424b.55e1d",
"type": "subflow",
"name": "Press Stop",
"info": "",
"in": [
{
"x": 200,
"y": 100,
"wires": [
{
"id": "60bd20c6.0025d"
}
]
}
],
"out": [
{
"x": 820,
"y": 100,
"wires": [
{
"id": "850355ef.851998",
"port": 0
}
]
}
]
},
{
"id": "9abe0d23.0b4f8",
"type": "subflow",
"name": "Pulse Output (2)",
"info": "",
"in": [
{
"x": 40,
"y": 40,
"wires": [
{
"id": "41047203.dfad6c"
},
{
"id": "79351d76.b04894"
}
]
}
],
"out": [
{
"x": 960,
"y": 40,
"wires": [
{
"id": "3793de77.f6cbe2",
"port": 1
}
]
}
]
},
{
"id": "25196831.e307e8",
"type": "subflow",
"name": "Press Start",
"info": "",
"in": [
{
"x": 140,
"y": 40,
"wires": [
{
"id": "bfb8739.367e79"
}
]
}
],
"out": [
{
"x": 620,
"y": 40,
"wires": [
{
"id": "b7028b9d.4d97c8",
"port": 0
}
]
}
]
},
{
"id": "9788ac6d.fc8e7",
"type": "subflow",
"name": "Chart Style",
"info": "",
"in": [
{
"x": 320,
"y": 60,
"wires": [
{
"id": "1c382f60.197ef1"
}
]
}
],
"out": [
{
"x": 700,
"y": 60,
"wires": [
{
"id": "1c382f60.197ef1",
"port": 0
}
]
}
]
},
{
"id": "a00cfa3a.41f338",
"type": "subflow",
"name": "Chart",
"info": "",
"in": [
{
"x": 200,
"y": 100,
"wires": [
{
"id": "91d0344.ca14fc8"
}
]
}
],
"out": [
{
"x": 620,
"y": 100,
"wires": [
{
"id": "91d0344.ca14fc8",
"port": 0
}
]
}
]
},
{
"id": "1314db79.10bc15",
"type": "subflow",
"name": "Pulse Output (3)",
"info": "",
"in": [
{
"x": 40,
"y": 40,
"wires": [
{
"id": "41047203.dfad6c"
},
{
"id": "79351d76.b04894"
}
]
}
],
"out": [
{
"x": 960,
"y": 40,
"wires": [
{
"id": "3793de77.f6cbe2",
"port": 1
}
]
}
]
},
{
"id": "8620b00f.557be",
"type": "websocket-listener",
"z": "158e314c.71084f",
"path": "/treadmill/clock",
"wholemsg": "false"
},
{
"id": "f7b7919.5b9c17",
"type": "exec",
"z": "3df81f27.d1f76",
"command": "ls ",
"addpay": true,
"append": "",
"useSpawn": "",
"timer": "",
"name": "Checkpassed file is there",
"x": 390,
"y": 100,
"wires": [
[
"abdf15f5.da7a88"
],
[],
[]
]
},
{
"id": "abdf15f5.da7a88",
"type": "function",
"z": "3df81f27.d1f76",
"name": "Handle Return",
"func": "if (msg.payload !== '')\n {\n msg.filename = flow.get('filename');\n return msg;\n }\nmsg.payload = 1;\nreturn [null,msg];\n",
"outputs": "2",
"noerr": 0,
"x": 580,
"y": 200,
"wires": [
[
"535f2194.14ff6"
],
[]
]
},
{
"id": "535f2194.14ff6",
"type": "file in",
"z": "3df81f27.d1f76",
"name": "Load Config",
"filename": "",
"format": "utf8",
"x": 810,
"y": 160,
"wires": [
[
"19817ca3.d71323"
]
]
},
{
"id": "19817ca3.d71323",
"type": "json",
"z": "3df81f27.d1f76",
"name": "Parse",
"x": 990,
"y": 160,
"wires": [
[]
]
},
{
"id": "102caa65.5e8136",
"type": "function",
"z": "3df81f27.d1f76",
"name": "Save Filename",
"func": "flow.set(\"filename\",msg.payload);\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 160,
"y": 100,
"wires": [
[
"f7b7919.5b9c17"
]
]
},
{
"id": "a1adac6a.11fc8",
"type": "trigger",
"z": "1314db79.10bc15",
"op1": "0",
"op2": "1",
"op1type": "num",
"op2type": "num",
"duration": "100",
"extend": false,
"units": "ms",
"reset": "",
"name": "Pulse Length",
"x": 410,
"y": 340,
"wires": [
[
"4e6c6245.26b0ac",
"60852ea2.56702"
]
]
},
{
"id": "35baf0bf.b736e",
"type": "function",
"z": "1314db79.10bc15",
"name": "Counter",
"func": "// initialise the counter to 0 if it doesn't exist already\nvar count;\nvar button = global.get(\"buttons\");\nif (msg.payload.count !== undefined)\n {\n count = msg.payload.count;\n global.set(\"btn\",button[msg.payload.button]);\n// if (button !== undefined)\n// node.warn (\"Pressing \" + button[msg.payload.button] + \" \" + msg.payload.count + \" times\");\n\nif (count === 0)\n {\n msg.payload = 1;\n// node.warn(\"Count came in as zero\");\n return [null,msg];\n }\n flow.set('count',count);\n flow.set('pin',msg.payload.button);\n msg.payload = 1;\n }\n\nif (msg.payload === 1) // the pulse ended\n {\n count = flow.get('count');\n// node.warn(\"Getting count \" + count);\n if (count > 0)\n {\n msg.payload = 1;\n count -= 1;\n // store the value back\n flow.set('count',count);\n// node.warn(\"pulsing \" + global.get(\"btn\"));\n return msg;\n }\n else\n {\n // done\n// node.warn(\"Pulsing \" + global.get(\"btn\") + \" done\");\n msg.payload = 1;\n return [null,msg];\n } \n }\n",
"outputs": "3",
"noerr": 0,
"x": 408,
"y": 206,
"wires": [
[
"24873f6c.7fb12"
],
[
"3793de77.f6cbe2"
],
[]
]
},
{
"id": "9c5c0f97.3da11",
"type": "delay",
"z": "1314db79.10bc15",
"name": "Pulse Delay",
"pauseType": "delay",
"timeout": "100",
"timeoutUnits": "milliseconds",
"rate": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"x": 412,
"y": 275,
"wires": [
[
"31b6e346.0a85fc"
]
]
},
{
"id": "5e9e4e0b.1b6dc",
"type": "switch",
"z": "1314db79.10bc15",
"name": "",
"property": "pin",
"propertyType": "flow",
"rules": [
{
"t": "eq",
"v": "40",
"vt": "num"
},
{
"t": "eq",
"v": "38",
"vt": "num"
},
{
"t": "eq",
"v": "37",
"vt": "num"
},
{
"t": "eq",
"v": "36",
"vt": "num"
},
{
"t": "eq",
"v": "35",
"vt": "num"
},
{
"t": "eq",
"v": "33",
"vt": "num"
},
{
"t": "eq",
"v": "32",
"vt": "str"
}
],
"checkall": "true",
"outputs": 7,
"x": 630,
"y": 320,
"wires": [
[
"c9aaabe.0c48b58"
],
[
"94e8772.0a2ea88"
],
[
"3e7dc97e.777246"
],
[
"79557b2.fad1e84"
],
[
"f57cd800.50f138"
],
[
"72b03f04.9ee18"
],
[
"b864f721.9d0f28"
]
]
},
{
"id": "91592364.7cd46",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Incline Up (40/21)",
"pin": "40",
"set": true,
"level": "1",
"out": "out",
"x": 886,
"y": 141,
"wires": []
},
{
"id": "75ffdd73.f1d3a4",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Incline Down (38/20)",
"pin": "38",
"set": true,
"level": "1",
"out": "out",
"x": 894,
"y": 199,
"wires": []
},
{
"id": "d5c94ed6.8791c",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Speed Up (37/26)",
"pin": "37",
"set": true,
"level": "1",
"out": "out",
"x": 886,
"y": 261,
"wires": []
},
{
"id": "ec624d05.ea8fa",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Speed Down (36/16)",
"pin": "36",
"set": true,
"level": "1",
"out": "out",
"x": 911,
"y": 315,
"wires": []
},
{
"id": "2fef3c40.6968f4",
"type": "change",
"z": "1314db79.10bc15",
"name": "Button Translator",
"rules": [
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "InclineUp",
"fromt": "str",
"to": "40",
"tot": "num"
},
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "InclineDown",
"fromt": "str",
"to": "38",
"tot": "num"
},
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "SpeedUp",
"fromt": "str",
"to": "37",
"tot": "num"
},
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "SpeedDown",
"fromt": "str",
"to": "36",
"tot": "str"
},
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "Start",
"fromt": "str",
"to": "35",
"tot": "num"
},
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "Stop",
"fromt": "str",
"to": "33",
"tot": "str"
},
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "Pause",
"fromt": "str",
"to": "32",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 158,
"y": 206,
"wires": [
[
"31b6e346.0a85fc"
]
]
},
{
"id": "df966913.ab2738",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Start (35/19)",
"pin": "35",
"set": true,
"level": "1",
"out": "out",
"x": 869,
"y": 376,
"wires": []
},
{
"id": "60a306a7.a84338",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Stop (33/13)",
"pin": "33",
"set": true,
"level": "1",
"out": "out",
"x": 866,
"y": 432,
"wires": []
},
{
"id": "d92e28d3.41a6e8",
"type": "function",
"z": "1314db79.10bc15",
"name": "Command Cycler",
"func": "var stack;\n//node.warn(\"d1\");\n//node.warn(msg.payload);\n\nif (Array.isArray(msg.payload))\n {\n// node.warn(\"Getting stack\");\n stack = msg.payload; // save the initial stack\n }\nelse\n {\n stack = global.get(\"stack\");\n// node.warn(\"Getting stored stack\");\n }\n\nmsg.payload = stack.shift(); // get the top command of the stack\nif (msg.payload === undefined)\n {\n// node.warn(\"Done Array\");\n msg.payload = 1;\n return [null,msg];\n }\nglobal.set(\"stack\",stack); // save the remaining cmds stack\n//node.warn(\"sending command\");\nreturn [msg,null]; // return the next command",
"outputs": "2",
"noerr": 0,
"x": 530,
"y": 20,
"wires": [
[
"fbfd91ab.3dc4"
],
[]
]
},
{
"id": "a9990521.96d778",
"type": "change",
"z": "1314db79.10bc15",
"name": "Reset All Relays",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "1",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 600,
"y": 100,
"wires": [
[
"c9aaabe.0c48b58",
"94e8772.0a2ea88",
"3e7dc97e.777246",
"79557b2.fad1e84",
"f57cd800.50f138",
"72b03f04.9ee18",
"b864f721.9d0f28",
"23ebea6d.751356"
]
]
},
{
"id": "f4234852.59e8c8",
"type": "delay",
"z": "1314db79.10bc15",
"name": "",
"pauseType": "delay",
"timeout": "250",
"timeoutUnits": "milliseconds",
"rate": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"x": 290,
"y": 20,
"wires": [
[
"3793de77.f6cbe2"
]
]
},
{
"id": "5642b5c6.2f005c",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Pause 32/12",
"pin": "32",
"set": true,
"level": "1",
"out": "out",
"x": 880,
"y": 500,
"wires": []
},
{
"id": "167edb66.f1b785",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Relay 8 - 31/6 Unused",
"pin": "31",
"set": true,
"level": "1",
"out": "out",
"x": 910,
"y": 560,
"wires": []
},
{
"id": "a01512ba.55d36",
"type": "debug",
"z": "1314db79.10bc15",
"name": "",
"active": true,
"console": "false",
"complete": "false",
"x": 680,
"y": 560,
"wires": []
},
{
"id": "60bd20c6.0025d",
"type": "function",
"z": "81a5424b.55e1d",
"name": "Press Stop",
"func": "msg.payload = [{\"count\":1,\"button\":\"Stop\"}];\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 390,
"y": 100,
"wires": [
[
"850355ef.851998"
]
]
},
{
"id": "850355ef.851998",
"type": "subflow:1314db79.10bc15",
"z": "81a5424b.55e1d",
"x": 570,
"y": 100,
"wires": [
[]
]
},
{
"id": "12d1e8e3.4b88f7",
"type": "trigger",
"z": "1314db79.10bc15",
"op1": "0",
"op2": "1",
"op1type": "num",
"op2type": "num",
"duration": "100",
"extend": false,
"units": "ms",
"reset": "",
"name": "Pulse Length",
"x": 410,
"y": 340,
"wires": [
[
"4e6c6245.26b0ac",
"60852ea2.56702"
]
]
},
{
"id": "cd327f84.0c51f",
"type": "function",
"z": "1314db79.10bc15",
"name": "Counter",
"func": "// initialise the counter to 0 if it doesn't exist already\nvar count;\nvar button = global.get(\"buttons\");\nif (msg.payload.count !== undefined)\n {\n count = msg.payload.count;\n global.set(\"btn\",button[msg.payload.button]);\n// if (button !== undefined)\n// node.warn (\"Pressing \" + button[msg.payload.button] + \" \" + msg.payload.count + \" times\");\n\nif (count === 0)\n {\n msg.payload = 1;\n// node.warn(\"Count came in as zero\");\n return [null,msg];\n }\n flow.set('count',count);\n flow.set('pin',msg.payload.button);\n msg.payload = 1;\n }\n\nif (msg.payload === 1) // the pulse ended\n {\n count = flow.get('count');\n// node.warn(\"Getting count \" + count);\n if (count > 0)\n {\n msg.payload = 1;\n count -= 1;\n // store the value back\n flow.set('count',count);\n// node.warn(\"pulsing \" + global.get(\"btn\"));\n return msg;\n }\n else\n {\n // done\n// node.warn(\"Pulsing \" + global.get(\"btn\") + \" done\");\n msg.payload = 1;\n return [null,msg];\n } \n }\n",
"outputs": "3",
"noerr": 0,
"x": 408,
"y": 206,
"wires": [
[
"24873f6c.7fb12"
],
[
"3793de77.f6cbe2"
],
[]
]
},
{
"id": "1bf37045.02ab3",
"type": "delay",
"z": "1314db79.10bc15",
"name": "Pulse Delay",
"pauseType": "delay",
"timeout": "100",
"timeoutUnits": "milliseconds",
"rate": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"x": 412,
"y": 275,
"wires": [
[
"31b6e346.0a85fc"
]
]
},
{
"id": "c49b5eee.24bcb",
"type": "switch",
"z": "1314db79.10bc15",
"name": "",
"property": "pin",
"propertyType": "flow",
"rules": [
{
"t": "eq",
"v": "40",
"vt": "num"
},
{
"t": "eq",
"v": "38",
"vt": "num"
},
{
"t": "eq",
"v": "37",
"vt": "num"
},
{
"t": "eq",
"v": "36",
"vt": "num"
},
{
"t": "eq",
"v": "35",
"vt": "num"
},
{
"t": "eq",
"v": "33",
"vt": "num"
},
{
"t": "eq",
"v": "32",
"vt": "str"
}
],
"checkall": "true",
"outputs": 7,
"x": 630,
"y": 320,
"wires": [
[
"c9aaabe.0c48b58"
],
[
"94e8772.0a2ea88"
],
[
"3e7dc97e.777246"
],
[
"79557b2.fad1e84"
],
[
"f57cd800.50f138"
],
[
"72b03f04.9ee18"
],
[
"b864f721.9d0f28"
]
]
},
{
"id": "8a53343d.524b08",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Incline Up (40/21)",
"pin": "40",
"set": true,
"level": "1",
"out": "out",
"x": 886,
"y": 141,
"wires": []
},
{
"id": "c946f9f8.65a968",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Incline Down (38/20)",
"pin": "38",
"set": true,
"level": "1",
"out": "out",
"x": 894,
"y": 199,
"wires": []
},
{
"id": "377883f2.45a35c",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Speed Up (37/26)",
"pin": "37",
"set": true,
"level": "1",
"out": "out",
"x": 886,
"y": 261,
"wires": []
},
{
"id": "90ff56ca.37dfc8",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Speed Down (36/16)",
"pin": "36",
"set": true,
"level": "1",
"out": "out",
"x": 911,
"y": 315,
"wires": []
},
{
"id": "dead5cad.9fea1",
"type": "change",
"z": "1314db79.10bc15",
"name": "Button Translator",
"rules": [
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "InclineUp",
"fromt": "str",
"to": "40",
"tot": "num"
},
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "InclineDown",
"fromt": "str",
"to": "38",
"tot": "num"
},
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "SpeedUp",
"fromt": "str",
"to": "37",
"tot": "num"
},
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "SpeedDown",
"fromt": "str",
"to": "36",
"tot": "str"
},
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "Start",
"fromt": "str",
"to": "35",
"tot": "num"
},
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "Stop",
"fromt": "str",
"to": "33",
"tot": "str"
},
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "Pause",
"fromt": "str",
"to": "32",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 158,
"y": 206,
"wires": [
[
"31b6e346.0a85fc"
]
]
},
{
"id": "69dc0637.3834c8",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Start (35/19)",
"pin": "35",
"set": true,
"level": "1",
"out": "out",
"x": 869,
"y": 376,
"wires": []
},
{
"id": "7ad71e57.2fcd2",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Stop (33/13)",
"pin": "33",
"set": true,
"level": "1",
"out": "out",
"x": 866,
"y": 432,
"wires": []
},
{
"id": "d2656670.dce9f8",
"type": "function",
"z": "1314db79.10bc15",
"name": "Command Cycler",
"func": "var stack;\n//node.warn(\"d1\");\n//node.warn(msg.payload);\n\nif (Array.isArray(msg.payload))\n {\n// node.warn(\"Getting stack\");\n stack = msg.payload; // save the initial stack\n }\nelse\n {\n stack = global.get(\"stack\");\n// node.warn(\"Getting stored stack\");\n }\n\nmsg.payload = stack.shift(); // get the top command of the stack\nif (msg.payload === undefined)\n {\n// node.warn(\"Done Array\");\n msg.payload = 1;\n return [null,msg];\n }\nglobal.set(\"stack\",stack); // save the remaining cmds stack\n//node.warn(\"sending command\");\nreturn [msg,null]; // return the next command",
"outputs": "2",
"noerr": 0,
"x": 530,
"y": 20,
"wires": [
[
"fbfd91ab.3dc4"
],
[]
]
},
{
"id": "e6240bd.b800bf8",
"type": "change",
"z": "1314db79.10bc15",
"name": "Reset All Relays",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "1",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 600,
"y": 100,
"wires": [
[
"c9aaabe.0c48b58",
"94e8772.0a2ea88",
"3e7dc97e.777246",
"79557b2.fad1e84",
"f57cd800.50f138",
"72b03f04.9ee18",
"b864f721.9d0f28",
"23ebea6d.751356"
]
]
},
{
"id": "5345c053.f7e67",
"type": "delay",
"z": "1314db79.10bc15",
"name": "",
"pauseType": "delay",
"timeout": "250",
"timeoutUnits": "milliseconds",
"rate": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"x": 290,
"y": 20,
"wires": [
[
"3793de77.f6cbe2"
]
]
},
{
"id": "37add411.aa815c",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Pause 32/12",
"pin": "32",
"set": true,
"level": "1",
"out": "out",
"x": 880,
"y": 500,
"wires": []
},
{
"id": "d6225a21.555d78",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Relay 8 - 31/6 Unused",
"pin": "31",
"set": true,
"level": "1",
"out": "out",
"x": 910,
"y": 560,
"wires": []
},
{
"id": "83d795b8.4128c8",
"type": "debug",
"z": "1314db79.10bc15",
"name": "",
"active": true,
"console": "false",
"complete": "false",
"x": 680,
"y": 560,
"wires": []
},
{
"id": "bfb8739.367e79",
"type": "function",
"z": "25196831.e307e8",
"name": "Press Start",
"func": "//node.warn(\"Pressing Start\");\nmsg.payload = [{\"count\":1,\"button\":\"Start\"}];\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 290,
"y": 40,
"wires": [
[
"b7028b9d.4d97c8"
]
]
},
{
"id": "b7028b9d.4d97c8",
"type": "subflow:1314db79.10bc15",
"z": "25196831.e307e8",
"x": 470,
"y": 40,
"wires": [
[]
]
},
{
"id": "1c382f60.197ef1",
"type": "template",
"z": "9788ac6d.fc8e7",
"name": "Chart Style",
"field": "chartstyle",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": "/* Style Sheet */\n.chartdiv {\n margin: 10px auto;\n width: 95%;\n BORDER: 2px solid #606dad;\n padding: 4px;\n border-radius: 9px;\n background-color: #9196af;\n}\n\n.chartdiv td {\n height: 20px;\n width: 15px;\n}\n\n.chartdiv .whitebox {\n background-color: #ccc;\n }\n \n.chartdiv .selectedwhitebox {\n background-color: #561232;\n }\n \n.chartdiv .speedbox {\n background-color: rgba(158, 53, 16, 0.64);\n}\n\n.chartdiv .inclinebox {\n background-color: rgba(57, 46, 167, 0.69);\n border-right: 2px solid #ccc;\n}\n\n.chartdiv .selectedspeedbox {\n background-color: rgba(158, 53, 16, 1.0);\n}\n\n.chartdiv .selectedinclinebox {\n background-color: rgba(57, 46, 167, 1.0);\n border-right: 2px solid #ccc;\n }\n\n.chartdiv .chartdiv {\n padding: 6px;\n font-weight: bold;\n}\n\n.chartdiv table {\n padding: 10px;\n border: 2px #555 solid;\n background-color: #ccc;\n border-radius: 10px;\n margin: 0 auto;\n width: 95%;\n }\n \n.chartdiv .legend {\n margin: 2px auto;\n border-right: 0;\n font-weight: bold;\n color: white;\n width: 100px;\n text-align: center;\n }\n \n.chartdiv .programtitle {\n font-size: 16px;\n font-weight: bold;\n padding-left: 10px;\n }",
"x": 530,
"y": 60,
"wires": [
[]
]
},
{
"id": "91d0344.ca14fc8",
"type": "function",
"z": "a00cfa3a.41f338",
"name": "Chart Generator",
"func": "context.global.createChart = function(programno,currentstep,selected)\n {\n html = \"\";\n var speed = 0;\n var include = 0;\n var col;\n programno = parseInt(programno);\n if (currentstep === undefined)\n currentstep = -1;\n var program = global.get(\"programs\")[programno];\n// node.warn(\"Program: \" + programno);\n html += \"
\";\n html += \"
\";\n if (selected !== undefined)\n {\n html += \"
\";\n html += \" \" : \"> \"; \n html += \"\";\n html += \"
\";\n }\n else\n {\n html += \"Program \" + (programno + 1) + \" - \" + program.name;\n }\n html += \"
\";\n html += \"
\";\n html += \"
';\n\n for (var row=4; row>=0; row--)\n {\n html += \" | \";\n for (col=0; col < global.get(\"timesteps\"); col++)\n {\n //node.warn(program[col]);\n if (program[col] !== undefined)\n {\n speed = program[col].speed;\n incline = program[col].incline;\n }\n //node.warn(\"Speed:\" + speed + \" Incline:\" + incline);\n speedclass = row >= speed ? \"whitebox\" : \n col<=currentstep?\"selectedspeedbox\": \"speedbox\";\n inclineclass = row >= incline ? \"whitebox\" :\n col<=currentstep?\"selectedinclinebox\": \"inclinebox\";\n html += \" | \\n\"; \n html += \" | \\n\"; \n }\n html += \"
\\n\";\n }\n html += \"\"; // OUTPUT THE BASELINE ELEMENTS\n for (col=0; col < global.get(\"timesteps\"); col++)\n {\n speedclass = col<=currentstep?\"selectedspeedbox\": \"speedbox\";\n inclineclass = col<=currentstep?\"selectedinclinebox\": \"inclinebox\";\n html += \" | \\n\"; \n html += \" | \\n\"; \n }\n html += \"
\\n\";\n html += \"
\";\n return html;\n }\n \nreturn msg;\n\n",
"outputs": 1,
"noerr": 0,
"x": 410,
"y": 100,
"wires": [
[]
]
},
{
"id": "24873f6c.7fb12",
"type": "trigger",
"z": "1314db79.10bc15",
"op1": "0",
"op2": "1",
"op1type": "num",
"op2type": "num",
"duration": "100",
"extend": false,
"units": "ms",
"reset": "",
"name": "Pulse Length",
"x": 410,
"y": 340,
"wires": [
[
"4e6c6245.26b0ac",
"60852ea2.56702"
]
]
},
{
"id": "31b6e346.0a85fc",
"type": "function",
"z": "1314db79.10bc15",
"name": "Counter",
"func": "// initialise the counter to 0 if it doesn't exist already\nvar count;\nvar button = global.get(\"buttons\");\nif (msg.payload.count !== undefined)\n {\n count = msg.payload.count;\n global.set(\"btn\",button[msg.payload.button]);\n// if (button !== undefined)\n// node.warn (\"Pressing \" + button[msg.payload.button] + \" \" + msg.payload.count + \" times\");\n\nif (count === 0)\n {\n msg.payload = 1;\n// node.warn(\"Count came in as zero\");\n return [null,msg];\n }\n flow.set('count',count);\n flow.set('pin',msg.payload.button);\n msg.payload = 1;\n }\n\nif (msg.payload === 1) // the pulse ended\n {\n count = flow.get('count');\n// node.warn(\"Getting count \" + count);\n if (count > 0)\n {\n msg.payload = 1;\n count -= 1;\n // store the value back\n flow.set('count',count);\n// node.warn(\"pulsing \" + global.get(\"btn\"));\n return msg;\n }\n else\n {\n // done\n// node.warn(\"Pulsing \" + global.get(\"btn\") + \" done\");\n msg.payload = 1;\n return [null,msg];\n } \n }\n",
"outputs": "3",
"noerr": 0,
"x": 408,
"y": 206,
"wires": [
[
"24873f6c.7fb12"
],
[
"3793de77.f6cbe2"
],
[]
]
},
{
"id": "60852ea2.56702",
"type": "delay",
"z": "1314db79.10bc15",
"name": "Pulse Delay",
"pauseType": "delay",
"timeout": "100",
"timeoutUnits": "milliseconds",
"rate": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"x": 412,
"y": 275,
"wires": [
[
"31b6e346.0a85fc"
]
]
},
{
"id": "4e6c6245.26b0ac",
"type": "switch",
"z": "1314db79.10bc15",
"name": "",
"property": "pin",
"propertyType": "flow",
"rules": [
{
"t": "eq",
"v": "40",
"vt": "num"
},
{
"t": "eq",
"v": "38",
"vt": "num"
},
{
"t": "eq",
"v": "37",
"vt": "num"
},
{
"t": "eq",
"v": "36",
"vt": "num"
},
{
"t": "eq",
"v": "35",
"vt": "num"
},
{
"t": "eq",
"v": "33",
"vt": "num"
},
{
"t": "eq",
"v": "32",
"vt": "str"
}
],
"checkall": "true",
"outputs": 7,
"x": 630,
"y": 320,
"wires": [
[
"c9aaabe.0c48b58"
],
[
"94e8772.0a2ea88"
],
[
"3e7dc97e.777246"
],
[
"79557b2.fad1e84"
],
[
"f57cd800.50f138"
],
[
"72b03f04.9ee18"
],
[
"b864f721.9d0f28"
]
]
},
{
"id": "c9aaabe.0c48b58",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Incline Up (40/21)",
"pin": "40",
"set": true,
"level": "1",
"out": "out",
"x": 886,
"y": 141,
"wires": []
},
{
"id": "94e8772.0a2ea88",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Incline Down (38/20)",
"pin": "38",
"set": true,
"level": "1",
"out": "out",
"x": 894,
"y": 199,
"wires": []
},
{
"id": "3e7dc97e.777246",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Speed Up (37/26)",
"pin": "37",
"set": true,
"level": "1",
"out": "out",
"x": 886,
"y": 261,
"wires": []
},
{
"id": "79557b2.fad1e84",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Speed Down (36/16)",
"pin": "36",
"set": true,
"level": "1",
"out": "out",
"x": 911,
"y": 315,
"wires": []
},
{
"id": "fbfd91ab.3dc4",
"type": "change",
"z": "1314db79.10bc15",
"name": "Button Translator",
"rules": [
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "InclineUp",
"fromt": "str",
"to": "40",
"tot": "num"
},
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "InclineDown",
"fromt": "str",
"to": "38",
"tot": "num"
},
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "SpeedUp",
"fromt": "str",
"to": "37",
"tot": "num"
},
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "SpeedDown",
"fromt": "str",
"to": "36",
"tot": "str"
},
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "Start",
"fromt": "str",
"to": "35",
"tot": "num"
},
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "Stop",
"fromt": "str",
"to": "33",
"tot": "str"
},
{
"t": "change",
"p": "payload.button",
"pt": "msg",
"from": "Pause",
"fromt": "str",
"to": "32",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 158,
"y": 206,
"wires": [
[
"31b6e346.0a85fc"
]
]
},
{
"id": "f57cd800.50f138",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Start (35/19)",
"pin": "35",
"set": true,
"level": "1",
"out": "out",
"x": 869,
"y": 376,
"wires": []
},
{
"id": "72b03f04.9ee18",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Stop (33/13)",
"pin": "33",
"set": true,
"level": "1",
"out": "out",
"x": 866,
"y": 432,
"wires": []
},
{
"id": "3793de77.f6cbe2",
"type": "function",
"z": "1314db79.10bc15",
"name": "Command Cycler",
"func": "var stack;\n//node.warn(\"d1\");\n//node.warn(msg.payload);\n\nif (Array.isArray(msg.payload))\n {\n// node.warn(\"Getting stack\");\n stack = msg.payload; // save the initial stack\n }\nelse\n {\n stack = global.get(\"stack\");\n// node.warn(\"Getting stored stack\");\n }\n\nmsg.payload = stack.shift(); // get the top command of the stack\nif (msg.payload === undefined)\n {\n// node.warn(\"Done Array\");\n msg.payload = 1;\n return [null,msg];\n }\nglobal.set(\"stack\",stack); // save the remaining cmds stack\n//node.warn(\"sending command\");\nreturn [msg,null]; // return the next command",
"outputs": "2",
"noerr": 0,
"x": 530,
"y": 20,
"wires": [
[
"fbfd91ab.3dc4"
],
[]
]
},
{
"id": "79351d76.b04894",
"type": "change",
"z": "1314db79.10bc15",
"name": "Reset All Relays",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "1",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 600,
"y": 100,
"wires": [
[
"c9aaabe.0c48b58",
"94e8772.0a2ea88",
"3e7dc97e.777246",
"79557b2.fad1e84",
"f57cd800.50f138",
"72b03f04.9ee18",
"b864f721.9d0f28",
"23ebea6d.751356"
]
]
},
{
"id": "41047203.dfad6c",
"type": "delay",
"z": "1314db79.10bc15",
"name": "",
"pauseType": "delay",
"timeout": "250",
"timeoutUnits": "milliseconds",
"rate": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"x": 290,
"y": 20,
"wires": [
[
"3793de77.f6cbe2"
]
]
},
{
"id": "b864f721.9d0f28",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Pause 32/12",
"pin": "32",
"set": true,
"level": "1",
"out": "out",
"x": 880,
"y": 500,
"wires": []
},
{
"id": "23ebea6d.751356",
"type": "rpi-gpio out",
"z": "1314db79.10bc15",
"name": "Relay 8 - 31/6 Unused",
"pin": "31",
"set": true,
"level": "1",
"out": "out",
"x": 910,
"y": 560,
"wires": []
},
{
"id": "f4ca549.6ae83a8",
"type": "debug",
"z": "1314db79.10bc15",
"name": "",
"active": true,
"console": "false",
"complete": "false",
"x": 680,
"y": 560,
"wires": []
},
{
"id": "f006fdf5.d8fe",
"type": "subflow:1314db79.10bc15",
"z": "158e314c.71084f",
"x": 360,
"y": 1000,
"wires": [
[
"96a4ae77.b42a"
]
]
},
{
"id": "2144e37e.ca249c",
"type": "http response",
"z": "158e314c.71084f",
"name": "web out",
"x": 1230,
"y": 1000,
"wires": []
},
{
"id": "4f1d7e35.ad794",
"type": "subflow:1314db79.10bc15",
"z": "158e314c.71084f",
"x": 360,
"y": 1200,
"wires": [
[
"fb2a07d1.a00918"
]
]
},
{
"id": "c02abd9c.1e652",
"type": "subflow:1314db79.10bc15",
"z": "158e314c.71084f",
"x": 351,
"y": 1139,
"wires": [
[
"aea37578.fb03f8"
]
]
},
{
"id": "80e9d7df.b56c98",
"type": "subflow:1314db79.10bc15",
"z": "158e314c.71084f",
"x": 360,
"y": 1260,
"wires": [
[
"9b326b13.9a5a38"
]
]
},
{
"id": "ed1f2d9a.4ddb6",
"type": "http in",
"z": "158e314c.71084f",
"name": "",
"url": "/treadmill",
"method": "get",
"swaggerDoc": "",
"x": 60,
"y": 60,
"wires": [
[
"801f68a8.a14248",
"72da95d9.3e3f1c"
]
]
},
{
"id": "9342013c.b3891",
"type": "template",
"z": "158e314c.71084f",
"name": "Form",
"field": "payload",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": "\n\n \n Treadmill Programmer\n \n \n \n \n \n \n {{{script}}}\n \n\n",
"x": 880,
"y": 400,
"wires": [
[
"f0efec4d.34d8"
]
]
},
{
"id": "f0efec4d.34d8",
"type": "http response",
"z": "158e314c.71084f",
"name": "",
"x": 1020,
"y": 400,
"wires": []
},
{
"id": "71819a22.7f00f4",
"type": "http in",
"z": "158e314c.71084f",
"name": "",
"url": "/treadmill/storeandgo",
"method": "post",
"swaggerDoc": "",
"x": 100,
"y": 764,
"wires": [
[
"50622682.881788"
]
]
},
{
"id": "97bf980c.f74958",
"type": "file",
"z": "158e314c.71084f",
"name": "Save Config",
"filename": "",
"appendNewline": true,
"createDir": false,
"overwriteFile": "true",
"x": 620,
"y": 840,
"wires": []
},
{
"id": "ad073d06.f485e",
"type": "function",
"z": "158e314c.71084f",
"name": "Set Weight",
"func": "//node.warn(\"Setting weight\");\nvar weight = global.get(\"weight\") - global.get(\"initialweight\");\nif (weight >= 0)\n msg.payload = [{\"count\":weight,\"button\":\"SpeedUp\"}];\nelse if (weight < 0)\n msg.payload = [{\"count\":-weight,\"button\":\"SpeedDown\"}];\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 140,
"y": 1200,
"wires": [
[
"4f1d7e35.ad794"
]
]
},
{
"id": "e4f341a3.8951b",
"type": "function",
"z": "158e314c.71084f",
"name": "Set Time",
"func": "//node.warn(\"Setting time\");\nvar time = global.get(\"time\") - global.get(\"initialtime\");\nif (time > 0)\n msg.payload = [{\"count\":time+2,\"button\":\"SpeedUp\"}];\nelse if (time < 0)\n msg.payload = [{\"count\":-time-2,\"button\":\"SpeedDown\"}];\nelse\n msg.payload = [];\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 130,
"y": 1260,
"wires": [
[
"80e9d7df.b56c98"
]
]
},
{
"id": "ba13f105.7b13",
"type": "template",
"z": "158e314c.71084f",
"name": "Script",
"field": "script",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": "\n",
"x": 740,
"y": 400,
"wires": [
[
"9342013c.b3891"
]
]
},
{
"id": "595309a.d8821f8",
"type": "comment",
"z": "158e314c.71084f",
"name": "Display Setup Form",
"info": "",
"x": 1180,
"y": 400,
"wires": []
},
{
"id": "eeb9e4b4.8651d8",
"type": "comment",
"z": "158e314c.71084f",
"name": "Store Settings",
"info": "Save the settings to a file and set the globals",
"x": 920,
"y": 800,
"wires": []
},
{
"id": "8031992a.67e118",
"type": "comment",
"z": "158e314c.71084f",
"name": "Initialize Treadmill",
"info": "",
"x": 780,
"y": 1180,
"wires": []
},
{
"id": "e7f57b5c.872088",
"type": "template",
"z": "158e314c.71084f",
"name": "Form",
"field": "payload",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": "\n\n \n Treadmill Programmer\n \n \n {{{chartparams}}}\n {{{googlechart}}}\n \n \n \n
\n
Treadmill Program
\n
\n
\n
\n
\n
\n \n \n \n
\n
\n \n
\n
\n
\n \n \n\n",
"x": 1080,
"y": 1000,
"wires": [
[
"2144e37e.ca249c"
]
]
},
{
"id": "3649d594.261e0a",
"type": "template",
"z": "158e314c.71084f",
"name": "Script",
"field": "script",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": " var ws;\n var wsUri = \"ws:\";\n var loc = window.location;\n console.log(loc);\n if (loc.protocol === \"https:\") { wsUri = \"wss:\"; }\n // This needs to point to the web socket in the Node-RED flow\n\n wsUri += \"//\" + loc.host + loc.pathname.replace(\"storeandgo\",\"clock\");\n\n function wsConnect() {\n //console.log(\"connect\",wsUri);\n ws = new WebSocket(wsUri);\n //console.log(Object.getOwnPropertyNames(WebSocket));\n //var line = \"\"; // either uncomment this for a building list of messages\n ws.onmessage = function(msg) {\n // parse the incoming message as a JSON object\n // console.log(msg);\n var message=JSON.parse(msg.data);\n var textmsg = message[0];\n var graph = message[1];\n var msgtype = message[2];\n if (message[3] != null)\n {\n if (message[3].time != null)\n {\n var time = message[3].time;\n chartdata0.setValue(0, 1, time);\n chart0.draw(chartdata0, chartoptions0);\n }\n if (message[3].secsleft != null)\n {\n var secsleft = message[3].secsleft;\n chartdata3.setValue(0, 1, secsleft);\n chart3.draw(chartdata3, chartoptions3);\n }\n if (message[3].speed != null)\n {\n var speed = message[3].speed;\n chartdata1.setValue(0, 1, speed);\n chart1.draw(chartdata1, chartoptions1);\n }\n if (message[3].incline != null)\n {\n var incline = message[3].incline;\n chartdata2.setValue(0, 1, incline);\n chart2.draw(chartdata2, chartoptions2);\n }\n }\n //console.log(message);\n // build the output from the topic and payload parts of the object\n // replace the messages div with the new \"line\"\n if (textmsg != null)\n document.getElementById('messages').innerHTML = textmsg;\n if (graph != null)\n document.getElementById('graph').innerHTML = graph;\n switch (msgtype)\n {\n case \"chart\": \n document.getElementById('stopbutton').setAttribute(\"style\",\"display:block\");\n document.getElementById('pausebutton').setAttribute(\"style\",\"display:block\");\n document.getElementById('resumebutton').setAttribute(\"style\",\"display:none\");\n break;\n case \"endchart\": \n/* document.getElementById('stopbutton').setAttribute(\"style\",\"display:none\");\n document.getElementById('pausebutton').setAttribute(\"style\",\"display:none\");\n document.getElementById('resumebutton').setAttribute(\"style\",\"display:none\");\n document.getElementById('restartbutton').setAttribute(\"style\",\"display:block\");\n*/\n document.getElementById('buttons').setAttribute(\"style\",\"display:none\");\n document.getElementById('restart').setAttribute(\"style\",\"display:block\");\n break;\n case \"pause\":\n document.getElementById('resumebutton').setAttribute(\"style\",\"display:block\");\n document.getElementById('pausebutton').setAttribute(\"style\",\"display:none\");\n break;\n case \"resume\":\n document.getElementById('resumebutton').setAttribute(\"style\",\"display:none\");\n document.getElementById('pausebutton').setAttribute(\"style\",\"display:block\");\n break;\n case 'hidepause':\n document.getElementById('pausebutton').disabled = true;\n break;\n case 'showpause':\n document.getElementById('pausebutton').disabled = false;\n break;\n\n case null:\n default:\n break;\n }\n \n //ws.send(JSON.stringify({data:data}));\n }\n ws.onopen = function() {\n // update the status div with the connection status\n // document.getElementById('status').innerHTML = \"connected\";\n //ws.send(\"Open for data\");\n console.log(\"connected\");\n }\n ws.onclose = function() {\n // update the status div with the connection status\n // document.getElementById('status').innerHTML = \"not connected\";\n // in case of lost connection tries to reconnect every 3 secs\n setTimeout(wsConnect,3000);\n }\n }\n \n function closeSocket()\n {\n ws = null;\n }\n \n function restart()\n {\n window.location.href = '/treadmill';\n }\n \n function doit(type) {\n if (ws) { \n ws.send(type); \n }\n }\n ",
"x": 940,
"y": 1000,
"wires": [
[
"e7f57b5c.872088"
]
]
},
{
"id": "7b5d806e.d25a4",
"type": "template",
"z": "158e314c.71084f",
"name": "Style",
"field": "style",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": "/* Style Sheet */\n\n#page {\n width: 930px;\n /*margin: 0 auto;*/\n}\n\n \n.area { \n font-family: arial;\n width: 930px;\n background-color: #bcbcbc;\n border-radius: 15px;\n margin: 0 auto 10px;\n padding: 12px;\n color: #444;\n}\n\n.area h1 {\n text-align: center;\n}\n\n.area .clear {\n clear: both;\n}\n\n#gauges {\n text-align: center;\n}\n\n#gaugesbox {\n display: inline-block;\n}\n\n#gauges .gauge {\n float: left;\n}\n\n#buttons, #restart {\n height: 160px;\n width: 90%;\n margin: 0 auto;\n}\n\n#stopbutton { \n display: none; \n float: left;\n}\n\n#restart { \n display: none;\n text-align: center;\n}\n\n#restartbutton { \n \n}\n\n#pausebutton, #resumebutton {\n display: none; \n float: right;\n}\n\n#resumebutton { \n background: #00dd00;\n border: solid #00aa00 4px;\n}\n\n#resumebutton:hover {\n cursor: pointer; \n background: #00ff00;\n}\n\n#pausebutton { \n background: #f7b35d;\n border: solid #FF8F00 4px;\n}\n\n#pausebutton:hover {\n cursor: pointer;\n background: #ff9b1c;\n}\n\n#pausebutton:disabled { \n cursor: default; \n background: #777;\n border: solid #444 4px;\n}\n\n\n.msg {\n font-size: 26px;\n text-align:center;\n font-weight: bold;\n padding-top: 3px;\n margin: 0 auto;\n color: red;\n }\n \n.btn {\n -webkit-border-radius: 28;\n -moz-border-radius: 28;\n border-radius: 28px;\n font-family: Arial;\n color: #ffffff;\n font-size: 60px;\n background: #b53838;\n padding: 40px 35px 40px 35px;\n border: solid #ff0022 4px;\n text-decoration: none;\n width: 350px;\n}\n\n.btn:hover {\n cursor: pointer;\n background: #ff0000;\n text-decoration: none;\n}",
"x": 740,
"y": 900,
"wires": [
[
"b0be1a45.9e43f8"
]
]
},
{
"id": "327331de.6a3d2e",
"type": "websocket out",
"z": "158e314c.71084f",
"name": "",
"server": "8620b00f.557be",
"client": "",
"x": 1240,
"y": 1260,
"wires": []
},
{
"id": "c918da3.97d8328",
"type": "function",
"z": "158e314c.71084f",
"name": "Set Globals",
"func": "\nglobal.set(\"initialweight\",150);\nglobal.set(\"initialtime\",20);\nglobal.set(\"timesteps\",20);\nglobal.set(\"speedsteps\",1); // Tenth of a MPH\nglobal.set(\"maxspeed\",100); // Tenth of a MPH\nglobal.set(\"minspeed\",5); // Tenth of a MPH\nglobal.set(\"inclinesteps\",5); // Tenth of a Degrees\nglobal.set(\"maxincline\",150); // Tenth of a Degrees\nglobal.set(\"minincline\",0); // Tenth of a Degrees\nglobal.set(\"minutetosecs\",60); // this should be 60 in production\nglobal.set(\"running\",false);\nif (msg.payload.maxspeedunits === undefined)\n {\n msg.payload = { \n \"minspeedunits\":'0',\n \"minspeedtenths\":'5',\n \"maxspeedunits\":'1',\n \"maxspeedtenths\":'5',\n \"mininclineunits\":'0', \n \"mininclinetenths\":'0', \n \"maxinclineunits\":'1', \n \"maxinclinetenths\":'0', \n \"weight\":'150', \n \"time\":'20',\n \"username\":'',\n \"newusername\":'',\n \"program\":'0'\n };\n }\n \nvar buttons = {40:\"SpeedUp\",\n 38:\"SpeedDown\",\n 37:\"InclineUp\",\n 36:\"InclineDown\",\n 35:\"Start\",\n 33:\"Stop\",\n 32:\"Pause\"};\nglobal.set(\"buttons\",buttons);\n\n// Missing indices will use the previous defined index\nvar programs = {\n 0: {\n \"name\":\"Fat Burning\",\n 0:{\"speed\":2,\"incline\":0},\n 1:{\"speed\":4,\"incline\":1},\n 2:{\"speed\":5,\"incline\":2},\n 3:{\"speed\":3,\"incline\":3},\n 4:{\"speed\":3,\"incline\":4},\n 6:{\"speed\":3,\"incline\":5},\n 7:{\"speed\":3,\"incline\":3},\n 8:{\"speed\":4,\"incline\":0},\n 10:{\"speed\":5,\"incline\":0},\n 11:{\"speed\":5,\"incline\":3},\n 12:{\"speed\":5,\"incline\":4},\n 13:{\"speed\":4,\"incline\":4},\n 14:{\"speed\":4,\"incline\":5},\n 15:{\"speed\":3,\"incline\":4},\n 16:{\"speed\":3,\"incline\":3},\n 17:{\"speed\":5,\"incline\":2},\n 18:{\"speed\":2,\"incline\":0},\n 19:{\"speed\":0,\"incline\":0}\n },\n 1: {\n \"name\":\"Intermediate\",\n 0:{\"speed\":2,\"incline\":0},\n 1:{\"speed\":3,\"incline\":1},\n 2:{\"speed\":4,\"incline\":2},\n 3:{\"speed\":5,\"incline\":3},\n 4:{\"speed\":4,\"incline\":5},\n 6:{\"speed\":4,\"incline\":1},\n 7:{\"speed\":5,\"incline\":3},\n 9:{\"speed\":4,\"incline\":1},\n 10:{\"speed\":5,\"incline\":5},\n 12:{\"speed\":4,\"incline\":1},\n 13:{\"speed\":3,\"incline\":3},\n 15:{\"speed\":4,\"incline\":1},\n 16:{\"speed\":4,\"incline\":4},\n 17:{\"speed\":4,\"incline\":3},\n 18:{\"speed\":3,\"incline\":2},\n 19:{\"speed\":2,\"incline\":1}\n },\n 2: {\n \"name\":\"Advanced\",\n 0:{\"speed\":1,\"incline\":0},\n 1:{\"speed\":2,\"incline\":0},\n 2:{\"speed\":5,\"incline\":1},\n 3:{\"speed\":4,\"incline\":2},\n 4:{\"speed\":4,\"incline\":3},\n 5:{\"speed\":4,\"incline\":4},\n 6:{\"speed\":4,\"incline\":5},\n 7:{\"speed\":3,\"incline\":5},\n 8:{\"speed\":3,\"incline\":4},\n 9:{\"speed\":4,\"incline\":3},\n 10:{\"speed\":4,\"incline\":3},\n 11:{\"speed\":4,\"incline\":4},\n 12:{\"speed\":4,\"incline\":5},\n 13:{\"speed\":3,\"incline\":5},\n 14:{\"speed\":3,\"incline\":4},\n 15:{\"speed\":4,\"incline\":3},\n 16:{\"speed\":4,\"incline\":2},\n 17:{\"speed\":5,\"incline\":1},\n 18:{\"speed\":2,\"incline\":0},\n 19:{\"speed\":1,\"incline\":0}\n },\n 3: {\n \"name\":\"Intervals\",\n 0:{\"speed\":1,\"incline\":0},\n 1:{\"speed\":2,\"incline\":1},\n 2:{\"speed\":3,\"incline\":2},\n 3:{\"speed\":5,\"incline\":5},\n 4:{\"speed\":3,\"incline\":0},\n 5:{\"speed\":5,\"incline\":5},\n 6:{\"speed\":3,\"incline\":0},\n 7:{\"speed\":5,\"incline\":5},\n 8:{\"speed\":3,\"incline\":0},\n 9:{\"speed\":5,\"incline\":5},\n 10:{\"speed\":3,\"incline\":0},\n 11:{\"speed\":5,\"incline\":5},\n 12:{\"speed\":3,\"incline\":0},\n 13:{\"speed\":5,\"incline\":5},\n 14:{\"speed\":3,\"incline\":0},\n 15:{\"speed\":5,\"incline\":5},\n 16:{\"speed\":3,\"incline\":0},\n 17:{\"speed\":5,\"incline\":5},\n 18:{\"speed\":2,\"incline\":1},\n 19:{\"speed\":1,\"incline\":0}\n },\n 4: {\n \"name\":\"Recommended by md.com\",\n 0:{\"speed\":0,\"incline\":0},\n 1:{\"speed\":2,\"incline\":0},\n 2:{\"speed\":3,\"incline\":0},\n 3:{\"speed\":4,\"incline\":1},\n 5:{\"speed\":4,\"incline\":3},\n 8:{\"speed\":5,\"incline\":5},\n 9:{\"speed\":4,\"incline\":3},\n 11:{\"speed\":5,\"incline\":5},\n 12:{\"speed\":4,\"incline\":3},\n 14:{\"speed\":5,\"incline\":5},\n 15:{\"speed\":4,\"incline\":3},\n 17:{\"speed\":3,\"incline\":1},\n 18:{\"speed\":2,\"incline\":0},\n 19:{\"speed\":1,\"incline\":0}\n } /*,\n 5: {\n \"name\":\"test\",\n 0:{\"speed\":5,\"incline\":5},\n 1:{\"speed\":0,\"incline\":0},\n 2:{\"speed\":1,\"incline\":1},\n 3:{\"speed\":2,\"incline\":2},\n 4:{\"speed\":3,\"incline\":3},\n 5:{\"speed\":4,\"incline\":4},\n 6:{\"speed\":5,\"incline\":5},\n 7:{\"speed\":0,\"incline\":0}\n }*/\n };\nglobal.set(\"programs\",programs);\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 620,
"y": 300,
"wires": [
[
"d92a4798.6bd818"
]
]
},
{
"id": "c4ac2c4e.127c1",
"type": "function",
"z": "158e314c.71084f",
"name": "Set Globals",
"func": "global.set('running',true);\nglobal.set('stop',0);\nglobal.set('pause',0);\nglobal.set(\"weight\",msg.payload.weight);\nglobal.set(\"time\",msg.payload.time);\nglobal.set(\"program\",msg.payload.program);\nglobal.set(\"usermaxspeed\",(parseInt(msg.payload.maxspeedunits)*10) + parseInt(msg.payload.maxspeedtenths));\nglobal.set(\"usermaxincline\",(parseInt(msg.payload.maxinclineunits)*10) + parseInt(msg.payload.maxinclinetenths));\nglobal.set(\"userminspeed\",Math.max(global.get('minspeed'),(parseInt(msg.payload.minspeedunits)*10) + parseInt(msg.payload.minspeedtenths)));\nglobal.set(\"userminincline\",(parseInt(msg.payload.mininclineunits)*10) + parseInt(msg.payload.mininclinetenths));\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 400,
"y": 900,
"wires": [
[
"73484767.ef4d48",
"47fc360f.1591c8"
]
]
},
{
"id": "7a270187.c9df5",
"type": "function",
"z": "158e314c.71084f",
"name": "Program Processor",
"func": "var currentSpeed = 0;\nvar currentIncline = 0;\nvar program = global.get(\"programs\")[global.get(\"program\")];\nif (program === undefined)\n {\n global.set(\"program\",0);\n program = global.get(\"programs\")[global.get(\"program\")];\n }\nvar speedSteps = (global.get(\"usermaxspeed\") - global.get(\"userminspeed\"))/5; \nvar inclineSteps = (global.get(\"usermaxincline\") - global.get(\"userminincline\"))/25; \n//node.warn('Speed steps: ' + speedSteps);\n//node.warn('Incline steps: ' + inclineSteps);\nfunction setSpeed(speed)\n {\n speed *= speedSteps;\n speed = Math.round(speed);\n var pulses = speed - currentSpeed;\n currentSpeed = speed;\n if (pulses > 0)\n {\n // do speed up\n return {\"count\":pulses,\"button\":\"SpeedUp\"};\n }\n else if (pulses < 0)\n {\n // do speed down\n return {\"count\":-pulses,\"button\":\"SpeedDown\"};\n }\n return null;\n }\nfunction setIncline(incline)\n {\n incline *= inclineSteps;\n incline = Math.round(incline);\n var pulses = incline - currentIncline;\n currentIncline = incline;\n if (pulses > 0)\n {\n // do incline up\n return {\"count\":pulses,\"button\":\"InclineUp\"};\n }\n else if (pulses < 0)\n {\n // do incline down\n return {\"count\":-pulses,\"button\":\"InclineDown\"};\n }\n return null;\n }\n \n function setSpeedAndIncline(speed,incline) {\n var cmd = [];\n var newspeed = setSpeed(speed);\n if (newspeed !== null)\n cmd.push(newspeed);\n var newincline = setIncline(incline);\n if (newincline !== null)\n cmd.push(newincline);\n msg.payload = cmd;\n node.send([null,msg]);\n }\n\n\nvar currentstep = 0;\nvar maxsteps = global.get(\"timesteps\");\nvar timePeriod = (global.get(\"time\") * global.get(\"minutetosecs\")) / maxsteps;\nvar seconds = -1;\nvar period = timePeriod;\n\n//node.warn(\"timeperiod \" + timePeriod);\n//dostep(true);\ncontext.global.timerId = setInterval(dostep,1000);\n\nfunction dostep()\n {\n if (global.get(\"pause\") == 1)\n return;\n var data = [];\n seconds++;\n var mins = Number(seconds/60).toFixed(2);\n// node.warn(\"Minutes:\" + mins);\n if (seconds % timePeriod !== 0)\n {\n data[0] = null;\n data[1] = null;\n data[2] = null;\n data[3] = {\"time\":mins,\"secsleft\":period,\"speed\":null,\"incline\":null};\n node.send([{\"payload\":JSON.stringify(data)},null]);\n if (--period === 0)\n period = timePeriod;\n return;\n }\n// node.warn(\"Doing step \" + currentstep);\n var stop = global.get('stop');\n // node.warn(\"Stop \" + stop);\n if (currentstep == maxsteps || stop == 1)\n {\n if (stop === 0)\n {\n data[0] = \"Program Ended
\";\n data[1] = context.global.createChart(global.get(\"program\"));\n data[2] = \"endchart\";\n data[3] = {\"time\":0,\"speed\":0,\"secsleft\":0,\"incline\":0};\n msg.payload = [{\"count\":1,\"button\":\"Stop\"}];\n node.send([{\"payload\":JSON.stringify(data)},msg]);\n }\n clearInterval(context.global.timerId);\n return;\n }\n \n\n if (program[currentstep] !== undefined)\n {\n setSpeedAndIncline(program[currentstep].speed,program[currentstep].incline);\n }\n var realSpeed = (Math.round((currentSpeed * global.get(\"speedsteps\")) + global.get(\"userminspeed\")))/10;\n// node.warn(realSpeed + ' ' + currentSpeed + ' ' + global.get(\"userminspeed\") + ' ' + global.get(\"speedsteps\")); \n var realIncline = (Math.round((currentIncline * global.get(\"inclinesteps\"))) + global.get(\"userminincline\"))/10;\n// node.warn(realIncline + ' ' + currentIncline + ' ' + global.get(\"userminincline\") + ' ' + global.get(\"inclinesteps\")); \n data[0] = \"Program Running
\";\n data[1] = context.global.createChart(global.get(\"program\"),currentstep);\n data[2] = \"chart\";\n data[3] = {\"time\":mins,\"secsleft\":period,\"speed\":realSpeed,\"incline\":realIncline};\n var payload = JSON.stringify(data);\n currentstep++;\n if (--period === 0)\n period = timePeriod;\n node.send([{payload:payload},null]);\n }\n",
"outputs": "2",
"noerr": 0,
"x": 960,
"y": 1420,
"wires": [
[
"1b44da52.c02e96"
],
[
"cda23fd3.a79b2"
]
]
},
{
"id": "d38771af.59018",
"type": "subflow:a00cfa3a.41f338",
"z": "158e314c.71084f",
"name": "Chart",
"x": 920,
"y": 300,
"wires": [
[
"1fffa6c8.217719"
]
]
},
{
"id": "7027323.8f9cecc",
"type": "template",
"z": "158e314c.71084f",
"name": "Style",
"field": "style",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": "/* Style Sheet */\n.btnbox {\n text-align: center;\n margin: 10px;\n }\n \n.btn {\n -webkit-border-radius: 28px;\n -moz-border-radius: 28px;\n border-radius: 28px;\n font-family: Arial;\n color: #ffffff;\n font-size: 60px;\n background: #b53838;\n padding: 40px 35px 40px 35px;\n border: solid #ff0022 4px;\n text-decoration: none;\n display: inline-block;\n width: 350px;\n}\n\n.smallbtn {\n -webkit-border-radius: 8px;\n -moz-border-radius: 8px;\n border-radius: 8px;\n font-family: Arial;\n color: #ffffff;\n font-size: 16px !important;\n background: #b53838 !important;\n padding: 2px;\n border: solid #ff0022 2px;\n text-decoration: none;\n display: inline-block;\n}\n\n.btn:hover, .smallbtn:hover {\n background: #ff0000 !important;\n cursor: pointer;\n text-decoration: none;\n}\n\n#page {\n width: 930px;\n /* margin: 0 auto; */\n}\n\n.area { \n font-family: arial;\n width: 930px;\n background-color: #bcbcbc;\n border-radius: 15px;\n margin: 0 auto 10px;\n padding: 12px;\n color: #444;\n}\n\n.area h1 {\n text-align: center;\n}\n\n#form {\n/* width: 80%; */\n margin: 0 auto;\n}\n\n.elemField {\n font-size: 24px;\n}\n\n.elemField select, .elemField input {\n float: left;\n font-size: 20px;\n background-color: #fff28f;\n margin: 0 4px 0 0;\n}\n\n.elemTitle {\n float: left;\n width: 450px;\n text-align: right;\n padding: 4px 0;\n font-size: 24px;\n}\n\n#chartarea {\n}\n\n.clear {\n clear: both;\n}\n\n/* hide input */\ninput.radio:empty {\n\t/*margin-left: -999px;*/\n\tdisplay: none;\n}\n\n\nlabel {\n width: 450px;\n border-radius: 3px;\n border: 0px solid #D1D3D4\n}\n\n/* style label */\ninput.radio:empty ~ label {\n\tposition: relative;\n\tfloat: left;\n\tline-height: 20px;\n\ttext-indent: 3.25em;\n\tmargin-bottom: 6px;\n\tcursor: pointer;\n\t-webkit-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n\tcolor: #5d5757;\n}\n\ninput.radio:empty ~ label:before {\n\tposition: absolute;\n\tdisplay: block;\n\ttop: 0;\n\tbottom: 0;\n\tleft: 0;\n\tcontent: '';\n\twidth: 2.5em;\n\tbackground: #D1D3D4;\n\tborder-radius: 3px;\n}\n\n/* toggle hover */\ninput.radio:hover:not(:checked) ~ label:before {\n\tcontent:'\\2714';\n\ttext-indent: .9em;\n\tcolor: #ff0000;\n}\n\ninput.radio:hover:not(:checked) ~ label {\n\tcolor: #ff0000;\n}\n\n/* toggle on */\ninput.radio:checked ~ label:before {\n\tcontent:'\\2714';\n\ttext-indent: .9em;\n\tcolor: #9CE2AE;\n\tbackground-color: #4DCB6D;\n}\n\ninput.radio:checked ~ label {\n\tcolor: #333;\n}\n\n/* radio focus */\ninput.radio:focus ~ label:before {\n\tbox-shadow: 0 0 0 2px #999;\n}",
"x": 600,
"y": 400,
"wires": [
[
"ba13f105.7b13"
]
]
},
{
"id": "81f53f59.1d757",
"type": "function",
"z": "158e314c.71084f",
"name": "Program Form Elements",
"func": "var selected;\nvar programs = global.get(\"programs\");\nvar programcount = Object.keys(programs).length;\n\nmsg.legend = \"Speed
\";\nmsg.legend += \"
Incline
\";\nmsg.tables = '';\nif (msg.payload.program === undefined)\n msg.payload.program = 0;\nfor (programno = 0; programno < programcount; programno++)\n {\n msg.tables += context.global.createChart(programno,global.get(\"timesteps\"),\n programno == msg.payload.program); \n }\n\nfunction padtitle(title,count) {\n var pad = '';\n if (count === undefined)\n count = 2;\n for (var i=0; i < count; i++)\n pad += \" \"\n return pad + title + pad;\n }\n \nmsg.weight = \"\";\n \n // Now do time selector\nmsg.time = \"\";\n \n // Now do user name selector\n\nmsg.usernamelist = \"\";\n//if (msg.payload.names.length)\n// msg.usernamelist += \"\";\n\nmsg.newusername = \"\";\n\n// Now do Max/Min selects\n\n// Min Speed Units\nmsg.minspeed = \"\";\n\n// Min Speed Tenths\nmsg.minspeed += \"\";\n\n// Max Speed Units\n\nmsg.maxspeed = \"\";\n\n// Max Speed Tenths\nmsg.maxspeed += \"\";\n\n// Min Incline Units\nmsg.minincline = \"\";\n\n// Min Incline Tenths\nmsg.minincline += \"\";\n\n// Max Incline Units\nmsg.maxincline = \"\";\n\n// Max Incline Tenths\nmsg.maxincline += \"\";\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 400,
"y": 400,
"wires": [
[
"7027323.8f9cecc"
]
]
},
{
"id": "1fffa6c8.217719",
"type": "subflow:9788ac6d.fc8e7",
"z": "158e314c.71084f",
"x": 1060,
"y": 300,
"wires": [
[
"81f53f59.1d757"
]
]
},
{
"id": "73484767.ef4d48",
"type": "subflow:9788ac6d.fc8e7",
"z": "158e314c.71084f",
"x": 590,
"y": 900,
"wires": [
[
"7b5d806e.d25a4"
]
]
},
{
"id": "47fc360f.1591c8",
"type": "function",
"z": "158e314c.71084f",
"name": "Stop",
"func": "msg.payload = [{\"count\":2,\"button\":\"Stop\"}];\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 220,
"y": 1000,
"wires": [
[
"f006fdf5.d8fe"
]
]
},
{
"id": "8d75fdf2.fccd7",
"type": "function",
"z": "158e314c.71084f",
"name": "Select Manual Program",
"func": "msg.payload = [{\"count\":1,\"button\":\"SpeedDown\"}]\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 140,
"y": 1140,
"wires": [
[
"c02abd9c.1e652"
]
]
},
{
"id": "aea37578.fb03f8",
"type": "subflow:25196831.e307e8",
"z": "158e314c.71084f",
"x": 540,
"y": 1140,
"wires": [
[
"ad073d06.f485e"
]
]
},
{
"id": "fb2a07d1.a00918",
"type": "subflow:25196831.e307e8",
"z": "158e314c.71084f",
"x": 550,
"y": 1200,
"wires": [
[
"e4f341a3.8951b"
]
]
},
{
"id": "4ebd43fb.fbd4ac",
"type": "subflow:25196831.e307e8",
"z": "158e314c.71084f",
"x": 120,
"y": 1420,
"wires": [
[
"29817444.21675c"
]
]
},
{
"id": "be1120cf.dd1e8",
"type": "comment",
"z": "158e314c.71084f",
"name": "Output Progress Screen",
"info": "",
"x": 1230,
"y": 1040,
"wires": []
},
{
"id": "da5f0ba.14de9f8",
"type": "template",
"z": "158e314c.71084f",
"name": "Google Chart API",
"field": "googlechart",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": "\n\n ",
"x": 1120,
"y": 900,
"wires": [
[
"3649d594.261e0a"
]
]
},
{
"id": "9b326b13.9a5a38",
"type": "function",
"z": "158e314c.71084f",
"name": "Start Countdown",
"func": "var wait = 8;\nvar data = [];\ndata[0] = \"Starting in \" + wait +\" seconds
\";\ndata[1] = context.global.createChart(global.get(\"program\"));\ndata[2] = \"chart\";\ndata[3] = {\"step\":0,\"speed\":0,\"incline\":0};\nvar payload = JSON.stringify(data);\nnode.send([null,{payload:payload}]);\n\nvar timerId = setInterval(docountdown,1000);\n\nfunction docountdown()\n {\n stop = global.get('stop');\n if (stop != 1)\n {\n data[0] = \"Starting in \" + wait +\" seconds
\";\n data[1] = null;\n data[2] = null;\n data[3] = null;\n var payload = JSON.stringify(data);\n node.send([null,{payload:payload}]);\n }\n \n if (stop != 1 && wait == 3) // start the treadmill\n node.send([msg,null]);\n\n if (wait === 0 || stop == 1)\n {\n clearInterval(timerId);\n// node.warn(\"Ending wait\");\n } \n \n wait--;\n }",
"outputs": "2",
"noerr": 0,
"x": 560,
"y": 1260,
"wires": [
[
"4ebd43fb.fbd4ac"
],
[
"327331de.6a3d2e"
]
]
},
{
"id": "50622682.881788",
"type": "switch",
"z": "158e314c.71084f",
"name": "Already Running",
"property": "running",
"propertyType": "global",
"rules": [
{
"t": "true"
},
{
"t": "false"
}
],
"checkall": "false",
"outputs": 2,
"x": 120,
"y": 864,
"wires": [
[
"ba54ef32.5ce5f",
"5d60f031.3c7c1"
],
[
"c4ac2c4e.127c1",
"e4b14181.8705a"
]
]
},
{
"id": "cedc864e.274508",
"type": "subflow:81a5424b.55e1d",
"z": "158e314c.71084f",
"x": 560,
"y": 700,
"wires": [
[]
]
},
{
"id": "a9318e60.e8e7b",
"type": "http response",
"z": "158e314c.71084f",
"name": "/treadmill",
"x": 560,
"y": 740,
"wires": []
},
{
"id": "ba54ef32.5ce5f",
"type": "template",
"z": "158e314c.71084f",
"name": "Redirect",
"field": "payload",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": "",
"x": 380,
"y": 740,
"wires": [
[
"a9318e60.e8e7b"
]
]
},
{
"id": "4f734e81.b7574",
"type": "comment",
"z": "158e314c.71084f",
"name": "Stop Treadmill and Redirect",
"info": "",
"x": 770,
"y": 740,
"wires": []
},
{
"id": "5d60f031.3c7c1",
"type": "function",
"z": "158e314c.71084f",
"name": "Stop Program",
"func": "clearInterval(context.global.timerId);\nglobal.set(\"stop\",1);\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 380,
"y": 700,
"wires": [
[
"cedc864e.274508"
]
]
},
{
"id": "29817444.21675c",
"type": "delay",
"z": "158e314c.71084f",
"name": "Wait for treadmill countdown",
"pauseType": "delay",
"timeout": "4",
"timeoutUnits": "seconds",
"rate": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"x": 330,
"y": 1420,
"wires": [
[
"bb5ef6c6.28bac8"
]
]
},
{
"id": "b0be1a45.9e43f8",
"type": "function",
"z": "158e314c.71084f",
"name": "Gauges Parameter",
"func": "msg.time = msg.payload.time;\nmsg.ticks = \"\";\nvar majorTicks = 5;\nif (timePeriod/majorTicks > 10)\n majorTicks += 5;\nfor (var incr=0; incr <= msg.time; incr += majorTicks)\n {\n if (msg.ticks.length > 0)\n msg.ticks += ',';\n msg.ticks += incr;\n }\nmsg.ticks = '[' + msg.ticks + ']';\nmsg.minorticks = 5;\nmsg.minspeed = global.get(\"userminspeed\")/10;\nmsg.minincline = global.get(\"userminincline\")/10;\nmsg.maxspeed = global.get(\"usermaxspeed\")/10;\nmsg.maxincline = global.get(\"usermaxincline\")/10;\n\nvar time = global.get(\"time\");\nvar timePeriod = (global.get(\"time\") * global.get(\"minutetosecs\")) / global.get(\"timesteps\");\nvar secsleftscales =\n {\n 15:{\"major\":\"[0,5,10,15,20,25,30,35,40,45]\",\"minor\":5},\n 20:{\"major\":\"[0,5,10,15,20,25,30,35,40,45,50,55,60]\",\"minor\":5},\n 25:{\"major\":\"[0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75]\",\"minor\":5},\n 30:{\"major\":\"[0,10,20,30,40,50,60,70,80,90]\",\"minor\":5},\n 35:{\"major\":\"[0,15,30,45,60,75,90,105]\",\"minor\":5},\n 40:{\"major\":\"[0,20,40,60,80,100,120]\",\"minor\":10},\n 45:{\"major\":\"[0,15,30,45,60,75,90,105,120,135]\",\"minor\":3},\n 50:{\"major\":\"[0,30,60,90,120,150]\",\"minor\":6},\n 55:{\"major\":\"[0,15,30,45,60,75,90,105,120,135,150,165]\",\"minor\":3},\n 60:{\"major\":\"[0,30,60,90,120,150,180]\",\"minor\":6}\n };\n\n\nmsg.secsleftmajorticks = secsleftscales[time].major;\nmsg.secsleftminorticks = secsleftscales[time].minor;\nmsg.secsleftmax = timePeriod;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 900,
"y": 900,
"wires": [
[
"da5f0ba.14de9f8"
]
]
},
{
"id": "72da95d9.3e3f1c",
"type": "exec",
"z": "158e314c.71084f",
"command": "ls -1 ~/.node-red/lib/flows/treadmill/users",
"addpay": false,
"append": "",
"useSpawn": "",
"timer": "",
"name": "Get User List",
"x": 240,
"y": 20,
"wires": [
[
"7d914628.205a48"
],
[],
[]
]
},
{
"id": "d92a4798.6bd818",
"type": "join",
"z": "158e314c.71084f",
"name": "",
"mode": "custom",
"build": "merged",
"property": "payload",
"propertyType": "msg",
"key": "payload",
"joiner": "\\n",
"timeout": "",
"count": "2",
"x": 780,
"y": 300,
"wires": [
[
"d38771af.59018"
]
]
},
{
"id": "7d914628.205a48",
"type": "function",
"z": "158e314c.71084f",
"name": "Parse names",
"func": "var names = msg.payload.replace(/\\n+/g,' ');\nnames = names.trim();\nnames = names.split(\" \");\nmsg.payload = {\"names\":names};\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 600,
"y": 20,
"wires": [
[
"d92a4798.6bd818"
]
]
},
{
"id": "e4b14181.8705a",
"type": "function",
"z": "158e314c.71084f",
"name": "Save User Settings",
"func": "var newuser = msg.payload.newusername.trim();\nvar currentuser = msg.payload.username;\nmsg.payload.newusername = ''; \nif (parseInt(msg.payload.minspeedunits) === 0 && parseInt(msg.payload.minspeedtenths) < global.get('minspeed'))\n msg.payload.minspeedtenths = '' + global.get('minspeed') + '';\n\nvar filenamebase = \"/home/pi/.node-red/lib/flows/treadmill/\"; \nif (newuser.length) // if there's a new user name defined save it\n {\n newuser = newuser.toLowerCase();\n newuser = newuser[0].toUpperCase() + newuser.slice(1);\n msg.filename = filenamebase + \"users/\" + newuser; \n msg.payload.username = newuser;\n node.send([msg,null]);\n }\nelse if (currentuser.length)\n {\n msg.filename = filenamebase + \"users/\" + currentuser;\n node.send([msg,null]);\n }\nmsg.filename = filenamebase + \"treadmill.cfg\"; \nreturn [null,msg];\n",
"outputs": "2",
"noerr": 0,
"x": 400,
"y": 820,
"wires": [
[
"26e12c93.906484"
],
[
"97bf980c.f74958"
]
]
},
{
"id": "26e12c93.906484",
"type": "file",
"z": "158e314c.71084f",
"name": "Save User Config",
"filename": "",
"appendNewline": true,
"createDir": false,
"overwriteFile": "true",
"x": 640,
"y": 780,
"wires": []
},
{
"id": "3e63460d.0a6aca",
"type": "switch",
"z": "158e314c.71084f",
"name": "User Defined?",
"property": "payload.username",
"propertyType": "msg",
"rules": [
{
"t": "neq",
"v": "''",
"vt": "str"
},
{
"t": "else"
}
],
"checkall": "true",
"outputs": 2,
"x": 470,
"y": 160,
"wires": [
[
"c918da3.97d8328"
],
[
"c6b5c65.34ad638"
]
]
},
{
"id": "c6b5c65.34ad638",
"type": "function",
"z": "158e314c.71084f",
"name": "Build User Filename",
"func": "var currentuser = msg.payload.username;\nmsg.payload = \"/home/pi/.node-red/lib/flows/treadmill/users/\" + currentuser; \nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 150,
"y": 300,
"wires": [
[
"b48e9919.9a09a8"
]
]
},
{
"id": "801f68a8.a14248",
"type": "function",
"z": "158e314c.71084f",
"name": "Set Base Config filename",
"func": "msg.payload = \"/home/pi/.node-red/lib/flows/treadmill/treadmill.cfg\";\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 280,
"y": 80,
"wires": [
[
"bc30f777.1302f8"
]
]
},
{
"id": "bc30f777.1302f8",
"type": "subflow:3df81f27.d1f76",
"z": "158e314c.71084f",
"x": 260,
"y": 160,
"wires": [
[
"3e63460d.0a6aca"
],
[
"c918da3.97d8328"
]
]
},
{
"id": "b48e9919.9a09a8",
"type": "subflow:3df81f27.d1f76",
"z": "158e314c.71084f",
"x": 360,
"y": 300,
"wires": [
[
"c918da3.97d8328"
],
[
"c918da3.97d8328"
]
]
},
{
"id": "cb54f3bb.8e9b",
"type": "debug",
"z": "158e314c.71084f",
"name": "",
"active": true,
"console": "false",
"complete": "false",
"x": 1480,
"y": 1300,
"wires": []
},
{
"id": "33c200ce.f3234",
"type": "http in",
"z": "158e314c.71084f",
"name": "",
"url": "/treadmill/ajax",
"method": "post",
"swaggerDoc": "",
"x": 110,
"y": 480,
"wires": [
[
"c3994341.c0128"
]
]
},
{
"id": "c3994341.c0128",
"type": "function",
"z": "158e314c.71084f",
"name": "Make Settings Flename",
"func": "msg.payload = \"/home/pi/.node-red/lib/flows/treadmill/users/\" + msg.payload.filename;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 340,
"y": 480,
"wires": [
[
"af4ea642.1544c8"
]
]
},
{
"id": "af4ea642.1544c8",
"type": "subflow:3df81f27.d1f76",
"z": "158e314c.71084f",
"x": 560,
"y": 480,
"wires": [
[
"19348e2b.4a7ec2"
],
[]
]
},
{
"id": "e0493a19.3f6e58",
"type": "http response",
"z": "158e314c.71084f",
"name": "",
"x": 1020,
"y": 480,
"wires": []
},
{
"id": "19348e2b.4a7ec2",
"type": "change",
"z": "158e314c.71084f",
"name": "",
"rules": [
{
"t": "set",
"p": "payload.success",
"pt": "msg",
"to": "true",
"tot": "bool"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 800,
"y": 480,
"wires": [
[
"e0493a19.3f6e58"
]
]
},
{
"id": "6eb6479d.959bb8",
"type": "comment",
"z": "158e314c.71084f",
"name": "AJAX Server",
"info": "",
"x": 90,
"y": 440,
"wires": []
},
{
"id": "41127064.c939c",
"type": "http in",
"z": "158e314c.71084f",
"name": "",
"url": "/treadmill/jquery",
"method": "get",
"swaggerDoc": "",
"x": 100,
"y": 600,
"wires": [
[
"a1421f74.fc4a7"
]
]
},
{
"id": "a1421f74.fc4a7",
"type": "file in",
"z": "158e314c.71084f",
"name": "Get Jquery File",
"filename": "/home/pi/.node-red/jquery.min.js",
"format": "utf8",
"x": 310,
"y": 600,
"wires": [
[
"38e5d7d5.bc3cf8"
]
]
},
{
"id": "38e5d7d5.bc3cf8",
"type": "http response",
"z": "158e314c.71084f",
"name": "",
"x": 480,
"y": 600,
"wires": []
},
{
"id": "f49a223b.d2f59",
"type": "comment",
"z": "158e314c.71084f",
"name": "Get Local JQuery File",
"info": "",
"x": 120,
"y": 560,
"wires": []
},
{
"id": "d1e193de.63e5b",
"type": "comment",
"z": "158e314c.71084f",
"name": "Read Default Config",
"info": "This area tried to read treadmill.cfg.\nIf it fails it skips the whole area and\ngoes to Set Globals, where defaults are set.\nIf it succeeded and contains a value for\nusername it tries to read the user's setting file.\nIf not the it skips the user file read.\nIf the user file is there and read then its\nvalues are used. Otherwise it does nothing\nand the values in treadmill.cfg are used.",
"x": 220,
"y": 200,
"wires": []
},
{
"id": "f5cec652.9e6618",
"type": "function",
"z": "158e314c.71084f",
"name": "Stop",
"func": "if (msg.payload == 'stop')\n {\n// node.warn(\"Stopping...\");\n clearInterval(context.global.timerId);\n global.set(\"stop\",1);\n// var program = global.get(\"programs\")[global.get(\"program\")];\n var data = [];\n data[0] = \"Program Stopped
\";\n data[1] = context.global.createChart(global.get(\"program\"));\n data[2] = \"endchart\";\n data[3] = {\"time\":0,\"speed\":0,\"secsleft\":0,\"incline\":0};\n var payload = JSON.stringify(data);\n msg.payload = [{\"count\":1,\"button\":\"Stop\"}];\n return [{payload:payload},msg];\n\n }\n",
"outputs": "2",
"noerr": 0,
"x": 760,
"y": 1340,
"wires": [
[
"327331de.6a3d2e"
],
[
"a451150a.24f988"
]
]
},
{
"id": "4b2bf575.bda25c",
"type": "websocket in",
"z": "158e314c.71084f",
"name": "",
"server": "8620b00f.557be",
"client": "",
"x": 590,
"y": 1340,
"wires": [
[
"f5cec652.9e6618"
]
]
},
{
"id": "a451150a.24f988",
"type": "delay",
"z": "158e314c.71084f",
"name": "Wait for scheduler to end",
"pauseType": "delay",
"timeout": "250",
"timeoutUnits": "milliseconds",
"rate": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"x": 960,
"y": 1360,
"wires": [
[
"702c9bfb.bdcb74"
]
]
},
{
"id": "7c20aceb.4d1274",
"type": "subflow:1314db79.10bc15",
"z": "158e314c.71084f",
"x": 1380,
"y": 1420,
"wires": [
[
"ddd7751c.fcf3a8"
]
]
},
{
"id": "96a4ae77.b42a",
"type": "function",
"z": "158e314c.71084f",
"name": "Set Imperial Units",
"func": "msg.payload = [{\"count\":1,\"button\":\"InclineDown\"}];\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 140,
"y": 1080,
"wires": [
[
"f44fe1b5.1e05a"
]
]
},
{
"id": "f44fe1b5.1e05a",
"type": "subflow:1314db79.10bc15",
"z": "158e314c.71084f",
"x": 347,
"y": 1081,
"wires": [
[
"8d75fdf2.fccd7"
]
]
},
{
"id": "fe1c89f.840e278",
"type": "comment",
"z": "158e314c.71084f",
"name": "Stop Treadmill",
"info": "",
"x": 700,
"y": 1300,
"wires": []
},
{
"id": "bb5ef6c6.28bac8",
"type": "function",
"z": "158e314c.71084f",
"name": "Initialize Speed/Incline",
"func": "var speedBaselineSteps =(global.get(\"userminspeed\") - global.get(\"minspeed\")); \nvar inclineBaselineSteps = (global.get(\"userminincline\") - global.get(\"minincline\"))/5.0; \n//node.warn('speed: ' + global.get(\"userminspeed\") + ' ' + global.get(\"minspeed\"));\n//node.warn(' incline: ' + global.get(\"userminincline\") + ' ' + global.get(\"minincline\"));\nmsg.payload = [{\"count\":speedBaselineSteps,\"button\":\"SpeedUp\"},{\"count\":inclineBaselineSteps,\"button\":\"InclineUp\"}];\n//node.warn(msg.payload);\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 570,
"y": 1420,
"wires": [
[
"bdabed30.4085b"
]
]
},
{
"id": "bdabed30.4085b",
"type": "subflow:1314db79.10bc15",
"z": "158e314c.71084f",
"x": 780,
"y": 1420,
"wires": [
[
"7a270187.c9df5"
]
]
},
{
"id": "75041a1d.3b4404",
"type": "http in",
"z": "158e314c.71084f",
"name": "",
"url": "/treadmill/chartloader",
"method": "get",
"swaggerDoc": "",
"x": 700,
"y": 600,
"wires": [
[
"f007ddaa.c2bba"
]
]
},
{
"id": "f007ddaa.c2bba",
"type": "file in",
"z": "158e314c.71084f",
"name": "Get Gauge JS File",
"filename": "/home/pi/.node-red/loader.js",
"format": "utf8",
"x": 920,
"y": 600,
"wires": [
[
"83b8182d.770e88"
]
]
},
{
"id": "83b8182d.770e88",
"type": "http response",
"z": "158e314c.71084f",
"name": "",
"x": 1080,
"y": 600,
"wires": []
},
{
"id": "9e6a09f2.1cbd58",
"type": "comment",
"z": "158e314c.71084f",
"name": "Get Local Gauges File",
"info": "",
"x": 700,
"y": 560,
"wires": []
},
{
"id": "499dae18.c9d07",
"type": "comment",
"z": "158e314c.71084f",
"name": "Read User Config",
"info": "",
"x": 340,
"y": 260,
"wires": []
},
{
"id": "9bc73be0.62ab58",
"type": "function",
"z": "158e314c.71084f",
"name": "Pause",
"func": "global.set(\"pause\",1);\nvar data = [];\n//data[0] = \"Program Paused
\";\ndata[0] = null;\ndata[1] = null;\ndata[2] = 'pause';\ndata[3] = null;\nvar payload = JSON.stringify(data);\nmsg.payload = [{\"count\":1,\"button\":\"Pause\"}];\nreturn [{payload:payload},msg];",
"outputs": "2",
"noerr": 0,
"x": 960,
"y": 1500,
"wires": [
[
"1b44da52.c02e96"
],
[
"7c7739be.cb0988"
]
]
},
{
"id": "4b2b8a1a.60ec64",
"type": "websocket in",
"z": "158e314c.71084f",
"name": "",
"server": "8620b00f.557be",
"client": "",
"x": 140,
"y": 1520,
"wires": [
[
"5cebf762.568268"
]
]
},
{
"id": "5cebf762.568268",
"type": "switch",
"z": "158e314c.71084f",
"name": "Pause or Resume?",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "pause",
"vt": "str"
},
{
"t": "eq",
"v": "resume",
"vt": "str"
}
],
"checkall": "true",
"outputs": 2,
"x": 380,
"y": 1500,
"wires": [
[
"bcb78594.272f18",
"9bc73be0.62ab58"
],
[
"62a7eee1.2651d"
]
]
},
{
"id": "62a7eee1.2651d",
"type": "function",
"z": "158e314c.71084f",
"name": "Resume",
"func": "clearInterval(flow.get('pauseTimer'));\nglobal.set(\"pause\",0);\nvar data = [];\ndata[0] = \"Program Running
\";\ndata[1] = null;\ndata[2] = 'resume';\ndata[3] = null;\nvar payload = JSON.stringify(data);\nmsg.payload = [{\"count\":1,\"button\":\"Start\"}];\nreturn [{payload:payload},msg];",
"outputs": "2",
"noerr": 0,
"x": 650,
"y": 1640,
"wires": [
[
"1b44da52.c02e96"
],
[
"4124c3fc.ba021c",
"7c7739be.cb0988"
]
]
},
{
"id": "bcb78594.272f18",
"type": "function",
"z": "158e314c.71084f",
"name": "Start Pause Countdown",
"func": "var wait = 240;\nfunction formatTime(time)\n {\n var mins = Math.floor(time/60); \n var secs = time % 60;\n if (secs < 10)\n secs = '0' + secs;\n return mins + ':' + secs;\n }\nvar data = [];\ndata[0] = \"Resuming in \" + formatTime(wait) +\" minutes
\";\ndata[1] = null;\ndata[2] = null;\ndata[3] = null;\nvar payload = JSON.stringify(data);\nnode.send([null,{payload:payload}]);\n\nvar timerId = setInterval(docountdown,1000);\nflow.set('pauseTimer',timerId);\n\nfunction docountdown()\n {\n stop = global.get('stop');\n if (stop != 1)\n {\n data[0] = \"Resuming in \" + formatTime(wait) +\" minutes
\";\n data[1] = null;\n data[2] = null;\n data[3] = null;\n payload = JSON.stringify(data);\n node.send([null,{payload:payload}]);\n }\n \n if (stop != 1 && wait == 3) // start the treadmill\n {\n node.send([msg,null]);\n }\n\n if (wait === 0 || stop == 1 || global.get(\"pause\") === 0)\n {\n clearInterval(timerId);\n// node.warn(\"Ending wait\");\n } \n \n wait--;\n }",
"outputs": "2",
"noerr": 0,
"x": 660,
"y": 1560,
"wires": [
[
"62a7eee1.2651d"
],
[
"1b44da52.c02e96"
]
]
},
{
"id": "7c7739be.cb0988",
"type": "subflow:1314db79.10bc15",
"z": "158e314c.71084f",
"x": 1100,
"y": 1700,
"wires": [
[]
]
},
{
"id": "cda23fd3.a79b2",
"type": "function",
"z": "158e314c.71084f",
"name": "Hide Pause",
"func": "var data = [];\ndata[0] = null;\ndata[1] = null;\ndata[2] = 'hidepause';\ndata[3] = null;\nvar payload = JSON.stringify(data);\nreturn [msg,{payload:payload}];\n",
"outputs": "2",
"noerr": 0,
"x": 1200,
"y": 1420,
"wires": [
[
"7c20aceb.4d1274"
],
[
"1b44da52.c02e96"
]
]
},
{
"id": "ddd7751c.fcf3a8",
"type": "function",
"z": "158e314c.71084f",
"name": "Show Pause",
"func": "var data = [];\ndata[0] = null;\ndata[1] = null;\ndata[2] = 'showpause';\ndata[3] = null;\nmsg.payload = JSON.stringify(data);\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 1540,
"y": 1420,
"wires": [
[
"1b44da52.c02e96"
]
]
},
{
"id": "1b44da52.c02e96",
"type": "websocket out",
"z": "158e314c.71084f",
"name": "",
"server": "8620b00f.557be",
"client": "",
"x": 1340,
"y": 1540,
"wires": []
},
{
"id": "4124c3fc.ba021c",
"type": "function",
"z": "158e314c.71084f",
"name": "Hide Pause",
"func": "var data = [];\ndata[0] = null;\ndata[1] = null;\ndata[2] = 'hidepause';\ndata[3] = null;\nmsg.payload = JSON.stringify(data);\nreturn msg;\n",
"outputs": "1",
"noerr": 0,
"x": 900,
"y": 1640,
"wires": [
[
"b8a6399.7be6ec8",
"1b44da52.c02e96"
]
]
},
{
"id": "a63e2905.1ad7d8",
"type": "function",
"z": "158e314c.71084f",
"name": "Show Pause",
"func": "var data = [];\ndata[0] = null;\ndata[1] = null;\ndata[2] = 'showpause';\ndata[3] = null;\nmsg.payload = JSON.stringify(data);\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 1260,
"y": 1640,
"wires": [
[
"1b44da52.c02e96"
]
]
},
{
"id": "b8a6399.7be6ec8",
"type": "delay",
"z": "158e314c.71084f",
"name": "",
"pauseType": "delay",
"timeout": "4",
"timeoutUnits": "seconds",
"rate": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"x": 1110,
"y": 1640,
"wires": [
[
"a63e2905.1ad7d8"
]
]
},
{
"id": "702c9bfb.bdcb74",
"type": "subflow:1314db79.10bc15",
"z": "158e314c.71084f",
"x": 1220,
"y": 1360,
"wires": [
[]
]
},
{
"id": "d80e90f6.78aec",
"type": "inject",
"z": "158e314c.71084f",
"name": "Start Active Pulse",
"topic": "",
"payload": "1",
"payloadType": "num",
"repeat": "2",
"crontab": "",
"once": true,
"x": 130,
"y": 1700,
"wires": [
[
"9ae24a7.e3f5cb8"
]
]
},
{
"id": "9ae24a7.e3f5cb8",
"type": "trigger",
"z": "158e314c.71084f",
"op1": "1",
"op2": "0",
"op1type": "str",
"op2type": "str",
"duration": "1",
"extend": false,
"units": "s",
"reset": "",
"name": "Flash",
"x": 310,
"y": 1700,
"wires": [
[
"76ada39b.12fd2c"
]
]
},
{
"id": "76ada39b.12fd2c",
"type": "rpi-gpio out",
"z": "158e314c.71084f",
"name": "Activity Flasher",
"pin": "29",
"set": true,
"level": "0",
"freq": "",
"out": "out",
"x": 480,
"y": 1700,
"wires": []
},
{
"id": "1476cb6.bfff335",
"type": "rpi-gpio in",
"z": "158e314c.71084f",
"name": "Shutdown switch",
"pin": "18",
"intype": "up",
"debounce": "25",
"read": false,
"x": 140,
"y": 1780,
"wires": [
[
"ba346fdf.9d1bf"
]
]
},
{
"id": "ba346fdf.9d1bf",
"type": "exec",
"z": "158e314c.71084f",
"command": "sudo shutdown -h now",
"addpay": false,
"append": "",
"useSpawn": "true",
"timer": "",
"oldrc": false,
"name": "Shutdown",
"x": 340,
"y": 1780,
"wires": [
[],
[],
[]
]
}
]