Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions io.openems.edge.application/EdgeApp.bndrun
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@
bnd.identity;id='io.openems.edge.meter.discovergy',\
bnd.identity;id='io.openems.edge.meter.eastron',\
bnd.identity;id='io.openems.edge.meter.hager',\
bnd.identity;id='io.openems.edge.meter.inepro',\
bnd.identity;id='io.openems.edge.meter.janitza',\
bnd.identity;id='io.openems.edge.meter.kdk',\
bnd.identity;id='io.openems.edge.meter.phoenixcontact',\
Expand Down Expand Up @@ -377,6 +378,7 @@
io.openems.edge.meter.discovergy;version=snapshot,\
io.openems.edge.meter.eastron;version=snapshot,\
io.openems.edge.meter.hager;version=snapshot,\
io.openems.edge.meter.inepro;version=snapshot,\
io.openems.edge.meter.janitza;version=snapshot,\
io.openems.edge.meter.kdk;version=snapshot,\
io.openems.edge.meter.phoenixcontact;version=snapshot,\
Expand Down
12 changes: 12 additions & 0 deletions io.openems.edge.meter.inepro/.classpath
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-21"/>
<classpathentry kind="src" output="bin" path="src"/>
<classpathentry kind="src" output="bin_test" path="test">
<attributes>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin"/>
</classpath>
2 changes: 2 additions & 0 deletions io.openems.edge.meter.inepro/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/bin_test/
/generated/
23 changes: 23 additions & 0 deletions io.openems.edge.meter.inepro/.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>io.openems.edge.meter.inepro</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>bndtools.core.bndbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>bndtools.core.bndnature</nature>
</natures>
</projectDescription>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8
16 changes: 16 additions & 0 deletions io.openems.edge.meter.inepro/bnd.bnd
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Bundle-Name: OpenEMS Edge io.openems.edge.meter.inepro
Bundle-Vendor: VEV Platform Services France
Bundle-License: https://opensource.org/licenses/EPL-2.0
Bundle-Version: 1.0.0.${tstamp}

-buildpath: \
${buildpath},\
io.openems.common,\
io.openems.edge.bridge.modbus,\
io.openems.edge.common,\
io.openems.edge.meter.api,\
io.openems.j2mod,\

-testpath: \
${testpath},\
io.openems.common
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package io.openems.edge.meter.inepro.pro380modct;

import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;

import io.openems.common.types.MeterType;

@ObjectClassDefinition(//
name = "Meter inepro Pro380ModCT", //
description = "Implements the inepro Pro380ModCT meter.")
public @interface Config {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Config should be package-private - it's an internal implementation detail, not part of the public api


@AttributeDefinition(name = "Component-ID", description = "Unique ID of this Component")
String id() default "meter0";

@AttributeDefinition(name = "Alias", description = "Human-readable name of this Component; defaults to Component-ID")
String alias() default "";

@AttributeDefinition(name = "Is enabled?", description = "Is this Component enabled?")
boolean enabled() default true;

@AttributeDefinition(name = "Modbus-ID", description = "ID of Modbus bridge.")
String modbus_id() default "modbus0";

@AttributeDefinition(name = "Modbus Unit-ID", description = "The Unit-ID of the Modbus device.")
int modbusUnitId() default 1;

@AttributeDefinition(name = "Modbus target filter", description = "This is auto-generated by 'Modbus-ID'.")
String Modbus_target() default "(enabled=true)";

String webconsole_configurationFactory_nameHint() default "io.openems.edge.meter.pro380modct [{id}]";

@AttributeDefinition(name = "Meter-Type", description = "What is measured by this Meter?")
Copy link
Collaborator

Choose a reason for hiding this comment

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

package io.openems.edge.meter.inepro.pro380modct;

import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;

import io.openems.common.types.MeterType;

@ObjectClassDefinition(//
		name = "Meter inepro Pro380ModCT", //
		description = "Implements the inepro Pro380ModCT meter.")
public @interface Config {

	@AttributeDefinition(name = "Component-ID", description = "Unique ID of this Component")
	String id() default "meter0";

	@AttributeDefinition(name = "Alias", description = "Human-readable name of this Component; defaults to Component-ID")
	String alias() default "";

	@AttributeDefinition(name = "Is enabled?", description = "Is this Component enabled?")
	boolean enabled() default true;

	@AttributeDefinition(name = "Modbus-ID", description = "ID of Modbus bridge.")
	String modbus_id() default "modbus0";

	@AttributeDefinition(name = "Modbus Unit-ID", description = "The Unit-ID of the Modbus device.")
	int modbusUnitId() default 1;

	@AttributeDefinition(name = "Meter-Type", description = "What is measured by this Meter?")
	MeterType type() default MeterType.CONSUMPTION_METERED;

	@AttributeDefinition(name = "Modbus target filter", description = "This is auto-generated by 'Modbus-ID'.")
	String Modbus_target() default "(enabled=true)";

	String webconsole_configurationFactory_nameHint() default "io.openems.edge.meter.pro380modct [{id}]";
}

MeterType type() default MeterType.CONSUMPTION_METERED;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.openems.edge.meter.inepro.pro380modct;

import io.openems.common.channel.Unit;
import io.openems.common.types.OpenemsType;
import io.openems.edge.common.channel.Doc;
import io.openems.edge.common.component.OpenemsComponent;
import io.openems.edge.meter.api.ElectricityMeter;

public interface Pro380modct extends ElectricityMeter, OpenemsComponent {

public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
APPARENT_POWER_L1(Doc.of(OpenemsType.INTEGER).unit(Unit.VOLT_AMPERE)), //
Copy link
Collaborator

Choose a reason for hiding this comment

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

package io.openems.edge.meter.inepro.pro380modct;

import io.openems.common.channel.Unit;
import io.openems.common.types.OpenemsType;
import io.openems.edge.common.channel.Doc;
import io.openems.edge.common.component.OpenemsComponent;
import io.openems.edge.meter.api.ElectricityMeter;

public interface Pro380modct extends ElectricityMeter, OpenemsComponent {

	public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
		APPARENT_POWER_L1(Doc.of(OpenemsType.INTEGER)//
				.unit(Unit.VOLT_AMPERE)), //
		APPARENT_POWER_L2(Doc.of(OpenemsType.INTEGER)//
				.unit(Unit.VOLT_AMPERE)), //
		APPARENT_POWER_L3(Doc.of(OpenemsType.INTEGER)//
				.unit(Unit.VOLT_AMPERE)), //
		APPARENT_POWER(Doc.of(OpenemsType.INTEGER)//
				.unit(Unit.VOLT_AMPERE));

