[fronius] Improve package structure & Enhance null annotations/handling (#17109)

* [fronius] Restructure DTOs & Improve null annotations/handling

Signed-off-by: Florian Hotze <florianh_dev@icloud.com>
Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
Florian Hotze 2024-07-25 09:47:22 +02:00 committed by Ciprian Pascu
parent 4d45b65917
commit 0cf877864a
32 changed files with 515 additions and 818 deletions

View File

@ -103,6 +103,8 @@ public class FroniusBindingConstants {
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 int API_TIMEOUT = 5000;
public static String getInverterDataUrl(String ip, int deviceId) {
return parseUrl(INVERTER_REALTIME_DATA_URL, ip, deviceId);
}
@ -120,7 +122,7 @@ public class FroniusBindingConstants {
}
public static String parseUrl(String url, String ip) {
return url.replace("%IP%", ip == null ? "" : ip.trim());
return url.replace("%IP%", ip.trim());
}
public static String parseUrl(String url, String ip, int deviceId) {

View File

@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal;
package org.openhab.binding.fronius.internal.api;
import java.io.IOException;

View File

@ -10,18 +10,19 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal;
package org.openhab.binding.fronius.internal.api;
import java.io.IOException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jetty.http.HttpMethod;
import org.openhab.core.io.net.http.HttpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* A version of HttpUtil implementation that retries on failure
* A version of HttpUtil implementation that retries on failure.
*
* @author Jimmy Tanagra - Initial contribution
*
@ -31,26 +32,29 @@ public class FroniusHttpUtil {
private static final Logger logger = LoggerFactory.getLogger(FroniusHttpUtil.class);
/**
* Issue a HTTP GET request and retry on failure
* Issue a HTTP request and retry on failure.
*
* @param httpMethod the HTTP method to use
* @param url the url to execute
* @param timeout the socket timeout in milliseconds to wait for data
* @return the response body
* @throws FroniusCommunicationException when the request execution failed or interrupted
*/
public static synchronized String executeUrl(String url, int timeout) throws FroniusCommunicationException {
public static synchronized String executeUrl(HttpMethod httpMethod, String url, int timeout)
throws FroniusCommunicationException {
int attemptCount = 1;
try {
while (true) {
Throwable lastException = null;
String result = null;
try {
result = HttpUtil.executeUrl("GET", url, timeout);
result = HttpUtil.executeUrl(httpMethod.asString(), url, timeout);
} catch (IOException e) {
// HttpUtil::executeUrl wraps InterruptedException into IOException.
// Unwrap and rethrow it so that we don't retry on InterruptedException
if (e.getCause() instanceof InterruptedException) {
throw (InterruptedException) e.getCause();
Throwable cause = e.getCause();
if (cause instanceof InterruptedException interruptException) {
throw interruptException;
}
lastException = e;
}

View File

@ -1,68 +0,0 @@
/**
* Copyright (c) 2010-2024 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 Head} is responsible for storing
* the "head" node of the JSON response from the Fronius Solar APIs (V1)
*
* The contents of the response object will vary depending on the preceding request but it always contains a common
* response header and a request body.
*
* @author Thomas Rokohl - Initial contribution
*/
public class Head {
@SerializedName("RequestArguments")
private HeadRequestArguments requestArguments;
@SerializedName("Status")
private HeadStatus status;
@SerializedName("Timestamp")
private String timestamp;
public HeadRequestArguments getRequestArguments() {
if (requestArguments == null) {
requestArguments = new HeadRequestArguments();
}
return requestArguments;
}
public void setRequestArguments(HeadRequestArguments requestArguments) {
this.requestArguments = requestArguments;
}
public HeadStatus getStatus() {
if (status == null) {
status = new HeadStatus();
status.setCode(255);
status.setReason("undefined runtime error");
}
return status;
}
public void setStatus(HeadStatus status) {
this.status = status;
}
public String getTimestamp() {
if (timestamp == null) {
timestamp = "";
}
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
}

View File

@ -1,76 +0,0 @@
/**
* Copyright (c) 2010-2024 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 HeadRequestArguments} is responsible for storing
* the "RequestArguments" node from the {@link Head}
*
* @author Thomas Rokohl - Initial contribution
*/
public class HeadRequestArguments {
@SerializedName("DataCollection")
private String dataCollection;
@SerializedName("DeviceClass")
private String deviceClass;
@SerializedName("DeviceId")
private String deviceId;
@SerializedName("Scope")
private String scope;
public String getDataCollection() {
if (null == dataCollection) {
dataCollection = "";
}
return dataCollection;
}
public void setDataCollection(String dataCollection) {
this.dataCollection = dataCollection;
}
public String getDeviceClass() {
if (null == deviceClass) {
deviceClass = "";
}
return deviceClass;
}
public void setDeviceClass(String deviceClass) {
this.deviceClass = deviceClass;
}
public String getDeviceId() {
if (null == deviceId) {
deviceId = "";
}
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getScope() {
if (null == scope) {
scope = "";
}
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
}

View File

@ -10,27 +10,24 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import com.google.gson.annotations.SerializedName;
/**
* base class for a response-object from the API
* Base class for a response-object from the Fronius Solar API (v1).
*
* @author Thomas Rokohl - Initial contribution
*/
@NonNullByDefault
public class BaseFroniusResponse {
@SerializedName("Head")
private Head head;
private @Nullable Head head;
public Head getHead() {
if (head == null) {
head = new Head();
}
public @Nullable Head getHead() {
return head;
}
public void setHead(Head head) {
this.head = head;
}
}

View File

@ -0,0 +1,49 @@
/**
* Copyright (c) 2010-2024 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.dto;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import com.google.gson.annotations.SerializedName;
/**
* The {@link Head} is responsible for storing the "Head" node of the JSON response from the
* {@link BaseFroniusResponse}.
*
* The contents of the response object will vary depending on the preceding request but it always contains a common
* response header and a request body.
*
* @author Thomas Rokohl - Initial contribution
*/
@NonNullByDefault
public class Head {
@SerializedName("RequestArguments")
private @Nullable HeadRequestArguments requestArguments;
@SerializedName("Status")
private @Nullable HeadStatus status;
@SerializedName("Timestamp")
private @Nullable String timestamp;
public @Nullable HeadRequestArguments getRequestArguments() {
return requestArguments;
}
public @Nullable HeadStatus getStatus() {
return status;
}
public @Nullable String getTimestamp() {
return timestamp;
}
}

View File

@ -0,0 +1,51 @@
/**
* Copyright (c) 2010-2024 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.dto;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import com.google.gson.annotations.SerializedName;
/**
* The {@link HeadRequestArguments} is responsible for storing the "RequestArguments" node from the {@link Head}.
*
* @author Thomas Rokohl - Initial contribution
*/
@NonNullByDefault
public class HeadRequestArguments {
@SerializedName("DataCollection")
private @Nullable String dataCollection;
@SerializedName("DeviceClass")
private @Nullable String deviceClass;
@SerializedName("DeviceId")
private @Nullable String deviceId;
@SerializedName("Scope")
private @Nullable String scope;
public @Nullable String getDataCollection() {
return dataCollection;
}
public @Nullable String getDeviceClass() {
return deviceClass;
}
public @Nullable String getDeviceId() {
return deviceId;
}
public @Nullable String getScope() {
return scope;
}
}

View File

@ -10,13 +10,12 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto;
import com.google.gson.annotations.SerializedName;
/**
* The {@link HeadStatus} is responsible for storing
* the "status" node from the {@link Head}
* The {@link HeadStatus} is responsible for storing the "Status" node from the {@link Head}.
*
* @author Thomas Rokohl - Initial contribution
*/

View File

@ -10,10 +10,12 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto;
import javax.measure.Unit;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.types.util.UnitUtils;
import org.slf4j.Logger;
@ -22,33 +24,24 @@ import org.slf4j.LoggerFactory;
import com.google.gson.annotations.SerializedName;
/**
* The {@link InverterRealtimeResponse} is responsible for storing
* a value
* The {@link ValueUnit} is responsible for storing a value.
*
* @author Thomas Rokohl - Initial contribution
* @author Jimmy Tanagra - Add conversion to QuantityType
*/
@NonNullByDefault
public class ValueUnit {
@SerializedName("Value")
private double value;
@SerializedName("Unit")
private String unit = "";
private @Nullable String unit = "";
public double getValue() {
return value;
}
public void setValue(double value) {
this.value = value;
}
public String getUnit() {
return this.unit == null ? "" : this.unit;
}
public void setUnit(String unit) {
this.unit = unit;
public @Nullable String getUnit() {
return unit;
}
public QuantityType<?> asQuantityType() {

View File

@ -10,17 +10,17 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto.inverter;
import com.google.gson.annotations.SerializedName;
/**
* The {@link DeviceStatus} is responsible for storing
* the "devicestatus" node
* The {@link InverterDeviceStatus} is responsible for storing
* the "DeviceStatus" node of the {@link InverterRealtimeBodyData}.
*
* @author Thomas Rokohl - Initial contribution
*/
public class DeviceStatus {
public class InverterDeviceStatus {
@SerializedName("StatusCode")
private int statusCode;
@SerializedName("MgmtTimerRemainingTime")
@ -38,47 +38,23 @@ public class DeviceStatus {
return statusCode;
}
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}
public int getMgmtTimerRemainingTime() {
return mgmtTimerRemainingTime;
}
public void setMgmtTimerRemainingTime(int mgmtTimerRemainingTime) {
this.mgmtTimerRemainingTime = mgmtTimerRemainingTime;
}
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public int getLedColor() {
return ledColor;
}
public void setLedColor(int ledColor) {
this.ledColor = ledColor;
}
public int getLedState() {
return ledState;
}
public void setLedState(int ledState) {
this.ledState = ledState;
}
public boolean isStateToReset() {
return stateToReset;
}
public void setStateToReset(boolean stateToReset) {
this.stateToReset = stateToReset;
}
}

View File

@ -10,28 +10,25 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto.inverter;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import com.google.gson.annotations.SerializedName;
/**
* The {@link InverterRealtimeBody} is responsible for storing
* the "body" node of the JSON response
* the "Body" node of the {@link InverterRealtimeResponse}.
*
* @author Thomas Rokohl - Initial contribution
*/
@NonNullByDefault
public class InverterRealtimeBody {
@SerializedName("Data")
private InverterRealtimeBodyData data;
private @Nullable InverterRealtimeBodyData data;
public InverterRealtimeBodyData getData() {
if (data == null) {
data = new InverterRealtimeBodyData();
}
public @Nullable InverterRealtimeBodyData getData() {
return data;
}
public void setData(InverterRealtimeBodyData data) {
this.data = data;
}
}

View File

@ -10,18 +10,20 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto.inverter;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.fronius.internal.api.dto.ValueUnit;
import com.google.gson.annotations.SerializedName;
/**
* The {@link InverterRealtimeBodyData} is responsible for storing
* the "data" node of the JSON response
* the "Data" node of the {@link InverterRealtimeBody}.
*
* @author Thomas Rokohl - Initial contribution
*/
public class InverterRealtimeBodyData {
@SerializedName("DAY_ENERGY")
private ValueUnit dayEnergy;
@SerializedName("FAC")
@ -49,75 +51,40 @@ public class InverterRealtimeBodyData {
@SerializedName("YEAR_ENERGY")
private ValueUnit yearEnergy;
@SerializedName("DeviceStatus")
private DeviceStatus deviceStatus;
private InverterDeviceStatus deviceStatus;
public ValueUnit getDayEnergy() {
return dayEnergy;
}
public void setDayEnergy(ValueUnit dayEnergy) {
this.dayEnergy = dayEnergy;
}
public ValueUnit getPac() {
return pac;
}
public void setPac(ValueUnit pac) {
this.pac = pac;
}
public ValueUnit getTotalEnergy() {
return totalEnergy;
}
public void setTotalEnergy(ValueUnit totalEnergy) {
this.totalEnergy = totalEnergy;
}
public ValueUnit getYearEnergy() {
return yearEnergy;
}
public void setYearEnergy(ValueUnit yearEnergy) {
this.yearEnergy = yearEnergy;
}
public DeviceStatus getDeviceStatus() {
if (deviceStatus == null) {
deviceStatus = new DeviceStatus();
}
public @Nullable InverterDeviceStatus getDeviceStatus() {
return deviceStatus;
}
public void setDeviceStatus(DeviceStatus deviceStatus) {
this.deviceStatus = deviceStatus;
}
public ValueUnit getFac() {
return fac;
}
public void setFac(ValueUnit fac) {
this.fac = fac;
}
public ValueUnit getIac() {
return iac;
}
public void setIac(ValueUnit iac) {
this.iac = iac;
}
public ValueUnit getIdc() {
return idc;
}
public void setIdc(ValueUnit idc) {
this.idc = idc;
}
public ValueUnit getIdc2() {
return idc2;
}
@ -130,18 +97,10 @@ public class InverterRealtimeBodyData {
return uac;
}
public void setUac(ValueUnit uac) {
this.uac = uac;
}
public ValueUnit getUdc() {
return udc;
}
public void setUdc(ValueUnit udc) {
this.udc = udc;
}
public ValueUnit getUdc2() {
return udc2;
}

View File

@ -10,29 +10,26 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto.inverter;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.fronius.internal.api.dto.BaseFroniusResponse;
import com.google.gson.annotations.SerializedName;
/**
* The {@link InverterRealtimeResponse} is responsible for storing
* the response from the realtime api
* the response from the GetInverterRealtimeData response.
*
* @author Thomas Rokohl - Initial contribution
*/
@NonNullByDefault
public class InverterRealtimeResponse extends BaseFroniusResponse {
@SerializedName("Body")
private InverterRealtimeBody body;
private @Nullable InverterRealtimeBody body;
public InverterRealtimeBody getBody() {
if (body == null) {
body = new InverterRealtimeBody();
}
public @Nullable InverterRealtimeBody getBody() {
return body;
}
public void setBody(InverterRealtimeBody body) {
this.body = body;
}
}

View File

@ -10,28 +10,25 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto.meter;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import com.google.gson.annotations.SerializedName;
/**
* The {@link MeterRealtimeBodyDTO} is responsible for storing
* the "body" node of the JSON response
* The {@link MeterRealtimeBody} is responsible for storing
* the "Body" node of the {@link MeterRealtimeResponse}.
*
* @author Jimmy Tanagra - Initial contribution
*/
public class MeterRealtimeBodyDTO {
@NonNullByDefault
public class MeterRealtimeBody {
@SerializedName("Data")
private MeterRealtimeBodyDataDTO data;
private @Nullable MeterRealtimeBodyData data;
public MeterRealtimeBodyDataDTO getData() {
if (data == null) {
data = new MeterRealtimeBodyDataDTO();
}
public @Nullable MeterRealtimeBodyData getData() {
return data;
}
public void setData(MeterRealtimeBodyDataDTO data) {
this.data = data;
}
}

View File

@ -10,20 +10,20 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto.meter;
import com.google.gson.annotations.SerializedName;
/**
* The {@link MeterRealtimeBodyDataDTO} is responsible for storing
* the "data" node of the JSON response
* The {@link MeterRealtimeBodyData} is responsible for storing
* the "Data" node of the {@link MeterRealtimeBody}.
*
* The main SerializedName values use Smart Meter 63A names
* The first SerializedName alternate names use Smart Meter 65A names
*
* @author Jimmy Tanagra - Initial contribution
*/
public class MeterRealtimeBodyDataDTO {
public class MeterRealtimeBodyData {
@SerializedName(value = "Current_AC_Phase_1", alternate = { "ACBRIDGE_CURRENT_ACTIVE_MEAN_01_F32" })
private double currentACPhase1;
@SerializedName(value = "Current_AC_Phase_2", alternate = { "ACBRIDGE_CURRENT_ACTIVE_MEAN_02_F32" })
@ -31,7 +31,7 @@ public class MeterRealtimeBodyDataDTO {
@SerializedName(value = "Current_AC_Phase_3", alternate = { "ACBRIDGE_CURRENT_ACTIVE_MEAN_03_F32" })
private double currentACPhase3;
@SerializedName("Details")
private MeterRealtimeDetailsDTO details;
private MeterRealtimeDetails details;
@SerializedName(value = "Enable", alternate = { "COMPONENTS_MODE_ENABLE_U16" })
private int enable;
@SerializedName(value = "EnergyReactive_VArAC_Sum_Consumed", alternate = {
@ -106,298 +106,150 @@ public class MeterRealtimeBodyDataDTO {
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() {
public MeterRealtimeDetails getDetails() {
if (details == null) {
details = new MeterRealtimeDetailsDTO();
details = new MeterRealtimeDetails();
}
return details;
}
public void setDetails(MeterRealtimeDetailsDTO details) {
this.details = details;
}
public int getEnable() {
return enable;
}
public void setEnable(int enable) {
this.enable = enable;
}
public double getEnergyReactiveVArACSumConsumed() {
return energyReactiveVArACSumConsumed;
}
public void setEnergyReactiveVArACSumConsumed(double energyReactiveVArACSumConsumed) {
this.energyReactiveVArACSumConsumed = energyReactiveVArACSumConsumed;
}
public double getEnergyReactiveVArACSumProduced() {
return energyReactiveVArACSumProduced;
}
public void setEnergyReactiveVArACSumProduced(double energyReactiveVArACSumProduced) {
this.energyReactiveVArACSumProduced = energyReactiveVArACSumProduced;
}
public double getEnergyRealWACMinusAbsolute() {
return energyRealWACMinusAbsolute;
}
public void setEnergyRealWACMinusAbsolute(double energyRealWACMinusAbsolute) {
this.energyRealWACMinusAbsolute = energyRealWACMinusAbsolute;
}
public double getEnergyRealWACPlusAbsolute() {
return energyRealWACPlusAbsolute;
}
public void setEnergyRealWACPlusAbsolute(double energyRealWACPlusAbsolute) {
this.energyRealWACPlusAbsolute = energyRealWACPlusAbsolute;
}
public double getEnergyRealWACSumConsumed() {
return energyRealWACSumConsumed;
}
public void setEnergyRealWACSumConsumed(double energyRealWACSumConsumed) {
this.energyRealWACSumConsumed = energyRealWACSumConsumed;
}
public double getEnergyRealWACSumProduced() {
return energyRealWACSumProduced;
}
public void setEnergyRealWACSumProduced(double 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 double getPowerApparentSSum() {
return powerApparentSSum;
}
public void setPowerApparentSSum(double 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;
}
}

View File

@ -10,17 +10,17 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto.meter;
import com.google.gson.annotations.SerializedName;
/**
* The {@link MeterRealtimeDetailsDTO} is responsible for storing
* the "body" node of the JSON response
* The {@link MeterRealtimeDetails} is responsible for storing
* the "Details" node of the {@link MeterRealtimeBodyData}.
*
* @author Jimmy Tanagra - Initial contribution
*/
public class MeterRealtimeDetailsDTO {
public class MeterRealtimeDetails {
@SerializedName("Manufacturer")
private String manufacturer;
@SerializedName("Model")
@ -32,23 +32,11 @@ public class MeterRealtimeDetailsDTO {
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;
}
}

View File

@ -10,28 +10,26 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto.meter;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.fronius.internal.api.dto.BaseFroniusResponse;
import com.google.gson.annotations.SerializedName;
/**
* The {@link MeterRealtimeResponseDTO} is responsible for storing
* the response from the powerflowrealtime api
* The {@link MeterRealtimeResponse} is responsible for storing
* the response from the GetMeterRealtimeData response.
*
* @author Jimmy Tanagra - Initial contribution
*/
public class MeterRealtimeResponseDTO extends BaseFroniusResponse {
@NonNullByDefault
public class MeterRealtimeResponse extends BaseFroniusResponse {
@SerializedName("Body")
private MeterRealtimeBodyDTO body;
private @Nullable MeterRealtimeBody body;
public MeterRealtimeBodyDTO getBody() {
if (body == null) {
body = new MeterRealtimeBodyDTO();
}
public @Nullable MeterRealtimeBody getBody() {
return body;
}
public void setBody(MeterRealtimeBodyDTO body) {
this.body = body;
}
}

View File

@ -10,28 +10,25 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto.ohmpilot;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import com.google.gson.annotations.SerializedName;
/**
* The {@link OhmpilotRealtimeBodyDTO} is responsible for storing
* the "body" node of the JSON response
* The {@link OhmpilotRealtimeBody} is responsible for storing
* the "Body" node of the {@link OhmpilotRealtimeResponse}.
*
* @author Hannes Spenger - Initial contribution
*/
public class OhmpilotRealtimeBodyDTO {
@NonNullByDefault
public class OhmpilotRealtimeBody {
@SerializedName("Data")
private OhmpilotRealtimeBodyDataDTO data;
private @Nullable OhmpilotRealtimeBodyData data;
public OhmpilotRealtimeBodyDataDTO getData() {
if (data == null) {
data = new OhmpilotRealtimeBodyDataDTO();
}
public @Nullable OhmpilotRealtimeBodyData getData() {
return data;
}
public void setData(OhmpilotRealtimeBodyDataDTO data) {
this.data = data;
}
}

View File

@ -10,19 +10,19 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto.ohmpilot;
import com.google.gson.annotations.SerializedName;
/**
* The {@link OhmpilotRealtimeBodyDataDTO} is responsible for storing
* the "data" node of the JSON response
* The {@link OhmpilotRealtimeBodyData} is responsible for storing
* the "Data" node of the {@link OhmpilotRealtimeBody}.
*
* @author Hannes Spenger - Initial contribution
*/
public class OhmpilotRealtimeBodyDataDTO {
public class OhmpilotRealtimeBodyData {
@SerializedName("Details")
private OhmpilotRealtimeDetailsDTO details;
private OhmpilotRealtimeDetails details;
@SerializedName("EnergyReal_WAC_Sum_Consumed")
private double energyRealWACSumConsumed;
@SerializedName("PowerReal_PAC_Sum")
@ -34,54 +34,30 @@ public class OhmpilotRealtimeBodyDataDTO {
@SerializedName("CodeOfState")
private int stateCode;
public OhmpilotRealtimeDetailsDTO getDetails() {
public OhmpilotRealtimeDetails getDetails() {
if (details == null) {
details = new OhmpilotRealtimeDetailsDTO();
details = new OhmpilotRealtimeDetails();
}
return details;
}
public void setDetails(OhmpilotRealtimeDetailsDTO details) {
this.details = details;
}
public double getEnergyRealWACSumConsumed() {
return energyRealWACSumConsumed;
}
public void setEnergyRealWACSumConsumed(double energyRealWACSumConsumed) {
this.energyRealWACSumConsumed = energyRealWACSumConsumed;
}
public double getPowerPACSum() {
return powerPACSum;
}
public void setPowerPACSum(double powerPACSum) {
this.powerPACSum = powerPACSum;
}
public double getTemperatureChannel1() {
return temperatureChannel1;
}
public void setTemperatureChannel1(double temperatureChannel1) {
this.temperatureChannel1 = temperatureChannel1;
}
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public int getStateCode() {
return stateCode;
}
public void setStateCode(int stateCode) {
this.stateCode = stateCode;
}
}

View File

@ -10,17 +10,17 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto.ohmpilot;
import com.google.gson.annotations.SerializedName;
/**
* The {@link OhmpilotRealtimeDetailsDTO} is responsible for storing
* the "body" node of the JSON response
* The {@link OhmpilotRealtimeDetails} is responsible for storing
* the "Details" node of the {@link OhmpilotRealtimeBodyData}.
*
* @author Hannes Spenger - Initial contribution
*/
public class OhmpilotRealtimeDetailsDTO {
public class OhmpilotRealtimeDetails {
@SerializedName("Hardware")
private String hardware;
@SerializedName("Manufacturer")

View File

@ -10,28 +10,26 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto.ohmpilot;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.fronius.internal.api.dto.BaseFroniusResponse;
import com.google.gson.annotations.SerializedName;
/**
* The {@link OhmpilotRealtimeResponseDTO} is responsible for storing
* the response from the GetOhmPilotRealtimeData api
* The {@link OhmpilotRealtimeResponse} is responsible for storing
* the response from the GetOhmPilotRealtimeData response.
*
* @author Hannes Spenger - Initial contribution
*/
public class OhmpilotRealtimeResponseDTO extends BaseFroniusResponse {
@NonNullByDefault
public class OhmpilotRealtimeResponse extends BaseFroniusResponse {
@SerializedName("Body")
private OhmpilotRealtimeBodyDTO body;
private @Nullable OhmpilotRealtimeBody body;
public OhmpilotRealtimeBodyDTO getBody() {
if (body == null) {
body = new OhmpilotRealtimeBodyDTO();
}
public @Nullable OhmpilotRealtimeBody getBody() {
return body;
}
public void setBody(OhmpilotRealtimeBodyDTO body) {
this.body = body;
}
}

View File

@ -10,28 +10,25 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto.powerflow;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import com.google.gson.annotations.SerializedName;
/**
* The {@link PowerFlowRealtimeBody} is responsible for storing
* the "body" node of the JSON response
* the "Body" node of the {@link PowerFlowRealtimeResponse}.
*
* @author Thomas Rokohl - Initial contribution
*/
@NonNullByDefault
public class PowerFlowRealtimeBody {
@SerializedName("Data")
private PowerFlowRealtimeBodyData data;
private @Nullable PowerFlowRealtimeBodyData data;
public PowerFlowRealtimeBodyData getData() {
if (data == null) {
data = new PowerFlowRealtimeBodyData();
}
public @Nullable PowerFlowRealtimeBodyData getData() {
return data;
}
public void setData(PowerFlowRealtimeBodyData data) {
this.data = data;
}
}

View File

@ -10,46 +10,39 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto.powerflow;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import com.google.gson.annotations.SerializedName;
/**
* The {@link PowerFlowRealtimeBodyData} is responsible for storing
* the "data" node of the JSON response
* the "Data" node of the {@link PowerFlowRealtimeBody}.
*
* @author Thomas Rokohl - Initial contribution
*/
@NonNullByDefault
public class PowerFlowRealtimeBodyData {
@SerializedName("Site")
private PowerFlowRealtimeSite site;
private @Nullable PowerFlowRealtimeSite site;
@SerializedName("Inverters")
private Map<String, PowerFlowRealtimeInverter> inverters;
private @Nullable Map<String, PowerFlowRealtimeInverter> inverters;
public Map<String, PowerFlowRealtimeInverter> getInverters() {
if (inverters == null) {
inverters = new HashMap<>();
Map<String, PowerFlowRealtimeInverter> localInverters = inverters;
if (localInverters == null) {
inverters = localInverters = new HashMap<>();
}
return inverters;
return localInverters;
}
public void setInverters(Map<String, PowerFlowRealtimeInverter> inverters) {
this.inverters = inverters;
}
public PowerFlowRealtimeSite getSite() {
if (site == null) {
site = new PowerFlowRealtimeSite();
}
public @Nullable PowerFlowRealtimeSite getSite() {
return site;
}
public void setSite(PowerFlowRealtimeSite site) {
this.site = site;
}
}

View File

@ -10,19 +10,18 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto.powerflow;
import com.google.gson.annotations.SerializedName;
/**
* The {@link PowerFlowRealtimeInverter} is responsible for storing
* the "inverter" node of the JSON response
* the "Inverter" node of the {@link PowerFlowRealtimeBodyData}.
*
* @author Thomas Rokohl - Initial contribution
* @author Thomas Kordelle - Added inverter power, battery state of charge and PV solar yield
*/
public class PowerFlowRealtimeInverter {
@SerializedName("DT")
private double dt;
@SerializedName("P")
@ -42,55 +41,27 @@ public class PowerFlowRealtimeInverter {
return dt;
}
public void setDt(double dt) {
this.dt = dt;
}
public double getP() {
return p;
}
public void setP(double p) {
this.p = p;
}
public double geteDay() {
return eDay;
}
public void seteDay(double eDay) {
this.eDay = eDay;
}
public double geteYear() {
return eYear;
}
public void seteYear(double eYear) {
this.eYear = eYear;
}
public double geteTotal() {
return eTotal;
}
public void seteTotal(double eTotal) {
this.eTotal = eTotal;
}
public String getBatteryMode() {
return batteryMode;
}
public void setBatteryMode(final String batteryMode) {
this.batteryMode = batteryMode;
}
public double getSoc() {
return soc;
}
public void setSoc(double soc) {
this.soc = soc;
}
}

View File

@ -10,28 +10,26 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto.powerflow;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.fronius.internal.api.dto.BaseFroniusResponse;
import com.google.gson.annotations.SerializedName;
/**
* The {@link PowerFlowRealtimeResponse} is responsible for storing
* the response from the powerflowrealtime api
* the response from the GetPowerFlowRealtimeData response.
*
* @author Thomas Rokohl - Initial contribution
*/
@NonNullByDefault
public class PowerFlowRealtimeResponse extends BaseFroniusResponse {
@SerializedName("Body")
private PowerFlowRealtimeBody body;
private @Nullable PowerFlowRealtimeBody body;
public PowerFlowRealtimeBody getBody() {
if (body == null) {
body = new PowerFlowRealtimeBody();
}
public @Nullable PowerFlowRealtimeBody getBody() {
return body;
}
public void setBody(PowerFlowRealtimeBody body) {
this.body = body;
}
}

View File

@ -10,18 +10,17 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.fronius.internal.api;
package org.openhab.binding.fronius.internal.api.dto.powerflow;
import com.google.gson.annotations.SerializedName;
/**
* The {@link PowerFlowRealtimeSite} is responsible for storing
* the "site" node
* the "Site" node of the {@link PowerFlowRealtimeBodyData}.
*
* @author Thomas Rokohl - Initial contribution
*/
public class PowerFlowRealtimeSite {
@SerializedName("Mode")
private String mode;
@SerializedName("P_Grid")
@ -52,87 +51,43 @@ public class PowerFlowRealtimeSite {
return mode;
}
public void setMode(String mode) {
this.mode = mode;
}
public double getPgrid() {
return pgrid;
}
public void setPgrid(double pgrid) {
this.pgrid = pgrid;
}
public double getPload() {
return pload;
}
public void setPload(double pload) {
this.pload = pload;
}
public double getPakku() {
return pakku;
}
public void setPakku(double pakku) {
this.pakku = pakku;
}
public double getPpv() {
return ppv;
}
public void setPpv(double ppv) {
this.ppv = ppv;
}
public double getRelSelfConsumption() {
return relSelfConsumption;
}
public void setRelSelfConsumption(double relSelfConsumption) {
this.relSelfConsumption = relSelfConsumption;
}
public double getRelAutonomy() {
return relAutonomy;
}
public void setRelAutonomy(double relAutonomy) {
this.relAutonomy = relAutonomy;
}
public double geteDay() {
return eDay;
}
public void seteDay(double eDay) {
this.eDay = eDay;
}
public double geteYear() {
return eYear;
}
public void seteYear(double eYear) {
this.eYear = eYear;
}
public double geteTotal() {
return eTotal;
}
public void seteTotal(double eTotal) {
this.eTotal = eTotal;
}
public String getMeterLocation() {
return meterLocation;
}
public void setMeterLocation(String meterLocation) {
this.meterLocation = meterLocation;
}
}

View File

@ -12,12 +12,17 @@
*/
package org.openhab.binding.fronius.internal.handler;
import org.eclipse.jdt.annotation.NonNull;
import static org.openhab.binding.fronius.internal.FroniusBindingConstants.API_TIMEOUT;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.http.HttpMethod;
import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration;
import org.openhab.binding.fronius.internal.FroniusCommunicationException;
import org.openhab.binding.fronius.internal.FroniusHttpUtil;
import org.openhab.binding.fronius.internal.api.BaseFroniusResponse;
import org.openhab.binding.fronius.internal.api.HeadStatus;
import org.openhab.binding.fronius.internal.api.FroniusCommunicationException;
import org.openhab.binding.fronius.internal.api.FroniusHttpUtil;
import org.openhab.binding.fronius.internal.api.dto.BaseFroniusResponse;
import org.openhab.binding.fronius.internal.api.dto.Head;
import org.openhab.binding.fronius.internal.api.dto.HeadStatus;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
@ -45,18 +50,17 @@ import com.google.gson.JsonSyntaxException;
* Convert ValueUnit to QuantityType
* Support NULL value
*/
@NonNullByDefault
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();
gson = new Gson();
}
@Override
@ -124,7 +128,7 @@ public abstract class FroniusBaseThingHandler extends BaseThingHandler {
* @param channelId the id identifying the channel
* @return the "new" associated value
*/
protected abstract State getValue(String channelId);
protected abstract @Nullable State getValue(String channelId);
/**
* Called by the bridge to fetch data and update channels
@ -158,22 +162,27 @@ public abstract class FroniusBaseThingHandler extends BaseThingHandler {
* @param url to request
* @return the object representation of the json response
*/
protected @NonNull <T extends BaseFroniusResponse> T collectDataFromUrl(Class<T> type, String url)
protected <T extends BaseFroniusResponse> T collectDataFromUrl(Class<T> type, String url)
throws FroniusCommunicationException {
try {
int attempts = 1;
while (true) {
logger.trace("Fetching URL = {}", url);
String response = FroniusHttpUtil.executeUrl(url, API_TIMEOUT);
String response = FroniusHttpUtil.executeUrl(HttpMethod.GET, url, API_TIMEOUT);
logger.trace("aqiResponse = {}", response);
@Nullable
T result = gson.fromJson(response, type);
if (result == null) {
throw new FroniusCommunicationException("Empty json result");
}
HeadStatus status = result.getHead().getStatus();
if (status.getCode() == 0) {
Head head = result.getHead();
if (head == null) {
throw new FroniusCommunicationException("Empty head in json result");
}
HeadStatus status = head.getStatus();
if (status != null && status.getCode() == 0) {
return result;
}
@ -185,9 +194,11 @@ public abstract class FroniusBaseThingHandler extends BaseThingHandler {
// "Reason" : "Transfer timeout.",
// "UserMessage" : ""
// },
logger.debug("Error from Fronius attempt #{}: {} - {}", attempts, status.getCode(), status.getReason());
int code = status != null ? status.getCode() : 255;
String reason = status != null ? status.getReason() : "undefined runtime error";
logger.debug("Error from Fronius attempt #{}: {} - {}", attempts, code, reason);
if (attempts >= 3) {
throw new FroniusCommunicationException(status.getReason());
throw new FroniusCommunicationException(reason);
}
Thread.sleep(500 * attempts);
attempts++;

View File

@ -12,6 +12,8 @@
*/
package org.openhab.binding.fronius.internal.handler;
import static org.openhab.binding.fronius.internal.FroniusBindingConstants.API_TIMEOUT;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ScheduledFuture;
@ -19,9 +21,10 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.http.HttpMethod;
import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration;
import org.openhab.binding.fronius.internal.FroniusCommunicationException;
import org.openhab.binding.fronius.internal.FroniusHttpUtil;
import org.openhab.binding.fronius.internal.api.FroniusCommunicationException;
import org.openhab.binding.fronius.internal.api.FroniusHttpUtil;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
@ -85,8 +88,9 @@ public class FroniusBridgeHandler extends BaseBridgeHandler {
@Override
public void dispose() {
if (refreshJob != null) {
refreshJob.cancel(true);
ScheduledFuture<?> localRefreshJob = refreshJob;
if (localRefreshJob != null) {
localRefreshJob.cancel(true);
refreshJob = null;
}
}
@ -108,8 +112,9 @@ public class FroniusBridgeHandler extends BaseBridgeHandler {
}
private void restartAutomaticRefresh() {
if (refreshJob != null) { // refreshJob should be null if the config isn't valid
refreshJob.cancel(false);
ScheduledFuture<?> localRefreshJob = refreshJob;
if (localRefreshJob != null) { // refreshJob should be null if the config isn't valid
localRefreshJob.cancel(false);
startAutomaticRefresh();
}
}
@ -118,7 +123,8 @@ public class FroniusBridgeHandler extends BaseBridgeHandler {
* Start the job refreshing the data
*/
private void startAutomaticRefresh() {
if (refreshJob == null || refreshJob.isCancelled()) {
ScheduledFuture<?> localRefreshJob = refreshJob;
if (localRefreshJob == null || localRefreshJob.isCancelled()) {
final FroniusBridgeConfiguration config = getConfigAs(FroniusBridgeConfiguration.class);
Runnable runnable = () -> {
try {
@ -140,6 +146,6 @@ public class FroniusBridgeHandler extends BaseBridgeHandler {
}
private void checkBridgeOnline(FroniusBridgeConfiguration config) throws FroniusCommunicationException {
FroniusHttpUtil.executeUrl("http://" + config.hostname, 5000);
FroniusHttpUtil.executeUrl(HttpMethod.GET, "http://" + config.hostname, API_TIMEOUT);
}
}

View File

@ -14,12 +14,15 @@ package org.openhab.binding.fronius.internal.handler;
import java.util.Map;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.fronius.internal.FroniusBaseDeviceConfiguration;
import org.openhab.binding.fronius.internal.FroniusBindingConstants;
import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration;
import org.openhab.binding.fronius.internal.FroniusCommunicationException;
import org.openhab.binding.fronius.internal.api.MeterRealtimeBodyDataDTO;
import org.openhab.binding.fronius.internal.api.MeterRealtimeResponseDTO;
import org.openhab.binding.fronius.internal.api.FroniusCommunicationException;
import org.openhab.binding.fronius.internal.api.dto.meter.MeterRealtimeBody;
import org.openhab.binding.fronius.internal.api.dto.meter.MeterRealtimeBodyData;
import org.openhab.binding.fronius.internal.api.dto.meter.MeterRealtimeDetails;
import org.openhab.binding.fronius.internal.api.dto.meter.MeterRealtimeResponse;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.Units;
@ -36,7 +39,7 @@ import org.openhab.core.types.State;
*/
public class FroniusMeterHandler extends FroniusBaseThingHandler {
private MeterRealtimeBodyDataDTO meterRealtimeBodyData;
private @Nullable MeterRealtimeBodyData meterRealtimeBodyData;
private FroniusBaseDeviceConfiguration config;
public FroniusMeterHandler(Thing thing) {
@ -69,7 +72,8 @@ public class FroniusMeterHandler extends FroniusBaseThingHandler {
*/
@Override
protected State getValue(String channelId) {
if (meterRealtimeBodyData == null) {
MeterRealtimeBodyData localMeterRealtimeBodyData = meterRealtimeBodyData;
if (localMeterRealtimeBodyData == null) {
return null;
}
@ -81,39 +85,39 @@ public class FroniusMeterHandler extends FroniusBaseThingHandler {
switch (fieldName) {
case FroniusBindingConstants.METER_ENABLE:
return new DecimalType(meterRealtimeBodyData.getEnable());
return new DecimalType(localMeterRealtimeBodyData.getEnable());
case FroniusBindingConstants.METER_LOCATION:
return new DecimalType(meterRealtimeBodyData.getMeterLocationCurrent());
return new DecimalType(localMeterRealtimeBodyData.getMeterLocationCurrent());
case FroniusBindingConstants.METER_CURRENT_AC_PHASE_1:
return new QuantityType<>(meterRealtimeBodyData.getCurrentACPhase1(), Units.AMPERE);
return new QuantityType<>(localMeterRealtimeBodyData.getCurrentACPhase1(), Units.AMPERE);
case FroniusBindingConstants.METER_CURRENT_AC_PHASE_2:
return new QuantityType<>(meterRealtimeBodyData.getCurrentACPhase2(), Units.AMPERE);
return new QuantityType<>(localMeterRealtimeBodyData.getCurrentACPhase2(), Units.AMPERE);
case FroniusBindingConstants.METER_CURRENT_AC_PHASE_3:
return new QuantityType<>(meterRealtimeBodyData.getCurrentACPhase3(), Units.AMPERE);
return new QuantityType<>(localMeterRealtimeBodyData.getCurrentACPhase3(), Units.AMPERE);
case FroniusBindingConstants.METER_VOLTAGE_AC_PHASE_1:
return new QuantityType<>(meterRealtimeBodyData.getVoltageACPhase1(), Units.VOLT);
return new QuantityType<>(localMeterRealtimeBodyData.getVoltageACPhase1(), Units.VOLT);
case FroniusBindingConstants.METER_VOLTAGE_AC_PHASE_2:
return new QuantityType<>(meterRealtimeBodyData.getVoltageACPhase2(), Units.VOLT);
return new QuantityType<>(localMeterRealtimeBodyData.getVoltageACPhase2(), Units.VOLT);
case FroniusBindingConstants.METER_VOLTAGE_AC_PHASE_3:
return new QuantityType<>(meterRealtimeBodyData.getVoltageACPhase3(), Units.VOLT);
return new QuantityType<>(localMeterRealtimeBodyData.getVoltageACPhase3(), Units.VOLT);
case FroniusBindingConstants.METER_POWER_PHASE_1:
return new QuantityType<>(meterRealtimeBodyData.getPowerRealPPhase1(), Units.WATT);
return new QuantityType<>(localMeterRealtimeBodyData.getPowerRealPPhase1(), Units.WATT);
case FroniusBindingConstants.METER_POWER_PHASE_2:
return new QuantityType<>(meterRealtimeBodyData.getPowerRealPPhase2(), Units.WATT);
return new QuantityType<>(localMeterRealtimeBodyData.getPowerRealPPhase2(), Units.WATT);
case FroniusBindingConstants.METER_POWER_PHASE_3:
return new QuantityType<>(meterRealtimeBodyData.getPowerRealPPhase3(), Units.WATT);
return new QuantityType<>(localMeterRealtimeBodyData.getPowerRealPPhase3(), Units.WATT);
case FroniusBindingConstants.METER_POWER_SUM:
return new QuantityType<>(meterRealtimeBodyData.getPowerRealPSum(), Units.WATT);
return new QuantityType<>(localMeterRealtimeBodyData.getPowerRealPSum(), Units.WATT);
case FroniusBindingConstants.METER_POWER_FACTOR_PHASE_1:
return new DecimalType(meterRealtimeBodyData.getPowerFactorPhase1());
return new DecimalType(localMeterRealtimeBodyData.getPowerFactorPhase1());
case FroniusBindingConstants.METER_POWER_FACTOR_PHASE_2:
return new DecimalType(meterRealtimeBodyData.getPowerFactorPhase2());
return new DecimalType(localMeterRealtimeBodyData.getPowerFactorPhase2());
case FroniusBindingConstants.METER_POWER_FACTOR_PHASE_3:
return new DecimalType(meterRealtimeBodyData.getPowerFactorPhase3());
return new DecimalType(localMeterRealtimeBodyData.getPowerFactorPhase3());
case FroniusBindingConstants.METER_ENERGY_REAL_SUM_CONSUMED:
return new QuantityType<>(meterRealtimeBodyData.getEnergyRealWACSumConsumed(), Units.WATT_HOUR);
return new QuantityType<>(localMeterRealtimeBodyData.getEnergyRealWACSumConsumed(), Units.WATT_HOUR);
case FroniusBindingConstants.METER_ENERGY_REAL_SUM_PRODUCED:
return new QuantityType<>(meterRealtimeBodyData.getEnergyRealWACSumProduced(), Units.WATT_HOUR);
return new QuantityType<>(localMeterRealtimeBodyData.getEnergyRealWACSumProduced(), Units.WATT_HOUR);
default:
break;
}
@ -122,14 +126,19 @@ public class FroniusMeterHandler extends FroniusBaseThingHandler {
}
private void updateProperties() {
if (meterRealtimeBodyData == null) {
MeterRealtimeBodyData localMeterRealtimeBodyData = meterRealtimeBodyData;
if (localMeterRealtimeBodyData == null) {
return;
}
MeterRealtimeDetails details = localMeterRealtimeBodyData.getDetails();
if (details == null) {
return;
}
Map<String, String> properties = editProperties();
properties.put(Thing.PROPERTY_MODEL_ID, meterRealtimeBodyData.getDetails().getModel());
properties.put(Thing.PROPERTY_SERIAL_NUMBER, meterRealtimeBodyData.getDetails().getSerial());
properties.put(Thing.PROPERTY_MODEL_ID, details.getModel());
properties.put(Thing.PROPERTY_SERIAL_NUMBER, details.getSerial());
updateProperties(properties);
}
@ -139,9 +148,14 @@ public class FroniusMeterHandler extends FroniusBaseThingHandler {
*/
private void updateData(FroniusBridgeConfiguration bridgeConfiguration, FroniusBaseDeviceConfiguration config)
throws FroniusCommunicationException {
MeterRealtimeResponseDTO meterRealtimeResponse = getMeterRealtimeData(bridgeConfiguration.hostname,
MeterRealtimeResponse meterRealtimeResponse = getMeterRealtimeData(bridgeConfiguration.hostname,
config.deviceId);
meterRealtimeBodyData = meterRealtimeResponse.getBody().getData();
MeterRealtimeBody meterRealtimeBody = meterRealtimeResponse.getBody();
if (meterRealtimeBody == null) {
meterRealtimeBodyData = null;
return;
}
meterRealtimeBodyData = meterRealtimeBody.getData();
}
/**
@ -151,9 +165,8 @@ public class FroniusMeterHandler extends FroniusBaseThingHandler {
* @param deviceId of the device
* @return {MeterRealtimeResponse} the object representation of the json response
*/
private MeterRealtimeResponseDTO getMeterRealtimeData(String ip, int deviceId)
throws FroniusCommunicationException {
private MeterRealtimeResponse getMeterRealtimeData(String ip, int deviceId) throws FroniusCommunicationException {
String location = FroniusBindingConstants.getMeterDataUrl(ip, deviceId);
return collectDataFromUrl(MeterRealtimeResponseDTO.class, location);
return collectDataFromUrl(MeterRealtimeResponse.class, location);
}
}

View File

@ -14,12 +14,15 @@ package org.openhab.binding.fronius.internal.handler;
import java.util.Map;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.fronius.internal.FroniusBaseDeviceConfiguration;
import org.openhab.binding.fronius.internal.FroniusBindingConstants;
import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration;
import org.openhab.binding.fronius.internal.FroniusCommunicationException;
import org.openhab.binding.fronius.internal.api.OhmpilotRealtimeBodyDataDTO;
import org.openhab.binding.fronius.internal.api.OhmpilotRealtimeResponseDTO;
import org.openhab.binding.fronius.internal.api.FroniusCommunicationException;
import org.openhab.binding.fronius.internal.api.dto.ohmpilot.OhmpilotRealtimeBody;
import org.openhab.binding.fronius.internal.api.dto.ohmpilot.OhmpilotRealtimeBodyData;
import org.openhab.binding.fronius.internal.api.dto.ohmpilot.OhmpilotRealtimeDetails;
import org.openhab.binding.fronius.internal.api.dto.ohmpilot.OhmpilotRealtimeResponse;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.Units;
@ -35,7 +38,7 @@ import org.openhab.core.types.State;
*/
public class FroniusOhmpilotHandler extends FroniusBaseThingHandler {
private OhmpilotRealtimeBodyDataDTO ohmpilotRealtimeBodyData;
private @Nullable OhmpilotRealtimeBodyData ohmpilotRealtimeBodyData;
private FroniusBaseDeviceConfiguration config;
public FroniusOhmpilotHandler(Thing thing) {
@ -68,7 +71,8 @@ public class FroniusOhmpilotHandler extends FroniusBaseThingHandler {
*/
@Override
protected State getValue(String channelId) {
if (ohmpilotRealtimeBodyData == null) {
OhmpilotRealtimeBodyData localOhmpilotRealtimeBodyData = ohmpilotRealtimeBodyData;
if (localOhmpilotRealtimeBodyData == null) {
return null;
}
@ -80,15 +84,15 @@ public class FroniusOhmpilotHandler extends FroniusBaseThingHandler {
switch (fieldName) {
case FroniusBindingConstants.OHMPILOT_POWER_REAL_SUM:
return new QuantityType<>(ohmpilotRealtimeBodyData.getPowerPACSum(), Units.WATT);
return new QuantityType<>(localOhmpilotRealtimeBodyData.getPowerPACSum(), Units.WATT);
case FroniusBindingConstants.OHMPILOT_ENERGY_REAL_SUM_CONSUMED:
return new QuantityType<>(ohmpilotRealtimeBodyData.getEnergyRealWACSumConsumed(), Units.WATT_HOUR);
return new QuantityType<>(localOhmpilotRealtimeBodyData.getEnergyRealWACSumConsumed(), Units.WATT_HOUR);
case FroniusBindingConstants.OHMPILOT_ENERGY_SENSOR_TEMPERATURE_CHANNEL_1:
return new QuantityType<>(ohmpilotRealtimeBodyData.getTemperatureChannel1(), Units.KELVIN);
return new QuantityType<>(localOhmpilotRealtimeBodyData.getTemperatureChannel1(), Units.KELVIN);
case FroniusBindingConstants.OHMPILOT_STATE_CODE:
return new DecimalType(ohmpilotRealtimeBodyData.getStateCode());
return new DecimalType(localOhmpilotRealtimeBodyData.getStateCode());
case FroniusBindingConstants.OHMPILOT_ERROR_CODE:
return new DecimalType(ohmpilotRealtimeBodyData.getErrorCode());
return new DecimalType(localOhmpilotRealtimeBodyData.getErrorCode());
default:
break;
@ -98,14 +102,19 @@ public class FroniusOhmpilotHandler extends FroniusBaseThingHandler {
}
private void updateProperties() {
if (ohmpilotRealtimeBodyData == null) {
OhmpilotRealtimeBodyData localOhmpilotRealtimeBodyData = ohmpilotRealtimeBodyData;
if (localOhmpilotRealtimeBodyData == null) {
return;
}
OhmpilotRealtimeDetails details = localOhmpilotRealtimeBodyData.getDetails();
if (details == null) {
return;
}
Map<String, String> properties = editProperties();
properties.put(Thing.PROPERTY_MODEL_ID, ohmpilotRealtimeBodyData.getDetails().getModel());
properties.put(Thing.PROPERTY_SERIAL_NUMBER, ohmpilotRealtimeBodyData.getDetails().getSerial());
properties.put(Thing.PROPERTY_MODEL_ID, details.getModel());
properties.put(Thing.PROPERTY_SERIAL_NUMBER, details.getSerial());
updateProperties(properties);
}
@ -115,9 +124,14 @@ public class FroniusOhmpilotHandler extends FroniusBaseThingHandler {
*/
private void updateData(FroniusBridgeConfiguration bridgeConfiguration, FroniusBaseDeviceConfiguration config)
throws FroniusCommunicationException {
OhmpilotRealtimeResponseDTO ohmpilotRealtimeResponse = getOhmpilotRealtimeData(bridgeConfiguration.hostname,
OhmpilotRealtimeResponse ohmpilotRealtimeResponse = getOhmpilotRealtimeData(bridgeConfiguration.hostname,
config.deviceId);
ohmpilotRealtimeBodyData = ohmpilotRealtimeResponse.getBody().getData();
OhmpilotRealtimeBody ohmpilotRealtimeBody = ohmpilotRealtimeResponse.getBody();
if (ohmpilotRealtimeBody == null) {
ohmpilotRealtimeBodyData = null;
return;
}
ohmpilotRealtimeBodyData = ohmpilotRealtimeBody.getData();
}
/**
@ -127,9 +141,9 @@ public class FroniusOhmpilotHandler extends FroniusBaseThingHandler {
* @param deviceId of the device
* @return {OhmpilotRealtimeResponse} the object representation of the json response
*/
private OhmpilotRealtimeResponseDTO getOhmpilotRealtimeData(String ip, int deviceId)
private OhmpilotRealtimeResponse getOhmpilotRealtimeData(String ip, int deviceId)
throws FroniusCommunicationException {
String location = FroniusBindingConstants.getOhmPilotDataUrl(ip, deviceId);
return collectDataFromUrl(OhmpilotRealtimeResponseDTO.class, location);
return collectDataFromUrl(OhmpilotRealtimeResponse.class, location);
}
}

View File

@ -16,23 +16,26 @@ import java.util.Optional;
import javax.measure.Unit;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.fronius.internal.FroniusBaseDeviceConfiguration;
import org.openhab.binding.fronius.internal.FroniusBindingConstants;
import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration;
import org.openhab.binding.fronius.internal.FroniusCommunicationException;
import org.openhab.binding.fronius.internal.api.InverterRealtimeBodyData;
import org.openhab.binding.fronius.internal.api.InverterRealtimeResponse;
import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeInverter;
import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeResponse;
import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeSite;
import org.openhab.binding.fronius.internal.api.ValueUnit;
import org.openhab.binding.fronius.internal.api.FroniusCommunicationException;
import org.openhab.binding.fronius.internal.api.dto.ValueUnit;
import org.openhab.binding.fronius.internal.api.dto.inverter.InverterDeviceStatus;
import org.openhab.binding.fronius.internal.api.dto.inverter.InverterRealtimeBody;
import org.openhab.binding.fronius.internal.api.dto.inverter.InverterRealtimeBodyData;
import org.openhab.binding.fronius.internal.api.dto.inverter.InverterRealtimeResponse;
import org.openhab.binding.fronius.internal.api.dto.powerflow.PowerFlowRealtimeBody;
import org.openhab.binding.fronius.internal.api.dto.powerflow.PowerFlowRealtimeBodyData;
import org.openhab.binding.fronius.internal.api.dto.powerflow.PowerFlowRealtimeInverter;
import org.openhab.binding.fronius.internal.api.dto.powerflow.PowerFlowRealtimeResponse;
import org.openhab.binding.fronius.internal.api.dto.powerflow.PowerFlowRealtimeSite;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.Units;
import org.openhab.core.thing.Thing;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link FroniusSymoInverterHandler} is responsible for updating the data, which are
@ -45,9 +48,8 @@ import org.slf4j.LoggerFactory;
*/
public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
private final Logger logger = LoggerFactory.getLogger(FroniusSymoInverterHandler.class);
private InverterRealtimeResponse inverterRealtimeResponse;
private PowerFlowRealtimeResponse powerFlowResponse;
private @Nullable InverterRealtimeResponse inverterRealtimeResponse;
private @Nullable PowerFlowRealtimeResponse powerFlowResponse;
private FroniusBaseDeviceConfiguration config;
public FroniusSymoInverterHandler(Thing thing) {
@ -85,8 +87,11 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
}
final String fieldName = fields[0];
if (inverterRealtimeResponse != null) {
InverterRealtimeBodyData inverterData = inverterRealtimeResponse.getBody().getData();
InverterRealtimeBodyData inverterData = getInverterData();
if (inverterData == null) {
return null;
}
switch (fieldName) {
case FroniusBindingConstants.INVERTER_DATA_CHANNEL_PAC:
return getQuantityOrZero(inverterData.getPac(), Units.WATT);
@ -124,46 +129,90 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
// Convert the unit to MWh for backwards compatibility with non-quantity type
return getQuantityOrZero(inverterData.getYearEnergy(), Units.MEGAWATT_HOUR).toUnit("MWh");
case FroniusBindingConstants.INVERTER_DATA_CHANNEL_DEVICE_STATUS_ERROR_CODE:
return new DecimalType(inverterData.getDeviceStatus().getErrorCode());
case FroniusBindingConstants.INVERTER_DATA_CHANNEL_DEVICE_STATUS_STATUS_CODE:
return new DecimalType(inverterData.getDeviceStatus().getStatusCode());
default:
break;
}
}
if (powerFlowResponse != null) {
PowerFlowRealtimeSite site = powerFlowResponse.getBody().getData().getSite();
switch (fieldName) {
case FroniusBindingConstants.POWER_FLOW_P_GRID:
return new QuantityType<>(site.getPgrid(), Units.WATT);
case FroniusBindingConstants.POWER_FLOW_P_LOAD:
return new QuantityType<>(site.getPload(), Units.WATT);
case FroniusBindingConstants.POWER_FLOW_P_AKKU:
return new QuantityType<>(site.getPakku(), Units.WATT);
case FroniusBindingConstants.POWER_FLOW_P_PV:
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_POWER:
return new QuantityType<>(getInverter(config.deviceId).getP(), Units.WATT);
case FroniusBindingConstants.POWER_FLOW_INVERTER_SOC:
return new QuantityType<>(getInverter(config.deviceId).getSoc(), Units.PERCENT);
// Kept for backwards compatibility
case FroniusBindingConstants.POWER_FLOW_INVERTER_1_POWER:
return new QuantityType<>(getInverter(1).getP(), Units.WATT);
case FroniusBindingConstants.POWER_FLOW_INVERTER_1_SOC:
return new QuantityType<>(getInverter(1).getSoc(), Units.PERCENT);
default:
break;
}
}
InverterDeviceStatus deviceStatus = inverterData.getDeviceStatus();
if (deviceStatus == null) {
return null;
}
return new DecimalType(deviceStatus.getErrorCode());
case FroniusBindingConstants.INVERTER_DATA_CHANNEL_DEVICE_STATUS_STATUS_CODE:
deviceStatus = inverterData.getDeviceStatus();
if (deviceStatus == null) {
return null;
}
return new DecimalType(deviceStatus.getStatusCode());
default:
break;
}
PowerFlowRealtimeBodyData powerFlowData = getPowerFlowRealtimeData();
if (powerFlowData == null) {
return null;
}
PowerFlowRealtimeSite site = powerFlowData.getSite();
if (site == null) {
return null;
}
return switch (fieldName) {
case FroniusBindingConstants.POWER_FLOW_P_GRID -> new QuantityType<>(site.getPgrid(), Units.WATT);
case FroniusBindingConstants.POWER_FLOW_P_LOAD -> new QuantityType<>(site.getPload(), Units.WATT);
case FroniusBindingConstants.POWER_FLOW_P_AKKU -> new QuantityType<>(site.getPakku(), Units.WATT);
case FroniusBindingConstants.POWER_FLOW_P_PV -> new QuantityType<>(site.getPpv(), Units.WATT);
case FroniusBindingConstants.POWER_FLOW_AUTONOMY ->
new QuantityType<>(site.getRelAutonomy(), Units.PERCENT);
case FroniusBindingConstants.POWER_FLOW_SELF_CONSUMPTION ->
new QuantityType<>(site.getRelSelfConsumption(), Units.PERCENT);
case FroniusBindingConstants.POWER_FLOW_INVERTER_POWER -> {
PowerFlowRealtimeInverter inverter = getInverter(config.deviceId);
if (inverter == null) {
yield null;
}
yield new QuantityType<>(inverter.getP(), Units.WATT);
}
case FroniusBindingConstants.POWER_FLOW_INVERTER_SOC -> {
PowerFlowRealtimeInverter inverter = getInverter(config.deviceId);
if (inverter == null) {
yield null;
}
yield new QuantityType<>(inverter.getSoc(), Units.PERCENT);
}
// Kept for backwards compatibility
case FroniusBindingConstants.POWER_FLOW_INVERTER_1_POWER -> {
PowerFlowRealtimeInverter inverter = getInverter(1);
if (inverter == null) {
yield null;
}
yield new QuantityType<>(inverter.getP(), Units.WATT);
}
case FroniusBindingConstants.POWER_FLOW_INVERTER_1_SOC -> {
PowerFlowRealtimeInverter inverter = getInverter(1);
if (inverter == null) {
yield null;
}
yield new QuantityType<>(inverter.getSoc(), Units.PERCENT);
}
default -> null;
};
}
private @Nullable InverterRealtimeBodyData getInverterData() {
InverterRealtimeResponse localInverterRealtimeResponse = inverterRealtimeResponse;
if (localInverterRealtimeResponse == null) {
return null;
}
InverterRealtimeBody inverterBody = localInverterRealtimeResponse.getBody();
return (inverterBody != null) ? inverterBody.getData() : null;
}
private @Nullable PowerFlowRealtimeBodyData getPowerFlowRealtimeData() {
PowerFlowRealtimeResponse localPowerFlowResponse = powerFlowResponse;
if (localPowerFlowResponse == null) {
return null;
}
PowerFlowRealtimeBody powerFlowBody = localPowerFlowResponse.getBody();
return (powerFlowBody != null) ? powerFlowBody.getData() : null;
}
/**
* get flow data for a specific inverter.
@ -171,8 +220,12 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
* @param number The inverter object of the given index
* @return a PowerFlowRealtimeInverter object.
*/
private PowerFlowRealtimeInverter getInverter(final int number) {
return powerFlowResponse.getBody().getData().getInverters().get(Integer.toString(number));
private @Nullable PowerFlowRealtimeInverter getInverter(final int number) {
PowerFlowRealtimeBodyData powerFlowData = getPowerFlowRealtimeData();
if (powerFlowData == null) {
return null;
}
return powerFlowData.getInverters().get(Integer.toString(number));
}
/**