mirror of
https://github.com/danieldemus/openhab-addons
synced 2026-07-29 12:34:21 +02:00
[fronius] Use Solar API for getting serial number (#19262)
* [fronius] Use Solar API for getting serial Signed-off-by: Florian Hotze <dev@florianhotze.com>
This commit is contained in:
+5
@@ -99,6 +99,7 @@ public class FroniusBindingConstants {
|
||||
|
||||
// List of all Urls
|
||||
public static final String INVERTER_REALTIME_DATA_URL = "%SCHEME%://%IP%/solar_api/v1/GetInverterRealtimeData.cgi?Scope=Device&DeviceId=%DEVICEID%&DataCollection=CommonInverterData";
|
||||
public static final String INVERTER_INFO_URL = "%SCHEME%://%IP%/solar_api/v1/GetInverterInfo.cgi";
|
||||
public static final String POWERFLOW_REALTIME_DATA_URL = "%SCHEME%://%IP%/solar_api/v1/GetPowerFlowRealtimeData.fcgi";
|
||||
public static final String METER_REALTIME_DATA_URL = "%SCHEME%://%IP%/solar_api/v1/GetMeterRealtimeData.cgi?Scope=Device&DeviceId=%DEVICEID%&DataCollection=MeterRealtimeData";
|
||||
public static final String OHMPILOT_REALTIME_DATA_URL = "%SCHEME%://%IP%/solar_api/v1/GetOhmPilotRealtimeData.cgi?Scope=Device&DeviceId=%DEVICEID%";
|
||||
@@ -110,6 +111,10 @@ public class FroniusBindingConstants {
|
||||
return parseUrl(INVERTER_REALTIME_DATA_URL, scheme, ip, deviceId);
|
||||
}
|
||||
|
||||
public static String getInverterInfoUrl(String scheme, String ip) {
|
||||
return parseUrl(INVERTER_INFO_URL, scheme, ip);
|
||||
}
|
||||
|
||||
public static String getPowerFlowDataUrl(String scheme, String ip) {
|
||||
return parseUrl(POWERFLOW_REALTIME_DATA_URL, scheme, ip);
|
||||
}
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2025 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.inverter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link InverterInfoBody} is responsible for storing the "Body" node of the {@link InverterInfoResponse}.
|
||||
*
|
||||
* @author Florian Hotze - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class InverterInfoBody {
|
||||
@SerializedName("Data")
|
||||
private @Nullable Map<Integer, InverterInfoBodyData> data;
|
||||
|
||||
public @Nullable Map<Integer, InverterInfoBodyData> getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2025 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.inverter;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link InverterInfoBodyData} is responsible for storing the "Data" node of the {@link InverterInfoBody}.
|
||||
*
|
||||
* @author Florian Hotze - Initial contribution
|
||||
*/
|
||||
public class InverterInfoBodyData {
|
||||
@SerializedName("DT")
|
||||
private Integer deviceType;
|
||||
|
||||
@SerializedName("PVPower")
|
||||
private Integer pvPower;
|
||||
|
||||
@SerializedName("CustomName")
|
||||
private String customName;
|
||||
|
||||
@SerializedName("Show")
|
||||
private Integer show;
|
||||
|
||||
@SerializedName("UniqueID")
|
||||
private Integer uniqueID;
|
||||
|
||||
@SerializedName("ErrorCode")
|
||||
private Integer errorCode;
|
||||
|
||||
@SerializedName("StatusCode")
|
||||
private Integer statusCode;
|
||||
|
||||
@SerializedName("InverterState")
|
||||
private String inverterState;
|
||||
|
||||
public Integer getDeviceType() {
|
||||
return deviceType;
|
||||
}
|
||||
|
||||
public Integer getPvPower() {
|
||||
return pvPower;
|
||||
}
|
||||
|
||||
public String getCustomName() {
|
||||
return customName;
|
||||
}
|
||||
|
||||
public Integer getShow() {
|
||||
return show;
|
||||
}
|
||||
|
||||
public Integer getUniqueID() {
|
||||
return uniqueID;
|
||||
}
|
||||
|
||||
public Integer getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
public Integer getStatusCode() {
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
public String getInverterState() {
|
||||
return inverterState;
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2025 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.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 InverterInfoResponse} is responsible for storing the response from the GetInverterInfo request.
|
||||
*
|
||||
* @author Florian Hotze - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class InverterInfoResponse extends BaseFroniusResponse {
|
||||
@SerializedName("Body")
|
||||
private @Nullable InverterInfoBody body;
|
||||
|
||||
public @Nullable InverterInfoBody getBody() {
|
||||
return body;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -20,7 +20,7 @@ import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link InverterRealtimeResponse} is responsible for storing
|
||||
* the response from the GetInverterRealtimeData response.
|
||||
* the response from the GetInverterRealtimeData request.
|
||||
*
|
||||
* @author Thomas Rokohl - Initial contribution
|
||||
*/
|
||||
|
||||
+62
-24
@@ -33,10 +33,7 @@ import org.openhab.binding.fronius.internal.api.FroniusBatteryControl;
|
||||
import org.openhab.binding.fronius.internal.api.FroniusCommunicationException;
|
||||
import org.openhab.binding.fronius.internal.api.FroniusHttpUtil;
|
||||
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.inverter.*;
|
||||
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;
|
||||
@@ -132,7 +129,10 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
|
||||
|
||||
Map<String, String> properties = editProperties();
|
||||
properties.put(Thing.PROPERTY_SERIAL_NUMBER, localInverterInfo.serial());
|
||||
properties.put(Thing.PROPERTY_FIRMWARE_VERSION, localInverterInfo.firmware());
|
||||
String firmware = localInverterInfo.firmware();
|
||||
if (firmware != null) {
|
||||
properties.put(Thing.PROPERTY_FIRMWARE_VERSION, firmware);
|
||||
}
|
||||
updateProperties(properties);
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
FroniusBridgeConfiguration bridgeConfig = bridge.getConfiguration().as(FroniusBridgeConfiguration.class);
|
||||
inverterInfo = getInverterInfo(bridgeConfig.hostname);
|
||||
inverterInfo = getInverterInfo(bridgeConfig.scheme, bridgeConfig.hostname, config.deviceId);
|
||||
updateProperties();
|
||||
initializeBatteryControl(bridgeConfig.hostname, bridgeConfig.username, bridgeConfig.password);
|
||||
}
|
||||
@@ -158,9 +158,10 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
|
||||
public void handleBridgeConfigurationUpdate(Map<String, Object> configurationParameters) {
|
||||
super.handleBridgeConfigurationUpdate(configurationParameters);
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
FroniusBaseDeviceConfiguration config = this.config;
|
||||
if (bridge != null && config != null) {
|
||||
FroniusBridgeConfiguration bridgeConfig = bridge.getConfiguration().as(FroniusBridgeConfiguration.class);
|
||||
inverterInfo = getInverterInfo(bridgeConfig.hostname);
|
||||
inverterInfo = getInverterInfo(bridgeConfig.scheme, bridgeConfig.hostname, config.deviceId);
|
||||
updateProperties();
|
||||
initializeBatteryControl(bridgeConfig.hostname, bridgeConfig.username, bridgeConfig.password);
|
||||
}
|
||||
@@ -380,6 +381,7 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
|
||||
/**
|
||||
* Make the InverterRealtimeDataRequest
|
||||
*
|
||||
* @param scheme http or https
|
||||
* @param ip address of the device
|
||||
* @param deviceId of the device
|
||||
* @return {InverterRealtimeResponse} the object representation of the json response
|
||||
@@ -390,6 +392,18 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
|
||||
return collectDataFromUrl(InverterRealtimeResponse.class, location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the InverterInfoRequest
|
||||
*
|
||||
* @param scheme http or https
|
||||
* @param ip address of the device
|
||||
* @return {InverterInfoResponse} the object representation of the json response
|
||||
*/
|
||||
private InverterInfoResponse getInverterInfoData(String scheme, String ip) throws FroniusCommunicationException {
|
||||
String location = FroniusBindingConstants.getInverterInfoUrl(scheme, ip);
|
||||
return collectDataFromUrl(InverterInfoResponse.class, location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the power value from the given voltage and current channels
|
||||
*
|
||||
@@ -406,11 +420,38 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
|
||||
/**
|
||||
* Get the version information of the inverter
|
||||
*
|
||||
* @param hostname the IP address of the inverter
|
||||
* @return InverterInfo containing serial number and firmware version, or null if not available
|
||||
* @param scheme http or https
|
||||
* @param ip address of the device
|
||||
* @param deviceId of the device
|
||||
* @return InverterInfoBody containing serial number and firmware version, or null if not available
|
||||
*/
|
||||
private @Nullable InverterInfo getInverterInfo(String hostname) {
|
||||
final String host = "http://" + hostname;
|
||||
private @Nullable InverterInfo getInverterInfo(String schema, String ip, int deviceId) {
|
||||
InverterInfoResponse inverterInfoResponse = null;
|
||||
try {
|
||||
inverterInfoResponse = getInverterInfoData(schema, ip);
|
||||
} catch (FroniusCommunicationException e) {
|
||||
logger.warn("Failed to get InverterInfo from Fronius inverter at {}: {}", ip, e.getMessage());
|
||||
return null;
|
||||
}
|
||||
if (inverterInfoResponse.getBody() == null) {
|
||||
return null;
|
||||
}
|
||||
InverterInfoBody inverterInfoBody = inverterInfoResponse.getBody();
|
||||
if (inverterInfoBody == null) {
|
||||
return null;
|
||||
}
|
||||
Map<Integer, InverterInfoBodyData> inverterInfoBodyData = inverterInfoBody.getData();
|
||||
if (inverterInfoBodyData == null) {
|
||||
return null;
|
||||
}
|
||||
InverterInfoBodyData data = inverterInfoBodyData.get(deviceId);
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String serial = String.valueOf(data.getUniqueID());
|
||||
|
||||
final String host = "http://" + ip;
|
||||
final String versionPath = "/status/version";
|
||||
|
||||
String url = host + "/api" + versionPath; // try the new API path first
|
||||
@@ -422,34 +463,31 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler {
|
||||
try {
|
||||
response = FroniusHttpUtil.executeUrl(HttpMethod.GET, url, API_TIMEOUT);
|
||||
} catch (FroniusCommunicationException ex) {
|
||||
logger.warn("Failed to get version info from Fronius inverter at {}: {}", hostname, ex.getMessage());
|
||||
return null;
|
||||
logger.debug("Failed to get version info from Fronius inverter at {}: {}", ip, ex.getMessage());
|
||||
return new InverterInfo(serial, null);
|
||||
}
|
||||
}
|
||||
try {
|
||||
JsonElement jsonElement = JsonParser.parseString(response);
|
||||
if (!jsonElement.isJsonObject()) {
|
||||
logger.warn("Invalid JSON response for version info from Fronius inverter at {}: {}", hostname,
|
||||
response);
|
||||
return null;
|
||||
logger.debug("Invalid JSON response for version info from Fronius inverter at {}: {}", ip, response);
|
||||
return new InverterInfo(serial, null);
|
||||
}
|
||||
try {
|
||||
String serial = jsonElement.getAsJsonObject().get("serialNumber").getAsString();
|
||||
String firmware = jsonElement.getAsJsonObject().get("swrevisions").getAsJsonObject().get("GEN24")
|
||||
.getAsString();
|
||||
return new InverterInfo(serial, firmware);
|
||||
} catch (IllegalStateException | UnsupportedOperationException e) {
|
||||
logger.warn("Failed to parse version info from Fronius inverter at {}: {}", hostname, e.getMessage());
|
||||
return null;
|
||||
logger.debug("Failed to parse version info from Fronius inverter at {}: {}", ip, e.getMessage());
|
||||
return new InverterInfo(serial, null);
|
||||
}
|
||||
} catch (JsonSyntaxException e) {
|
||||
// 404 errors go here, as the response is not valid JSON
|
||||
logger.debug("Invalid JSON response for version info from Fronius inverter at {}: {}", hostname, response,
|
||||
e);
|
||||
logger.debug("Invalid JSON response for version info from Fronius inverter at {}: {}", ip, response, e);
|
||||
}
|
||||
return null;
|
||||
return new InverterInfo(serial, null);
|
||||
}
|
||||
|
||||
private record InverterInfo(String serial, String firmware) {
|
||||
private record InverterInfo(String serial, @Nullable String firmware) {
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user