article

Dirk-Jan Faber (Victron Energy) avatar image
Dirk-Jan Faber (Victron Energy) posted

Node-RED VRM API and Dynamic ESS

Node-RED VRM API and Dynamic ESS

From today on, we’ve added some extra functionality to the VRM API, allowing a lot more flexibility when you are already using Dynamic ESS. In this article, I’ll guide you through some of the possibilities and how to set things up initially.

As I realise there is a lot of text below to wade through, let me first give you a glimpse in what you’ll be able to do with it before starting the deep dive into the subject.

Switch between trade and green mode

1718214250211.png

Adjust your formula, based on the time of day

1718214254846.png

Set restrictions based on the sell price

1718214260831.png

Of course you can adjust the flows to fit your personal installation and situation. In the comments below, you are invited to come up with your own ideas..

One precautionary thing to mind is that by changing the configuration of Dynamic ESS, the system will trigger re-scheduling (which can take up to 10 minutes) and won’t necessarily help you in saving most money on your energy bill. Leaving the system running is generally the best idea, as the system schedules up to 48 hours ahead. That being said, there are also cases where it will help you and we gladly give you the tools to experiment with.

Getting started with Node-RED

If you have never worked with Node-RED, I advise you start with either reading https://www.victronenergy.com/live/venus-os:large on Node-RED or by checking out our 3-part webinars on the subject, which are also linked from there.

In short, to get going with Node-RED and the VRM-API node, install the latest large beta firmware release on your GX device. And make sure that VRM-API version 0.2.5 is running. In case of troubles with that, check out the Troubleshooting / FAQ section at the end of this article.

1718214275025.png1718214284761.png

Implementing the flows

With the latest Venus OS beta releases, the VRM-API node became part of the large GX firmware image, meaning that you no longer need to install it via the palette manager yourself. The VRM API is a programmable interface into VRM, that allows you to query information from your installation(s) easily. On https://vrm-api-docs.victronenergy.com/#/ you can find all the related documentation, which you sometimes might need when using the node.

When installed correctly, the Node-RED system should provide you with this extra node, which is located in the Victron Energy menu and looks like this:

1718214302263.png

It has both an input as an output, meaning you can trigger it via an inject node to start querying the VRM API and you get the answer via the output. We will first start by retrieving the Dynamic ESS configuration for your site.

Once you dragged the first node to the canvas, double-click it. We want it to look like as below.

1718214312535.png

For the VRM part, you will need to create an API access token first. This can be done via VRM itself under Preferences -> Integrations -> Access tokens: https://vrm.victronenergy.com/access-tokens . Store this configuration as “VRM”. You’ll only need to do this once, this configuration can be used with other nodes and flows too.

For the API type, select Installations. And under Installation, select Get Dynamic ESS configuration. Note that there also is API type Dynamic ESS, but we don’t use that yet.

The VRM site id is the number that the API uses to identify which site to query. It is the number you also see in the URL when you are on the VRM dashboard of your site. So make sure that you have your own number there (your access token is restricted to only allow access to your own site id).

1718214325431.png

Under Installation select Get Dynamic ESS configuration and check the Store the response in the global context? checkbox. Hook this up to an inject node on the input side and a debug node on the output side and deploy the flow. It should look like this:

1718214333950.png

If you trigger the flow, the debug tab will show you all of the configuration information of your Dynamic ESS system. It looks something like this:

1718214339571.png

So it gives you everything you filled out in the Dynamic ESS settings on VRM. The checkbox to store the answer into context takes care of also saving this information under the global context with the path `installations["dynamic-ess-settings"]["274468”]`. If you need to read more about working with contexts, check out the official documentation on that: https://nodered.org/docs/user-guide/context

While this is already handy, the true power comes in the ability to change these settings at will. This can be done by selecting Modify Dynamic ESS configuration under Installation:

1718214348408.png

There are a few things to mind when modifying the configuration. First of all, the system expects a JSON formatted string. So you need to set the `msg.payload` to type JSON.

Then the payload itself also needs to be JSON formatted, mainly meaning brackets around it and quotes around the fields.

1718214357329.png

That is basically it. When the code gets injected, the responding payload will contain the full adjusted configuration in its answer and update the context (if that has been checked) with the new values.

The logical next step is to adjust settings time based. Please don’t inject too often, as the system will need to re-calculate the full planned schedule after configuration changes. This can take up to 10 minutes. After changes the system will end up at the end of the queue again, so if you update too often, you might even end up in the situation where your system doesn’t get to the beginning of the queue and getting a fresh schedule.

So the best thing is to set the inject node to inject once at a specific time to set a value and at a later moment inject the alternate value you want the system to work with. As a payload, you will need to insert something like: `{"buyPriceFormula":"(p+0.13)*1.21”}` in one node and `{"buyPriceFormula":"(p+0.15)*1.21”}` in the other inject node.

1718214370712.png

Finally, for this article, let’s take a look at acting on the current sell price. This can be queried by a different VRM endpoint. Select API type Installations and Installation Installation stats, attribute Dynamic ESS. Configure the API node as follows:

1718214382128.pngThis only queries the info for the current hour, so the resulting answer can be connected to a function node to use the info from the first field in the answer:

                 
  1. let price = msg.payload.records.deGs[0][1]
  2. msg.payload = (price <= 0.0) ? 1 : 0
  3. let fill = 'red'
  4. let text = 'Nope, positive price'
  5. if (msg.payload) {
  6.   fill = 'green'
  7.   text = 'Yes! Negative price'
  8. }
  9. text += ': €' + price.toFixed(2)
  10. node.status({fill, shape: 'dot', text})
  11. return msg;


