diff --git a/bundles/org.openhab.binding.senechome/README.md b/bundles/org.openhab.binding.senechome/README.md index bcc4b0c579ba..198e66f3e58a 100644 --- a/bundles/org.openhab.binding.senechome/README.md +++ b/bundles/org.openhab.binding.senechome/README.md @@ -25,7 +25,19 @@ Examples: Lights, pool filters, wash machines, ... demo.things ```java -Thing senechome:senechome:pvbattery [ hostname="192.168.0.128", refreshInterval=60, limitationTresholdValue=70, limitationDuration=60, usePlain=false ] +Thing senechome:senechome:pvbattery [ + hostname="192.168.0.128", + refreshInterval=60, + limitationTresholdValue=70, + limitationDuration=60, + useHttp=false, + // optional: mein-senec.de connection for statistic values + meinSenecRefreshInterval=300, + meinSenecUsername=address@mailprovider.com, + meinSenecPassword=SecretPassword, + // only required if you have more than one device registered in mein-senec.de + meinSenecDeviceId=1234 +] ``` If the thing goes online then the connection to the web interface is successful. @@ -108,6 +120,18 @@ The property `limitationTresholdValue` is used as threshold for channel `powerLi | wallbox1ChargingCurrentPhase3 | ampere | Wallbox 1 charging current Phase 3 | | wallbox1ChargingPower | watt | Wallbox 1 charging power | +If you configure the (Mein Senec)[https://mein-senec.de/] login username and password, you will also receive data in these channels: + +| Channel | Type | Description | +| ----------------------------- | -------------- | ------------------------------------------------------------------------ | +| liveBatCharge | kilo watt hour | Live Total Bat Charge | +| liveBatDischarge | kilo watt hour | Live Total Bat Discharge | +| liveGridImport | kilo watt hour | Live Total Grid Import | +| liveGridExport | kilo watt hour | Live Total Grid Export | +| liveHouseConsumption | kilo watt hour | Live Total House Consumption (without WB) | +| livePowerGenerator | kilo watt hour | Live Total PV generator generated energy | +| liveEnergyWallbox1 | kilo watt hour | Live Total Wallbox 1 charged energy | + ## Items Sample: @@ -135,6 +159,10 @@ Number SenecGridVoltagePh2 "Voltage Level on Phase 2 [%d V]" { channel="senechome:senechome:pvbattery:gridVoltagePhase3" } Number SenecGridFrequency "Grid Frequency [%.2f Hz]" { channel="senechome:senechome:pvbattery:gridFrequency" } Number SenecBatteryVoltage "Battery Voltage [%.1f V]" { channel="senechome:senechome:pvbattery:batteryVoltage" } +Number SenecLiveBatCharge "Live Bat Charge [%d kWh]" { channel="senechome:senechome:pvbattery:liveBatCharge" } +Number SenecLiveBatDischarge "Live Bat Discharge [%d kWh]" { channel="senechome:senechome:pvbattery:liveBatDischarge" } +Number SenecLiveGridImport "Live Grid Import [%d kWh]" { channel="senechome:senechome:pvbattery:liveGridImport" } +Number SenecLiveGridExport "Live Grid Export [%d kWh]" { channel="senechome:senechome:pvbattery:liveGridExport" } ``` ## Sitemap @@ -166,6 +194,10 @@ Text label="Power Grid"{ Default item=SenecGridVoltagePh3 Default item=SenecGridFrequency Default item=SenecBatteryVoltage + Default item=SenecLiveBatCharge + Default item=SenecLiveBatDischarge + Default item=SenecLiveGridImport + Default item=SenecLiveGridExport } } ``` diff --git a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/MeinSenecApi.java b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/MeinSenecApi.java new file mode 100644 index 000000000000..7e7a424de5f1 --- /dev/null +++ b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/MeinSenecApi.java @@ -0,0 +1,286 @@ +/** + * Copyright (c) 2010-2023 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.senechome.internal; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.util.StringContentProvider; +import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.openhab.binding.senechome.internal.json.MeinSenecResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; + +/** + * The {@link MeinSenecApi} class configures https client and performs status requests + * + * @author Korbinian Probst - Initial contribution + * + */ +@NonNullByDefault +public class MeinSenecApi { + private final Logger logger = LoggerFactory.getLogger(MeinSenecApi.class); + private static final String BASE_URL = "https://app-gateway-prod.senecops.com/v1/senec"; + private final HttpClient httpClient; + private final Gson gson = new Gson(); + private boolean isEnabled = false; + private String username = ""; + private String password = ""; + private String token = ""; + private String deviceId = ""; + + public MeinSenecApi(HttpClient httpClient) { + this.httpClient = httpClient; + } + + /** + * Return if the mein-senec.de api can be accessed + * + * @return true = enabled, false = disabled + */ + public boolean isEnabled() { + return this.isEnabled; + } + + public void loginMeinSenec(String username, String password, String deviceId) { + // if username or password are empty, mein-senec.de stays disabled + if (username == null || username.isEmpty() || !username.contains("@")) { + logger.debug("No username given, mein-senec.de stays disabled"); + return; + } + if (password == null || password.isEmpty()) { + logger.debug("No password given, mein-senec.de stays disabled"); + return; + } + + this.username = username; + this.password = password; + + getLoginToken(); + verifyDevice(deviceId); + + // if the token could not be received or the device position not clarified, mein-senec.de stays disabled + if ((token.isEmpty()) || (this.deviceId.isEmpty())) { + logger.debug("Problems with token or deviceId, mein-senec.de stays disabled"); + } else { + isEnabled = true; + } + } + + /** + * If no login token is set, login to mein-senec.de to generate and store the token for future api calls + */ + private void getLoginToken() { + try { + String loginUrl = BASE_URL + "/login"; + Request request = httpClient.newRequest(loginUrl); + + // Set the HTTP request method to POST + request.method(HttpMethod.POST); + + // Create the payload data as a JSON string + Map payloadData = new HashMap<>(); + payloadData.put("username", username); + payloadData.put("password", password); + String payloadJson = gson.toJson(payloadData); + + // Set the request content + request.content(new StringContentProvider(payloadJson), "application/json"); + + // Send the request + ContentResponse response = request.send(); + + if (response.getStatus() == 200) { + // Parse the JSON response to extract the access token + Map responseMap = gson.fromJson(response.getContentAsString(), Map.class); + // Code below looks strange because of the build error + // Null type mismatch: required 'java.lang.@NonNull String' but the provided value is inferred as + // @org.eclipse.jdt.annotation.Nullable + String local_token = (responseMap.get("token") instanceof String) ? (String) responseMap.get("token") + : ""; + + if (local_token != null) { + logger.debug("Login successful!"); + token = local_token; + } else { + logger.error("Login failed. Token not found in response."); + token = ""; + } + } else { + logger.debug("Login failed with status code: {}", response.getStatus()); + } + } catch (Exception e) { + logger.error("An error occurred during login: {}", e.getMessage()); + } + } + + /** + * Get all devices from mein-senec.de. Either only one device exists or the device with the given deviceId will be + * taken for fetching + * + * @param deviceId optional + */ + private void verifyDevice(String deviceId) { + List> devicesData = null; + + try { + String devicesUrl = BASE_URL + "/anlagen"; + Request request = httpClient.newRequest(devicesUrl); + + // Set the HTTP request method to GET + request.method(HttpMethod.GET); + + // Set the authorization header + request.header("Authorization", token); + + // Send the request + ContentResponse response = request.send(); + + if (response.getStatus() == 200) { + // Parse the JSON response to extract the list of devices + devicesData = gson.fromJson(response.getContentAsString(), List.class); + + logger.debug("Devices Data:"); + logger.debug("{}", gson.toJson(devicesData)); + + if (devicesData.size() == 0) { + // No device, nothing to do + } + if (devicesData.size() == 1) { + // With only one device just take it + Map device = devicesData.get(0); + String id = (String) device.get("id"); + if (id != null) { + this.deviceId = id; + } + } else if (deviceId.isEmpty()) { + // if no device id is given but the size of the array is > 1, print all IDs + logger.warn("There are {} devices configured in mein-senec.de, but no device id was configured.", + devicesData.size()); + for (int i = 0; i < devicesData.size(); i++) { + Map device = devicesData.get(i); + String id = (String) device.get("id"); + String steuereinheitnummer = (String) device.get("steuereinheitnummer"); + String gehaeusenummer = (String) device.get("gehaeusenummer"); + String strasse = (String) device.get("strasse"); + String hausnummer = (String) device.get("hausnummer"); + String postleitzahl = (String) device.get("postleitzahl"); + String ort = (String) device.get("ort"); + String zeitzone = (String) device.get("zeitzone"); + String systemType = (String) device.get("systemType"); + logger.warn( + "Id: {}, control device id: {}, housing id: {} address: {} {}, {} {}, timezone: {}, system type: {}", + id, steuereinheitnummer, gehaeusenummer, strasse, hausnummer, postleitzahl, ort, + zeitzone, systemType); + } + } else { + // If size > 1 and a device id was given, try to identify the position in the array + for (int i = 0; i < devicesData.size(); i++) { + Map device = devicesData.get(i); + String id = (String) device.get("id"); + if (deviceId.equals(id)) { + // Code below looks strange because of build error + // Null type mismatch: required 'java.lang.@NonNull String' but the provided value is + // inferred as @org.eclipse.jdt.annotation.Nullable + String local_id = (id instanceof String) ? (String) id : ""; + this.deviceId = local_id; + break; // Exit the loop once the device is found + } + } + } + + // last verify that the device was found + if (this.deviceId.length() > 0) { + logger.debug("Device ID {} found and verified", this.deviceId); + } else { + logger.debug("Device ID not found in the devicesData array."); + } + } else { + logger.debug("Failed to retrieve devices with status code: {}", response.getStatus()); + logger.debug("Request URL: {}", devicesUrl); + + // Iterate over the headers + for (HttpField field : request.getHeaders()) { + String headerName = field.getName(); + String headerValue = field.getValue(); + + logger.debug("Header Name: {}", headerName); + logger.debug("Header Value: {}", headerValue); + } + } + } catch (Exception e) { + logger.error("An error occurred while retrieving devices: {}", e.getMessage()); + } + } + + public MeinSenecResponse getDashboard() { + try { + HttpClient httpClient = new HttpClient(new SslContextFactory.Client()); + httpClient.start(); + + String dashboardUrl = BASE_URL + "/anlagen/" + deviceId + "/dashboard"; + Request request = httpClient.newRequest(dashboardUrl); + + // Set the HTTP request method to GET + request.method(HttpMethod.GET); + + // Set the authorization header + request.header("Authorization", token); + + // Send the request + ContentResponse response = request.send(); + + if (response.getStatus() == 200) { + // Parse the JSON response to extract dashboard data + // Map dashboardData = gson.fromJson(response.getContentAsString(), Map.class); + + // logger.debug("Dashboard Data:"); + // logger.debug("{}", gson.toJson(dashboardData, Map.class)); + + // // Convert the dashboardData map to a JSON string + // String dashboardJson = gson.toJson(dashboardData, Map.class); + + // Deserialize the JSON string into a MeinSenecResponse object + // return Objects.requireNonNull(gson.fromJson(dashboardJson, MeinSenecResponse.class)); + return Objects.requireNonNull(gson.fromJson(response.getContentAsString(), MeinSenecResponse.class)); + } else { + logger.debug("Failed to retrieve dashboard data with status code: {}", response.getStatus()); + logger.debug("Request URL: {}", dashboardUrl); + + // Iterate over the headers + for (HttpField field : request.getHeaders()) { + String headerName = field.getName(); + String headerValue = field.getValue(); + + logger.debug("Header Name: {}", headerName); + logger.debug("Header Value: {}", headerValue); + } + } + + } catch (Exception e) { + logger.error("An error occurred while retrieving dashboard data: {}", e.getMessage()); + } + // TODO what to return if everything breaks? + return new MeinSenecResponse(); + } +} diff --git a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeBindingConstants.java b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeBindingConstants.java index 903ca4b115bb..2a73dda009ac 100644 --- a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeBindingConstants.java +++ b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeBindingConstants.java @@ -65,6 +65,15 @@ public class SenecHomeBindingConstants { public static final String CHANNEL_SENEC_GRID_VOLTAGE_PH3 = "gridVoltagePhase3"; public static final String CHANNEL_SENEC_GRID_FREQUENCY = "gridFrequency"; + // SenecHomeStatistics + public static final String CHANNEL_SENEC_LIVE_BAT_CHARGE = "liveBatCharge"; + public static final String CHANNEL_SENEC_LIVE_BAT_DISCHARGE = "liveBatDischarge"; + public static final String CHANNEL_SENEC_LIVE_GRID_IMPORT = "liveGridImport"; + public static final String CHANNEL_SENEC_LIVE_GRID_EXPORT = "liveGridExport"; + public static final String CHANNEL_SENEC_LIVE_HOUSE_CONSUMPTION = "liveHouseConsumption"; + public static final String CHANNEL_SENEC_LIVE_POWER_GENERATOR = "livePowerGenerator"; + public static final String CHANNEL_SENEC_LIVE_ENERGY_WALLBOX1 = "liveEnergyWallbox1"; + // SenecHomeBattery public static final String CHANNEL_SENEC_CHARGED_ENERGY_PACK1 = "chargedEnergyPack1"; public static final String CHANNEL_SENEC_CHARGED_ENERGY_PACK2 = "chargedEnergyPack2"; diff --git a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeConfigurationDTO.java b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeConfigurationDTO.java index e2590978a0af..a8ec5b397dfe 100644 --- a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeConfigurationDTO.java +++ b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeConfigurationDTO.java @@ -23,4 +23,8 @@ public class SenecHomeConfigurationDTO { public int limitationTresholdValue = 95; public int limitationDuration = 120; public boolean useHttp = false; + public int meinSenecRefreshInterval = 300; + public String meinSenecUsername = ""; + public String meinSenecPassword = ""; + public String meinSenecDeviceId = ""; } diff --git a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeHandler.java b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeHandler.java index bf46457352c1..71118f9374d0 100644 --- a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeHandler.java +++ b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeHandler.java @@ -32,6 +32,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; +import org.openhab.binding.senechome.internal.json.MeinSenecResponse; import org.openhab.binding.senechome.internal.json.SenecHomeResponse; import org.openhab.core.cache.ExpiringCache; import org.openhab.core.library.types.DecimalType; @@ -83,12 +84,14 @@ public class SenecHomeHandler extends BaseThingHandler { private @Nullable ScheduledFuture refreshJob; private @Nullable PowerLimitationStatusDTO limitationStatus = null; private final @Nullable SenecHomeApi senecHomeApi; + private final @Nullable MeinSenecApi meinSenecApi; private SenecHomeConfigurationDTO config = new SenecHomeConfigurationDTO(); private final ExpiringCache refreshCache = new ExpiringCache<>(Duration.ofSeconds(5), this::refreshState); public SenecHomeHandler(Thing thing, HttpClient httpClient) { super(thing); this.senecHomeApi = new SenecHomeApi(httpClient); + this.meinSenecApi = new MeinSenecApi(httpClient); } @Override @@ -125,6 +128,7 @@ protected void stopJobIfRunning() { public void initialize() { config = getConfigAs(SenecHomeConfigurationDTO.class); senecHomeApi.setHostname("%s://%s".formatted(config.useHttp ? "http" : "https", config.hostname)); + meinSenecApi.loginMeinSenec(config.meinSenecUsername, config.meinSenecPassword, config.meinSenecDeviceId); refreshJob = scheduler.scheduleWithFixedDelay(this::refresh, 0, config.refreshInterval, TimeUnit.SECONDS); limitationStatus = null; } @@ -135,8 +139,10 @@ private void refresh() { public @Nullable Boolean refreshState() { SenecHomeResponse response = null; + MeinSenecResponse responseMeinSenec = null; try { response = senecHomeApi.getStatistics(); + responseMeinSenec = meinSenecApi.getDashboard(); logger.trace("received {}", response); BigDecimal pvLimitation = new BigDecimal(100).subtract(getSenecValue(response.power.powerLimitation)) @@ -197,21 +203,23 @@ private void refresh() { updateQtyState(CHANNEL_SENEC_GRID_VOLTAGE_PH3, response.grid.currentGridVoltagePerPhase[2], 2, Units.VOLT); updateQtyState(CHANNEL_SENEC_GRID_FREQUENCY, response.grid.currentGridFrequency, 2, Units.HERTZ); - // updateQtyState(CHANNEL_SENEC_LIVE_BAT_CHARGE, response.statistics.liveBatCharge, 2, Units.KILOWATT_HOUR); - // updateQtyState(CHANNEL_SENEC_LIVE_BAT_DISCHARGE, response.statistics.liveBatDischarge, 2, - // Units.KILOWATT_HOUR); - // updateQtyState(CHANNEL_SENEC_LIVE_GRID_IMPORT, response.statistics.liveGridImport, 2, - // Units.KILOWATT_HOUR); - // updateQtyState(CHANNEL_SENEC_LIVE_GRID_EXPORT, response.statistics.liveGridExport, 2, - // Units.KILOWATT_HOUR); - // updateQtyState(CHANNEL_SENEC_LIVE_HOUSE_CONSUMPTION, response.statistics.liveHouseConsumption, 2, - // Units.KILOWATT_HOUR); - // updateQtyState(CHANNEL_SENEC_LIVE_POWER_GENERATOR, response.statistics.livePowerGenerator, 2, - // Units.KILOWATT_HOUR); - // if (response.statistics.liveWallboxEnergy != null) { - // updateQtyState(CHANNEL_SENEC_LIVE_ENERGY_WALLBOX1, response.statistics.liveWallboxEnergy[0], 2, - // Units.KILOWATT_HOUR, DIVISOR_ISO_TO_KILO); - // } + if (meinSenecApi.isEnabled()) { + updateMeinSenecState(CHANNEL_SENEC_LIVE_BAT_CHARGE, + responseMeinSenec.getAktuell().getSpeicherbeladung().getWert(), Units.KILOWATT_HOUR); + updateMeinSenecState(CHANNEL_SENEC_LIVE_BAT_DISCHARGE, + responseMeinSenec.getAktuell().getStromverbrauch().getWert(), Units.KILOWATT_HOUR); + updateMeinSenecState(CHANNEL_SENEC_LIVE_GRID_IMPORT, + responseMeinSenec.getAktuell().getNetzbezug().getWert(), Units.KILOWATT_HOUR); + updateMeinSenecState(CHANNEL_SENEC_LIVE_GRID_EXPORT, + responseMeinSenec.getAktuell().getNetzeinspeisung().getWert(), Units.KILOWATT_HOUR); + updateMeinSenecState(CHANNEL_SENEC_LIVE_HOUSE_CONSUMPTION, + responseMeinSenec.getAktuell().getStromverbrauch().getWert(), Units.KILOWATT_HOUR); + updateMeinSenecState(CHANNEL_SENEC_LIVE_POWER_GENERATOR, + responseMeinSenec.getAktuell().getStromerzeugung().getWert(), Units.KILOWATT_HOUR); + updateMeinSenecState(CHANNEL_SENEC_LIVE_ENERGY_WALLBOX1, + responseMeinSenec.getAktuell().getWallbox().getWert(), Units.KILOWATT_HOUR, + DIVISOR_ISO_TO_KILO); + } if (response.battery.chargedEnergy != null) { updateQtyState(CHANNEL_SENEC_CHARGED_ENERGY_PACK1, response.battery.chargedEnergy[0], 2, @@ -345,6 +353,20 @@ protected > void updateQtyState(String channelName, String updateState(channel.getUID(), new QuantityType(value, unit)); } + protected > void updateMeinSenecState(String channelName, double doubleValue, Unit unit) { + updateMeinSenecState(channelName, doubleValue, unit, null); + } + + protected > void updateMeinSenecState(String channelName, double doubleValue, Unit unit, + @Nullable BigDecimal divisor) { + Channel channel = getThing().getChannel(channelName); + BigDecimal value = new BigDecimal(doubleValue); + if (divisor != null) { + value = value.divide(divisor, 1, RoundingMode.HALF_UP); + } + updateState(channel.getUID(), new QuantityType(value, unit)); + } + protected BigDecimal getSenecValue(String value) { String[] type = value.split("_"); diff --git a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/MeinSenecResponse.java b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/MeinSenecResponse.java new file mode 100644 index 000000000000..d2ad39fb5de2 --- /dev/null +++ b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/MeinSenecResponse.java @@ -0,0 +1,152 @@ +/** + * Copyright (c) 2010-2023 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.senechome.internal.json; + +import java.io.Serializable; + +/** + * Json model of mein-senec.de dashboard api, rebuilt by analyzing the api. + * + * @author Korbinian Probst - Initial Contribution + */ +public class MeinSenecResponse implements Serializable { + private Aktuell aktuell; + private Heute heute; + private String zeitstempel; + private boolean electricVehicleConnected; + + public Aktuell getAktuell() { + return aktuell; + } + + public Heute getHeute() { + return heute; + } + + public String getZeitstempel() { + return zeitstempel; + } + + public boolean isElectricVehicleConnected() { + return electricVehicleConnected; + } + + public static class Aktuell implements Serializable { + private Wert stromerzeugung; + private Wert stromverbrauch; + private Wert netzeinspeisung; + private Wert netzbezug; + private Wert speicherbeladung; + private Wert speicherentnahme; + private Wert speicherfuellstand; + private Wert autarkie; + private Wert wallbox; + + public Wert getStromerzeugung() { + return stromerzeugung; + } + + public Wert getStromverbrauch() { + return stromverbrauch; + } + + public Wert getNetzeinspeisung() { + return netzeinspeisung; + } + + public Wert getNetzbezug() { + return netzbezug; + } + + public Wert getSpeicherbeladung() { + return speicherbeladung; + } + + public Wert getSpeicherentnahme() { + return speicherentnahme; + } + + public Wert getSpeicherfuellstand() { + return speicherfuellstand; + } + + public Wert getAutarkie() { + return autarkie; + } + + public Wert getWallbox() { + return wallbox; + } + } + + public static class Heute implements Serializable { + private Wert stromerzeugung; + private Wert stromverbrauch; + private Wert netzeinspeisung; + private Wert netzbezug; + private Wert speicherbeladung; + private Wert speicherentnahme; + private Wert speicherfuellstand; + private Wert autarkie; + private Wert wallbox; + + public Wert getStromerzeugung() { + return stromerzeugung; + } + + public Wert getStromverbrauch() { + return stromverbrauch; + } + + public Wert getNetzeinspeisung() { + return netzeinspeisung; + } + + public Wert getNetzbezug() { + return netzbezug; + } + + public Wert getSpeicherbeladung() { + return speicherbeladung; + } + + public Wert getSpeicherentnahme() { + return speicherentnahme; + } + + public Wert getSpeicherfuellstand() { + return speicherfuellstand; + } + + public Wert getAutarkie() { + return autarkie; + } + + public Wert getWallbox() { + return wallbox; + } + } + + public static class Wert implements Serializable { + private double wert; + private String einheit; + + public double getWert() { + return wert; + } + + public String getEinheit() { + return einheit; + } + } +} diff --git a/bundles/org.openhab.binding.senechome/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.senechome/src/main/resources/OH-INF/thing/thing-types.xml index 62d639332bae..31d1d6f246ea 100644 --- a/bundles/org.openhab.binding.senechome/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.senechome/src/main/resources/OH-INF/thing/thing-types.xml @@ -48,6 +48,15 @@ + + + + + + + + + @@ -114,10 +123,31 @@ 120 - + Use legacy http access false + + + Rate of refreshing details (in s) + 300 + + + + Enter the username that you use to login to mein-senec.de + email + + + + Enter the password that you use to login to mein-senec.de + password + + + + Enter the device id if you have more than one device connected at mein-senec.de. Leave it empty to take + the first and only device. + +