[ { "id": "5042e496e3bb2cb7", "type": "tab", "label": "ESS Forecast Charge", "disabled": false, "info": "", "env": [] }, { "id": "93f485839dfa27a8", "type": "subflow", "name": "Forecast Solar", "info": "This subflow uses the http request node to fetch solar forecasts for geographical positions, using the API from https://forecast.solar/. Please check their website and consider getting a paid account.\n\nDo note that, on a free account, you are limited in the number of requests to do. Also note that the data only gets updated once every 15 minutes, so there is no reason to query more often. There is rate limiting built in the subflow not to perform requests more than once every 15 minutes.\n\n# Configuration\n\nIt uses the parameters as described on: http://doc.forecast.solar/doku.php\n\n - `:apikey` - personal API key for registered users\n - `:lat` - latitude of location, -90 (south) … 90 (north); Internal precission is 0.0001 or abt. 10 m\n - `:lon` - longitude of location, -180 (west) … 180 (east); Internal precission is 0.0001 or abt. 10 m\n - `:dec` - plane declination, 0 (horizontal) … 90 (vertical); Internal precission is integer\n - `:az` - plane azimuth, -180 … 180 (-180 = north, -90 = east, 0 = south, 90 = west, 180 = north); Internal precission is integer\n - `:kwp` - installed modules power in kilo watt peak (kWp)\n\nYou can choose between 3 different type of requests. Note that only `estimate` is available on the free plan.\n\n- `estimate` - this is the forecasted estimate that your panels should produce (given the right parameter settings)\n- `history` - historical data showing the long term averages for the days to come. See [https://joint-research-centre.ec.europa.eu/pvgis-online-tool/pvgis-data-download/cm-saf-solar-radiation_en](https://joint-research-centre.ec.europa.eu/pvgis-online-tool/pvgis-data-download/cm-saf-solar-radiation_en) for where the data is fetched from.\n- `clear sky` - estimate given if there would be a clear sky tomorrow\n\nIn case of estimates, one of the following options can be selected:\n- `watts` - Watts (power) average for the period\n- `watt_hours_period` - Watt hours (energy) for the period\n- `watt_hours` - Watt hours (energy) summarized over the day\n- `watt_hours_day` - Watt hours (energy) summarized for each day\n\nFor the graph output there are some extra settings available:\n\n- _Output in kWh_ - when checked output can be set to kWh instead of Wh\n- _Show todays forecast_ - whether or not to include todays forecast\n- _Days to forecast_ - the number of days to forecast (excluding today). Note that you can not get more days forecasted than your API key allows.\n- _Widen graph_ - widen the graph to only show non-zero values\n\n# Input \n\nThe input is for triggering the solar forecast request. \nIt triggers when injecting a message into the node.\n\n# Output\n\nThere are two outputs. The first output is an object with the result and a status message stored into the `msg.payload`.\n\nMost important is the `msg.payload.result`, which contains the estimated production of the panels. E.g.:\n\n```\npayload: object\n result: object\n 2022-11-28: 23\n 2022-11-29: 35\n```\n\nThe `msg.payload.message` gives information on how successful the query was, the exitcode of the query and the status of the rate limit (how many queries you have left).\n\nThe **second** output can be directly linked to a line or a bar chart, quickly giving a once-glance overview for the predicted forecast.\n\n# Status\n\nInitially the status of the note will be a blue dot, showing \"_Unknown limit_\", as it is unaware of the set ratelmits. After the first request, the returned ratelimit will be put in the text in the form of `remaining/limit`. If more than half the limit is remaining, the dot will be green. If less then half the limit is remaining, the dot will be yellow. If no limit is left, the dot will turn red.\nPlease keep in mind that the ratelimit will be reset after one hour, so you can send a new request after that hour.\n\nIf something is wrong in the API request, the dot will turn red\nand the message will contain the msg.payload with the error. This\nhappens typically when the API is temporally down for maintenance.", "category": "", "in": [ { "x": 260, "y": 100, "wires": [ { "id": "b9488734852cd0ca" } ] } ], "out": [ { "x": 770, "y": 260, "wires": [ { "id": "2f42837904c91d73", "port": 0 }, { "id": "fcc8d69a3ab88e6d", "port": 0 } ] } ], "env": [ { "name": "latitude", "type": "num", "value": "51.3", "ui": { "icon": "font-awesome/fa-location-arrow", "type": "input", "opts": { "types": [ "num" ] } } }, { "name": "longitude", "type": "num", "value": "5.6", "ui": { "icon": "font-awesome/fa-location-arrow", "type": "input", "opts": { "types": [ "num" ] } } }, { "name": "declination", "type": "num", "value": "37", "ui": { "icon": "font-awesome/fa-chevron-up", "type": "input", "opts": { "types": [ "num" ] } } }, { "name": "azimuth", "type": "num", "value": "0", "ui": { "icon": "font-awesome/fa-compass", "type": "spinner", "opts": { "min": -180, "max": 180 } } }, { "name": "modules power", "type": "num", "value": "1", "ui": { "icon": "font-awesome/fa-power-off", "type": "input", "opts": { "types": [ "num" ] } } }, { "name": "apikey", "type": "cred", "ui": { "icon": "font-awesome/fa-key", "type": "input", "opts": { "types": [ "cred" ] } } }, { "name": "type", "type": "str", "value": "estimate", "ui": { "label": { "en-US": "type" }, "type": "select", "opts": { "opts": [ { "l": { "en-US": "Estimate" }, "v": "estimate" }, { "l": { "en-US": "History" }, "v": "history" }, { "l": { "en-US": "Clear sky" }, "v": "clearsky" } ] } } }, { "name": "watt", "type": "str", "value": "watts", "ui": { "icon": "font-awesome/fa-question-circle-o", "type": "select", "opts": { "opts": [ { "l": { "en-US": "Watts (power) average for the period" }, "v": "watts" }, { "l": { "en-US": "Watt hours (energy) for the period" }, "v": "watt_hours_period" }, { "l": { "en-US": "Watt hours (energy) summarized over the day" }, "v": "watt_hours" }, { "l": { "en-US": "Watt hours (energy) summarized for each day" }, "v": "watt_hours_day" } ] } } }, { "name": "kwhoutput", "type": "bool", "value": "true", "ui": { "label": { "en-US": "Output in kWh (in the graph)" }, "type": "checkbox" } }, { "name": "showtoday", "type": "bool", "value": "false", "ui": { "label": { "en-US": "Show todays forecast" }, "type": "checkbox" } }, { "name": "daystoforecast", "type": "str", "value": "-1", "ui": { "label": { "en-US": "Days to forecast" }, "type": "select", "opts": { "opts": [ { "l": { "en-US": "Max" }, "v": "-1" }, { "l": { "en-US": "0" }, "v": "0" }, { "l": { "en-US": "1" }, "v": "1" }, { "l": { "en-US": "2" }, "v": "2" }, { "l": { "en-US": "3" }, "v": "3" }, { "l": { "en-US": "4" }, "v": "4" }, { "l": { "en-US": "5" }, "v": "5" }, { "l": { "en-US": "6" }, "v": "6" } ] } } }, { "name": "widengraph", "type": "bool", "value": "true", "ui": { "label": { "en-US": "Widen graph" }, "type": "checkbox" } } ], "meta": { "module": "Solar Forecast", "version": "0.0.9", "author": "dfaber@victronenergy.com", "desc": "Get solar forecasting per location", "keywords": "solar,forecast,api", "license": "GPL-3.0" }, "color": "#FFCC66", "inputLabels": [ "trigger" ], "outputLabels": [ "output" ], "icon": "font-awesome/fa-sun-o", "status": { "x": 740, "y": 520, "wires": [ { "id": "1bfc1cde3ee94e4b", "port": 0 }, { "id": "a798fbe66cf133d5", "port": 0 } ] } }, { "id": "8e11c34e65339b88", "type": "subflow", "name": "Solcast API", "info": "", "category": "", "in": [ { "x": 100, "y": 220, "wires": [ { "id": "29c5c88c5e35da06" } ] } ], "out": [ { "x": 1040, "y": 220, "wires": [ { "id": "4878dd1b4cce73a5", "port": 0 } ] }, { "x": 1040, "y": 440, "wires": [ { "id": "2b06f27f02c9e7f7", "port": 0 } ] } ], "env": [], "meta": {}, "color": "#F3B567", "icon": "node-red/cog.svg" }, { "id": "0169c507ea4f38a3", "type": "group", "z": "5042e496e3bb2cb7", "name": "", "style": { "stroke": "#ffC000", "fill": "#ffefbf", "label": false, "fill-opacity": "0.58" }, "nodes": [ "386c9fddbe3c0b3e", "5a6f42da37140895", "77b21e4f95016374", "606181d0995a3938", "e2f3761012423b6a", "1ed775a3090df71b", "4488c67c39ca4f8e", "0e58f71d419159d7", "f17db0ee335d0db0", "66b80f2d2c0ffb97", "59af4d6b567841f0", "897ed0abe133a28b" ], "x": 54, "y": 379, "w": 1312, "h": 222 }, { "id": "416efad388f85db0", "type": "group", "z": "5042e496e3bb2cb7", "name": "", "style": { "stroke": "#3f93cf", "fill": "#bfdbef", "label": false, "fill-opacity": "0.58" }, "nodes": [ "62a8b2385cf52811", "dd74f83175edcb7e", "24d788b88b4205b9", "64378564303c1353", "d6d78e34d7018a9e", "a02e26737e8d4a9c", "5361b5132ae8510e", "459d750ce708b4bc", "f78b9b4cdf67b280", "952a87f0d3ac76c5", "ecfc6114a646a313", "6cd9fbba64ed1ef6", "f2b0f7ba788ab79b", "0486d3aafd519527", "50dbeb70a1175629", "e71e0bcce8930f1f", "87e0a7645d276afb", "4f9ef9d03f9ee24e", "2bc44ba9baa3e9e0", "a319b3a1bd539543", "e17d83f97adc7295", "e62ab0e17b6badce", "eac55f87bb4f470c", "61eb1e60369d2d43", "766de8375ae3806b" ], "x": 54, "y": 619, "w": 1312, "h": 549.5 }, { "id": "52dd229ad312e8ba", "type": "group", "z": "5042e496e3bb2cb7", "name": "", "style": { "fill": "#d1d1d1", "label": false, "fill-opacity": "0.6" }, "nodes": [ "be3c9209155a3099", "9cc6a564cad6e42b", "2a7e0ee0b0112350", "2b88804fd4e18ae9", "0feca34e12fe5a4e", "27440ddfdb6223aa", "aa3861c2b6962c40", "de5deea31e945508", "5080fc6e39eab860", "724a330f2bd7d00b", "37dd47c111e38eb0", "b80bba99fd534e7a" ], "x": 54, "y": 1199, "w": 1252, "h": 242 }, { "id": "c81f84a443806937", "type": "group", "z": "5042e496e3bb2cb7", "name": "", "style": { "stroke": "#92d04f", "fill": "#e3f3d3", "fill-opacity": "0.58", "label": false }, "nodes": [ "82aa6b0cb02c754e", "71ec1982cc297480", "3396f37a87aafeb1", "eecc35e8f5b537bd", "e21993f799e39c2e", "10a65e2d7c8de048", "fce306ba33691cb0", "8f800b4a18f84c29", "261edb937bff7595", "49ccceed2c928b0e", "82eae5094501b352", "1d675c1dce5f5523", "59f97492fa06c31b", "02278983f5802fdd", "7ee12c7a203084d7", "6cb6191b64aee6ce", "1ad92a6f76bb2e97", "523dee34376df263", "023c1ec34838268e" ], "x": 54, "y": 39, "w": 1312, "h": 322 }, { "id": "4801a1f1d857cc4c", "type": "ui_tab", "name": "Home", "icon": "dashboard", "disabled": false, "hidden": false }, { "id": "f19325ee9c986d94", "type": "ui_tab", "name": "Summary", "icon": "dashboard", "order": 1, "disabled": false, "hidden": false }, { "id": "2c49990b9e262446", "type": "ui_base", "theme": { "name": "theme-light", "lightTheme": { "default": "#0094CE", "baseColor": "#0094CE", "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", "edited": false }, "darkTheme": { "default": "#097479", "baseColor": "#097479", "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", "edited": false }, "customTheme": { "name": "Untitled Theme 1", "default": "#4B7930", "baseColor": "#4B7930", "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" }, "themeState": { "base-color": { "default": "#0094CE", "value": "#0094CE", "edited": false }, "page-titlebar-backgroundColor": { "value": "#0094CE", "edited": false }, "page-backgroundColor": { "value": "#fafafa", "edited": false }, "page-sidebar-backgroundColor": { "value": "#ffffff", "edited": false }, "group-textColor": { "value": "#1bbfff", "edited": false }, "group-borderColor": { "value": "#ffffff", "edited": false }, "group-backgroundColor": { "value": "#ffffff", "edited": false }, "widget-textColor": { "value": "#111111", "edited": false }, "widget-backgroundColor": { "value": "#0094ce", "edited": false }, "widget-borderColor": { "value": "#ffffff", "edited": false }, "base-font": { "value": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" } }, "angularTheme": { "primary": "indigo", "accents": "blue", "warn": "red", "background": "grey", "palette": "light" } }, "site": { "name": "Node-RED Dashboard", "hideToolbar": "false", "allowSwipe": "false", "lockMenu": "false", "allowTempTheme": "true", "dateFormat": "DD/MM/YYYY", "sizes": { "sx": 48, "sy": 48, "gx": 6, "gy": 6, "cx": 6, "cy": 6, "px": 0, "py": 0 } } }, { "id": "e889f2db31c97dbf", "type": "ui_base", "theme": { "name": "theme-light", "lightTheme": { "default": "#0094CE", "baseColor": "#0094CE", "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", "edited": true, "reset": false }, "darkTheme": { "default": "#097479", "baseColor": "#097479", "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", "edited": false }, "customTheme": { "name": "Untitled Theme 1", "default": "#4B7930", "baseColor": "#4B7930", "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" }, "themeState": { "base-color": { "default": "#0094CE", "value": "#0094CE", "edited": false }, "page-titlebar-backgroundColor": { "value": "#0094CE", "edited": false }, "page-backgroundColor": { "value": "#fafafa", "edited": false }, "page-sidebar-backgroundColor": { "value": "#ffffff", "edited": false }, "group-textColor": { "value": "#1bbfff", "edited": false }, "group-borderColor": { "value": "#ffffff", "edited": false }, "group-backgroundColor": { "value": "#ffffff", "edited": false }, "widget-textColor": { "value": "#111111", "edited": false }, "widget-backgroundColor": { "value": "#0094ce", "edited": false }, "widget-borderColor": { "value": "#ffffff", "edited": false }, "base-font": { "value": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" } }, "angularTheme": { "primary": "indigo", "accents": "blue", "warn": "red", "background": "grey", "palette": "light" } }, "site": { "name": "Node-RED Dashboard", "hideToolbar": "false", "allowSwipe": "false", "lockMenu": "false", "allowTempTheme": "true", "dateFormat": "DD/MM/YYYY", "sizes": { "sx": 48, "sy": 48, "gx": 6, "gy": 6, "cx": 6, "cy": 6, "px": 0, "py": 0 } } }, { "id": "victron-client-id", "type": "victron-client" }, { "id": "c706820c0d61f023", "type": "http request", "z": "93f485839dfa27a8", "name": "Forecast Solar", "method": "GET", "ret": "txt", "paytoqs": "ignore", "url": "", "tls": "", "persist": false, "proxy": "", "insecureHTTPParser": false, "authType": "", "senderr": false, "headers": [], "x": 400, "y": 180, "wires": [ [ "1b5ccaa05d54f7c3" ] ] }, { "id": "b9488734852cd0ca", "type": "function", "z": "93f485839dfa27a8", "name": "create forecast.solar url", "func": "msg.url = 'https://api.forecast.solar/';\n\nif (env.get('apikey')) {\n msg.url += env.get('apikey') + '/';\n }\n\nmsg.url += env.get('type') + '/';\n\nmsg.url += env.get('watt') + '/';\n\nmsg.url += env.get('latitude') + '/' +\n env.get('longitude') + '/' +\n env.get('declination') + '/' +\n env.get('azimuth') + '/' +\n env.get('modules power');\n\nmsg.topic = 'solar forecast: '+(env.get('type') || '');\nmsg.topic += (' '+env.get('watt') || '');\nif (env.get('kwhoutput')) {\n msg.topic += ' (kWh)';\n}\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 630, "y": 100, "wires": [ [ "975daf96f15cfb61" ] ] }, { "id": "1b5ccaa05d54f7c3", "type": "json", "z": "93f485839dfa27a8", "name": "Convert to json", "property": "payload", "action": "", "pretty": false, "x": 660, "y": 180, "wires": [ [ "e718a22973cc2864" ] ] }, { "id": "559391d1288f762a", "type": "function", "z": "93f485839dfa27a8", "name": "update ratelimit", "func": "var remaining = msg.payload.message.ratelimit.remaining || 0;\nvar limit = msg.payload.message.ratelimit.limit;\n\nflow.set('forecast.solar.ratelimit.remaining', remaining)\nflow.set('forecast.solar.ratelimit.limit', limit)\n\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 580, "y": 440, "wires": [ [ "e56826252134b93a" ] ] }, { "id": "e718a22973cc2864", "type": "link out", "z": "93f485839dfa27a8", "name": "link out 1", "mode": "link", "links": [ "3fa24f2d08195961", "0a20e852662c8cec" ], "x": 815, "y": 180, "wires": [] }, { "id": "3fa24f2d08195961", "type": "link in", "z": "93f485839dfa27a8", "name": "link in 1", "links": [ "e718a22973cc2864" ], "x": 445, "y": 440, "wires": [ [ "559391d1288f762a" ] ] }, { "id": "0a20e852662c8cec", "type": "link in", "z": "93f485839dfa27a8", "name": "link in 2", "links": [ "e718a22973cc2864" ], "x": 265, "y": 260, "wires": [ [ "fcc8d69a3ab88e6d" ] ] }, { "id": "4734b6f403e1f03e", "type": "inject", "z": "93f485839dfa27a8", "name": "", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": true, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 590, "y": 400, "wires": [ [ "e56826252134b93a" ] ] }, { "id": "1bfc1cde3ee94e4b", "type": "function", "z": "93f485839dfa27a8", "name": "update status", "func": "var remaining = flow.get('forecast.solar.ratelimit.remaining') || -1;\nvar limit = flow.get('forecast.solar.ratelimit.limit') || -1\n\nvar text = remaining.toString() + '/' + limit.toString();\nvar fill = \"green\";\n\nif (remaining == 0) {\n fill = \"red\";\n text = \"Limit used\";\n}\n\nif (remaining > 0 && remaining < limit / 2) {\n fill = \"yellow\"\n}\n\nif (remaining == -1 ) {\n fill = \"blue\"\n text = \"Limits unknown\"\n}\n\nmsg.payload = ({ fill: fill, text: text });\n\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 580, "y": 540, "wires": [ [] ] }, { "id": "975daf96f15cfb61", "type": "link out", "z": "93f485839dfa27a8", "name": "link out 7", "mode": "link", "links": [ "14f2e68e572f4ef8" ], "x": 815, "y": 100, "wires": [] }, { "id": "14f2e68e572f4ef8", "type": "link in", "z": "93f485839dfa27a8", "name": "link in 18", "links": [ "975daf96f15cfb61" ], "x": 265, "y": 180, "wires": [ [ "c706820c0d61f023" ] ] }, { "id": "c4307905e114824f", "type": "catch", "z": "93f485839dfa27a8", "name": "", "scope": null, "uncaught": false, "x": 320, "y": 400, "wires": [ [ "f427f19392c399ce" ] ] }, { "id": "e56826252134b93a", "type": "link out", "z": "93f485839dfa27a8", "name": "link out 8", "mode": "link", "links": [ "dbaf8f5f5a920686" ], "x": 745, "y": 440, "wires": [] }, { "id": "dbaf8f5f5a920686", "type": "link in", "z": "93f485839dfa27a8", "name": "link in 19", "links": [ "e56826252134b93a" ], "x": 445, "y": 540, "wires": [ [ "1bfc1cde3ee94e4b" ] ] }, { "id": "f427f19392c399ce", "type": "link out", "z": "93f485839dfa27a8", "name": "link out 9", "mode": "link", "links": [ "2ded0c14a222b4d9", "2f42837904c91d73" ], "x": 445, "y": 400, "wires": [] }, { "id": "2ded0c14a222b4d9", "type": "link in", "z": "93f485839dfa27a8", "name": "link in 20", "links": [ "f427f19392c399ce" ], "x": 445, "y": 500, "wires": [ [ "a798fbe66cf133d5" ] ] }, { "id": "a798fbe66cf133d5", "type": "function", "z": "93f485839dfa27a8", "name": "Set error status", "func": "node.warn(msg.payload)\nmsg.payload = ({ fill: \"red\", text: msg.payload });\n\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 580, "y": 500, "wires": [ [] ] }, { "id": "2f42837904c91d73", "type": "link in", "z": "93f485839dfa27a8", "name": "link in 21", "links": [ "f427f19392c399ce" ], "x": 605, "y": 320, "wires": [ [] ] }, { "id": "fcc8d69a3ab88e6d", "type": "function", "z": "93f485839dfa27a8", "name": "Processed info", "func": "msg.resolution = 60;\nmsg.days = 1;\nmsg.type = env.get('type');\nmsg.watt = env.get('watt');\nmsg.kwhoutput = env.get('kwhoutput');\n\nvar key1 = Object.keys(msg.payload.result)[1];\nvar key2 = Object.keys(msg.payload.result)[2];\nvar key3 = Object.keys(msg.payload.result)[Object.keys(msg.payload.result).length-1];\n\nvar d1 = new Date(key1);\nvar d2 = new Date(key2); \nvar d3 = new Date(key3);\n\nmsg.resolution = 3600000 / (d2.getTime() - d1.getTime());\n\nmsg.days = Math.floor((d3.getTime() - d1.getTime()) / (1000 * 3600 * 24));\n\nif (msg.watt === 'watt_hours_day') {\n msg.resolution = null;\n}\n\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 400, "y": 260, "wires": [ [] ], "info": "Function to process the result from forecast.solar to add\nextra information, which is handy for either graphing or\nto store in a database.\n\n\nThe extra values added:\n- `msg.resolution` - The number of measurements per hour. If\nno API key is used, this will be 1. Other values may be 2 or 4.\n- `msg.days` - The number of days in the forcast. If no API\n- key is used this will be 1. Other values may be 3 or 6." }, { "id": "29c5c88c5e35da06", "type": "http request", "z": "8e11c34e65339b88", "name": "Solcast ", "method": "GET", "ret": "obj", "paytoqs": "ignore", "url": "https://api.solcast.com.au/rooftop_sites/###YOUR API SITE###/forecasts?format=json&hours=72", "tls": "", "persist": false, "proxy": "", "insecureHTTPParser": false, "authType": "basic", "senderr": false, "headers": [], "x": 240, "y": 220, "wires": [ [ "1bc841a4b0c71079", "031c5b77e02c21be" ] ] }, { "id": "1bc841a4b0c71079", "type": "function", "z": "8e11c34e65339b88", "name": "Extract All", "func": "// add up all the values:\nfor (var i in msg.payload.forecasts) {\n msg.payload.forecasts[i] = Number(msg.payload.forecasts[i].pv_estimate);\n }\n msg.payload.pvtotal = msg.payload.forecasts.reduce(function(a, b){\n return a + b;\n }, 0);\n// halve the value due to a reading every 30 minutes:\nmsg.payload.pvtotal = msg.payload.pvtotal/2;\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 480, "y": 120, "wires": [ [ "488f446ff16a34c7", "f3c4d443bdcf9c9b", "c8c29d172095b303" ] ] }, { "id": "488f446ff16a34c7", "type": "change", "z": "8e11c34e65339b88", "name": "PVForecast to global", "rules": [ { "t": "set", "p": "pvforecast", "pt": "global", "to": "payload.pvtotal", "tot": "msg" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 820, "y": 120, "wires": [ [] ] }, { "id": "f3c4d443bdcf9c9b", "type": "change", "z": "8e11c34e65339b88", "name": "Write forecasts array to global", "rules": [ { "t": "set", "p": "individualforecast", "pt": "global", "to": "payload.forecasts", "tot": "msg" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 850, "y": 80, "wires": [ [] ] }, { "id": "f9e6352b98d1eaaa", "type": "function", "z": "8e11c34e65339b88", "name": "Extract Daily Total", "func": "// add up all the values:\nvar pvtotal = 0\nvar x = -1\nvar zeroday = 0\nvar forecasts = []\nvar dailypv = []\nfor (var i in msg.payload) {\n if (msg.payload[i]==0) {\n zeroday = 0;\n } else if (zeroday==1) {\n dailypv[x] = dailypv[x] + msg.payload[i]/2;\n }else{\n zeroday = 1\n x = x + 1\n dailypv[x] = 0\n dailypv[x] = dailypv[x] + msg.payload[i]/2;\n}}\nmsg.payload = dailypv;\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 510, "y": 220, "wires": [ [ "4878dd1b4cce73a5" ] ] }, { "id": "4878dd1b4cce73a5", "type": "change", "z": "8e11c34e65339b88", "name": "Set Daily Total to Global", "rules": [ { "t": "set", "p": "DailyTotal", "pt": "global", "to": "payload", "tot": "msg" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 830, "y": 220, "wires": [ [] ] }, { "id": "fcda0bcd9e547ec1", "type": "function", "z": "8e11c34e65339b88", "name": "Extract DailyP10 Total", "func": "// add up all the values:\nvar pvtotal = 0\nvar x = -1\nvar zeroday = 0\nvar forecasts = []\nvar dailypv = []\nfor (var i in msg.payload) {\n if (msg.payload[i]==0) {\n zeroday = 0;\n } else if (zeroday==1) {\n dailypv[x] = dailypv[x] + msg.payload[i]/2;\n }else{\n zeroday = 1\n x = x + 1\n dailypv[x] = 0\n dailypv[x] = dailypv[x] + msg.payload[i]/2;\n}}\nmsg.payload = dailypv;\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 520, "y": 440, "wires": [ [ "2b06f27f02c9e7f7" ] ] }, { "id": "2b06f27f02c9e7f7", "type": "change", "z": "8e11c34e65339b88", "name": "Set Daily Total to Global", "rules": [ { "t": "set", "p": "DailyTotalP10", "pt": "global", "to": "payload", "tot": "msg" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 830, "y": 440, "wires": [ [] ] }, { "id": "bd7319d721ca078a", "type": "change", "z": "8e11c34e65339b88", "name": "PVForecast to global", "rules": [ { "t": "set", "p": "pvforecastP10", "pt": "global", "to": "payload.pvtotal", "tot": "msg" }, { "t": "set", "p": "payload", "pt": "msg", "to": "", "tot": "str" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 820, "y": 340, "wires": [ [] ] }, { "id": "c5c6050f03989745", "type": "change", "z": "8e11c34e65339b88", "name": "Write forecasts array to global", "rules": [ { "t": "set", "p": "individualforecastP10", "pt": "global", "to": "payload.forecasts", "tot": "msg" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 850, "y": 300, "wires": [ [] ] }, { "id": "031c5b77e02c21be", "type": "function", "z": "8e11c34e65339b88", "name": "Extract All P10", "func": "// add up all the values:\nfor (var i in msg.payload.forecasts) {\n msg.payload.forecasts[i] = Number(msg.payload.forecasts[i].pv_estimate10);\n }\n msg.payload.pvtotal = msg.payload.forecasts.reduce(function(a, b){\n return a + b;\n }, 0);\n// halve the value due to a reading every 30 minutes:\nmsg.payload.pvtotal = msg.payload.pvtotal/2;\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "x": 500, "y": 340, "wires": [ [ "bd7319d721ca078a", "c5c6050f03989745", "5491e2909ca39cfb" ] ] }, { "id": "c8c29d172095b303", "type": "change", "z": "8e11c34e65339b88", "name": "Change for total", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "individualforecast", "tot": "global" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 800, "y": 160, "wires": [ [ "f9e6352b98d1eaaa" ] ] }, { "id": "5491e2909ca39cfb", "type": "change", "z": "8e11c34e65339b88", "name": "Change for P10 total", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "individualforecastP10", "tot": "global" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 820, "y": 380, "wires": [ [ "fcda0bcd9e547ec1" ] ] }, { "id": "82aa6b0cb02c754e", "type": "subflow:93f485839dfa27a8", "z": "5042e496e3bb2cb7", "g": "c81f84a443806937", "name": "Forecast.Solar API", "env": [ { "name": "latitude", "value": "???", "type": "num" }, { "name": "longitude", "value": "???", "type": "num" }, { "name": "declination", "value": "20", "type": "num" }, { "name": "azimuth", "value": "15", "type": "num" }, { "name": "modules power", "value": "13.5", "type": "num" }, { "name": "apikey", "type": "cred" }, { "name": "watt", "value": "watt_hours_day", "type": "str" }, { "name": "kwhoutput", "type": "bool", "value": "false" } ], "x": 430, "y": 320, "wires": [ [ "3396f37a87aafeb1" ] ] }, { "id": "71ec1982cc297480", "type": "inject", "z": "5042e496e3bb2cb7", "g": "c81f84a443806937", "name": "23:45 Local", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "45 23 * * *", "once": false, "onceDelay": 0.1, "topic": "", "payload": "Inject each night at 23:45", "payloadType": "str", "x": 190, "y": 240, "wires": [ [ "6cb6191b64aee6ce", "82aa6b0cb02c754e", "eecc35e8f5b537bd" ] ] }, { "id": "3396f37a87aafeb1", "type": "function", "z": "5042e496e3bb2cb7", "g": "c81f84a443806937", "name": "Extract Next Days Forecast", "func": "var key1 = Object.keys(msg.payload.result)[1];\nvar key2 = Object.keys(msg.payload.result)[2];\n\nvar d1 = new Date(key1);\nvar d2 = new Date(key2); \n\nvar outputValue = -99;\n\nif(d1 < d2){\n outputValue = msg.payload.result[key2];\n} else{\n outputValue = msg.payload.result[key1];\n}\n\nmsg.payload = outputValue;\n\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 860, "y": 320, "wires": [ [ "7ee12c7a203084d7" ] ] }, { "id": "386c9fddbe3c0b3e", "type": "delay", "z": "5042e496e3bb2cb7", "g": "0169c507ea4f38a3", "name": "Delay 20 mins or 80 mins (BST TIme)", "pauseType": "delay", "timeout": "80", "timeoutUnits": "minutes", "rate": "1", "nbRateUnits": "1", "rateUnits": "second", "randomFirst": "1", "randomLast": "5", "randomUnits": "seconds", "drop": false, "allowrate": false, "outputs": 1, "x": 670, "y": 500, "wires": [ [ "5a6f42da37140895", "59af4d6b567841f0" ] ] }, { "id": "5a6f42da37140895", "type": "switch", "z": "5042e496e3bb2cb7", "g": "0169c507ea4f38a3", "name": "(1) High SOC (2) Mid SOC (3) Low SOC", "property": "payload", "propertyType": "msg", "rules": [ { "t": "lte", "v": "20000", "vt": "str" }, { "t": "lte", "v": "40000", "vt": "str" }, { "t": "gt", "v": "40000", "vt": "str" } ], "checkall": "false", "repair": false, "outputs": 3, "x": 1080, "y": 500, "wires": [ [ "77b21e4f95016374" ], [ "606181d0995a3938" ], [ "e2f3761012423b6a" ] ] }, { "id": "62a8b2385cf52811", "type": "comment", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "N.B. Set SOC sets min SOC to X % then resets after 4hr 50mins to 15%", "info": "This sets Min SOC % make sure you follow through if one value is changed", "x": 1090, "y": 920, "wires": [] }, { "id": "dd74f83175edcb7e", "type": "comment", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "N.B Full Charge sets the ESS mode to 9 (Keep charged) then resets after 4hr 50mins to 10 (Optimised w/o Batt Life)", "info": "", "x": 950, "y": 740, "wires": [] }, { "id": "eecc35e8f5b537bd", "type": "subflow:8e11c34e65339b88", "z": "5042e496e3bb2cb7", "g": "c81f84a443806937", "name": "", "x": 410, "y": 160, "wires": [ [ "8f800b4a18f84c29" ], [ "fce306ba33691cb0" ] ] }, { "id": "e21993f799e39c2e", "type": "range", "z": "5042e496e3bb2cb7", "g": "c81f84a443806937", "minin": "0", "maxin": "1", "minout": "0", "maxout": "1000", "action": "scale", "round": true, "property": "payload", "name": "Kwh to Watt hr", "x": 760, "y": 140, "wires": [ [ "1ad92a6f76bb2e97" ] ] }, { "id": "10a65e2d7c8de048", "type": "range", "z": "5042e496e3bb2cb7", "g": "c81f84a443806937", "minin": "0", "maxin": "1", "minout": "0", "maxout": "1000", "action": "scale", "round": true, "property": "payload", "name": "Kwh to Watt hr", "x": 760, "y": 180, "wires": [ [ "523dee34376df263" ] ] }, { "id": "fce306ba33691cb0", "type": "change", "z": "5042e496e3bb2cb7", "g": "c81f84a443806937", "name": "Strip Val out", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "payload[1]", "tot": "msg" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 590, "y": 180, "wires": [ [ "10a65e2d7c8de048" ] ] }, { "id": "8f800b4a18f84c29", "type": "change", "z": "5042e496e3bb2cb7", "g": "c81f84a443806937", "name": "Strip Val out", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "payload[1]", "tot": "msg" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 590, "y": 140, "wires": [ [ "e21993f799e39c2e" ] ] }, { "id": "261edb937bff7595", "type": "calculator", "z": "5042e496e3bb2cb7", "g": "c81f84a443806937", "name": "Average", "inputMsgField": "payload", "outputMsgField": "payload", "operation": "avg", "constant": "", "round": false, "decimals": 0, "x": 1240, "y": 160, "wires": [ [ "02278983f5802fdd" ] ] }, { "id": "49ccceed2c928b0e", "type": "join", "z": "5042e496e3bb2cb7", "g": "c81f84a443806937", "name": "Array", "mode": "custom", "build": "array", "property": "payload", "propertyType": "msg", "key": "topic", "joiner": "\\n", "joinerType": "str", "accumulate": false, "timeout": "5", "count": "", "reduceRight": false, "reduceExp": "", "reduceInit": "", "reduceInitType": "", "reduceFixup": "", "x": 1070, "y": 160, "wires": [ [ "261edb937bff7595" ] ] }, { "id": "77b21e4f95016374", "type": "link out", "z": "5042e496e3bb2cb7", "g": "0169c507ea4f38a3", "name": "link out 10", "mode": "link", "links": [ "459d750ce708b4bc" ], "x": 1325, "y": 460, "wires": [] }, { "id": "606181d0995a3938", "type": "link out", "z": "5042e496e3bb2cb7", "g": "0169c507ea4f38a3", "name": "link out 11", "mode": "link", "links": [ "6cd9fbba64ed1ef6" ], "x": 1325, "y": 500, "wires": [] }, { "id": "e2f3761012423b6a", "type": "link out", "z": "5042e496e3bb2cb7", "g": "0169c507ea4f38a3", "name": "link out 12", "mode": "link", "links": [ "0486d3aafd519527" ], "x": 1325, "y": 540, "wires": [] }, { "id": "1ed775a3090df71b", "type": "comment", "z": "5042e496e3bb2cb7", "g": "0169c507ea4f38a3", "name": "(2) Forecasts are averaged and split into the SOC requirement.", "info": "", "x": 310, "y": 420, "wires": [] }, { "id": "4488c67c39ca4f8e", "type": "link in", "z": "5042e496e3bb2cb7", "g": "0169c507ea4f38a3", "name": "link in 25", "links": [ "1d675c1dce5f5523", "82eae5094501b352" ], "x": 95, "y": 500, "wires": [ [ "f17db0ee335d0db0" ] ] }, { "id": "82eae5094501b352", "type": "link out", "z": "5042e496e3bb2cb7", "g": "c81f84a443806937", "name": "link out 13", "mode": "link", "links": [ "4488c67c39ca4f8e", "27440ddfdb6223aa" ], "x": 1325, "y": 320, "wires": [] }, { "id": "1d675c1dce5f5523", "type": "link out", "z": "5042e496e3bb2cb7", "g": "c81f84a443806937", "name": "link out 14", "mode": "link", "links": [ "4488c67c39ca4f8e", "27440ddfdb6223aa" ], "x": 1325, "y": 220, "wires": [] }, { "id": "be3c9209155a3099", "type": "e-mail", "z": "5042e496e3bb2cb7", "g": "52dd229ad312e8ba", "server": "smtp.gmail.com", "port": "465", "authtype": "BASIC", "saslformat": false, "token": "", "secure": true, "tls": true, "name": "### Your email ###", "dname": "", "x": 1190, "y": 1340, "wires": [] }, { "id": "0e58f71d419159d7", "type": "calculator", "z": "5042e496e3bb2cb7", "g": "0169c507ea4f38a3", "name": "", "inputMsgField": "payload", "outputMsgField": "payload", "operation": "avg", "constant": "", "round": false, "decimals": 0, "x": 420, "y": 500, "wires": [ [ "66b80f2d2c0ffb97", "386c9fddbe3c0b3e" ] ] }, { "id": "59f97492fa06c31b", "type": "comment", "z": "5042e496e3bb2cb7", "g": "c81f84a443806937", "name": "(1) Gathers API from Solar Forecast websites, averages Solcast then injects both to the SOC requirement.", "info": "", "x": 440, "y": 80, "wires": [] }, { "id": "9cc6a564cad6e42b", "type": "function", "z": "5042e496e3bb2cb7", "g": "52dd229ad312e8ba", "name": "Write Email Msg", "func": "msg.payload = \n\n`Node Red used an average of ${msg.payload} Wh as the basis of the ESS charge setting change. \n\nESS SOC was set to: ${flow.get(\"ESS.Set\")} ${flow.get(\"ESS.Charge\")}\n\nForecasts used were:\n\n - Forecast Solar: ${flow.get(\"Forecast.Solar\")} Wh.\n \n - Solcast: ${flow.get(\"Solcast.Av\")} Wh (Average of: Estimate ${flow.get(\"Solcast.Est\")} Wh & Pessimistic ${flow.get(\"Solcast.P10\")} Wh ) \n \n `;\nmsg.topic = 'Node Red Update Email'\nreturn msg;\n\n\n", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 880, "y": 1280, "wires": [ [ "be3c9209155a3099" ] ], "icon": "node-red/envelope.svg" }, { "id": "02278983f5802fdd", "type": "function", "z": "5042e496e3bb2cb7", "g": "c81f84a443806937", "name": "Sol Av", "func": "flow.set('Solcast.Av', msg.payload);\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 1230, "y": 220, "wires": [ [ "1d675c1dce5f5523" ] ], "icon": "node-red/file-in.svg" }, { "id": "7ee12c7a203084d7", "type": "function", "z": "5042e496e3bb2cb7", "g": "c81f84a443806937", "name": "Forecast.Solar", "func": "flow.set('Forecast.Solar', msg.payload);\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 1100, "y": 320, "wires": [ [ "82eae5094501b352" ] ], "icon": "node-red/file-in.svg" }, { "id": "2a7e0ee0b0112350", "type": "trigger", "z": "5042e496e3bb2cb7", "g": "52dd229ad312e8ba", "name": "Trigger if no reset", "op1": "", "op2": "Msg Not Arrived", "op1type": "nul", "op2type": "str", "duration": "1", "extend": true, "overrideDelay": false, "units": "min", "reset": "", "bytopic": "all", "topic": "topic", "outputs": 1, "x": 670, "y": 1380, "wires": [ [ "2b88804fd4e18ae9" ] ] }, { "id": "2b88804fd4e18ae9", "type": "function", "z": "5042e496e3bb2cb7", "g": "52dd229ad312e8ba", "name": "ERROR Email Msg", "func": "msg.payload = `Node Red has an ERROR with the following:\n\n ${msg.payload} \n`;\nmsg.topic = 'Node Red ERROR'\nreturn msg;\n\n\n", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 890, "y": 1380, "wires": [ [ "be3c9209155a3099" ] ], "icon": "node-red/envelope.svg" }, { "id": "f17db0ee335d0db0", "type": "join", "z": "5042e496e3bb2cb7", "g": "0169c507ea4f38a3", "name": "Combine as Array", "mode": "custom", "build": "array", "property": "payload", "propertyType": "msg", "key": "topic", "joiner": "\\n", "joinerType": "str", "accumulate": false, "timeout": "30", "count": "2", "reduceRight": false, "reduceExp": "", "reduceInit": "", "reduceInitType": "", "reduceFixup": "", "x": 230, "y": 500, "wires": [ [ "0e58f71d419159d7" ] ] }, { "id": "0feca34e12fe5a4e", "type": "function", "z": "5042e496e3bb2cb7", "g": "52dd229ad312e8ba", "name": "Reset if Valid", "func": "msg.reset=true\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 310, "y": 1360, "wires": [ [ "2a7e0ee0b0112350" ] ], "icon": "font-awesome/fa-undo" }, { "id": "27440ddfdb6223aa", "type": "link in", "z": "5042e496e3bb2cb7", "g": "52dd229ad312e8ba", "name": "link in 26", "links": [ "6cb6191b64aee6ce", "82eae5094501b352", "1d675c1dce5f5523" ], "x": 95, "y": 1380, "wires": [ [ "2a7e0ee0b0112350" ] ] }, { "id": "6cb6191b64aee6ce", "type": "link out", "z": "5042e496e3bb2cb7", "g": "c81f84a443806937", "name": "link out 15", "mode": "link", "links": [ "27440ddfdb6223aa" ], "x": 535, "y": 240, "wires": [] }, { "id": "66b80f2d2c0ffb97", "type": "link out", "z": "5042e496e3bb2cb7", "g": "0169c507ea4f38a3", "name": "link out 16", "mode": "link", "links": [ "aa3861c2b6962c40" ], "x": 535, "y": 560, "wires": [] }, { "id": "aa3861c2b6962c40", "type": "link in", "z": "5042e496e3bb2cb7", "g": "52dd229ad312e8ba", "name": "link in 27", "links": [ "66b80f2d2c0ffb97" ], "x": 95, "y": 1320, "wires": [ [ "0feca34e12fe5a4e" ] ] }, { "id": "de5deea31e945508", "type": "comment", "z": "5042e496e3bb2cb7", "g": "52dd229ad312e8ba", "name": "(4) Compiles and sends either a completion email with the values used or an error mail", "info": "", "x": 380, "y": 1240, "wires": [] }, { "id": "5080fc6e39eab860", "type": "catch", "z": "5042e496e3bb2cb7", "g": "52dd229ad312e8ba", "name": "Error Catch", "scope": null, "uncaught": false, "x": 310, "y": 1400, "wires": [ [ "2a7e0ee0b0112350" ] ] }, { "id": "1ad92a6f76bb2e97", "type": "function", "z": "5042e496e3bb2cb7", "g": "c81f84a443806937", "name": "Sol Est", "func": "flow.set('Solcast.Est', msg.payload);\nreturn msg;\n", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 920, "y": 140, "wires": [ [ "49ccceed2c928b0e" ] ], "icon": "node-red/file-in.svg" }, { "id": "523dee34376df263", "type": "function", "z": "5042e496e3bb2cb7", "g": "c81f84a443806937", "name": "Sol P10", "func": "flow.set('Solcast.P10', msg.payload);\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 920, "y": 180, "wires": [ [ "49ccceed2c928b0e" ] ], "icon": "node-red/file-in.svg" }, { "id": "724a330f2bd7d00b", "type": "delay", "z": "5042e496e3bb2cb7", "g": "52dd229ad312e8ba", "name": "60sec", "pauseType": "delay", "timeout": "1", "timeoutUnits": "minutes", "rate": "1", "nbRateUnits": "1", "rateUnits": "second", "randomFirst": "1", "randomLast": "5", "randomUnits": "seconds", "drop": false, "allowrate": false, "outputs": 1, "x": 710, "y": 1280, "wires": [ [ "9cc6a564cad6e42b" ] ], "icon": "font-awesome/fa-pause" }, { "id": "023c1ec34838268e", "type": "comment", "z": "5042e496e3bb2cb7", "g": "c81f84a443806937", "name": "N.B. Inject is Local so adjust for BST on delay", "info": "", "x": 730, "y": 240, "wires": [] }, { "id": "24d788b88b4205b9", "type": "moment", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "Month", "topic": "", "input": "", "inputType": "date", "inTz": "Europe/London", "adjAmount": 0, "adjType": "days", "adjDir": "add", "format": "MMM", "locale": "en_gb", "output": "", "outputType": "msg", "outTz": "Europe/London", "x": 410, "y": 740, "wires": [ [ "64378564303c1353" ] ] }, { "id": "64378564303c1353", "type": "switch", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "Season Split (1) Winter (2) Spring/Autumn (3) Summer", "property": "payload", "propertyType": "msg", "rules": [ { "t": "regex", "v": "Jan|Feb|Nov|Dec", "vt": "str", "case": false }, { "t": "regex", "v": "Mar|Apr|Sep|Oct", "vt": "str", "case": false }, { "t": "regex", "v": "May|Jun|Jul|Aug", "vt": "str", "case": false } ], "checkall": "true", "repair": false, "outputs": 3, "x": 340, "y": 800, "wires": [ [ "a02e26737e8d4a9c" ], [ "5361b5132ae8510e" ], [ "a319b3a1bd539543" ] ] }, { "id": "d6d78e34d7018a9e", "type": "range", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "minin": "0", "maxin": "20000", "minout": "0", "maxout": ".5", "action": "clamp", "round": true, "property": "payload", "name": "<20kw = High SOC", "x": 230, "y": 740, "wires": [ [ "24d788b88b4205b9" ] ] }, { "id": "a02e26737e8d4a9c", "type": "trigger", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "Full Charge", "op1": "9", "op2": "10", "op1type": "num", "op2type": "num", "duration": "290", "extend": false, "overrideDelay": false, "units": "min", "reset": "", "bytopic": "all", "topic": "topic", "outputs": 1, "x": 970, "y": 780, "wires": [ [ "766de8375ae3806b" ] ], "icon": "font-awesome/fa-battery-full" }, { "id": "5361b5132ae8510e", "type": "trigger", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "Set SOC 85%", "op1": "85", "op2": "15", "op1type": "num", "op2type": "num", "duration": "290", "extend": false, "overrideDelay": false, "units": "min", "reset": "", "bytopic": "all", "topic": "topic", "outputs": 1, "x": 980, "y": 960, "wires": [ [ "61eb1e60369d2d43" ] ], "icon": "font-awesome/fa-battery-2" }, { "id": "459d750ce708b4bc", "type": "link in", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "link in 28", "links": [ "77b21e4f95016374" ], "x": 95, "y": 740, "wires": [ [ "d6d78e34d7018a9e" ] ] }, { "id": "f78b9b4cdf67b280", "type": "moment", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "Month", "topic": "", "input": "", "inputType": "date", "inTz": "Europe/London", "adjAmount": 0, "adjType": "days", "adjDir": "add", "format": "MMM", "locale": "en_gb", "output": "", "outputType": "msg", "outTz": "Europe/London", "x": 410, "y": 900, "wires": [ [ "4f9ef9d03f9ee24e" ] ] }, { "id": "952a87f0d3ac76c5", "type": "victron-output-ess", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "service": "com.victronenergy.settings", "path": "/Settings/CGwacs/BatteryLife/MinimumSocLimit", "serviceObj": { "service": "com.victronenergy.settings", "name": "ESS System Settings", "paths": [ { "path": "/Settings/CGwacs/AcPowerSetPoint", "type": "integer", "name": "Grid set-point (W)", "writable": true }, { "path": "/Settings/CGwacs/BatteryLife/MinimumSocLimit", "type": "integer", "name": "Minimum Discharge SOC (%)", "writable": true }, { "path": "/Settings/CGwacs/BatteryLife/State", "type": "enum", "name": "ESS state", "enum": { "1": "BatteryLife enabled (GUI controlled)", "2": "Optimized Mode /w BatteryLife: self consumption", "3": "Optimized Mode /w BatteryLife: self consumption, SoC exceeds 85%", "4": "Optimized Mode /w BatteryLife: self consumption, SoC at 100%", "5": "Optimized Mode /w BatteryLife: SoC below dynamic SoC limit", "6": "Optimized Mode /w BatteryLife: SoC has been below SoC limit for more than 24 hours. Charging the battery (5A)", "7": "Optimized Mode /w BatteryLife: Inverter/Charger is in sustain mode", "8": "Optimized Mode /w BatteryLife: recharging, SoC dropped by 5% or more below the minimum SoC", "9": "'Keep batteries charged' mode is enabled", "10": "Optimized mode w/o BatteryLife: self consumption, SoC at or above minimum SoC", "11": "Optimized mode w/o BatteryLife: self consumption, SoC is below minimum SoC", "12": "Optimized mode w/o BatteryLife: recharging, SoC dropped by 5% or more below minimum SoC" }, "writable": true }, { "path": "/Settings/CGwacs/Hub4Mode", "type": "enum", "name": "ESS mode", "enum": { "1": "Optimized mode or 'keep batteries charged' and phase compensation enabled", "2": "Optimized mode or 'keep batteries charged' and phase compensation disabled", "3": "External control" }, "writable": true }, { "path": "/Settings/CGwacs/MaxDischargePower", "type": "integer", "name": "Max inverter power (W)", "writable": true }, { "path": "/Settings/CGwacs/MaxFeedInPower", "type": "integer", "name": "Maximum System Grid Feed In (W)", "remarks": "

Applies to DC-coupled and AC-coupled feed-in.

", "writable": true }, { "path": "/Settings/CGwacs/OvervoltageFeedIn", "type": "enum", "name": "Feed excess DC-coupled PV into grid", "enum": { "0": "Don’t feed excess DC-tied PV into grid", "1": "Feed excess DC-tied PV into the grid" }, "writable": true }, { "path": "/Settings/CGwacs/PreventFeedback", "type": "enum", "name": "Don’t feed excess AC-coupled PV into grid", "enum": { "0": "Feed excess AC-tied PV into grid", "1": "Don’t feed excess AC-tied PV into the grid" }, "writable": true }, { "path": "/Settings/SystemSetup/MaxChargeCurrent", "type": "float", "name": "Charge current limit (A)", "writable": true } ] }, "pathObj": { "path": "/Settings/CGwacs/BatteryLife/MinimumSocLimit", "type": "integer", "name": "Minimum Discharge SOC (%)", "writable": true }, "initial": "", "name": "ESS Min SOC Set", "x": 1250, "y": 1020, "wires": [] }, { "id": "ecfc6114a646a313", "type": "victron-output-ess", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "service": "com.victronenergy.settings", "path": "/Settings/CGwacs/BatteryLife/State", "serviceObj": { "service": "com.victronenergy.settings", "name": "ESS System Settings", "paths": [ { "path": "/Settings/CGwacs/AcPowerSetPoint", "type": "integer", "name": "Grid set-point (W)", "writable": true }, { "path": "/Settings/CGwacs/BatteryLife/MinimumSocLimit", "type": "integer", "name": "Minimum Discharge SOC (%)", "writable": true }, { "path": "/Settings/CGwacs/BatteryLife/State", "type": "enum", "name": "ESS state", "enum": { "1": "BatteryLife enabled (GUI controlled)", "2": "Optimized Mode /w BatteryLife: self consumption", "3": "Optimized Mode /w BatteryLife: self consumption, SoC exceeds 85%", "4": "Optimized Mode /w BatteryLife: self consumption, SoC at 100%", "5": "Optimized Mode /w BatteryLife: SoC below dynamic SoC limit", "6": "Optimized Mode /w BatteryLife: SoC has been below SoC limit for more than 24 hours. Charging the battery (5A)", "7": "Optimized Mode /w BatteryLife: Inverter/Charger is in sustain mode", "8": "Optimized Mode /w BatteryLife: recharging, SoC dropped by 5% or more below the minimum SoC", "9": "'Keep batteries charged' mode is enabled", "10": "Optimized mode w/o BatteryLife: self consumption, SoC at or above minimum SoC", "11": "Optimized mode w/o BatteryLife: self consumption, SoC is below minimum SoC", "12": "Optimized mode w/o BatteryLife: recharging, SoC dropped by 5% or more below minimum SoC" }, "writable": true }, { "path": "/Settings/CGwacs/Hub4Mode", "type": "enum", "name": "ESS mode", "enum": { "1": "Optimized mode or 'keep batteries charged' and phase compensation enabled", "2": "Optimized mode or 'keep batteries charged' and phase compensation disabled", "3": "External control" }, "writable": true }, { "path": "/Settings/CGwacs/MaxDischargePower", "type": "integer", "name": "Max inverter power (W)", "writable": true }, { "path": "/Settings/CGwacs/MaxFeedInPower", "type": "integer", "name": "Maximum System Grid Feed In (W)", "remarks": "

Applies to DC-coupled and AC-coupled feed-in.

", "writable": true }, { "path": "/Settings/CGwacs/OvervoltageFeedIn", "type": "enum", "name": "Feed excess DC-coupled PV into grid", "enum": { "0": "Don’t feed excess DC-tied PV into grid", "1": "Feed excess DC-tied PV into the grid" }, "writable": true }, { "path": "/Settings/CGwacs/PreventFeedback", "type": "enum", "name": "Don’t feed excess AC-coupled PV into grid", "enum": { "0": "Feed excess AC-tied PV into grid", "1": "Don’t feed excess AC-tied PV into the grid" }, "writable": true }, { "path": "/Settings/SystemSetup/MaxChargeCurrent", "type": "float", "name": "Charge current limit (A)", "writable": true } ] }, "pathObj": { "path": "/Settings/CGwacs/BatteryLife/State", "type": "enum", "name": "ESS state", "enum": { "1": "BatteryLife enabled (GUI controlled)", "2": "Optimized Mode /w BatteryLife: self consumption", "3": "Optimized Mode /w BatteryLife: self consumption, SoC exceeds 85%", "4": "Optimized Mode /w BatteryLife: self consumption, SoC at 100%", "5": "Optimized Mode /w BatteryLife: SoC below dynamic SoC limit", "6": "Optimized Mode /w BatteryLife: SoC has been below SoC limit for more than 24 hours. Charging the battery (5A)", "7": "Optimized Mode /w BatteryLife: Inverter/Charger is in sustain mode", "8": "Optimized Mode /w BatteryLife: recharging, SoC dropped by 5% or more below the minimum SoC", "9": "'Keep batteries charged' mode is enabled", "10": "Optimized mode w/o BatteryLife: self consumption, SoC at or above minimum SoC", "11": "Optimized mode w/o BatteryLife: self consumption, SoC is below minimum SoC", "12": "Optimized mode w/o BatteryLife: recharging, SoC dropped by 5% or more below minimum SoC" }, "writable": true }, "initial": "", "name": "ESS Charge Mode", "x": 1250, "y": 840, "wires": [] }, { "id": "6cd9fbba64ed1ef6", "type": "link in", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "link in 29", "links": [ "606181d0995a3938" ], "x": 95, "y": 900, "wires": [ [ "50dbeb70a1175629" ] ] }, { "id": "f2b0f7ba788ab79b", "type": "moment", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "Month", "topic": "", "input": "", "inputType": "date", "inTz": "Europe/London", "adjAmount": 0, "adjType": "days", "adjDir": "add", "format": "MMM", "locale": "en_gb", "output": "", "outputType": "msg", "outTz": "Europe/London", "x": 410, "y": 1060, "wires": [ [ "2bc44ba9baa3e9e0" ] ] }, { "id": "0486d3aafd519527", "type": "link in", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "link in 30", "links": [ "e2f3761012423b6a" ], "x": 95, "y": 1060, "wires": [ [ "e71e0bcce8930f1f" ] ] }, { "id": "50dbeb70a1175629", "type": "range", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "minin": "0", "maxin": "40000", "minout": "0", "maxout": ".5", "action": "clamp", "round": true, "property": "payload", "name": "20 - 40kw = Mid SOC", "x": 240, "y": 900, "wires": [ [ "f78b9b4cdf67b280" ] ] }, { "id": "e71e0bcce8930f1f", "type": "range", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "minin": "40000", "maxin": "2000000", "minout": "0", "maxout": ".5", "action": "clamp", "round": true, "property": "payload", "name": "> 40kw = Low SOC", "x": 230, "y": 1060, "wires": [ [ "f2b0f7ba788ab79b" ] ] }, { "id": "87e0a7645d276afb", "type": "trigger", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "Set SOC 75%", "op1": "75", "op2": "15", "op1type": "num", "op2type": "num", "duration": "290", "extend": false, "overrideDelay": false, "units": "min", "reset": "", "bytopic": "all", "topic": "topic", "outputs": 1, "x": 980, "y": 1000, "wires": [ [ "61eb1e60369d2d43" ] ], "icon": "font-awesome/fa-battery-2" }, { "id": "4f9ef9d03f9ee24e", "type": "switch", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "Season Split (1) Winter (2) Spring/Autumn (3) Summer", "property": "payload", "propertyType": "msg", "rules": [ { "t": "regex", "v": "Jan|Feb|Nov|Dec", "vt": "str", "case": false }, { "t": "regex", "v": "Mar|Apr|Sep|Oct", "vt": "str", "case": false }, { "t": "regex", "v": "May|Jun|Jul|Aug", "vt": "str", "case": false } ], "checkall": "true", "repair": false, "outputs": 3, "x": 340, "y": 960, "wires": [ [ "a02e26737e8d4a9c" ], [ "87e0a7645d276afb" ], [ "a319b3a1bd539543" ] ] }, { "id": "2bc44ba9baa3e9e0", "type": "switch", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "Season Split (1) Winter (2) Spring/Autumn (3) Summer", "property": "payload", "propertyType": "msg", "rules": [ { "t": "regex", "v": "Jan|Feb|Nov|Dec", "vt": "str", "case": false }, { "t": "regex", "v": "Mar|Apr|Sep|Oct", "vt": "str", "case": false }, { "t": "regex", "v": "May|Jun|Jul|Aug", "vt": "str", "case": false } ], "checkall": "true", "repair": false, "outputs": 3, "x": 340, "y": 1120, "wires": [ [ "5361b5132ae8510e" ], [ "a319b3a1bd539543" ], [ "e17d83f97adc7295" ] ] }, { "id": "a319b3a1bd539543", "type": "trigger", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "Set SOC 65%", "op1": "65", "op2": "15", "op1type": "num", "op2type": "num", "duration": "290", "extend": false, "overrideDelay": false, "units": "min", "reset": "", "bytopic": "all", "topic": "topic", "outputs": 1, "x": 980, "y": 1040, "wires": [ [ "61eb1e60369d2d43" ] ], "icon": "font-awesome/fa-battery-2" }, { "id": "e17d83f97adc7295", "type": "trigger", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "Set SOC 45%", "op1": "45", "op2": "15", "op1type": "num", "op2type": "num", "duration": "290", "extend": false, "overrideDelay": false, "units": "min", "reset": "", "bytopic": "all", "topic": "topic", "outputs": 1, "x": 980, "y": 1120, "wires": [ [ "61eb1e60369d2d43" ] ], "icon": "font-awesome/fa-battery-2" }, { "id": "e62ab0e17b6badce", "type": "trigger", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "Set SOC 55%", "op1": "55", "op2": "15", "op1type": "num", "op2type": "num", "duration": "290", "extend": false, "overrideDelay": false, "units": "min", "reset": "", "bytopic": "all", "topic": "topic", "outputs": 1, "x": 980, "y": 1080, "wires": [ [ "61eb1e60369d2d43" ] ], "icon": "font-awesome/fa-battery-2" }, { "id": "eac55f87bb4f470c", "type": "comment", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "(3) Dependant on SOC requirement, the ESS state is set by season and resets after a 4hr 50min delay", "info": "", "x": 430, "y": 660, "wires": [] }, { "id": "61eb1e60369d2d43", "type": "function", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "ESS Set", "func": "flow.set('ESS.Charge', \"\")\nflow.set('ESS.Set', msg.payload);\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 1240, "y": 960, "wires": [ [ "952a87f0d3ac76c5" ] ], "icon": "node-red/file-in.svg" }, { "id": "766de8375ae3806b", "type": "function", "z": "5042e496e3bb2cb7", "g": "416efad388f85db0", "name": "ESS Charge", "func": "flow.set('ESS.Set',\"\");\nflow.set('ESS.Charge', \"Keep Charged\");\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 1250, "y": 780, "wires": [ [ "ecfc6114a646a313" ] ], "icon": "node-red/file-in.svg" }, { "id": "59af4d6b567841f0", "type": "link out", "z": "5042e496e3bb2cb7", "g": "0169c507ea4f38a3", "name": "link out 17", "mode": "link", "links": [ "37dd47c111e38eb0" ], "x": 865, "y": 560, "wires": [] }, { "id": "37dd47c111e38eb0", "type": "link in", "z": "5042e496e3bb2cb7", "g": "52dd229ad312e8ba", "name": "link in 31", "links": [ "59af4d6b567841f0" ], "x": 595, "y": 1280, "wires": [ [ "724a330f2bd7d00b" ] ] }, { "id": "897ed0abe133a28b", "type": "comment", "z": "5042e496e3bb2cb7", "g": "0169c507ea4f38a3", "name": "N.B. 20 min delay fires at 00.05, 80 min delay fires at 01.05", "info": "", "x": 790, "y": 420, "wires": [] }, { "id": "b80bba99fd534e7a", "type": "comment", "z": "5042e496e3bb2cb7", "g": "52dd229ad312e8ba", "name": "N.B. 60sec delay is to ensure email is complied on latest flow set.", "info": "", "x": 770, "y": 1320, "wires": [] } ]