Created
December 7, 2018 08:10
-
-
Save btsimonh/178e1e736c7e4a8b0a549991c9331d7c to your computer and use it in GitHub Desktop.
node-red eq3 dev flow
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[{"id":"d9611430.c0dd78","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"f13a5e82.66c6","type":"inject","z":"d9611430.c0dd78","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":100,"y":100,"wires":[["81d1f125.7392"]]},{"id":"869cb11a.bc68e","type":"inject","z":"d9611430.c0dd78","name":"","topic":"","payload":"{\"names\":{\"00:1a:22:09:2c:db\":\"Living Room 1\",\"00:1a:22:09:2c:9a\":\"Living Room 2\",\"00:1a:22:09:2c:df\":\"Conservatory\",\"00:1a:22:09:08:37\":\"Office\",\"00:1a:22:09:2f:b7\":\"Dining\",\"00:1a:22:09:2f:06\":\"Utility\",\"00:1a:22:09:2f:ab\":\"Kathryn\",\"00:1a:22:09:2e:e0\":\"Jess\"}}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":90,"y":40,"wires":[["f77a8453.c541d8"]]},{"id":"f77a8453.c541d8","type":"function","z":"d9611430.c0dd78","name":"start","func":"var require = global.get('require');\n\nvar eq3interface = require('/home/pi/.node-red/node_modules/node-red-contrib-eq3-bluetooth/lib/eq3interface.js');\nvar noble = require('noble');\n//NobleDevice.prototype.SCAN_DUPLICATES = true;\n\nvar eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (!eq3){\n eq3 = require('/home/pi/.node-red/node_modules/node-red-contrib-eq3-bluetooth/lib/eq3device.js');\n global.set('eq3', eq3);\n eq3info = {\n devices: {},\n names:{},\n info:{}\n };\n \n global.set('eq3info', eq3info);\n node.warn(\"new global eq3\");\n} else {\n node.warn(\"existing global eq3\");\n}\n\nif (msg.payload.names){\n eq3info.names = msg.payload.names;\n}\n\neq3.prototype.SCAN_DUPLICATES = true;\n\n\nvar eq3info = global.get('eq3info');\n\nif (eq3info.discovercallback){\n eq3.stopDiscover(eq3info.discovercallback);\n delete eq3info.discovercallback;\n}\n\n\nif (eq3info.anyDiscovery){\n noble.removeListener('discover', eq3info.anyDiscovery);\n}\neq3info.anyDiscovery = function(peripheral){\n try{\n if (peripheral.connectable === false){\n return;\n }\n var name = 'unknown';\n if (eq3info.names && eq3info.names[peripheral.address]){\n name = eq3info.names[peripheral.address];\n }\n \n eq3info.peripherals = eq3info.peripherals || [];\n eq3info.peripherals[peripheral.id] = eq3info.peripherals[peripheral.id] || {};\n eq3info.peripherals[peripheral.id].peripheral = peripheral;\n\n if (peripheral.advertisement){\n if (peripheral.advertisement.localName !== \"CC-RT-M-BLE\"){\n //node.warn(peripheral);\n }\n var newmsg = {\n topic: \"blediscover/\"+peripheral.id.toLowerCase(),\n payload:{\n rssi: peripheral.rssi,\n txPowerLevel: peripheral.advertisement.txPowerLevel,\n serviceUuids: peripheral.advertisement.serviceUuids,\n serviceData: {},\n localName: peripheral.advertisement.localName,\n name: name\n }\n }\n if (peripheral.advertisement.serviceData){\n for (var i = 0; i < peripheral.advertisement.serviceData.length; i++){\n newmsg.payload.serviceData[peripheral.advertisement.serviceData[i].uuid] = \n peripheral.advertisement.serviceData[i].data.toString('hex');\n }\n }\n \n setTimeout(function(){\n node.send(newmsg);\n }, 1);\n }\n } catch (e){\n node.error(e);\n }\n};\n\nnoble.on('discover', eq3info.anyDiscovery);\n\n\n\n\neq3info.disconnectCallback = function(device) {\n try{\n if (!device){\n node.error(\"disconnect: no device\")\n } else {\n clearTimeout(device.disconnecttimer);\n device.disconnecttimer = null;\n //node.warn( \"got disconnected\"+ device.address );\n if (eq3info.info[device.address]){\n eq3info.info[device.address].my_state = 'disconnected';\n } else {\n node.error(\"disconnect: no info for \"+device.address);\n }\n }\n } catch(e){\n node.error(e);\n }\n};\n\neq3info.discovercallback = function(device){\n var eq3info = global.get('eq3info');\n\n eq3info.info[device.address] = eq3info.info[device.address] || {};\n eq3info.info[device.address].rssi = device._peripheral.rssi;\n //node.warn(eq3info.devices[device.address]);\n if (eq3info.devices[device.address]){\n eq3info.info[device.address].discoverycount = (eq3info.info[device.address].discoverycount || 0)+1;\n //node.warn( \"re-discovered \"+ device.address+ ' rssi:' + device._peripheral.rssi);\n eq3info.info[device.address].last_seen = (new Date()).valueOf();\n \n // always re-add disconnect listener, just in case\n if (device.disconnectFn){\n device.removeListener('disconnect', device.disconnectFn);\n }\n device.disconnectFn = function(){\n eq3info.disconnectCallback(device);\n };\n device.on('disconnect', device.disconnectFn );\n \n } else {\n eq3info.info[device.address].last_seen = (new Date()).valueOf();\n eq3info.devices[device.address] = device;\n //node.warn(eq3info.devices[device.address]);\n node.warn( \"discovered new \"+ device.address+ ' rssi:' + device._peripheral.rssi);\n // always remove and re-add disconnect listener, just in case\n if (device.disconnectFn){\n device.removeListener('disconnect', device.disconnectFn);\n }\n device.disconnectFn = function(){\n eq3info.disconnectCallback(device);\n };\n device.on('disconnect', device.disconnectFn );\n }\n};\n\n\nnode.warn(\"starting discovery\");\n\nif (eq3){\n var keys = Object.keys(eq3info.devices);\n\n // we want to remove all devices.\n for (var i = 0; i < keys.length; i++) {\n var device = eq3info.devices[keys[i]];\n node.warn( 'disconnect:'+ device.address+ ' rssi:' + device._peripheral.rssi);\n if (device.disconnectFn){\n device.removeListener('disconnect', device.disconnectFn);\n }\n device.disconnect();\n }\n}\n\neq3info.devices = {};\neq3info.info = {};\n//node.warn(eq3info.devices);\nglobal.set('eq3info', eq3info);\n\neq3.discoverAll(eq3info.discovercallback);\nnoble.startScanning([], true);\n\n\nreturn msg;","outputs":1,"noerr":0,"x":310,"y":40,"wires":[["aaa501f8.d744e","4ab8a582.5327fc"]]},{"id":"81d1f125.7392","type":"function","z":"d9611430.c0dd78","name":"stopdiscovery","func":"var eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (eq3){\n if (eq3info.discovercallback){\n node.warn(\"stop discovery\");\n eq3.stopDiscoverAll(eq3info.discovercallback);\n delete eq3info.discovercallback;\n }\n}\n\n\nreturn msg;","outputs":1,"noerr":0,"x":335,"y":101,"wires":[[]]},{"id":"b20be09f.80fd3","type":"inject","z":"d9611430.c0dd78","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":100,"y":180,"wires":[["77447862.1e2eb8"]]},{"id":"77447862.1e2eb8","type":"function","z":"d9611430.c0dd78","name":"disconnectall","func":"var eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (eq3){\n var keys = Object.keys(eq3info.devices);\n\n for (var i = 0; i < keys.length; i++) {\n var device = eq3info.devices[keys[i]];\n node.warn( 'fromglobal:'+ device.address+ ' rssi:' + device._peripheral.rssi);\n device.disconnect();\n }\n}\n\n\nreturn msg;","outputs":1,"noerr":0,"x":330,"y":180,"wires":[[]]},{"id":"235452f8.32841e","type":"inject","z":"d9611430.c0dd78","name":"","topic":"","payload":"","payloadType":"date","repeat":"30","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":240,"wires":[["2502a69.7e60a5a"]]},{"id":"2502a69.7e60a5a","type":"function","z":"d9611430.c0dd78","name":"rssi","func":"var eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (eq3 && eq3info.info){\n \n var keys = Object.keys(eq3info.info);\n\n var points = [];\n var now = new Date();\n\n for (var i = 0; i < keys.length; i++) {\n var info = eq3info.info[keys[i]];\n var newmsg = {\n topic:'rssi-'+info.name,\n payload:info.rssi\n };\n node.send(newmsg);\n }\n}\n\n","outputs":1,"noerr":0,"x":310,"y":240,"wires":[["b3f5608f.f8475"]]},{"id":"b3f5608f.f8475","type":"ui_chart","z":"d9611430.c0dd78","name":"","group":"34dcf9c9.e64796","order":0,"width":0,"height":0,"label":"chart","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"-150","ymax":"-40","removeOlder":"24","removeOlderPoints":"1000","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":490,"y":240,"wires":[[],[]]},{"id":"93597422.104a78","type":"ui_chart","z":"d9611430.c0dd78","name":"","group":"34dcf9c9.e64796","order":0,"width":0,"height":0,"label":"chart","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"100","removeOlder":"24","removeOlderPoints":"1000","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":950,"y":640,"wires":[[],[]]},{"id":"88321dc7.cc57","type":"ui_chart","z":"d9611430.c0dd78","name":"","group":"34dcf9c9.e64796","order":0,"width":0,"height":0,"label":"chart","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"30","removeOlder":"24","removeOlderPoints":"1000","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":950,"y":700,"wires":[[],[]]},{"id":"a7768e04.0d9d9","type":"ui_template","z":"d9611430.c0dd78","group":"24fd5e57.122362","name":"","order":0,"width":"6","height":"12","format":"\n<div ng-repeat=\"(key, value) in msg.payload\">\n <p>{{key}} - {{value.name}} - {{value.my_state}}</p>\n <p>Target:{{value.info.targetTemperature}} Valve:{{value.info.valvePosition}}</p>\n <p>last:{{value.last_response}}</p>\n <div ng-repeat=\"day in value.days\">\n day: {{day.day}}:\n <span ng-repeat=\"sched in day.segments\">\n {{sched.temp}} to {{sched.endtime.hour}}:{{sched.endtime.min}},\n </span>\n </div>\n \n \n</div>\n","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":680,"y":960,"wires":[[]]},{"id":"3ea3ece4.4a4a34","type":"ui_button","z":"d9611430.c0dd78","name":"clear","group":"34dcf9c9.e64796","order":0,"width":0,"height":0,"passthru":false,"label":"Clear","color":"","bgcolor":"","icon":"","payload":"[]","payloadType":"json","topic":"","x":120,"y":400,"wires":[["b3f5608f.f8475","93597422.104a78","88321dc7.cc57","7526a157.fbd93"]]},{"id":"7526a157.fbd93","type":"delay","z":"d9611430.c0dd78","name":"","pauseType":"delay","timeout":"0.2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":210,"y":460,"wires":[["fe80ba30.a06448","bf2fbe23.b741f"]]},{"id":"fe80ba30.a06448","type":"delay","z":"d9611430.c0dd78","name":"","pauseType":"delay","timeout":"0.2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":210,"y":520,"wires":[["bf2fbe23.b741f"]]},{"id":"bf2fbe23.b741f","type":"function","z":"d9611430.c0dd78","name":"","func":"\nreturn msg;","outputs":1,"noerr":0,"x":380,"y":500,"wires":[["448cbf8c.ea7a1","2502a69.7e60a5a"]]},{"id":"448cbf8c.ea7a1","type":"function","z":"d9611430.c0dd78","name":"loop devices","func":"var eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\ncontext.dev = context.dev || 0;\n\nif (!eq3)\n return;\n\nvar now = (new Date()).valueOf();\n\nvar keys = Object.keys(eq3info.devices);\n//node.warn(keys);\n\ncontext.dev = (context.dev+1) % keys.length;\n\n//for (var i = 0; i < keys.length; i++) {\nvar i = context.dev;\n\n var device = eq3info.devices[keys[i]];\n var info = eq3info.info[keys[i]];\n \n // only if seen in last 60 seconds\n if (info && info.last_seen + 60000 > now){\n var sendaddr = function(a){\n var newmsg1 = {\n device_address: keys[i],\n };\n node.send(newmsg1);\n };\n sendaddr(keys[i]);\n }\n \n//}\n\n","outputs":1,"noerr":0,"x":330,"y":600,"wires":[["98856bc5.4acfe8"]]},{"id":"93a9aa.05577658","type":"inject","z":"d9611430.c0dd78","name":"","topic":"","payload":"","payloadType":"date","repeat":"10","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":600,"wires":[["448cbf8c.ea7a1"]]},{"id":"bd1fae1e.f2472","type":"inject","z":"d9611430.c0dd78","name":"","topic":"","payload":"","payloadType":"date","repeat":"5","crontab":"","once":false,"onceDelay":0.1,"x":690,"y":880,"wires":[["8cb9965.2a0c768"]]},{"id":"8cb9965.2a0c768","type":"function","z":"d9611430.c0dd78","name":"loop devices","func":"var eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (!eq3)\n return;\n\n\nvar newinfo = JSON.stringify(eq3info.info);\n\nvar keys = Object.keys(eq3info.info);\n\nfor (var i = 0; i < keys.length; i++){\n eq3info.info[keys[i]].days = eq3info.info[keys[i]].days || [];\n //node.warn(util.inspect(eq3info.devices[keys[i]], {depth:null}));\n}\n\n//node.warn(eq3info.info);\n\nif ( newinfo !== context.lastinfo ){\n context.lastinfo = newinfo;\n var newmsg = {\n payload:eq3info.info\n };\n \n return newmsg;\n}\n\n","outputs":1,"noerr":0,"x":690,"y":920,"wires":[["a7768e04.0d9d9"]]},{"id":"bc50f8f3.c83668","type":"function","z":"d9611430.c0dd78","name":"extract valve","func":"var eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (!eq3)\n return;\n\nvar device = eq3info.devices[msg.device_address];\nvar info = eq3info.info[msg.device_address];\n\ntry{\n switch(msg.cmd){\n case 'setBoost':\n case 'setDateTime':\n case 'getInfo':\n case 'automaticMode':\n case 'ecoMode':\n case 'manualMode':\n if (!msg.payload){\n node.error(\"no payload?\"+util.inspect(msg));\n return;\n }\n if (!msg.payload.status){\n node.error(\"no payload?\"+util.inspect(msg));\n return;\n }\n \n msg.payload.status.readtime = (new Date()).valueOf();\n\n info.info = msg.payload.status;\n info.deviceaddress = msg.device_address;\n \n var newmsg = {\n topic:'valve-'+info.name,\n payload:info.info.valvePosition\n };\n node.send(newmsg);\n \n var newmsg2 = {\n topic:'temp-'+info.name,\n payload:info.info.targetTemperature\n };\n node.send([null, newmsg2]);\n \n break;\n default:\n break;\n }\n} catch(e){\n node.error(e);\n}\n\n","outputs":2,"noerr":0,"x":810,"y":660,"wires":[["93597422.104a78"],["88321dc7.cc57"]]},{"id":"385d4c9.8bc79b4","type":"debug","z":"d9611430.c0dd78","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":610,"y":820,"wires":[]},{"id":"9e0b8b90.df8918","type":"function","z":"d9611430.c0dd78","name":"Connect","func":"var eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\nvar require = global.get('require');\nvar noble = require('noble');\n\nif (!eq3){\n return;\n}\n\n// device_address: keys[i],\n// cmd: 'getInfo' // msg.payload = addrss\n\n\nvar device = eq3info.devices[msg.device_address];\nvar info = eq3info.info[msg.device_address];\n\nswitch(info.my_state){\n case 'connected': \n //node.warn( device.address+ ' already connected' );\n //if already connected, stay connected another 10s\n clearTimeout(device.disconnecttimer);\n device.disconnecttimer = setTimeout(function(){\n device.disconnect();\n }, 1000);\n node.send(msg);\n break;\n case undefined:\n case 'disconnected':\n case 'connectfailed':\n case 'connecttimeout':\n //node.warn( device.address+ ' try to connect' );\n info.my_state = 'connecting';\n device.connectAndSetup().then(\n (ok)=>{\n clearTimeout(device.connecttimer);\n noble.startScanning([], true);\n eq3info.info[device.address] = eq3info.info[device.address] || {};\n if (eq3info.names[device.address]){\n eq3info.info[device.address].name = eq3info.names[device.address];\n } else {\n eq3info.info[device.address].name = device.address;\n }\n \n //node.warn( device.address+ ' connected' );\n /*\n device._peripheral.updateRssi(function(error, rssi){\n //node.warn( \"rssi update:\"+ device.address+ ' rssi:' + device._peripheral.rssi);\n if (eq3info.info[device.address]){\n eq3info.info[device.address].rssi = device._peripheral.rssi;\n if (eq3info.names[device.address]){\n eq3info.info[device.address].name = eq3info.names[device.address];\n } else {\n eq3info.info[device.address].name = device.address;\n }\n }\n });\n */\n info.isconnected = true;\n \n clearTimeout(device.disconnecttimer);\n device.disconnecttimer = setTimeout(function(){\n device.disconnect();\n }, 1000);\n \n //node.warn( device.address+ ' connected' );\n info.my_state = 'connected';\n setTimeout(function(){\n node.send(msg);\n }, 1);\n },\n (err)=>{\n noble.startScanning([], true);\n node.error( device.address+ ' connect unsuccessful:'+err.toString() );\n info.my_state = 'connectfailed';\n \n setTimeout(function(){\n node.error('Retry from fail '+device.address);\n node.send([null, msg]);\n }, 2000);\n }\n );\n\n // if we timeout on connection\n clearTimeout(device.connecttimer);\n device.connecttimer = setTimeout(function(){\n // then disconnect\n if (eq3info.info[device.address]){\n eq3info.info[device.address].my_state = 'connecttimeout';\n device.disconnect();\n }\n //node.warn('connect timeout '+device.address);\n setTimeout(function(){\n node.error('Retry from timeout '+device.address);\n node.send([null, msg]);\n }, 2000);\n }, 15000);\n \n break;\n case 'connecting':\n // do nothing, we're already on it\n break;\n}\n\n\n","outputs":2,"noerr":0,"x":540,"y":700,"wires":[["74b17db7.d7d5b4"],["97f7e5e9.0866f8"]],"outputLabels":["","retry"]},{"id":"74b17db7.d7d5b4","type":"function","z":"d9611430.c0dd78","name":"readinfo","func":"var eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (!eq3)\n return;\n\n// device_address: keys[i],\n// cmd: 'getInfo' // msg.payload = addrss\n\nif (!msg.device_address){\n node.error(\"no device address\");\n return;\n}\n\n// nothing to do\nif (!msg.cmd){\n return;\n}\n\n\nvar device = eq3info.devices[msg.device_address];\nvar info = eq3info.info[msg.device_address];\n\nif (!device){\n node.error(\"no device for \"+msg.device_address);\n return;\n} else {\n}\n\nif (!device[msg.cmd]){\n node.error(\"invalid command \"+msg.cmd)\n return;\n}\n\nvar newmsg = {\n device_address: msg.device_address,\n cmd: msg.cmd\n};\n\nvar param1 = msg.payload;\nvar param2 = null;\n\n// functions with two parameters: \nswitch(msg.cmd){\n case 'ecoMode':\n param1 = msg.payload.temp;\n param2 = msg.payload.date;\n break;\n \n case 'updateOpenWindowConfiguration':\n param1 = msg.payload.temp;\n param2 = msg.payload.duration;\n break;\n \n case 'setComfortTemps':\n param1 = msg.payload.night;\n param2 = msg.payload.day;\n break;\n \n}\n\n//node.warn(\"cmd \"+msg.cmd+\" send \"+msg.payload);\ndevice[msg.cmd](param1, param2).then(\n a => {\n info.last_response = (new Date()).valueOf();\n newmsg.payload = a;\n setTimeout(function(){\n node.send(newmsg);\n if (info.commands && info.commands.length){\n info.commands.shift();\n if (info.commands.length){\n node.send([null, info.commands[0]]);\n }\n }\n }, 1);\n },\n err => {\n node.error(\"can't read from device \"+device.address+\" error \"+err);\n if (info.commands && info.commands.length){\n info.commands.shift();\n if (info.commands.length){\n node.send([null, info.commands[0]]);\n }\n }\n }\n);\n\n","outputs":2,"noerr":0,"x":540,"y":740,"wires":[["bc50f8f3.c83668","385d4c9.8bc79b4","ea3c271.5cb59d8","169bc4f2.ca11ab"],["9e0b8b90.df8918"]]},{"id":"36a1b3e4.5c18dc","type":"function","z":"d9611430.c0dd78","name":"queuemessage","func":"var eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (!eq3)\n return;\n\n// device_address: keys[i],\n// cmd: 'getInfo' // msg.payload = addrss\n\nif (!msg.device_address){\n node.warn(\"no device address\");\n return;\n}\n\n// nothing to do\nif (!msg.cmd){\n return;\n}\n\n\nvar device = eq3info.devices[msg.device_address];\nvar info = eq3info.info[msg.device_address];\n\n\nif (!device[msg.cmd]){\n node.warn(\"invalid command \"+msg.cmd)\n return;\n}\n\nif (!device){\n node.warn(\"no device for \"+msg.device_address);\n return;\n} else {\n}\n\nvar newmsg = {\n device_address: msg.device_address,\n cmd: msg.cmd,\n payload: msg.payload,\n};\n\ninfo.commands = info.commands || [];\n\ninfo.commands.push(newmsg);\n//node.warn(info.commands);\nif (info.commands.length === 1){\n return newmsg; \n}\n\n","outputs":1,"noerr":0,"x":360,"y":700,"wires":[["9e0b8b90.df8918"]]},{"id":"1cbbc812.bf41a8","type":"inject","z":"d9611430.c0dd78","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":100,"y":800,"wires":[["be5df164.cf5a2"]]},{"id":"be5df164.cf5a2","type":"function","z":"d9611430.c0dd78","name":"Add Functions","func":"\nvar eq3 = global.get('eq3');\n\nvar require = global.get('require');\nvar eq3interface = require('/home/pi/.node-red/node_modules/node-red-contrib-eq3-bluetooth/lib/eq3interface.js');\n\nif (!eq3)\n return;\n\n\nconst status = {\n manual: 1,\n holiday: 2,\n boost: 4,\n dst: 8,\n openWindow: 16,\n lock: 32,\n unknown2: 64,\n lowBattery: 128,\n};\n\n\n \neq3interface.parseInfo = function(info){\n try{\n switch(info[0]){\n case 0: // ??\n node.warn(info);\n return { \n unknown:true,\n raw: info,\n };\n break;\n\n case 1: // sysinfo\n node.warn(info);\n return {\n sysinfo:{\n ver: info[1],\n type: info[2],\n },\n raw: info,\n };\n break;\n\n case 2:\n node.warn(info);\n switch(info[1] & 0xf){\n case 1: // normal info\n const statusMask = info[2];\n const valvePosition = info[3];\n const targetTemperature = info[5] / 2;\n \n node.warn(info);\n \n var ecotime = undefined; \n node.warn(statusMask+\" \"+status.holiday+\" \"+info.length)\n if (((statusMask & status.holiday) === status.holiday) && (info.length >= 10)) {\n // parse extra bytes\n ecotime = {\n day:info[6],\n year: info[7]+2000,\n hour: (info[8]/2)>>0,\n min: (info[8] & 1)? 30:0,\n month: info[9],\n };\n ecotime.date = new Date(ecotime.year, ecotime.month-1, ecotime.day, ecotime.hour, ecotime.min, 0, 0);\n }\n \n return {\n raw:info,\n status: {\n manual: (statusMask & status.manual) === status.manual,\n holiday: (statusMask & status.holiday) === status.holiday,\n boost: (statusMask & status.boost) === status.boost,\n lock: (statusMask & status.lock) === status.lock,\n dst: (statusMask & status.dst) === status.dst,\n openWindow: (statusMask & status.openWindow) === status.openWindow,\n lowBattery: (statusMask & status.lowBattery) === status.lowBattery,\n valvePosition,\n targetTemperature,\n ecotime: ecotime,\n },\n };\n break;\n \n case 2: // schedule set response, returns day set\n var res = {\n raw:info,\n dayresponse:{\n day: info[2]\n } \n }\n return res;\n break;\n \n case 0x80: // return from setTempOffset \n var res = {\n ok: true,\n raw:info,\n }\n return res;\n break;\n }\n break;\n\n case 4: // time request?\n node.warn(info);\n return {\n timerequest:true,\n raw:info,\n };\n break;\n\n case 0x21:\n node.warn(info);\n var day = {\n day: info[1],\n segments: [],\n };\n for (var i = 2; i < info.length; i += 2){\n var segment = {\n temp: info[i]/2,\n endtime:{\n hour: ((info[i+1]*10)/60)>>0,\n min: ((info[i+1]*10)%60)>>0,\n }\n };\n day.segments.push(segment);\n }\n return {\n raw:info,\n dayschedule: day\n }\n break;\n \n case 0xa0:\n node.warn(info);\n // start firmware update\n break;\n \n case 0xa1:\n node.warn(info);\n switch(info[1]){\n default:\n break;\n case 0x11: // start next firmware package\n break;\n case 0x22: // send next frame\n break\n case 0x33: // restart frame transmission\n break;\n case 0x44: // update finished\n break;\n }\n // start firmware update\n break;\n default:\n node.warn(info);\n return {\n unknown:true,\n raw:info,\n };\n break;\n }\n \n } catch(e){\n return{ error: e.toString() };\n }\n};\n \n \neq3.prototype.automaticMode = function() {\n return this.writeAndGetNotification(eq3interface.payload.setAutomaticMode())\n .then(info => eq3interface.parseInfo(info), err => {return { error: err }});\n}\n\neq3.prototype.manualMode = function() {\n return this.writeAndGetNotification(eq3interface.payload.setManualMode())\n .then(info => eq3interface.parseInfo(info), err => {return { error: err }});\n}\n\n\n// sending ecoMode empty just turns on holiday mode.\neq3.prototype.holidayMode = function() {\n return this.ecoMode();\n}\n\n// sending ecoMode empty just turns on holiday mode (holiday+manual).\n// sending with just temp turns on holiday mode, returns a time? (now+1day?)\n// sending with empty temp and date turns on holiday mode (holiday+manual), but does not return a date\n// I think if the command is 'short', it can use bytes from the last command instead!!!\neq3.prototype.ecoMode = function(temp, date) {\n var tempstr = '00';\n if (!temp){\n tempstr = 'FF'; // 'vacation mode'\n } else {\n tempstr = ('0'+(0x80 | ((temp*2)>>0)).toString(16)).slice(-2);\n }\n if (date)\n node.warn(\"set eco @ \"+temp+\" until \"+date.toString());\n else \n node.warn(\"set eco @ \"+temp+\" no date\");\n \n const prefix = '40';\n var out = undefined;\n if (date){\n const year = ('0'+((date.getFullYear() - 2000)).toString(16)).slice(-2);\n const month = ('0'+(date.getMonth() + 1).toString(16)).slice(-2);\n const day = ('0'+date.getDate().toString(16)).slice(-2);\n var hour = date.getHours();\n const minute = date.getMinutes();\n hour *=2;\n if (minute >= 30){\n hour++;\n }\n hour = ('0'+hour.toString(16)).slice(-2);\n out = new Buffer(prefix+ tempstr + day+year + hour + month, 'hex');\n } else {\n out = new Buffer(prefix+ tempstr, 'hex');\n }\n\n node.warn(out);\n\n return this.writeAndGetNotification(out)\n .then(info => eq3interface.parseInfo(info), err => {return { error: err }});\n};\n \n \neq3.prototype.updateOpenWindowConfiguration = function(temperature, minDuration) {\n const temp = ('0'+(2 * temperature).toString(16)).slice(-2);\n const dur = ('0'+(minDuration / 5).toString(16)).slice(-2);\n var out =new Buffer(`14${temp}${dur}`, 'hex')\n\n return this.writeAndGetNotification(out)\n .then(info => eq3interface.parseInfo(info), err => {return { error: err }});\n};\n\neq3.prototype.setComfortTemps = function(night, day) {\n const tempNight = ('0'+(2 * night).toString(16)).slice(-2);\n const tempDay = ('0'+(2 * day).toString(16)).slice(-2);\n var out = new Buffer(`11${tempDay}${tempNight}`, 'hex')\n return this.writeAndGetNotification(out)\n .then(info => eq3interface.parseInfo(info), err => {return { error: err }});\n}\n\n \neq3.prototype.setDateTime = function(date) {\n var out = new Buffer(7);\n out[0] = 3;\n out[1] = date.getFullYear() - 2000;\n out[2] = (date.getMonth() + 1);\n out[3] = date.getDate();\n out[4] = date.getHours();\n out[5] = date.getMinutes();\n out[6] = date.getSeconds();\n\n return this.writeAndGetNotification(out)\n .then(info => eq3interface.parseInfo(info), err => {return { error: err }});\n}\n\neq3.prototype.getSysInfo = function() {\n var out = new Buffer(1);\n out[0] = 0;\n\n return this.writeAndGetNotification(out)\n .then(info => eq3interface.parseInfo(info), err => {return { error: err }});\n}\n\n \neq3.prototype.setBoost = function(enable) {\n if (enable) {\n return this.writeAndGetNotification(eq3interface.payload.activateBoostmode())\n .then(info => eq3interface.parseInfo(info), err => {return { error: err }});\n }\n return this.writeAndGetNotification(eq3interface.payload.deactivateBoostmode())\n .then(info => eq3interface.parseInfo(info), err => {return { error: err }});\n}\n\n\neq3.prototype.getDay = function(day){\n return this.writeAndGetNotification(new Buffer('200'+day, 'hex'))\n .then(info => eq3interface.parseInfo(info), err => {return { error: err }});\n/* \n .then(\n info => {\n if (info[0] != 0x21) return { error: 'incorrect return' };\n var day = {\n day: info[1],\n segments: [],\n raw:info,\n };\n for (var i = 2; i < info.length; i += 2){\n var segment = {\n temp: info[i]/2,\n hh: ((info[i+1]*10)/60)>>0,\n mm: ((info[i+1]*10)%60)>>0,\n };\n day.segments.push(segment);\n }\n return day;\n }, \n err => console.log(\"error in getInfo \"+err));\n*/ \n};\n\neq3.prototype.setDay = function(day){\n var out = new Buffer(16);\n out[0] = 0x10;\n out[1] = day.day;\n\n // zero all first\n for (var i = 0; i < 7; i++){\n out[(i*2)+2] = 0;\n out[(i*2)+3] = 0;\n }\n\n \n for (var i = 0; i < 7; i++){\n out[(i*2)+2] = 0;\n out[(i*2)+3] = 0;\n \n if (day.segments[i].temp && day.segments[i].endtime && day.segments[i].endtime.hour && day.segments[i].endtime.min ){\n out[(i*2)+2] = (day.segments[i].temp * 2)>>0;\n out[(i*2)+3] = (((day.segments[i].endtime.hour * 60) + day.segments[i].endtime.min)/10)>>0;\n } else {\n break; // stop at first non-temp\n }\n }\n \n \n return this.writeAndGetNotification(out)\n .then(info => eq3interface.parseInfo(info), err => {return { error: err }});\n/* .then(\n info => {\n if (info[0] !== 0x02) return { error: 'incorrect return' };\n if ((info[1] & 0xf) != 0x02) return { error: 'incorrect return' };\n var res = {\n day: info[2],\n raw:info,\n };\n return res;\n }, \n err => console.log(\"error in getInfo \"+err));\n */\n};\n\n\n\neq3.prototype.setComfortTemp = function() {\n var out =new Buffer(1);\n out[0] = 0x43;\n\n return this.writeAndGetNotification(out)\n .then(info => eq3interface.parseInfo(info), err => {return { error: err }});\n};\n\neq3.prototype.setEcoTemp = function() {\n var out =new Buffer(1);\n out[0] = 0x44;\n\n return this.writeAndGetNotification(out)\n .then(info => eq3interface.parseInfo(info), err => {return { error: err }});\n};\n\neq3.prototype.setTemperature = function(temp) {\n return this.writeAndGetNotification(eq3interface.payload.setTemperature(temp))\n .then(info => eq3interface.parseInfo(info), err => {return { error: err }});\n};\n\neq3.prototype.setLock = function(enable) {\n if (enable) {\n return this.writeAndGetNotification(eq3interface.payload.lockThermostat())\n .then(info => eq3interface.parseInfo(info), err => {return { error: err }});\n }\n return this.writeAndGetNotification(eq3interface.payload.unlockThermostat())\n .then(info => eq3interface.parseInfo(info), err => {return { error: err }});\n}\n\n\nreturn msg;\n","outputs":1,"noerr":0,"x":280,"y":800,"wires":[[]]},{"id":"ea3c271.5cb59d8","type":"function","z":"d9611430.c0dd78","name":"extract day","func":"var eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (!eq3)\n return;\n\nvar device = eq3info.devices[msg.device_address];\nvar info = eq3info.info[msg.device_address];\n\n\nswitch(msg.cmd){\n case 'getDay':\n if (!msg.payload){\n node.error(\"no payload?\"+util.inspect(msg));\n return;\n }\n if (msg.payload.dayschedule !== undefined){\n if (msg.payload.dayschedule.day !== undefined){\n info.days = info.days || {};\n info.days[msg.payload.dayschedule.day] = msg.payload.dayschedule;\n info.days[msg.payload.dayschedule.day].readtime = (new Date()).valueOf();\n }\n }\n \n //node.warn(info);\n break;\n default:\n break;\n}\n\n","outputs":1,"noerr":0,"x":810,"y":720,"wires":[[]]},{"id":"f5533844.9a85a8","type":"function","z":"d9611430.c0dd78","name":"GetAllDays","func":"\n\nvar eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (!eq3)\n return;\n\n\nmsg.device_address = \"00:1a:22:09:2c:df\";\n\nif (!msg.device_address){\n node.warn(\"no device address\");\n return;\n}\n\n\n\nvar device = eq3info.devices[msg.device_address];\nvar info = eq3info.info[msg.device_address];\n\n\nif (!device || !info){\n return;\n}\n\nvar get = function(address, day){\n var newmsg = {\n cmd: 'getDay',\n device_address: address,\n payload: day,\n };\n \n node.send(newmsg);\n}\n\n\nfor (var i = 0; i < 7; i++){\n get(msg.device_address, i);\n}\n\n//return msg;","outputs":1,"noerr":0,"x":150,"y":720,"wires":[["36a1b3e4.5c18dc"]]},{"id":"df2dd332.4d96b","type":"inject","z":"d9611430.c0dd78","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":80,"y":840,"wires":[["f5533844.9a85a8"]]},{"id":"4d5cfbb5.6117f4","type":"function","z":"d9611430.c0dd78","name":"Set Day","func":"\n\nvar eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (!eq3)\n return;\n\nmsg.device_address = \"00:1a:22:09:2c:df\";\n\nif (!msg.device_address){\n node.warn(\"no device address\");\n return;\n}\n\n\nvar device = eq3info.devices[msg.device_address];\nvar info = eq3info.info[msg.device_address];\n\n\nif (!device || !info){\n return;\n}\n\n\n\nvar set = function(address, day){\n var newmsg = {\n cmd: 'setDay',\n device_address: address,\n payload: day,\n };\n \n node.send(newmsg);\n}\n\nvar day = JSON.parse(JSON.stringify(info.days[0]));\nday.day = 1;\n\nset(msg.device_address, day);\n\n\n//return msg;","outputs":1,"noerr":0,"x":260,"y":880,"wires":[["36a1b3e4.5c18dc"]]},{"id":"8a041cda.8d52a","type":"inject","z":"d9611430.c0dd78","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":80,"y":880,"wires":[["4d5cfbb5.6117f4"]]},{"id":"169bc4f2.ca11ab","type":"function","z":"d9611430.c0dd78","name":"extract set day resp","func":"var eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (!eq3)\n return;\n\nvar device = eq3info.devices[msg.device_address];\nvar info = eq3info.info[msg.device_address];\n\n\nswitch(msg.cmd){\n case 'setDay':\n if (!msg.payload){\n node.error(\"no payload?\"+util.inspect(msg));\n return;\n }\n \n if (msg.payload.dayresponse !== undefined){\n if (msg.payload.dayresponse.day !== undefined){\n info.days = info.days || {};\n info.dayswritten = info.dayswritten || {};\n if (info.dayswritten[msg.payload.dayresponse.day]){\n info.days[msg.payload.dayresponse.day] = info.dayswritten[msg.payload.dayresponse.day]\n }\n info.days[msg.payload.dayresponse.day].writetime = (new Date()).valueOf();\n }\n }\n \n //node.warn(info);\n break;\n default:\n break;\n}\n\n","outputs":1,"noerr":0,"x":830,"y":760,"wires":[[]]},{"id":"832b8035.59c06","type":"inject","z":"d9611430.c0dd78","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":80,"y":920,"wires":[["98856bc5.4acfe8"]]},{"id":"98856bc5.4acfe8","type":"function","z":"d9611430.c0dd78","name":"Set DateTime","func":"\n\nvar eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (!eq3)\n return;\n\nif (!msg.device_address){\n node.warn(\"no device address\");\n return;\n}\n\n\nvar device = eq3info.devices[msg.device_address];\nvar info = eq3info.info[msg.device_address];\n\n\nif (!device || !info){\n return;\n}\n\n var newmsg = {\n cmd: 'setDateTime',\n device_address: msg.device_address,\n payload: new Date(),\n };\n \n node.send(newmsg);\n","outputs":1,"noerr":0,"x":280,"y":920,"wires":[["36a1b3e4.5c18dc"]]},{"id":"96a11b8.1e1e7e8","type":"inject","z":"d9611430.c0dd78","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":80,"y":960,"wires":[["d45b5125.a9707"]]},{"id":"d45b5125.a9707","type":"function","z":"d9611430.c0dd78","name":"setTemperatureOffset","func":"\n\nvar eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (!eq3)\n return;\n\nmsg.device_address = \"00:1a:22:09:2c:df\";\n\nif (!msg.device_address){\n node.warn(\"no device address\");\n return;\n}\n\n\nvar device = eq3info.devices[msg.device_address];\nvar info = eq3info.info[msg.device_address];\n\n\nif (!device || !info){\n return;\n}\n\n var newmsg = {\n cmd: 'setTemperatureOffset',\n device_address: msg.device_address,\n payload: 0,\n };\n \n node.send(newmsg);\n","outputs":1,"noerr":0,"x":300,"y":960,"wires":[["50d15325.61df5c"]]},{"id":"50d15325.61df5c","type":"function","z":"d9611430.c0dd78","name":"","func":"\nreturn msg;","outputs":1,"noerr":0,"x":470,"y":1000,"wires":[["36a1b3e4.5c18dc"]]},{"id":"8ecd0a2b.f41b08","type":"inject","z":"d9611430.c0dd78","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":80,"y":1000,"wires":[["a4e0bfc9.09cb4"]]},{"id":"a4e0bfc9.09cb4","type":"function","z":"d9611430.c0dd78","name":"setBoost0","func":"\n\nvar eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (!eq3)\n return;\n\nmsg.device_address = \"00:1a:22:09:2c:df\";\n\nif (!msg.device_address){\n node.warn(\"no device address\");\n return;\n}\n\n\nvar device = eq3info.devices[msg.device_address];\nvar info = eq3info.info[msg.device_address];\n\n\nif (!device || !info){\n return;\n}\n\n var newmsg = {\n cmd: 'setBoost',\n device_address: msg.device_address,\n payload: false,\n };\n \n node.send(newmsg);\n","outputs":1,"noerr":0,"x":260,"y":1000,"wires":[["50d15325.61df5c"]]},{"id":"b002d3d6.52194","type":"function","z":"d9611430.c0dd78","name":"setBoost1","func":"\n\nvar eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (!eq3)\n return;\n\nmsg.device_address = \"00:1a:22:09:2c:df\";\n\nif (!msg.device_address){\n node.warn(\"no device address\");\n return;\n}\n\n\nvar device = eq3info.devices[msg.device_address];\nvar info = eq3info.info[msg.device_address];\n\n\nif (!device || !info){\n return;\n}\n\n var newmsg = {\n cmd: 'setBoost',\n device_address: msg.device_address,\n payload: 1,\n };\n \n node.send(newmsg);\n","outputs":1,"noerr":0,"x":260,"y":1040,"wires":[["50d15325.61df5c"]]},{"id":"e88f3852.241568","type":"inject","z":"d9611430.c0dd78","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":80,"y":1040,"wires":[["96313a3a.ccb3b8"]]},{"id":"96313a3a.ccb3b8","type":"function","z":"d9611430.c0dd78","name":"testCommands","func":"\n\nvar eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (!eq3)\n return;\n\nmsg.device_address = \"00:1a:22:09:2c:df\";\n\nif (!msg.device_address){\n node.warn(\"no device address\");\n return;\n}\n\n\nvar device = eq3info.devices[msg.device_address];\nvar info = eq3info.info[msg.device_address];\n\n\nif (!device || !info){\n return;\n}\n\n var newmsg2 = {\n cmd: 'manualMode',\n device_address: msg.device_address,\n payload: null,\n };\n node.send(newmsg2);\n\n var newmsg3 = {\n cmd: 'ecoMode',\n device_address: msg.device_address,\n payload: {temp:0, date:(new Date((new Date()).valueOf()+ 1000*60*60*24))},\n };\n //node.send(newmsg3);\n\n\n var newmsg = {\n cmd: 'ecoMode',\n device_address: msg.device_address,\n payload: {},\n };\n //node.send(newmsg);\n\n\n var newmsg4 = {\n cmd: 'ecoMode',\n device_address: msg.device_address,\n payload: {temp:13, date:(new Date((new Date()).valueOf()+ 1000*60*60*24))},\n };\n node.send(newmsg4);\n\n var newmsg2 = {\n cmd: 'automaticMode',\n device_address: msg.device_address,\n payload: null,\n };\n node.send(newmsg2);\n","outputs":1,"noerr":0,"x":280,"y":1080,"wires":[["50d15325.61df5c"]]},{"id":"ceae85fd.4c5c58","type":"function","z":"d9611430.c0dd78","name":"testCommands","func":"\n\nvar eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (!eq3)\n return;\n\nmsg.device_address = \"00:1a:22:09:2c:df\";\n\nif (!msg.device_address){\n node.warn(\"no device address\");\n return;\n}\n\n\nvar device = eq3info.devices[msg.device_address];\nvar info = eq3info.info[msg.device_address];\n\n\nif (!device || !info){\n return;\n}\n\n var newmsg2 = {\n cmd: 'manualMode',\n device_address: msg.device_address,\n payload: null,\n };\n node.send(newmsg2);\n\n var newmsg4 = {\n cmd: 'setTemperature',\n device_address: msg.device_address,\n payload: 10,\n };\n node.send(newmsg4);\n\n \nreturn;\n\n var newmsg3 = {\n cmd: 'ecoMode',\n device_address: msg.device_address,\n payload: {temp:18, date:(new Date((new Date()).valueOf()+ 1000*60*60))},\n };\n// node.send(newmsg3);\n\n var newmsg = {\n cmd: 'setLock',\n device_address: msg.device_address,\n payload: 1,\n };\n node.send(newmsg);\n\n var newmsg4 = {\n cmd: 'setLock',\n device_address: msg.device_address,\n payload: 0,\n };\n node.send(newmsg4);\n\n\n\n","outputs":1,"noerr":0,"x":280,"y":1120,"wires":[["50d15325.61df5c"]]},{"id":"33975019.ed20b","type":"inject","z":"d9611430.c0dd78","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":80,"y":1100,"wires":[["ceae85fd.4c5c58"]]},{"id":"4d7e0649.4b1228","type":"inject","z":"d9611430.c0dd78","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":80,"y":1160,"wires":[["41363ada.16b1b4"]]},{"id":"41363ada.16b1b4","type":"function","z":"d9611430.c0dd78","name":"testCommands","func":"\n\nvar eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (!eq3)\n return;\n\nmsg.device_address = \"00:1a:22:09:2c:df\";\n\nif (!msg.device_address){\n node.warn(\"no device address\");\n return;\n}\n\n\nvar device = eq3info.devices[msg.device_address];\nvar info = eq3info.info[msg.device_address];\n\n\nif (!device || !info){\n return;\n}\n\nvar s = function(b){\n var newmsg3 = {\n cmd: 'sendRaw',\n device_address: msg.device_address,\n payload: new Buffer(b, 'hex'),\n };\n node.send(newmsg3);\n \n}\n\ns('b0');\ns('c0');\ns('d0');\ns('e0');\n\nreturn;\n\n\n\n\n\n var newmsg2 = {\n cmd: 'manualMode',\n device_address: msg.device_address,\n payload: null,\n };\n node.send(newmsg2);\n\n var newmsg4 = {\n cmd: 'setTemperature',\n device_address: msg.device_address,\n payload: 10,\n };\n node.send(newmsg4);\n\n \nreturn;\n\n\n var newmsg = {\n cmd: 'setLock',\n device_address: msg.device_address,\n payload: 1,\n };\n node.send(newmsg);\n\n var newmsg4 = {\n cmd: 'setLock',\n device_address: msg.device_address,\n payload: 0,\n };\n node.send(newmsg4);\n\n\n\n","outputs":1,"noerr":0,"x":280,"y":1180,"wires":[["50d15325.61df5c"]]},{"id":"7c1d2c4d.b03194","type":"function","z":"d9611430.c0dd78","name":"testCommands","func":"\n\nvar eq3 = global.get('eq3');\nvar eq3info = global.get('eq3info');\n\nif (!eq3)\n return;\n\nmsg.device_address = \"00:1a:22:09:2c:db\";\n\nif (!msg.device_address){\n node.warn(\"no device address\");\n return;\n}\n\n\nvar device = eq3info.devices[msg.device_address];\n\nnode.warn(util.inspect(device));\nmsg.payload = device._characteristics;\n\nreturn msg;","outputs":1,"noerr":0,"x":280,"y":1340,"wires":[["ff3eead8.073548"]]},{"id":"14830a0f.c1dad6","type":"inject","z":"d9611430.c0dd78","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":100,"y":1340,"wires":[["7c1d2c4d.b03194"]]},{"id":"ff3eead8.073548","type":"debug","z":"d9611430.c0dd78","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":480,"y":1360,"wires":[]},{"id":"97f7e5e9.0866f8","type":"function","z":"d9611430.c0dd78","name":"Retry connect loop","func":"\nreturn msg;","outputs":1,"noerr":0,"x":550,"y":660,"wires":[["9e0b8b90.df8918"]]},{"id":"aaa501f8.d744e","type":"mqtt out","z":"d9611430.c0dd78","name":"","topic":"","qos":"0","retain":"false","broker":"2d9e7c35.a76844","x":870,"y":40,"wires":[]},{"id":"4ab8a582.5327fc","type":"debug","z":"d9611430.c0dd78","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":520,"y":80,"wires":[]},{"id":"54b66c60.4141f4","type":"mqtt in","z":"d9611430.c0dd78","name":"","topic":"blectl/+","qos":"2","broker":"2d9e7c35.a76844","x":500,"y":140,"wires":[["215868a1.824d98"]]},{"id":"42cdfd1a.281824","type":"debug","z":"d9611430.c0dd78","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":690,"y":220,"wires":[]},{"id":"215868a1.824d98","type":"function","z":"d9611430.c0dd78","name":"getservices","func":"var eq3info = global.get('eq3info');\n\nvar t = msg.topic.split('/');\nvar deviceuuid = t[t.length-1];\n\n\nif (eq3info.peripherals){\n if (eq3info.peripherals[deviceuuid] && eq3info.peripherals[deviceuuid].peripheral){\n var id = deviceuuid;\n \n if (eq3info.peripherals[deviceuuid].peripheral.connectable){\n var c = function(error){\n try{\n node.warn(\"connected\");\n node.warn(error);\n var cb = function(error, services, characteristics){\n var newmsg = {\n topic: \"blediscover/\"+id+\"/services\", \n };\n if (error){\n newmsg.payload = {\n error: error.toString()\n };\n } else {\n eq3info.peripherals[deviceuuid].services = services;\n \n newmsg.payload = {\n services:[]\n }\n for (var i = 0; i < services.length; i++){\n var service = {\n uuid: services[i].uuid,\n characteristics:[]\n };\n \n for (var c = 0; c < services[i].characteristics.length; c++){\n var characteristic = {\n uuid: services[i].characteristics[c].uuid,\n properties: services[i].characteristics[c].properties,\n \n \n };\n service.characteristics.push(characteristic);\n }\n \n newmsg.payload.services.push(service);\n }\n //node.warn(services);\n }\n eq3info.peripherals[deviceuuid].peripheral.disconnect();\n node.send(newmsg);\n }\n node.warn(\"request all services for \"+deviceuuid);\n eq3info.peripherals[deviceuuid].peripheral.discoverAllServicesAndCharacteristics(cb);\n } catch(e){\n node.warn(e);\n }\n }\n try{\n eq3info.peripherals[deviceuuid].peripheral.connect(c)\n } catch(e){\n node.warn(e);\n }\n } else {\n node.warn(\"not connectable\");\n }\n \n }\n}\n\n","outputs":1,"noerr":0,"x":610,"y":180,"wires":[["42cdfd1a.281824","aaa501f8.d744e"]]},{"id":"b03aed81.005c2","type":"mqtt in","z":"d9611430.c0dd78","name":"","topic":"blectl/+/+/+","qos":"2","broker":"2d9e7c35.a76844","x":500,"y":320,"wires":[["c3fdff55.1b8f7"]]},{"id":"c3fdff55.1b8f7","type":"function","z":"d9611430.c0dd78","name":"characteristic","func":"var eq3info = global.get('eq3info');\n\nvar t = msg.topic.split('/');\nvar deviceuuid = t[t.length-3];\nvar serviceuuid = t[t.length-2];\nvar characteristicuuid = t[t.length-1];\n\n\nif (eq3info.peripherals){\n if (eq3info.peripherals[deviceuuid] && eq3info.peripherals[deviceuuid].services){\n \n// return;\n \n var services = eq3info.peripherals[deviceuuid].services;\n \n for (var s = 0; s < services.length; s++){\n if (services[s].uuid === serviceuuid){\n var service = services[s];\n for (var c = 0; c < service.characteristics.length; c++){\n if (service.characteristics[c].uuid === characteristicuuid){\n char = service.characteristics[c];\n var cb = function(error, data){\n try{\n node.warn('read cb');\n node.warn(data);\n \n var newmsg = {\n topic: \"blediscover/\"+deviceuuid+\"/\"+serviceuuid+\"/\"+characteristicuuid, \n };\n if (error){\n newmsg.payload = {\n error: error.toString()\n };\n } else {\n newmsg.payload = { data:data.toString('hex') };\n }\n node.send(newmsg);\n } catch(e){\n node.warn(e);\n }\n }\n \n \n if (eq3info.peripherals[deviceuuid].peripheral.state === 'connected'){\n node.warn(\"reading connected\");\n try{\n char.read(cb);\n } catch(e){\n node.warn(e);\n }\n } else {\n node.warn(\"calling connect\");\n //node.warn(eq3info.peripherals[deviceuuid]);\n if (eq3info.peripherals[deviceuuid].peripheral.connectable){\n var c = function(error){\n try{\n node.warn(\"connected\");\n node.warn(error);\n char.read(cb);\n } catch(e){\n node.warn(e);\n }\n }\n try{\n eq3info.peripherals[deviceuuid].peripheral.connect(c)\n } catch(e){\n node.warn(e);\n }\n } else {\n node.warn(\"not connectable\");\n }\n }\n break;\n }\n }\n break;\n }\n }\n } else {\n node.warn(\"no services\");\n }\n}\n\n","outputs":1,"noerr":0,"x":650,"y":320,"wires":[["aaa501f8.d744e"]]},{"id":"34dcf9c9.e64796","type":"ui_group","z":"","name":"heating","tab":"95e3af4d.5dfb5","disp":true,"width":"6","collapse":false},{"id":"24fd5e57.122362","type":"ui_group","z":"","name":"Default","tab":"95e3af4d.5dfb5","disp":true,"width":"6","collapse":false},{"id":"2d9e7c35.a76844","type":"mqtt-broker","z":"","name":"","broker":"192.168.1.210","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"95e3af4d.5dfb5","type":"ui_tab","z":"","name":"Home","icon":"dashboard"}] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment