From fe5e9b85e813d7e514211a3e99c8d97330e39378 Mon Sep 17 00:00:00 2001 From: jimtng <2554958+jimtng@users.noreply.github.com> Date: Tue, 29 Dec 2020 03:24:10 +1000 Subject: [PATCH] [fronius] Add support for Fronius Smart Meter (#9209) * [fronius] Add support for Fronius Smart Meter * [fronius] Use DTO, implement UoM * [fronius] fix README.md * [fronius] Add mandatory label for channel-type and fix property update * [fronius] Store meterRealtimeBodyData instead of meterRealtimeResponse Signed-off-by: Jimmy Tanagra --- bundles/org.openhab.binding.fronius/README.md | 122 ++++-- .../internal/FroniusBindingConstants.java | 20 + .../internal/FroniusHandlerFactory.java | 4 + .../internal/api/MeterRealtimeBodyDTO.java | 37 ++ .../api/MeterRealtimeBodyDataDTO.java | 397 ++++++++++++++++++ .../internal/api/MeterRealtimeDetailsDTO.java | 54 +++ .../api/MeterRealtimeResponseDTO.java | 37 ++ .../handler/FroniusBaseThingHandler.java | 65 +++ .../internal/handler/FroniusMeterHandler.java | 154 +++++++ .../handler/FroniusSymoInverterHandler.java | 60 --- .../resources/OH-INF/thing/thing-types.xml | 114 +++++ 11 files changed, 974 insertions(+), 90 deletions(-) create mode 100644 bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/MeterRealtimeBodyDTO.java create mode 100644 bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/MeterRealtimeBodyDataDTO.java create mode 100644 bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/MeterRealtimeDetailsDTO.java create mode 100644 bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/MeterRealtimeResponseDTO.java create mode 100644 bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusMeterHandler.java diff --git a/bundles/org.openhab.binding.fronius/README.md b/bundles/org.openhab.binding.fronius/README.md index 28d56c72c..fba833df0 100644 --- a/bundles/org.openhab.binding.fronius/README.md +++ b/bundles/org.openhab.binding.fronius/README.md @@ -1,12 +1,16 @@ # Fronius Binding -This binding uses the [Fronius Solar API V1](https://www.fronius.com/en/photovoltaics/products/all-products/system-monitoring/open-interfaces/fronius-solar-api-json-) to obtain data from a Fronius devices. +This binding uses the [Fronius Solar API V1](https://www.fronius.com/en/photovoltaics/products/all-products/system-monitoring/open-interfaces/fronius-solar-api-json-) to obtain data from Fronius devices. +It supports Fronius inverters and Fronius Smart Meter. Tested with a Fronius Symo 8.2-3-M and Fronius Smart Meter 63A. ## Supported Things -Support Fronius Galvo, Fronius Symo inverters and other Fronius inverters in combination with the Fronius Datamanager 1.0 / 2.0 or Fronius Datalogger. -You can add multiple inverters that depend on the same datalogger with different device ids. (Default 1) +| Thing Type | Description | +| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `bridge` | The Bridge | +| `powerinverter` | Fronius Galvo, Symo and other Fronius inverters in combination with the Fronius Datamanager 1.0 / 2.0 or Fronius Datalogger. You can add multiple inverters that depend on the same datalogger with different device ids. (Default 1) | +| `meter` | Fronius Smart Meter. You can add multiple smart meters with different device ids. (The default id = 0) | ## Discovery @@ -14,41 +18,83 @@ There is no discovery implemented. You have to create your things manually and s ## Binding Configuration -The binding has no configuration options, all configuration is done at `bridge` or `powerinverter` level. +The binding has no configuration options, all configuration is done at `bridge`, `powerinverter` or `meter` level. ## Thing Configuration ### Bridge Thing Configuration -| Parameter | Description | -|-----------------|------------------------------------------------------ | -| hostname | The hostname or IP address of your Fronius Datalogger | -| refreshInterval | Refresh interval in seconds | +| Parameter | Description | +| ----------------- | ----------------------------------------------------- | +| `hostname` | The hostname or IP address of your Fronius Datalogger | +| `refreshInterval` | Refresh interval in seconds | ### Powerinverter Thing Configuration -| Parameter | Description | -|-----------------|------------------------------------------------------ | -| deviceId | The identifier of your device (Default: 1) | +| Parameter | Description | +| ---------- | ------------------------------------------ | +| `deviceId` | The identifier of your device (Default: 1) | + +### Meter Thing Configuration + +| Parameter | Description | +| ---------- | ----------------------------------------------- | +| `deviceId` | The identifier of your smart meter (Default: 0) | ## Channels -| Channel ID | Item Type | Description | -|------------|--------------|------------------------- | -| inverterdatachanneldayenergy | Number | Energy generated on current day | -| inverterdatachannelpac | Number | AC powery | -| 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
`0` - `6` Startup
`7` Running
`8` Standby
`9` Bootloading
`10` Error | -| powerflowchannelpgrid | Number | Power + from grid, - to grid | -| powerflowchannelpload | Number | Power + generator, - consumer | -| powerflowchannelpakku | Number | Power + charge, - discharge | +### 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
`0` - `6` Startup
`7` Running
`8` Standby
`9` Bootloading
`10` Error | +| `powerflowchannelpgrid` | Number | Power + from grid, - to grid | +| `powerflowchannelpload` | Number | Power + generator, - consumer | +| `powerflowchannelpakku` | Number | Power + charge, - discharge | + +### Channels for `meter` Thing + +| Channel ID | Item Type | Description | +| ----------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `enable` | Number | 1 = enabled, 0 = disabled | +| `location` | Number | 0 = grid interconnection point (primary meter)
1 = load (primary meter)
3 = external generator (secondary meters)(multiple)
256-511 = subloads (secondary meters)(unique). Refer to Fronius Solar API. | +| `currentacphase1` | Number:ElectricCurrent | AC Current on Phase 1 | +| `currentacphase2` | Number:ElectricCurrent | AC Current on Phase 2 | +| `currentacphase3` | Number:ElectricCurrent | AC Current on Phase 3 | +| `voltageacphase1` | Number:ElectricPotential | AC Voltage on Phase 1 | +| `voltageacphase2` | Number:ElectricPotential | AC Voltage on Phase 2 | +| `voltageacphase3` | Number:ElectricPotential | AC Voltage on Phase 3 | +| `powerrealphase1` | Number:Power | Real Power on Phase 1 | +| `powerrealphase2` | Number:Power | Real Power on Phase 2 | +| `powerrealphase3` | Number:Power | Real Power on Phase 3 | +| `powerfactorphase1` | Number | Power Factor on Phase 1 | +| `powerfactorphase2` | Number | Power Factor on Phase 2 | +| `powerfactorphase3` | Number | Power Factor on Phase 3 | +| `energyrealsumconsumed` | Number:Energy | Real Energy consumed | +| `energyrealsumproduced` | Number:Energy | Real Energy produced | +| | + + + + +## Properties + +The `meter` thing has the following properties: + +| Property | Description | +| -------- | ------------------------------ | +| `model` | The model name of the meter | +| `serial` | The serial number of the meter | ## Full Example @@ -57,13 +103,14 @@ demo.things: ``` Bridge fronius:bridge:mybridge [hostname="192.168.66.148", refreshInterval=5] { Thing powerinverter myinverter [deviceId=1] + Thing meter mymeter [deviceId=0] } ``` demo.items: ``` -Number AC_Powery { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachannelpac" } +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" } @@ -77,6 +124,21 @@ Number StatusCode { channel="fronius:powerinverter:mybridge:myinverter:inverterd Number Grid_Power { channel="fronius:powerinverter:mybridge:myinverter:powerflowchannelpgrid" } Number Load_Power { channel="fronius:powerinverter:mybridge:myinverter:powerflowchannelpload" } Number Battery_Power { channel="fronius:powerinverter:mybridge:myinverter:powerflowchannelpakku" } -``` -Tested with a Fronius Symo 8.2-3-M +Number Meter_Enable { channel="fronius:meter:mybridge:mymeter:enable" } +Number Meter_Location { channel="fronius:meter:mybridge:mymeter:location" } +Number:ElectricCurrent Meter_CurrentPhase1 { channel="fronius:meter:mybridge:mymeter:currentacphase1" } +Number:ElectricCurrent Meter_CurrentPhase2 { channel="fronius:meter:mybridge:mymeter:currentacphase2" } +Number:ElectricCurrent Meter_CurrentPhase3 { channel="fronius:meter:mybridge:mymeter:currentacphase3" } +Number:Voltage Meter_VoltagePhase1 { channel="fronius:meter:mybridge:mymeter:voltageacphase1" } +Number:Voltage Meter_VoltagePhase2 { channel="fronius:meter:mybridge:mymeter:voltageacphase2" } +Number:Voltage Meter_VoltagePhase3 { channel="fronius:meter:mybridge:mymeter:voltageacphase3" } +Number:Power Meter_PowerPhase1 { channel="fronius:meter:mybridge:mymeter:powerrealphase1" } +Number:Power Meter_PowerPhase2 { channel="fronius:meter:mybridge:mymeter:powerrealphase2" } +Number:Power Meter_PowerPhase3 { channel="fronius:meter:mybridge:mymeter:powerrealphase3" } +Number Meter_PowerFactorPhase1 { channel="fronius:meter:mybridge:mymeter:powerfactorphase1" } +Number Meter_PowerFactorPhase2 { channel="fronius:meter:mybridge:mymeter:powerfactorphase2" } +Number Meter_PowerFactorPhase3 { channel="fronius:meter:mybridge:mymeter:powerfactorphase3" } +Number:Energy Meter_EnergyConsumed { channel="fronius:meter:mybridge:mymeter:energyrealsumconsumed" } +Number:Energy Meter_EnergyProduced { channel="fronius:meter:mybridge:mymeter:energyrealsumproduced" } +``` diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusBindingConstants.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusBindingConstants.java index d71677c92..32f39fd9f 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusBindingConstants.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusBindingConstants.java @@ -30,6 +30,7 @@ public class FroniusBindingConstants { // 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_METER = new ThingTypeUID(BINDING_ID, "meter"); // List of all Channel ids public static final String InverterDataChannelDayEnergy = "inverterdatachanneldayenergy"; @@ -46,8 +47,27 @@ public class FroniusBindingConstants { 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"; // 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 METER_REALTIME_DATA_URL = "http://%IP%/solar_api/v1/GetMeterRealtimeData.cgi?Scope=Device&DeviceId=%DEVICEID%&DataCollection=MeterRealtimeData"; } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusHandlerFactory.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusHandlerFactory.java index ae4390473..adacb6eb7 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusHandlerFactory.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusHandlerFactory.java @@ -18,6 +18,7 @@ import java.util.HashSet; import java.util.Set; import org.openhab.binding.fronius.internal.handler.FroniusBridgeHandler; +import org.openhab.binding.fronius.internal.handler.FroniusMeterHandler; import org.openhab.binding.fronius.internal.handler.FroniusSymoInverterHandler; import org.openhab.core.thing.Bridge; import org.openhab.core.thing.Thing; @@ -42,6 +43,7 @@ public class FroniusHandlerFactory extends BaseThingHandlerFactory { { add(THING_TYPE_INVERTER); add(THING_TYPE_BRIDGE); + add(THING_TYPE_METER); } }; @@ -58,6 +60,8 @@ public class FroniusHandlerFactory extends BaseThingHandlerFactory { return new FroniusSymoInverterHandler(thing); } else if (thingTypeUID.equals(THING_TYPE_BRIDGE)) { return new FroniusBridgeHandler((Bridge) thing); + } else if (thingTypeUID.equals(THING_TYPE_METER)) { + return new FroniusMeterHandler(thing); } return null; } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/MeterRealtimeBodyDTO.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/MeterRealtimeBodyDTO.java new file mode 100644 index 000000000..a61476b82 --- /dev/null +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/MeterRealtimeBodyDTO.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2010-2020 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.api; + +import com.google.gson.annotations.SerializedName; + +/** + * The {@link MeterRealtimeBody} is responsible for storing + * the "body" node of the JSON response + * + * @author Jimmy Tanagra - Initial contribution + */ +public class MeterRealtimeBodyDTO { + @SerializedName("Data") + private MeterRealtimeBodyDataDTO data; + + public MeterRealtimeBodyDataDTO getData() { + if (data == null) { + data = new MeterRealtimeBodyDataDTO(); + } + return data; + } + + public void setData(MeterRealtimeBodyDataDTO data) { + this.data = data; + } +} diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/MeterRealtimeBodyDataDTO.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/MeterRealtimeBodyDataDTO.java new file mode 100644 index 000000000..71f26b7ad --- /dev/null +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/MeterRealtimeBodyDataDTO.java @@ -0,0 +1,397 @@ +/** + * Copyright (c) 2010-2020 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.api; + +import com.google.gson.annotations.SerializedName; + +/** + * The {@link MeterRealtimeBodyData} is responsible for storing + * the "data" node of the JSON response + * + * @author Jimmy Tanagra - Initial contribution + */ +public class MeterRealtimeBodyDataDTO { + @SerializedName("Current_AC_Phase_1") + private double currentACPhase1; + @SerializedName("Current_AC_Phase_2") + private double currentACPhase2; + @SerializedName("Current_AC_Phase_3") + private double currentACPhase3; + @SerializedName("Details") + private MeterRealtimeDetailsDTO details; + @SerializedName("Enable") + private int enable; + @SerializedName("EnergyReactive_VArAC_Sum_Consumed") + private int energyReactiveVArACSumConsumed; + @SerializedName("EnergyReactive_VArAC_Sum_Produced") + private int energyReactiveVArACSumProduced; + @SerializedName("EnergyReal_WAC_Minus_Absolute") + private int energyRealWACMinusAbsolute; + @SerializedName("EnergyReal_WAC_Plus_Absolute") + private int energyRealWACPlusAbsolute; + @SerializedName("EnergyReal_WAC_Sum_Consumed") + private int energyRealWACSumConsumed; + @SerializedName("EnergyReal_WAC_Sum_Produced") + private int energyRealWACSumProduced; + @SerializedName("Frequency_Phase_Average") + private double frequencyPhaseAverage; + @SerializedName("Meter_Location_Current") + private int meterLocationCurrent; + @SerializedName("PowerApparent_S_Phase_1") + private double powerApparentSPhase1; + @SerializedName("PowerApparent_S_Phase_2") + private double powerApparentSPhase2; + @SerializedName("PowerApparent_S_Phase_3") + private double powerApparentSPhase3; + @SerializedName("PowerApparent_S_Sum") + private int powerApparentSSum; + @SerializedName("PowerFactor_Phase_1") + private double powerFactorPhase1; + @SerializedName("PowerFactor_Phase_2") + private double powerFactorPhase2; + @SerializedName("PowerFactor_Phase_3") + private double powerFactorPhase3; + @SerializedName("PowerFactor_Sum") + private double powerFactorSum; + @SerializedName("PowerReactive_Q_Phase_1") + private double powerReactiveQPhase1; + @SerializedName("PowerReactive_Q_Phase_2") + private double powerReactiveQPhase2; + @SerializedName("PowerReactive_Q_Phase_3") + private double powerReactiveQPhase3; + @SerializedName("PowerReactive_Q_Sum") + private double powerReactiveQSum; + @SerializedName("PowerReal_P_Phase_1") + private double powerRealPPhase1; + @SerializedName("PowerReal_P_Phase_2") + private double powerRealPPhase2; + @SerializedName("PowerReal_P_Phase_3") + private double powerRealPPhase3; + @SerializedName("PowerReal_P_Sum") + private double powerRealPSum; + @SerializedName("TimeStamp") + private int timeStamp; + @SerializedName("Visible") + private int visible; + @SerializedName("Voltage_AC_PhaseToPhase_12") + private double voltageACPhaseToPhase12; + @SerializedName("Voltage_AC_PhaseToPhase_23") + private double voltageACPhaseToPhase23; + @SerializedName("Voltage_AC_PhaseToPhase_31") + private double voltageACPhaseToPhase31; + @SerializedName("Voltage_AC_Phase_1") + private double voltageACPhase1; + @SerializedName("Voltage_AC_Phase_2") + private double voltageACPhase2; + @SerializedName("Voltage_AC_Phase_3") + private double voltageACPhase3; + + public double getCurrentACPhase1() { + return currentACPhase1; + } + + public void setCurrentACPhase1(double currentACPhase1) { + this.currentACPhase1 = currentACPhase1; + } + + public double getCurrentACPhase2() { + return currentACPhase2; + } + + public void setCurrentACPhase2(double currentACPhase2) { + this.currentACPhase2 = currentACPhase2; + } + + public double getCurrentACPhase3() { + return currentACPhase3; + } + + public void setCurrentACPhase3(double currentACPhase3) { + this.currentACPhase3 = currentACPhase3; + } + + public MeterRealtimeDetailsDTO getDetails() { + if (details == null) { + details = new MeterRealtimeDetailsDTO(); + } + return details; + } + + public void setDetails(MeterRealtimeDetailsDTO details) { + this.details = details; + } + + public int getEnable() { + return enable; + } + + public void setEnable(int enable) { + this.enable = enable; + } + + public int getEnergyReactiveVArACSumConsumed() { + return energyReactiveVArACSumConsumed; + } + + public void setEnergyReactiveVArACSumConsumed(int energyReactiveVArACSumConsumed) { + this.energyReactiveVArACSumConsumed = energyReactiveVArACSumConsumed; + } + + public int getEnergyReactiveVArACSumProduced() { + return energyReactiveVArACSumProduced; + } + + public void setEnergyReactiveVArACSumProduced(int energyReactiveVArACSumProduced) { + this.energyReactiveVArACSumProduced = energyReactiveVArACSumProduced; + } + + public int getEnergyRealWACMinusAbsolute() { + return energyRealWACMinusAbsolute; + } + + public void setEnergyRealWACMinusAbsolute(int energyRealWACMinusAbsolute) { + this.energyRealWACMinusAbsolute = energyRealWACMinusAbsolute; + } + + public int getEnergyRealWACPlusAbsolute() { + return energyRealWACPlusAbsolute; + } + + public void setEnergyRealWACPlusAbsolute(int energyRealWACPlusAbsolute) { + this.energyRealWACPlusAbsolute = energyRealWACPlusAbsolute; + } + + public int getEnergyRealWACSumConsumed() { + return energyRealWACSumConsumed; + } + + public void setEnergyRealWACSumConsumed(int energyRealWACSumConsumed) { + this.energyRealWACSumConsumed = energyRealWACSumConsumed; + } + + public int getEnergyRealWACSumProduced() { + return energyRealWACSumProduced; + } + + public void setEnergyRealWACSumProduced(int energyRealWACSumProduced) { + this.energyRealWACSumProduced = energyRealWACSumProduced; + } + + public double getFrequencyPhaseAverage() { + return frequencyPhaseAverage; + } + + public void setFrequencyPhaseAverage(double frequencyPhaseAverage) { + this.frequencyPhaseAverage = frequencyPhaseAverage; + } + + public int getMeterLocationCurrent() { + return meterLocationCurrent; + } + + public void setMeterLocationCurrent(int meterLocationCurrent) { + this.meterLocationCurrent = meterLocationCurrent; + } + + public double getPowerApparentSPhase1() { + return powerApparentSPhase1; + } + + public void setPowerApparentSPhase1(double powerApparentSPhase1) { + this.powerApparentSPhase1 = powerApparentSPhase1; + } + + public double getPowerApparentSPhase2() { + return powerApparentSPhase2; + } + + public void setPowerApparentSPhase2(double powerApparentSPhase2) { + this.powerApparentSPhase2 = powerApparentSPhase2; + } + + public double getPowerApparentSPhase3() { + return powerApparentSPhase3; + } + + public void setPowerApparentSPhase3(double powerApparentSPhase3) { + this.powerApparentSPhase3 = powerApparentSPhase3; + } + + public int getPowerApparentSSum() { + return powerApparentSSum; + } + + public void setPowerApparentSSum(int powerApparentSSum) { + this.powerApparentSSum = powerApparentSSum; + } + + public double getPowerFactorPhase1() { + return powerFactorPhase1; + } + + public void setPowerFactorPhase1(double powerFactorPhase1) { + this.powerFactorPhase1 = powerFactorPhase1; + } + + public double getPowerFactorPhase2() { + return powerFactorPhase2; + } + + public void setPowerFactorPhase2(double powerFactorPhase2) { + this.powerFactorPhase2 = powerFactorPhase2; + } + + public double getPowerFactorPhase3() { + return powerFactorPhase3; + } + + public void setPowerFactorPhase3(double powerFactorPhase3) { + this.powerFactorPhase3 = powerFactorPhase3; + } + + public double getPowerFactorSum() { + return powerFactorSum; + } + + public void setPowerFactorSum(double powerFactorSum) { + this.powerFactorSum = powerFactorSum; + } + + public double getPowerReactiveQPhase1() { + return powerReactiveQPhase1; + } + + public void setPowerReactiveQPhase1(double powerReactiveQPhase1) { + this.powerReactiveQPhase1 = powerReactiveQPhase1; + } + + public double getPowerReactiveQPhase2() { + return powerReactiveQPhase2; + } + + public void setPowerReactiveQPhase2(double powerReactiveQPhase2) { + this.powerReactiveQPhase2 = powerReactiveQPhase2; + } + + public double getPowerReactiveQPhase3() { + return powerReactiveQPhase3; + } + + public void setPowerReactiveQPhase3(double powerReactiveQPhase3) { + this.powerReactiveQPhase3 = powerReactiveQPhase3; + } + + public double getPowerReactiveQSum() { + return powerReactiveQSum; + } + + public void setPowerReactiveQSum(double powerReactiveQSum) { + this.powerReactiveQSum = powerReactiveQSum; + } + + public double getPowerRealPPhase1() { + return powerRealPPhase1; + } + + public void setPowerRealPPhase1(double powerRealPPhase1) { + this.powerRealPPhase1 = powerRealPPhase1; + } + + public double getPowerRealPPhase2() { + return powerRealPPhase2; + } + + public void setPowerRealPPhase2(double powerRealPPhase2) { + this.powerRealPPhase2 = powerRealPPhase2; + } + + public double getPowerRealPPhase3() { + return powerRealPPhase3; + } + + public void setPowerRealPPhase3(double powerRealPPhase3) { + this.powerRealPPhase3 = powerRealPPhase3; + } + + public double getPowerRealPSum() { + return powerRealPSum; + } + + public void setPowerRealPSum(double powerRealPSum) { + this.powerRealPSum = powerRealPSum; + } + + public int getTimeStamp() { + return timeStamp; + } + + public void setTimeStamp(int timeStamp) { + this.timeStamp = timeStamp; + } + + public int getVisible() { + return visible; + } + + public void setVisible(int visible) { + this.visible = visible; + } + + public double getVoltageACPhaseToPhase12() { + return voltageACPhaseToPhase12; + } + + public void setVoltageACPhaseToPhase12(double voltageACPhaseToPhase12) { + this.voltageACPhaseToPhase12 = voltageACPhaseToPhase12; + } + + public double getVoltageACPhaseToPhase23() { + return voltageACPhaseToPhase23; + } + + public void setVoltageACPhaseToPhase23(double voltageACPhaseToPhase23) { + this.voltageACPhaseToPhase23 = voltageACPhaseToPhase23; + } + + public double getVoltageACPhaseToPhase31() { + return voltageACPhaseToPhase31; + } + + public void setVoltageACPhaseToPhase31(double voltageACPhaseToPhase31) { + this.voltageACPhaseToPhase31 = voltageACPhaseToPhase31; + } + + public double getVoltageACPhase1() { + return voltageACPhase1; + } + + public void setVoltageACPhase1(double voltageACPhase1) { + this.voltageACPhase1 = voltageACPhase1; + } + + public double getVoltageACPhase2() { + return voltageACPhase2; + } + + public void setVoltageACPhase2(double voltageACPhase2) { + this.voltageACPhase2 = voltageACPhase2; + } + + public double getVoltageACPhase3() { + return voltageACPhase3; + } + + public void setVoltageACPhase3(double voltageACPhase3) { + this.voltageACPhase3 = voltageACPhase3; + } +} diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/MeterRealtimeDetailsDTO.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/MeterRealtimeDetailsDTO.java new file mode 100644 index 000000000..6cc3dbeaa --- /dev/null +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/MeterRealtimeDetailsDTO.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2010-2020 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.api; + +import com.google.gson.annotations.SerializedName; + +/** + * The {@link MeterRealtimeDetails} is responsible for storing + * the "body" node of the JSON response + * + * @author Jimmy Tanagra - Initial contribution + */ +public class MeterRealtimeDetailsDTO { + @SerializedName("Manufacturer") + private String manufacturer; + @SerializedName("Model") + private String model; + @SerializedName("Serial") + private String serial; + + public String getManufacturer() { + return manufacturer; + } + + public void setManufacturer(String manufacturer) { + this.manufacturer = manufacturer; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + public String getSerial() { + return serial; + } + + public void setSerial(String serial) { + this.serial = serial; + } +} diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/MeterRealtimeResponseDTO.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/MeterRealtimeResponseDTO.java new file mode 100644 index 000000000..765dacb24 --- /dev/null +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/MeterRealtimeResponseDTO.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2010-2020 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.api; + +import com.google.gson.annotations.SerializedName; + +/** + * The {@link MeterRealtimeResponse} is responsible for storing + * the response from the powerflowrealtime api + * + * @author Jimmy Tanagra - Initial contribution + */ +public class MeterRealtimeResponseDTO extends BaseFroniusResponse { + @SerializedName("Body") + private MeterRealtimeBodyDTO body; + + public MeterRealtimeBodyDTO getBody() { + if (body == null) { + body = new MeterRealtimeBodyDTO(); + } + return body; + } + + public void setBody(MeterRealtimeBodyDTO body) { + this.body = body; + } +} diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBaseThingHandler.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBaseThingHandler.java index 9a0a620a8..add6097c0 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBaseThingHandler.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBaseThingHandler.java @@ -12,16 +12,22 @@ */ package org.openhab.binding.fronius.internal.handler; +import java.io.IOException; import java.math.BigDecimal; import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration; +import org.openhab.binding.fronius.internal.api.BaseFroniusResponse; import org.openhab.binding.fronius.internal.api.ValueUnit; +import org.openhab.core.io.net.http.HttpUtil; 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; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.binding.BaseThingHandler; import org.openhab.core.thing.binding.ThingHandler; import org.openhab.core.types.Command; @@ -30,6 +36,9 @@ import org.openhab.core.types.State; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; + /** * Basic Handler class for all Fronius services. * @@ -38,12 +47,15 @@ import org.slf4j.LoggerFactory; */ public abstract class FroniusBaseThingHandler extends BaseThingHandler { + private static final int API_TIMEOUT = 5000; private final Logger logger = LoggerFactory.getLogger(FroniusBaseThingHandler.class); private final String serviceDescription; private FroniusBridgeHandler bridgeHandler; + private final Gson gson; public FroniusBaseThingHandler(Thing thing) { super(thing); + gson = new Gson(); serviceDescription = getDescription(); } @@ -115,6 +127,10 @@ public abstract class FroniusBaseThingHandler extends BaseThingHandler { state = new DecimalType((double) value); } else if (value instanceof ValueUnit) { state = new DecimalType(((ValueUnit) value).getValue()); + } else if (value instanceof String) { + state = new StringType((String) value); + } else if (value instanceof QuantityType) { + state = (QuantityType) value; } else { logger.warn("Update channel {}: Unsupported value type {}", channelId, value.getClass().getSimpleName()); } @@ -149,4 +165,53 @@ public abstract class FroniusBaseThingHandler extends BaseThingHandler { * @param bridgeConfiguration the connected bridge configuration */ public abstract void refresh(FroniusBridgeConfiguration bridgeConfiguration); + + /** + * + * @param type response class type + * @param url to request + * @return the object representation of the json response + */ + protected T collectDataFormUrl(Class type, String url) { + T result = null; + boolean resultOk = false; + String errorMsg = null; + + try { + logger.debug("URL = {}", url); + String response = HttpUtil.executeUrl("GET", url, API_TIMEOUT); + + if (response != null) { + logger.debug("aqiResponse = {}", response); + result = gson.fromJson(response, type); + } + + if (result == null) { + errorMsg = "no data returned"; + } else { + if (result.getHead().getStatus().getCode() == 0) { + resultOk = true; + } else { + errorMsg = result.getHead().getStatus().getReason(); + } + } + if (!resultOk) { + logger.debug("Error in fronius response: {}", errorMsg); + } + } catch (JsonSyntaxException e) { + errorMsg = "Invalid JSON data received"; + logger.debug("Error running fronius request: {}", errorMsg); + } catch (IOException | IllegalStateException e) { + errorMsg = e.getMessage(); + logger.debug("Error running fronius request: {}", errorMsg); + } + + // Update the thing status + if (resultOk) { + updateStatus(ThingStatus.ONLINE); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, errorMsg); + } + return resultOk ? result : null; + } } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusMeterHandler.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusMeterHandler.java new file mode 100644 index 000000000..f28ae2307 --- /dev/null +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusMeterHandler.java @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2010-2020 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.handler; + +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +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.MeterRealtimeBodyDataDTO; +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 + */ +public class FroniusMeterHandler extends FroniusBaseThingHandler { + + private final Logger logger = LoggerFactory.getLogger(FroniusMeterHandler.class); + private MeterRealtimeBodyDataDTO meterRealtimeBodyData; + private FroniusBaseDeviceConfiguration config; + + public FroniusMeterHandler(Thing thing) { + super(thing); + } + + @Override + protected String getDescription() { + return "Fronius Smart Meter"; + } + + @Override + public void refresh(FroniusBridgeConfiguration bridgeConfiguration) { + updateData(bridgeConfiguration, config); + updateChannels(); + updateProperties(); + } + + @Override + public void initialize() { + config = getConfigAs(FroniusBaseDeviceConfiguration.class); + super.initialize(); + } + + /** + * Update the channel from the last data retrieved + * + * @param channelId the id identifying the channel to be updated + * @return the last retrieved data + */ + @Override + protected Object getValue(String channelId) { + if (meterRealtimeBodyData == null) { + return null; + } + + String[] fields = StringUtils.split(channelId, "#"); + String fieldName = fields[0]; + + switch (fieldName) { + case FroniusBindingConstants.MeterEnable: + return meterRealtimeBodyData.getEnable(); + case FroniusBindingConstants.MeterLocation: + 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: + return meterRealtimeBodyData.getPowerFactorPhase1(); + case FroniusBindingConstants.MeterPowerFactorPhase2: + return meterRealtimeBodyData.getPowerFactorPhase2(); + case FroniusBindingConstants.MeterPowerFactorPhase3: + 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); + } + + return null; + } + + private void updateProperties() { + if (meterRealtimeBodyData == null) { + return; + } + + Map properties = editProperties(); + + properties.put(FroniusBindingConstants.MeterModel, meterRealtimeBodyData.getDetails().getModel()); + properties.put(FroniusBindingConstants.MeterSerial, meterRealtimeBodyData.getDetails().getSerial()); + + updateProperties(properties); + } + + /** + * Get new data + */ + private void updateData(FroniusBridgeConfiguration bridgeConfiguration, FroniusBaseDeviceConfiguration config) { + MeterRealtimeResponseDTO meterRealtimeResponse = getMeterRealtimeData(bridgeConfiguration.hostname, + config.deviceId); + if (meterRealtimeResponse == null) { + meterRealtimeBodyData = null; + } else { + meterRealtimeBodyData = meterRealtimeResponse.getBody().getData(); + } + } + + /** + * Make the MeterRealtimeData request + * + * @param ip address of the device + * @param deviceId of the device + * @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)); + location = location.replace("%DEVICEID%", Integer.toString(deviceId)); + return collectDataFormUrl(MeterRealtimeResponseDTO.class, location); + } +} diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusSymoInverterHandler.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusSymoInverterHandler.java index 0590b21d6..a3683eb7f 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusSymoInverterHandler.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusSymoInverterHandler.java @@ -12,26 +12,17 @@ */ package org.openhab.binding.fronius.internal.handler; -import java.io.IOException; - import org.apache.commons.lang.StringUtils; 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.BaseFroniusResponse; import org.openhab.binding.fronius.internal.api.InverterRealtimeResponse; import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeResponse; import org.openhab.binding.fronius.internal.api.ValueUnit; -import org.openhab.core.io.net.http.HttpUtil; import org.openhab.core.thing.Thing; -import org.openhab.core.thing.ThingStatus; -import org.openhab.core.thing.ThingStatusDetail; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.gson.Gson; -import com.google.gson.JsonSyntaxException; - /** * The {@link FroniusSymoInverterHandler} is responsible for updating the data, which are * sent to one of the channels. @@ -41,16 +32,13 @@ import com.google.gson.JsonSyntaxException; */ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler { - private static final int API_TIMEOUT = 5000; private final Logger logger = LoggerFactory.getLogger(FroniusSymoInverterHandler.class); private InverterRealtimeResponse inverterRealtimeResponse; private PowerFlowRealtimeResponse powerFlowResponse; private FroniusBaseDeviceConfiguration config; - private final Gson gson; public FroniusSymoInverterHandler(Thing thing) { super(thing); - gson = new Gson(); } @Override @@ -149,54 +137,6 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler { powerFlowResponse = getPowerFlowRealtime(bridgeConfiguration.hostname); } - /** - * - * @param type response class type - * @param url to request - * @return the object representation of the json response - */ - private T collectDataFormUrl(Class type, String url) { - T result = null; - boolean resultOk = false; - String errorMsg = null; - - try { - logger.debug("URL = {}", url); - String response = HttpUtil.executeUrl("GET", url, API_TIMEOUT); - - if (response != null) { - logger.debug("aqiResponse = {}", response); - result = gson.fromJson(response, type); - } - - if (result == null) { - errorMsg = "no data returned"; - } else { - if (result.getHead().getStatus().getCode() == 0) { - resultOk = true; - } else { - errorMsg = result.getHead().getStatus().getReason(); - } - } - if (!resultOk) { - logger.debug("Error in fronius response: {}", errorMsg); - } - } catch (JsonSyntaxException e) { - errorMsg = "Configuration is incorrect"; - logger.debug("Error running fronius request: {}", errorMsg); - } catch (IOException | IllegalStateException e) { - logger.debug("Error running fronius request: {}", e.getMessage()); - } - - // Update the thing status - if (resultOk) { - updateStatus(ThingStatus.ONLINE); - } else { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, errorMsg); - } - return resultOk ? result : null; - } - /** * Make the PowerFlowRealtimeDataRequest * diff --git a/bundles/org.openhab.binding.fronius/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.fronius/src/main/resources/OH-INF/thing/thing-types.xml index b110b20f7..d6334bdc8 100644 --- a/bundles/org.openhab.binding.fronius/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.fronius/src/main/resources/OH-INF/thing/thing-types.xml @@ -38,6 +38,75 @@ + + + + + + + Fronius Smart Meter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Specific device identifier + 0 + + + + Number @@ -127,4 +196,49 @@ Battery Power ( + charge, - discharge ) + + + + Number + + Enabled + + + + Number + + Meter location code + + + + Number:ElectricCurrent + + + + + + Number:ElectricPotential + + + + + + Number:Power + + + + + + Number + + + + + + Number:Energy + + + + +