Skip to content

Commit

Permalink
[fronius] Add action to set reserve battery capacity
Browse files Browse the repository at this point in the history
Signed-off-by: Florian Hotze <[email protected]>
  • Loading branch information
florian-h05 committed Jan 20, 2025
1 parent d0b918e commit 0c7bc3f
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 0 deletions.
4 changes: 4 additions & 0 deletions bundles/org.openhab.binding.fronius/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ Once the actions instance has been retrieved, you can invoke the following metho
- `forceBatteryCharging(QuantityType<Power> power)`: Force the battery to charge with the specified power (removes all battery control schedules first and applies all the time).
- `addForcedBatteryChargingSchedule(LocalTime from, LocalTime until, QuantityType<Power> power)`: Add a schedule to force the battery to charge with the specified power in the specified time range.
- `addForcedBatteryChargingSchedule(ZonedDateTime from, ZonedDateTime until, QuantityType<Power> power)`: Add a schedule to force the battery to charge with the specified power in the specified time range.
- `setBackupReservedBatteryCapacity(int percent)`: Set the reserved battery capacity for backup power.
- `setBackupReservedBatteryCapacity(PercentType percent)`: Set the reserved battery capacity for backup power.

All methods return a boolean value indicating whether the action was successful.

Expand All @@ -201,6 +203,8 @@ froniusInverterActions.resetBatteryControl();
froniusInverterActions.addHoldBatteryChargeSchedule(time.toZDT('18:00'), time.toZDT('22:00'));
froniusInverterActions.addForcedBatteryChargingSchedule(time.toZDT('22:00'), time.toZDT('23:59'), Quantity('5 kW'));
froniusInverterActions.addForcedBatteryChargingSchedule(time.toZDT('00:00'), time.toZDT('06:00'), Quantity('5 kW'));

