Connecting Kostal Piko PV inverter to OpenEMS

You’re mistaken — the line

org.jsoup:jsoup,\

is not wrong.

This is a valid and fully supported Maven coordinate syntax in Bndtools.

The colon (:slight_smile: does not make the dependency invalid. It simply tells Bndtools to resolve the library using Maven coordinates (groupId:artifactId), rather than as an OSGi bundle symbolic name.

Both notations are allowed and functionally correct:

org.jsoup → resolves by Bundle-SymbolicName in the OSGi repositories (e.g. bnd-cache, cnf/repo)

org.jsoup:jsoup → resolves by Maven coordinate through the configured BndPomRepository (e.g. Maven Central)

The error

org.jsoup:jsoup;version=0 Not found

does not indicate an invalid syntax — it simply means that Bndtools couldn’t find the artifact in the configured repositories.

That happens when:

the Maven repository (e.g. Maven Central) isn’t properly declared in cnf/build.bnd,

the POM index (pom-Maven Central.xml) hasn’t been generated or is outdated, or

you’re building offline with an empty cache.

So changing the line to org.jsoup,\ didn’t fix a syntax problem — it merely changed how Bndtools searches for the dependency.

The version without a colon works because jsoup already includes a valid Bundle-SymbolicName: org.jsoup in its manifest, allowing Bndtools to find it as an OSGi bundle in the cache.

To summarize:

> The problem isn’t with the : syntax — it’s with the missing Maven repository configuration.

org.jsoup:jsoup is completely correct when the environment is set up properly.

@Sn0w3y I just recognized another thing which puzzles me, maybe you have an idea about it:
Looking at todays history, there are no values for the Kostal Piko inverters:


This seems to be wrong, and displaying the graph of the inverters, I do see values (as well, as the live view showed values):

Is there some channel in the inverter missing to sum it up, or should that happen within the UI/influxDB?

Edit: I’m confused.
I have switched from influxdb (disabled component) to rrd4j (installed and enabled component) and after a reboot, no data was shown in the UI history.
Switching back (disabling the rrd4j component, enabling back the influxdb component) and rebooting again, the UI now shows half an hour of data saved to the rrd4j-file including the Kostal Piko inverter data (which was missing before), but no newer data after switching back to influxdb anymore is displayed in the UI history… (for any pv inverter)
Can someone give me some guidance? Thanks in advance!

Edit2: After deleting the rrd4j (instead of just disabling it), the data from the influxdb is shown again in the UI history (displaying half an hour gap, where rrd4j was active). And again the data of the Kostal Piko inverters is missing.

To summarize:

  • for switching a persistence backend (influxdbrrd4j) enabling and disabling the component seems to be ok for saving data to it, but the UI does not honor the enabled/disabled persistence component (maybe just reading from the last created persistence component?). @stefan.feilmeier is this worth a bug report? Seems a little counterintuitive to me at least. :slight_smile:
  • the Kostal Piko inverter seems to have an issue writing data to influxdb, but works fine with rrd4j. @Sn0w3y this seems to be a bug. Do you have an idea where to poke into the code to find the culprit?

system environment: official docker images, using influxdb v2

Is this the place to look at for the difference between Live and History view?

HISTORY in openems/ui/src/app/edge/history/common/production/flat/flat.html

@for (component of productionMeterComponents; track component; let i = $index) {
	<oe-flat-widget-line [name]="component.alias" [channelAddress]="component.id + '/ActiveProductionEnergy'"
		[converter]="CONVERT_TO_KILO_WATTHOURS">
...
@for (component of chargerComponents; track component) {
	<oe-flat-widget-line [name]="component.alias" [channelAddress]="component.id + '/ActualEnergy'"

vs.
LIVE in openems/ui/src/app/edge/live/common/production/flat/flat.html

@for (component of productionMeterComponents; track component; let i = $index) {
	<oe-flat-widget-line [name]="component.alias" [channelAddress]="component.id + '/ActivePower'"
		[converter]="CONVERT_WATT_TO_KILOWATT">
...
@for (component of chargerComponents; track component) {
	<oe-flat-widget-line [name]="component.alias" [channelAddress]="component.id + '/ActualPower'"

If I check the Channels through http://localhost:4200/device/0/settings/channels I see the following:

Fronius pvInverter0:
ActivePower: 665 W
ActiveProductionEnergy: 29320100 Wh_Σ

Kostal pvInverter12:
ActivePower: 817 W
ActiveProductionEnergy: 139324 Wh_Σ

While the ActivePower values fit to the LIVE display, the ActiveProductionEnergy values DON’T fit to HISTORY.
The mentioned [converter] don’t seem to do more than number formatting (if openems/ui/src/app/shared/utils/utils.ts is the right place to look). Thus they do not explain why the values of channel ActiveProductionEnergy do not match to the displayed numbers of HISTORY.

For the Kostal, the explanation on first glance could be simple: the values are just too small → therefore 0 kWh shown in HISTORY. But with manual calculation from ActiveProductionEnergy above I still get 139 kWh.

But for the Fronius this does not work: Why 2,4 kWh is shown in HISTORY??? I would say it should be 29320 kWh, converting manually from the value in ActiveProductionEnergy above…

Where is the error? Where do the displayed values in HISTORY come from?

InfluxDB does not seem to be the culprit.
It worked with RRD4j on my system (History showed values for the Kostal Piko pvInverters in the Production widget), but now it does not anymore… Same situation as with InfluxDB.

Very strange…

Through the InfluxDB Web-UI I could see that the data in the InfluxDB correspond to the values I got from the channels - makes sense to me.

But where do the values in the UI>HISTORY then come from?

It is getting even more strange. Apparently I still do not understand how the system really works.

First of all, the values are back with the RRD4j, as you can see on the screenshot below. I do not know why, nor what I changed to make that happen..

Fixing the conversion bug in the HTML-parser (missing kWh→Wh) of the Kostal Piko (see fixed Kostal Piko HTML parsing bug: kWh for Total Energy in HTML, instead of expected Wh in ActiveProductionEnergy by janklostermann · Pull Request #3465 · OpenEMS/openems · GitHub ) I got a weird effect:

For all the Kostal Piko pvinverters I suddenly got huge numbers in the History, as you can still see on the screenshot for e.g. Turnhalle3. As if representing directly the values from channel ActiveProductionEnergy as shown above, but without conversion from Wh to kWh.

The screenshot below I made after I did the following after this discovery:

  1. Reverting the above mentioned PR with the bugfix, compiling again, restarting Edge.
  2. Deleting the RRD4j from the config through the UI. After that history was not available anymore, as expected
  3. Reinstalling RRD4j though the UI and switching back to history
  4. In the first moment all Kostal Pikos had still these huge values, but then new data apparently arrived and some were updated, like Turnhalle1, to far smaller values. That’s the moment, when I made the screenshot.
  5. After a while, all Kostal Piko were then down to 0 or 0,1 kWh

What I do not get: Why does removing a factor of 1000 result in a display change of factor 1000000? What is there happening in between? And where in the code is this done?

After putting the bugfix from the PR back in, the huge numbers where back again.

Yes, thats expected. You read the WHOLE value for that day - so you see it on the first day, where it has been read.

The next day it should work again i guess.

Energy values in OpenEMS per definition have to be steadily increasing. The history then just shows the last value minus the first value of a Period. You need to let it run for an entire day without changing the factor to get proper values.

See this elder explanation:

Regards,
Stefan

1 Like

ok. I will wait.

But I do not understand your argumentation. I understand and agree, that energy values have to be steadily increasing, and the last value minus first value of a period need to be positive due to that. But I cannot see, how this explains why you need to wait for a whole day.
(I deleted history by deleting the data storage (I believe), and did not change the unit calculation factor afterwards.)

Does all this mean, before I have measurements for a whole year I will not be able to get reasonable energy values choosing the year overview (just to take the longest Period from the UI as example)?

That does not sound right. My thinking:
Consider I have started with a fresh RRD4j or InfluxDB.
After the first 2 energy values (the first calculated from minimum 2 power values over the time (kind of integral) between these values or read directly from the device, and then the next (read from the device or calculated accumulating)), I should already be able to provide a reasonable first value in the History’s energy production list, shouldn’t I?
Sure, only given from the start of history, which might be a few minutes ago, but nonetheless, not only after a full day…

Apparently the system does something else, which I still do not understand.

If I read the energy value from the device, I might read a first value that might have been accumulated over years. Thus only a (not available) “all time” period would be the right time span to show that value. All shorter periods of openEMS history storage can only talk about the time they know of (by the calculation last - first value) in their period. Either they simply start with the moment of the start of their history with what they calculate and display, or they should show “unknown” as they cannot resolve their full period due to the unknown part of history within that period. Isn’t it?

The second of the above options would lead to “unknown” for almost a full year in the years period view, if the system went live at the 2nd of January. The first option should show results correct results for the period since the start of history data almost immediately, even though incomplete. But this incompleteness is very obvious and intuitive anyway, as the time graph on the same page has the same incompleteness and therefore provides a good graphical hint about that context.

But what does the system instead, as it shows these huge values?

I would be very thankful for some clarification on what is actually going on in the system as it is (and why).

With the start of the new day, the values of the day dropped to 0 kWh, which makes sense, no sunshine until now.

What I find strange: The values of yesterday are still these huge “all time” (?) values for the Kostal Piko. For the Fronius and Kostal Plenticore they are just around reasonable 80 kWh, as in the screenshot above.

If I select the year view, they jump to huge values as well (30 MWh). Even though history in OpenEMS started only yesterday. Thus: How they know it happened in 2025, and not in 2024?
In both years (2024 & 2025) the graph shows no data available, as it does for the month Dezember, but interestingly not for this week, where it shows yesterday’s and today’s data, which makes sense to me.

I find this behavior a bit inconsistent. And I do not know, what of it is intended. (I think you can already guess my preferences, but the project’s might be different.)
Could you help me to understand the intended logic?

Your assumptions all seem to be right. I did not follow the details of the Kostal Piko implementation, but in the latest PR ( fixed Kostal Piko HTML parsing bug: kWh for Total Energy in HTML, instead of expected Wh in ActiveProductionEnergy by janklostermann · Pull Request #3465 · OpenEMS/openems · GitHub ) the conversion for energy values (totalYield → stored as ActiveProductionEnergy in OpenEMS) was fixed to multiply with 1000.

This means for systems that had been running before, the the update there are very small values written in ActiveProductionEnergy; and with the update they are much higher. Example

  • 05.12. 00:00 ActiveProductionEnergy = 10
  • 06.12. 00:00 ActiveProductionEnergy = 11 (day of update)
  • 07.12. 00:00 ActiveProductionEnergy = 12,000
  • 08.12. 00:00 ActiveProductionEnergy = 13,000

Daily Production Energy will be correct for 07.12. (13000 - 12000 = 1000 Wh); but wrong for 06.12. (12000 - 11 = 11089 Wh)

@stefan.feilmeier The behavior you describe is clear for the transition, when you have old an new values. But in the end, the old small values are irrelevant, as they are too small to make a difference.

What I was taking about is the behaviour when a system is freshly started.

Shouldn’t it be consistent from day or even hour one? In all timescales?

To me it seems to be a quite easy to fix initialisation issue.

What are your thoughts on that?

Ok, maybe I misunderstood you. In OpenEMS we currently have two approaches for energy values - both with PROs and CONs:

  • Calculate Energy from Power inside OpenEMS
    • OpenEMS provides a helper for this in CalculateEnergyFromPower
    • PRO:
      • Values are guaranted to be continuously rising
      • On restart, last value is read from local timedata (rrd4j)
      • Starts from “zero” at first start; not causing very high initial values no matter how long the device has been in use before
      • Keeps counting correctly even if the hardware device gets exchanged
    • CON:
      • Not as accurate as internal calculation in the device
      • Only considers data if communication between device and EMS is available
  • Use Energy values provided by device
    • Opposite of above :slight_smile:

It’s your choice. :wink: Developers of the KOSTAL Piko implementation chose the second variant.

I do understand the argument, and also see why the second approach can result in the consquences described.

But I don’t think, that this in inenvitable. It should be possible to show meaningful values for all ranges, if you add a “lifetime” range, as potentially longer than a year, where the start of OpenEMS history can start with whatever value is read at first time from the device. And everything else deducts from there…

Would you be interested in going this path?

I don’t think it will be easy to add this “lifetime” range in OpenEMS, as we are always using concrete dates for queries etc. But I am very open to improving the way energy values are handled - sure!