In addition, historical data of your system is not enough. You would also need historical forecast data. Coming up with an optimal strategy if you know all the data is trivial ![]()
The highest priority would not even be a simulator actually, that would be to create shared platform to bring all these individual DESS initiatives together in a structural way that allows us to compare functionality, performance, pro’s and con’s and above all a consistent way of defining a good requirements specification to tie it all together with. I’m not the best person for implementing the platform technicalities but I do have the systems engineering experience to look into the requirements specification and it’s subsequent derivatives (for a first impression look up v-model, not that that is the holy grail but it’s a start) Or check this: Volere Requirements Specification Template – Volere Requirements
The hardest part of creating a good solution is to come up with the correct problem definition, one that does not implicitly dictates any specific solutions upfront. That’s harder than you might think actually.
But first we would need a place to collaborate, could be on this forum, could be elsewhere, as long as it allows a structural improvement over all the ad hoc discussion scattered all over the place we are now having.
Thanks @bartm for highlighting the issue of large batteries draining over time. Turns out my assumption was wrong. A longer forecasting window will cause the battery to drain, only at a slower rate. This is unwanted behavior:
I overhauled the battery state of energy logic to be able to modify the objective function. The solver is now reimbursed for the energy that it has at the end. But I have found this behavior to be very difficult to steer using a min function or quantile(buy_price, 20%).
For this case a quantile(buy_price, 30%) + cycle_cost works:
But I imagine the current implementation of a quantile is very depended, on the number of cheap and expensive hours. What does seem to work is median(buy_price) * inverter_efficiency + cycle_cost, It captures the true replenishment cost, but I do not know how well it works in edge cases. For now I leave it, but maybe in the future a min SoE is needed to have the battery stay in a certain region for large systems.
Hi @nortciv. Nice simulations! Setting the terminal energy valuation to the minimum should have only an effect if there is excess solar. It will never buy energy from the grid to store in the battery because it’s not worth is (taking into account efficiency). If you increase it, the optimization should buy from grid at times where the buy price is lower than the chosen value.
During winter, when the risk of having a full battery due to large solar production is small, you could even argue that a fixed price makes sense: This should translate into “if the price is below x, buy from grid to use at a later time” behaviour. (note: in Belgium there are a lot of taxes, so a huge gap between buy and sell price. In practice thes means that there are almost no trading opportunities).
I’ve played around with creating a linear programming optimization myself and used a javascript solver (actually it’s webassembly). This allowed me to create a simple html front-end to play with the settings and get a feel for the effects of config changes. I’ve deployed it using github pages at https://optivolt.bartm.be/
I’ve loaded a simple demo config, but you can easily tweak the values. All changes will be stored in local storage in the browser. You can also share a config with someone using the share link. If I find time next weekend, I might try to fetch the predictions and prices from the Victron API.
Wow, great work @bartm! I am absolutely stunned by how nicely your solution works (and looks)! The overall structure of both our solvers is largely the same (HiGHS, constraints, etc.). But the use of WASM is amazing! It plays much nicer with a possible future Node-RED solver block. I had thought about writing the solver in JavaScript myself, but my lack of JS programming experience forced me to prototype in python. Seeing how far OptiVolt is coming along makes me wonder if it would be more worthwhile for me to help you out sometime developing OptiVolt? I do have a few questions:
In the future, would it also be possible to create individual Node-RED dess building blocks? A LinearSolver block and a StrategyParser block could allow victron users to detach from the discontinued VRM Node-RED implementation while allowing them to build a custom DESS tailored to their need. I am not saying you should do this, I was just wondering if the use of WASM would allow for this?
Do you plan to implement some risk reducing logic in the solver? For example, I achieved this by taking prediction variance into account and view whatever solar is within the variance (error bars) as risky solar. In the objective function, I added the cost for this risky solar: self.price_sell + self.cycle_cost/2 + self.alpha_risk * (self.price_buy - self.price_sell. Alpha risk being between 0 and 1 just means: should risky solar be expensive or cheap. I am aware that this solution works best if the buy price and sell price are close to each other. If there is a large gap because of taxes, alpha needs to be really small to get the same behavior. Nevertheless, it helps users like me who have a small battery and way too much solar. But also users who have uncertain solar.
What size forecasting window are you hoping to work with? Keep it at 24 hours or more of a strategic multi-day planner? I can imagine that the ev-solver needs more than one day.
Anyway, If you want my help, just say so. I would gladly share my code/insights or invest some time in development/testing ![]()
Hi @nortciv
At the moment this is just a fun hobby project for me. I’m absolutely open to discussing ideas, exchanging code, point people in the right direction, etc. However, I’m not looking to make this a community project, manage it and provide support (I already have to do that at my job
). For example, I want to have the freedom to make changes that might only be applicable to my installation.
Converting your Python code to JavaScript should be straightforward. The hard part is coming up with the equations and you already have those. Generating them in the right format is something that ChatGPT should be able to do. Especially if you already have Python code. In my repo this code can be found at optivolt/src/build-lp.js at main · bmesuere/optivolt · GitHub
I have zero experience with Node-RED, so I’m afraid I can’t answer that question. I have no idea if it allow running WASM code. I was thinking of running this locally using a lightweight webserver in a docker container myself. I would imagine that Node-RED has support for calling REST APIs.
Implementing a risk factor is something that might make sense for PV production. Alternatively, we could adjust the predictions based on the measured data of that day. Or just try to improve the predictions ![]()
I was also thinking about reducing the risk that occurs before a price peak when the actual load turned out to be higher than expected resulting in an empty battery and expensive grid usage. A mitigation might be taking the time of the morning and evening price peak, and setting the minimal soc 5-10% higher for the timestamp 30 minutes before the peak. This would allow for a bit of additional buffer.
For now, my biggest unknown is how to convert the optimal plan to something operational. Which API’s can we call? Use the VRM api? MQTT? Something else? Steering on expected SOC is not enough, you also need to set a strategy, but I don’t know if that’s possible.
HAve you guys seem ‘DAO’? This sound like something similar.
Won’t be long and DESS may be DOA, as in classical first-mover disadvantage (risk). Think Betamax, Nokia, Kodak. Open sourcing venusOS was a genius move, keeping the scheduler proprietary seems odd to me, same goes for the centralized storage of life performance data.
I’ve pushed an update that allows you to enter a token and fetch data from the VRM API (Everything is handled client side so your token is safe. There is only communication between your browser and Victron.) If you have DESS configured, it can autofill some settings and it also fetches forecasts and prices. The graphs were updated to work with actual times instead of generic time slots.
note: the victron forecast data is still hour-based. I split them over 4 equal15-minute intervals. For the PV data, it might make sense to do a smarter split.
The generated plan almost perfectly matches what I see in DESS, so it’s a good starting point for making tweaks to the rules if I/we spot situations where we think DESS should behave differently.
I just stumbled upon this branch by chance and find it extremely interesting. I’m not a programmer, but I’ve been an enthusiastic DESS user for about two years, through all the ups and downs. I think you’re currently working on one of the most critical aspects of the system: limiting the forecast period and dealing with energy surpluses at the end of the forecast period. These are two problems that I’m currently trying to resolve by adjusting the minimum Soc. Please continue working on this.
I think
and the entire development team should follow your work with great interest, if they haven’t already.
I read “Designed for integration with Home Assistant or custom dashboards” as if you were building a Home Assistant integration and publishing it that way. But looking back, I may have read it a bit too quickly. I also don’t want to be responsible for controlling other people’s systems in that way, that’s why I mentioned Node-RED.
If the solver could just be a node people can import, they could use it to build their own DESS. Node-RED runs on the Cerbo and has easy access to system parameters. The maintenance burden, forecasting implementation, and most importantly the responsibility would then lie with the end user. Plus, they could build in their own system-specific quirks.
Just thinking out loud, I’ll maybe look into it when I have some time next week. Anyway, I really like your implementation @bartm ![]()
I haven’t written any code yet to translate from the solver to strategies. However, here are some helpful sources: all the ModbusTCP registers are available (MQTT control is also possible and generally easier), and Victron’s own strategy interpretation is open-source and available in the file dynamicess.py
Hi Bartm,
I’m getting a CORS error on the VRM API requests when trying with the token.
Hmm, I hadn’t noticed before because I used localhost myself. I just now added a small self-hosted proxy that forwards results and circumvents the error. I’ll later make the proxy configurable, so you can use your own.



