]> git.basschouten.com Git - openhab-addons.git/commitdiff
[fronius] Added inverter power, battery state of charge and PV solar yield (#10757)
authorThomasK <THKDev@users.noreply.github.com>
Sun, 11 Jul 2021 07:38:45 +0000 (09:38 +0200)
committerGitHub <noreply@github.com>
Sun, 11 Jul 2021 07:38:45 +0000 (09:38 +0200)
* [fronius] add battery state of charge and PV yield.

Signed-off-by: THKDev <THKDev@users.noreply.github.com>
* [fronius] Actually constants should be all upper case. Words in labels should be capitalized (except prepositions and so on). Use %unit% placeholder.

Signed-off-by: THKDev <THKDev@users.noreply.github.com>
* [fronius] fixed checkstyle error; removed some warnings (eg. StringUtils)

Signed-off-by: THKDev <THKDev@users.noreply.github.com>
* Revert "[fronius] fixed checkstyle error; removed some warnings (eg. StringUtils)"

This reverts commit 73065c65

Signed-off-by: THKDev <THKDev@users.noreply.github.com>
* [fronius] fixed checkstyle error

Signed-off-by: THKDev <THKDev@users.noreply.github.com>
* [fronius] removed org.apache.commons.lang3.StringUtils

Signed-off-by: THKDev <THKDev@users.noreply.github.com>
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/PowerFlowRealtimeInverter.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/FroniusSymoInverterHandler.java
bundles/org.openhab.binding.fronius/src/main/resources/OH-INF/thing/thing-types.xml

index a8723c3c67e96e2c7d6022a62501fdfb831ba5ad..371f3860ba74086fa3189f51e5a7753002d62925 100644 (file)
@@ -21,6 +21,7 @@ import org.openhab.core.thing.ThingTypeUID;
  *
  * @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
  */
 @NonNullByDefault
 public class FroniusBindingConstants {
@@ -33,38 +34,53 @@ public class FroniusBindingConstants {
     public static final ThingTypeUID THING_TYPE_METER = new ThingTypeUID(BINDING_ID, "meter");
 
     // List of all Channel ids
-    public static final String InverterDataChannelDayEnergy = "inverterdatachanneldayenergy";
-    public static final String InverterDataChannelPac = "inverterdatachannelpac";
-    public static final String InverterDataChannelTotal = "inverterdatachanneltotal";
-    public static final String InverterDataChannelYear = "inverterdatachannelyear";
-    public static final String InverterDataChannelFac = "inverterdatachannelfac";
-    public static final String InverterDataChannelIac = "inverterdatachanneliac";
-    public static final String InverterDataChannelIdc = "inverterdatachannelidc";
-    public static final String InverterDataChannelUac = "inverterdatachanneluac";
-    public static final String InverterDataChannelUdc = "inverterdatachanneludc";
-    public static final String InverterDataChannelDeviceStatusErrorCode = "inverterdatadevicestatuserrorcode";
-    public static final String InverterDataChannelDeviceStatusStatusCode = "inverterdatadevicestatusstatuscode";
-    public static final String PowerFlowpGrid = "powerflowchannelpgrid";
-    public static final String PowerFlowpLoad = "powerflowchannelpload";
-    public static final String PowerFlowpAkku = "powerflowchannelpakku";
-    public static final String MeterModel = "model";
-    public static final String MeterSerial = "serial";
-    public static final String MeterEnable = "enable";
-    public static final String MeterLocation = "location";
-    public static final String MeterCurrentAcPhase1 = "currentacphase1";
-    public static final String MeterCurrentAcPhase2 = "currentacphase2";
-    public static final String MeterCurrentAcPhase3 = "currentacphase3";
-    public static final String MeterVoltageAcPhase1 = "voltageacphase1";
-    public static final String MeterVoltageAcPhase2 = "voltageacphase2";
-    public static final String MeterVoltageAcPhase3 = "voltageacphase3";
-    public static final String MeterPowerPhase1 = "powerrealphase1";
-    public static final String MeterPowerPhase2 = "powerrealphase2";
-    public static final String MeterPowerPhase3 = "powerrealphase3";
-    public static final String MeterPowerFactorPhase1 = "powerfactorphase1";
-    public static final String MeterPowerFactorPhase2 = "powerfactorphase2";
-    public static final String MeterPowerFactorPhase3 = "powerfactorphase3";
-    public static final String MeterEnergyRealSumConsumed = "energyrealsumconsumed";
-    public static final String MeterEnergyRealSumProduced = "energyrealsumproduced";
+    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";
+    public static final String INVERTER_DATA_CHANNEL_YEAR = "inverterdatachannelyear";
+    public static final String INVERTER_DATA_CHANNEL_FAC = "inverterdatachannelfac";
+    public static final String INVERTER_DATA_CHANNEL_IAC = "inverterdatachanneliac";
+    public static final String INVERTER_DATA_CHANNEL_IDC = "inverterdatachannelidc";
+    public static final String INVERTER_DATA_CHANNEL_UAC = "inverterdatachanneluac";
+    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";
+    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 METER_MODEL = "model";
+    public static final String METER_SERIAL = "serial";
+    public static final String METER_ENABLE = "enable";
+    public static final String METER_LOCATION = "location";
+    public static final String METER_CURRENT_AC_PHASE_1 = "currentacphase1";
+    public static final String METER_CURRENT_AC_PHASE_2 = "currentacphase2";
+    public static final String METER_CURRENT_AC_PHASE_3 = "currentacphase3";
+    public static final String METER_VOLTAGE_AC_PHASE_1 = "voltageacphase1";
+    public static final String METER_VOLTAGE_AC_PHASE_2 = "voltageacphase2";
+    public static final String METER_VOLTAGE_AC_PHASE_3 = "voltageacphase3";
+    public static final String METER_POWER_PHASE_1 = "powerrealphase1";
+    public static final String METER_POWER_PHASE_2 = "powerrealphase2";
+    public static final String METER_POWER_PHASE_3 = "powerrealphase3";
+    public static final String METER_POWER_FACTOR_PHASE_1 = "powerfactorphase1";
+    public static final String METER_POWER_FACTOR_PHASE_2 = "powerfactorphase2";
+    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";
+
+    /*
+     * 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";
index 15c78bab4e649271350ac425cb28044f942b5b26..f83b6cc3ca0af1907e82ffa6af7b5bb28d48e5bc 100644 (file)
@@ -19,6 +19,7 @@ import com.google.gson.annotations.SerializedName;
  * the "inverter" node of the JSON response
  *
  * @author Thomas Rokohl - Initial contribution
+ * @author Thomas Kordelle - Added inverter power, battery state of charge and PV solar yield
  */
 public class PowerFlowRealtimeInverter {
 
@@ -32,6 +33,10 @@ public class PowerFlowRealtimeInverter {
     private double eYear;
     @SerializedName("E_Total")
     private double eTotal;
+    @SerializedName("Battery_Mode")
+    private String batteryMode;
+    @SerializedName("SOC")
+    private double soc;
 
     public double getDt() {
         return dt;
@@ -72,4 +77,20 @@ public class PowerFlowRealtimeInverter {
     public void seteTotal(double eTotal) {
         this.eTotal = eTotal;
     }
+
+    public String getBatteryMode() {
+        return batteryMode;
+    }
+
+    public void setBatteryMode(final String batteryMode) {
+        this.batteryMode = batteryMode;
+    }
+
+    public double getSoc() {
+        return soc;
+    }
+
+    public void setSoc(double soc) {
+        this.soc = soc;
+    }
 }
index 7f6f66357b4f49a6967e530ab98958b16fc7d326..406d776c3bf9cad9590f0856ab7bb428bcc3d0e8 100644 (file)
@@ -44,6 +44,7 @@ import com.google.gson.JsonSyntaxException;
  *
  * @author Gerrit Beine - Initial contribution
  * @author Thomas Rokohl - Refactoring to merge the concepts
+ * @author Thomas Kordelle - Added inverter power, battery state of charge and PV solar yield
  */
 public abstract class FroniusBaseThingHandler extends BaseThingHandler {
 
@@ -198,7 +199,7 @@ public abstract class FroniusBaseThingHandler extends BaseThingHandler {
             if (!resultOk) {
                 logger.debug("Error in fronius response: {}", errorMsg);
             }
-        } catch (JsonSyntaxException e) {
+        } catch (JsonSyntaxException | NumberFormatException e) {
             errorMsg = "Invalid JSON data received";
             logger.debug("Error running fronius request: {}", e.getMessage());
         } catch (IOException | IllegalStateException e) {
index 9e590f0f7912c9c009d214712b21fa2b009c1e9a..a54585ac0004a5441fcd8ed7b2fff8014b327d08 100644 (file)
@@ -14,7 +14,6 @@ package org.openhab.binding.fronius.internal.handler;
 
 import java.util.Map;
 
-import org.apache.commons.lang3.StringUtils;
 import org.openhab.binding.fronius.internal.FroniusBaseDeviceConfiguration;
 import org.openhab.binding.fronius.internal.FroniusBindingConstants;
 import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration;
@@ -23,18 +22,16 @@ import org.openhab.binding.fronius.internal.api.MeterRealtimeResponseDTO;
 import org.openhab.core.library.types.QuantityType;
 import org.openhab.core.library.unit.Units;
 import org.openhab.core.thing.Thing;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * The {@link FroniusMeterHandler} is responsible for updating the data, which are
  * sent to one of the channels.
  *
  * @author Jimmy Tanagra - Initial contribution
+ * @author Thomas Kordelle - Actually constants should be all upper case.
  */
 public class FroniusMeterHandler extends FroniusBaseThingHandler {
 
-    private final Logger logger = LoggerFactory.getLogger(FroniusMeterHandler.class);
     private MeterRealtimeBodyDataDTO meterRealtimeBodyData;
     private FroniusBaseDeviceConfiguration config;
 
@@ -72,42 +69,47 @@ public class FroniusMeterHandler extends FroniusBaseThingHandler {
             return null;
         }
 
-        String[] fields = StringUtils.split(channelId, "#");
-        String fieldName = fields[0];
+        final String[] fields = channelId.split("#");
+        if (fields.length < 1) {
+            return null;
+        }
+        final String fieldName = fields[0];
 
         switch (fieldName) {
-            case FroniusBindingConstants.MeterEnable:
+            case FroniusBindingConstants.METER_ENABLE:
                 return meterRealtimeBodyData.getEnable();
-            case FroniusBindingConstants.MeterLocation:
+            case FroniusBindingConstants.METER_LOCATION:
                 return meterRealtimeBodyData.getMeterLocationCurrent();
-            case FroniusBindingConstants.MeterCurrentAcPhase1:
-                return new QuantityType(meterRealtimeBodyData.getCurrentACPhase1(), Units.AMPERE);
-            case FroniusBindingConstants.MeterCurrentAcPhase2:
-                return new QuantityType(meterRealtimeBodyData.getCurrentACPhase2(), Units.AMPERE);
-            case FroniusBindingConstants.MeterCurrentAcPhase3:
-                return new QuantityType(meterRealtimeBodyData.getCurrentACPhase3(), Units.AMPERE);
-            case FroniusBindingConstants.MeterVoltageAcPhase1:
-                return new QuantityType(meterRealtimeBodyData.getVoltageACPhase1(), Units.VOLT);
-            case FroniusBindingConstants.MeterVoltageAcPhase2:
-                return new QuantityType(meterRealtimeBodyData.getVoltageACPhase2(), Units.VOLT);
-            case FroniusBindingConstants.MeterVoltageAcPhase3:
-                return new QuantityType(meterRealtimeBodyData.getVoltageACPhase3(), Units.VOLT);
-            case FroniusBindingConstants.MeterPowerPhase1:
-                return new QuantityType(meterRealtimeBodyData.getPowerRealPPhase1(), Units.WATT);
-            case FroniusBindingConstants.MeterPowerPhase2:
-                return new QuantityType(meterRealtimeBodyData.getPowerRealPPhase2(), Units.WATT);
-            case FroniusBindingConstants.MeterPowerPhase3:
-                return new QuantityType(meterRealtimeBodyData.getPowerRealPPhase3(), Units.WATT);
-            case FroniusBindingConstants.MeterPowerFactorPhase1:
+            case FroniusBindingConstants.METER_CURRENT_AC_PHASE_1:
+                return new QuantityType<>(meterRealtimeBodyData.getCurrentACPhase1(), Units.AMPERE);
+            case FroniusBindingConstants.METER_CURRENT_AC_PHASE_2:
+                return new QuantityType<>(meterRealtimeBodyData.getCurrentACPhase2(), Units.AMPERE);
+            case FroniusBindingConstants.METER_CURRENT_AC_PHASE_3:
+                return new QuantityType<>(meterRealtimeBodyData.getCurrentACPhase3(), Units.AMPERE);
+            case FroniusBindingConstants.METER_VOLTAGE_AC_PHASE_1:
+                return new QuantityType<>(meterRealtimeBodyData.getVoltageACPhase1(), Units.VOLT);
+            case FroniusBindingConstants.METER_VOLTAGE_AC_PHASE_2:
+                return new QuantityType<>(meterRealtimeBodyData.getVoltageACPhase2(), Units.VOLT);
+            case FroniusBindingConstants.METER_VOLTAGE_AC_PHASE_3:
+                return new QuantityType<>(meterRealtimeBodyData.getVoltageACPhase3(), Units.VOLT);
+            case FroniusBindingConstants.METER_POWER_PHASE_1:
+                return new QuantityType<>(meterRealtimeBodyData.getPowerRealPPhase1(), Units.WATT);
+            case FroniusBindingConstants.METER_POWER_PHASE_2:
+                return new QuantityType<>(meterRealtimeBodyData.getPowerRealPPhase2(), Units.WATT);
+            case FroniusBindingConstants.METER_POWER_PHASE_3:
+                return new QuantityType<>(meterRealtimeBodyData.getPowerRealPPhase3(), Units.WATT);
+            case FroniusBindingConstants.METER_POWER_FACTOR_PHASE_1:
                 return meterRealtimeBodyData.getPowerFactorPhase1();
-            case FroniusBindingConstants.MeterPowerFactorPhase2:
+            case FroniusBindingConstants.METER_POWER_FACTOR_PHASE_2:
                 return meterRealtimeBodyData.getPowerFactorPhase2();
-            case FroniusBindingConstants.MeterPowerFactorPhase3:
+            case FroniusBindingConstants.METER_POWER_FACTOR_PHASE_3:
                 return meterRealtimeBodyData.getPowerFactorPhase3();
-            case FroniusBindingConstants.MeterEnergyRealSumConsumed:
-                return new QuantityType(meterRealtimeBodyData.getEnergyRealWACSumConsumed(), Units.WATT_HOUR);
-            case FroniusBindingConstants.MeterEnergyRealSumProduced:
-                return new QuantityType(meterRealtimeBodyData.getEnergyRealWACSumProduced(), Units.WATT_HOUR);
+            case FroniusBindingConstants.METER_ENERGY_REAL_SUM_CONSUMED:
+                return new QuantityType<>(meterRealtimeBodyData.getEnergyRealWACSumConsumed(), Units.WATT_HOUR);
+            case FroniusBindingConstants.METER_ENERGY_REAL_SUM_PRODUCED:
+                return new QuantityType<>(meterRealtimeBodyData.getEnergyRealWACSumProduced(), Units.WATT_HOUR);
+            default:
+                break;
         }
 
         return null;
@@ -120,8 +122,8 @@ public class FroniusMeterHandler extends FroniusBaseThingHandler {
 
         Map<String, String> properties = editProperties();
 
-        properties.put(FroniusBindingConstants.MeterModel, meterRealtimeBodyData.getDetails().getModel());
-        properties.put(FroniusBindingConstants.MeterSerial, meterRealtimeBodyData.getDetails().getSerial());
+        properties.put(FroniusBindingConstants.METER_MODEL, meterRealtimeBodyData.getDetails().getModel());
+        properties.put(FroniusBindingConstants.METER_SERIAL, meterRealtimeBodyData.getDetails().getSerial());
 
         updateProperties(properties);
     }
@@ -147,7 +149,8 @@ public class FroniusMeterHandler extends FroniusBaseThingHandler {
      * @return {MeterRealtimeResponse} the object representation of the json response
      */
     private MeterRealtimeResponseDTO getMeterRealtimeData(String ip, int deviceId) {
-        String location = FroniusBindingConstants.METER_REALTIME_DATA_URL.replace("%IP%", StringUtils.trimToEmpty(ip));
+        String location = FroniusBindingConstants.METER_REALTIME_DATA_URL.replace("%IP%",
+                (ip != null ? ip.trim() : ""));
         location = location.replace("%DEVICEID%", Integer.toString(deviceId));
         return collectDataFormUrl(MeterRealtimeResponseDTO.class, location);
     }
index ff8592f8d20c2baa8fd0b020cc3fd83584fbc933..4aa28d0ce490a48bf9b2e63b5450124c62735798 100644 (file)
  */
 package org.openhab.binding.fronius.internal.handler;
 
-import org.apache.commons.lang3.StringUtils;
+import java.util.Map;
+
 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.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.ValueUnit;
+import org.openhab.core.library.types.QuantityType;
+import org.openhab.core.library.unit.Units;
 import org.openhab.core.thing.Thing;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -29,9 +33,15 @@ 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
  */
 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;
@@ -66,66 +76,101 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
      */
     @Override
     protected Object getValue(String channelId) {
-        String[] fields = StringUtils.split(channelId, "#");
-
-        String fieldName = fields[0];
-
-        if (inverterRealtimeResponse == null) {
+        final String[] fields = channelId.split("#");
+        if (fields.length < 1) {
             return null;
         }
-        switch (fieldName) {
-            case FroniusBindingConstants.InverterDataChannelDayEnergy:
-                ValueUnit day = inverterRealtimeResponse.getBody().getData().getDayEnergy();
-                if (day != null) {
-                    day.setUnit("kWh");
-                }
-                return day;
-            case FroniusBindingConstants.InverterDataChannelPac:
-                ValueUnit pac = inverterRealtimeResponse.getBody().getData().getPac();
-                if (pac == null) {
-                    pac = new ValueUnit();
-                    pac.setValue(0);
-                }
-                return pac;
-            case FroniusBindingConstants.InverterDataChannelTotal:
-                ValueUnit total = inverterRealtimeResponse.getBody().getData().getTotalEnergy();
-                if (total != null) {
-                    total.setUnit("MWh");
-                }
-                return total;
-            case FroniusBindingConstants.InverterDataChannelYear:
-                ValueUnit year = inverterRealtimeResponse.getBody().getData().getYearEnergy();
-                if (year != null) {
-                    year.setUnit("MWh");
-                }
-                return year;
-            case FroniusBindingConstants.InverterDataChannelFac:
-                return inverterRealtimeResponse.getBody().getData().getFac();
-            case FroniusBindingConstants.InverterDataChannelIac:
-                return inverterRealtimeResponse.getBody().getData().getIac();
-            case FroniusBindingConstants.InverterDataChannelIdc:
-                return inverterRealtimeResponse.getBody().getData().getIdc();
-            case FroniusBindingConstants.InverterDataChannelUac:
-                return inverterRealtimeResponse.getBody().getData().getUac();
-            case FroniusBindingConstants.InverterDataChannelUdc:
-                return inverterRealtimeResponse.getBody().getData().getUdc();
-            case FroniusBindingConstants.InverterDataChannelDeviceStatusErrorCode:
-                return inverterRealtimeResponse.getBody().getData().getDeviceStatus().getErrorCode();
-            case FroniusBindingConstants.InverterDataChannelDeviceStatusStatusCode:
-                return inverterRealtimeResponse.getBody().getData().getDeviceStatus().getStatusCode();
+        final String fieldName = fields[0];
+
+        if (inverterRealtimeResponse != null) {
+            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;
+                case FroniusBindingConstants.INVERTER_DATA_CHANNEL_FAC:
+                    return inverterRealtimeResponse.getBody().getData().getFac();
+                case FroniusBindingConstants.INVERTER_DATA_CHANNEL_IAC:
+                    return inverterRealtimeResponse.getBody().getData().getIac();
+                case FroniusBindingConstants.INVERTER_DATA_CHANNEL_IDC:
+                    return inverterRealtimeResponse.getBody().getData().getIdc();
+                case FroniusBindingConstants.INVERTER_DATA_CHANNEL_UAC:
+                    return inverterRealtimeResponse.getBody().getData().getUac();
+                case FroniusBindingConstants.INVERTER_DATA_CHANNEL_UDC:
+                    return inverterRealtimeResponse.getBody().getData().getUdc();
+                case FroniusBindingConstants.INVERTER_DATA_CHANNEL_DEVICE_STATUS_ERROR_CODE:
+                    return inverterRealtimeResponse.getBody().getData().getDeviceStatus().getErrorCode();
+                case FroniusBindingConstants.INVERTER_DATA_CHANNEL_DEVICE_STATUS_STATUS_CODE:
+                    return inverterRealtimeResponse.getBody().getData().getDeviceStatus().getStatusCode();
+                default:
+                    break;
+            }
+        }
+
+        if (powerFlowResponse != null) {
+            switch (fieldName) {
+                case FroniusBindingConstants.POWER_FLOW_P_GRID:
+                    return new QuantityType<>(powerFlowResponse.getBody().getData().getSite().getPgrid(), Units.WATT);
+                case FroniusBindingConstants.POWER_FLOW_P_LOAD:
+                    return new QuantityType<>(powerFlowResponse.getBody().getData().getSite().getPload(), Units.WATT);
+                case FroniusBindingConstants.POWER_FLOW_P_AKKU:
+                    return new QuantityType<>(powerFlowResponse.getBody().getData().getSite().getPakku(), Units.WATT);
+                case FroniusBindingConstants.POWER_FLOW_P_PV:
+                    return new QuantityType<>(powerFlowResponse.getBody().getData().getSite().getPpv(), Units.WATT);
+                case FroniusBindingConstants.POWER_FLOW_INVERTER_1_POWER:
+                    return getInverterFlowValue(INVERTER_POWER, "1");
+                case FroniusBindingConstants.POWER_FLOW_INVERTER_1_SOC:
+                    return getInverterFlowValue(INVERTER_SOC, "1");
+                default:
+                    break;
+            }
         }
-        if (powerFlowResponse == null) {
+
+        return null;
+    }
+
+    /**
+     * get flow data for a specific inverter.
+     *
+     * @param fieldName
+     * @param number
+     * @return
+     */
+    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 FroniusBindingConstants.PowerFlowpGrid:
-                return powerFlowResponse.getBody().getData().getSite().getPgrid();
-            case FroniusBindingConstants.PowerFlowpLoad:
-                return powerFlowResponse.getBody().getData().getSite().getPload();
-            case FroniusBindingConstants.PowerFlowpAkku:
-                return powerFlowResponse.getBody().getData().getSite().getPakku();
+            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;
     }
 
@@ -144,7 +189,8 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
      * @return {PowerFlowRealtimeResponse} the object representation of the json response
      */
     private PowerFlowRealtimeResponse getPowerFlowRealtime(String ip) {
-        String location = FroniusBindingConstants.POWERFLOW_REALTIME_DATA.replace("%IP%", StringUtils.trimToEmpty(ip));
+        String location = FroniusBindingConstants.POWERFLOW_REALTIME_DATA.replace("%IP%",
+                (ip != null ? ip.trim() : ""));
         return collectDataFormUrl(PowerFlowRealtimeResponse.class, location);
     }
 
@@ -157,7 +203,7 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
      */
     private InverterRealtimeResponse getRealtimeData(String ip, int deviceId) {
         String location = FroniusBindingConstants.INVERTER_REALTIME_DATA_URL.replace("%IP%",
-                StringUtils.trimToEmpty(ip));
+                (ip != null ? ip.trim() : ""));
         location = location.replace("%DEVICEID%", Integer.toString(deviceId));
         return collectDataFormUrl(InverterRealtimeResponse.class, location);
     }
index d6334bdc8c8b8be5dcadf947c4c228b9b5eae208..fb61c75112900c541f3a413de6f512a13ba94fc7 100644 (file)
                        <channel id="inverterdatachanneludc" typeId="udc"/>
                        <channel id="inverterdatadevicestatuserrorcode" typeId="devicestatus_errorcode"/>
                        <channel id="inverterdatadevicestatusstatuscode" typeId="devicestatus_statuscode"/>
-                       <channel id="powerflowchannelpgrid" typeId="pGrid"/>
+                       <channel id="powerflowchannelpgrid" typeId="pGrid">
+                               <label>Grid Power</label>
+                       </channel>
                        <channel id="powerflowchannelpload" typeId="pLoad"/>
-                       <channel id="powerflowchannelpakku" typeId="pAkku"/>
+                       <channel id="powerflowchannelpakku" typeId="pAkku">
+                               <label>Charge / Discharge of Battery</label>
+                       </channel>
+                       <channel id="powerflowchannelppv" typeId="pPv">
+                               <label>Current Solar Yield</label>
+                       </channel>
+                       <channel id="powerflowinverter1power" typeId="inverter1Power">
+                               <label>Power Flow (Inverter 1)</label>
+                       </channel>
+                       <channel id="powerflowinverter1soc" typeId="inverter1Soc">
+                               <label>State of Charge (Inverter 1)</label>
+                       </channel>
                </channels>
 
                <config-description>
        </channel-type>
 
        <channel-type id="pGrid">
-               <item-type>Number</item-type>
+               <item-type>Number:Power</item-type>
                <label>Grid Power</label>
                <description>Grid Power ( + from grid, - to grid )</description>
-               <state pattern="%.2f W" readOnly="true"></state>
+               <state pattern="%.2f %unit%" readOnly="true"></state>
        </channel-type>
        <channel-type id="pLoad">
-               <item-type>Number</item-type>
+               <item-type>Number:Power</item-type>
                <label>Load Power</label>
                <description>Load Power ( + generator, - consumer )</description>
-               <state pattern="%.2f W" readOnly="true"></state>
+               <state pattern="%.2f %unit%" readOnly="true"></state>
        </channel-type>
        <channel-type id="pAkku">
-               <item-type>Number</item-type>
+               <item-type>Number:Power</item-type>
                <label>Battery Power</label>
-               <description>Battery Power ( + charge, - discharge )</description>
-               <state pattern="%.2f W" readOnly="true"></state>
+               <description>Battery Power ( + discharge, - charge )</description>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+       <channel-type id="pPv">
+               <item-type>Number:Power</item-type>
+               <label>Solar Plant Power</label>
+               <description>Current Solar Plant Power</description>
+               <state pattern="%.2f %unit%" readOnly="true"></state>
+       </channel-type>
+       <channel-type id="inverter1Power">
+               <item-type>Number:Power</item-type>
+               <label>Inverter 1 Power</label>
+               <description>Inverter 1 Power</description>
+               <state pattern="%.2f %unit%" readOnly="true"></state>
+       </channel-type>
+       <channel-type id="inverter1Soc">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Inverter 1 State of Charge</label>
+               <description>Inverter 1 State of Charge</description>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
        </channel-type>
 
 
        <channel-type id="meter_location" advanced="true">
                <item-type>Number</item-type>
                <label>Location</label>
-               <description>Meter location code</description>
+               <description>Meter Location Code</description>
                <state readOnly="true"></state>
        </channel-type>
        <channel-type id="meter_ac_current">