PV-Inverter does not show up in UI

Hello,

I’ve implemented a custom PV-Inverter, but even though its active power is printed correctly in the debug log (added correctly to the production), it does not show up in the user interface. However, if I implement a Meter with Metertype.PRODUCTION with otherwise the same methods, it also shows up in the user interface.
This seems weird to me, since in the PV-Inverter interface the Metertype is set to PRODUCTION by default, so I don’t see the difference.
Is this a bug or is it intended that only meters show up in the UI?

Best regards,
Simon

Hi Simon,

without seeing the code I can only guess where the error is. Be aware that, in order to be recognized as a valid implementation of an OSGi service, you have to explicitely implement all interfaces in your component - even though this would not be strictly required in Java.

Example: the KACO blueplanet PV-Inverter explicitely implements the ManagedSymmetricPvInverter and SymmetricMeter.

This information is evaluated in the UI, when deciding which components to list e.g. in the Production widget on the Live screen:

Regards,
Stefan

Hi Stefan,
thank you for the prompt reply. I have, indeed, implemented both the ManagedSymmetricPvInverter and the SymmetricMeter. I have attached the full code here. The device basically fills the OpenEMS channels with information gathered from an external API request (implemented in the class “SolarwebAPIRequestPV”).

package io.openems.edge.pvinverter.fronius;

import java.io.IOException;

import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;
import org.osgi.service.metatype.annotations.Designate;

import io.openems.common.exceptions.OpenemsException;
import io.openems.edge.common.channel.Doc;
import io.openems.edge.common.component.AbstractOpenemsComponent;
import io.openems.edge.common.component.OpenemsComponent;
import io.openems.edge.common.event.EdgeEventConstants;
import io.openems.edge.meter.api.SymmetricMeter;
import io.openems.edge.pvinverter.api.ManagedSymmetricPvInverter;

@Designate(ocd = Config.class, factory = true)
@Component(//
		name = "PV-Inverter.Fronius", //
		immediate = true, //
		configurationPolicy = ConfigurationPolicy.REQUIRE, //
		property = { //
				EventConstants.EVENT_TOPIC + "=" + EdgeEventConstants.TOPIC_CYCLE_BEFORE_PROCESS_IMAGE //
		} //
)
public class FroniusPV extends AbstractOpenemsComponent implements ManagedSymmetricPvInverter, SymmetricMeter, OpenemsComponent, EventHandler {

	private Config config = null;
	private SolarwebAPIRequestPV request;

	public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
		;

		private final Doc doc;

		private ChannelId(Doc doc) {
			this.doc = doc;
		}

		@Override
		public Doc doc() {
			return this.doc;
		}
	}

	public FroniusPV() {
		super(//
				OpenemsComponent.ChannelId.values(), //
				SymmetricMeter.ChannelId.values(), //
				ManagedSymmetricPvInverter.ChannelId.values() //
		);
	}

	@Activate
	void activate(ComponentContext context, Config config) throws IOException, InterruptedException {
		super.activate(context, config.id(), config.alias(), config.enabled());
		this.config = config;
		this.request = new SolarwebAPIRequestPV(
				this.config.accessKeyID(), 
				this.config.accessKeyValue(), 
				this.config.pvSystemID(), 
				this.config.refreshInterval()
				);
		this._setActivePowerLimit(this.request.getMaxPowerPV());
	}

	@Deactivate
	protected void deactivate() {
		super.deactivate();
	}

	@Override
	public void handleEvent(Event event) {
		if (!this.isEnabled()) {
			return;
		}
		switch (event.getTopic()) {
		case EdgeEventConstants.TOPIC_CYCLE_BEFORE_PROCESS_IMAGE:
			// TODO: fill channels
			try {
				this._setActivePower(this.request.getPowerPV()); // set active power
			} catch (IOException | InterruptedException | OpenemsException e) {
				System.out.println("Error during Solarweb API request");
				e.printStackTrace();
			}
			break;
		}
	}

	@Override
	public String debugLog() {
		return "L:" + this.getActivePower().asString();
	}
}

Many thanks for your help!

Best regards,
Simon

Ok, then it should indeed work already. Strange. Do you have a full example in a git repository, so that I could have a more detailed look?

As a sidenote - but I am aware this is not your priority right now:

  1. The EventHandler should never block the cycle, so any calls to external APIs should be done in a separate worker thread. See the Discovergy Meter implementation as an example.

  2. Add Fronius to the compatibility list would we very good to have. Why are you using the Solar-API? From my understanding Fronius also has a Modbus/TCP interface, most likely even SunSpec, which might be easier to implement in OpenEMS, as a lot of this functionality is already there.

Thank you for the tips! You can have a look at the full repository here: openems/io.openems.edge.pvinverter.fronius at develop · simonhow/openems · GitHub

  • Ad 1.: This is really useful, I have already implemented an AbstractWorker which updates the values regularly.
  • Ad 2.: To be honest, this just was the task given to me (I am an MA student) and due to the whole Covid situation there was no hardware for me to implement and test it on. But you are absolutely right, this package just reads values and does not support any “back channel” to control the real devices, so a Modbus/TCP support would be really useful.

Hello Simon,

Have you resolve your problem ?
Because I’m in the same case than you but for me it’s with a custom “meter consumption” not an inverter.
In the UI, I can see that my meter is giving the same data than my Modbus/TCP support but I don’t have any graphic representation on the “Energy Monitor”.

So the result is like that :

Thanks for your answer.

@SimonH: As FENECON we might have customers who have Fronius PV Inverters and then - if they agree - I would be able to establish a remote connection for you, to implement it directly. Would that be an option, or can you access the Fronius in your lab by now? I would really recommending to go the Modbus/SunSpec way, as it will be easier to implement. Solar-API is also possible of course, but I did not yet have time to look into your code.

@LucasU: Sorry, this is actually a pending TODO, that separate Consumption-Meters are not taken into account for calculating the sum. See

It should not be too difficult to implement it, though. The different MeterTypes are explained here: https://github.com/OpenEMS/openems/blob/develop/io.openems.edge.meter.api/src/io/openems/edge/meter/api/MeterType.java

1 Like