Skip to content

Instantly share code, notes, and snippets.

@billerby
Last active December 28, 2022 10:29
Show Gist options
  • Save billerby/303658fd5009da5820a6e5212988362e to your computer and use it in GitHub Desktop.
Save billerby/303658fd5009da5820a6e5212988362e to your computer and use it in GitHub Desktop.
TOU flow NodeRed
[{"id":"1eb5a1b2baed1909","type":"subflow","name":"Prepare TOU Pattern","info":"","category":"","in":[{"x":20,"y":80,"wires":[{"id":"d4f5d2197bc0cdb1"}]}],"out":[{"x":380,"y":80,"wires":[{"id":"d4f5d2197bc0cdb1","port":0}]}],"env":[],"meta":{},"color":"#DDAA99"},{"id":"d4f5d2197bc0cdb1","type":"function","z":"1eb5a1b2baed1909","name":"Prepare hh:mm-hh:mm","func":"function createTimeRangeString(item) {\n // Parse the time string into a Date object\n const startTime = new Date(item.time);\n\n \n // Get the hours\n const startHours = startTime.getHours().toString().padStart(2, '0');\n \n\n \n // Return the time range string\n let startHoursMinutes = `${startHours}:00`;\n\n const nextdate = new Date();\n const [hours2, minutes2] = startHoursMinutes.split(\":\").map(x => parseInt(x, 10));\n nextdate.setHours(hours2);\n nextdate.setMinutes(minutes2);\n nextdate.setHours(hours2 + item.countHours);\n const endChargeHoursMinutes = nextdate.toTimeString().slice(0, 5);\n\n return `${startHoursMinutes}-${endChargeHoursMinutes}`;\n}\n\nlet timeRanges = msg.payload.schedule.map(function (item) {\n // Call your function here and pass in the item as an argument\n return createTimeRangeString(item);\n});\n\nconst periods = [];\n\nfor (const timeRange of timeRanges) {\n periods.push(`${timeRange}`);\n}\n\nmsg.payload = {\n \"periods\": periods\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":210,"y":80,"wires":[[]]},{"id":"4fdf10518254202b","type":"subflow","name":"Filter schedules","info":"","category":"","in":[{"x":0,"y":80,"wires":[{"id":"5a191564e3b521d4"}]}],"out":[{"x":380,"y":80,"wires":[{"id":"5a191564e3b521d4","port":0}]}],"env":[],"meta":{},"color":"#DDAA99"},{"id":"5a191564e3b521d4","type":"function","z":"4fdf10518254202b","name":"Remove unwanted nodes","func":"function filterSchedule(schedule) {\n // Get the current time\n const currentTime = new Date();\n\n // Filter the schedule array\n const filteredSchedule = schedule.filter(item => {\n // Parse the time string into a Date object\n const time = new Date(item.time);\n\n // Return true if the time has not passed and the value is true\n return time > currentTime && item.value && item.countHours != null;\n });\n\n return filteredSchedule;\n}\n\nmsg.payload.schedule = filterSchedule(msg.payload.schedule);\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":190,"y":80,"wires":[[]]},{"id":"cef971cc346c85a6","type":"tab","label":"Calculate TOU","disabled":false,"info":"","env":[]},{"id":"48bcdcca.fe42a4","type":"api-current-state","z":"cef971cc346c85a6","name":"Read Nord Pool","server":"d47a09d6.cf4748","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.nordpool_kwh_se3_sek_3_10_025","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entity"}],"for":0,"forType":"num","forUnits":"minutes","x":120,"y":180,"wires":[["428d7c7ca88db95f"]]},{"id":"428d7c7ca88db95f","type":"ps-receive-price","z":"cef971cc346c85a6","name":"Price Receiver","x":160,"y":340,"wires":[["bda78da2e8c95450","9157e6b16f9fabb7"]]},{"id":"bda78da2e8c95450","type":"ps-strategy-lowest-price","z":"cef971cc346c85a6","name":"Lowest Price","fromTime":"00","toTime":"07","hoursOn":"5","maxPrice":"","doNotSplit":true,"sendCurrentValueWhenRescheduling":true,"outputValueForOn":"true","outputValueForOff":"false","outputValueForOntype":"bool","outputValueForOfftype":"bool","outputIfNoSchedule":"true","outputOutsidePeriod":"false","contextStorage":"memory","x":390,"y":180,"wires":[[],[],["6647300243bff296"]]},{"id":"2dc3e87f425d30a8","type":"cronplus","z":"cef971cc346c85a6","name":"Trigger at 14.00 Every day","outputField":"payload","timeZone":"","persistDynamic":false,"commandResponseMsgOutput":"output1","outputs":1,"options":[{"name":"schedule1","topic":"topic1","payloadType":"default","payload":"","expressionType":"cron","expression":"0 0 14 * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":160,"y":60,"wires":[["48bcdcca.fe42a4"]]},{"id":"af43e4b735355b40","type":"api-call-service","z":"cef971cc346c85a6","name":"Set TOU Periods","server":"24cba002.90109","version":5,"debugenabled":true,"domain":"huawei_solar","service":"set_tou_periods","areaId":[],"deviceId":[],"entityId":[],"data":"{ \"device_id\": \"9b80e4bb5e879c09ed84abe968ce937b\", \"periods\": payload.periods }","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1030,"y":720,"wires":[[]]},{"id":"9157e6b16f9fabb7","type":"function","z":"cef971cc346c85a6","name":"Negate prices","func":"function negateValues(data) {\n return data.map(x => ({ ...x, value: -x.value }));\n}\n\nlet negatedData = negateValues(msg.payload.priceData);\n\nmsg.payload.priceData = negatedData;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":380,"y":400,"wires":[["2b281b42d65caecc"]]},{"id":"404caaad53947da0","type":"inject","z":"cef971cc346c85a6","name":"Trigger","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":130,"y":500,"wires":[["ca99353faa7c0de3"]]},{"id":"ca99353faa7c0de3","type":"function","z":"cef971cc346c85a6","name":"Mocked data","func":"let payload = {\n \"priceData\": [\n {\n \"value\": 0.279,\n \"start\": \"2022-12-28T00:00:00+01:00\"\n },\n {\n \"value\": 0.139,\n \"start\": \"2022-12-28T01:00:00+01:00\"\n },\n {\n \"value\": 0.08,\n \"start\": \"2022-12-28T02:00:00+01:00\"\n },\n {\n \"value\": 0.07,\n \"start\": \"2022-12-28T03:00:00+01:00\"\n },\n {\n \"value\": 0.16,\n \"start\": \"2022-12-28T04:00:00+01:00\"\n },\n {\n \"value\": 0.274,\n \"start\": \"2022-12-28T05:00:00+01:00\"\n },\n {\n \"value\": 0.425,\n \"start\": \"2022-12-28T06:00:00+01:00\"\n },\n {\n \"value\": 0.979,\n \"start\": \"2022-12-28T07:00:00+01:00\"\n },\n {\n \"value\": 1.137,\n \"start\": \"2022-12-28T08:00:00+01:00\"\n },\n {\n \"value\": 1.33,\n \"start\": \"2022-12-28T09:00:00+01:00\"\n },\n {\n \"value\": 1.309,\n \"start\": \"2022-12-28T10:00:00+01:00\"\n },\n {\n \"value\": 1.479,\n \"start\": \"2022-12-28T11:00:00+01:00\"\n },\n {\n \"value\": 1.506,\n \"start\": \"2022-12-28T12:00:00+01:00\"\n },\n {\n \"value\": 1.515,\n \"start\": \"2022-12-28T13:00:00+01:00\"\n },\n {\n \"value\": 1.523,\n \"start\": \"2022-12-28T14:00:00+01:00\"\n },\n {\n \"value\": 1.772,\n \"start\": \"2022-12-28T15:00:00+01:00\"\n },\n {\n \"value\": 2.013,\n \"start\": \"2022-12-28T16:00:00+01:00\"\n },\n {\n \"value\": 2.165,\n \"start\": \"2022-12-28T17:00:00+01:00\"\n },\n {\n \"value\": 2.246,\n \"start\": \"2022-12-28T18:00:00+01:00\"\n },\n {\n \"value\": 1.688,\n \"start\": \"2022-12-28T19:00:00+01:00\"\n },\n {\n \"value\": 1.325,\n \"start\": \"2022-12-28T20:00:00+01:00\"\n },\n {\n \"value\": 0.958,\n \"start\": \"2022-12-28T21:00:00+01:00\"\n },\n {\n \"value\": 0.931,\n \"start\": \"2022-12-28T22:00:00+01:00\"\n },\n {\n \"value\": 0.885,\n \"start\": \"2022-12-28T23:00:00+01:00\"\n },\n {\n \"value\": 0.698,\n \"start\": \"2022-12-29T00:00:00+01:00\"\n },\n {\n \"value\": 0.462,\n \"start\": \"2022-12-29T01:00:00+01:00\"\n },\n {\n \"value\": 0.48,\n \"start\": \"2022-12-29T02:00:00+01:00\"\n },\n {\n \"value\": 0.472,\n \"start\": \"2022-12-29T03:00:00+01:00\"\n },\n {\n \"value\": 0.621,\n \"start\": \"2022-12-29T04:00:00+01:00\"\n },\n {\n \"value\": 0.73,\n \"start\": \"2022-12-29T05:00:00+01:00\"\n },\n {\n \"value\": 0.868,\n \"start\": \"2022-12-29T06:00:00+01:00\"\n },\n {\n \"value\": 0.908,\n \"start\": \"2022-12-29T07:00:00+01:00\"\n },\n {\n \"value\": 0.974,\n \"start\": \"2022-12-29T08:00:00+01:00\"\n },\n {\n \"value\": 0.971,\n \"start\": \"2022-12-29T09:00:00+01:00\"\n },\n {\n \"value\": 0.977,\n \"start\": \"2022-12-29T10:00:00+01:00\"\n },\n {\n \"value\": 0.98,\n \"start\": \"2022-12-29T11:00:00+01:00\"\n },\n {\n \"value\": 0.009,\n \"start\": \"2022-12-29T12:00:00+01:00\"\n },\n {\n \"value\": 1.06,\n \"start\": \"2022-12-29T13:00:00+01:00\"\n },\n {\n \"value\": 1.095,\n \"start\": \"2022-12-29T14:00:00+01:00\"\n },\n {\n \"value\": 1.382,\n \"start\": \"2022-12-29T15:00:00+01:00\"\n },\n {\n \"value\": 1.594,\n \"start\": \"2022-12-29T16:00:00+01:00\"\n },\n {\n \"value\": 1.692,\n \"start\": \"2022-12-29T17:00:00+01:00\"\n },\n {\n \"value\": 1.673,\n \"start\": \"2022-12-29T18:00:00+01:00\"\n },\n {\n \"value\": 1.327,\n \"start\": \"2022-12-29T19:00:00+01:00\"\n },\n {\n \"value\": 1.138,\n \"start\": \"2022-12-29T20:00:00+01:00\"\n },\n {\n \"value\": 0.963,\n \"start\": \"2022-12-29T21:00:00+01:00\"\n },\n {\n \"value\": 0.843,\n \"start\": \"2022-12-29T22:00:00+01:00\"\n },\n {\n \"value\": 0.612,\n \"start\": \"2022-12-29T23:00:00+01:00\"\n }\n ],\n \"source\": \"Nordpool\"\n}\nmsg.payload = payload;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":290,"y":500,"wires":[["9157e6b16f9fabb7","bda78da2e8c95450"]]},{"id":"2b281b42d65caecc","type":"ps-strategy-lowest-price","z":"cef971cc346c85a6","name":"Find highest prices","fromTime":"06","toTime":"22","hoursOn":"14","maxPrice":"","doNotSplit":false,"sendCurrentValueWhenRescheduling":true,"outputValueForOn":"true","outputValueForOff":"false","outputValueForOntype":"bool","outputValueForOfftype":"bool","outputIfNoSchedule":"false","outputOutsidePeriod":"false","contextStorage":"memory","x":430,"y":300,"wires":[[],[],["65aaca6c2d1dbb6a"]]},{"id":"e9dbdf8889b28738","type":"join","z":"cef971cc346c85a6","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":1050,"y":340,"wires":[["13812d63668cd805"]]},{"id":"6647300243bff296","type":"subflow:4fdf10518254202b","z":"cef971cc346c85a6","name":"","x":540,"y":80,"wires":[["f076ea1ff13f7908"]]},{"id":"65aaca6c2d1dbb6a","type":"subflow:4fdf10518254202b","z":"cef971cc346c85a6","name":"","x":660,"y":280,"wires":[["a39658735562ae24"]]},{"id":"a39658735562ae24","type":"subflow:1eb5a1b2baed1909","z":"cef971cc346c85a6","name":"","x":740,"y":380,"wires":[["e5281e3a5e08170b"]]},{"id":"f076ea1ff13f7908","type":"subflow:1eb5a1b2baed1909","z":"cef971cc346c85a6","name":"","x":660,"y":220,"wires":[["e39003f00fedd8a4"]]},{"id":"e39003f00fedd8a4","type":"function","z":"cef971cc346c85a6","name":"append charge info","func":"const modifiedArray = msg.payload.periods.map(str => {\n return str + \"/1234567/+\";\n})\n\nmsg.payload = modifiedArray;\nreturn msg; \n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":890,"y":240,"wires":[["e9dbdf8889b28738"]]},{"id":"e5281e3a5e08170b","type":"function","z":"cef971cc346c85a6","name":"append discharge info","func":"const modifiedArray = msg.payload.periods.map(str => {\n return str + \"/1234567/-\";\n})\n\nmsg.payload = modifiedArray;\nreturn msg; \n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":760,"y":500,"wires":[["e9dbdf8889b28738"]]},{"id":"496fb3665e8e4952","type":"debug","z":"cef971cc346c85a6","name":"debug 10","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1060,"y":520,"wires":[]},{"id":"13812d63668cd805","type":"function","z":"cef971cc346c85a6","name":"merge arrays","func":"const mergedArray = msg.payload.flat();\n\nconst concatenatedString = mergedArray.join('\\n');\nmsg.payload = concatenatedString;\nreturn msg; \n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":910,"y":600,"wires":[["496fb3665e8e4952","af43e4b735355b40"]]},{"id":"d47a09d6.cf4748","type":"server","name":"Home Assistant","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30,"areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true},{"id":"24cba002.90109","type":"server","name":"Home Assistant","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30,"areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true}]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment