Issue accessing ConsumptionActivePower from Sum component – undefined

Hello everyone,
I hope you’re all doing great!

I’m working on a custom component in OpenEMS where I need to access the total consumption power using the getConsumptionActivePower() method from the Sum interface.

In the SumImpl debug logs, I can see that the ConsumptionActivePower value is being correctly calculated, which means the data does exist. However, when I try to access it in my own code (for example, to print or log it), it seems to return undefined.

Here’s roughly what I’m doing: package io.openems.edge.meter.ConsProd;

import org.osgi.service.cm.ConfigurationAdmin;
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.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
import org.osgi.service.event.propertytypes.EventTopics;
import org.osgi.service.metatype.annotations.Designate;

import io.openems.common.channel.AccessMode;
import io.openems.common.types.MeterType;
import io.openems.edge.bridge.modbus.api.ModbusComponent;
import io.openems.edge.common.component.AbstractOpenemsComponent;
import io.openems.edge.common.component.ComponentManager;
import io.openems.edge.common.component.OpenemsComponent;
import io.openems.edge.common.event.EdgeEventConstants;
import io.openems.edge.common.modbusslave.ModbusSlaveTable;
import io.openems.edge.common.sum.Sum;
import io.openems.edge.meter.api.ElectricityMeter;
import io.openems.edge.meter.api.VirtualMeter;
import io.openems.edge.timedata.api.Timedata;
import io.openems.edge.timedata.api.TimedataProvider;

@Designate(ocd = Config.class, factory = true)
@Component(//
		name = "Meter.Regulator", //
		immediate = true, //
		configurationPolicy = ConfigurationPolicy.REQUIRE //
)
@EventTopics({ //
		EdgeEventConstants.TOPIC_CYCLE_AFTER_PROCESS_IMAGE //
})
public class MeterConProdImpl extends AbstractOpenemsComponent implements Sum, MeterConsProd,
		ElectricityMeter, OpenemsComponent, TimedataProvider, EventHandler,VirtualMeter {


	private MeterType meterType = MeterType.PRODUCTION;

	@Reference
	private ConfigurationAdmin cm;
	
	private Sum sum; 
	
	private Config config;
	
	private ComponentManager componentmanager;
	

	@Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.OPTIONAL)
	private volatile Timedata timedata;


	public MeterConProdImpl() {
		super(//
				OpenemsComponent.ChannelId.values(), //
				ModbusComponent.ChannelId.values(), //
				ElectricityMeter.ChannelId.values(), //
				MeterConsProd.ChannelId.values(), //
				Sum.ChannelId.values()
		);

	}

	@Activate
	private void activate(ComponentContext context, Config config) {
		super.activate(context, config.id(), config.alias(), config.enabled());
		this.config = config;
	}

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

	@Override
	public MeterType getMeterType() {
		return this.meterType;
	}
	/*private void consumption() {
		var test = this.channel(Sum.ChannelId.CONSUMPTION_ACTIVE_POWER).value();

		System.out.println("this is a consumption : "+ test);
	}*/
	
	@Override
	public String debugLog() {
		
		return "consumption : " + this.channel(Sum.ChannelId.CONSUMPTION_ACTIVE_POWER).getNextValue();
	}

	
	//private void updateChannels() {
		//IntegerReadChannel activePower = this.channel(ElectricityMeter.ChannelId.ACTIVE_POWER);
		/*var AggregatedActivePower = this.getEssActivePower();
		
		if (AggregatedActivePower.get() != null && AggregatedActivePower.get() < 0) {
		    // safe to compare
			_setActivePower(AggregatedActivePower.get());*/
	//	}
			
	
	
	@Override
	public Timedata getTimedata() {
		return this.timedata;
	}

	@Override
	public void handleEvent(Event event) {/*
		if (!this.isEnabled()) {
			return;
		}
		switch (event.getTopic()) {
		case EdgeEventConstants.TOPIC_CYCLE_AFTER_PROCESS_IMAGE -> this.updateChannelsBeforeProcessImage();
		}*/
		/*this.consumption();
	}

	@Override
	public boolean addToSum() {
		return true;
	}

	@Override
	public void updateChannelsBeforeProcessImage() {/*
		this.updateChannels();*/
		
	}

	@Override
	public boolean addToSum() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public void updateChannelsBeforeProcessImage() {
		// TODO Auto-generated method stub
		
	}

}
  • Is there something I’m missing to properly read the channel value from another component?
  • Does getConsumptionActivePower().get() require any special timing or initialization before it returns valid values?
  • Is there a better or recommended way to forward this value to a VirtualMeter?

Thanks in advance for your help!

Hi @alm20 and welcome to the community.

  1. The Channel-IDs defined in the constructor are only for your own Component. So Sum.ChannelId.values() is wrong in that place.

  2. If you want to access a Channel of the Sum component you need to get it via Dependency Injection. You are nearly there with private Sum sum;, but you forgot @Reference. See this example: openems/io.openems.edge.controller.ess.emergencycapacityreserve/src/io/openems/edge/controller/ess/emergencycapacityreserve/ControllerEssEmergencyCapacityReserveImpl.java at develop · OpenEMS/openems · GitHub

  3. Then you wil be able to call this.sum.getConsumptionActivePower() in your component.

Regards,
Stefan

I’m happy to be here Thanks for the help and , it’s working now!

I was trying to assign the consumption value to production to correct for negative values, which aren’t suitable for analysis. However, I’m still seeing negative Consumption values. It seems the virtual meter is writing the Production channel before the actual consumption is recorded, causing production to show the previous consumption value.

Any ideas on how to address this timing issue?

I am not sure what exactly you are trying to do, maybe you can explain your setup in a little bit more detail.

Also please read the section on “Process Image” - maybe this is what’s causes problems for you: Edge Architecture :: Open Energy Management System

1 Like