		private final Doc doc;

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

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

}

APPARENT_POWER_L2(Doc.of(OpenemsType.INTEGER).unit(Unit.VOLT_AMPERE)), //
APPARENT_POWER_L3(Doc.of(OpenemsType.INTEGER).unit(Unit.VOLT_AMPERE)), //
APPARENT_POWER(Doc.of(OpenemsType.INTEGER).unit(Unit.VOLT_AMPERE));

private final Doc doc;

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

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

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package io.openems.edge.meter.inepro.pro380modct;

import io.openems.common.exceptions.OpenemsException;
import io.openems.common.types.MeterType;
import io.openems.edge.bridge.modbus.api.AbstractOpenemsModbusComponent;
import io.openems.edge.bridge.modbus.api.BridgeModbus;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Also please apply Ctrl+Shift+O after all for Sorting the imports

import io.openems.edge.bridge.modbus.api.ElementToChannelConverter;
import io.openems.edge.bridge.modbus.api.ModbusComponent;
import io.openems.edge.bridge.modbus.api.ModbusProtocol;
import io.openems.edge.bridge.modbus.api.element.FloatDoublewordElement;
import io.openems.edge.bridge.modbus.api.element.WordOrder;
import io.openems.edge.bridge.modbus.api.task.FC3ReadRegistersTask;
import io.openems.edge.common.component.OpenemsComponent;
import io.openems.edge.common.taskmanager.Priority;
import io.openems.edge.meter.api.ElectricityMeter;
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.Deactivate;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.metatype.annotations.Designate;

@Designate(ocd = Config.class, factory = true)
@Component(//
name = "Meter.inepro.Pro380ModCT", //
immediate = true, //
configurationPolicy = ConfigurationPolicy.REQUIRE //
)
public class Pro380modctImpl extends AbstractOpenemsModbusComponent implements Pro380modct, ElectricityMeter, ModbusComponent, OpenemsComponent {

@Reference
private ConfigurationAdmin cm;

@Reference(policy = ReferencePolicy.STATIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.MANDATORY)
protected void setModbus(BridgeModbus modbus) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Method overrides AbstractOpenemsModbusComponent.setModbus(). The @OverRide annotation provides compile-time safety and documents intent.

super.setModbus(modbus);
}

private Config config = null;

public Pro380modctImpl() {
super(//
OpenemsComponent.ChannelId.values(), //
ModbusComponent.ChannelId.values(), //
ElectricityMeter.ChannelId.values(), //
Pro380modct.ChannelId.values() //
);
}

@Activate
private void activate(ComponentContext context, Config config) throws OpenemsException {
if (super.activate(context, config.id(), config.alias(), config.enabled(), config.modbusUnitId(), this.cm, "Modbus",
config.modbus_id())) {
return;
}
this.config = config;
}

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

@Override
protected ModbusProtocol defineModbusProtocol() {
var modbusProtocol = new ModbusProtocol(this, //
// VOLTAGE + FREQUENCY
new FC3ReadRegistersTask(0x5002, Priority.HIGH, //
m(ElectricityMeter.ChannelId.VOLTAGE_L1, //
new FloatDoublewordElement(0x5002).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3), //
m(ElectricityMeter.ChannelId.VOLTAGE_L2, //
new FloatDoublewordElement(0x5004).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3), //
m(ElectricityMeter.ChannelId.VOLTAGE_L3, //
new FloatDoublewordElement(0x5006).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3), //
m(ElectricityMeter.ChannelId.FREQUENCY, //
new FloatDoublewordElement(0x5008).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3) //
), //
// CURRENT (total + L1/L2/L3)
new FC3ReadRegistersTask(0x500A, Priority.HIGH, //
m(ElectricityMeter.ChannelId.CURRENT, //
new FloatDoublewordElement(0x500A).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3), //
m(ElectricityMeter.ChannelId.CURRENT_L1, //
new FloatDoublewordElement(0x500C).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3), //
m(ElectricityMeter.ChannelId.CURRENT_L2, //
new FloatDoublewordElement(0x500E).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3), //
m(ElectricityMeter.ChannelId.CURRENT_L3, //
new FloatDoublewordElement(0x5010).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3) //
), //
// ACTIVE POWER (kW) total + L1/L2/L3
new FC3ReadRegistersTask(0x5012, Priority.HIGH, //
m(ElectricityMeter.ChannelId.ACTIVE_POWER, //
new FloatDoublewordElement(0x5012).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3), //
m(ElectricityMeter.ChannelId.ACTIVE_POWER_L1, //
new FloatDoublewordElement(0x5014).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3), //
m(ElectricityMeter.ChannelId.ACTIVE_POWER_L2, //
new FloatDoublewordElement(0x5016).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3), //
m(ElectricityMeter.ChannelId.ACTIVE_POWER_L3, //
new FloatDoublewordElement(0x5018).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3) //
), //
// REACTIVE POWER (kvar) total + L1/L2/L3
new FC3ReadRegistersTask(0x501A, Priority.HIGH, //
m(ElectricityMeter.ChannelId.REACTIVE_POWER, //
new FloatDoublewordElement(0x501A).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3), //
m(ElectricityMeter.ChannelId.REACTIVE_POWER_L1, //
new FloatDoublewordElement(0x501C).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3), //
m(ElectricityMeter.ChannelId.REACTIVE_POWER_L2, //
new FloatDoublewordElement(0x501E).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3), //
m(ElectricityMeter.ChannelId.REACTIVE_POWER_L3, //
new FloatDoublewordElement(0x5020).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3) //
), //
// APPARENT POWER (kVA) total + L1/L2/L3
new FC3ReadRegistersTask(0x5022, Priority.HIGH, //
m(Pro380modct.ChannelId.APPARENT_POWER, //
new FloatDoublewordElement(0x5022).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3), //
m(Pro380modct.ChannelId.APPARENT_POWER_L1, //
new FloatDoublewordElement(0x5024).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3), //
m(Pro380modct.ChannelId.APPARENT_POWER_L2, //
new FloatDoublewordElement(0x5026).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3), //
m(Pro380modct.ChannelId.APPARENT_POWER_L3, //
new FloatDoublewordElement(0x5028).wordOrder(WordOrder.MSWLSW), //
ElementToChannelConverter.SCALE_FACTOR_3) //
) //
);

return modbusProtocol;
}

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

@Override
public MeterType getMeterType() {
return this.config.type();
}
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package io.openems.edge.meter.inepro.pro380modct;

import io.openems.common.utils.ConfigUtils;
import io.openems.common.test.AbstractComponentConfig;
import io.openems.common.types.MeterType;

@SuppressWarnings("all")
public class MyConfig extends AbstractComponentConfig implements Config {

public static class Builder {
private String id;
private String modbusId = null;
private int modbusUnitId;
private MeterType type;

private Builder() {
}

public Builder setId(String id) {
this.id = id;
return this;
}

public Builder setModbusId(String modbusId) {
this.modbusId = modbusId;
return this;
}

public Builder setType(MeterType type) {
this.type = type;
return this;
}

public Builder setModbusUnitId(int modbusUnitId) {
this.modbusUnitId = modbusUnitId;
return this;
}

public MyConfig build() {
return new MyConfig(this);
}

}

/**
* Create a Config builder.
*
* @return a {@link Builder}
*/
public static Builder create() {
return new Builder();
}

private final Builder builder;

private MyConfig(Builder builder) {
super(Config.class, builder.id);
this.builder = builder;
}

@Override
public String modbus_id() {
return this.builder.modbusId;
}

@Override
public String Modbus_target() {
return ConfigUtils.generateReferenceTargetFilter(this.id(), this.modbus_id());
}

@Override
public int modbusUnitId() {
return this.builder.modbusUnitId;
}

@Override
public MeterType type() {
return this.builder.type;
}

}
Loading