[fronius] Add Autonomy and Self Consumption channels (#12420)

* 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>
This commit is contained in:
jimtng 2022-03-28 03:10:24 +10:00 committed by GitHub
parent 0c2901f3ed
commit c5b6ce97bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 198 additions and 266 deletions

View File

@ -57,25 +57,27 @@ The binding has no configuration options, all configuration is done at `bridge`,
### Channels for `powerinverter` Thing ### Channels for `powerinverter` Thing
| Channel ID | Item Type | Description | | Channel ID | Item Type | Description |
| ------------------------------------ | -------------------- | ----------------------------------------------------------------------------------------------------------------- | | ------------------------------------ | ------------------------ | ----------------------------------------------------------------------------------------------------------------- |
| `inverterdatachanneldayenergy` | Number | Energy generated on current day | | `inverterdatachannelpac` | Number:Power | Power generated |
| `inverterdatachannelpac` | Number | AC power | | `inverterdatachannelfac` | Number:Frequency | AC frequency |
| `inverterdatachanneltotal` | Number | Energy generated overall | | `inverterdatachanneliac` | Number:ElectricCurrent | AC current |
| `inverterdatachannelyear` | Number | Energy generated in current year | | `inverterdatachannelidc` | Number:ElectricCurrent | DC current |
| `inverterdatachannelfac` | Number | AC frequency | | `inverterdatachanneluac` | Number:ElectricPotential | AC voltage |
| `inverterdatachanneliac` | Number | AC current | | `inverterdatachanneludc` | Number:ElectricPotential | DC voltage |
| `inverterdatachannelidc` | Number | DC current | | `inverterdatachanneldayenergy` | Number:Energy | Energy generated on current day |
| `inverterdatachanneluac` | Number | AC voltage | | `inverterdatachannelyear` | Number:Energy | Energy generated in current year |
| `inverterdatachanneludc` | Number | DC voltage | | `inverterdatachanneltotal` | Number:Energy | Energy generated overall |
| `inverterdatadevicestatuserrorcode` | Number | Device error code | | `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 | | `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) | | `powerflowchannelpgrid` | Number:Power | Grid Power (+ from grid, - to grid) |
| `powerflowchannelpload` | Number:Power | Power (+ generator, - consumer) | | `powerflowchannelpload` | Number:Power | Load Power (+ generator, - consumer) |
| `powerflowchannelpakku` | Number:Power | Power (+ charge, - discharge) | | `powerflowchannelpakku` | Number:Power | Battery Power (+ charge, - discharge) |
| `powerflowchannelppv` | Number:Power | Power (+ production) | | `powerflowchannelppv` | Number:Power | Solar Power (+ production) |
| `powerflowinverter1power` | Number:Power | Current power of inverter 1, null if not running (+ produce/export, - consume/import) | | `powerflowautonomy` | Number:Dimensionless | The current relative autonomy in % |
| `powerflowinverter1soc` | Number:Dimensionless | Current state of charge of inverter 1 in percent | | `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 ### 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 | | `powerfactorphase3` | Number | Power Factor on Phase 3 |
| `energyrealsumconsumed` | Number:Energy | Real Energy consumed | | `energyrealsumconsumed` | Number:Energy | Real Energy consumed |
| `energyrealsumproduced` | Number:Energy | Real Energy produced | | `energyrealsumproduced` | Number:Energy | Real Energy produced |
| |
### Channels for `ohmpilot` Thing ### Channels for `ohmpilot` Thing
@ -110,7 +111,6 @@ The binding has no configuration options, all configuration is done at `bridge`,
| `temperaturechannel1` | Number:Temperature | Temperature | | `temperaturechannel1` | Number:Temperature | Temperature |
| `errorcode` | Number | Device error code | | `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 | | `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 ## Properties
@ -144,21 +144,23 @@ Bridge fronius:bridge:mybridge [hostname="192.168.66.148", refreshInterval=5] {
demo.items: demo.items:
``` ```
Number AC_Power { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachannelpac" } Number:Power AC_Power { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachannelpac" }
Number Day_Energy { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneldayenergy" } Number:Energy Day_Energy { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneldayenergy" }
Number Total_Energy { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneltotal" } Number:Energy Total_Energy { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneltotal" }
Number Year_Energy { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachannelyear" } Number:Energy Year_Energy { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachannelyear" }
Number FAC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachannelfac" } Number:Frequency FAC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachannelfac" }
Number IAC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneliac" } Number:ElectricCurrent IAC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneliac" }
Number IDC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachannelidc" } Number:ElectricCurrent IDC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachannelidc" }
Number UAC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneluac" } Number:ElectricPotential UAC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneluac" }
Number UDC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneludc" } Number:ElectricPotential UDC { channel="fronius:powerinverter:mybridge:myinverter:inverterdatachanneludc" }
Number ErrorCode { channel="fronius:powerinverter:mybridge:myinverter:inverterdatadevicestatuserrorcode" } Number ErrorCode { channel="fronius:powerinverter:mybridge:myinverter:inverterdatadevicestatuserrorcode" }
Number StatusCode { channel="fronius:powerinverter:mybridge:myinverter:inverterdatadevicestatusstatuscode" } Number StatusCode { channel="fronius:powerinverter:mybridge:myinverter:inverterdatadevicestatusstatuscode" }
Number:Power Grid_Power { channel="fronius:powerinverter:mybridge:myinverter:powerflowchannelpgrid" } Number:Power Grid_Power { channel="fronius:powerinverter:mybridge:myinverter:powerflowchannelpgrid" }
Number:Power Load_Power { channel="fronius:powerinverter:mybridge:myinverter:powerflowchannelpload" } Number:Power Load_Power { channel="fronius:powerinverter:mybridge:myinverter:powerflowchannelpload" }
Number:Power Battery_Power { channel="fronius:powerinverter:mybridge:myinverter:powerflowchannelpakku" } Number:Power Battery_Power { channel="fronius:powerinverter:mybridge:myinverter:powerflowchannelpakku" }
Number:Power Production_Power { channel="fronius:powerinverter:mybridge:myinverter:powerflowchannelppv" } 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:Power Inverter1_Power { channel="fronius:powerinverter:mybridge:myinverter:powerflowinverter1power" }
Number:Dimensionless Inverter1_SOC { channel="fronius:powerinverter:mybridge:myinverter:powerflowinverter1soc" } Number:Dimensionless Inverter1_SOC { channel="fronius:powerinverter:mybridge:myinverter:powerflowinverter1soc" }

View File

@ -23,6 +23,7 @@ import org.openhab.core.thing.ThingTypeUID;
* @author Peter Schraffl - Added device status and error status channels * @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 Thomas Kordelle - Added inverter power, battery state of charge and PV solar yield
* @author Hannes Spenger - Added ohmpilot & meter power sum * @author Hannes Spenger - Added ohmpilot & meter power sum
* @author Jimmy Tanagra - Implement a common url parsing method
*/ */
@NonNullByDefault @NonNullByDefault
public class FroniusBindingConstants { public class FroniusBindingConstants {
@ -30,12 +31,12 @@ public class FroniusBindingConstants {
private static final String BINDING_ID = "fronius"; private static final String BINDING_ID = "fronius";
// List of all Thing Type UIDs // 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_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_METER = new ThingTypeUID(BINDING_ID, "meter");
public static final ThingTypeUID THING_TYPE_OHMPILOT = new ThingTypeUID(BINDING_ID, "ohmpilot"); 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_DAY_ENERGY = "inverterdatachanneldayenergy";
public static final String INVERTER_DATA_CHANNEL_PAC = "inverterdatachannelpac"; 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_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_UDC = "inverterdatachanneludc";
public static final String INVERTER_DATA_CHANNEL_DEVICE_STATUS_ERROR_CODE = "inverterdatadevicestatuserrorcode"; 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 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_GRID = "powerflowchannelpgrid";
public static final String POWER_FLOW_P_LOAD = "powerflowchannelpload"; 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_AKKU = "powerflowchannelpakku";
public static final String POWER_FLOW_P_PV = "powerflowchannelppv"; 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_ENABLE = "enable";
public static final String METER_LOCATION = "location"; 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_1 = "currentacphase1";
@ -68,29 +78,41 @@ public class FroniusBindingConstants {
public static final String METER_POWER_FACTOR_PHASE_3 = "powerfactorphase3"; 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_CONSUMED = "energyrealsumconsumed";
public static final String METER_ENERGY_REAL_SUM_PRODUCED = "energyrealsumproduced"; 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_POWER_REAL_SUM = "powerrealsum";
public static final String OHMPILOT_ENERGY_REAL_SUM_CONSUMED = "energyrealsumconsumed"; 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_ENERGY_SENSOR_TEMPERATURE_CHANNEL_1 = "temperaturechannel1";
public static final String OHMPILOT_ERROR_CODE = "errorcode"; public static final String OHMPILOT_ERROR_CODE = "errorcode";
public static final String OHMPILOT_STATE_CODE = "statecode"; 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 // 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 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 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 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));
}
} }

View File

@ -12,7 +12,12 @@
*/ */
package org.openhab.binding.fronius.internal.api; 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; import com.google.gson.annotations.SerializedName;
@ -21,12 +26,14 @@ import com.google.gson.annotations.SerializedName;
* a value * a value
* *
* @author Thomas Rokohl - Initial contribution * @author Thomas Rokohl - Initial contribution
* @author Jimmy Tanagra - Add conversion to QuantityType
*/ */
public class ValueUnit { public class ValueUnit {
@SerializedName("Value") @SerializedName("Value")
private double value; private double value;
@SerializedName("Unit") @SerializedName("Unit")
private String unit; private String unit = "";
public double getValue() { public double getValue() {
return value; return value;
@ -37,14 +44,20 @@ public class ValueUnit {
} }
public String getUnit() { public String getUnit() {
if (unit == null) { return this.unit == null ? "" : this.unit;
unit = "";
}
return unit;
} }
public void setUnit(String unit) { public void setUnit(String unit) {
this.setValue(KilowattConverter.convertTo(this.getValue(), this.getUnit(), unit));
this.unit = 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);
}
} }

View 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.FroniusHttpUtil;
import org.openhab.binding.fronius.internal.api.BaseFroniusResponse; import org.openhab.binding.fronius.internal.api.BaseFroniusResponse;
import org.openhab.binding.fronius.internal.api.HeadStatus; 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.Bridge;
import org.openhab.core.thing.Channel; import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID; 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.Command;
import org.openhab.core.types.RefreshType; import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State; import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -45,6 +42,8 @@ import com.google.gson.JsonSyntaxException;
* @author Thomas Rokohl - Refactoring to merge the concepts * @author Thomas Rokohl - Refactoring to merge the concepts
* @author Thomas Kordelle - Added inverter power, battery state of charge and PV solar yield * @author Thomas Kordelle - Added inverter power, battery state of charge and PV solar yield
* @author Jimmy Tanagra - Implement connection retry * @author Jimmy Tanagra - Implement connection retry
* Convert ValueUnit to QuantityType
* Support NULL value
*/ */
public abstract class FroniusBaseThingHandler extends BaseThingHandler { public abstract class FroniusBaseThingHandler extends BaseThingHandler {
@ -100,31 +99,16 @@ public abstract class FroniusBaseThingHandler extends BaseThingHandler {
return; return;
} }
Object value = getValue(channelId); State state = getValue(channelId);
if (value == null) { if (state == null) {
logger.debug("Value retrieved for channel '{}' was null. Can't update.", channelId); state = UnDefType.NULL;
return;
} }
State state = null; if (logger.isTraceEnabled()) {
if (value instanceof QuantityType) { logger.trace("Update channel {} with state {} ({})", channelId, state.toString(),
state = (QuantityType) value; state.getClass().getSimpleName());
} 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());
}
logger.trace("Update channel {} with state {} ({})", channelId, (state == null) ? "null" : state.toString(),
value.getClass().getSimpleName());
// Update the channel
if (state != null) {
updateState(channelId, state);
} }
updateState(channelId, state);
} }
/** /**
@ -140,7 +124,7 @@ public abstract class FroniusBaseThingHandler extends BaseThingHandler {
* @param channelId the id identifying the channel * @param channelId the id identifying the channel
* @return the "new" associated value * @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 * Called by the bridge to fetch data and update channels

View 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.FroniusCommunicationException;
import org.openhab.binding.fronius.internal.api.MeterRealtimeBodyDataDTO; import org.openhab.binding.fronius.internal.api.MeterRealtimeBodyDataDTO;
import org.openhab.binding.fronius.internal.api.MeterRealtimeResponseDTO; 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.types.QuantityType;
import org.openhab.core.library.unit.Units; import org.openhab.core.library.unit.Units;
import org.openhab.core.thing.Thing; import org.openhab.core.thing.Thing;
import org.openhab.core.types.State;
/** /**
* The {@link FroniusMeterHandler} is responsible for updating the data, which are * 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 * @return the last retrieved data
*/ */
@Override @Override
protected Object getValue(String channelId) { protected State getValue(String channelId) {
if (meterRealtimeBodyData == null) { if (meterRealtimeBodyData == null) {
return null; return null;
} }
@ -79,9 +81,9 @@ public class FroniusMeterHandler extends FroniusBaseThingHandler {
switch (fieldName) { switch (fieldName) {
case FroniusBindingConstants.METER_ENABLE: case FroniusBindingConstants.METER_ENABLE:
return meterRealtimeBodyData.getEnable(); return new DecimalType(meterRealtimeBodyData.getEnable());
case FroniusBindingConstants.METER_LOCATION: case FroniusBindingConstants.METER_LOCATION:
return meterRealtimeBodyData.getMeterLocationCurrent(); return new DecimalType(meterRealtimeBodyData.getMeterLocationCurrent());
case FroniusBindingConstants.METER_CURRENT_AC_PHASE_1: case FroniusBindingConstants.METER_CURRENT_AC_PHASE_1:
return new QuantityType<>(meterRealtimeBodyData.getCurrentACPhase1(), Units.AMPERE); return new QuantityType<>(meterRealtimeBodyData.getCurrentACPhase1(), Units.AMPERE);
case FroniusBindingConstants.METER_CURRENT_AC_PHASE_2: case FroniusBindingConstants.METER_CURRENT_AC_PHASE_2:
@ -103,11 +105,11 @@ public class FroniusMeterHandler extends FroniusBaseThingHandler {
case FroniusBindingConstants.METER_POWER_SUM: case FroniusBindingConstants.METER_POWER_SUM:
return new QuantityType<>(meterRealtimeBodyData.getPowerRealPSum(), Units.WATT); return new QuantityType<>(meterRealtimeBodyData.getPowerRealPSum(), Units.WATT);
case FroniusBindingConstants.METER_POWER_FACTOR_PHASE_1: case FroniusBindingConstants.METER_POWER_FACTOR_PHASE_1:
return meterRealtimeBodyData.getPowerFactorPhase1(); return new DecimalType(meterRealtimeBodyData.getPowerFactorPhase1());
case FroniusBindingConstants.METER_POWER_FACTOR_PHASE_2: case FroniusBindingConstants.METER_POWER_FACTOR_PHASE_2:
return meterRealtimeBodyData.getPowerFactorPhase2(); return new DecimalType(meterRealtimeBodyData.getPowerFactorPhase2());
case FroniusBindingConstants.METER_POWER_FACTOR_PHASE_3: case FroniusBindingConstants.METER_POWER_FACTOR_PHASE_3:
return meterRealtimeBodyData.getPowerFactorPhase3(); return new DecimalType(meterRealtimeBodyData.getPowerFactorPhase3());
case FroniusBindingConstants.METER_ENERGY_REAL_SUM_CONSUMED: case FroniusBindingConstants.METER_ENERGY_REAL_SUM_CONSUMED:
return new QuantityType<>(meterRealtimeBodyData.getEnergyRealWACSumConsumed(), Units.WATT_HOUR); return new QuantityType<>(meterRealtimeBodyData.getEnergyRealWACSumConsumed(), Units.WATT_HOUR);
case FroniusBindingConstants.METER_ENERGY_REAL_SUM_PRODUCED: case FroniusBindingConstants.METER_ENERGY_REAL_SUM_PRODUCED:
@ -151,9 +153,7 @@ public class FroniusMeterHandler extends FroniusBaseThingHandler {
*/ */
private MeterRealtimeResponseDTO getMeterRealtimeData(String ip, int deviceId) private MeterRealtimeResponseDTO getMeterRealtimeData(String ip, int deviceId)
throws FroniusCommunicationException { throws FroniusCommunicationException {
String location = FroniusBindingConstants.METER_REALTIME_DATA_URL.replace("%IP%", String location = FroniusBindingConstants.getMeterDataUrl(ip, deviceId);
(ip != null ? ip.trim() : ""));
location = location.replace("%DEVICEID%", Integer.toString(deviceId));
return collectDataFromUrl(MeterRealtimeResponseDTO.class, location); return collectDataFromUrl(MeterRealtimeResponseDTO.class, location);
} }
} }

View File

@ -24,6 +24,7 @@ import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.Units; import org.openhab.core.library.unit.Units;
import org.openhab.core.thing.Thing; import org.openhab.core.thing.Thing;
import org.openhab.core.types.State;
/** /**
* The {@link FroniusOhmpilotHandler} is responsible for updating the data, which are * 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 * @return the last retrieved data
*/ */
@Override @Override
protected Object getValue(String channelId) { protected State getValue(String channelId) {
if (ohmpilotRealtimeBodyData == null) { if (ohmpilotRealtimeBodyData == null) {
return null; return null;
} }
@ -128,9 +129,7 @@ public class FroniusOhmpilotHandler extends FroniusBaseThingHandler {
*/ */
private OhmpilotRealtimeResponseDTO getOhmpilotRealtimeData(String ip, int deviceId) private OhmpilotRealtimeResponseDTO getOhmpilotRealtimeData(String ip, int deviceId)
throws FroniusCommunicationException { throws FroniusCommunicationException {
String location = FroniusBindingConstants.OHMPILOT_REALTIME_DATA_URL.replace("%IP%", String location = FroniusBindingConstants.getOhmPilotDataUrl(ip, deviceId);
(ip != null ? ip.trim() : ""));
location = location.replace("%DEVICEID%", Integer.toString(deviceId));
return collectDataFromUrl(OhmpilotRealtimeResponseDTO.class, location); return collectDataFromUrl(OhmpilotRealtimeResponseDTO.class, location);
} }
} }

View File

@ -12,19 +12,25 @@
*/ */
package org.openhab.binding.fronius.internal.handler; 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.FroniusBaseDeviceConfiguration;
import org.openhab.binding.fronius.internal.FroniusBindingConstants; import org.openhab.binding.fronius.internal.FroniusBindingConstants;
import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration; import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration;
import org.openhab.binding.fronius.internal.FroniusCommunicationException; 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.InverterRealtimeResponse;
import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeInverter; import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeInverter;
import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeResponse; 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.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.QuantityType;
import org.openhab.core.library.unit.Units; import org.openhab.core.library.unit.Units;
import org.openhab.core.thing.Thing; import org.openhab.core.thing.Thing;
import org.openhab.core.types.State;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -35,14 +41,10 @@ import org.slf4j.LoggerFactory;
* @author Thomas Rokohl - Initial contribution * @author Thomas Rokohl - Initial contribution
* @author Peter Schraffl - Added device status and error status channels * @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 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 { 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 final Logger logger = LoggerFactory.getLogger(FroniusSymoInverterHandler.class);
private InverterRealtimeResponse inverterRealtimeResponse; private InverterRealtimeResponse inverterRealtimeResponse;
private PowerFlowRealtimeResponse powerFlowResponse; private PowerFlowRealtimeResponse powerFlowResponse;
@ -76,7 +78,7 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
* @return the last retrieved data * @return the last retrieved data
*/ */
@Override @Override
protected Object getValue(String channelId) { protected State getValue(String channelId) {
final String[] fields = channelId.split("#"); final String[] fields = channelId.split("#");
if (fields.length < 1) { if (fields.length < 1) {
return null; return null;
@ -84,65 +86,57 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
final String fieldName = fields[0]; final String fieldName = fields[0];
if (inverterRealtimeResponse != null) { if (inverterRealtimeResponse != null) {
InverterRealtimeBodyData inverterData = inverterRealtimeResponse.getBody().getData();
switch (fieldName) { 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: case FroniusBindingConstants.INVERTER_DATA_CHANNEL_PAC:
ValueUnit pac = inverterRealtimeResponse.getBody().getData().getPac(); return getQuantityOrZero(inverterData.getPac(), Units.WATT);
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: case FroniusBindingConstants.INVERTER_DATA_CHANNEL_FAC:
return inverterRealtimeResponse.getBody().getData().getFac(); return getQuantityOrZero(inverterData.getFac(), Units.HERTZ);
case FroniusBindingConstants.INVERTER_DATA_CHANNEL_IAC: case FroniusBindingConstants.INVERTER_DATA_CHANNEL_IAC:
return inverterRealtimeResponse.getBody().getData().getIac(); return getQuantityOrZero(inverterData.getIac(), Units.AMPERE);
case FroniusBindingConstants.INVERTER_DATA_CHANNEL_IDC: case FroniusBindingConstants.INVERTER_DATA_CHANNEL_IDC:
return inverterRealtimeResponse.getBody().getData().getIdc(); return getQuantityOrZero(inverterData.getIdc(), Units.AMPERE);
case FroniusBindingConstants.INVERTER_DATA_CHANNEL_UAC: case FroniusBindingConstants.INVERTER_DATA_CHANNEL_UAC:
return inverterRealtimeResponse.getBody().getData().getUac(); return getQuantityOrZero(inverterData.getUac(), Units.VOLT);
case FroniusBindingConstants.INVERTER_DATA_CHANNEL_UDC: 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: 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: case FroniusBindingConstants.INVERTER_DATA_CHANNEL_DEVICE_STATUS_STATUS_CODE:
return inverterRealtimeResponse.getBody().getData().getDeviceStatus().getStatusCode(); return new DecimalType(inverterData.getDeviceStatus().getStatusCode());
default: default:
break; break;
} }
} }
if (powerFlowResponse != null) { if (powerFlowResponse != null) {
PowerFlowRealtimeSite site = powerFlowResponse.getBody().getData().getSite();
switch (fieldName) { switch (fieldName) {
case FroniusBindingConstants.POWER_FLOW_P_GRID: 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: 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: 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: 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: 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: case FroniusBindingConstants.POWER_FLOW_INVERTER_1_SOC:
return getInverterFlowValue(INVERTER_SOC, "1"); return new QuantityType<>(getInverter("1").getSoc(), Units.PERCENT);
default: default:
break; break;
} }
@ -154,25 +148,24 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
/** /**
* get flow data for a specific inverter. * get flow data for a specific inverter.
* *
* @param fieldName * @param number The inverter object of the given index
* @param number * @return an PowerFlowRealtimeInverter object.
* @return
*/ */
private Object getInverterFlowValue(final String fieldName, final String number) { private PowerFlowRealtimeInverter getInverter(final String number) {
final Map<String, PowerFlowRealtimeInverter> inverters = powerFlowResponse.getBody().getData().getInverters(); return powerFlowResponse.getBody().getData().getInverters().get(number);
if ((inverters == null) || (inverters.get(number) == null)) { }
logger.debug("No data for inverter '{}' found.", number);
return null; /**
} * Return the value as QuantityType with the unit extracted from ValueUnit
switch (fieldName) { * or a zero QuantityType with the given unit argument when value is null
case INVERTER_POWER: *
return new QuantityType<>(inverters.get(number).getP(), Units.WATT); * @param value The ValueUnit data
case INVERTER_SOC: * @param unit The default unit to use when value is null
return new QuantityType<>(inverters.get(number).getSoc(), Units.PERCENT); * @return a QuantityType from the given value
default: */
break; private QuantityType<?> getQuantityOrZero(ValueUnit value, Unit unit) {
} return Optional.ofNullable(value).map(val -> val.asQuantityType().toUnit(unit))
return null; .orElse(new QuantityType<>(0, unit));
} }
/** /**
@ -191,8 +184,7 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
* @return {PowerFlowRealtimeResponse} the object representation of the json response * @return {PowerFlowRealtimeResponse} the object representation of the json response
*/ */
private PowerFlowRealtimeResponse getPowerFlowRealtime(String ip) throws FroniusCommunicationException { private PowerFlowRealtimeResponse getPowerFlowRealtime(String ip) throws FroniusCommunicationException {
String location = FroniusBindingConstants.POWERFLOW_REALTIME_DATA.replace("%IP%", String location = FroniusBindingConstants.getPowerFlowDataUrl(ip);
(ip != null ? ip.trim() : ""));
return collectDataFromUrl(PowerFlowRealtimeResponse.class, location); return collectDataFromUrl(PowerFlowRealtimeResponse.class, location);
} }
@ -204,9 +196,7 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
* @return {InverterRealtimeResponse} the object representation of the json response * @return {InverterRealtimeResponse} the object representation of the json response
*/ */
private InverterRealtimeResponse getRealtimeData(String ip, int deviceId) throws FroniusCommunicationException { private InverterRealtimeResponse getRealtimeData(String ip, int deviceId) throws FroniusCommunicationException {
String location = FroniusBindingConstants.INVERTER_REALTIME_DATA_URL.replace("%IP%", String location = FroniusBindingConstants.getInverterDataUrl(ip, deviceId);
(ip != null ? ip.trim() : ""));
location = location.replace("%DEVICEID%", Integer.toString(deviceId));
return collectDataFromUrl(InverterRealtimeResponse.class, location); return collectDataFromUrl(InverterRealtimeResponse.class, location);
} }
} }

View File

@ -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);
}
}

View File

@ -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;
}
}

View 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.pPv.description = Current Solar Plant Power
channel-type.fronius.pac.label = AC Power channel-type.fronius.pac.label = AC Power
channel-type.fronius.pac.description = 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.label = Total Energy
channel-type.fronius.total_energy.description = Energy generated overall channel-type.fronius.total_energy.description = Energy generated overall
channel-type.fronius.uac.label = AC Voltage channel-type.fronius.uac.label = AC Voltage

View File

@ -34,6 +34,8 @@
<channel id="powerflowchannelppv" typeId="pPv"> <channel id="powerflowchannelppv" typeId="pPv">
<label>Current Solar Yield</label> <label>Current Solar Yield</label>
</channel> </channel>
<channel id="powerflowautonomy" typeId="powerflow_rel_autonomy"/>
<channel id="powerflowselfconsumption" typeId="powerflow_rel_selfconsumption"/>
<channel id="powerflowinverter1power" typeId="inverter1Power"> <channel id="powerflowinverter1power" typeId="inverter1Power">
<label>Power Flow (Inverter 1)</label> <label>Power Flow (Inverter 1)</label>
</channel> </channel>
@ -144,58 +146,58 @@
</thing-type> </thing-type>
<channel-type id="day_energy"> <channel-type id="day_energy">
<item-type>Number</item-type> <item-type>Number:Energy</item-type>
<label>Day Energy</label> <label>Day Energy</label>
<description>Energy generated on current day</description> <description>Energy generated on current day</description>
<state pattern="%.2f kWh" readOnly="true"></state> <state pattern="%.2f kWh" readOnly="true"></state>
</channel-type> </channel-type>
<channel-type id="pac"> <channel-type id="pac">
<item-type>Number</item-type> <item-type>Number:Power</item-type>
<label>AC Power</label> <label>AC Power</label>
<description>AC power</description> <description>AC power</description>
<state pattern="%f W" readOnly="true"></state> <state pattern="%f W" readOnly="true"></state>
</channel-type> </channel-type>
<channel-type id="total_energy"> <channel-type id="total_energy">
<item-type>Number</item-type> <item-type>Number:Energy</item-type>
<label>Total Energy</label> <label>Total Energy</label>
<description>Energy generated overall</description> <description>Energy generated overall</description>
<state pattern="%.3f MWh" readOnly="true"></state> <state pattern="%.3f MWh" readOnly="true"></state>
</channel-type> </channel-type>
<channel-type id="year_energy"> <channel-type id="year_energy">
<item-type>Number</item-type> <item-type>Number:Energy</item-type>
<label>Year Energy</label> <label>Year Energy</label>
<description>Energy generated in current year</description> <description>Energy generated in current year</description>
<state pattern="%.3f MWh" readOnly="true"></state> <state pattern="%.3f MWh" readOnly="true"></state>
</channel-type> </channel-type>
<channel-type id="fac"> <channel-type id="fac">
<item-type>Number</item-type> <item-type>Number:Frequency</item-type>
<label>AC Frequency</label> <label>AC Frequency</label>
<description>AC frequency</description> <description>AC frequency</description>
<state pattern="%.2f Hz" readOnly="true"></state> <state pattern="%.2f Hz" readOnly="true"></state>
</channel-type> </channel-type>
<channel-type id="iac"> <channel-type id="iac">
<item-type>Number</item-type> <item-type>Number:ElectricCurrent</item-type>
<label>AC Current</label> <label>AC Current</label>
<description>AC current</description> <description>AC current</description>
<state pattern="%.2f A" readOnly="true"></state> <state pattern="%.2f A" readOnly="true"></state>
</channel-type> </channel-type>
<channel-type id="idc"> <channel-type id="idc">
<item-type>Number</item-type> <item-type>Number:ElectricCurrent</item-type>
<label>DC Current</label> <label>DC Current</label>
<description>DC current</description> <description>DC current</description>
<state pattern="%.2f A" readOnly="true"></state> <state pattern="%.2f A" readOnly="true"></state>
</channel-type> </channel-type>
<channel-type id="uac"> <channel-type id="uac">
<item-type>Number</item-type> <item-type>Number:ElectricPotential</item-type>
<label>AC Voltage</label> <label>AC Voltage</label>
<description>AC voltage</description> <description>AC voltage</description>
<state pattern="%.1f V" readOnly="true"></state> <state pattern="%.1f V" readOnly="true"></state>
</channel-type> </channel-type>
<channel-type id="udc"> <channel-type id="udc">
<item-type>Number</item-type> <item-type>Number:ElectricPotential</item-type>
<label>DC Voltage</label> <label>DC Voltage</label>
<description>DC voltage</description> <description>DC voltage</description>
<state pattern="%.1f V" readOnly="true"></state> <state pattern="%.1f V" readOnly="true"></state>
@ -238,6 +240,18 @@
<description>Current Solar Plant Power</description> <description>Current Solar Plant Power</description>
<state pattern="%.2f %unit%" readOnly="true"></state> <state pattern="%.2f %unit%" readOnly="true"></state>
</channel-type> </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"> <channel-type id="inverter1Power">
<item-type>Number:Power</item-type> <item-type>Number:Power</item-type>
<label>Inverter 1 Power</label> <label>Inverter 1 Power</label>
@ -310,5 +324,4 @@
</channel-type> </channel-type>
</thing:thing-descriptions> </thing:thing-descriptions>