Skip to content

Implement SMA STP-10.0 SE Hybrid ESS#2618

Merged
sfeilmeier merged 8 commits intoOpenEMS:developfrom
opernikus-common:feature/sma-stp-10-hybrid
Dec 14, 2025
Merged

Implement SMA STP-10.0 SE Hybrid ESS#2618
sfeilmeier merged 8 commits intoOpenEMS:developfrom
opernikus-common:feature/sma-stp-10-hybrid

Conversation

@tsicking
Copy link
Copy Markdown
Contributor

Implementation of SMA STP 10.0 Hybrid ESS.
The implementation is split into Battery, Inverter and DC Charger. The inverter only works with that battery, but the implementation had to be split up as the devices use different Modbus Unit IDs.
The components are located in the existing bundle io.openems.edge.ess.sma. Note that the other packages were renamed to io.openems.edge.ess.sma.sunnyisland and io.openems.edge.ess.sma.enums.

@tsicking tsicking requested a review from clehne April 15, 2024 11:31
@github-actions
Copy link
Copy Markdown

Code Coverage

Copy link
Copy Markdown
Contributor

@clehne clehne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Locks good to me. Please see my comment.

- SinglePhaseEss
- ManagedSinglePhaseEss

== SMA STP 10.0 SE
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could name it "SMA STP 10.0 Smart Energy"

sma.applyPower(setActivePower, setReactivePower);
return;
}
this.logError(this.log, "Failed to run inverter. Battery is not SMA battery.");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove log output and replace with a new fault state channel, e.g. WRONG_BATTERY


