This is an improved version of our original furnace control project, main improvements are:
- Using Node-RED SDK to develop control application.
- Added return and supply duct temperature sensors.
It is single stage cooling/heating furnace, with regular thermostat wiring.
Next Pi-Cubes products are used :
- Pi-Cubes Main Board
- Pi-Cubes DO4 Module
- Pi-Cubes Communication Thermostat
Furnace is wired to the Digital Outputs Module and two duct temperature sensors are wired to the Universal Inputs Module.
Communication Thermostat is wired using CAT5 cable that provides communication and power through same cable.
SoftwareThe control software application is developed in the Node-RED using Pi-Cubes SDK, information how to install Node-RED on the Raspbian may be find in next project tutorial:
https://www.hackster.io/cube-controls/temperature-monitoring-with-pi-cubes-raspberry-pi-646f35
Use the import function in the Node-RED and import each workspace in to Node-RED.
Set Thermostat Workspace
First the workspace program sets up thermostat configuration and time on it.
[{"id":"bd1de3da.42e22","type":"CTA","name":"Unit","slave":"1","regaddr":"2","scale":"1","scan":"30","x":444,"y":72,"z":"96fe3354.6901d","wires":[[]]},{"id":"3006bdb4.cff942","type":"CTA","name":"EnableClock","slave":"1","regaddr":"10","scale":"1","scan":"30","x":451,"y":162,"z":"96fe3354.6901d","wires":[[]]},{"id":"1fa6e3fb.e0591c","type":"CTA","name":"SetHour","slave":"1","regaddr":"11","scale":"1","scan":"30","x":506,"y":501,"z":"96fe3354.6901d","wires":[[]]},{"id":"1262046e.ed9dfc","type":"CTA","name":"SetMinutes","slave":"1","regaddr":"12","scale":"1","scan":"30","x":511,"y":600,"z":"96fe3354.6901d","wires":[[]]},{"id":"bad131b9.452ed","type":"function","name":"GetTime","func":"var now = new Date();\n\nvar hour = now.getHours();\nvar minute = now.getMinutes();\n\nvar newMsg1 = { payload: hour };\nvar newMsg2 = { payload: minute };\n\nreturn [ newMsg1, newMsg2 ];","outputs":"2","noerr":0,"x":304,"y":548,"z":"96fe3354.6901d","wires":[["1fa6e3fb.e0591c"],["1262046e.ed9dfc"]]},{"id":"97c746a7.6838b8","type":"CTA","name":"EnableFanIcon","slave":"1","regaddr":"15","scale":"1","scan":"30","x":457,"y":218,"z":"96fe3354.6901d","wires":[[]]},{"id":"bbe36d07.441c9","type":"CTA","name":"EnableSetPoint","slave":"1","regaddr":"30","scale":"1","scan":"30","x":459,"y":273,"z":"96fe3354.6901d","wires":[[]]},{"id":"f74bcfba.08b43","type":"CTA","name":"EnableFanMode","slave":"1","regaddr":"35","scale":"1","scan":"30","x":465,"y":334,"z":"96fe3354.6901d","wires":[[]]},{"id":"f7ea10ca.0815f","type":"CTA","name":"EnableHVACMode","slave":"1","regaddr":"40","scale":"1","scan":"30","x":470,"y":394,"z":"96fe3354.6901d","wires":[[]]},{"id":"a3cf17c2.5c30e8","type":"constant","name":"","value":"0","repeat":"15","x":166.66665649414062,"y":63.666656494140625,"z":"96fe3354.6901d","wires":[["bd1de3da.42e22"]]},{"id":"bb63fbc.f449c08","type":"constant","name":"","value":"1","repeat":"10","x":164.66665649414062,"y":175.66665649414062,"z":"96fe3354.6901d","wires":[["3006bdb4.cff942","97c746a7.6838b8","bbe36d07.441c9","f74bcfba.08b43","f7ea10ca.0815f"]]},{"id":"f945f183.06ba1","type":"constant","name":"","value":"1","repeat":"30","x":148.66665649414062,"y":549.6666870117188,"z":"96fe3354.6901d","wires":[["bad131b9.452ed"]]}]
Control Workspace
This is the main control program that runs furnace fan, cooling and staging based on the room temperature, setpoints and other parameters from the thermostat.
[{"id":"1b7de26e.e4821e","type":"writeDO","name":"Cool","module":"1","output":"2","x":1405.0000305175781,"y":54,"z":"fcc44c0.f033bb","wires":[["659ccc48.9a6334","1ee22bc4.e11dd4"]]},{"id":"2b53c1d8.d4ac3e","type":"writeDO","name":"Heat","module":"1","output":"3","x":1405.9999084472656,"y":206.00001525878906,"z":"fcc44c0.f033bb","wires":[["659ccc48.9a6334","4a687bb9.b59784"]]},{"id":"e47f3b09.1b80c8","type":"CTA","name":"CoolHeatIcon","slave":"1","regaddr":"5","scale":"1","scan":"30","x":1823.6668090820312,"y":125.66664123535156,"z":"fcc44c0.f033bb","wires":[[]]},{"id":"2d9cfb7d.d26304","type":"CTA","name":"SystemHVAC","slave":"1","regaddr":"4","scale":"1","scan":"10","x":665.6668090820312,"y":668.666748046875,"z":"fcc44c0.f033bb","wires":[[]]},{"id":"6799cb21.986634","type":"CTA","name":"RoomTemp","slave":"1","regaddr":"0","scale":"0.1","scan":"5","x":130.6666259765625,"y":255.6666259765625,"z":"fcc44c0.f033bb","wires":[["e4096e4a.1bf69","7abf47ed.8540b8","6171d738.9e8e28","2323eab0.dcdc16"]]},{"id":"8e6a50eb.7195b","type":"CTA","name":"RoomSetPt","slave":"1","regaddr":"31","scale":"0.1","scan":"10","x":126.66665649414062,"y":23.666641235351562,"z":"fcc44c0.f033bb","wires":[["e4096e4a.1bf69","7abf47ed.8540b8","cff8ffb0.3007","4da44a96.b25bb4","386ef375.c7910c"]]},{"id":"dbc24247.243dc","type":"CTA","name":"HVACMode","slave":"1","regaddr":"41","scale":"1","scan":"10","x":143.66665649414062,"y":411.0000305175781,"z":"fcc44c0.f033bb","wires":[["e0823934.1f7dc8","32949680.cd6b6a"]]},{"id":"fa11fef5.05ee","type":"CTA","name":"FanMode","slave":"1","regaddr":"36","scale":"1","scan":"10","x":143.66665649414062,"y":775.6666717529297,"z":"fcc44c0.f033bb","wires":[["3872c24c.c78d3e"]]},{"id":"87e8bf20.78174","type":"constant","name":"Deadband","value":"0.5","repeat":"5","x":130.66665649414062,"y":187.6666259765625,"z":"fcc44c0.f033bb","wires":[["cff8ffb0.3007","4da44a96.b25bb4"]]},{"id":"e4096e4a.1bf69","type":"hysteresis","name":"Cool","topicX":"RoomTemp","topicY0":"CoolSetPt","topicY1":"RoomSetPt","x":745.6666870117188,"y":60.666656494140625,"z":"fcc44c0.f033bb","wires":[["e6d07461.192f88"]]},{"id":"7abf47ed.8540b8","type":"hysteresis","name":"Heat","topicX":"RoomTemp","topicY0":"HeatSetPt","topicY1":"RoomSetPt","x":747.6666259765625,"y":211.66664123535156,"z":"fcc44c0.f033bb","wires":[["1eaa2fbc.e155d"]]},{"id":"36ce0e6c.c931f2","type":"constant","name":"1","value":"1","repeat":"5","x":118.66665649414062,"y":579.6666641235352,"z":"fcc44c0.f033bb","wires":[["e0823934.1f7dc8"]]},{"id":"72f599.ff8d0a68","type":"constant","name":"0","value":"0","repeat":"5","x":121.66665649414062,"y":508.66666412353516,"z":"fcc44c0.f033bb","wires":[["e0823934.1f7dc8"]]},{"id":"661c7688.99e388","type":"writeDO","name":"Fan","module":"1","output":"1","x":1340.6667785644531,"y":842.6666564941406,"z":"fcc44c0.f033bb","wires":[["d1c1617.f2e3ea","c9f3ba5e.360c48","e494858c.1b6b78","712fe791.8ed018"]]},{"id":"8cd6867b.732978","type":"delay-on-off","name":"Delay Off","delayon":"0","delayoff":"45","x":1022.6666717529297,"y":841.3332824707031,"z":"fcc44c0.f033bb","wires":[["661c7688.99e388"]]},{"id":"240b9b50.dbf464","type":"constant","name":"1","value":"1","repeat":"5","x":123.66665649414062,"y":966.3333740234375,"z":"fcc44c0.f033bb","wires":[["3872c24c.c78d3e"]]},{"id":"d1c1617.f2e3ea","type":"CTA","name":"FanRunIcon","slave":"1","regaddr":"16","scale":"1","scan":"30","x":1630.0000610351562,"y":842.0001602172852,"z":"fcc44c0.f033bb","wires":[[]]},{"id":"cff8ffb0.3007","type":"math","name":"CoolSetPt","math":"Add","number":"2","topicY0":"RoomSetPt","topicY1":"Deadband","topicY2":"","topicY3":"","x":424,"y":92,"z":"fcc44c0.f033bb","wires":[["e4096e4a.1bf69","6171d738.9e8e28"]]},{"id":"4da44a96.b25bb4","type":"math","name":"HeatSetPt","math":"Sub","number":"2","topicY0":"RoomSetPt","topicY1":"Deadband","topicY2":"","topicY3":"","x":424,"y":163,"z":"fcc44c0.f033bb","wires":[["7abf47ed.8540b8","6171d738.9e8e28"]]},{"id":"3ba7fb2d.c45804","type":"logic","name":"Not","operator":"Not","number":"2","topicX":"HVACMode","topicY0":"","topicY1":"","topicY2":"","topicY3":"","x":707,"y":538,"z":"fcc44c0.f033bb","wires":[["e6d07461.192f88"]]},{"id":"659ccc48.9a6334","type":"logic","name":"","operator":"Or","number":"2","topicX":"","topicY0":"Cool","topicY1":"Heat","topicY2":"","topicY3":"","x":1588,"y":126,"z":"fcc44c0.f033bb","wires":[["e47f3b09.1b80c8"]]},{"id":"6171d738.9e8e28","type":"hysteresis","name":"Mode","topicX":"RoomTemp","topicY0":"HeatSetPt","topicY1":"CoolSetPt","x":427,"y":334,"z":"fcc44c0.f033bb","wires":[["e0823934.1f7dc8"]]},{"id":"e0823934.1f7dc8","type":"logic","name":"HVACMode","operator":"Mux","number":"3","topicX":"HVACMode","topicY0":"0","topicY1":"1","topicY2":"Mode","topicY3":"","x":452.99998474121094,"y":529.9999923706055,"z":"fcc44c0.f033bb","wires":[["3ba7fb2d.c45804","1eaa2fbc.e155d","2d9cfb7d.d26304"]]},{"id":"1eaa2fbc.e155d","type":"logic","name":"Heat","operator":"And","number":"2","topicX":"","topicY0":"Heat","topicY1":"HVACMode","topicY2":"","topicY3":"","x":958.9999847412109,"y":208,"z":"fcc44c0.f033bb","wires":[["5fcf5c16.a030a4","c9f3ba5e.360c48"]]},{"id":"e6d07461.192f88","type":"logic","name":"Cool","operator":"And","number":"2","topicX":"","topicY0":"Cool","topicY1":"Not","topicY2":"","topicY3":"","x":957.9999847412109,"y":58,"z":"fcc44c0.f033bb","wires":[["5fcf5c16.a030a4","e494858c.1b6b78"]]},{"id":"15cf66b6.ea3099","type":"comment","name":"Mode","info":"0 - Cool\n1 - Heat","x":446.895751953125,"y":476.8888854980469,"z":"fcc44c0.f033bb","wires":[]},{"id":"3872c24c.c78d3e","type":"logic","name":"FanMode","operator":"Mux","number":"3","topicX":"FanMode","topicY0":"0","topicY1":"1","topicY2":"HeatCoolCall","topicY3":"","x":514.8957977294922,"y":843,"z":"fcc44c0.f033bb","wires":[["8cd6867b.732978"]]},{"id":"72fcab1c.8d0354","type":"constant","name":"0","value":"0","repeat":"5","x":123.89582824707031,"y":893,"z":"fcc44c0.f033bb","wires":[["3872c24c.c78d3e"]]},{"id":"5fcf5c16.a030a4","type":"logic","name":"HeatCoolCall","operator":"Or","number":"2","topicX":"","topicY0":"Cool","topicY1":"Heat","topicY2":"","topicY3":"","x":1019.8958129882812,"y":340.11112213134766,"z":"fcc44c0.f033bb","wires":[["3872c24c.c78d3e"]]},{"id":"e494858c.1b6b78","type":"logic","name":"","operator":"And","number":"2","topicX":"","topicY0":"Cool","topicY1":"Fan","topicY2":"","topicY3":"","x":1197.3403625488281,"y":54.888885498046875,"z":"fcc44c0.f033bb","wires":[["1b7de26e.e4821e"]]},{"id":"c9f3ba5e.360c48","type":"logic","name":"","operator":"And","number":"2","topicX":"","topicY0":"Heat","topicY1":"Fan","topicY2":"","topicY3":"","x":1198.34033203125,"y":208.88888549804688,"z":"fcc44c0.f033bb","wires":[["2b53c1d8.d4ac3e"]]},{"id":"2323eab0.dcdc16","type":"function","name":"Global RoomTemp","func":"context.global.roomtemp = msg.payload;\nreturn msg;","outputs":1,"noerr":0,"x":128,"y":352,"z":"fcc44c0.f033bb","wires":[[]]},{"id":"1ee22bc4.e11dd4","type":"function","name":"Global Cool","func":"if (msg.payload == \"0\") context.global.cool = \"OFF\";\nelse context.global.cool = \"ON\";\nreturn msg;","outputs":1,"noerr":0,"x":1649,"y":55,"z":"fcc44c0.f033bb","wires":[[]]},{"id":"4a687bb9.b59784","type":"function","name":"Global Heat","func":"if (msg.payload == \"0\") context.global.heat = \"OFF\";\nelse context.global.heat = \"ON\";\nreturn msg;","outputs":1,"noerr":0,"x":1645,"y":210,"z":"fcc44c0.f033bb","wires":[[]]},{"id":"712fe791.8ed018","type":"function","name":"Global Fan","func":"if (msg.payload == \"0\") context.global.fan = \"OFF\";\nelse context.global.fan = \"ON\";\nreturn msg;","outputs":1,"noerr":0,"x":1615,"y":906,"z":"fcc44c0.f033bb","wires":[[]]},{"id":"32949680.cd6b6a","type":"function","name":"Global HVACMode","func":"if (msg.payload == \"0\") context.global.mode = \"COOL\"; \nelse if (msg.payload == \"1\") context.global.mode = \"HEAT\"; \nelse context.global.mode = \"AUTO\"; \nreturn msg;","outputs":1,"noerr":0,"x":395,"y":402,"z":"fcc44c0.f033bb","wires":[[]]},{"id":"386ef375.c7910c","type":"function","name":"Global Set Point","func":"if (context.global.setpointchanged == 1)\n{\n msg.payload = context.global.setpoint;\n context.global.setpointchanged = 0;\n return msg;\n}\n\ncontext.global.setpoint = msg.payload;\n","outputs":1,"noerr":0,"x":125,"y":98,"z":"fcc44c0.f033bb","wires":[["8e6a50eb.7195b"]]},{"id":"e501698a.1afe98","type":"readUI","name":"ReturnAirTemp","module":"2","input":"1","uitype":"3","unit":"0","scan":"5","x":163,"y":1071,"z":"fcc44c0.f033bb","wires":[[]]},{"id":"c7d7381e.3828c8","type":"readUI","name":"SupplyAirTemp","module":"2","input":"2","uitype":"3","unit":"0","scan":"5","x":161,"y":1146,"z":"fcc44c0.f033bb","wires":[[]]},{"id":"e7621fd7.189de","type":"readUI","name":"DiffPressure","module":"2","input":"3","uitype":"2","unit":"0","scan":"5","x":152,"y":1223,"z":"fcc44c0.f033bb","wires":[["6f161ed7.90e9e"]]},{"id":"6f161ed7.90e9e","type":"range","minin":"10","maxin":"100","minout":"0.25","maxout":"1.50","action":"scale","round":false,"name":"","x":401,"y":1226,"z":"fcc44c0.f033bb","wires":[["ff1ca825.00e358"]]},{"id":"ff1ca825.00e358","type":"monitor","name":"","x":663,"y":1223,"z":"fcc44c0.f033bb","wires":[[]]}]
Web Workspace
This is a program that provides web interface.
[{"id":"b0a28c64.4f5d7","type":"websocket-listener","path":"/ws/mobiui","wholemsg":"false"},{"id":"5c0e4799.a3f1b8","type":"http in","name":"HTTP request","url":"/mobiui","method":"get","x":375,"y":156,"z":"4218cc1f.bde734","wires":[["2eafafdc.d1505"]]},{"id":"929cbcf3.6d634","type":"function","name":"ui dispatcher","func":"var obj = JSON.parse(msg.payload);\ndelete msg.payload;\ndelete msg._session;\n\n\nif(obj.id==\"sld-setpoint\")\n{\n context.global.setpoint = obj.v;\n context.global.setpointchanged = 1;\n msg.payload = {\"id\": obj.id, \"v\": obj.v};\n \n return msg;\n}","outputs":"1","noerr":0,"x":637,"y":754,"z":"4218cc1f.bde734","wires":[["153eaa3.feac156","f58bffa0.0a74"]]},{"id":"153eaa3.feac156","type":"websocket out","name":"web socket mobiUI - out","server":"b0a28c64.4f5d7","client":"","x":1031,"y":267,"z":"4218cc1f.bde734","wires":[]},{"id":"820757dd.7df8a8","type":"websocket in","name":"web socket mobiui - in","server":"b0a28c64.4f5d7","x":384,"y":752,"z":"4218cc1f.bde734","wires":[["929cbcf3.6d634"]]},{"id":"a33297a.f5ccd68","type":"function","name":"set ui status msg","func":"var statusMsg = {stMsg: msg.topic, dur:0, pri:1};\nmsg.payload = {id:\"sta-1\", v:statusMsg};\nreturn msg;","outputs":1,"noerr":0,"x":668,"y":318,"z":"4218cc1f.bde734","wires":[["153eaa3.feac156"]]},{"id":"f58bffa0.0a74","type":"debug","name":"","active":false,"console":"false","complete":"true","x":967,"y":765,"z":"4218cc1f.bde734","wires":[]},{"id":"7335140d.8ccaec","type":"http response","name":"http responce: mobiui","x":1026,"y":154,"z":"4218cc1f.bde734","wires":[]},{"id":"2eafafdc.d1505","type":"template","name":"Mobile web-App v1.2 ","field":"","template":"<!DOCTYPE HTML>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta HTTP-EQUIV=\"CACHE-CONTROL\" CONTENT=\"NO-CACHE\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" /> \n <meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n <title>Node-RED mobi ui</title>\n <link rel=\"stylesheet\" href=\"//code.jquery.com/mobile/1.4.3/jquery.mobile-1.4.3.min.css\" />\n <script src=\"//code.jquery.com/jquery-1.11.1.min.js\"></script>\n <script src=\"//code.jquery.com/mobile/1.4.3/jquery.mobile-1.4.3.min.js\"></script>\n <script src=\"//cdnjs.cloudflare.com/ajax/libs/highcharts/4.0.3/highcharts.js\"></script>\n <script>//Node-Red mobi ui - LHG industrialinternet.co.uk\n\tconsole.log(\"NR mobi UI 1.1.a : Controls, Chart & Schedule\");\n\tvar schedule = null;\t\t\t\t// schedule Obj \n\tvar itemLookup = null; \t\t\t// pointer to current schedule event\n\tvar statusMsgDisplayed= false;\t// flag to stop msg disco effect\n\tvar prioritySet =false;\t\t \t// flag showing if high prio msg being displayed\n\tvar daiableWidgets = false; \n\tvar connected = false;\n \tif(location.protocol==\"https:\"){\n\t\tvar wsUri=\"wss://\"+window.location.hostname+\":1880/ws/mobiui\";\n\t} else {\n\t\tvar wsUri=\"ws://\"+window.location.hostname+\":1880/ws/mobiui\";\n\t}\n\tvar ws=null;\n\tfunction appInit(){\n\t\tif ( schedule == null && localStorage[\"schedule\"]) {\n\t\t\tschedule = localStorage[\"schedule\"];\n\t\t\tconsole.log(\"loaded schedule from local.\");\n\t\t} \n\t}\n\tappInit();\n\tfunction wsConn() {\n\t\tws = new WebSocket(wsUri);\n\t\tws.onmessage = function(m) {\n\t\t\tconsole.log('< from-node-red:',m.data);\n\t\t\tif (typeof(m.data) === \"string\" && m. data !== null){\n\t\t\t\tvar msg =JSON.parse(m.data);\n\t\t\t\tvar ftc = msg.id.substring(0, 3);\n\t\t\t\t//console.log(\"id:\"+msg.id+\" fct:\"+ftc);\n\t\t\t\tif(ftc== \"ini\") {uiInit(msg.v);}\n\t\t\t\tif(ftc==\"tsw\"){setFlip(msg.id,msg.v);}\n\t\t\t\tif(ftc==\"sld\"){setSlider(msg.id,msg.v);}\n\t\t\t\tif(ftc==\"val\"){setValue(msg.id,msg.v);}\n\t\t\t\t//if(ftc==\"cha\"){showCharts( msg.v.values,msg.v.colors,msg.v.engs,msg.v.tags,msg.v.names,msg.v.nos,msg.v.title,.msg.v.yTitle)};\n\t\t\t\tif(ftc==\"cha\"){showCharts( msg.v.values,msg.v.colors,msg.v.engs,msg.v.tags,msg.v.names,msg.v.nos,msg.v.title,msg.v.xtitle,msg.v.ytitle)};\n\t\t\t\tif(ftc==\"shd\"){setSchedule(msg.v);}\n\t\t\t\tif(ftc==\"sta\"){statusMsgDisplayed= false;setStatus(msg.v.stMsg,msg.v.dur,msg.v.pri);}\n\t\t\t\tif(ftc==\"ack\"){clearReq();}\n\t\t\t}\n\t\t}\n\t\tws.onopen = function() { \n\t\t\tstatusMsgDisplayed=false;\n\t\t\tif(daiableWidgets==true){enablePage();}\n\t\t\tsetStatus(\"Connected\",5,0); \n\t\t\tconnected = true;\n\t\t\tvar obj = {\"id\":\"init\",\"v\":document.cookie};\n\t\t\tgetRequest = JSON.stringify(obj); \t\n\t\t\tws.send(getRequest);\t\t\t// Request ui status from NR\n\t\t\tconsole.log(\"sent init requeset\");\n\t\t}\n\t\tws.onclose = function() {\n\t\t\tconsole.log('Node-RED connection closed: '+new Date().toUTCString()); \n\t\t\tconnected = false; \n\t\t\tws = null;\n\t\t\tsetStatus(\"No connection to server!\",0,1);\n\t\t\tif(daiableWidgets==false){disablePage();}\n\t\t\tsetTimeout(wsConn, 10000);\n\t\t}\t\n\t\tws.onerror = function(){\n\t\t\tconsole.log(\"connection error\");\n\t\t}\n\t}\n\twsConn(); \t\t\t\t\t// connect to Node-RED server\n\t\n\tfunction uiInit(values){ \t\t// initialise UI controls\n\t\tvar ui = values; // JSON.parse(values);\n\t\t for (var item in ui) {\n\t\t\tconsole.log(\"id:\"+item.toString() +\" v:\"+ui[item].v);\n\t\t\tvar m = {\"id\" : item.toString(), \"v\": ui[item].v};\n\t\t\t//console.log(\"m: \"+m);\n\t\t\tinitSetters(m);\n\t\t}\n\t}\n\tfunction initSetters(msg){ \t// update UI widgets on connect \n\t\tconsole.log(\"init item id:\"+msg.id+\" value:\"+ msg.v);\n\t\tvar ftc = msg.id.substring(0, 3);\n\t\tif(ftc==\"tsw\"){setFlip(msg.id,msg.v);}\n\t\tif(ftc==\"sld\"){setSlider(msg.id,msg.v);}\n\t\tif(ftc==\"val\"){setValue(msg.id,msg.v);}\n\t\tif(ftc==\"cha\"){showCharts( msg.v.values,msg.v.colors,msg.v.engs,msg.v.tags,msg.v.names,msg.v.nos,msg.v.title,msg.v.xTitle.msg.v.yTitle)};\n\t\tif(ftc==\"shd\"){setSchedule(msg.v);}\n\t\tif(ftc==\"sta\"){setStatus(msg.v);}\n\t}\n\tfunction setFlip(_id,_v){ \t// update flip \n\t\tmyselect = $(\"#\"+_id);\n\t\t//console.log(\"flip id:\"+_id+\" value:\"+_v+\" tyepof:\"+ typeof _v +\" state:\"+myselect.data('state')+\" req:\"+myselect.data('req'));\n\t\t//if(myselect.data('req')==1) return; // request on progress stops flip UI chatter \n\t\tif(myselect.data('state')!=_v){\n\t\t\tif(_v== true || _v=='true'){\n\t\t\t\tmyselect[0].selectedIndex=1; \n\t\t\t\tmyselect.data('state',1)\n\t\t\t} \n\t\t\telse { \n\t\t\t\tmyselect[0].selectedIndex=0;\n\t\t\t\tmyselect.data('state',0);\n\t\t\t}\n\t\t\tmyselect.flipswitch(\"refresh\");\n\t\t\t//myselect.stopImmediatePropagation();\n\t\t\t//console.log(\"jq:\"+myselect[0].selectedIndex+\" flip id:\"+_id+\" v:\"+value+\" data-state:\"+myselect.data('state'));\n\t\t}\n\t}\n\tfunction setSlider(_id,_v){\t// update slider\n\t\tmyselect = $(\"#\"+_id);\n\t\t myselect.val(_v);\n\t\t myselect.slider('refresh');\n\t}\n\tfunction setValue(_id,_v){\t// update value display\n\t\tmyselect = $(\"#\"+_id);\n\t\tmyselect.val(_v);\n\t}\n\tfunction showCharts(_data,colors,engs,tags,names,nos,cTitle,xTitle,yTitle){ // render chart\n\t\tvar seriesNo = [];\n\t\tfor (i=0; i<nos; i++){\n\t\t\tseriesNo.push({}); \n\t\t}\n\t\tconsole.log(\"seriesNo:\"+seriesNo);\n\t\tvar options = {\n\t\t\tchart: {\n\t\t\t\tmarginRight: 30,\n\t\t\t\trenderTo: 'container',\n\t\t\t\ttype: 'spline',\n\t\t\t\t},\n\t\t\t\t title: {\n\t\t\t\t\t\ttext: cTitle\n\t\t\t\t},\n\t\t\t\t xAxis: {\n\t\t\t\t\t type: 'datetime',\n\t\t\t\t\tdateTimeLabelFormats: {\n\t\t\t\t\t\thour: '%H',\n\t\t\t\t\t\tday: '%H <br/>%a %d %b' \n\t\t\t\t\t},\n\t\t\t\t\tgridLineColor: '#C0C0C0',\n\t\t\t\t\ttickInterval: 1 * 3600 * 1000,\n\t\t\t\t\ttitle: {\n\t\t\t\t\t\ttext: xTitle\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t yAxis: {\n\t\t\t\t\ttitle: {\n\t\t\t\t\t\ttext: yTitle\n\t\t\t\t\t},\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tgridLineWidth: 0.5\t\t\t\n\t\t\t\t},\n\t\t\t\ttooltip: {\n\t\t\t\t\tformatter: function() {\n\t\t\t\t\t\teng=engs[this.series.options.id];\n\t\t\t\t\t\ttag=tags[this.series.options.id]; \n\t\t\t\t\t\treturn \"<strong>\"+ Highcharts.numberFormat(this.y, 1) +\"</strong>\"+eng+\" \"+tag+\"<br/>\"+ Highcharts.dateFormat('%a %d %b %H:%M:%S', this.x) +'<br/>';\t\t\t \n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\tseries: seriesNo\n\t\t};\n\t\tfor (i=0; i<nos; i++){\n\t\t\toptions.series[i].id=i;\n\t\t\toptions.series[i].color=colors[i];\n\t\t\toptions.series[i].lineWidth=1;\n\t\t\toptions.series[i].name= names[i];\n\t\t\toptions.series[i].data = JSON.parse(_data[i]);\n\t\t}\n\t\tvar chart = new Highcharts.Chart(options);\n\t}\n\tfunction setSchedule(_v){\t// update schedule \n\t\tconsole.log(\"shed:\"+typeof _v);\n\t\tif(typeof _v == \"string\") { // update from NR\n\t\t\tschedule = JSON.parse(_v);\n\t\t\tlocalStorage[\"schedule\"] = schedule;\n\t\t}\n\t\tconsole.log(\"shed:\"+schedule.items[0].id);\n\t\t$(\"#shd-1\").prop( \"checked\", true ).checkboxradio( \"refresh\" );\n\t\titemLookup = 0;\n\t\t$('#shd-tag').val(schedule.items[0].tag);\n\t\t$('#shd-st').val(schedule.items[0].startTime);\n\t\t$('#shd-st-v').val(schedule.items[0].startValue);\n\t\t$('#shd-et').val(schedule.items[0].endTime);\n\t\t$('#shd-et-v').val(schedule.items[0].endValue);\n\t\t$(\"checkbox\").prop( \"checked\", false ).checkboxradio( \"refresh\" );\n\t\tfor (dow = 0; dow< 7; dow++) {\n\t\t\tvar dowUI = '#shd-dow-'+dow;\n\t\t\tif (schedule.items[0].dofWeek[dow]==1){\n\t\t\t\t$(dowUI).prop( \"checked\", true ).checkboxradio( \"refresh\" );\n\t\t\t} else {\n\t\t\t\t$(dowUI).prop( \"checked\", false ).checkboxradio( \"refresh\" );\n\t\t\t}\n\t\t}\t\n\t}\n\tfunction setStatus(msg,dur,pri){\t // show msg on status bar\n\t\tconsole.log(\"statusMsgDisplayed:\"+statusMsgDisplayed);\n\t\tif(statusMsgDisplayed== true){return};\n\t\tstatusMsgDisplayed=true;\n\t\tif(pri>0 && prioritySet == false ){\n\t\t\tprioritySet = true;\t\t\t\n\t\t\t$(\"#statusView\").toggleClass(\"statusViewAlert\"); // toggle ON\n\t\t} else if ( pri==0 && prioritySet == true) {\n\t\t\tprioritySet = false;\n\t\t\t$(\"#statusView\").toggleClass(\"statusViewAlert\"); // toggle Off\n\t\t}\n\t\t$(\"#statusView\").show();\n\t\t$(\"#statusView\").html(msg);\n\t\tdur = dur*1000;\n\t\tif(dur >0){\n\t\t\tsetTimeout(function(){$(\"#statusView\").hide(200);$(\"#statusView\").html(\"\"); statusMsgDisplayed= false;prioritySet=false;},dur)\n\t\t}\n\t}\n\tfunction disablePage(){\t\t\n\t\t$(\"[data-role=flipswitch]\").flipswitch( \"disable\" );\n\t\t//$(\"[data-role=range]\").disabled = true;\n\t\t$(\"[data-role=range]\").slider( \"option\", \"disabled\", true );\n\t\t$(\"[data-rel=popup]\").toggleClass(\"ui-disabled\");\n\t\tdaiableWidgets = true;\n\t}\n\tfunction enablePage(){\n\t\t$(\"[data-role=flipswitch]\").flipswitch( \"enable\" );\n\t\t$(\"[data-role=range]\").slider( \"option\", \"enabled\", true );\n\t\t$(\"[data-role=range]\").slider( \"enable\" );\n\t\t$(\"[data-rel=popup]\").toggleClass(\"ui-disabled\");\n\t\tdaiableWidgets = false;\n\t}\t\n\t$(function() { \t\t\t\t// UI event handlers \n\t\t// Flip-switch change\n\t\t$(\"[data-role=flipswitch]\").bind( \"change\", function(event, ui) {\n\t\t\t//console.log(\"id:\"+this.id+\" val:\"+$(this).flipswitch().val()+\" state:\"+$(this).data('state')+\" req:\"+$(this).data('reqstate'));\n\t\t\tvar _value = $(this).flipswitch().val();\n\t\t\tif($(this).data('state') != _value){\n\t\t\t\t$(this).data('state',_value); \n\t\t\t\tvar obj = {\"id\":\"\"+this.id+\"\",\"v\":_value};\n\t\t\t\tsetActions = JSON.stringify(obj); \t\n\t\t\t\tws.send(setActions);\n\t\t\t}\n\t\t});\n\t\t// Slider end\n\t\t$(\".ui-slider\").bind( \"slidestop\", function(event, ui) {\n\t\t\tvar obj = {\"id\":\"\"+event.target.id+\"\",\"v\":event.target.value};\n\t\t\tsetActions = JSON.stringify(obj); \t\n\t\t\tws.send(setActions);\n\t\t});\n\t\t// Popup send\n\t\t$(\"[data-ui-type=pop-save]\").bind( \"click\", function(event, ui) {\n\t\t\tbid = this.id.split(\"_\");\n\t\t\twid =\"#\"+bid[0]+\"-pop\";\n\t\t\t$(wid ).popup( \"close\" );\n\t\t\ttid=\"#\"+bid[0];\n\t\t\tvar obj = {\"id\":\"\"+bid[0]+\"\",\"v\":$(tid ).val()};\n\t\t\tsetActions = JSON.stringify(obj); \t\n\t\t\tws.send(setActions);\n\t\t});\n\t\t$( document ).on( \"vmouseout\", \"textarea\", function() {\n\t\t\tconsole.log(\"text id: \"+this.id+\" v:\"+$(this ).val());\n\t\t\tvar obj = {\"id\":\"\"+this.id+\"\",\"v\":$(this ).val()};\n\t\t\tsetActions = JSON.stringify(obj); \t\n\t\t\tws.send(setActions);\n\t\t});\n\t\t// Grouped Radio buttons click\n\t\t$(\"[data-ui-type=shd-sel]\").bind( \"click\", function(event, ui) {\n\t\t\t$(\"[data-ui-type=shd-sel]\").prop( \"checked\", false ).checkboxradio( \"refresh\" );\n\t\t\t$(this ).prop( \"checked\", true ).checkboxradio( \"refresh\" );\n\t\t\tvar item = this.id.split(\"-\");\n\t\t\tif( itemLookup == null){\n\t\t\t\t itemLookup = item[1]-1;\n\t\t\t } else { // Copy item edits back obj\n\t\t\t\tschedule.items[itemLookup].tag\t\t = $('#shd-tag').val();\n\t\t\t\tschedule.items[itemLookup].startTime = $('#shd-st').val();\n\t\t\t\tschedule.items[itemLookup].startValue = $('#shd-st-v').val();\n\t\t\t\tschedule.items[itemLookup].endTime\t = $('#shd-et').val();\n\t\t\t\tschedule.items[itemLookup].endValue\t = $('#shd-et-v').val();\n\t\t\t\tfor (dow = 0; dow< 7; dow++) {\n\t\t\t\t\tvar dowUI = '#shd-dow-'+dow;\n\t\t\t\t\tif( $(dowUI).prop( \"checked\")){\n\t\t\t\t\t\tschedule.items[itemLookup].dofWeek[dow] = 1 ;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tschedule.items[itemLookup].dofWeek[dow] = 0 ;\n\t\t\t\t\t}\n\t\t\t\t} \n\t\t\t\titemLookup = item[1]-1;\n\t\t\t }\n\t\t\tconsole.log(\"shed item\"+item[1]+\" lookup tag:\"+schedule.items[itemLookup].tag);\n\t\t\t$('#shd-tag').val(schedule.items[itemLookup].tag);\n\t\t\t$('#shd-st').val(schedule.items[itemLookup].startTime);\n\t\t\t$('#shd-st-v').val(schedule.items[itemLookup].startValue);\n\t\t\t$('#shd-et').val(schedule.items[itemLookup].endTime);\n\t\t\t$('#shd-et-v').val(schedule.items[itemLookup].endValue);\n\t\t\t//console.log(\"group radio - id:\"+ this.id+\" val:\"+$(this).val());\n\t\t\tfor (dow = 0; dow< 7; dow++) {\n\t\t\t\tvar dowUI = '#shd-dow-'+dow;\n\t\t\t\tif (schedule.items[itemLookup].dofWeek[dow]==1){\n\t\t\t\t\t$(dowUI).prop( \"checked\", true ).checkboxradio( \"refresh\" )\n\t\t\t\t} else {\n\t\t\t\t\t$(dowUI).prop( \"checked\", false ).checkboxradio( \"refresh\" )\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\t// Schedule save\n\t\t$( \"#shd-save\" ).bind( \"click\", function(event, ui) {\n\t\t\tconsole.log(\"shd-save\");\n\t\t\tif( itemLookup != null){\n\t\t\t\tschedule.items[itemLookup].tag\t\t = $('#shd-tag').val();\n\t\t\t\tschedule.items[itemLookup].startTime = $('#shd-st').val();\n\t\t\t\tschedule.items[itemLookup].startValue = $('#shd-st-v').val();\n\t\t\t\tschedule.items[itemLookup].endTime\t = $('#shd-et').val();\n\t\t\t\tschedule.items[itemLookup].endValue\t = $('#shd-et-v').val();\n\t\t\t\tfor (dow = 0; dow< 7; dow++) {\n\t\t\t\t\tvar dowUI = '#shd-dow-'+dow;\n\t\t\t\t\tif( $(dowUI).prop( \"checked\")){\n\t\t\t\t\t\tschedule.items[itemLookup].dofWeek[dow] = 1 ;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tschedule.items[itemLookup].dofWeek[dow] = 0 ;\n\t\t\t\t\t}\n\t\t\t\t} \n\t\t\t\tlocalStorage[\"schedule\"] = schedule;\n\t\t\t\tvar obj = {\"id\":\"shd-save\",\"v\":schedule};\n\t\t\t\tgetRequest = JSON.stringify(obj); \t\n\t\t\t\tws.send(getRequest);\n\t\t\t}\n\t\t});\n\t\t// Utills\n\t\tvar showHide=0;\n\t\t$(window).keydown(function(event) {\n\t\t\tif(event.shiftKey && event.keyCode == 68 ) { \n\t\t\t\t//console.log(event.keyCode);\n\t\t\t\tif(showHide==0){$(\"#foo\").show('slow');showHide=1;}else{$(\"#foo\").hide();showHide=0;}\n\t\t\t\tevent.preventDefault(); \n\t\t\t}\n\t\t}); \n\t\t$( document ).on( \"vclick\", \"#b1\", function() {\n\t\t\tlocation.reload();\n\t\t\tconsole.log(\"reload button\");\n\t\t});\t\n\t});\n </script>\n <style>\n\t\t#c1, #c2 {background-color: #FFF !important;}\n \t\tdiv .ui-input-text {padding:0 .4em;} \n\t\t.valLable {float: left !important; min-width: 85px !important; margin-top:4px !important; padding: 0;}\n\t\t.valSmall {width:70px; height: 40px !important; float: left !important; margin-top:-12px !important;}\n\t\t.valMedium {width:156px; height: 40px !important; float: left !important; margin-top:-12px !important;}\n\t\t.valLarge {width:220px; height: 40px !important; float: left !important; margin-top:-12px !important;}\n\t\t.valHour {width:100px; height: 40px !important; float: left !important; margin-top:-12px !important;}\n\t\t.flipLable {float: left !important; min-width: 140px !important;}\n\t\t@media only screen and (min-width: 521px){\n\t\t\t#header1 {width: 507px !important; margin:auto auto !important; position: relative !important; border:1px solid #cccccc;}\n\t\t\t#c1 {width: 475px !important; min-height:500px !important; margin:auto auto !important; position: relative !important; border:1px solid #cccccc; border-top:0px;}\n\t\t\t#c2 {width: 475px !important; min-height:500px !important; margin:auto auto !important; position: relative !important; border:1px solid #cccccc; border-top:0px;}\n\t\t\t.t1 {width: 506px !important; margin:auto auto !important; position: relative !important; padding-right: 4px !important;}\n\t\t\t.flipLable {float: left !important; min-width: 320px !important;}\n\t\t\t.valMedium {width:330px; height: 40px !important; float: left !important; margin-top:-12px !important;}\n\t\t\t.sep {display: none !important;}\n\t\t}\t\n\t\t.alert {font-weight: bold; color: #FF6C01;}\n\t\t.smallin .ui-input-text {width: 200px !important; color:red;}\n\t\tlegend.h1lb {padding:0 0 0 0;}\n\t\t.statusView {width: 100% !important; margin:0px; position: relative !important; height:28px; padding:10px 0 0 0; background-color:#E9E9E9; font-weight:bold; -webkit-border-radius: 0.7em !important; border-radius: 0.7em; text-align:center; }\n\t\t.statusViewAlert {width: 100% !important; margin:0px; position: relative !important; height:28px; padding:10px 0 0 0; background-color:#F8B584 !important; font-weight:bold; -webkit-border-radius: 0.7em !important; border-radius: 0.7em; display:none; text-align:center; }\n\t\t.ui-flipswitch {\"border-radius: 2em !important; -webkit-border-radius: 2em !important; -moz-border-radius: 2em !important;}\n\t\t/* Active button */\n\t\t.ui-page-theme-a .ui-btn.ui-btn-active,html .ui-bar-a .ui-btn.ui-btn-active,html .ui-body-a .ui-btn.ui-btn-active,html body .ui-group-theme-a .ui-btn.ui-btn-active,html head + body .ui-btn.ui-btn-a.ui-btn-active,\n\t\t/* Active checkbox icon */\n\t\t.ui-page-theme-a .ui-checkbox-on:after,html .ui-bar-a .ui-checkbox-on:after,html .ui-body-a .ui-checkbox-on:after,html body .ui-group-theme-a .ui-checkbox-on:after,.ui-btn.ui-checkbox-on.ui-btn-a:after,\n\t\t/* Active flipswitch background */.ui-page-theme-a .ui-flipswitch-active,html .ui-bar-a .ui-flipswitch-active,html .ui-body-a .ui-flipswitch-active,html body .ui-group-theme-a .ui-flipswitch-active,\n\t\thtml body .ui-flipswitch.ui-bar-a.ui-flipswitch-active,\n\t\t/* Active slider track */\n\t\t.ui-page-theme-a .ui-slider-track .ui-btn-active,html .ui-bar-a .ui-slider-track .ui-btn-active,html .ui-body-a .ui-slider-track .ui-btn-active,html body .ui-group-theme-a .ui-slider-track .ui-btn-active,html body div.ui-slider-track.ui-body-a .ui-btn-active {\n\t\t\tbackground-color: \t\t#FF6C01 !important;\n\t\t\tborder-color:\t \t\t#FF6C01 !important;\n\t\t\tcolor: \t\t\t\t\t#fff /*{a-active-color}*/;\n\t\t\ttext-shadow: 0 /*{a-active-shadow-x}*/ 1px /*{a-active-shadow-y}*/ 0 /*{a-active-shadow-radius}*/ #005599 /*{a-active-shadow-color}*/;\n\t\t}\n </style>\n</head>\n<body>\n <!-- Home -->\n <div data-role=\"page\" id=\"noderedmobiui\">\n <div id=\"header1\" data-role=\"header\">\n <h3 style=\"color:#FF6C01\">Pi-Cubes Furnace Control</h3>\n\t\t<a href=\"#\" title=\"reload\" class=\"ui-btn ui-shadow ui-corner-all ui-icon-refresh ui-btn-icon-notext ui-btn-inline\" id=\"b1\" >Reload</a>\t\n\t</div>\n\t\t<div id=\"c1\" class=\"ui-content\">\n\t\t\t<div id=\"statusView\" class=\"statusView\" style=\"display:none;\"></div>\t\t\n\t\t\t<ul data-role=\"listview\" data-inset=\"true\">\n\t\t\t \n\t\t\t <li class=\"ui-field-contain\">\n\t\t\t\t\t<label for=\"val-roomtemp\" class=\"valLable\">Room Temp</label>\n\t\t\t\t\t<div class=\"valSmall\"><input type=\"text\" id=\"val-roomtemp\" style=\"width: 150px\" placeholder=\"\" value=\"\" readonly=\"readonly\"></div>\n\t\t\t\t</li>\n\t\t\t \n\t\t\t <li class=\"ui-field-contain\">\n\t\t\t\t\t<label for=\"val-cool\" class=\"valLable\">Cool</label>\n\t\t\t\t\t<div class=\"valSmall\"><input type=\"text\" id=\"val-cool\" style=\"width: 150px\" placeholder=\"\" value=\"\" readonly=\"readonly\"></div>\n\t\t\t\t</li>\n\n\t\t\t <li class=\"ui-field-contain\">\n\t\t\t\t\t<label for=\"val-heat\" class=\"valLable\">Heat</label>\n\t\t\t\t\t<div class=\"valSmall\"><input type=\"text\" id=\"val-heat\" style=\"width: 150px\" placeholder=\"\" value=\"\" readonly=\"readonly\"></div>\n\t\t\t\t</li>\n\n\t\t\t <li class=\"ui-field-contain\">\n\t\t\t\t\t<label for=\"val-fan\" class=\"valLable\">Fan</label>\n\t\t\t\t\t<div class=\"valSmall\"><input type=\"text\" id=\"val-fan\" style=\"width: 150px\" placeholder=\"\" value=\"\" readonly=\"readonly\"></div>\n\t\t\t\t</li>\n\t\t\t\t\n\t\t\t <li class=\"ui-field-contain\">\n\t\t\t\t\t<label for=\"val-mode\" class=\"valLable\">Mode</label>\n\t\t\t\t\t<div class=\"valSmall\"><input type=\"text\" id=\"val-mode\" style=\"width: 150px\" placeholder=\"\" value=\"\" readonly=\"readonly\"></div>\n\t\t\t\t</li>\n\t\t\t\t\n\t\t\t\t<li class=\"ui-field-contain\">\n\t\t\t\t\t<label for=\"sld-setpoint\">Set Point</label>\n\t\t\t\t\t<input id=\"sld-setpoint\" type=\"range\" data-role=\"range\" value=\"0\" min=\"18\" max=\"28\" step=\"0.5\" data-highlight=\"true\" />\n\t\t\t\t</li>\n\n\t\t\t </ul>\n\t\t\t<div id=\"container\" style=\"width: 100%; margin-left:-5px;\"></div>\t\t\n\t\t</div>\n\t</div><!-- eof page -->\n </body>\n</html>","x":639,"y":157,"z":"4218cc1f.bde734","wires":[["7335140d.8ccaec"]]},{"id":"6fd25395.902dac","type":"inject","name":"Inject Data","topic":"","payload":"","payloadType":"date","repeat":"5","crontab":"","once":true,"x":435,"y":457,"z":"4218cc1f.bde734","wires":[["87506dfa.78af9","90aad043.6f553","c42f9e1b.3bd06","16943469.e96bcc","a33297a.f5ccd68","39ced810.c63128","632b24de.9cd4dc"]]},{"id":"87506dfa.78af9","type":"function","name":"Set Room Temp","func":"msg.payload = {id:\"val-roomtemp\", v: parseFloat(context.global.roomtemp).toFixed(1)+\" C\"+String.fromCharCode(176)};\nreturn msg;","outputs":1,"noerr":0,"x":667,"y":506,"z":"4218cc1f.bde734","wires":[["153eaa3.feac156"]]},{"id":"90aad043.6f553","type":"function","name":"Set Cool","func":"msg.payload = {id:\"val-cool\", v: context.global.cool};\nreturn msg;","outputs":1,"noerr":0,"x":640,"y":460,"z":"4218cc1f.bde734","wires":[["153eaa3.feac156"]]},{"id":"c42f9e1b.3bd06","type":"function","name":"Set Heat","func":"msg.payload = {id:\"val-heat\", v: context.global.heat};\nreturn msg;","outputs":1,"noerr":0,"x":639,"y":418,"z":"4218cc1f.bde734","wires":[["153eaa3.feac156"]]},{"id":"16943469.e96bcc","type":"function","name":"Set Fan","func":"msg.payload = {id:\"val-fan\", v: context.global.fan};\nreturn msg;","outputs":1,"noerr":0,"x":639,"y":374,"z":"4218cc1f.bde734","wires":[["153eaa3.feac156"]]},{"id":"39ced810.c63128","type":"function","name":"Set Mode","func":"msg.payload = {id:\"val-mode\", v: context.global.mode};\nreturn msg;","outputs":1,"noerr":0,"x":648,"y":549,"z":"4218cc1f.bde734","wires":[["153eaa3.feac156"]]},{"id":"632b24de.9cd4dc","type":"function","name":"Set Room Setpoint","func":"msg.payload = {id:\"sld-setpoint\", v: parseFloat(context.global.setpoint).toFixed(1)};\nreturn msg;","outputs":1,"noerr":0,"x":680,"y":638,"z":"4218cc1f.bde734","wires":[["153eaa3.feac156"]]}]
Ubidots Workspace
This is a program that provides connection to the Ubidots dashboard.
[{"id":"c91152bb.36eeb","type":"function","name":"GetRoomTemp","func":"var obj = JSON.parse(context.global.roomtemp);\nmsg.payload = obj;\nreturn msg;","outputs":1,"noerr":0,"x":380,"y":160,"z":"6497d892.9b6828","wires":[["9ff39c9c.600c6"]]},{"id":"26fa98de.d90568","type":"inject","name":"","topic":"","payload":"","payloadType":"date","repeat":"10","crontab":"","once":false,"x":161,"y":162,"z":"6497d892.9b6828","wires":[["c91152bb.36eeb"]]},{"id":"9ff39c9c.600c6","type":"ubidots","name":"Room Temperature","auth_token":"","variable_id":"","x":647,"y":162,"z":"6497d892.9b6828","wires":[]}]
Schedule Workspace
This is a program that provides simple schedule.
[{"id":"4e9968c6.b16698","type":"function","name":"Schedule","func":"var now = new Date();\ncontext.flag = context.flag || 0;\n\nvar hour = now.getHours();\nvar minute = now.getMinutes();\n\nif ((hour === 23) && (minute === 0) && (context.flag === 0))\n{\n context.global.setpoint = 21;\n context.global.setpointchanged = 1;\n context.flag = 1;\n} else\nif ((hour === 6) && (minute === 0) && (context.flag === 0))\n{\n context.global.setpoint = 24;\n context.global.setpointchanged = 1;\n context.flag = 1;\n} else\n{\n context.flag = 0; \n}\n\nreturn msg;","outputs":1,"noerr":0,"x":376,"y":172,"z":"84261036.7bd9f","wires":[[]]},{"id":"78564ece.87a9b","type":"inject","name":"","topic":"","payload":"","payloadType":"date","repeat":"15","crontab":"","once":false,"x":169,"y":169,"z":"84261036.7bd9f","wires":[["4e9968c6.b16698"]]}]
Comments