Skip to content

Instantly share code, notes, and snippets.

@fidian
Created April 10, 2018 11:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fidian/e19abe283c278adc1397d6fb9a35bc2e to your computer and use it in GitHub Desktop.
Save fidian/e19abe283c278adc1397d6fb9a35bc2e to your computer and use it in GitHub Desktop.
SmartThings Node Red X10 Bridge Flow
[
{
"id": "a206e388.d25c7",
"type": "tab",
"label": "Smartthings X10 Connector",
"disabled": false,
"info": ""
},
{
"id": "8f319222.e6859",
"type": "debug",
"z": "a206e388.d25c7",
"name": "",
"active": false,
"console": "false",
"complete": "payload",
"x": 630,
"y": 840,
"wires": []
},
{
"id": "5e396823.403508",
"type": "function",
"z": "a206e388.d25c7",
"name": "Parse mochad Messages",
"func": "msg.headers = {};\nmsg.headers['Content-Type'] = 'application/json';\nmsg.headers['X10NodeRed'] = 'DeviceUpdate';\n \nvar lastCommand = global.get(\"LastCommand\");\nlastCommand = lastCommand.toLowerCase().trim();\n//node.warn(lastCommand);\n\nconst inLines = new Buffer(msg.payload, 'hex'); \n//node.warn(inLines.toString());\nvar lastCodeSeen = context.get(\"lastCodeSeen\");\nif(typeof lastCodeSeen == \"undefined\") {\n lastCodeSeen = {\n housecode: \"x\",\n unitcode: \"0\"\n };\n context.set(\"lastCodeSeen\", lastCodeSeen);\n}\n\ntry {\n\n var eventData, m;\n \n if (m = /^\\d{2}\\/\\d{2}\\s+(?:\\d{2}:){2}\\d{2}\\s(Tx|Rx)\\s+(RF|PL)\\s+House:\\s+([a-pA-P])\\s+Func:\\s+All\\s+(units|lights)\\s+(on|off)$/m.exec(inLines)) {\n eventData = {\n protocol: m[2].toLowerCase().trim(),\n direction: m[1].toLowerCase().trim(),\n housecode: m[3].toLowerCase().trim(),\n unitcode: \"*\" + m[4].trim(),\n state: m[5].toLowerCase().trim()\n };\n \n msg.payload = JSON.stringify(eventData);\n msg.headers['eventData'] = msg.payload;\n return msg; //{payload: JSON.stringify(eventData)};\n }\n if (m = /^\\d{2}\\/\\d{2}\\s+(?:\\d{2}:){2}\\d{2}\\s(Tx|Rx)\\s+(RFSEC)\\s+Addr:\\s+([xX:0-9a-fA-F]+)(\\s+)Func:\\s+(.+)$/m.exec(inLines)) {\n eventData = {\n protocol: m[2].toLowerCase().trim(),\n direction: m[1].toLowerCase().trim(),\n housecode: m[3].toLowerCase().trim(),\n unitcode: \"*\" + m[4].trim(),\n state: m[5].toLowerCase().trim()\n };\n msg.payload = JSON.stringify(eventData);\n msg.headers['eventData'] = msg.payload;\n return msg; //{payload: JSON.stringify(eventData)};\n }\n if (m = /^\\d{2}\\/\\d{2}\\s+(?:\\d{2}:){2}\\d{2}\\s(Tx|Rx)\\s+(RF|PL)\\s+HouseUnit:\\s+([a-pA-P])(\\d{1,2})\\s+Func:\\s+(On|Off)/m.exec(inLines)) {\n eventData = {\n protocol: m[2].toLowerCase().trim(),\n direction: m[1].toLowerCase().trim(),\n housecode: m[3].toLowerCase().trim(),\n unitcode: parseInt(m[4].trim(), 10),\n state: m[5].toLowerCase().trim()\n };\n msg.payload = JSON.stringify(eventData);\n msg.headers['eventData'] = msg.payload;\n return msg; //{payload: JSON.stringify(eventData)};\n } else if (m = /^\\d{2}\\/\\d{2}\\s+(?:\\d{2}:){2}\\d{2}\\s(?:Rx)\\s+(?:RF|PL)\\s+HouseUnit:\\s+([a-pA-P])(\\d{1,2})/m.exec(inLines)) {\n lastCodeSeen.housecode = m[1].toLowerCase().trim();\n lastCodeSeen.unitcode = parseInt(m[2].trim(), 10);\n context.set(\"lastCodeSeen\", lastCodeSeen);\n }\n if (lastCodeSeen.housecode && lastCodeSeen.unitcode && (m = /\\d{2}\\/\\d{2}\\s+(?:\\d{2}:){2}\\d{2}\\s(Rx|Tx)\\s+(RF|PL)\\s+House:\\s+([a-pA-P])\\s+Func:\\s+(On|Off|Dim|Bright)$/m.exec(inLines))) {\n eventData = {\n protocol: m[2].toLowerCase().trim(),\n direction: m[1].toLowerCase().trim(),\n housecode: m[3].toLowerCase().trim(),\n unitcode: null,\n state: m[4].toLowerCase().trim()\n };\n if (eventData.housecode === lastCodeSeen.housecode) {\n eventData.unitcode = lastCodeSeen.unitcode;\n msg.payload = JSON.stringify(eventData);\n msg.headers['eventData'] = msg.payload;\n return msg; //{payload: JSON.stringify(eventData)};\n }\n }\n} \ncatch(err) {\n return null; //ignore the exception, its probably a message we don't understand\n //console.log(\"exception in parsing: \" + err.message); \n} \n \nreturn null;\n\n",
"outputs": 1,
"noerr": 0,
"x": 530,
"y": 200,
"wires": [
[
"f4e17d6f.f9033",
"2ebf47b8.c5f118"
]
]
},
{
"id": "54852502.0e31bc",
"type": "http in",
"z": "a206e388.d25c7",
"name": "/register",
"url": "/register",
"method": "get",
"upload": false,
"swaggerDoc": "",
"x": 80,
"y": 751,
"wires": [
[
"7ba3251f.24a4fc",
"f87a71e8.d3759"
]
]
},
{
"id": "6a2e72ce.234d6c",
"type": "http response",
"z": "a206e388.d25c7",
"name": "Send respone to ST",
"statusCode": "",
"headers": {},
"x": 640,
"y": 760,
"wires": []
},
{
"id": "ba53ff3f.4a99a",
"type": "http request",
"z": "a206e388.d25c7",
"name": "http request to ST",
"method": "POST",
"ret": "txt",
"url": "",
"tls": "",
"x": 850,
"y": 320,
"wires": [
[]
]
},
{
"id": "2ebf47b8.c5f118",
"type": "debug",
"z": "a206e388.d25c7",
"name": "",
"active": false,
"console": "false",
"complete": "true",
"x": 810,
"y": 200,
"wires": []
},
{
"id": "80ccf868.d26d28",
"type": "file in",
"z": "a206e388.d25c7",
"name": "Read ST setting after restart",
"filename": "/home/fidian/.red-st-connect.conf",
"format": "utf8",
"chunk": false,
"sendError": false,
"x": 366.5,
"y": 80,
"wires": [
[
"bdb1a3ab.ec377"
]
]
},
{
"id": "82222da6.2ea49",
"type": "inject",
"z": "a206e388.d25c7",
"name": "Startup",
"topic": "",
"payload": "",
"payloadType": "date",
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": "",
"x": 91,
"y": 81,
"wires": [
[
"80ccf868.d26d28",
"1c8a3b01.a2a6d5"
]
]
},
{
"id": "f87a71e8.d3759",
"type": "file",
"z": "a206e388.d25c7",
"name": "Persist ST settings to File",
"filename": "/home/fidian/.red-st-connect.conf",
"appendNewline": false,
"createDir": true,
"overwriteFile": "true",
"x": 316.5,
"y": 719,
"wires": []
},
{
"id": "86014fed.fc818",
"type": "comment",
"z": "a206e388.d25c7",
"name": "setup config file path",
"info": "If you are not running as pi or /home/pi is\nnot writable change the location of where\nthis flow will read and write ST settings\nsettings will be stored in /home/pi/.red-st-connect.conf",
"x": 348,
"y": 43,
"wires": []
},
{
"id": "bdb1a3ab.ec377",
"type": "function",
"z": "a206e388.d25c7",
"name": "Set ST Settings in global context",
"func": "try {\n var STsettings = JSON.parse(msg.payload);\n if (typeof obj !== 'string' ) \n global.set(\"STsettings\", STsettings);\n global.set(\"LastCommand\", \" \");\n} catch (e) {\n // ignore errors\n}\n\nmsg.payload = \"Smartthings settings: \" + JSON.stringify (STsettings);\n\nreturn msg\n\n\n\n",
"outputs": 1,
"noerr": 0,
"x": 674,
"y": 80,
"wires": [
[]
]
},
{
"id": "f4e17d6f.f9033",
"type": "function",
"z": "a206e388.d25c7",
"name": "Setup http request",
"func": "\n// if you want to hard code the url to ST uncomment these two lines and\n// delete or comment out the rest of the lines in this node\n// msg.url. = \"http://ip_address_of_Smartthings_hub:39500/\";\n// return msg;\n\nvar STsettings = global.get(\"STsettings\");\nif(typeof STsettings == \"undefined\") {\n node.error(\"Can't continue. Don't know where Smartthings hub is.\");\n return null;\n}\nnode.log(\"Please ignore the message properties override warning\");\nmsg.url =\"http://\" + STsettings.ip_for_st + \":\" + STsettings.port_for_st;\nreturn msg;\n\n\n\n\n\n",
"outputs": 1,
"noerr": 0,
"x": 630,
"y": 260,
"wires": [
[
"2ebf47b8.c5f118",
"ba53ff3f.4a99a"
]
]
},
{
"id": "fecd2465.c22738",
"type": "http in",
"z": "a206e388.d25c7",
"name": "/push",
"url": "/push",
"method": "get",
"upload": false,
"swaggerDoc": "",
"x": 61,
"y": 500,
"wires": [
[
"fc432ad6.d35fd8",
"898566fd.e0bd68"
]
]
},
{
"id": "7ba3251f.24a4fc",
"type": "function",
"z": "a206e388.d25c7",
"name": "Registration response",
"func": "msg.headers = {};\nmsg.headers['Content-Type'] = 'application/json';\nmsg.headers['X10NodeRed'] = 'Registered';\nmsg.payload = {\"X10NodeRed\":\"Registered\"};\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"x": 310,
"y": 792,
"wires": [
[
"6a2e72ce.234d6c",
"8f319222.e6859"
]
]
},
{
"id": "7e85adfe.5eb384",
"type": "comment",
"z": "a206e388.d25c7",
"name": "setup mochad host ip",
"info": "This is the mochad listener you should \nsetup the mochad host address here\n",
"x": 320,
"y": 160,
"wires": []
},
{
"id": "49074972.110bb8",
"type": "function",
"z": "a206e388.d25c7",
"name": "parse send message",
"func": "var jsonText = JSON.stringify(msg.payload); \nvar obj = JSON.parse(jsonText);\n\nif (typeof obj !== 'string' ) {\n var device = obj.device.replace(/-/g, \" \");\n msg.payload = device + \" \" + obj.action+\"\\n\";\n global.set(\"LastCommand\", msg.payload);\n return msg;\n}",
"outputs": 1,
"noerr": 0,
"x": 300,
"y": 400,
"wires": [
[
"56e95236.13472c",
"c33ad720.a00f88",
"1c8a3b01.a2a6d5"
]
]
},
{
"id": "64d3c2c5.39f3bc",
"type": "comment",
"z": "a206e388.d25c7",
"name": "setup config file path",
"info": "If you are not running as pi or /home/pi is\nnot writable change the location of where\nthis flow will read and write ST settings\nsettigns will be stored in /home/pi/.red-st-connect.conf",
"x": 310,
"y": 676,
"wires": []
},
{
"id": "56e95236.13472c",
"type": "function",
"z": "a206e388.d25c7",
"name": "OK response",
"func": "msg.headers = {};\nmsg.headers['Content-Type'] = 'application/json';\nmsg.payload = {\"X10NodeRed\":\"OK\"};\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"x": 610,
"y": 600,
"wires": [
[
"6a2e72ce.234d6c"
]
]
},
{
"id": "c33ad720.a00f88",
"type": "debug",
"z": "a206e388.d25c7",
"name": "",
"active": false,
"console": "false",
"complete": "payload",
"x": 570,
"y": 420,
"wires": []
},
{
"id": "fc432ad6.d35fd8",
"type": "debug",
"z": "a206e388.d25c7",
"name": "",
"active": false,
"console": "false",
"complete": "payload",
"x": 230,
"y": 600,
"wires": []
},
{
"id": "9c0e4d3f.247a9",
"type": "function",
"z": "a206e388.d25c7",
"name": "Rate Limiter",
"func": "var interval = (500); // minimum interval between messages (ms)\ncontext.lastTime = context.lastTime || 0;\n\nvar now = Date.now();\n\nif (now-context.lastTime > interval) {\n context.lastTime = now;\n return msg;\n} else {\n return null;\n}",
"outputs": 1,
"noerr": 0,
"x": 370,
"y": 260,
"wires": [
[
"5e396823.403508"
]
]
},
{
"id": "1c8a3b01.a2a6d5",
"type": "tcp request",
"z": "a206e388.d25c7",
"server": "localhost",
"port": "1099",
"out": "sit",
"splitc": " ",
"name": "mochad",
"x": 280,
"y": 200,
"wires": [
[
"9c0e4d3f.247a9"
]
]
},
{
"id": "898566fd.e0bd68",
"type": "delay",
"z": "a206e388.d25c7",
"name": "",
"pauseType": "rate",
"timeout": "5",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"x": 210,
"y": 480,
"wires": [
[
"49074972.110bb8"
]
]
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment