Create a project line on battery SOC in the Advanced section of VRM and New Grid setpoint shortcut

In air traffic control, our radar has a predict timeline, 2, 5 and 10 minutes. If the aircraft maintains its current heading and speed the line projects where it would be at the selected time in the future. This enables confict detection and small changes to avoid confliction.

I would like to see the same in the SOC chart in VRM this would enable, should everything stay pretty much the same, the user to adjust discharge to arrive at a specified SOC at a specific time. The units should be perhaps 1, 2, 3, and 4 hours or perhaps ther could be a dropdown menu for up to say 6 hours?

I would also find it useful to have a shortcut button to Console, Settings, ESS, Grid setpoint. I visit this several times a day to fine tune battery discharge and export. Its approximately 25 button presses to acess this point.

Thanks

Have you tried out DynamicESS?

It will do that “fine tuning” every 15 minutes, 24h a day based on an “ideal” roadmap calculated according to your system state, prices and forecast.
It then will also show you a fully forecasted SOC-line in the VRM graph, not just the “heading” based on momentary values:

This can easily be done via Node Red. I use a Node Red flow to set the “grid setpoint” according to current SOC, minSOC and solar yield forecast. The solar forecast can be easily queried via the VRM-API node.

I have 5.4 kWp installed solar power, and have just a MP2-3000 which can deliver not more than 2.4 kW. To be able to feed in all excess solar power to the grid I use my 15 kWh battery as a buffer and feed in from battery over night.

Edit: The flow uses a global variable “global.vrmSiteId” to hold your individual VRM Site Id. This Id should not be published. Use an extra flow to set this global variable according to your individual valie.

[
   {
       "id": "cecfa760836ea314",
       "type": "inject",
       "z": "1459d4d7551ca112",
       "name": "execute_every_1h",
       "props": [
           {
               "p": "payload"
           },
           {
               "p": "topic",
               "vt": "str"
           }
       ],
       "repeat": "3600",
       "crontab": "",
       "once": true,
       "onceDelay": "0.5",
       "topic": "",
       "payload": "",
       "payloadType": "date",
       "x": 170,
       "y": 140,
       "wires": [
           [
               "83e1731df2cb4a4f",
               "4509958d36211e97",
               "58bf60b68439ec53"
           ]
       ]
   },
   {
       "id": "83e1731df2cb4a4f",
       "type": "vrm-api",
       "z": "1459d4d7551ca112",
       "vrm": "cca5d0a225796a2b",
       "name": "forecast_today",
       "api_type": "installations",
       "idUser": "",
       "users": "",
       "idSite": "{{global.vrmSiteId}}",
       "installations": "stats",
       "attribute": "solar_yield_forecast",
       "stats_interval": "15mins",
       "show_instance": false,
       "stats_start": "bod",
       "stats_end": "eod",
       "use_utc": false,
       "gps_start": "",
       "gps_end": "",
       "widgets": "",
       "instance": "",
       "vrm_id": "",
       "country": "",
       "b_max": "",
       "tb_max": "",
       "fb_max": "",
       "tg_max": "",
       "fg_max": "",
       "b_cycle_cost": "",
       "buy_price_formula": "",
       "sell_price_formula": "",
       "green_mode_on": "",
       "feed_in_possible": "",
       "feed_in_control_on": "",
       "b_goal_hour": "",
       "b_goal_SOC": "",
       "store_in_global_context": false,
       "verbose": false,
       "x": 380,
       "y": 80,
       "wires": [
           [
               "b6d55740f5a71d7d"
           ]
       ]
   },
   {
       "id": "9a0e3d6e3a04fda2",
       "type": "change",
       "z": "1459d4d7551ca112",
       "name": "Korrekturfaktor",
       "rules": [
           {
               "t": "set",
               "p": "forecast_tomorrow",
               "pt": "flow",
               "to": "0.9*payload.totals.solar_yield_forecast",
               "tot": "jsonata"
           },
           {
               "t": "set",
               "p": "payload",
               "pt": "msg",
               "to": "forecast_tomorrow",
               "tot": "flow"
           }
       ],
       "action": "",
       "property": "",
       "from": "",
       "to": "",
       "reg": false,
       "x": 600,
       "y": 200,
       "wires": [
           [
               "bc15c2dd4db42c81"
           ]
       ]
   },
   {
       "id": "b6d55740f5a71d7d",
       "type": "change",
       "z": "1459d4d7551ca112",
       "name": "Korrekturfaktor",
       "rules": [
           {
               "t": "set",
               "p": "forecast_today",
               "pt": "flow",
               "to": "0.9*payload.totals.solar_yield_forecast",
               "tot": "jsonata"
           },
           {
               "t": "set",
               "p": "payload",
               "pt": "msg",
               "to": "forecast_today",
               "tot": "flow"
           }
       ],
       "action": "",
       "property": "",
       "from": "",
       "to": "",
       "reg": false,
       "x": 600,
       "y": 80,
       "wires": [
           [
               "ce10e89d55ef11a6"
           ]
       ]
   },
   {
       "id": "53ec77049a4d0973",
       "type": "victron-input-battery",
       "z": "1459d4d7551ca112",
       "service": "com.victronenergy.battery/512",
       "path": "/Soc",
       "serviceObj": {
           "service": "com.victronenergy.battery/512",
           "name": "Batterie"
       },
       "pathObj": {
           "path": "/Soc",
           "type": "float",
           "name": "State of charge (%)"
       },
       "name": "currentSOC",
       "onlyChanges": true,
       "roundValues": "0",
       "x": 190,
       "y": 300,
       "wires": [
           [
               "e2356f404424d7e5"
           ]
       ]
   },
   {
       "id": "f2a2c02c8c22031a",
       "type": "inject",
       "z": "1459d4d7551ca112",
       "name": "execute-oncedaily",
       "props": [
           {
               "p": "payload"
           },
           {
               "p": "topic",
               "vt": "str"
           }
       ],
       "repeat": "",
       "crontab": "11 00 * * *",
       "once": true,
       "onceDelay": "0.6",
       "topic": "",
       "payload": "",
       "payloadType": "date",
       "x": 170,
       "y": 400,
       "wires": [
           [
               "07f9999728e60555"
           ]
       ]
   },
   {
       "id": "4509958d36211e97",
       "type": "vrm-api",
       "z": "1459d4d7551ca112",
       "vrm": "cca5d0a225796a2b",
       "name": "forecast_tomorrow",
       "api_type": "installations",
       "idUser": "",
       "users": "",
       "idSite": "{{global.vrmSiteId}}",
       "installations": "stats",
       "attribute": "solar_yield_forecast",
       "stats_interval": "15mins",
       "show_instance": false,
       "stats_start": "bot",
       "stats_end": "86400",
       "use_utc": false,
       "gps_start": "",
       "gps_end": "",
       "widgets": "",
       "instance": "",
       "vrm_id": "",
       "country": "",
       "b_max": "",
       "tb_max": "",
       "fb_max": "",
       "tg_max": "",
       "fg_max": "",
       "b_cycle_cost": "",
       "buy_price_formula": "",
       "sell_price_formula": "",
       "green_mode_on": "",
       "feed_in_possible": "",
       "feed_in_control_on": "",
       "b_goal_hour": "",
       "b_goal_SOC": "",
       "store_in_global_context": false,
       "verbose": false,
       "x": 390,
       "y": 200,
       "wires": [
           [
               "9a0e3d6e3a04fda2"
           ]
       ]
   },
   {
       "id": "07f9999728e60555",
       "type": "function",
       "z": "1459d4d7551ca112",
       "name": "minSOC_saison",
       "func": "// Aktuelles Datum abrufen\n// const d = new Date();\n// let cmonth = d.getMonth(); // 0-11\n// Monat um 1 erhöhen, um 1 bis 12 zu erhalten:\n// cmonth++;\n// let currentdate = flow.get('cdatearray');\n// let cmonth = currentdate[0];\n// let cmonth = flow.get('cmonth');\n\nlet d = new Date();\nlet cmonth = 1 + d.getMonth();\nlet cday = d.getDate();\n\n// Berechnung minSOC nach Jahreszeit (Nordhalbkugel)\n// Winter 45%: November (11), Dezember (12), Januar (1), Februar (2)\n// Frühling, Herbst 30%: März (3), April (4), September (9), Oktober (10)\n// Sommer 20%: Mai (5), Juni (6), Juli (6), August (8)\n\nswitch (cmonth) {\n  case 1:\n      minSOC = 40;\n      break;\n  case 2:\n      minSOC = 40;\n      break;\n  case 3:\n      if (cday < 15) {\n          minSOC = 35;\n      } else if (true) {\n          minSOC = 30;\n      }\n      break;\n  case 4:\n      minSOC = 25;\n      break;\n  case 5:\n      minSOC = 20;\n      break;\n  case 6:\n      minSOC = 20;\n      break;\n  case 7:\n      minSOC = 20;\n      break;\n  case 8:\n      minSOC = 20;\n      break;\n  case 9:\n      minSOC = 25;\n      break;\n  case 10:\n      if (cday < 15) {\n          minSOC = 30;\n      } else if (true) {\n          minSOC = 35;\n      }\n      break;\n  case 11:\n      minSOC = 40;\n      break;\n  case 12:\n      minSOC = 40;\n      break;\n  default:\n      minSOC = 40;\n}\n\n// als flow-variablen setzen, um sie weiterhin nutzen zu können\nflow.set ('minSOC' , minSOC);\n\n// Nachricht setzen\nmsg.payload = minSOC;\n// Optional: minSOC auch als Payload für Schalter senden\n// msg.minSOC = minSOC; \n\nreturn msg;\n",
       "outputs": 1,
       "timeout": 0,
       "noerr": 0,
       "initialize": "",
       "finalize": "",
       "libs": [],
       "x": 380,
       "y": 400,
       "wires": [
           [
               "9b375ebef613ee7c"
           ]
       ]
   },
   {
       "id": "ce10e89d55ef11a6",
       "type": "debug",
       "z": "1459d4d7551ca112",
       "name": "forecast_today",
       "active": true,
       "tosidebar": false,
       "console": false,
       "tostatus": true,
       "complete": "payload",
       "targetType": "msg",
       "statusVal": "payload",
       "statusType": "auto",
       "x": 800,
       "y": 80,
       "wires": []
   },
   {
       "id": "bc15c2dd4db42c81",
       "type": "debug",
       "z": "1459d4d7551ca112",
       "name": "forecast_tomorrow",
       "active": true,
       "tosidebar": false,
       "console": false,
       "tostatus": true,
       "complete": "payload",
       "targetType": "msg",
       "statusVal": "payload",
       "statusType": "auto",
       "x": 810,
       "y": 200,
       "wires": []
   },
   {
       "id": "9b375ebef613ee7c",
       "type": "victron-output-ess",
       "z": "1459d4d7551ca112",
       "service": "com.victronenergy.settings",
       "path": "/Settings/CGwacs/BatteryLife/MinimumSocLimit",
       "serviceObj": {
           "service": "com.victronenergy.settings",
           "name": "Venus settings"
       },
       "pathObj": {
           "path": "/Settings/CGwacs/BatteryLife/MinimumSocLimit",
           "type": "integer",
           "name": "Minimum Discharge SOC (%)",
           "mode": "both"
       },
       "initial": 20,
       "name": "set-MinSOC",
       "onlyChanges": false,
       "x": 590,
       "y": 400,
       "wires": []
   },
   {
       "id": "58bf60b68439ec53",
       "type": "vrm-api",
       "z": "1459d4d7551ca112",
       "vrm": "cca5d0a225796a2b",
       "name": "forecast_restofday",
       "api_type": "installations",
       "idUser": "",
       "users": "",
       "idSite": "{{global.vrmSiteId}}",
       "installations": "stats",
       "attribute": "solar_yield_forecast",
       "stats_interval": "15mins",
       "show_instance": false,
       "stats_start": "0",
       "stats_end": "eod",
       "use_utc": false,
       "gps_start": "",
       "gps_end": "",
       "widgets": "",
       "instance": "",
       "vrm_id": "",
       "country": "",
       "b_max": "",
       "tb_max": "",
       "fb_max": "",
       "tg_max": "",
       "fg_max": "",
       "b_cycle_cost": "",
       "buy_price_formula": "",
       "sell_price_formula": "",
       "green_mode_on": "",
       "feed_in_possible": "",
       "feed_in_control_on": "",
       "b_goal_hour": "",
       "b_goal_SOC": "",
       "store_in_global_context": false,
       "verbose": false,
       "x": 390,
       "y": 140,
       "wires": [
           [
               "4e3e0b44fd6a8109"
           ]
       ]
   },
   {
       "id": "4e3e0b44fd6a8109",
       "type": "change",
       "z": "1459d4d7551ca112",
       "name": "Korrekturfaktor",
       "rules": [
           {
               "t": "set",
               "p": "forecast_restofday",
               "pt": "flow",
               "to": "0.9*payload.totals.solar_yield_forecast",
               "tot": "jsonata"
           },
           {
               "t": "set",
               "p": "payload",
               "pt": "msg",
               "to": "forecast_restofday",
               "tot": "flow"
           }
       ],
       "action": "",
       "property": "",
       "from": "",
       "to": "",
       "reg": false,
       "x": 600,
       "y": 140,
       "wires": [
           [
               "4d003d0b786480b7"
           ]
       ]
   },
   {
       "id": "4d003d0b786480b7",
       "type": "debug",
       "z": "1459d4d7551ca112",
       "name": "forecast_restofday",
       "active": true,
       "tosidebar": false,
       "console": false,
       "tostatus": true,
       "complete": "payload",
       "targetType": "msg",
       "statusVal": "payload",
       "statusType": "auto",
       "x": 810,
       "y": 140,
       "wires": []
   },
   {
       "id": "2cc09b109a7328c4",
       "type": "inject",
       "z": "1459d4d7551ca112",
       "name": "execute-everyhour",
       "props": [
           {
               "p": "payload"
           }
       ],
       "repeat": "3600",
       "crontab": "",
       "once": true,
       "onceDelay": "0.6",
       "topic": "",
       "payload": "20",
       "payloadType": "num",
       "x": 180,
       "y": 480,
       "wires": [
           [
               "5096be16a5dae81c"
           ]
       ]
   },
   {
       "id": "5096be16a5dae81c",
       "type": "function",
       "z": "1459d4d7551ca112",
       "name": "calc_gridsetpoint",
       "func": "let forecast_today = flow.get ('forecast_today');\nlet forecast_tomorrow = flow.get ('forecast_tomorrow');\nlet currentsoc = flow.get ('currentsoc');\nlet minSOC = flow.get ('minSOC') || 20;\nlet missingload = flow.get ('missingload') || 0;\nlet fcrest = flow.get ('flow.forecast_restofday');\n\nlet d = new Date();\nlet cmonth = 1 + d.getMonth();\nlet cday = d.getDate();\nlet chour = d.getHours();\nlet cminute = d.getMinutes();\n\nlet gridsetpoint = 20;\n\nif (cmonth === 5 || cmonth === 6 || cmonth === 7 || cmonth === 8) {\n    if ((17 <= chour) && (chour < 20)) { // zwischen 17 und 20 Uhr voll laden\n        gridsetpoint = -20;\n    } else if ((20 <= chour) && (45 < currentsoc) && (8000 < forecast_tomorrow)) {\n        gridsetpoint = -1000;\n    } else if ((chour <= 7) && (35 < currentsoc) && (8000 < forecast_today)) {\n        gridsetpoint = -1000;\n    } else if ((7 < chour) && (chour < 14) && (60 < currentsoc) && (6000 < fcrest)) {\n        gridsetpoint = -1400;\n    } else if ((14 <= chour) && (chour < 17) && (80 < currentsoc)  && (6000 < fcrest)) {\n        gridsetpoint = -1800;\n    } else {\n        gridsetpoint = -20;\n    }\n} else if (cmonth === 4 || cmonth === 9) {\n    if ((16 <= chour) && (chour < 20)) { // zwischen 16 und 20 Uhr voll laden\n        gridsetpoint = -20;\n    } else if ((20 <= chour) && (55 < currentsoc) && (8000 < forecast_tomorrow)) {\n        gridsetpoint = -600;\n    } else if ((chour < 7) && (50 < currentsoc) && (8000 < forecast_today)) {\n        gridsetpoint = -600;\n    } else if ((7 <= chour) && (chour < 12) && (50 < currentsoc) && (8000 < fcrest)) {\n        gridsetpoint = -800;\n    } else if ((12 <= chour) && (chour < 16) && (80 < currentsoc) && (6000 < fcrest)) {\n        gridsetpoint = -1000;\n    } else {\n        gridsetpoint = -20;\n    }\n} else if (cmonth === 3 || cmonth === 10) {\n    if ((16 <= chour) && (chour < 20)) { // zwischen 16 und 20 Uhr voll laden\n        gridsetpoint = -20;\n    } else if ((20 <= chour) && (60 < currentsoc) && (10000 < forecast_tomorrow)) {\n        gridsetpoint = -600;\n    } else if ((chour <= 7) && (55 < currentsoc) && (10000 < forecast_today)) {\n        gridsetpoint = -600;\n    } else if ((7 < chour) && (chour < 12) && (60 < currentsoc) && (10000 < fcrest)) {\n        gridsetpoint = -800;\n    } else if ((12 <= chour) && (chour < 16) && (80 < currentsoc) && (6000 < fcrest)) {\n        gridsetpoint = -1000;\n    } else {\n        gridsetpoint = -20;\n    }\n} else if (true) {\n        gridsetpoint = 20;\n    }\n\nflow.set ('gridsetpoint' , gridsetpoint);\n\nmsg.payload = gridsetpoint;\nreturn msg;",
       "outputs": 1,
       "timeout": 0,
       "noerr": 0,
       "initialize": "",
       "finalize": "",
       "libs": [],
       "x": 390,
       "y": 480,
       "wires": [
           [
               "62cff6b823712e53"
           ]
       ]
   },
   {
       "id": "62cff6b823712e53",
       "type": "victron-output-ess",
       "z": "1459d4d7551ca112",
       "service": "com.victronenergy.settings",
       "path": "/Settings/CGwacs/AcPowerSetPoint",
       "serviceObj": {
           "service": "com.victronenergy.settings",
           "name": "Venus settings"
       },
       "pathObj": {
           "path": "/Settings/CGwacs/AcPowerSetPoint",
           "type": "integer",
           "name": "Grid set-point (W)",
           "mode": "both"
       },
       "initial": 20,
       "name": "set-GridSetpoint",
       "onlyChanges": false,
       "x": 600,
       "y": 480,
       "wires": []
   },
   {
       "id": "e2356f404424d7e5",
       "type": "function",
       "z": "1459d4d7551ca112",
       "name": "set_flowSOC",
       "func": "let currentSOC = msg.payload;\nlet minSOC = flow.get ('minSOC') || 40;\nlet diffSOC = 100 - currentSOC;\nconst fullbattery = 14000;\nlet missingload = diffSOC * fullbattery / 100;\n\nflow.set ('missingload', missingload);\nflow.set ('currentSOC', currentSOC);\n\nmsg.payload = currentSOC;\nreturn msg;",
       "outputs": 1,
       "timeout": 0,
       "noerr": 0,
       "initialize": "",
       "finalize": "",
       "libs": [],
       "x": 370,
       "y": 300,
       "wires": [
           []
       ]
   },
   {
       "id": "7e94cf2671a9b2dd",
       "type": "function",
       "z": "1459d4d7551ca112",
       "name": "calc_gridsetpoint_demo",
       "func": "let forecast_today = 11000; //= flow.get ('forecast_today');\nlet forecast_tomorrow = 11000; // = flow.get ('forecast_tomorrow');\nlet currentsoc = 65; // = flow.get ('currentsoc');\nlet minSOC = 20; // flow.get ('minSOC') || 20;\nlet missingload = 8000; //flow.get ('missingload') || 0;\nlet fcrest = 11000; // flow.get ('flow.forecast_restofday');\n\n// let d = new Date();\nlet cmonth = 3; // 1 + d.getMonth();\n// let cday = d.getDate();\nlet chour = 6; // = d.getHours();\n// let cminute = d.getMinutes();\n\nlet gridset = 19;\n\nif (cmonth === 5 || cmonth === 6 || cmonth === 7 || cmonth === 8) {\n    if ((17 <= chour) && (chour < 20)) { // zwischen 17 und 20 Uhr voll laden\n        gridsetpoint = -20;\n    } else if ((20 <= chour) && (45 < currentsoc) && (8000 < forecast_tomorrow)) {\n        gridsetpoint = -1000;\n    } else if ((chour <= 7) && (35 < currentsoc) && (8000 < forecast_today)) {\n        gridsetpoint = -1000;\n    } else if ((7 < chour) && (chour < 14) && (60 < currentsoc) && (6000 < fcrest)) {\n        gridsetpoint = -1400;\n    } else if ((14 <= chour) && (chour < 17) && (80 < currentsoc)  && (6000 < fcrest)) {\n        gridsetpoint = -1800;\n    } else {\n        gridsetpoint = -20;\n    }\n} else if (cmonth === 4 || cmonth === 9) {\n    if ((16 <= chour) && (chour < 20)) { // zwischen 16 und 20 Uhr voll laden\n        gridsetpoint = -20;\n    } else if ((20 <= chour) && (55 < currentsoc) && (8000 < forecast_tomorrow)) {\n        gridsetpoint = -600;\n    } else if ((chour < 7) && (50 < currentsoc) && (8000 < forecast_today)) {\n        gridsetpoint = -600;\n    } else if ((7 <= chour) && (chour < 12) && (50 < currentsoc) && (8000 < fcrest)) {\n        gridsetpoint = -800;\n    } else if ((12 <= chour) && (chour < 16) && (80 < currentsoc) && (6000 < fcrest)) {\n        gridsetpoint = -1000;\n    } else {\n        gridsetpoint = -20;\n    }\n} else if (cmonth === 3 || cmonth === 10) {\n    if ((16 <= chour) && (chour < 20)) { // zwischen 16 und 20 Uhr voll laden\n        gridsetpoint = -20;\n    } else if ((20 <= chour) && (60 < currentsoc) && (10000 < forecast_tomorrow)) {\n        gridsetpoint = -600;\n    } else if ((chour <= 7) && (55 < currentsoc) && (10000 < forecast_today)) {\n        gridsetpoint = -600;\n    } else if ((7 < chour) && (chour < 12) && (60 < currentsoc) && (10000 < fcrest)) {\n        gridsetpoint = -800;\n    } else if ((12 <= chour) && (chour < 16) && (80 < currentsoc) && (6000 < fcrest)) {\n        gridsetpoint = -1000;\n    } else {\n        gridsetpoint = -20;\n    }\n} else if (true) {\n        gridsetpoint = 20;\n    }\n\n\nflow.set ('gridsetpoint' , gridsetpoint);\n\nmsg.payload = gridsetpoint;\nreturn msg;",
       "outputs": 1,
       "timeout": 0,
       "noerr": 0,
       "initialize": "",
       "finalize": "",
       "libs": [],
       "x": 550,
       "y": 560,
       "wires": [
           [
               "315af0a55c88cad9"
           ]
       ]
   },
   {
       "id": "67156c8207c78082",
       "type": "inject",
       "z": "1459d4d7551ca112",
       "name": "Demo",
       "props": [
           {
               "p": "payload"
           },
           {
               "p": "topic",
               "vt": "str"
           }
       ],
       "repeat": "",
       "crontab": "",
       "once": false,
       "onceDelay": 0.1,
       "topic": "",
       "payload": "",
       "payloadType": "date",
       "x": 350,
       "y": 560,
       "wires": [
           [
               "7e94cf2671a9b2dd"
           ]
       ]
   },
   {
       "id": "315af0a55c88cad9",
       "type": "debug",
       "z": "1459d4d7551ca112",
       "name": "demo-gridsetpoint",
       "active": true,
       "tosidebar": false,
       "console": false,
       "tostatus": true,
       "complete": "payload",
       "targetType": "msg",
       "statusVal": "payload",
       "statusType": "auto",
       "x": 810,
       "y": 560,
       "wires": []
   },
   {
       "id": "2f5522e00a078a17",
       "type": "comment",
       "z": "1459d4d7551ca112",
       "name": "Description",
       "info": "Global variable:\n\nvrmSiteId = the individual VRM site id\n            I set this global variable in an extra flow\n            Never publish your VRM site id!\n\nFlow variables:\n\nUpdated every hour:\nforecast_today = VRM forecast for whole today\nforecast_tomorrow = VRM forecast for whole day tomorrow\nforecast_restofday = VRM forecast from now to end of day\n\nPermanently updated:\ncurrentSOC = the current SOC \nmissingload = load (in Wh) necessary for 100% SOC\n\nUpdated once daily:\nminSOC = minimal SOC for ESS, different for each month of the year\n\nUpdated every hour:\ngridsetpoint = Grid Setpoint, to enable grid-feed-in when more solar yield is expected than inverter power\n\nThe gridsetpoint is modified according to month (seasonal difference), hour (discharging full battery over night etc), current SOC and forecast_restofday\n\nThe calc_gridsetpoint_demo can be used to evaluate different settings according to a different system. The variables cmonth, cday, forecast_today, forecast_tomorrow, forecast_restofday, currentSOC, missingload can be set to the values to be tested. Just click on the inject node.",
       "x": 140,
       "y": 40,
       "wires": []
   },
   {
       "id": "cca5d0a225796a2b",
       "type": "config-vrm-api",
       "name": "SolarVorhersage"
   }
]