This checks the `msg.payload.records.deGs[0][1]` field for the price. If it is negative, it wil set the msg.payload to 1, otherwise to 0, which can be directly connected to a regular Victron node to disable feeding into the grid when the price is negative.

1718214395332.png

This about wraps it up for this article. I am sure there will be some comments and suggestions below.
Still keep in mind that on every change of the configuration, the whole schedule needs to be recalculated, which can cause a less than ideal schedule if the changes are abrupt or big.

Troubleshooting / FAQ

Q: I already have the victron-vrm-api node installed, how to remove that?

If you’ve already installed the Victron VRM-API before and then switch to the latest beta firmware, you can end up with 2 installations of the Victron VRM-API node on your system: one that comes with the firmware and one that you installed yourself. Even worse is that this isn’t shown clearly and the system won’t allow you to update to the node to the latest version.

The solution is to uninstall the manually installed version first. The most user-friendly way is to do this by switching to the official release of Venus first and removing it there from the palette.

Q: What does the VRM-API Dynamic ESS do?

It is an alternative implementation of the Node-RED node: https://flows.nodered.org/node/victron-dynamic-ess. It is very likely to get more attention in the future. Feel free to experiment with it and provide feedback in the comments below.

VRMNode-REDdynamic essapi
1718214250211.png (54.9 KiB)
1718214254846.png (61.7 KiB)
1718214260831.png (85.9 KiB)
1718214275025.png (80.9 KiB)
1718214284761.png (13.0 KiB)
1718214302263.png (10.3 KiB)
1718214312535.png (73.0 KiB)
1718214325431.png (21.8 KiB)
1718214333950.png (38.9 KiB)
1718214339571.png (244.2 KiB)
1718214348408.png (113.8 KiB)
1718214357329.png (27.9 KiB)
1718214370712.png (39.0 KiB)
1718214382128.png (61.8 KiB)
1718214395332.png (85.9 KiB)
4 comments
2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

givenmotorsport avatar image givenmotorsport commented ·

This is great thank you.

ive got node red to pull down my UK Agile prices, so I just need to format them correctly and I can push them to DESS every day at 4pm.

0 Likes 0 ·
andrii-podanenko avatar image andrii-podanenko commented ·

Finally I've found a time to record this @Dirk-Jan Faber (Victron Energy)

Using DESS to overcome blackouts and charge battery from excess solar

1719832879400.png

1719830265999.png

Let me know if I should provide more details



How I determine I have excess of solar on MultiRS + SmartSolar MPPT

1719829607022.png

var rs1_mppt_state=flow.get('rs1_mppt_state', 0);

var is_adjustable = flow.get('rs1_ac1in_is_adjustable', 0);

var large_battery_soc = flow.get('large_battery_soc', 90);

rs1_mppt_state = msg.payload;
flow.set('rs1_mppt_state', rs1_mppt_state);

if (is_adjustable != 0) {
    if (rs1_mppt_state === 1 || (large_battery_soc >=98.5 && rs1_mppt_state === 2 )) {
        // Enough PV, current limited
       return {payload:true}
    }
    if (rs1_mppt_state !== 1 && large_battery_soc < 92 && rs1_mppt_state !== 2) {
        // No PV
       return {payload:false}
    }
}


return msg;


This is how I'm creating Array of Buy/Sell prices from my local grid provider input

API call to Local Grid Provider

1719829774566.png

Code in next comment ( limitations )

0 Likes 0 ·
1719829607022.png (53.4 KiB)
1719832879400.png (254.1 KiB)
Dirk-Jan Faber (Victron Energy) avatar image Dirk-Jan Faber (Victron Energy) ♦♦ andrii-podanenko commented ·

This is truly awesome. I am happy that I've been able to assist you into levering the system to act like this.

1 Like 1 ·
andrii-podanenko avatar image andrii-podanenko andrii-podanenko commented ·

Code for processing input data from Local Grid provider

let hoursList = msg.payload.graphs.today.hoursList;

function formatHour(hour) {
    return (hour - 1).toString().padStart(2, '0') + ':00';
}

function getPrice(electricity) {
    switch (electricity) {
        case 0: return 4.32;
        case 1: return 60;
        case 2: return 30;
        default: return 0; 
    }
}

let schedule = [];
let currentPrice = null;
let currentStart = null;


for (let i = 0; i < hoursList.length; i++) {
    const hour = hoursList[i];
    const price = getPrice(hour.electricity);

    if (price !== currentPrice || i === hoursList.length - 1) {
        if (currentStart !== null) {
            schedule.push({
                from: formatHour(currentStart),
                to: formatHour(hour.hour), 
                price: currentPrice
            });
        }
        currentPrice = price;
        currentStart = hour.hour;
    }
}

if (schedule.length > 0 && schedule[schedule.length - 1].to === '23:00') {
    schedule[schedule.length - 1].to = '00:00';
}


newBuyPriceSchedule = [{
    days: [0,1,2,3,4,5,6], 
    schedule: schedule
}];


msg = {};

let newPrices = { 
    "buyPriceSchedule": JSON.stringify(newBuyPriceSchedule),
    "sellPriceSchedule": JSON.stringify(newBuyPriceSchedule)
};

msg.payload = {};


msg.payload = { ...newPrices }

return msg;


1719830139597.png

0 Likes 0 ·

Article

Contributors

dfaber contributed to this article