-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathVPControl-node-red-flow-advanced.json
More file actions
1 lines (1 loc) · 16.4 KB
/
Copy pathVPControl-node-red-flow-advanced.json
File metadata and controls
1 lines (1 loc) · 16.4 KB
1
[{"id":"4b7b595c.a15c08","type":"tab","label":"VP Control","disabled":false,"info":""},{"id":"ba57f093.a1b27","type":"debug","z":"4b7b595c.a15c08","name":"RAW XML","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":870,"y":100,"wires":[]},{"id":"32d37c60.d9ddb4","type":"inject","z":"4b7b595c.a15c08","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"0 0-22 * * *","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":170,"y":200,"wires":[["15950a06.34b7f6"]]},{"id":"797d2c4.efe84d4","type":"http request","z":"4b7b595c.a15c08","name":"","method":"GET","ret":"txt","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":490,"y":200,"wires":[["ba57f093.a1b27","8dc62d3d.c98e1"]]},{"id":"8dc62d3d.c98e1","type":"xml","z":"4b7b595c.a15c08","name":"","property":"payload","attr":"","chr":"","x":700,"y":300,"wires":[["b735446f.712bf8","f5be349f.43e048"]]},{"id":"b735446f.712bf8","type":"debug","z":"4b7b595c.a15c08","name":"JSON","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":880,"y":160,"wires":[]},{"id":"f5be349f.43e048","type":"function","z":"4b7b595c.a15c08","name":"Get Price value","func":"const sekEur = 10.8; // parseFloat(env.get('SEK_EUR')).toFixed(2) || 10.3;\nconst tz = 2; // parseFloat(env.get('TIME_ZONE_ADJUSTMENT')).toFixed(0)\n\nconst prices = msg.payload.Publication_MarketDocument.TimeSeries[0].Period[0].Point;\nconst currentHour = (new Date().getUTCHours() + tz);\n// Get the price in SEK re / kWh\nconst price = Math.round(parseFloat(prices[currentHour]['price.amount'][0]).toFixed(2) * sekEur / 10);\nflow.set('CURRENT_PRICE', price);\n\nconst sumDayAverage = prices.reduce((sum, price) => sum + Math.round(parseFloat(price['price.amount'][0]).toFixed(2)), 0);\nconst average = Math.round(parseFloat(sumDayAverage / 24).toFixed(2));\nflow.set('DAY_AVERAGE_PRICE', average);\n\nreturn {\n payload: {\n prices,\n average,\n currentHour,\n exchangeRateSEK_EUR: sekEur,\n price\n }\n};","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":920,"y":380,"wires":[["819e4c6.0436fb","a0d58a1f.29a638","90b8c16e.aa54f","e21aa25e.6ba75","31e969e5.76f146"]]},{"id":"819e4c6.0436fb","type":"debug","z":"4b7b595c.a15c08","name":"Price for coming hour","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1120,"y":280,"wires":[]},{"id":"df1056f2.de5588","type":"debug","z":"4b7b595c.a15c08","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"url","targetType":"msg","statusVal":"","statusType":"auto","x":440,"y":420,"wires":[]},{"id":"15950a06.34b7f6","type":"function","z":"4b7b595c.a15c08","name":"Format URL","func":"const params = {\n securityToken: env.get('ENTSOE_SECURITY_TOKEN'),\n priceRegion: env.get('ENTSOE_PRICE_REGION') || '10Y1001A1001A46L' // =Sweden SE3\n};\n\nlet date = new Date(msg.payload);\n// We want date/time as e.g. 20220802, we'll add hours in the URL\ndate = (date.getFullYear() + '' + \n ('00' + (date.getMonth()+1)).slice(-2) + '' + \n ('00' + date.getDate()).slice(-2));\n // ('00' + date.getHours()).slice(-2) \n // ('00' + date.getMinutes()).slice(-2)\n // ('00' + date.getSeconds()).slice(-2)\nconst url = `https://web-api.tp.entsoe.eu/api?securityToken=${params.securityToken}&documentType=A44&in_Domain=${params.priceRegion}&out_Domain=${params.priceRegion}&periodStart=${date}0000&periodEnd=${date}0100`;\n\nreturn { url };","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":220,"y":380,"wires":[["df1056f2.de5588","797d2c4.efe84d4"]]},{"id":"71f2041c.45d98c","type":"rpi-gpio out","z":"4b7b595c.a15c08","name":"Relay control","pin":"17","set":true,"level":"0","freq":"","out":"out","bcm":true,"x":1250,"y":560,"wires":[]},{"id":"a0d58a1f.29a638","type":"function","z":"4b7b595c.a15c08","name":"On/Block","func":"const cutOffValue = flow.get('CUT_OFF_LIMIT');\nconst currentPrice = parseFloat(flow.get('CURRENT_PRICE')).toFixed(0);\n\nconst mainSwitch = flow.get('MAIN_SWITCH');\n\nconst useDayAverage = flow.get('USE_DAY_AVERAGE');\nconst dayAverage = flow.get('DAY_AVERAGE_PRICE');\nconst maxAverage = flow.get('MAX_AVERAGE') || 0;\n\n\n// If we are to use Day Average then we need to swap the cut off price\nconst cutOff = useDayAverage ? parseFloat(dayAverage).toFixed(0) : parseFloat(cutOffValue).toFixed(0);\n// Check if cutOff is lower than the current price\nconst condition = (Number(cutOff) - Number(currentPrice)) <= 0;\nconst overMaxAverage = !useDayAverage || isNaN(maxAverage) ? false : (Number(currentPrice) - Number(maxAverage)) > 0;\n\n// ++ Below object is just for debugging\nconst s = {\n cutOffValue,\n cutOff,\n currentPrice,\n mainSwitch,\n useDayAverage,\n dayAverage,\n maxAverage,\n condition\n};\nmsg.debug = s;\n// --\n\n// Default to let it run, relay is open\n// The relay is open in power off (NO) and sending zero closes it\n// so it works \"backwards\", hence 1 = heating is on, 0 = blocked\nmsg.payload = 1;\nif (mainSwitch && (condition || overMaxAverage)) {\n // Pull the relay, we want to block, if the main switch is on\n msg.payload = 0;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1040,"y":480,"wires":[["d58686f7.41f258","71f2041c.45d98c","2f68c2c4.9bcfee","65e8af46.5a818"]]},{"id":"d58686f7.41f258","type":"debug","z":"4b7b595c.a15c08","name":"on/Block","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1240,"y":440,"wires":[]},{"id":"893f01d9.2a0fd","type":"rpi-gpio out","z":"4b7b595c.a15c08","name":"Main control","pin":"27","set":true,"level":"0","freq":"","out":"out","bcm":true,"x":570,"y":740,"wires":[]},{"id":"bc070dca.6a12","type":"function","z":"4b7b595c.a15c08","name":"Set params","func":"flow.set('CUT_OFF_LIMIT', parseFloat(msg.payload).toFixed(0));\nglobal.set('VPC_CUT_OFF_LIMIT', flow.get('CUT_OFF_LIMIT'));\nmsg.payload = flow.get('CUT_OFF_LIMIT');\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":530,"y":880,"wires":[["7d5b666.d1c2098","a0d58a1f.29a638"]]},{"id":"7d5b666.d1c2098","type":"debug","z":"4b7b595c.a15c08","name":"Set Cut-Off","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":880,"wires":[]},{"id":"e2708226.24c2a","type":"status","z":"4b7b595c.a15c08","name":"Status VP Control enabled","scope":["34d72492.037e7c"],"x":230,"y":780,"wires":[["894299b2.b50fe8"]]},{"id":"d1e6420c.3fa1d","type":"debug","z":"4b7b595c.a15c08","name":"Status VP Control On/Off","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":830,"y":800,"wires":[]},{"id":"894299b2.b50fe8","type":"function","z":"4b7b595c.a15c08","name":"Set flow status","func":"flow.set('MAIN_SWITCH', msg.status.text === 'on');\nglobal.set('VPC_MAIN_SWITCH', msg.status.text === 'on' ? 1 : 0);\nmsg.payload = `MAIN_SWITCH: ${msg.status.text === 'on'}`;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":540,"y":800,"wires":[["d1e6420c.3fa1d","a0d58a1f.29a638"]]},{"id":"5dd2c1f1.85aa9","type":"function","z":"4b7b595c.a15c08","name":"Set dayAverage switch","func":"flow.set('USE_DAY_AVERAGE', msg.status.text === 'on');\nglobal.set('VPC_USE_DAY_AVERAGE', msg.status.text === 'on' ? 1 : 0);\n// Disable and set the current cut-off value\nmsg.payload = flow.get('CUT_OFF_LIMIT');\nmsg.enabled = msg.status.text === 'off';\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":560,"y":940,"wires":[["6834b7a5.b75bc8"]]},{"id":"71bf5779.315c68","type":"status","z":"4b7b595c.a15c08","name":"","scope":["db2345a1.58c388"],"x":240,"y":1020,"wires":[["5dd2c1f1.85aa9"]]},{"id":"c18d8b6c.9315e8","type":"debug","z":"4b7b595c.a15c08","name":"Temperatures","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":440,"y":520,"wires":[]},{"id":"562ef29b.42165c","type":"function","z":"4b7b595c.a15c08","name":"Set max average","func":"flow.set('MAX_AVERAGE', parseFloat(msg.payload).toFixed(0));\nglobal.set('VPC_MAX_AVERAGE', flow.get('MAX_AVERAGE'));\nmsg.payload = flow.get('MAX_AVERAGE');\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":570,"y":1120,"wires":[[]]},{"id":"31e969e5.76f146","type":"function","z":"4b7b595c.a15c08","name":"Price chart of the day","func":"const sekEur = 10.3; // parseFloat(env.get('SEK_EUR')).toFixed(2) || 10.3;\n\nconst prices = msg.payload.prices.map((price) => \n Math.round(parseFloat(price['price.amount'][0]).toFixed(2) * sekEur / 10));\n\nmsg.payload=[{\n \"series\": [\"öre/kWh\" ],\n \"data\": [ prices ],\n \"labels\": [\n '01', '02', '03', '04', '05', '06', '07', '08',\n '09', '10', '11', '12', '13', '14', '15', '16',\n '17', '18', '19', '20', '21', '22', '23'\n ]\n}];\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1080,"y":200,"wires":[["117d2eca.e12001"]]},{"id":"72593d66.bae5c4","type":"sensor-ds18b20","z":"4b7b595c.a15c08","name":"Warm water temp","topic":"","sensorid":"28-031702ef57ff","timer":"20","repeat":true,"x":170,"y":500,"wires":[["c18d8b6c.9315e8","3d629639.57c8ba","85f6be8d.7475b"]]},{"id":"34d72492.037e7c","type":"ui_switch","z":"4b7b595c.a15c08","name":"","label":"VP Control enabled","tooltip":"","group":"7f260cb3.6d6324","order":1,"width":0,"height":0,"passthru":true,"decouple":"false","topic":"","topicType":"str","style":"","onvalue":"1","onvalueType":"num","onicon":"","oncolor":"","offvalue":"0","offvalueType":"num","officon":"","offcolor":"","animate":true,"className":"","x":170,"y":740,"wires":[["893f01d9.2a0fd"]]},{"id":"db2345a1.58c388","type":"ui_switch","z":"4b7b595c.a15c08","name":"","label":"Use below day average","tooltip":"If you select this option the heat-pump will only be blocked when the price is above the days average price","group":"7f260cb3.6d6324","order":4,"width":0,"height":0,"passthru":true,"decouple":"false","topic":"","topicType":"str","style":"","onvalue":"1","onvalueType":"num","onicon":"","oncolor":"","offvalue":"0","offvalueType":"num","officon":"","offcolor":"","animate":true,"className":"","x":190,"y":980,"wires":[[]]},{"id":"6834b7a5.b75bc8","type":"ui_text_input","z":"4b7b595c.a15c08","name":"Cut-off price","label":"Cut-off price (öre/kWh) ","tooltip":"","group":"7f260cb3.6d6324","order":2,"width":0,"height":0,"passthru":true,"mode":"number","delay":300,"topic":"","sendOnBlur":true,"className":"","topicType":"str","x":130,"y":900,"wires":[["bc070dca.6a12"]]},{"id":"fd708d2b.8597c","type":"ui_text_input","z":"4b7b595c.a15c08","name":"Max average","label":"Max. for average control","tooltip":"If you use average price, this is the absolute maximum you allow. Setting it to zero or empty value there is no upper limit for day average.","group":"7f260cb3.6d6324","order":5,"width":0,"height":0,"passthru":true,"mode":"number","delay":300,"topic":"","sendOnBlur":true,"className":"","topicType":"str","x":150,"y":1160,"wires":[["562ef29b.42165c"]]},{"id":"90b8c16e.aa54f","type":"ui_text","z":"4b7b595c.a15c08","group":"d3aa98d4.f35778","order":2,"width":0,"height":0,"name":"Current Price","label":"Current price (öre/kWh)","format":"{{msg.payload.price}}","layout":"row-spread","className":"","x":1250,"y":380,"wires":[]},{"id":"e21aa25e.6ba75","type":"ui_text","z":"4b7b595c.a15c08","group":"7f260cb3.6d6324","order":5,"width":0,"height":0,"name":"Day Average price","label":"Day average price (öre/kWh)","format":"{{msg.payload.average}}","layout":"row-spread","className":"","x":1270,"y":340,"wires":[]},{"id":"3d629639.57c8ba","type":"ui_text","z":"4b7b595c.a15c08","group":"7205371f.19e458","order":2,"width":0,"height":0,"name":"Warm water temp","label":"Warm water temp.","format":"{{msg.payload}}","layout":"row-spread","className":"","x":450,"y":560,"wires":[]},{"id":"65e8af46.5a818","type":"ui_chart","z":"4b7b595c.a15c08","name":"Heat-pump enabled","group":"d3aa98d4.f35778","order":2,"width":0,"height":0,"label":"Heat-pump enabled","chartType":"line","legend":"false","xformat":"dd HH:mm","interpolate":"step","nodata":"","dot":false,"ymin":"0","ymax":"1","removeOlder":"48","removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#df2666","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":1230,"y":680,"wires":[[]]},{"id":"85f6be8d.7475b","type":"ui_chart","z":"4b7b595c.a15c08","name":"","group":"7205371f.19e458","order":3,"width":0,"height":0,"label":"Water temp","chartType":"line","legend":"false","xformat":"dd HH:mm","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"100","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"604800","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#5d78e5","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":630,"y":560,"wires":[[]]},{"id":"117d2eca.e12001","type":"ui_chart","z":"4b7b595c.a15c08","name":"Price over day","group":"7f260cb3.6d6324","order":7,"width":0,"height":0,"label":"Daily prices","chartType":"line","legend":"false","xformat":"HH","interpolate":"bezier","nodata":"","dot":true,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"86400","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#68d61f","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":1380,"y":200,"wires":[[]]},{"id":"2f68c2c4.9bcfee","type":"ui_led","z":"4b7b595c.a15c08","order":1,"group":"d3aa98d4.f35778","width":0,"height":0,"label":"Heating status","labelPlacement":"left","labelAlignment":"left","colorForValue":[{"color":"#00ff2a","value":"1","valueType":"num"},{"color":"#ff571f","value":"0","valueType":"num"}],"allowColorForValueInMessage":false,"shape":"circle","showGlow":true,"name":"Heating status","x":1240,"y":620,"wires":[]},{"id":"2dd0e2655eb8abb4","type":"inject","z":"4b7b595c.a15c08","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"VPC_MAIN_SWITCH","payloadType":"global","x":180,"y":660,"wires":[["34d72492.037e7c"]]},{"id":"f6380ddbd130c3b2","type":"inject","z":"4b7b595c.a15c08","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"VPC_CUT_OFF_LIMIT","payloadType":"global","x":170,"y":820,"wires":[["c7c314be7b93ada3"]]},{"id":"e09d91eb222fa1dc","type":"inject","z":"4b7b595c.a15c08","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"VPC_USE_DAY_AVERAGE","payloadType":"global","x":160,"y":940,"wires":[["db2345a1.58c388"]]},{"id":"b921ab2350aac68d","type":"inject","z":"4b7b595c.a15c08","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"VPC_MAX_AVERAGE","payloadType":"global","x":150,"y":1080,"wires":[["cf86412e39a81f18"]]},{"id":"c7c314be7b93ada3","type":"function","z":"4b7b595c.a15c08","name":"toNumber","func":"msg.payload = Number(msg.payload);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":120,"y":860,"wires":[["6834b7a5.b75bc8"]]},{"id":"cf86412e39a81f18","type":"function","z":"4b7b595c.a15c08","name":"toNumber","func":"msg.payload = Number(msg.payload);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":100,"y":1120,"wires":[["fd708d2b.8597c"]]},{"id":"7f260cb3.6d6324","type":"ui_group","name":"Control","tab":"7586f32f.8b050c","order":1,"disp":true,"width":"6","collapse":false,"className":""},{"id":"d3aa98d4.f35778","type":"ui_group","name":"Status","tab":"7586f32f.8b050c","order":2,"disp":true,"width":"6","collapse":false},{"id":"7205371f.19e458","type":"ui_group","name":"Temperatures","tab":"7586f32f.8b050c","order":3,"disp":true,"width":"6","collapse":false,"className":""},{"id":"7586f32f.8b050c","type":"ui_tab","name":"VP Control","icon":"dashboard","disabled":false,"hidden":false}]