Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/victron multiplus ess #1819

Open
wants to merge 17 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 12 additions & 0 deletions io.openems.edge.batteryinverter.victron/.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-11"/>
<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.batteryinverter.victron/.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.batteryinverter.victron/.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.batteryinverter.victron</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>
21 changes: 21 additions & 0 deletions io.openems.edge.batteryinverter.victron/bnd.bnd
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Bundle-Name: OpenEMS Edge Battery Inverter Victron
Bundle-Vendor: Ernst KNOLL Feinmechanik GmbH
Bundle-License: https://opensource.org/licenses/EPL-2.0
Bundle-Version: 1.0.0.${tstamp}

-buildpath: \
${buildpath},\
io.openems.common,\
io.openems.edge.battery.api,\
io.openems.edge.batteryinverter.api,\
io.openems.edge.bridge.modbus,\
io.openems.edge.common,\
io.openems.edge.core,\
io.openems.edge.controller.api,\
io.openems.edge.ess.api,\
io.openems.edge.meter.api,\
io.openems.edge.timedata.api,\
io.openems.edge.pvinverter.api

-testpath: \
${testpath}
Binary file not shown.
11 changes: 11 additions & 0 deletions io.openems.edge.batteryinverter.victron/readme.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
= Victron Battery Inverter

Implementation of Victron Battery Inverter
- tested with Victron Multiplus 2GX ESS


Implemented Natures::
- SymmetricEss
- ManagedSymmetricEss

https://github.com/OpenEMS/openems/tree/develop/io.openems.edge.batteryinverter.victron[Source Code icon:github[]]
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.openems.edge.battery.victron;

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

@ObjectClassDefinition(//
name = "Battery Victron", //
description = "Implements the Victron CANBus Battery.")
public @interface Config {

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

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

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

@AttributeDefinition(name = "Modbus-ID", description = "ID of Modbus bridge to Victron Inverter / Same as for the Victron ESS.")
String modbus_id() default "modbus0";

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

String webconsole_configurationFactory_nameHint() default "Battery Victron [{id}]";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
package io.openems.edge.battery.victron;

import io.openems.common.channel.AccessMode;
import io.openems.common.channel.Unit;
import io.openems.common.types.OpenemsType;
import io.openems.edge.battery.api.Battery;
import io.openems.edge.common.channel.Doc;
import io.openems.edge.common.channel.IntegerReadChannel;
import io.openems.edge.common.channel.value.Value;
import io.openems.edge.common.component.OpenemsComponent;
import io.openems.edge.victron.enums.ActiveInactive;
import io.openems.edge.victron.enums.Alarm;
import io.openems.edge.victron.enums.Error;
import io.openems.edge.victron.enums.LowCellVoltageAlarm;
import io.openems.edge.victron.enums.OpenClosed;
import io.openems.edge.victron.enums.SystemSwitch;
import io.openems.edge.victron.enums.VictronState;

public interface VictronBattery extends Battery, OpenemsComponent {

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


STARTER_BATTERY_VOLTAGE(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.VOLT)),
TEMPERATURE(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.DEGREE_CELSIUS)),
MID_VOLTAGE(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.VOLT)),
MID_VOLTAGE_DEVIATION(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.PERCENT)),
CONSUMED_AMPHOURS(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.AMPERE_HOURS)),
ALARM(Doc.of(Alarm.values())
.accessMode(AccessMode.READ_ONLY)),
LOW_VOLTAGE_ALARM(Doc.of(Alarm.values())
.accessMode(AccessMode.READ_ONLY)),
HIGH_VOLTAGE_ALARM(Doc.of(Alarm.values())
.accessMode(AccessMode.READ_ONLY)),
LOW_STARTER_VOLTAGE_ALARM(Doc.of(Alarm.values())
.accessMode(AccessMode.READ_ONLY)),
HIGH_STARTER_VOLTAGE_ALARM(Doc.of(Alarm.values())
.accessMode(AccessMode.READ_ONLY)),
LOW_STATE_OF_CHARGE_ALARM(Doc.of(Alarm.values())
.accessMode(AccessMode.READ_ONLY)),
LOW_TEMPERATURE_ALARM(Doc.of(Alarm.values())
.accessMode(AccessMode.READ_ONLY)),
HIGH_TEMPERATURE_ALARM(Doc.of(Alarm.values())
.accessMode(AccessMode.READ_ONLY)),
MID_VOLTAGE_ALARM(Doc.of(Alarm.values())
.accessMode(AccessMode.READ_ONLY)),
LOW_FUSED_VOLTAGE_ALARM(Doc.of(Alarm.values())
.accessMode(AccessMode.READ_ONLY)),
HIGH_FUSED_VOLTAGE_ALARM(Doc.of(Alarm.values())
.accessMode(AccessMode.READ_ONLY)),
FUSE_BLOWN_ALARM(Doc.of(Alarm.values())
.accessMode(AccessMode.READ_ONLY)),
HIGH_INTERNAL_TEMPERATURE_ALARM(Doc.of(Alarm.values())
.accessMode(AccessMode.READ_ONLY)),
RELAY_STATUS(Doc.of(OpenClosed.values())
.accessMode(AccessMode.READ_WRITE)),
DEEPEST_DISCHARGE(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.AMPERE_HOURS)),
LAST_DISCHARGE(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.AMPERE_HOURS)),
AVERAGE_DISCHARGE(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.AMPERE_HOURS)),
CHARGE_CYCLES(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.NONE)),
FULL_DISCHARGES(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.NONE)),
TOTAL_AMPHOURS_DRAWN(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.AMPERE_HOURS)),
HISTORY_MIN_VOLTAGE(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.VOLT)),
HISTORY_MAX_VOLTAGE(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.VOLT)),
TIME_SINCE_LAST_FULL_CHARGE(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.SECONDS)),
AUTOMATIC_SYNCS(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.NONE)),
LOW_VOLTAGE_ALARMS(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.NONE)),
HIGH_VOLTAGE_ALARMS(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.NONE)),
LOW_STARTER_VOLTAGE_ALARMS(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.NONE)),
HIGH_STARTER_VOLTAGE_ALARMS(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.NONE)),
MIN_STARTER_VOLTAGE(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.VOLT)),
MAX_STARTER_VOLTAGE(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.VOLT)),
LOW_FUSED_VOLTAGE_ALARMS(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.NONE)),
HIGH_FUSED_VOLTAGE_ALARMS(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.NONE)),
MIN_FUSED_VOLTAGE(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.VOLT)),
MAX_FUSED_VOLTAGE(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.VOLT)),
DISCHARGED_ENERGY(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.KILOWATT_HOURS)),
CHARGED_ENERGY(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.KILOWATT_HOURS)),
TIME_TO_GO(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.SECONDS)),
CAPACITY_IN_AMPHOURS(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.AMPERE_HOURS)),
TIMESTAMP_1ST_LAST_ERROR(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)),
TIMESTAMP_2ND_LAST_ERROR(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)),
TIMESTAMP_3RD_LAST_ERROR(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)),
TIMESTAMP_4TH_LAST_ERROR(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)),
HIGH_CHARGE_CURRENT_ALARM(Doc.of(Alarm.values())
.accessMode(AccessMode.READ_ONLY)),
HIGH_DISCHARGE_CURRENT_ALARM(Doc.of(Alarm.values())
.accessMode(AccessMode.READ_ONLY)),
CELL_IMBALANCE_ALARM(Doc.of(Alarm.values())
.accessMode(AccessMode.READ_ONLY)),
INTERNAL_FAILURE_ALARM(Doc.of(Alarm.values())
.accessMode(AccessMode.READ_ONLY)),
HIGH_CHARGE_TEMPERATURE_ALARM(Doc.of(Alarm.values())
.accessMode(AccessMode.READ_ONLY)),
LOW_CHARGE_TEMPERATURE_ALARM(Doc.of(Alarm.values())
.accessMode(AccessMode.READ_ONLY)),
LOW_CELL_VOLTAGE_ALARM(Doc.of(LowCellVoltageAlarm.values())
.accessMode(AccessMode.READ_ONLY)),
VICTRON_STATE(Doc.of(VictronState.values())
.accessMode(AccessMode.READ_ONLY)),
ERROR(Doc.of(Error.values())
.accessMode(AccessMode.READ_ONLY)),
SYSTEM_SWITCH(Doc.of(SystemSwitch.values())
.accessMode(AccessMode.READ_ONLY)),
BALANCING(Doc.of(ActiveInactive.values())
.accessMode(AccessMode.READ_ONLY)),
NUMBER_OF_BATTERIES(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.NONE)),
BATTERIES_PARALLEL(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.NONE)),
BATTERIES_SERIES(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.NONE)),
NUMBER_OF_CELLS_PER_BATTERY(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.NONE)),
SYSTEM_MIN_CELL_VOLTAGE(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.VOLT)),
SYSTEM_MAX_CELL_VOLTAGE(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.VOLT)),
SHUTDOWNS_DUE_ERROR(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.NONE)),
DIAGNOSTICS_1ST_LAST_ERROR(Doc.of(Error.values())
.accessMode(AccessMode.READ_ONLY)),
DIAGNOSTICS_2ND_LAST_ERROR(Doc.of(Error.values())
.accessMode(AccessMode.READ_ONLY)),
DIAGNOSTICS_3RD_LAST_ERROR(Doc.of(Error.values())
.accessMode(AccessMode.READ_ONLY)),
DIAGNOSTICS_4TH_LAST_ERROR(Doc.of(Error.values())
.accessMode(AccessMode.READ_ONLY)),
ALLOW_TO_CHARGE(Doc.of(OpenemsType.BOOLEAN)
.accessMode(AccessMode.READ_ONLY)),
ALLOW_TO_DISCHARGE(Doc.of(OpenemsType.BOOLEAN)
.accessMode(AccessMode.READ_ONLY)),
EXTERNAL_RELAY(Doc.of(ActiveInactive.values())
.accessMode(AccessMode.READ_ONLY)),
HISTORY_MIN_CELL_VOLTAGE(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.VOLT)),
HISTORY_MAX_CELL_VOLTAGE(Doc.of(OpenemsType.INTEGER)
.accessMode(AccessMode.READ_ONLY)
.unit(Unit.VOLT));


private final Doc doc;

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

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

public default IntegerReadChannel getCapacityInAmphoursChannel() {
return this.channel(ChannelId.CAPACITY_IN_AMPHOURS);
}

public default Value<Integer> getCapacityInAmphours() {
return this.getCapacityInAmphoursChannel().value();
}

public default void _setCapacityInAmphours(Integer value) {
this.getCapacityInAmphoursChannel().setNextValue(value);
}

}