@Override
public String debugLog() {
return "|L:" + this.getActivePower().asString(); //
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could consider using the method
Battery.generateDebugLog(this, this.stateMachine);
here

@sfeilmeier
Copy link
Copy Markdown
Contributor

Is this something you are actively working on? I believe (better) SMA support would be generally nice to have in OpenEMS.

Implementation of SMA STP 10.0 Hybrid ESS.
The implementation is split into Battery, Inverter and DC Charger. The inverter only works with that battery, but the implementation had to be split up as the devices use different Modbus Unit IDs.

It sounds like bad abstraction if they only work in this combination anyway. If Modbus Unit-ID is your only problem, we should be able to find an alternative - see e.g. https://github.com/OpenEMS/openems/blob/develop/io.openems.edge.ess.byd.container/src/io/openems/edge/ess/byd/container/Config.java#L23-L30

@tsicking
Copy link
Copy Markdown
Contributor Author

Is this something you are actively working on? I believe (better) SMA support would be generally nice to have in OpenEMS.

Implementation of SMA STP 10.0 Hybrid ESS.
The implementation is split into Battery, Inverter and DC Charger. The inverter only works with that battery, but the implementation had to be split up as the devices use different Modbus Unit IDs.

It sounds like bad abstraction if they only work in this combination anyway. If Modbus Unit-ID is your only problem, we should be able to find an alternative - see e.g. https://github.com/OpenEMS/openems/blob/develop/io.openems.edge.ess.byd.container/src/io/openems/edge/ess/byd/container/Config.java#L23-L30

Yes, we are actively working on this, and we have such an inverter in use on a productive system.
I agree that the abstraction is not very good, and I was trying to get around it too. We definitely need both Unit IDs. Under one unit ID (3 by default) you'll find a protocol needed for write access (similar to the one of ESS Sunny Island), and under the other unit ID (126 by default), there is a SunSpec protocol, as in the SMA PV inverter.
I couldn't find a way of having two unit IDs in one component, as the unit ID is part of the AbstractOpenemsModbusComponent. In the example you give, there are two different modbus bridges (so I assume two different IP addresses), but only one unit ID.
I was also thinking that instead of combining the inverter and the battery to a GenericManagedEss, you have a EssSma combining them, but in the end I didn't see the benefit of it.
I would be glad if you or anyone else has a suggestion of how to deal with different unit IDs in the same component. I saw at least two other modbus devices that use different unit IDs (though in both these cases, one unit ID can be ignored, as the registers are not too relevant).

Best regards,
Thomas

@codecov
Copy link
Copy Markdown

codecov bot commented Nov 4, 2024

Codecov Report

❌ Patch coverage is 67.15928% with 200 lines in your changes missing coverage. Please review.

Additional details and impacted files
@@              Coverage Diff              @@
##             develop    #2618      +/-   ##
=============================================
+ Coverage      59.45%   59.51%   +0.07%     
  Complexity       112      112              
=============================================
  Files           2914     2922       +8     
  Lines         125438   126028     +590     
  Branches        9392     9410      +18     
=============================================
+ Hits           74566    74995     +429     
- Misses         48038    48183     +145     
- Partials        2834     2850      +16     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@tsicking
Copy link
Copy Markdown
Contributor Author

tsicking commented Nov 4, 2024

Backported changes we had done, mainly:

  1. Adaption to new SunSpec implementation
  2. A "Smart Mode" similar to GoodWe was introduced

Regarding the problem with the two different Unit-IDs, I have a suggestion but neither time to implement it nor do I know if it's really a good idea. It is as follows: The Unit-ID should not be part of the Modbus component, but rather be part of the Modbus task, as it is really part of the request, like you see here. So the constructor of the FC3ReadRegistersTask for instance would not only have a start address, a priority and Modbus elements, but also a Unit-ID.
Now this would of course be a huge change in a very central component, but to me it would make a bit more sense this way.

@github-actions
Copy link
Copy Markdown

This PR has been automatically marked as stale due to inactivity. It will be closed in 7 days if no further activity occurs.

@github-actions github-actions bot added Stale and removed Stale labels Sep 19, 2025
@cb0s
Copy link
Copy Markdown

cb0s commented Dec 12, 2025

I would like to add a similar setup to my OpenEMS setup, so I wanted to ask what is missing for this PR to be merged, apart from additional test coverage. Maybe I could find the time to help.

# Conflicts:
#	io.openems.edge.ess.sma/readme.adoc
#	io.openems.edge.ess.sma/src/io/openems/edge/ess/sma/enums/OperatingModeForActivePowerLimitation.java
#	io.openems.edge.ess.sma/src/io/openems/edge/ess/sma/enums/OperationHealth.java
#	io.openems.edge.ess.sma/src/io/openems/edge/ess/sma/enums/PowerSupplyStatus.java
#	io.openems.edge.ess.sma/src/io/openems/edge/ess/sma/enums/SetControlMode.java
#	io.openems.edge.ess.sma/src/io/openems/edge/ess/sma/enums/SystemState.java
#	io.openems.edge.ess.sma/src/io/openems/edge/ess/sma/sunnyisland/Config.java
#	io.openems.edge.ess.sma/src/io/openems/edge/ess/sma/sunnyisland/EssSmaSunnyIsland.java
#	io.openems.edge.ess.sma/src/io/openems/edge/ess/sma/sunnyisland/EssSmaSunnyIslandImpl.java
#	io.openems.edge.ess.sma/src/io/openems/edge/sma/enums/OperatingModeForActivePowerLimitation.java
#	io.openems.edge.ess.sma/src/io/openems/edge/sma/enums/OperationHealth.java
#	io.openems.edge.ess.sma/src/io/openems/edge/sma/enums/PowerSupplyStatus.java
#	io.openems.edge.ess.sma/src/io/openems/edge/sma/enums/SetControlMode.java
#	io.openems.edge.ess.sma/src/io/openems/edge/sma/enums/SystemState.java
#	io.openems.edge.ess.sma/src/io/openems/edge/sma/sunnyisland/Config.java
#	io.openems.edge.ess.sma/src/io/openems/edge/sma/sunnyisland/EssSmaSunnyIsland.java
#	io.openems.edge.ess.sma/src/io/openems/edge/sma/sunnyisland/EssSmaSunnyIslandImpl.java
#	io.openems.edge.ess.sma/test/io/openems/edge/ess/sma/sunnyisland/EssSmaSunnyIslandImplTest.java
#	io.openems.edge.ess.sma/test/io/openems/edge/ess/sma/sunnyisland/MyConfig.java
#	io.openems.edge.ess.sma/test/io/openems/edge/sma/sunnyisland/EssSmaSunnyIslandImplTest.java
#	io.openems.edge.ess.sma/test/io/openems/edge/sma/sunnyisland/MyConfig.java
#	io.openems.edge.sma/bnd.bnd
#	io.openems.edge.sma/src/io/openems/edge/sma/ess/sunnyisland/Config.java
#	io.openems.edge.sma/src/io/openems/edge/sma/ess/sunnyisland/EssSmaSunnyIsland.java
#	io.openems.edge.sma/src/io/openems/edge/sma/ess/sunnyisland/EssSmaSunnyIslandImpl.java
#	io.openems.edge.sma/src/io/openems/edge/sma/ess/sunnyisland/enums/OperatingModeForActivePowerLimitation.java
#	io.openems.edge.sma/src/io/openems/edge/sma/ess/sunnyisland/enums/OperationHealth.java
#	io.openems.edge.sma/src/io/openems/edge/sma/ess/sunnyisland/enums/PowerSupplyStatus.java
#	io.openems.edge.sma/src/io/openems/edge/sma/ess/sunnyisland/enums/SetControlMode.java
#	io.openems.edge.sma/src/io/openems/edge/sma/ess/sunnyisland/enums/SystemState.java
#	io.openems.edge.sma/test/io/openems/edge/sma/ess/sunnyisland/EssSmaSunnyIslandImplTest.java
#	io.openems.edge.sma/test/io/openems/edge/sma/meter/shm20/MyConfig.java
Copy link
Copy Markdown
Contributor

@sfeilmeier sfeilmeier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Moved implementation to combined io.openems.edge.sma bundle
  • BREAKING CHANGE: unified factory PIDs

Everything should still work - but I cannot validate the implementation myself and the JUnit tests are very basic.

@sfeilmeier sfeilmeier merged commit d37666f into OpenEMS:develop Dec 14, 2025
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants