-
Notifications
You must be signed in to change notification settings - Fork 437
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New controller for flexibility trading with Levl Energy #2873
Conversation
remove physical soc bounds and target grid setpoint from config
LevlControlRequest
variables; fix efficiency calculation
…emove empty comments at line endings
handling in impl; move request handling to before_process_image event; clean up files
LastRequestTimestamp channel; add comments
can be analyzed in time db
well for realized battery value of last request
handleRequest; add logging and set log-level to debug; auto-formatting
calculation; fix swinging of remaining energy around zero;
Could you please ellaborate what the following means:
Which test scenarios did you execute and which OpenEMS test framework do you refer to? If you refer to the tests in |
@parapluplu Thanks for the question. Of course by "OpenEMS test framework" I meant the tests in BalancingImplTest using OpenEMS' own test framework "ControllerTest". It's described as a "generic test framework for OpenEMS". Since it tests the whole controller and multiple cycles, I mentioned it separately to differentiate between the single tested methods within ControllerEssBalancingImplTest. So yes, my description might be a bit misunderstood :-) We also tested the controller within our own development environment using several simulated OpenEMS edge instances. |
} | ||
|
||
//Just for testing | ||
public LevlControlRequest(int sellToGridLimitW, int buyFromGridLimitW, String levlRequestId, String timestamp, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
package level visibility should be good enough then, isn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
protected would even do. I adjusted this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
protected
is more than package level visibility, see https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
But protected
is good as well :)
import java.time.LocalDateTime; | ||
import java.util.Objects; | ||
|
||
public class LevlControlRequest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be good to put a version on this request, so it's easier to change the API version eventually
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. It's definitely something we'll add at a later date. For the beta it will be fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm okay with this approach, but it eases it if it's built in from the beginning
import java.time.LocalDateTime; | ||
import java.util.Objects; | ||
|
||
public class LevlControlRequest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the motivation to perform parts of the controlling via an external API and not within OpenEMS?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's about virtual power plants. I can imagine this being implemented within OpenEMS, with a virtual power plant coordinator running OpenEMS and multiple batteries running OpenEMS connected to the power plant. That’s the reason for my question.
This question isn’t intended to block or hinder the merge request; it’s simply out of curiosity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey guys, sorry for the late response. Levl enables battery owners to participate in the electricity market, making more efficient use of the batteries and reducing amortisation costs. At the same time, the electricity grid is relieved as electricity is bought when it is cheap (a lot of renewables energy in the grid) and sold when demand is high (coal and gas is needed).
Unfortunately, this is not quite so simple from a regulatory perspective, as battery storage systems behind-the-meter, especially with a primary use case such as optimising self-consumption, requires a distinction to be made between self-consumption and temporarily stored energy. This is the only way the energy supplier can correctly bill the quantities purchased. For this reason, we act as an aggregator with Levl.
In the end, this controller is comparable to various other controllers that make it possible to use an external service on the hardware and/or software side to optimise your own system.
To come back to your idea @parapluplu: If regulation were left out of the equation, that might be possible. But you would still need someone to run and manage this coordinator centrally. However, Levl's long-term goal is to enable all battery owners, regardless of the EMS used, to become part of a virtual power plant with their system.
At the moment we're working with a lot of battery owners who are using OpenEMS as well as working directly with Fenecon. For this reason we're looking forward to becoming part of the OpenEMS community :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey,
Just had a quick glance.
Here are my 2 cents, listed down below.
Also: Please consider to rename the package to something like
"io.openems.edge.controller.ess.balancing.levl"
or something like that,
instead of io.openems.levl.controller
Helps to identify and categorize the controller
|
||
protected static Clock clock = Clock.systemDefaultZone(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of useing Clock.systemDefaultZone(),
Consider useing the clock of the ComponentManager , since (all) components (FeneconBatteryExample), useing a clock, refer to the Clock of the ComponentManager (or a ClockProvider in general).
Consider applying this to the LevelControlRequest as well, if needed/possible.
Also: This allows compatability JUnit Tests and TimeLeapClock (example, FeneconBatteryTest).
private long applyBound(long power, long lowerBound, long upperBound) { | ||
return max(min(power, upperBound), lowerBound); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider useing the TypeUtils.fitWithin() methods
And introduce a new TypeUtils.fitWithin() method returning and useing long values.
@Designate(ocd = Config.class, factory = true) | ||
@Component(name = "Controller.Levl.Symmetric.Balancing", immediate = true, configurationPolicy = ConfigurationPolicy.REQUIRE) | ||
@EventTopics({ EdgeEventConstants.TOPIC_CYCLE_BEFORE_PROCESS_IMAGE, EdgeEventConstants.TOPIC_CYCLE_AFTER_WRITE, }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CodeFormatting, See FeneconBatteryExample
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe a stupid question, but if checkstyle does not complain code formatting should be ok, shouldn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@parapluplu You are right. If checkstyle does not complain, the code formatting should be ok.
Regardless of this, using the code formatting like in FeneconBatteryExample has some advantages. For example, for me it took 2-5s to understand the configuration of the fenecon battery. In your code it took me 15-20s. This is, because it took me some time to mentally divide the lines into several lines. This is how may brain is trained (because of other OpenEMS code). Other developers may have the same problem.
As we all want to work efficiently on the same code base it would be nice if we format the code more or less identical.
And in the end this issue should be reflected by an updated set of checkstyle rules..
Hey @DerStoecki, thanks for your 2 cents and advice. I have implemented your notes into the controller. Especially the TimeLeapClock was new to me, so thank you very much. I think we will use this in a later version for some further testing. On the package renaming: We used io.openems.edge.levl.controller as the package name because we were inspired by other controllers like io.openems.edge.kostal.piko. |
Hi @DennisLevl, can you please allow Commits for me. This would allow me to effectively work on the PR. Thanks! |
Unfortunately, this does not work for forks owned by an org (in this case, levlenergy. See https://github.com/orgs/community/discussions/5634). However, I have added you to the fork as a member. |
Codecov ReportAttention: Patch coverage is ❌ Your patch status has failed because the patch coverage (73.37%) is below the target coverage (75.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## develop #2873 +/- ##
=============================================
+ Coverage 56.65% 56.74% +0.09%
- Complexity 10164 10255 +91
=============================================
Files 2360 2365 +5
Lines 99894 100292 +398
Branches 7223 7248 +25
=============================================
+ Hits 56582 56896 +314
- Misses 41239 41309 +70
- Partials 2073 2087 +14 |
I did a detailed review and code cleanups/stylings. I had to do some (possibly) breaking changes. Unit-Tests are still working, but I was not able to do a real test. Please @friends from Levl, test again and suggest changes if required. |
Adds new controller for flexibility trading with Levl Energy
General Information
This pull request introduces a new controller that enables OpenEMS and Fenecon customers to trade their flexibility using the Levl Energy platform. This functionality is currently in the beta stage and will be refined based on feedback and additional testing.
How it works
This controller receives charging/discharging instructions from Levl Energy and executes these taking into account local optimization and various constraints (such as state of charge, grid limits, etc.).
Testing
The business logic has been covered by unit tests. The controller has also been tested using multiple test scenarios within the OpenEMS test framework to ensure functionality and reliability.
Please review the changes and provide feedback. Once approved, this will be ready for merge. Thank you in advance!