Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@
@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 = "Victron ESS-ID", description = "ESS-ID to which the batteryinverter is connected to")
String ess_id() default "ess0";

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

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import static org.osgi.service.component.annotations.ConfigurationPolicy.REQUIRE;
import static org.osgi.service.component.annotations.ReferenceCardinality.MANDATORY;
import static org.osgi.service.component.annotations.ReferenceCardinality.MULTIPLE;
import static org.osgi.service.component.annotations.ReferenceCardinality.OPTIONAL;
import static org.osgi.service.component.annotations.ReferencePolicy.DYNAMIC;
import static org.osgi.service.component.annotations.ReferencePolicy.STATIC;
import static org.osgi.service.component.annotations.ReferencePolicyOption.GREEDY;
Expand Down Expand Up @@ -47,7 +46,6 @@
import io.openems.edge.controller.ess.emergencycapacityreserve.ControllerEssEmergencyCapacityReserve;
import io.openems.edge.controller.ess.limittotaldischarge.ControllerEssLimitTotalDischarge;
import io.openems.edge.victron.batteryinverter.VictronBatteryInverterImpl;
import io.openems.edge.victron.ess.VictronEss;

@Designate(ocd = Config.class, factory = true)
@Component(//
Expand Down Expand Up @@ -86,9 +84,6 @@ protected void setModbus(BridgeModbus modbus) {
super.setModbus(modbus);
}

@Reference(policy = DYNAMIC, policyOption = GREEDY, cardinality = OPTIONAL)
private volatile VictronEss ess;

@Reference(policy = DYNAMIC, policyOption = GREEDY, cardinality = MULTIPLE, target = "(&(enabled=true)(isReserveSocEnabled=true))")
private volatile List<ControllerEssEmergencyCapacityReserve> ctrlEmergencyCapacityReserves = new CopyOnWriteArrayList<>();

Expand All @@ -102,15 +97,10 @@ protected void activate(ComponentContext context, Config config) throws OpenemsN
this.config = config;

if (super.activate(context, config.id(), config.alias(), config.enabled(), DEFAULT_UNIT_ID, this.cm, "Modbus",
config.modbus_id())
|| OpenemsComponent.updateReferenceFilter(this.cm, this.servicePid(), "Ess", config.ess_id())) {
config.modbus_id())) {
return;
}

if (this.ess != null) {
this.ess.setBattery(this);
}

this.installListener();
}

Expand Down Expand Up @@ -142,13 +132,6 @@ public void setStartStop(StartStop value) throws OpenemsNamedException {
}

private void checkSocControllers() {
if (this.ess == null) {
this.logDebug(this.log, "No Controller active on ESS, exiting.");
this.minSocPercentage = 0;
this.maxSocPercentage = 100;
return;
}

this.minSocPercentage = Utils.getEssMinSocPercentage(this.ctrlLimitTotalDischarges,
this.ctrlEmergencyCapacityReserves);
this.maxSocPercentage = 100; // Default max SoC
Expand All @@ -160,11 +143,6 @@ private void checkSocControllers() {
private void installListener() {
this.getCapacityInAmphoursChannel().onUpdate(value -> {

if (this.ess == null) {
this.logError(this.log, "No ESS reference available.");
return;
}

// Check if value is null or invalid
if (value == null) {
this.logError(this.log, "Invalid capacity value received.");
Expand All @@ -182,7 +160,7 @@ private void installListener() {

this.logDebug(this.log, "Current State of Charge (SoC): " + soc);

// Update SoC limits
// Update SoC limits from controllers
this.checkSocControllers();
this.logDebug(this.log,
"SoC limits updated - MinSoC: " + this.minSocPercentage + ", MaxSoC: " + this.maxSocPercentage);
Expand All @@ -199,33 +177,10 @@ private void installListener() {
// Calculate total capacity in watt-hours
int totalCapacityWh = totalCapacityAh * BATTERY_VOLTAGE;

// Calculate the usable SoC within the MinSoC and MaxSoC limits
int useableSoc = soc > this.maxSocPercentage ? 100
: soc < this.minSocPercentage ? 0
: (int) (((double) (soc - this.minSocPercentage)
/ (this.maxSocPercentage - this.minSocPercentage)) * 100);
this.logDebug(this.log, "Normalized usable SoC: " + useableSoc + "% based on current SoC: " + soc);

// Calculate the usable capacity based on MinSoC and MaxSoC limits
// First, calculate the percentage of capacity that can be used between MinSoC
// and MaxSoC
double usableCapacityRange = (this.maxSocPercentage - this.minSocPercentage) / 100.0;
// Usable capacity within min and max SoC range
int totalUsableCapacityWh = (int) (totalCapacityWh * usableCapacityRange);

// Now calculate the current usable capacity based on the usable SoC
int useableCapacityWh = (int) (totalUsableCapacityWh * (useableSoc / 100.0));

// Ensure useableCapacityWh is within valid bounds (0 to totalUsableCapacityWh)
useableCapacityWh = Math.max(Math.min(useableCapacityWh, totalUsableCapacityWh), 0);

// Set the capacities in ESS
// Set the capacity on Battery
this._setCapacity(totalCapacityWh);
this.ess._setUseableSoc(useableSoc);
this.ess._setUseableCapacity(useableCapacityWh);

this.logDebug(this.log, "installListener: SoC: real|usable " + soc + "|" + useableSoc
+ "[%] Capacity real|usable " + totalCapacityWh + "|" + useableCapacityWh + " [Wh]");
this.logDebug(this.log, "installListener: SoC: " + soc + "[%] Capacity: " + totalCapacityWh + " [Wh]");
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,6 @@
@AttributeDefinition(name = "Read-Only mode", description = "Enables Read-Only mode")
boolean readOnlyMode() default false;

@AttributeDefinition(name = "Victron ESS-ID", description = "ESS-ID to which the batteryinverter is connected to")
String ess_id() default "ess0";

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

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import io.openems.edge.common.component.OpenemsComponent;
import io.openems.edge.common.modbusslave.ModbusSlave;
import io.openems.edge.common.startstop.StartStoppable;
import io.openems.edge.victron.battery.VictronBattery;
import io.openems.edge.victron.batteryinverter.statemachine.StateMachine.State;
import io.openems.edge.victron.enums.ActiveInactive;
import io.openems.edge.victron.enums.ActiveInputSource;
Expand Down Expand Up @@ -875,20 +874,6 @@ public default IntegerReadChannel getMaxChargeVoltageChannel() {
return this.channel(ChannelId.MAX_CHARGE_VOLTAGE);
}

/**
* Sets the battery reference.
*
* @param battery the {@link VictronBattery}
*/
public void setBattery(VictronBattery battery);

/**
* Unsets the battery reference.
*
* @param battery the {@link VictronBattery}
*/
public void unsetBattery(VictronBattery battery);

/**
* Gets the maximum charge power in [W].
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import static io.openems.edge.common.event.EdgeEventConstants.TOPIC_CYCLE_BEFORE_PROCESS_IMAGE;
import static org.osgi.service.component.annotations.ConfigurationPolicy.REQUIRE;
import static org.osgi.service.component.annotations.ReferenceCardinality.MANDATORY;
import static org.osgi.service.component.annotations.ReferenceCardinality.OPTIONAL;
import static org.osgi.service.component.annotations.ReferencePolicy.STATIC;
import static org.osgi.service.component.annotations.ReferencePolicyOption.GREEDY;

Expand All @@ -22,7 +21,8 @@
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferencePolicy;
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 org.slf4j.Logger;
Expand Down Expand Up @@ -58,7 +58,6 @@
import io.openems.edge.ess.power.api.Power;
import io.openems.edge.ess.power.api.Pwr;
import io.openems.edge.ess.power.api.Relationship;
import io.openems.edge.victron.battery.VictronBattery;
import io.openems.edge.victron.batteryinverter.statemachine.Context;
import io.openems.edge.victron.batteryinverter.statemachine.StateMachine;
import io.openems.edge.victron.batteryinverter.statemachine.StateMachine.State;
Expand Down Expand Up @@ -91,8 +90,9 @@
TOPIC_CYCLE_BEFORE_PROCESS_IMAGE, //
TOPIC_CYCLE_AFTER_PROCESS_IMAGE //
})
public class VictronBatteryInverterImpl extends AbstractOpenemsModbusComponent implements VictronBatteryInverter,
ManagedSymmetricBatteryInverter, SymmetricBatteryInverter, OpenemsComponent, StartStoppable, ModbusSlave {
public class VictronBatteryInverterImpl extends AbstractOpenemsModbusComponent
implements VictronBatteryInverter, ManagedSymmetricBatteryInverter, SymmetricBatteryInverter, OpenemsComponent,
StartStoppable, ModbusSlave, EventHandler {

private final Logger log = LoggerFactory.getLogger(VictronBatteryInverterImpl.class);

Expand Down Expand Up @@ -128,24 +128,10 @@ protected void setModbus(BridgeModbus modbus) {
super.setModbus(modbus);
}

@Reference(policy = ReferencePolicy.DYNAMIC, policyOption = GREEDY, cardinality = OPTIONAL)
private volatile VictronEss ess;

@Reference(policy = STATIC, policyOption = GREEDY, cardinality = OPTIONAL)
private VictronBattery battery;

@Reference(cardinality = OPTIONAL, policy = STATIC)
@Override
public synchronized void setBattery(VictronBattery battery) {
this.battery = battery;
}

@Override
public synchronized void unsetBattery(VictronBattery battery) {
if (this.battery == battery) {
this.battery = null;
}
}
/**
* Battery reference, set via run() method from ESS.
*/
private volatile Battery battery;

private Integer batteryInverterMaxChargePower;
private Integer batteryInverterMaxDischargePower;
Expand All @@ -163,14 +149,10 @@ protected void activate(ComponentContext context, Config config) throws OpenemsN
return;
}

OpenemsComponent.updateReferenceFilter(this.cm, this.servicePid(), "Ess", config.ess_id());

this._setMaxApparentPower(this.config.DeviceType().getApparentPowerLimit());
this._setGridMode(GridMode.ON_GRID);

if (this.ess != null) {
this.ess.setBatteryInverter(this);
}
// Note: ESS binds to this BatteryInverter via its own @Reference - no callback
// needed
}

@Override
Expand All @@ -179,6 +161,21 @@ protected void deactivate() {
super.deactivate();
}

@Override
public void handleEvent(Event event) {
if (!this.isEnabled()) {
return;
}
switch (event.getTopic()) {
case TOPIC_CYCLE_BEFORE_PROCESS_IMAGE -> {
// Prepare for cycle
}
case TOPIC_CYCLE_AFTER_PROCESS_IMAGE -> {
this.calculateHardwareLimits();
}
}
}

/**
* Calculates and sets the maximum charge and discharge power limits based on
* hardware capabilities and the shared configuration limit.
Expand Down Expand Up @@ -287,6 +284,9 @@ public void run(Battery battery, int setActivePower, int setReactivePower) throw
return;
}

// Store battery reference for limit calculations
this.battery = battery;

if (this.config.DeviceType() == DeviceType.UNDEFINED) {
this.logError(this.log, "Device Type of inverter not configured!");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public enum ChargeStateEss implements OptionsEnum {
ABSORPTION_REPEAT(5, "Absorption Repeat"), //
ABSORPTION_FORCED(6, "Absorption Forced"), //
EQUALIZE(7, "Equalize"), //
BULK_STOPPED(1, "Bulk Stopped"), //
BULK_STOPPED(8, "Bulk Stopped"), //
UNKNOWN(9, "Unknown");

private final int value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@
@AttributeDefinition(name = "Is enabled?", description = "Is this Component enabled?")
boolean enabled() default true;

@AttributeDefinition(name = "Battery-Inverter-ID", description = "ID of Battery-Inverter.")
String batteryInverter_id() default "batteryInverter0";

@AttributeDefinition(name = "Battery-ID", description = "ID of Battery.")
String battery_id() default "battery0";

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

Expand All @@ -40,6 +46,12 @@
@AttributeDefinition(name = "Max Apparent Power", description = "Maximum apparent power in VA")
int maxApparentPower() default 5000;

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

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

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@
import io.openems.edge.common.component.OpenemsComponent;
import io.openems.edge.common.modbusslave.ModbusSlave;
import io.openems.edge.common.type.Phase.SinglePhase;
import io.openems.edge.victron.battery.VictronBattery;
import io.openems.edge.victron.batteryinverter.VictronBatteryInverter;
import io.openems.edge.victron.enums.ActiveInactive;
import io.openems.edge.victron.enums.ActiveInputSource;
import io.openems.edge.victron.enums.Alarm;
Expand Down Expand Up @@ -1143,34 +1141,6 @@ public default IntegerReadChannel getUseableSocChannel() {
return this.channel(ChannelId.USEABLE_SOC);
}

/**
* Sets the battery inverter reference.
*
* @param batteryInverter the {@link VictronBatteryInverter}
*/
public void setBatteryInverter(VictronBatteryInverter batteryInverter);

/**
* Unsets the battery inverter reference.
*
* @param batteryInverter the {@link VictronBatteryInverter}
*/
public void unsetBatteryInverter(VictronBatteryInverter batteryInverter);

/**
* Sets the battery reference.
*
* @param battery the {@link VictronBattery}
*/
public void setBattery(VictronBattery battery);

/**
* Unsets the battery reference.
*
* @param battery the {@link VictronBattery}
*/
public void unsetBattery(VictronBattery battery);

/**
* Gets the phase the ESS is connected to.
*
Expand Down
Loading
Loading