Skip to content

Commit e32f717

Browse files
authored
[sonnen] Add support to actively charge the battery from grid (openhab#18213)
* Initial commit for V3 sonnen binding. Added functionality for start/stop charging battery from grid. Signed-off-by: chingon007 <[email protected]>
1 parent 96def56 commit e32f717

File tree

9 files changed

+212
-47
lines changed

9 files changed

+212
-47
lines changed

bundles/org.openhab.binding.sonnen/README.md

+22-20
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,28 @@ If you want to use the V2 API, which supports more channels, you need to provide
2020

2121
The following channels are yet supported:
2222

23-
| Channel | Type | Access | Description |
24-
| ------------------------------ | ------------- | ------ | --------------------------------------------------------------------------------------- |
25-
| batteryChargingState | Switch | read | Indicates if the Battery is charging at that moment |
26-
| batteryCharging | Number:Power | read | Indicates the actual current charging the Battery. Otherwise 0. |
27-
| batteryDischargingState | Switch | read | Indicates if the Battery is discharging at that moment |
28-
| batteryDischarging | Number:Power | read | Indicates the actual current discharging the Battery. Otherwise 0. |
29-
| consumption | Number:Power | read | Indicates the actual consumption of the consumer in watt |
30-
| gridFeedIn | Number:Power | read | Indicates the actual current feeding to the Grid in watt.0 if nothing is feeded |
31-
| gridConsumption | Number:Power | read | Indicates the actual current consumption from the Grid in watt.0 if nothing is received |
32-
| solarProduction | Number:Power | read | Indicates the actual production of the Solar system in watt |
33-
| batteryLevel | Number | read | Indicates the actual Battery Level in % from 0 - 100 |
34-
| flowConsumptionBatteryState | Switch | read | Indicates if there is a current flow from Battery towards Consumption |
35-
| flowConsumptionGridState | Switch | read | Indicates if there is a current flow from Grid towards Consumption |
36-
| flowConsumptionProductionState | Switch | read | Indicates if there is a current flow from Solar Production towards Consumption |
37-
| flowGridBatteryState | Switch | read | Indicates if there is a current flow from Grid towards Battery |
38-
| flowProductionBatteryState | Switch | read | Indicates if there is a current flow from Production towards Battery |
39-
| energyImportedStateProduction | Number:Energy | read | Indicates the imported kWh Production |
40-
| energyExportedStateProduction | Number:Energy | read | Indicates the exported kWh Production |
41-
| energyImportedStateConsumption | Number:Energy | read | Indicates the imported kWh Consumption |
42-
| energyExportedStateConsumption | Number:Energy | read | Indicates the exported kWh Consumption |
23+
| Channel | Type | Access | Description |
24+
|--------------------------------|---------------|------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
25+
| batteryChargingState | Switch | read | Indicates if the Battery is charging at that moment |
26+
| batteryCharging | Number:Power | read | Indicates the actual current charging the Battery. Otherwise 0. |
27+
| batteryDischargingState | Switch | read | Indicates if the Battery is discharging at that moment |
28+
| batteryDischarging | Number:Power | read | Indicates the actual current discharging the Battery. Otherwise 0. |
29+
| consumption | Number:Power | read | Indicates the actual consumption of the consumer in watt |
30+
| gridFeedIn | Number:Power | read | Indicates the actual current feeding to the Grid in watt.0 if nothing is feeded |
31+
| gridConsumption | Number:Power | read | Indicates the actual current consumption from the Grid in watt.0 if nothing is received |
32+
| solarProduction | Number:Power | read | Indicates the actual production of the Solar system in watt |
33+
| batteryLevel | Number | read | Indicates the actual Battery Level in % from 0 - 100 |
34+
| flowConsumptionBatteryState | Switch | read | Indicates if there is a current flow from Battery towards Consumption |
35+
| flowConsumptionGridState | Switch | read | Indicates if there is a current flow from Grid towards Consumption |
36+
| flowConsumptionProductionState | Switch | read | Indicates if there is a current flow from Solar Production towards Consumption |
37+
| flowGridBatteryState | Switch | read | Indicates if there is a current flow from Grid towards Battery |
38+
| flowProductionBatteryState | Switch | read | Indicates if there is a current flow from Production towards Battery |
39+
| energyImportedStateProduction | Number:Energy | read | Indicates the imported kWh Production |
40+
| energyExportedStateProduction | Number:Energy | read | Indicates the exported kWh Production |
41+
| energyImportedStateConsumption | Number:Energy | read | Indicates the imported kWh Consumption |
42+
| energyExportedStateConsumption | Number:Energy | read | Indicates the exported kWh Consumption |
43+
| batteryChargingFromGrid | Switch | read/write | Starts and stops the active battery charging from Grid. Note: "Write-API" in Software-Integration page of the local web interface from the sonnen battery must be activated and the given token must be entered in authentication token field of the binding |
44+
| batteryOperationMode | String | read | Indicates if the Battery is operating in automatic or manual mode. Manual mode is required for active charging the battery. Assure that the battery is in automatic mode if you don't actively charge the battery.Changing the operation mode is happening with the channel "batteryChargingFromGrid" |
4345

4446
## Full Example
4547

bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/SonnenBindingConstants.java

+4
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,8 @@ public class SonnenBindingConstants {
5151
public static final String CHANNELENERGYEXPORTEDSTATEPRODUCTION = "energyExportedStateProduction";
5252
public static final String CHANNELENERGYIMPORTEDSTATECONSUMPTION = "energyImportedStateConsumption";
5353
public static final String CHANNELENERGYEXPORTEDSTATECONSUMPTION = "energyExportedStateConsumption";
54+
55+
// List of new Channel ids for battery charging from Grid
56+
public static final String CHANNELBATTERYCHARGINGGRID = "batteryChargingFromGrid";
57+
public static final String CHANNELBATTERYOPERATIONMODE = "batteryOperationMode";
5458
}

bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/SonnenConfiguration.java

+1
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@ public class SonnenConfiguration {
2525
public String hostIP = "";
2626
public int refreshInterval = 30;
2727
public String authToken = "";
28+
public int chargingPower = -1;
2829
}

bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/SonnenHandler.java

+51-15
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.openhab.binding.sonnen.internal.communication.SonnenJsonPowerMeterDataDTO;
2727
import org.openhab.core.library.types.OnOffType;
2828
import org.openhab.core.library.types.QuantityType;
29+
import org.openhab.core.library.types.StringType;
2930
import org.openhab.core.library.unit.Units;
3031
import org.openhab.core.thing.Channel;
3132
import org.openhab.core.thing.ChannelUID;
@@ -61,8 +62,6 @@ public class SonnenHandler extends BaseThingHandler {
6162

6263
private boolean sonnenAPIV2 = false;
6364

64-
private int disconnectionCounter = 0;
65-
6665
private Map<String, Boolean> linkedChannels = new HashMap<>();
6766

6867
public SonnenHandler(Thing thing) {
@@ -76,7 +75,7 @@ public void initialize() {
7675
config = getConfigAs(SonnenConfiguration.class);
7776
if (config.refreshInterval < 0 || config.refreshInterval > 1000) {
7877
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
79-
"Parameter 'refresh Rate' msut be in the range 0-1000!");
78+
"Parameter 'refresh Rate' must be in the range 0-1000.");
8079
return;
8180
}
8281
if (config.hostIP.isBlank()) {
@@ -114,16 +113,15 @@ private boolean updateBatteryData() {
114113
error = serviceCommunication.refreshBatteryConnectionAPICALLV1();
115114
}
116115
if (error.isEmpty()) {
116+
if (ThingStatus.OFFLINE.equals(getThing().getStatus())) {
117+
updateStatus(ThingStatus.UNKNOWN);
118+
}
117119
if (!ThingStatus.ONLINE.equals(getThing().getStatus())) {
118120
updateStatus(ThingStatus.ONLINE);
119-
disconnectionCounter = 0;
120121
}
121122
} else {
122-
disconnectionCounter++;
123123
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, error);
124-
if (disconnectionCounter < 60) {
125-
return true;
126-
}
124+
return false;
127125
}
128126
return error.isEmpty();
129127
}
@@ -161,9 +159,10 @@ private void startAutomaticRefresh() {
161159
}
162160

163161
private void refreshChannels() {
164-
updateBatteryData();
165-
for (Channel channel : getThing().getChannels()) {
166-
updateChannel(channel.getUID().getId());
162+
if (updateBatteryData()) {
163+
for (Channel channel : getThing().getChannels()) {
164+
updateChannel(channel.getUID().getId(), null);
165+
}
167166
}
168167
}
169168

@@ -175,7 +174,7 @@ public void channelLinked(ChannelUID channelUID) {
175174
automaticRefreshing = true;
176175
}
177176
verifyLinkedChannel(channelUID.getId());
178-
updateChannel(channelUID.getId());
177+
updateChannel(channelUID.getId(), null);
179178
}
180179

181180
@Override
@@ -188,7 +187,7 @@ public void channelUnlinked(ChannelUID channelUID) {
188187
}
189188
}
190189