froniusInverterActions.setBackupReservedBatteryCapacity(50);
```

## Full Example
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.openhab.core.automation.annotation.ActionInput;
import org.openhab.core.automation.annotation.ActionOutput;
import org.openhab.core.automation.annotation.RuleAction;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.thing.binding.ThingActions;
import org.openhab.core.thing.binding.ThingActionsScope;
Expand Down Expand Up @@ -97,6 +98,24 @@ public static boolean addForcedBatteryChargingSchedule(ThingActions actions, Zon
return addForcedBatteryChargingSchedule(actions, from.toLocalTime(), until.toLocalTime(), power);
}

public static boolean setBackupReservedBatteryCapacity(ThingActions actions, int percent) {
if (actions instanceof FroniusSymoInverterActions froniusSymoInverterActions) {
return froniusSymoInverterActions.setBackupReservedBatteryCapacity(percent);
} else {
throw new IllegalArgumentException(
"The 'actions' argument is not an instance of FroniusSymoInverterActions");
}
}

public static boolean setBackupReservedBatteryCapacity(ThingActions actions, PercentType percent) {
if (actions instanceof FroniusSymoInverterActions froniusSymoInverterActions) {
return froniusSymoInverterActions.setBackupReservedBatteryCapacity(percent);
} else {
throw new IllegalArgumentException(
"The 'actions' argument is not an instance of FroniusSymoInverterActions");
}
}

@Override
public void setThingHandler(@Nullable ThingHandler handler) {
this.handler = (FroniusSymoInverterHandler) handler;
Expand Down Expand Up @@ -166,4 +185,18 @@ public boolean addForcedBatteryChargingSchedule(ZonedDateTime from, ZonedDateTim
QuantityType<Power> power) {
return addForcedBatteryChargingSchedule(from.toLocalTime(), until.toLocalTime(), power);
}

@RuleAction(label = "@text/actions.backup-reserved-battery-capacity.label", description = "@text/actions.backup-reserved-battery-capacity.description")
public @ActionOutput(type = "boolean", label = "Success") boolean setBackupReservedBatteryCapacity(
@ActionInput(name = "percent", label = "@text/actions.soc.label", description = "@text/actions.soc.description", required = true) int percent) {
FroniusSymoInverterHandler handler = this.handler;
if (handler != null) {
return handler.setBackupReservedBatteryCapacity(new PercentType(percent));
}
return false;
}

public boolean setBackupReservedBatteryCapacity(PercentType percent) {
return setBackupReservedBatteryCapacity(percent.intValue());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.net.URI;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.Properties;

import javax.measure.quantity.Power;
Expand All @@ -32,6 +33,7 @@
import org.openhab.binding.fronius.internal.api.dto.inverter.batterycontrol.TimeOfUseRecords;
import org.openhab.binding.fronius.internal.api.dto.inverter.batterycontrol.TimeTableRecord;
import org.openhab.binding.fronius.internal.api.dto.inverter.batterycontrol.WeekdaysRecord;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.Units;
import org.slf4j.Logger;
Expand All @@ -49,6 +51,8 @@
@NonNullByDefault
public class FroniusBatteryControl {
private static final String TIME_OF_USE_ENDPOINT = "/config/timeofuse";
private static final String BATTERIES_ENDPOINT = "/config/batteries";
private static final String BACKUP_RESERVED_CAPACITY_PARAMETER = "HYB_BACKUP_RESERVED";

private static final Logger LOGGER = LoggerFactory.getLogger(FroniusBatteryControl.class);
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm");
Expand All @@ -64,13 +68,15 @@ public class FroniusBatteryControl {
private final String username;
private final String password;
private final URI timeOfUseUri;
private final URI batteriesUri;

public FroniusBatteryControl(HttpClient httpClient, URI baseUri, String username, String password) {
this.httpClient = httpClient;
this.baseUri = baseUri;
this.username = username;
this.password = password;
this.timeOfUseUri = baseUri.resolve(URI.create(TIME_OF_USE_ENDPOINT));
this.batteriesUri = baseUri.resolve(URI.create(BATTERIES_ENDPOINT));
}

/**
Expand Down Expand Up @@ -208,4 +214,36 @@ ScheduleType.CHARGE_MIN, new TimeTableRecord(from.format(TIME_FORMATTER), until.
timeOfUse[timeOfUse.length - 1] = holdCharge;
setTimeOfUse(new TimeOfUseRecords(timeOfUse));
}

/**
* Sets the reserved battery capacity for backup power.
*
* @param percent the reserved battery capacity for backup power
* @throws FroniusCommunicationException when an error occurs during communication with the inverter
* @throws IllegalArgumentException if the percent is not in [10,95]
* @throws FroniusUnauthorizedException when the login failed due to invalid credentials
*/
public void setBackupReservedCapacity(PercentType percent)
throws FroniusCommunicationException, FroniusUnauthorizedException {
if (percent.intValue() < 10 || percent.intValue() > 95) {
throw new IllegalArgumentException("invalid percent value: " + percent + " (must be in [10,95])");
}

// Login and get the auth header for the next request
String authHeader = FroniusConfigAuthUtil.login(httpClient, baseUri, username, password, HttpMethod.POST,
batteriesUri.getPath(), API_TIMEOUT);
Properties headers = new Properties();
headers.put(HttpHeader.AUTHORIZATION.asString(), authHeader);

// Set the setting
String json = gson.toJson(Map.of(BACKUP_RESERVED_CAPACITY_PARAMETER, percent.intValue()));
String responseString = FroniusHttpUtil.executeUrl(HttpMethod.POST, batteriesUri.toString(), headers,
new ByteArrayInputStream(json.getBytes()), "application/json", API_TIMEOUT);
PostConfigResponse response = gson.fromJson(responseString, PostConfigResponse.class);
if (!response.writeSuccess().contains(BACKUP_RESERVED_CAPACITY_PARAMETER)) {
LOGGER.debug("{}", responseString);
throw new FroniusCommunicationException("Failed to write configuration to inverter");
}
LOGGER.trace("Backup Reserved Capacity setting set successfully");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import org.openhab.binding.fronius.internal.api.dto.powerflow.PowerFlowRealtimeResponse;
import org.openhab.binding.fronius.internal.api.dto.powerflow.PowerFlowRealtimeSite;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.Units;
import org.openhab.core.thing.Thing;
Expand Down Expand Up @@ -185,6 +186,23 @@ public boolean addForcedBatteryChargingSchedule(LocalTime from, LocalTime until,
return false;
}

public boolean setBackupReservedBatteryCapacity(PercentType percent) {
FroniusBatteryControl batteryControl = getBatteryControl();
if (batteryControl != null) {
try {
batteryControl.setBackupReservedCapacity(percent);
return true;
} catch (IllegalArgumentException e) {
logger.warn("Failed to set backup reserved battery capacity: {}", e.getMessage());
} catch (FroniusCommunicationException e) {
logger.warn("Failed to set backup reserved battery capacity", e);
} catch (FroniusUnauthorizedException e) {
logger.warn("Failed to set backup reserved battery capacity: Invalid username or password");
}
}
return false;
}

/**
* Update the channel from the last data retrieved
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,13 @@ actions.force-battery-charging.label = Force Battery Charging
actions.force-battery-charging.description = Force the battery to charge with the specified power
actions.add-forced-battery-charging-schedule.label = Add Forced Battery Charging Schedule
actions.add-forced-battery-charging-schedule.description = Add a schedule to force the battery to charge with the specified power in the specified time range
actions.backup-reserved-battery-capacity.label = Backup Power Reserved Battery Capacity
actions.backup-reserved-battery-capacity.description = Set the reserved battery capacity for backup power supply
actions.from.label = Begin Timestamp
actions.from.description = The beginning of the time range
actions.until.label = End Timestamp
actions.until.description = The (inclusive) end of the time range
actions.power.label = Power
actions.power.description = The power to charge the battery with
actions.soc.label = State of Charge
actions.soc.description = Battery State of Charge (in percent)

0 comments on commit 0c7bc3f

Please sign in to comment.