Starting with Node-Red on Victron [Guide]

Victron’s GX devices have a firmware ~large version for the VenusOS devices. These come with Node-Red which you can use to control things and also has a dashboard.
Let’s see how you can get started with it.

First you need to install the ~large version of the firmware. It’s build by Victron but is not supported officially. Follow Victron’s guide to install (item 3) the ~large firmware and Enable Node-Red under the Venus OS Large features image

Now open your web browser to http://venus.local:1880/ and you will see Node-Red.

On the left (red) you will find all the nodes. You can drag and drop these nodes onto the Flow in the middle (green).
Nodes that have a small grey square on the left can receive an input, while a grey square on the right are the node’s output. You drag and drop the output square onto an input square to link them.

To use the dashboard and create a simple State Of Charge display, we first need to install it. Click the hamburger menu top right and then Manage palette.
Under the Install tab search for node-red-dashboard and click install. This will add new nodes to the node list (left).
Under the Victron Energy nodes, drag and drop the Battery Monitor node image onto the Flow, and under the Dashboard section drag and drop the Gauge node image node to the Flow.

Double click on the Battery Monitor node in the flow to edit it. Your Battery Monitor from your VenusOS should already be selected, but under Measurement select the State of charge (%) property and also give it a nice label (Done to complete)

Then double click on the Gauge node to edit it as well. The Dashboard nodes require a Group and a group must be on a Tab. For now you need to know that these just help in the display of the items, so without going into detail just add a new ui group by clicking on the pencil icon image to create a Battery group, and add the Battery group to a new ui tab by clicking that pencil icon image and creating the Home tab (keep it enabled and visible). Click Done twice (on the Tab and the Group) to get back to the Gauge.

Set the Gauge’s label to SOC% , the units to %, the range to min=0, max=100, Name to System SOC % and save with Done

To link Victron’s Battery SOC% node to the SOC% Gauge you drag and drop the grey output (right side) to the grey input (left side).
Click the Deploy button to run this flow.

The Dashboard is located at http://venus.local:1880/ui/ and show the Home tab with the Battery group and SOC% gauge.


Well done, thanks Louis.


Thanks Louis
Any chance you or someone else can help with the steps for Pi setup when Node Red is on a another Pi. I have a Cerbo. I have tried but break my Node Red setup ;(

Why don’t you just use the Victron ~large firmware. It’s all set up and linked and runs on your Cerbo

I have a Pi4 running all my bits (nodered, HA) at the moment and don’t want to add extra to the Cerbo.

Try the install section here

Man , I am itching how much is a Venus going for these days? Is trade-ins considered ?

Just received this via email.

Maybe you can get a good price. I cant seem to upload it, not a supported format, but happy to email to whomever wants it.

I am running an external node red on my laptop fed from the rpi3.
Still fine-tuning the pv and grid divert functions.

1 Like

Here is the complete json flow link if anyone is interested in using or improving it.
It uses mqtt and the “artless gauge” which will need to be downloaded in the node red palette.

1 Like

So at last I ventured into NodeRED on the Cerbo, as it is all contained in one spot.

Man, I would be annoyed if the Firmware upgrades and NodeRED gets “lost”. It seems though, on Rel Candidate v2.90~14 onwards, that it is not the case.

@GVC , your link above to your Dashboard is next. :wink:

First I wanted to just get three things done:

  1. Optimale Panels usage = set the inverter max to what the panels can do, using the battery as the setpoint to measure. Because we are in Cpt and have weather.
  2. Increase the SOC slowly during the day, to optimize evening use. Because we are in Cpt and have weather.
  3. Set the inverter to i.e. 600watts at 6pm to run through the night till the sun takes over. Less strain on system.

Set Inverter watts to Panel max:

Increase the SOC during the day for evening use:

Set the inverter for evening use:

1 Like

Must say, from where I started: Victron Cronjobs

To HomeAssistant … o yeah, it broke again after updating, so it is going to go. Why? Victron Cerbo updates spoils one ito reliability even when running on “cutting edge” firmware like Release Candidate releases. Cudo’s to @plonkster and Co.

So HA is to be replaced with Ubuntu 20.4 on Hyper-V (I see there is now a Win10 Ubuntu version) running (with help to setup) NodeRED + Graphana.

Ubuntu is going to run the Automations coming like geyser control via cell app as well as keeping track of the BMS data … IF all plans play out. Got gatvol of people asking me, “Daaaaad … what is the geyser temp? Must we switch it on?”

Why Hyper-V some may wonder? Cause one can make a damn fast backup/restore of the entire machine for when I break things, not if, when …

Hence also the split with Victron stuff running on Victron platform, home automation stuff on home automation dedicated setup, which not only “protects me from myself”, it also is simpler when stuff runs on the same hardware already running stuff 24/7/365.

1 Like


Updated to latest Vernus Release Candidate, and Nodered was all still there. Obviously one must make backups, but they did it … YES!!!

I see you, and I raise you configurability per month of the year, and adjustments to minimum SoC based on the time of the day relative to sunrise and sunset. :wink:

Here’s the JavaScript for the “Calculate Minimum SoC” function node:

//Calculates the minimum SoC ESS setting. The strategy is to set a low minimum SoC just
//before sunrise, ramping it up to a higher minimum SoC just before sunset to leave enough
//margin for overnight power failures.

//-----------Configuration start-------------

//The daytime minimum SoC for the first of each month
const dayTimeMinimumSoCByMonth = [
    20, //1 jan 
    20, //1 feb
    20, //1 mar
    20, //1 apr
    20, //1 may
    25, //1 jun
    35, //1 jul
    25, //1 aug
    20, //1 sep
    20, //1 oct
    20, //1 nov
    20 //1 dec

//The nighttime minimum SoC for the first of each month
const nightTimeMinimumSoCByMonth = [
    40, //1 jan 
    40, //1 feb
    40, //1 mar
    40, //1 apr
    40, //1 may
    45, //1 jun
    55, //1 jul
    45, //1 aug
    40, //1 sep
    40, //1 oct
    40, //1 nov
    40 //1 dec

//The number of hours before sunrise from which the day time SoC applies
const sunriseMarginHours = 3;

//The maximum number of hours over which the minimum SoC is ramped up before sunset
const rampUpHours = 4;

//The number of hours before sunset by which the ramp-up must be finished
const sunsetMarginHours = 2;

//The desired margin between the current SoC and the minimum SoC to allow for some 
//discharge during the ramp-up if the ramp-up can be done faster than rampUpHours
const dischargeMargin = 0;

//-----------Configuration end-------------

//The SoC setting interval in %
const minimumSoCInterval = 5;

//The sunrise hour on the first of each month
const sunriseHourByMonth = [
    5.60, //1 jan 
    6.08, //1 feb
    6.52, //1 mar
    6.93, //1 apr
    7.32, //1 may
    7.68, //1 jun
    7.85, //1 jul
    7.62, //1 aug
    7.05, //1 sep
    6.35, //1 oct
    5.73, //1 nov
    5.43 //1 dec

//The sunset hour on the first of each month
const sunsetHourByMonth = [
    19.98, //1 jan 
    19.83, //1 feb
    19.35, //1 mar
    18.65, //1 apr
    18.05, //1 may
    17.72, //1 jun
    17.77, //1 jul
    18.07, //1 aug
    18.43, //1 sep
    18.78, //1 oct
    19.22, //1 nov
    19.68 //1 dec

//The payload is the current SoC
currentSoC = msg.payload;

var currentDate = new Date();
var currentYear = currentDate.getFullYear();
var currentMonth = currentDate.getMonth(); //month is 0-based
var currentDay = currentDate.getDate(); //day is 1-based
var currentHour = currentDate.getHours() + currentDate.getMinutes() / 60;

var nextMonth = (currentMonth + 1) % 12; //month is 0-based

//day 0 is the last day of the previous month
var daysInCurrentMonth = new Date(currentYear, nextMonth, 0).getDate();

//perform a straight line interpolation of the sunrise and sunset times between months
var thisMonthFraction = (daysInCurrentMonth - currentDay + 1) / daysInCurrentMonth;
var nextMonthFraction = 1 - thisMonthFraction;
var sunriseHour = sunriseHourByMonth[currentMonth] * thisMonthFraction
  + sunriseHourByMonth[nextMonth] * nextMonthFraction;
var sunsetHour = sunsetHourByMonth[currentMonth] * thisMonthFraction
  + sunsetHourByMonth[nextMonth] * nextMonthFraction;

//The minimum SoC values during the day and night
var dayTimeMinimumSoC = dayTimeMinimumSoCByMonth[currentMonth] * thisMonthFraction
  + dayTimeMinimumSoCByMonth[nextMonth] * nextMonthFraction;
var nightTimeMinimumSoC = nightTimeMinimumSoCByMonth[currentMonth] * thisMonthFraction
  + nightTimeMinimumSoCByMonth[nextMonth] * nextMonthFraction;

//Round the minimum SoC values to the nearest interval
dayTimeMinimumSoC = Math.round(dayTimeMinimumSoC / minimumSoCInterval) * minimumSoCInterval;
nightTimeMinimumSoC = Math.round(nightTimeMinimumSoC / minimumSoCInterval) * minimumSoCInterval;

//The hour just before sunrise when the low minimum SoC is set
var daytimeSoCStartHour = sunriseHour - sunriseMarginHours;

//The hour when ramping up of the minimum SoC starts
var minimumSoCRampStartHour = sunsetHour - sunsetMarginHours - rampUpHours;

//Default to the night time minimum SoC
var minimumSoC = nightTimeMinimumSoC;

//Is the current hour just before sunrise?
if (currentHour >= daytimeSoCStartHour) 
    //Before the ramp-up time?
    if (currentHour < minimumSoCRampStartHour)  
        //Before the ramp-up, so use the daytime minimum SoC
        minimumSoC = dayTimeMinimumSoC;
        //After the start of ramp-up to the nighttime minimum SoC
        //Calculate the ramp-up fraction
        var rampFraction = (currentHour - minimumSoCRampStartHour) / rampUpHours;
        //Calculate the ramped up minimum SoC
        minimumSoC = dayTimeMinimumSoC + (nightTimeMinimumSoC - dayTimeMinimumSoC) * rampFraction;
        //If the current SoC already exceeds the calculated minimum, use the current SoC
        //with a margin to allow for some discharge during the ramp-up
        minimumSoC = Math.max(minimumSoC, currentSoC - dischargeMargin);

        //Cap the calculated value at the nighttime minimum SoC
        minimumSoC = Math.min(minimumSoC, nightTimeMinimumSoC);


//Round the minimum SoC down to the nearest multiple of 5%
minimumSoC = Math.floor(minimumSoC / minimumSoCInterval) * minimumSoCInterval;

msg.debugInfo = [
    "fraction of month passed = " + nextMonthFraction,
    "sunrise hour = " + sunriseHour,
    "sunset hour = " + sunsetHour,
    dayTimeMinimumSoC + "% SoC from hour " + daytimeSoCStartHour,
    "SoC ramp-up to " + nightTimeMinimumSoC + "% from hour " + minimumSoCRampStartHour 
        + " to hour " + (sunsetHour - sunsetMarginHours),
    "current hour = " + currentHour,
    "current SoC = " + currentSoC,
    "calculated minimum SoC = " + minimumSoC + "%"

msg.payload = minimumSoC;

return msg;

Note the sunrise and sunset times are for Somerset West.


:rofl: Well played.

Question … what happens when weather enters the equation?

Cause my Min SOC, is driven by “weather” … the part of “Optimal Panel Usage”.

Edit: And Hysteresis, when you increase the SOC I don’t want the system to be charging 3% upwards before “settling” back to powering the house.

To sort Hysteresis, this works:
At 100% SOC, I set it to “Keep Charged”, so that the house gets all the power, no battery used, cause in the evenings I offset the 100% SOC charged, to also keep LS at bay.

Weather is a tricky one. I’ve found that weather forecasts are rarely accurate and detailed enough to the point that you could transpose them to reasonably accurate insolation forecasts. I found a weather-based insolation forecast input for Node-RED online, but the service is not free. Not knowing how accurate it is I didn’t pursue it any further.

I have settled on leaving a 30% SoC safety margin overnight and a 10% safety margin during daytime in summer, and slightly more in winter. Extended power failures here in Somerset West are rare, so I only need to cover for loadshedding. Dropping the safety margin just before sunrise means I use my batteries fully every day.

I no longer have to worry about loadshedding notifications and manually adjusting minimum SoC all the time, so it is working really well for me.

I have a fairly large battery, so charge/discharge bounce around the minimum SoC on bad weather days happens slowly enough to not be a problem. There’s a “dischargeMargin” configuration setting in the script to add some hysteresis, but I’ve found that I don’t actually need to use it.

1 Like

There are free API’s.


Having been at this issue now for years, checking the battery draw, we found, is the most accurate way to handle bad weather. No prediction, no API, no guessing.

The inverter wattage control is mainly there to not let the system get “stuck” on a SOC like say 20%, some sun, charges to 24%, discharge to 20%, enters hysteresis, uses all the panels and/or Eskom to get back to 23%, discharges again … the “stuck” part I see.

Creeping the SOC up came because of days with clouds moving overhead. Clouds move past, feed the house charge the batts, clouds overhead, drop the inverter watts based on battery draw, all the time increasing the SOC if possible whilst avoiding hysteresis.

If there is good weather, none of the above is needed obviously.

Example of why, on bad weather days like today, with 5.25kw panels, I throttle the inverter max.

Now the batts get it all as it would make no difference for the house loads.


1 Like

My SoC is currently bouncing around 20%. During the course of the afternoon Node-RED will slowly force it up to 40% and then drop it back to 20% tomorrow morning. I know LFP batteries don’t like to be kept at a low SoC for extended periods, but what constitutes an “extended period”? When the weather clears by Friday it should hit 100% again.

Obviously this bounce around 20% is not ideal either, but how bad is it really?

So the question I am asking is: If I let it bounce around 20% for a couple of bad weather days, am I shortening the life of my batteries to a significant degree?

We used to say every 7 days lead acid banks must be at least once at 100%.

But that “bouncing” is exactly why I did this move. With LS hovering around again, at least solar charge my batts now, even if it is slow.

Sat/Sun the weather clears a bit: Yr - -33.829, 18.611 - Long term forecast

1 Like