191-
private void updateChannel(String channelId) {
190+
private void updateChannel(String channelId, @Nullable String putData) {
192191
if (isLinked(channelId)) {
193192
State state = null;
194193
SonnenJsonDataDTO data = serviceCommunication.getBatteryData();
@@ -278,6 +277,28 @@ private void updateChannel(String channelId) {
278277
case CHANNELFLOWPRODUCTIONGRIDSTATE:
279278
update(OnOffType.from(data.isFlowProductionGrid()), channelId);
280279
break;
280+
case CHANNELBATTERYCHARGINGGRID:
281+
if (putData != null) {
282+
serviceCommunication.startStopBatteryCharging(putData);
283+
// put it to true as switch was turned on if it goes into manual mode
284+
if (putData.contains("1")) {
285+
update(OnOffType.from(true), channelId);
286+
} else if (putData.contains("2")) {
287+
update(OnOffType.from(false), channelId);
288+
}
289+
} else {
290+
// Reflect the status of operation mode in the switch
291+
update(OnOffType.from(!data.isInAutomaticMode()), channelId);
292+
}
293+
break;
294+
case CHANNELBATTERYOPERATIONMODE:
295+
if (!data.isInAutomaticMode()) {
296+
state = new StringType("Manual");
297+
} else if (data.isInAutomaticMode()) {
298+
state = new StringType("Automatic");
299+
}
300+
update(state, channelId);
301+
break;
281302
}
282303
}
283304
} else {
@@ -314,8 +335,23 @@ private void update(@Nullable State state, String channelId) {
314335
@Override
315336
public void handleCommand(ChannelUID channelUID, Command command) {
316337
if (command == RefreshType.REFRESH) {
317-
updateBatteryData();
318-
updateChannel(channelUID.getId());
338+
if (updateBatteryData()) {
339+
updateChannel(channelUID.getId(), null);
340+
}
341+
}
342+
if (channelUID.getId().equals(CHANNELBATTERYCHARGINGGRID)) {
343+
String putData = null;
344+
if (command.equals(OnOffType.ON)) {
345+
// Set battery to manual mode with 1
346+
putData = "EM_OperatingMode=1";
347+
} else if (command.equals(OnOffType.OFF)) {
348+
// set battery to automatic mode with 2
349+
putData = "EM_OperatingMode=2";
350+
}
351+
if (putData != null) {
352+
logger.debug("Executing {} command", CHANNELBATTERYCHARGINGGRID);
353+
updateChannel(channelUID.getId(), putData);
354+
}
319355
}
320356
}
321357
}

0 commit comments

Comments
 (0)