Skip to content

Commit bd34ffb

Browse files
authored
[fronius] Add battery Thing type (#20650)
* [fronius] Add `battery` Thing type Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
1 parent f44930f commit bd34ffb

12 files changed

Lines changed: 759 additions & 21 deletions

File tree

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

Lines changed: 91 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ Inverters with integrated Solar API V1 support include:
1818
|-----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
1919
| `bridge` | The Bridge |
2020
| `powerinverter` | Fronius Galvo, Symo and other Fronius inverters: You can add multiple inverters that depend on the same datalogger with different device ids. (default id = 1) |
21+
| `battery` | Fronius Battery: Battery devices that map to storage controller fields (default id = 0) |
2122
| `meter` | Fronius Smart Meter: You can add multiple smart meters with different device ids. (default id = 0) |
22-
| `ohmpilot` | Fronius Ohmpilot ( default id = 0) |
23+
| `ohmpilot` | Fronius Ohmpilot (default id = 0) |
2324

2425
## Discovery
2526

@@ -44,27 +45,33 @@ The binding has no configuration options, all configuration is done at `bridge`,
4445
### Powerinverter Thing Configuration
4546

4647
| Parameter | Description |
47-
| ---------- | ------------------------------------------ |
48+
|------------|--------------------------------------------|
4849
| `deviceId` | The identifier of your device (Default: 1) |
4950

51+
### Battery Thing Configuration
52+
53+
| Parameter | Description |
54+
|------------|----------------------------------------------------|
55+
| `deviceId` | The identifier of your battery device (Default: 0) |
56+
5057
### Meter Thing Configuration
5158

5259
| Parameter | Description |
53-
| ---------- | ----------------------------------------------- |
60+
|------------|-------------------------------------------------|
5461
| `deviceId` | The identifier of your smart meter (Default: 0) |
5562

5663
### Ohmpilot Thing Configuration
5764

5865
| Parameter | Description |
59-
| ---------- | -------------------------------------------- |
66+
|------------|----------------------------------------------|
6067
| `deviceId` | The identifier of your ohmpilot (Default: 0) |
6168

6269
## Channels
6370

6471
### `powerinverter` Thing Channels
6572

6673
| Channel ID | Item Type | Description |
67-
| ------------------------------------ | ------------------------ | ----------------------------------------------------------------------------------------------------------------- |
74+
|--------------------------------------|--------------------------|-------------------------------------------------------------------------------------------------------------------|
6875
| `inverterdatachannelpac` | Number:Power | AC Power generated |
6976
| `inverterdatachannelpdc` | Number:Power | DC Power calculated from DC voltage * DC current |
7077
| `inverterdatachannelpdc2` | Number:Power | DC Power generated by MPPT tracker 2 |
@@ -94,10 +101,24 @@ The binding has no configuration options, all configuration is done at `bridge`,
94101
| `powerflowinverter1power` | Number:Power | Current power of inverter 1, null if not running (+ produce/export, - consume/import) - DEPRECATED |
95102
| `powerflowinverter1soc` | Number:Dimensionless | Current state of charge of inverter 1 in percent - DEPRECATED |
96103

104+
### `battery` Thing Channels
105+
106+
| Channel ID | Item Type | Description |
107+
|--------------------|--------------------------|----------------------------------------|
108+
| `maximumCapacity` | Number:Energy | Current maximum battery capacity in Wh |
109+
| `designedCapacity` | Number:Energy | Designed battery capacity in Wh |
110+
| `currentDc` | Number:ElectricCurrent | DC current |
111+
| `voltageDc` | Number:ElectricPotential | DC voltage |
112+
| `soc` | Number:Dimensionless | State of charge in percent |
113+
| `status` | String | Battery cell status code |
114+
| `enable` | Number | Enable flag for the battery controller |
115+
| `temperature` | Number:Temperature | Cell temperature |
116+
| `timestamp` | DateTime | Timestamp of the last measurement |
117+
97118
### `meter` Thing Channels
98119

99120
| Channel ID | Item Type | Description |
100-
| ----------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
121+
|-------------------------|--------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
101122
| `enable` | Number | 1 = enabled, 0 = disabled |
102123
| `location` | Number | 0 = grid interconnection point (primary meter)<br/> 1 = load (primary meter) <br />3 = external generator (secondary meters)(multiple)<br />256-511 = subloads (secondary meters)(unique). Refer to Fronius Solar API. |
103124
| `currentacphase1` | Number:ElectricCurrent | AC Current on Phase 1 |
@@ -119,7 +140,7 @@ The binding has no configuration options, all configuration is done at `bridge`,
119140
### `ohmpilot` Thing Channels
120141

121142
| Channel ID | Item Type | Description |
122-
| ----------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
143+
|-------------------------|--------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
123144
| `energyrealsumconsumed` | Number:Energy | Real Energy consumed |
124145
| `powerrealsum` | Number:Power | Real Power |
125146
| `temperaturechannel1` | Number:Temperature | Temperature |
@@ -128,17 +149,25 @@ The binding has no configuration options, all configuration is done at `bridge`,
128149

129150
## Properties
130151

152+
### `battery` Thing Properties
153+
154+
| Property | Description |
155+
|----------------|----------------------------------|
156+
| `vendor` | The manufacturer of the battery |
157+
| `modelId` | The model name of the battery |
158+
| `serialNumber` | The serial number of the battery |
159+
131160
### `meter` Thing Properties
132161

133162
| Property | Description |
134-
| -------------- | ------------------------------ |
163+
|----------------|--------------------------------|
135164
| `modelId` | The model name of the meter |
136165
| `serialNumber` | The serial number of the meter |
137166

138167
### `ohmpilot` Thing Properties
139168

140169
| Property | Description |
141-
| -------------- | --------------------------------- |
170+
|----------------|-----------------------------------|
142171
| `modelId` | The model name of the ohmpilot |
143172
| `serialNumber` | The serial number of the ohmpilot |
144173

@@ -172,6 +201,19 @@ var froniusInverterActions = actions.thingActions('fronius', 'fronius:powerinver
172201

173202
:::
174203

204+
::: tab JRuby
205+
206+
In JRuby, the action methods are attached to the Thing object.
207+
208+
```rb
209+
my_inverter = things["fronius:powerinverter:mybridge:myinverter"]
210+
211+
# call some actions
212+
my_inverter.prevent_battery_charging
213+
```
214+
215+
:::
216+
175217
::::
176218

177219
Where the first parameter must always be `fronius` and the second must be the full Thing UID of the inverter.
@@ -212,6 +254,10 @@ All methods return a boolean value indicating whether the action was successful.
212254

213255
### Examples
214256

257+
:::: tabs
258+
259+
::: tab JS
260+
215261
```javascript
216262
var froniusInverterActions = actions.thingActions('fronius', 'fronius:powerinverter:mybridge:myinverter');
217263

@@ -231,13 +277,41 @@ froniusInverterActions.addSchedule(time.toZDT('10:00'), time.toZDT('11:00'), 'DI
231277
froniusInverterActions.setBackupReservedBatteryCapacity(50);
232278
```
233279

280+
:::
281+
282+
::: tab JRuby
283+
284+
```rb
285+
inverter = things["fronius:powerinverter:mybridge:myinverter"]
286+
287+
inverter.reset_battery_control
288+
inverter.hold_battery_charge
289+
inverter.force_battery_charging(5 | "kW")
290+
291+
inverter.reset_battery_control
292+
inverter.add_hold_battery_charge_schedule(LocalTime.parse("18:00"), LocalTime.parse("22:00"))
293+
inverter.add_forced_battery_charging_schedule(LocalTime.parse("22:00"), LocalTime.parse("23:59"), 5 | "kW")
294+
inverter.add_forced_battery_charging_schedule(LocalTime.parse("00:00"), LocalTime.parse("06:00"), 5 | "kW")
295+
inverter.add_forced_battery_discharging_schedule(LocalTime.parse("07:00"), LocalTime.parse("09:00"))
296+
inverter.add_prevent_battery_charging_schedule(LocalTime.parse("09:00"), LocalTime.parse("12:00"))
297+
298+
inverter.add_schedule(LocalTime.parse("10:00"), LocalTime.parse("11:00"), 'DISCHARGE_MAX', 500 | "W")
299+
300+
inverter.set_backup_reserved_battery_capacity(50)
301+
```
302+
303+
:::
304+
305+
::::
306+
234307
## Full Example
235308

236309
demo.things:
237310

238311
```java
239312
Bridge fronius:bridge:mybridge [hostname="192.168.66.148", refreshInterval=5, username="customer", password="someSecretPassword", scheme="http"] {
240313
Thing powerinverter myinverter [deviceId=1]
314+
Thing battery mybattery [deviceId=0]
241315
Thing meter mymeter [deviceId=0]
242316
Thing ohmpilot myohmpilot [deviceId=0]
243317
}
@@ -291,6 +365,14 @@ Number:Power Ohmpilot_PowerSum { channel="fronius:ohmpilot:mybridge:myohmpilot:p
291365
Number:Temperature Ohmpilot_Temperature { channel="fronius:ohmpilot:mybridge:myohmpilot:temperaturechannel1" }
292366
Number Ohmpilot_State { channel="fronius:ohmpilot:mybridge:myohmpilot:statecode" }
293367
Number Ohmpilot_Errorcode { channel="fronius:ohmpilot:mybridge:myohmpilot:errorcode" }
368+
369+
Number:Energy Battery_MaxCapacity { channel="fronius:battery:mybridge:mybattery:maximumCapacity" }
370+
Number:Energy Battery_DesignedCapacity { channel="fronius:battery:mybridge:mybattery:designedCapacity" }
371+
Number:ElectricCurrent Battery_CurrentDC { channel="fronius:battery:mybridge:mybattery:currentDc" }
372+
Number:ElectricPotential Battery_VoltageDC { channel="fronius:battery:mybridge:mybattery:voltageDc" }
373+
Number:Dimensionless Battery_SOC { channel="fronius:battery:mybridge:mybattery:soc" }
374+
Number:Temperature Battery_Temperature { channel="fronius:battery:mybridge:mybattery:temperature" }
375+
DateTime Battery_Timestamp { channel="fronius:battery:mybridge:mybattery:timestamp" }
294376
```
295377

296378
Note: Make sure to turn on the **Night Mode** in the Display Settings on the Fronius inverter to keep it from going offline at night.

bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusBindingConstants.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public class FroniusBindingConstants {
3535
public static final ThingTypeUID THING_TYPE_INVERTER = new ThingTypeUID(BINDING_ID, "powerinverter");
3636
public static final ThingTypeUID THING_TYPE_METER = new ThingTypeUID(BINDING_ID, "meter");
3737
public static final ThingTypeUID THING_TYPE_OHMPILOT = new ThingTypeUID(BINDING_ID, "ohmpilot");
38+
public static final ThingTypeUID THING_TYPE_BATTERY = new ThingTypeUID(BINDING_ID, "battery");
3839

3940
// Inverter channels
4041
public static final String INVERTER_DATA_CHANNEL_DAY_ENERGY = "inverterdatachanneldayenergy";
@@ -97,12 +98,24 @@ public class FroniusBindingConstants {
9798
public static final String OHMPILOT_ERROR_CODE = "errorcode";
9899
public static final String OHMPILOT_STATE_CODE = "statecode";
99100

101+
// Battery channels
102+
public static final String BATTERY_CAPACITY_MAXIMUM = "maximumCapacity";
103+
public static final String BATTERY_DESIGNED_CAPACITY = "designedCapacity";
104+
public static final String BATTERY_CURRENT_DC = "currentDc";
105+
public static final String BATTERY_VOLTAGE_DC = "voltageDc";
106+
public static final String BATTERY_STATE_OF_CHARGE = "soc";
107+
public static final String BATTERY_STATUS_BATTERY_CELL = "status";
108+
public static final String BATTERY_ENABLE = "enable";
109+
public static final String BATTERY_TEMPERATURE_CELL = "temperature";
110+
public static final String BATTERY_TIMESTAMP = "timestamp";
111+
100112
// List of all Urls
101113
public static final String INVERTER_REALTIME_DATA_URL = "%SCHEME%://%IP%/solar_api/v1/GetInverterRealtimeData.cgi?Scope=Device&DeviceId=%DEVICEID%&DataCollection=CommonInverterData";
102114
public static final String INVERTER_INFO_URL = "%SCHEME%://%IP%/solar_api/v1/GetInverterInfo.cgi";
103115
public static final String POWERFLOW_REALTIME_DATA_URL = "%SCHEME%://%IP%/solar_api/v1/GetPowerFlowRealtimeData.fcgi";
104116
public static final String METER_REALTIME_DATA_URL = "%SCHEME%://%IP%/solar_api/v1/GetMeterRealtimeData.cgi?Scope=Device&DeviceId=%DEVICEID%&DataCollection=MeterRealtimeData";
105117
public static final String OHMPILOT_REALTIME_DATA_URL = "%SCHEME%://%IP%/solar_api/v1/GetOhmPilotRealtimeData.cgi?Scope=Device&DeviceId=%DEVICEID%";
118+
public static final String BATTERY_REALTIME_DATA_URL = "%SCHEME%://%IP%/solar_api/v1/GetStorageRealtimeData.cgi?Scope=Device&DeviceId=%DEVICEID%&DataCollection=StorageRealtimeData";
106119

107120
public static final int API_TIMEOUT = 5000;
108121
public static final int DEFAULT_REFRESH_PERIOD = 10;
@@ -127,6 +140,10 @@ public static String getOhmPilotDataUrl(String scheme, String ip, int deviceId)
127140
return parseUrl(OHMPILOT_REALTIME_DATA_URL, scheme, ip, deviceId);
128141
}
129142

143+
public static String getBatteryDataUrl(String scheme, String ip, int deviceId) {
144+
return parseUrl(BATTERY_REALTIME_DATA_URL, scheme, ip, deviceId);
145+
}
146+
130147
public static String parseUrl(String url, String scheme, String ip) {
131148
return url.replace("%SCHEME%", scheme).replace("%IP%", ip.trim());
132149
}

bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusHandlerFactory.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import org.eclipse.jdt.annotation.NonNullByDefault;
2121
import org.eclipse.jdt.annotation.Nullable;
22+
import org.openhab.binding.fronius.internal.handler.FroniusBatteryHandler;
2223
import org.openhab.binding.fronius.internal.handler.FroniusBridgeHandler;
2324
import org.openhab.binding.fronius.internal.handler.FroniusMeterHandler;
2425
import org.openhab.binding.fronius.internal.handler.FroniusOhmpilotHandler;
@@ -39,7 +40,9 @@
3940
* handlers.
4041
*
4142
* @author Thomas Rokohl - Initial contribution
43+
* @author Jimmy Tanagra - Added meter
4244
* @author Hannes Spenger - Added ohmpilot
45+
* @author Jimmy Tanagra - Added battery
4346
*/
4447
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.fronius")
4548
@NonNullByDefault
@@ -54,6 +57,7 @@ public class FroniusHandlerFactory extends BaseThingHandlerFactory {
5457
add(THING_TYPE_BRIDGE);
5558
add(THING_TYPE_METER);
5659
add(THING_TYPE_OHMPILOT);
60+
add(THING_TYPE_BATTERY);
5761
}
5862
};
5963

@@ -81,6 +85,8 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
8185
return new FroniusMeterHandler(thing);
8286
} else if (thingTypeUID.equals(THING_TYPE_OHMPILOT)) {
8387
return new FroniusOhmpilotHandler(thing);
88+
} else if (thingTypeUID.equals(THING_TYPE_BATTERY)) {
89+
return new FroniusBatteryHandler(thing);
8490
}
8591
return null;
8692
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright (c) 2010-2026 Contributors to the openHAB project
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0
10+
*
11+
* SPDX-License-Identifier: EPL-2.0
12+
*/
13+
package org.openhab.binding.fronius.internal.api.dto.storage;
14+
15+
import org.eclipse.jdt.annotation.NonNullByDefault;
16+
import org.eclipse.jdt.annotation.Nullable;
17+
18+
import com.google.gson.annotations.SerializedName;
19+
20+
/**
21+
* The {@link StorageController} is responsible for storing the "Controller" node
22+
* of the {@link StorageRealtimeResponse}.
23+
*
24+
* @author Jimmy Tanagra - Initial contribution
25+
*/
26+
@NonNullByDefault
27+
public class StorageController {
28+
@SerializedName("Capacity_Maximum")
29+
private double capacityMaximum;
30+
31+
@SerializedName("Current_DC")
32+
private double currentDC;
33+
34+
@SerializedName("DesignedCapacity")
35+
private double designedCapacity;
36+
37+
@SerializedName("Details")
38+
private @Nullable StorageDetails details;
39+
40+
@SerializedName("Enable")
41+
private int enable;
42+
43+
@SerializedName("StateOfCharge_Relative")
44+
private double stateOfChargeRelative;
45+
46+
@SerializedName("Status_BatteryCell")
47+
private @Nullable String statusBatteryCell;
48+
49+
@SerializedName("Temperature_Cell")
50+
private double temperatureCell;
51+
52+
@SerializedName("TimeStamp")
53+
private int timeStamp;
54+
55+
@SerializedName("Voltage_DC")
56+
private double voltageDC;
57+
58+
public double getCapacityMaximum() {
59+
return capacityMaximum;
60+
}
61+
62+
public double getCurrentDC() {
63+
return currentDC;
64+
}
65+
66+
public double getDesignedCapacity() {
67+
return designedCapacity;
68+
}
69+
70+
public @Nullable StorageDetails getDetails() {
71+
return details;
72+
}
73+
74+
public int getEnable() {
75+
return enable;
76+
}
77+
78+
public double getStateOfChargeRelative() {
79+
return stateOfChargeRelative;
80+
}
81+
82+
public @Nullable String getStatusBatteryCell() {
83+
return statusBatteryCell;
84+
}
85+
86+
public double getTemperatureCell() {
87+
return temperatureCell;
88+
}
89+
90+
public int getTimeStamp() {
91+
return timeStamp;
92+
}
93+
94+
public double getVoltageDC() {
95+
return voltageDC;
96+
}
97+
}

0 commit comments

Comments
 (0)