Hi @dognose , No I havent tried the dynamic ESS. I initially looked at the forecast solar when it first came out a few years ago and it was so innaccurate for our location that I was better off using my met training and local experience to forecast cloud cover. I haven’t revisited it to see if any improvements have been made.

Thanks for the suggestion.

Unfortunately @TomBerger , You’re way over my head. I’m trying to get someone local to give me a foot up on the way to HA but as for other programming ? The last bit of programming I did was in 1974 on a “portable” computer which came to a not nearby school in several boxes, allowing us to have a day trip out (after several days at our own school of BASIC training) to add 2 plus 2, using cards to input the information .. no keyboards in those days.

Home Assistant is on the cards, forgive the pun, for this coming winter.

Thanks for the reply

I started programming Node Red just 10 days ago. Really. This isn’t rocket science or anything like that.

Node Red comes with the Victron Venus OS large image.

:smile: Night scool next winter then.

That’s right. It’s not the programming that’s the problem, but translating what you have in your mind into some kind of flow.
It took me a full year to setup and debugging my flow. Another 6 months fine tuning.
Everything is working as it should I think. Untill a rare situation arrives and I can start debugging again.

2 Likes

Yes, of course. But you don’t start debugging and redesigning again because there is any need for it. You start again because it’s fun!

My very big problem is: my solar power system is now doing everything exactly as I ever expected. There’s nothing left for me to improve. And that’s a rather sad realization.