]> git.basschouten.com Git - openhab-addons.git/commitdiff
[fronius] Add Autonomy and Self Consumption channels (#12420)
authorjimtng <2554958+jimtng@users.noreply.github.com>
Sun, 27 Mar 2022 17:10:24 +0000 (03:10 +1000)
committerGitHub <noreply@github.com>
Sun, 27 Mar 2022 17:10:24 +0000 (19:10 +0200)
* Add Autonomy and Self Consumption channels
* Change Inverter channels from DecimalType to QuantityType
* Convert ValueUnit to QuantityType, honour the unit from ValueUnit
* Replace custom unit converter with QuantityType's unit conversion
* Return QuantityType of zero for missing ValueUnit data, to be consistent with P_AC.
* Return UnDefType.NULL for other missing data
* De-duplicate URL parsing routine

Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
bundles/org.openhab.binding.fronius/README.md
bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusBindingConstants.java
bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/ValueUnit.java
bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBaseThingHandler.java
bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusMeterHandler.java
bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusOhmpilotHandler.java
bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusSymoInverterHandler.java
bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/math/KilowattConverter.java [deleted file]
bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/math/SiPrefixFactors.java [deleted file]
bundles/org.openhab.binding.fronius/src/main/resources/OH-INF/i18n/fronius.properties
bundles/org.openhab.binding.fronius/src/main/resources/OH-INF/thing/thing-types.xml

index 777d73c4467035a23896d4565789b61a44860ef5..ebe794dde1332b97f143e25e7e254fff11f989b0 100644 (file)
@@ -57,25 +57,27 @@ The binding has no configuration options, all configuration is done at `bridge`,
 
 ### Channels for `powerinverter` Thing
 
-| Channel ID                           | Item Type            | Description                                                                                                       |
-| ------------------------------------ | -------------------- | ----------------------------------------------------------------------------------------------------------------- |
-| `inverterdatachanneldayenergy`       | Number               | Energy generated on current day                                                                                   |
-| `inverterdatachannelpac`             | Number               | AC power                                                                                                          |
-| `inverterdatachanneltotal`           | Number               | Energy generated overall                                                                                          |
-| `inverterdatachannelyear`            | Number               | Energy generated in current year                                                                                  |
-| `inverterdatachannelfac`             | Number               | AC frequency                                                                                                      |
-| `inverterdatachanneliac`             | Number               | AC current                                                                                                        |
-| `inverterdatachannelidc`             | Number               | DC current                                                                                                        |
-| `inverterdatachanneluac`             | Number               | AC voltage                                                                                                        |
-| `inverterdatachanneludc`             | Number               | DC voltage                                                                                                        |
-| `inverterdatadevicestatuserrorcode`  | Number               | Device error code                                                                                                 |
-| `inverterdatadevicestatusstatuscode` | Number               | Device status code<br />`0` - `6` Startup<br />`7` Running <br />`8` Standby<br />`9` Bootloading<br />`10` Error |
-| `powerflowchannelpgrid`              | Number:Power         | Power (+ from grid, - to grid)                                                                                    |
-| `powerflowchannelpload`              | Number:Power         | Power (+ generator, - consumer)                                                                                   |
-| `powerflowchannelpakku`              | Number:Power         | Power (+ charge, - discharge)                                                                                     |
-| `powerflowchannelppv`                | Number:Power         | Power (+ production)                                                                                              |
-| `powerflowinverter1power`            | Number:Power         | Current power of inverter 1, null if not running (+ produce/export, - consume/import)                             |
-| `powerflowinverter1soc`              | Number:Dimensionless | Current state of charge of inverter 1 in percent                                                                  |
+| Channel ID                           | Item Type                | Description                                                                                                       |
+| ------------------------------------ | ------------------------ | ----------------------------------------------------------------------------------------------------------------- |
+| `inverterdatachannelpac`             | Number:Power             | Power generated                                                                                                   |
+| `inverterdatachannelfac`             | Number:Frequency         | AC frequency                                                                                                      |
+| `inverterdatachanneliac`             | Number:ElectricCurrent   | AC current                                                                                                        |
+| `inverterdatachannelidc`             | Number:ElectricCurrent   | DC current                                                                                                        |
+| `inverterdatachanneluac`             | Number:ElectricPotential | AC voltage                                                                                                        |
+| `inverterdatachanneludc`             | Number:ElectricPotential | DC voltage                                                                                                        |
+| `inverterdatachanneldayenergy`       | Number:Energy            | Energy generated on current day                                                                                   |
+| `inverterdatachannelyear`            | Number:Energy            | Energy generated in current year                                                                                  |
+| `inverterdatachanneltotal`           | Number:Energy            | Energy generated overall                                                                                          |
+| `inverterdatadevicestatuserrorcode`  | Number                   | Device error code                                                                                                 |
+| `inverterdatadevicestatusstatuscode` | Number                   | Device status code<br />`0` - `6` Startup<br />`7` Running <br />`8` Standby<br />`9` Bootloading<br />`10` Error |
+| `powerflowchannelpgrid`              | Number:Power             | Grid Power (+ from grid, - to grid)                                                                               |
+| `powerflowchannelpload`              | Number:Power             | Load Power (+ generator, - consumer)                                                                              |
+| `powerflowchannelpakku`              | Number:Power             | Battery Power (+ charge, - discharge)                                                                             |
+| `powerflowchannelppv`                | Number:Power             | Solar Power (+ production)                                                                                              |
+| `powerflowautonomy`                  | Number:Dimensionless     | The current relative autonomy in %                                                                                |
+| `powerflowselfconsumption`           | Number:Dimensionless     | The current relative self consumption in %                                                                        |
+| `powerflowinverter1power`            | Number:Power             | Current power of inverter 1, null if not running (+ produce/export, - consume/import)                             |
+| `powerflowinverter1soc`              | Number:Dimensionless     | Current state of charge of inverter 1 in percent                                                                  |
 
 ### Channels for `meter` Thing
 
@@ -98,7 +100,6 @@ The binding has no configuration options, all configuration is done at `bridge`,
 | `powerfactorphase3`     | Number                   | Power Factor on Phase 3                                                                                                                                                                                                  |
 | `energyrealsumconsumed` | Number:Energy            | Real Energy consumed                                                                                                                                                                                                     |
 | `energyrealsumproduced` | Number:Energy            | Real Energy produced                                                                                                                                                                                                     |
-|                         |
 
 
 ### Channels for `ohmpilot` Thing
@@ -110,7 +111,6 @@ The binding has no configuration options, all configuration is done at `bridge`,
 | `temperaturechannel1`   | Number:Temperature | Temperature                                                                                                                                                              |
 | `errorcode`             | Number             | Device error code                                                                                                                                                        |
 | `statecode`             | Number             | Device state code<br />`0` up and running <br />`1` keep minimum temperature <br />`2` legionella protection <br />`3` critical fault<br />`4` fault<br />`5` boost mode |
-|                         |
 
 
 ## Properties
@@ -144,21 +144,23 @@ Bridge fronius:bridge:mybridge [hostname="192.168.66.148", refreshInterval=5] {
 demo.items:
 
 ```
-Number AC_Power { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachannelpac" }
-Number Day_Energy { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneldayenergy" }
-Number Total_Energy { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneltotal" }
-Number Year_Energy { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachannelyear" }
-Number FAC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachannelfac" }
-Number IAC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneliac" }
-Number IDC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachannelidc" }
-Number UAC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneluac" }
-Number UDC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneludc" }
+Number:Power AC_Power { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachannelpac" }
+Number:Energy Day_Energy { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneldayenergy" }
+Number:Energy Total_Energy { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneltotal" }
+Number:Energy Year_Energy { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachannelyear" }
+Number:Frequency FAC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachannelfac" }
+Number:ElectricCurrent IAC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneliac" }
+Number:ElectricCurrent IDC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachannelidc" }
+Number:ElectricPotential UAC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneluac" }
+Number:ElectricPotential UDC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneludc" }
 Number ErrorCode { channel="fronius:powerinverter:mybridge:myinverter:inverterdatadevicestatuserrorcode" }
 Number StatusCode { channel="fronius:powerinverter:mybridge:myinverter:inverterdatadevicestatusstatuscode" }
 Number:Power Grid_Power { channel="fronius:powerinverter:mybridge:myinverter:powerflowchannelpgrid" }
 Number:Power Load_Power { channel="fronius:powerinverter:mybridge:myinverter:powerflowchannelpload" }
 Number:Power Battery_Power { channel="fronius:powerinverter:mybridge:myinverter:powerflowchannelpakku" }
 Number:Power Production_Power { channel="fronius:powerinverter:mybridge:myinverter:powerflowchannelppv" }
+Number:Dimensionless Power_Autonomy { channel="fronius:powerinverter:mybridge:myinverter:powerflowautonomy" }
+Number:Dimensionless Power_SelfConsumption { channel="fronius:powerinverter:mybridge:myinverter:powerflowselfconsumption" }
 Number:Power Inverter1_Power { channel="fronius:powerinverter:mybridge:myinverter:powerflowinverter1power" }
 Number:Dimensionless Inverter1_SOC { channel="fronius:powerinverter:mybridge:myinverter:powerflowinverter1soc" }
 
index 2067ec250d9cbf6d5d2ef1aec232150fb512389c..02e260d884583bfc1d771aeee437ee533568582d 100644 (file)
@@ -23,6 +23,7 @@ import org.openhab.core.thing.ThingTypeUID;
  * @author Peter Schraffl - Added device status and error status channels
  * @author Thomas Kordelle - Added inverter power, battery state of charge and PV solar yield
  * @author Hannes Spenger - Added ohmpilot & meter power sum
+ * @author Jimmy Tanagra - Implement a common url parsing method
  */
 @NonNullByDefault
 public class FroniusBindingConstants {
@@ -30,12 +31,12 @@ public class FroniusBindingConstants {
     private static final String BINDING_ID = "fronius";
 
     // List of all Thing Type UIDs
-    public static final ThingTypeUID THING_TYPE_INVERTER = new ThingTypeUID(BINDING_ID, "powerinverter");
     public static final ThingTypeUID THING_TYPE_BRIDGE = new ThingTypeUID(BINDING_ID, "bridge");
+    public static final ThingTypeUID THING_TYPE_INVERTER = new ThingTypeUID(BINDING_ID, "powerinverter");
     public static final ThingTypeUID THING_TYPE_METER = new ThingTypeUID(BINDING_ID, "meter");
     public static final ThingTypeUID THING_TYPE_OHMPILOT = new ThingTypeUID(BINDING_ID, "ohmpilot");
 
-    // List of all Channel ids
+    // Inverter channels
     public static final String INVERTER_DATA_CHANNEL_DAY_ENERGY = "inverterdatachanneldayenergy";
     public static final String INVERTER_DATA_CHANNEL_PAC = "inverterdatachannelpac";
     public static final String INVERTER_DATA_CHANNEL_TOTAL = "inverterdatachanneltotal";
@@ -47,10 +48,19 @@ public class FroniusBindingConstants {
     public static final String INVERTER_DATA_CHANNEL_UDC = "inverterdatachanneludc";
     public static final String INVERTER_DATA_CHANNEL_DEVICE_STATUS_ERROR_CODE = "inverterdatadevicestatuserrorcode";
     public static final String INVERTER_DATA_CHANNEL_DEVICE_STATUS_STATUS_CODE = "inverterdatadevicestatusstatuscode";
+
+    // Power Flow channels
     public static final String POWER_FLOW_P_GRID = "powerflowchannelpgrid";
     public static final String POWER_FLOW_P_LOAD = "powerflowchannelpload";
     public static final String POWER_FLOW_P_AKKU = "powerflowchannelpakku";
     public static final String POWER_FLOW_P_PV = "powerflowchannelppv";
+    public static final String POWER_FLOW_AUTONOMY = "powerflowautonomy";
+    public static final String POWER_FLOW_SELF_CONSUMPTION = "powerflowselfconsumption";
+
+    public static final String POWER_FLOW_INVERTER_1_POWER = "powerflowinverter1power";
+    public static final String POWER_FLOW_INVERTER_1_SOC = "powerflowinverter1soc";
+
+    // Meter channels
     public static final String METER_ENABLE = "enable";
     public static final String METER_LOCATION = "location";
     public static final String METER_CURRENT_AC_PHASE_1 = "currentacphase1";
@@ -68,29 +78,41 @@ public class FroniusBindingConstants {
     public static final String METER_POWER_FACTOR_PHASE_3 = "powerfactorphase3";
     public static final String METER_ENERGY_REAL_SUM_CONSUMED = "energyrealsumconsumed";
     public static final String METER_ENERGY_REAL_SUM_PRODUCED = "energyrealsumproduced";
+
+    // OhmPilot channels
     public static final String OHMPILOT_POWER_REAL_SUM = "powerrealsum";
     public static final String OHMPILOT_ENERGY_REAL_SUM_CONSUMED = "energyrealsumconsumed";
     public static final String OHMPILOT_ENERGY_SENSOR_TEMPERATURE_CHANNEL_1 = "temperaturechannel1";
     public static final String OHMPILOT_ERROR_CODE = "errorcode";
     public static final String OHMPILOT_STATE_CODE = "statecode";
 
-    /*
-     * part of POWERFLOW_REALTIME_DATA using Symo Gen24
-     * "Inverters" : {
-     * "1" : {
-     * "Battery_Mode" : "normal",
-     * "DT" : 1,
-     * "P" : 356,
-     * "SOC" : 95.199996948242188
-     * }
-     * },
-     */
-    public static final String POWER_FLOW_INVERTER_1_POWER = "powerflowinverter1power";
-    public static final String POWER_FLOW_INVERTER_1_SOC = "powerflowinverter1soc";
-
     // List of all Urls
     public static final String INVERTER_REALTIME_DATA_URL = "http://%IP%/solar_api/v1/GetInverterRealtimeData.cgi?Scope=Device&DeviceId=%DEVICEID%&DataCollection=CommonInverterData";
-    public static final String POWERFLOW_REALTIME_DATA = "http://%IP%/solar_api/v1/GetPowerFlowRealtimeData.fcgi";
+    public static final String POWERFLOW_REALTIME_DATA_URL = "http://%IP%/solar_api/v1/GetPowerFlowRealtimeData.fcgi";
     public static final String METER_REALTIME_DATA_URL = "http://%IP%/solar_api/v1/GetMeterRealtimeData.cgi?Scope=Device&DeviceId=%DEVICEID%&DataCollection=MeterRealtimeData";
     public static final String OHMPILOT_REALTIME_DATA_URL = "http://%IP%/solar_api/v1/GetOhmPilotRealtimeData.cgi?Scope=Device&DeviceId=%DEVICEID%";
+
+    public static String getInverterDataUrl(String ip, int deviceId) {
+        return parseUrl(INVERTER_REALTIME_DATA_URL, ip, deviceId);
+    }
+
+    public static String getPowerFlowDataUrl(String ip) {
+        return parseUrl(POWERFLOW_REALTIME_DATA_URL, ip);
+    }
+
+    public static String getMeterDataUrl(String ip, int deviceId) {
+        return parseUrl(METER_REALTIME_DATA_URL, ip, deviceId);
+    }
+
+    public static String getOhmPilotDataUrl(String ip, int deviceId) {
+        return parseUrl(OHMPILOT_REALTIME_DATA_URL, ip, deviceId);
+    }
+
+    public static String parseUrl(String url, String ip) {
+        return url.replace("%IP%", ip == null ? "" : ip.trim());
+    }
+
+    public static String parseUrl(String url, String ip, int deviceId) {
+        return parseUrl(url, ip).replace("%DEVICEID%", Integer.toString(deviceId));
+    }
 }
index 3820fd8c968ca773d404ddb5f0318bd723e09b99..79cd332143ddcf7f9b1d9bd2a14efd9e1bda3215 100644 (file)
  */
 package org.openhab.binding.fronius.internal.api;
 
-import org.openhab.binding.fronius.internal.math.KilowattConverter;
+import javax.measure.Unit;
+
+import org.openhab.core.library.types.QuantityType;
+import org.openhab.core.types.util.UnitUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.gson.annotations.SerializedName;
 
@@ -21,12 +26,14 @@ import com.google.gson.annotations.SerializedName;
  * a value
  *
  * @author Thomas Rokohl - Initial contribution
+ * @author Jimmy Tanagra - Add conversion to QuantityType
  */
 public class ValueUnit {
+
     @SerializedName("Value")
     private double value;
     @SerializedName("Unit")
-    private String unit;
+    private String unit = "";
 
     public double getValue() {
         return value;
@@ -37,14 +44,20 @@ public class ValueUnit {
     }
 
     public String getUnit() {
-        if (unit == null) {
-            unit = "";
-        }
-        return unit;
+        return this.unit == null ? "" : this.unit;
     }
 
     public void setUnit(String unit) {
-        this.setValue(KilowattConverter.convertTo(this.getValue(), this.getUnit(), unit));
         this.unit = unit;
     }
+
+    public QuantityType<?> asQuantityType() {
+        Unit<?> unit = UnitUtils.parseUnit(getUnit());
+        if (unit == null) {
+            final Logger logger = LoggerFactory.getLogger(ValueUnit.class);
+            logger.debug("The unit for ValueUnit ({})/({}) cannot be parsed", value, this.unit);
+            unit = QuantityType.ONE.getUnit();
+        }
+        return new QuantityType<>(value, unit);
+    }
 }
index f0caee8cf51c6adda7359b485405d28e08ba6210..5ab34576126ceaa8326c180e0afb2a4ff900c33f 100644 (file)
@@ -18,10 +18,6 @@ import org.openhab.binding.fronius.internal.FroniusCommunicationException;
 import org.openhab.binding.fronius.internal.FroniusHttpUtil;
 import org.openhab.binding.fronius.internal.api.BaseFroniusResponse;
 import org.openhab.binding.fronius.internal.api.HeadStatus;
-import org.openhab.binding.fronius.internal.api.ValueUnit;
-import org.openhab.core.library.types.DecimalType;
-import org.openhab.core.library.types.QuantityType;
-import org.openhab.core.library.types.StringType;
 import org.openhab.core.thing.Bridge;
 import org.openhab.core.thing.Channel;
 import org.openhab.core.thing.ChannelUID;
@@ -32,6 +28,7 @@ import org.openhab.core.thing.binding.BaseThingHandler;
 import org.openhab.core.types.Command;
 import org.openhab.core.types.RefreshType;
 import org.openhab.core.types.State;
+import org.openhab.core.types.UnDefType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -45,6 +42,8 @@ import com.google.gson.JsonSyntaxException;
  * @author Thomas Rokohl - Refactoring to merge the concepts
  * @author Thomas Kordelle - Added inverter power, battery state of charge and PV solar yield
  * @author Jimmy Tanagra - Implement connection retry
+ *         Convert ValueUnit to QuantityType
+ *         Support NULL value
  */
 public abstract class FroniusBaseThingHandler extends BaseThingHandler {
 
@@ -100,31 +99,16 @@ public abstract class FroniusBaseThingHandler extends BaseThingHandler {
             return;
         }
 
-        Object value = getValue(channelId);
-        if (value == null) {
-            logger.debug("Value retrieved for channel '{}' was null. Can't update.", channelId);
-            return;
-        }
-
-        State state = null;
-        if (value instanceof QuantityType) {
-            state = (QuantityType) value;
-        } else if (value instanceof Number) {
-            state = new DecimalType((Number) value);
-        } else if (value instanceof ValueUnit) {
-            state = new DecimalType(((ValueUnit) value).getValue());
-        } else if (value instanceof String) {
-            state = new StringType((String) value);
-        } else {
-            logger.warn("Update channel {}: Unsupported value type {}", channelId, value.getClass().getSimpleName());
+        State state = getValue(channelId);
+        if (state == null) {
+            state = UnDefType.NULL;
         }
-        logger.trace("Update channel {} with state {} ({})", channelId, (state == null) ? "null" : state.toString(),
-                value.getClass().getSimpleName());
 
-        // Update the channel
-        if (state != null) {
-            updateState(channelId, state);
+        if (logger.isTraceEnabled()) {
+            logger.trace("Update channel {} with state {} ({})", channelId, state.toString(),
+                    state.getClass().getSimpleName());
         }
+        updateState(channelId, state);
     }
 
     /**
@@ -140,7 +124,7 @@ public abstract class FroniusBaseThingHandler extends BaseThingHandler {
      * @param channelId the id identifying the channel
      * @return the "new" associated value
      */
-    protected abstract Object getValue(String channelId);
+    protected abstract State getValue(String channelId);
 
     /**
      * Called by the bridge to fetch data and update channels
index 5d3910275ed6898409c7afc04e3be5e537286f00..2b62ef9f7c0f10897bb05c566b529265895a954b 100644 (file)
@@ -20,9 +20,11 @@ import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration;
 import org.openhab.binding.fronius.internal.FroniusCommunicationException;
 import org.openhab.binding.fronius.internal.api.MeterRealtimeBodyDataDTO;
 import org.openhab.binding.fronius.internal.api.MeterRealtimeResponseDTO;
+import org.openhab.core.library.types.DecimalType;
 import org.openhab.core.library.types.QuantityType;
 import org.openhab.core.library.unit.Units;
 import org.openhab.core.thing.Thing;
+import org.openhab.core.types.State;
 
 /**
  * The {@link FroniusMeterHandler} is responsible for updating the data, which are
@@ -66,7 +68,7 @@ public class FroniusMeterHandler extends FroniusBaseThingHandler {
      * @return the last retrieved data
      */
     @Override
-    protected Object getValue(String channelId) {
+    protected State getValue(String channelId) {
         if (meterRealtimeBodyData == null) {
             return null;
         }
@@ -79,9 +81,9 @@ public class FroniusMeterHandler extends FroniusBaseThingHandler {
 
         switch (fieldName) {
             case FroniusBindingConstants.METER_ENABLE:
-                return meterRealtimeBodyData.getEnable();
+                return new DecimalType(meterRealtimeBodyData.getEnable());
             case FroniusBindingConstants.METER_LOCATION:
-                return meterRealtimeBodyData.getMeterLocationCurrent();
+                return new DecimalType(meterRealtimeBodyData.getMeterLocationCurrent());
             case FroniusBindingConstants.METER_CURRENT_AC_PHASE_1:
                 return new QuantityType<>(meterRealtimeBodyData.getCurrentACPhase1(), Units.AMPERE);
             case FroniusBindingConstants.METER_CURRENT_AC_PHASE_2:
@@ -103,11 +105,11 @@ public class FroniusMeterHandler extends FroniusBaseThingHandler {
             case FroniusBindingConstants.METER_POWER_SUM:
                 return new QuantityType<>(meterRealtimeBodyData.getPowerRealPSum(), Units.WATT);
             case FroniusBindingConstants.METER_POWER_FACTOR_PHASE_1:
-                return meterRealtimeBodyData.getPowerFactorPhase1();
+                return new DecimalType(meterRealtimeBodyData.getPowerFactorPhase1());
             case FroniusBindingConstants.METER_POWER_FACTOR_PHASE_2:
-                return meterRealtimeBodyData.getPowerFactorPhase2();
+                return new DecimalType(meterRealtimeBodyData.getPowerFactorPhase2());
             case FroniusBindingConstants.METER_POWER_FACTOR_PHASE_3:
-                return meterRealtimeBodyData.getPowerFactorPhase3();
+                return new DecimalType(meterRealtimeBodyData.getPowerFactorPhase3());
             case FroniusBindingConstants.METER_ENERGY_REAL_SUM_CONSUMED:
                 return new QuantityType<>(meterRealtimeBodyData.getEnergyRealWACSumConsumed(), Units.WATT_HOUR);
             case FroniusBindingConstants.METER_ENERGY_REAL_SUM_PRODUCED:
@@ -151,9 +153,7 @@ public class FroniusMeterHandler extends FroniusBaseThingHandler {
      */
     private MeterRealtimeResponseDTO getMeterRealtimeData(String ip, int deviceId)
             throws FroniusCommunicationException {
-        String location = FroniusBindingConstants.METER_REALTIME_DATA_URL.replace("%IP%",
-                (ip != null ? ip.trim() : ""));
-        location = location.replace("%DEVICEID%", Integer.toString(deviceId));
+        String location = FroniusBindingConstants.getMeterDataUrl(ip, deviceId);
         return collectDataFromUrl(MeterRealtimeResponseDTO.class, location);
     }
 }
index a61917a967a5b3877b67a7a9417448c16384ff83..11dfd1dd7367bd1ff3e00608cdecfd01e15668c5 100644 (file)
@@ -24,6 +24,7 @@ import org.openhab.core.library.types.DecimalType;
 import org.openhab.core.library.types.QuantityType;
 import org.openhab.core.library.unit.Units;
 import org.openhab.core.thing.Thing;
+import org.openhab.core.types.State;
 
 /**
  * The {@link FroniusOhmpilotHandler} is responsible for updating the data, which are
@@ -66,7 +67,7 @@ public class FroniusOhmpilotHandler extends FroniusBaseThingHandler {
      * @return the last retrieved data
      */
     @Override
-    protected Object getValue(String channelId) {
+    protected State getValue(String channelId) {
         if (ohmpilotRealtimeBodyData == null) {
             return null;
         }
@@ -128,9 +129,7 @@ public class FroniusOhmpilotHandler extends FroniusBaseThingHandler {
      */
     private OhmpilotRealtimeResponseDTO getOhmpilotRealtimeData(String ip, int deviceId)
             throws FroniusCommunicationException {
-        String location = FroniusBindingConstants.OHMPILOT_REALTIME_DATA_URL.replace("%IP%",
-                (ip != null ? ip.trim() : ""));
-        location = location.replace("%DEVICEID%", Integer.toString(deviceId));
+        String location = FroniusBindingConstants.getOhmPilotDataUrl(ip, deviceId);
         return collectDataFromUrl(OhmpilotRealtimeResponseDTO.class, location);
     }
 }
index d5ea05953febe5483fb305e68170cbc3c28786cc..1cada21e3cbf4218dc46cbb209d95f6dc3465dd2 100644 (file)
  */
 package org.openhab.binding.fronius.internal.handler;
 
-import java.util.Map;
+import java.util.Optional;
+
+import javax.measure.Unit;
 
 import org.openhab.binding.fronius.internal.FroniusBaseDeviceConfiguration;
 import org.openhab.binding.fronius.internal.FroniusBindingConstants;
 import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration;
 import org.openhab.binding.fronius.internal.FroniusCommunicationException;
+import org.openhab.binding.fronius.internal.api.InverterRealtimeBodyData;
 import org.openhab.binding.fronius.internal.api.InverterRealtimeResponse;
 import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeInverter;
 import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeResponse;
+import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeSite;
 import org.openhab.binding.fronius.internal.api.ValueUnit;
+import org.openhab.core.library.types.DecimalType;
 import org.openhab.core.library.types.QuantityType;
 import org.openhab.core.library.unit.Units;
 import org.openhab.core.thing.Thing;
+import org.openhab.core.types.State;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -35,14 +41,10 @@ import org.slf4j.LoggerFactory;
  * @author Thomas Rokohl - Initial contribution
  * @author Peter Schraffl - Added device status and error status channels
  * @author Thomas Kordelle - Added inverter power, battery state of charge and PV solar yield
+ * @author Jimmy Tanagra - Add powerflow autonomy, self consumption channels
  */
 public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
 
-    /* power produced/handled by the inverter. */
-    public static final String INVERTER_POWER = "power";
-    /* state of charge of the battery or other storage device */
-    public static final String INVERTER_SOC = "soc";
-
     private final Logger logger = LoggerFactory.getLogger(FroniusSymoInverterHandler.class);
     private InverterRealtimeResponse inverterRealtimeResponse;
     private PowerFlowRealtimeResponse powerFlowResponse;
@@ -76,7 +78,7 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
      * @return the last retrieved data
      */
     @Override
-    protected Object getValue(String channelId) {
+    protected State getValue(String channelId) {
         final String[] fields = channelId.split("#");
         if (fields.length < 1) {
             return null;
@@ -84,65 +86,57 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
         final String fieldName = fields[0];
 
         if (inverterRealtimeResponse != null) {
+            InverterRealtimeBodyData inverterData = inverterRealtimeResponse.getBody().getData();
             switch (fieldName) {
-                case FroniusBindingConstants.INVERTER_DATA_CHANNEL_DAY_ENERGY:
-                    ValueUnit day = inverterRealtimeResponse.getBody().getData().getDayEnergy();
-                    if (day != null) {
-                        day.setUnit("kWh");
-                    }
-                    return day;
                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_PAC:
-                    ValueUnit pac = inverterRealtimeResponse.getBody().getData().getPac();
-                    if (pac == null) {
-                        pac = new ValueUnit();
-                        pac.setValue(0);
-                    }
-                    return pac;
-                case FroniusBindingConstants.INVERTER_DATA_CHANNEL_TOTAL:
-                    ValueUnit total = inverterRealtimeResponse.getBody().getData().getTotalEnergy();
-                    if (total != null) {
-                        total.setUnit("MWh");
-                    }
-                    return total;
-                case FroniusBindingConstants.INVERTER_DATA_CHANNEL_YEAR:
-                    ValueUnit year = inverterRealtimeResponse.getBody().getData().getYearEnergy();
-                    if (year != null) {
-                        year.setUnit("MWh");
-                    }
-                    return year;
+                    return getQuantityOrZero(inverterData.getPac(), Units.WATT);
                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_FAC:
-                    return inverterRealtimeResponse.getBody().getData().getFac();
+                    return getQuantityOrZero(inverterData.getFac(), Units.HERTZ);
                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_IAC:
-                    return inverterRealtimeResponse.getBody().getData().getIac();
+                    return getQuantityOrZero(inverterData.getIac(), Units.AMPERE);
                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_IDC:
-                    return inverterRealtimeResponse.getBody().getData().getIdc();
+                    return getQuantityOrZero(inverterData.getIdc(), Units.AMPERE);
                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_UAC:
-                    return inverterRealtimeResponse.getBody().getData().getUac();
+                    return getQuantityOrZero(inverterData.getUac(), Units.VOLT);
                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_UDC:
-                    return inverterRealtimeResponse.getBody().getData().getUdc();
+                    return getQuantityOrZero(inverterData.getUdc(), Units.VOLT);
+                case FroniusBindingConstants.INVERTER_DATA_CHANNEL_DAY_ENERGY:
+                    // Convert the unit to kWh for backwards compatibility with non-quantity type
+                    return getQuantityOrZero(inverterData.getDayEnergy(), Units.KILOWATT_HOUR).toUnit("kWh");
+                case FroniusBindingConstants.INVERTER_DATA_CHANNEL_TOTAL:
+                    // Convert the unit to MWh for backwards compatibility with non-quantity type
+                    return getQuantityOrZero(inverterData.getTotalEnergy(), Units.MEGAWATT_HOUR).toUnit("MWh");
+                case FroniusBindingConstants.INVERTER_DATA_CHANNEL_YEAR:
+                    // Convert the unit to MWh for backwards compatibility with non-quantity type
+                    return getQuantityOrZero(inverterData.getYearEnergy(), Units.MEGAWATT_HOUR).toUnit("MWh");
                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_DEVICE_STATUS_ERROR_CODE:
-                    return inverterRealtimeResponse.getBody().getData().getDeviceStatus().getErrorCode();
+                    return new DecimalType(inverterData.getDeviceStatus().getErrorCode());
                 case FroniusBindingConstants.INVERTER_DATA_CHANNEL_DEVICE_STATUS_STATUS_CODE:
-                    return inverterRealtimeResponse.getBody().getData().getDeviceStatus().getStatusCode();
+                    return new DecimalType(inverterData.getDeviceStatus().getStatusCode());
                 default:
                     break;
             }
         }
 
         if (powerFlowResponse != null) {
+            PowerFlowRealtimeSite site = powerFlowResponse.getBody().getData().getSite();
             switch (fieldName) {
                 case FroniusBindingConstants.POWER_FLOW_P_GRID:
-                    return new QuantityType<>(powerFlowResponse.getBody().getData().getSite().getPgrid(), Units.WATT);
+                    return new QuantityType<>(site.getPgrid(), Units.WATT);
                 case FroniusBindingConstants.POWER_FLOW_P_LOAD:
-                    return new QuantityType<>(powerFlowResponse.getBody().getData().getSite().getPload(), Units.WATT);
+                    return new QuantityType<>(site.getPload(), Units.WATT);
                 case FroniusBindingConstants.POWER_FLOW_P_AKKU:
-                    return new QuantityType<>(powerFlowResponse.getBody().getData().getSite().getPakku(), Units.WATT);
+                    return new QuantityType<>(site.getPakku(), Units.WATT);
                 case FroniusBindingConstants.POWER_FLOW_P_PV:
-                    return new QuantityType<>(powerFlowResponse.getBody().getData().getSite().getPpv(), Units.WATT);
+                    return new QuantityType<>(site.getPpv(), Units.WATT);
+                case FroniusBindingConstants.POWER_FLOW_AUTONOMY:
+                    return new QuantityType<>(site.getRelAutonomy(), Units.PERCENT);
+                case FroniusBindingConstants.POWER_FLOW_SELF_CONSUMPTION:
+                    return new QuantityType<>(site.getRelSelfConsumption(), Units.PERCENT);
                 case FroniusBindingConstants.POWER_FLOW_INVERTER_1_POWER:
-                    return getInverterFlowValue(INVERTER_POWER, "1");
+                    return new QuantityType<>(getInverter("1").getP(), Units.WATT);
                 case FroniusBindingConstants.POWER_FLOW_INVERTER_1_SOC:
-                    return getInverterFlowValue(INVERTER_SOC, "1");
+                    return new QuantityType<>(getInverter("1").getSoc(), Units.PERCENT);
                 default:
                     break;
             }
@@ -154,25 +148,24 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
     /**
      * get flow data for a specific inverter.
      *
-     * @param fieldName
-     * @param number
-     * @return
+     * @param number The inverter object of the given index
+     * @return an PowerFlowRealtimeInverter object.
      */
-    private Object getInverterFlowValue(final String fieldName, final String number) {
-        final Map<String, PowerFlowRealtimeInverter> inverters = powerFlowResponse.getBody().getData().getInverters();
-        if ((inverters == null) || (inverters.get(number) == null)) {
-            logger.debug("No data for inverter '{}' found.", number);
-            return null;
-        }
-        switch (fieldName) {
-            case INVERTER_POWER:
-                return new QuantityType<>(inverters.get(number).getP(), Units.WATT);
-            case INVERTER_SOC:
-                return new QuantityType<>(inverters.get(number).getSoc(), Units.PERCENT);
-            default:
-                break;
-        }
-        return null;
+    private PowerFlowRealtimeInverter getInverter(final String number) {
+        return powerFlowResponse.getBody().getData().getInverters().get(number);
+    }
+
+    /**
+     * Return the value as QuantityType with the unit extracted from ValueUnit
+     * or a zero QuantityType with the given unit argument when value is null
+     * 
+     * @param value The ValueUnit data
+     * @param unit The default unit to use when value is null
+     * @return a QuantityType from the given value
+     */
+    private QuantityType<?> getQuantityOrZero(ValueUnit value, Unit unit) {
+        return Optional.ofNullable(value).map(val -> val.asQuantityType().toUnit(unit))
+                .orElse(new QuantityType<>(0, unit));
     }
 
     /**
@@ -191,8 +184,7 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
      * @return {PowerFlowRealtimeResponse} the object representation of the json response
      */
     private PowerFlowRealtimeResponse getPowerFlowRealtime(String ip) throws FroniusCommunicationException {
-        String location = FroniusBindingConstants.POWERFLOW_REALTIME_DATA.replace("%IP%",
-                (ip != null ? ip.trim() : ""));
+        String location = FroniusBindingConstants.getPowerFlowDataUrl(ip);
         return collectDataFromUrl(PowerFlowRealtimeResponse.class, location);
     }
 
@@ -204,9 +196,7 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
      * @return {InverterRealtimeResponse} the object representation of the json response
      */
     private InverterRealtimeResponse getRealtimeData(String ip, int deviceId) throws FroniusCommunicationException {
-        String location = FroniusBindingConstants.INVERTER_REALTIME_DATA_URL.replace("%IP%",
-                (ip != null ? ip.trim() : ""));
-        location = location.replace("%DEVICEID%", Integer.toString(deviceId));
+        String location = FroniusBindingConstants.getInverterDataUrl(ip, deviceId);
         return collectDataFromUrl(InverterRealtimeResponse.class, location);
     }
 }
diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/math/KilowattConverter.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/math/KilowattConverter.java
deleted file mode 100644 (file)
index e1d0a06..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * Copyright (c) 2010-2022 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.fronius.internal.math;
-
-/**
- * Helper class for unit conversions
- *
- * @author Thomas Rokohl - Initial contribution
- *
- */
-public class KilowattConverter {
-
-    public static double getConvertFactor(String fromUnit, String toUnit) {
-        String adjustedFromUnit = fromUnit.replace("Wh", "");
-        String adjustedtoUnit = toUnit.replace("Wh", "");
-        return SiPrefixFactors.getFactorToBaseUnit(adjustedFromUnit) * 1
-                / SiPrefixFactors.getFactorToBaseUnit(adjustedtoUnit);
-    }
-
-    public static double convertTo(double value, String fromUnit, String toUnit) {
-        return value * getConvertFactor(fromUnit, toUnit);
-    }
-}
diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/math/SiPrefixFactors.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/math/SiPrefixFactors.java
deleted file mode 100644 (file)
index ef37ec9..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * Copyright (c) 2010-2022 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.fronius.internal.math;
-
-/**
- * Helper class for unit conversions
- *
- * @author Thomas Rokohl - Initial contribution
- *
- */
-public class SiPrefixFactors {
-
-    /**
-     * return the relative factor to the base unit
-     * k == 1000, M = 1000000 ...
-     * Not completely!!! Rank from n to T
-     *
-     * @param prefix of the unit
-     * @return relative factor to the base unit
-     */
-
-    public static double getFactorToBaseUnit(String prefix) {
-        if (prefix.isEmpty()) {
-            return 1;
-        }
-        switch (prefix) {
-            case "T":
-                return 1000000000000d;
-            case "G":
-                return 1000000000;
-            case "M":
-                return 1000000;
-            case "k":
-                return 1000;
-            case "h":
-                return 100;
-            case "da":
-                return 10;
-            case "d":
-                return 0.1;
-            case "c":
-                return 0.01;
-            case "m":
-                return 0.001;
-            case "ยต":
-                return 0.000001;
-            case "n":
-                return 0.000000001;
-        }
-        return 1;
-    }
-}
index a01821504074bf699f7a2797788653f2b0536131..c510a15324dc439e7869adada5b11541a339d259 100644 (file)
@@ -90,6 +90,10 @@ channel-type.fronius.pPv.label = Solar Plant Power
 channel-type.fronius.pPv.description = Current Solar Plant Power
 channel-type.fronius.pac.label = AC Power
 channel-type.fronius.pac.description = AC power
+channel-type.fronius.powerflow_rel_autonomy.label = Autonomy
+channel-type.fronius.powerflow_rel_autonomy.description = The current relative autonomy in %, NULL if no smart meter is connected
+channel-type.fronius.powerflow_rel_selfconsumption.label = Self Consumption
+channel-type.fronius.powerflow_rel_selfconsumption.description = The current relative self consumption in %, NULL if no smart meter is connected
 channel-type.fronius.total_energy.label = Total Energy
 channel-type.fronius.total_energy.description = Energy generated overall
 channel-type.fronius.uac.label = AC Voltage
index f9b1c2e859c97d456b62d10eb6a744c02c82ff30..0c6ffa97f462c99bf75745b44321efac3c8ce9c8 100644 (file)
@@ -34,6 +34,8 @@
                        <channel id="powerflowchannelppv" typeId="pPv">
                                <label>Current Solar Yield</label>
                        </channel>
+                       <channel id="powerflowautonomy" typeId="powerflow_rel_autonomy"/>
+                       <channel id="powerflowselfconsumption" typeId="powerflow_rel_selfconsumption"/>
                        <channel id="powerflowinverter1power" typeId="inverter1Power">
                                <label>Power Flow (Inverter 1)</label>
                        </channel>
        </thing-type>
 
        <channel-type id="day_energy">
-               <item-type>Number</item-type>
+               <item-type>Number:Energy</item-type>
                <label>Day Energy</label>
                <description>Energy generated on current day</description>
                <state pattern="%.2f kWh" readOnly="true"></state>
        </channel-type>
        <channel-type id="pac">
-               <item-type>Number</item-type>
+               <item-type>Number:Power</item-type>
                <label>AC Power</label>
                <description>AC power</description>
                <state pattern="%f W" readOnly="true"></state>
        </channel-type>
        <channel-type id="total_energy">
-               <item-type>Number</item-type>
+               <item-type>Number:Energy</item-type>
                <label>Total Energy</label>
                <description>Energy generated overall</description>
                <state pattern="%.3f MWh" readOnly="true"></state>
        </channel-type>
        <channel-type id="year_energy">
-               <item-type>Number</item-type>
+               <item-type>Number:Energy</item-type>
                <label>Year Energy</label>
                <description>Energy generated in current year</description>
                <state pattern="%.3f MWh" readOnly="true"></state>
        </channel-type>
 
        <channel-type id="fac">
-               <item-type>Number</item-type>
+               <item-type>Number:Frequency</item-type>
                <label>AC Frequency</label>
                <description>AC frequency</description>
                <state pattern="%.2f Hz" readOnly="true"></state>
        </channel-type>
 
        <channel-type id="iac">
-               <item-type>Number</item-type>
+               <item-type>Number:ElectricCurrent</item-type>
                <label>AC Current</label>
                <description>AC current</description>
                <state pattern="%.2f A" readOnly="true"></state>
        </channel-type>
 
        <channel-type id="idc">
-               <item-type>Number</item-type>
+               <item-type>Number:ElectricCurrent</item-type>
                <label>DC Current</label>
                <description>DC current</description>
                <state pattern="%.2f A" readOnly="true"></state>
        </channel-type>
        <channel-type id="uac">
-               <item-type>Number</item-type>
+               <item-type>Number:ElectricPotential</item-type>
                <label>AC Voltage</label>
                <description>AC voltage</description>
                <state pattern="%.1f V" readOnly="true"></state>
        </channel-type>
        <channel-type id="udc">
-               <item-type>Number</item-type>
+               <item-type>Number:ElectricPotential</item-type>
                <label>DC Voltage</label>
                <description>DC voltage</description>
                <state pattern="%.1f V" readOnly="true"></state>
                <description>Current Solar Plant Power</description>
                <state pattern="%.2f %unit%" readOnly="true"></state>
        </channel-type>
+       <channel-type id="powerflow_rel_autonomy">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Autonomy</label>
+               <description>The current relative autonomy in %, NULL if no smart meter is connected</description>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+       <channel-type id="powerflow_rel_selfconsumption">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Self Consumption</label>
+               <description>The current relative self consumption in %, NULL if no smart meter is connected</description>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
        <channel-type id="inverter1Power">
                <item-type>Number:Power</item-type>
                <label>Inverter 1 Power</label>
        </channel-type>
 
 
-
 </thing:thing-descriptions>