diff --git a/bundles/org.openhab.binding.senechome/README.md b/bundles/org.openhab.binding.senechome/README.md index 22fad8764..c188babea 100644 --- a/bundles/org.openhab.binding.senechome/README.md +++ b/bundles/org.openhab.binding.senechome/README.md @@ -18,13 +18,14 @@ Examples: Lights, pool filters, wash machines, ... - only V3, V3duo have a power generator and thus MPPs (V3 has 2 MPP, V3duo has 3 MPP) - not equipped battery packs will return 0 for all ...Pack channels - currently channels for the first wallbox are implemented (senec could handle 4 wallboxes) +- Senec disables http access at ~30.08.2023 ## Thing Configuration demo.things ```java -Thing senechome:senechome:pvbattery [ hostname="192.168.0.128", refreshInterval=60, limitationTresholdValue=70, limitationDuration=60 ] +Thing senechome:senechome:pvbattery [ hostname="192.168.0.128", refreshInterval=60, limitationTresholdValue=70, limitationDuration=60, useHttp=false ] ``` If the thing goes online then the connection to the web interface is successful. @@ -69,13 +70,6 @@ The property `limitationTresholdValue` is used as threshold for channel `powerLi | gridVoltagePhase2 | volt | Grid voltage on Phase 2 | | gridVoltagePhase3 | volt | Grid voltage on Phase 3 | | gridFrequency | hertz | Grid frequency | -| 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 | | chargedEnergyPack1 | kilo watt hour | total charged energy battery pack 1 | | chargedEnergyPack2 | kilo watt hour | total charged energy battery pack 2 | | chargedEnergyPack3 | kilo watt hour | total charged energy battery pack 3 | @@ -141,10 +135,6 @@ 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 @@ -176,10 +166,6 @@ 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/SenecHomeApi.java b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeApi.java index da5f773d5..22f57ad93 100644 --- a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeApi.java +++ b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeApi.java @@ -13,7 +13,6 @@ package org.openhab.binding.senechome.internal; import java.io.IOException; -import java.net.MalformedURLException; import java.util.Objects; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; @@ -33,19 +32,17 @@ import org.slf4j.LoggerFactory; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; -import com.google.gson.stream.MalformedJsonException; /** * The {@link SenecHomeApi} class configures http client and * performs status requests * * @author Steven Schwarznau - Initial contribution + * @author Robert Delbrück - Update for Senec API changes * */ @NonNullByDefault public class SenecHomeApi { - private static final String HTTP_PROTO_PREFIX = "http://"; - private final Logger logger = LoggerFactory.getLogger(SenecHomeApi.class); private final HttpClient httpClient; private final Gson gson = new Gson(); @@ -66,28 +63,33 @@ public class SenecHomeApi { * To receive new values, just modify the Json objects and add them to the thing channels * * @return Instance of SenecHomeResponse - * @throws MalformedURLException Configuration/URL is wrong + * @throws TimeoutException Communication failed (Timeout) + * @throws ExecutionException Communication failed * @throws IOException Communication failed + * @throws InterruptedException Communication failed (Interrupted) + * @throws JsonSyntaxException Received response has an invalid json syntax */ public SenecHomeResponse getStatistics() - throws InterruptedException, TimeoutException, ExecutionException, IOException { - String location = HTTP_PROTO_PREFIX + hostname; + throws TimeoutException, ExecutionException, IOException, InterruptedException, JsonSyntaxException { + String location = hostname + "/lala.cgi"; + logger.trace("sending request to: {}", location); Request request = httpClient.newRequest(location); request.header(HttpHeader.ACCEPT, MimeTypes.Type.APPLICATION_JSON.asString()); - request.header(HttpHeader.CONTENT_TYPE, MimeTypes.Type.FORM_ENCODED.asString()); + request.header(HttpHeader.CONTENT_TYPE, MimeTypes.Type.APPLICATION_JSON.asString()); ContentResponse response = null; try { - response = request.method(HttpMethod.POST) - .content(new StringContentProvider(gson.toJson(new SenecHomeResponse()))).send(); + String dataToSend = gson.toJson(new SenecHomeResponse()); + logger.trace("data to send: {}", dataToSend); + response = request.method(HttpMethod.POST).content(new StringContentProvider(dataToSend)).send(); if (response.getStatus() == HttpStatus.OK_200) { - return Objects.requireNonNull(gson.fromJson(response.getContentAsString(), SenecHomeResponse.class)); + String responseString = response.getContentAsString(); + return Objects.requireNonNull(gson.fromJson(responseString, SenecHomeResponse.class)); } else { logger.trace("Got unexpected response code {}", response.getStatus()); throw new IOException("Got unexpected response code " + response.getStatus()); } - } catch (MalformedJsonException | JsonSyntaxException | InterruptedException | TimeoutException - | ExecutionException e) { + } catch (JsonSyntaxException | InterruptedException | TimeoutException | ExecutionException e) { String errorMessage = "\nlocation: " + location; errorMessage += "\nrequest: " + request.toString(); errorMessage += "\nrequest.getHeaders: " + request.getHeaders(); 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 2a73dda00..ad48f43dd 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 @@ -23,7 +23,7 @@ import org.openhab.core.thing.ThingTypeUID; */ @NonNullByDefault public class SenecHomeBindingConstants { - private static final String BINDING_ID = "senechome"; + protected static final String BINDING_ID = "senechome"; private static final String THING_BASE_ID = "senechome"; public static final ThingTypeUID THING_TYPE_SENEC_HOME_BATTERY = new ThingTypeUID(BINDING_ID, THING_BASE_ID); @@ -65,15 +65,6 @@ 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 af7d25d7c..58b1d48bc 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 @@ -16,10 +16,12 @@ package org.openhab.binding.senechome.internal; * The {@link SenecHomeConfigurationDTO} class contains fields mapping thing configuration parameters. * * @author Steven Schwarznau - Initial contribution + * @author Robert Delbrück - Add useHttp */ public class SenecHomeConfigurationDTO { public String hostname; public int refreshInterval = 15; public int limitationTresholdValue = 95; public int limitationDuration = 120; + public boolean useHttp = false; } 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 a7b5e757e..5ac740360 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 @@ -124,7 +124,7 @@ public class SenecHomeHandler extends BaseThingHandler { @Override public void initialize() { config = getConfigAs(SenecHomeConfigurationDTO.class); - senecHomeApi.setHostname(config.hostname); + senecHomeApi.setHostname("%s://%s".formatted(config.useHttp ? "http" : "https", config.hostname)); refreshJob = scheduler.scheduleWithFixedDelay(this::refresh, 0, config.refreshInterval, TimeUnit.SECONDS); limitationStatus = null; } @@ -197,20 +197,6 @@ public class SenecHomeHandler extends BaseThingHandler { 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 (response.battery.chargedEnergy != null) { updateQtyState(CHANNEL_SENEC_CHARGED_ENERGY_PACK1, response.battery.chargedEnergy[0], 2, Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO); diff --git a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeHandlerFactory.java b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeHandlerFactory.java index 82757dbde..df08c8074 100644 --- a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeHandlerFactory.java +++ b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeHandlerFactory.java @@ -17,15 +17,19 @@ import java.util.Set; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.util.ssl.SslContextFactory; import org.openhab.core.io.net.http.HttpClientFactory; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.thing.binding.BaseThingHandlerFactory; import org.openhab.core.thing.binding.ThingHandler; import org.openhab.core.thing.binding.ThingHandlerFactory; +import org.osgi.service.component.ComponentContext; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The {@link SenecHomeHandlerFactory} is responsible for creating things and thing @@ -36,15 +40,17 @@ import org.osgi.service.component.annotations.Reference; @NonNullByDefault @Component(configurationPid = "binding.senechome", service = ThingHandlerFactory.class) public class SenecHomeHandlerFactory extends BaseThingHandlerFactory { + private final Logger logger = LoggerFactory.getLogger(SenecHomeHandlerFactory.class); private static final Set SUPPORTED_THING_TYPES_UIDS = Set .of(SenecHomeBindingConstants.THING_TYPE_SENEC_HOME_BATTERY); - private HttpClient httpClient; + private final HttpClient httpClient; @Activate public SenecHomeHandlerFactory(@Reference HttpClientFactory httpClientFactory) { - this.httpClient = httpClientFactory.getCommonHttpClient(); + SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(true); // Accept all certificates + this.httpClient = httpClientFactory.createHttpClient(SenecHomeBindingConstants.BINDING_ID, sslContextFactory); } @Override @@ -62,4 +68,26 @@ public class SenecHomeHandlerFactory extends BaseThingHandlerFactory { return null; } + + @Override + protected void activate(ComponentContext componentContext) { + super.activate(componentContext); + + try { + httpClient.start(); + } catch (Exception e) { + logger.warn("cannot start Jetty-Http-Client", e); + } + } + + @Override + protected void deactivate(ComponentContext componentContext) { + super.deactivate(componentContext); + + try { + httpClient.stop(); + } catch (Exception e) { + logger.warn("cannot stop Jetty-Http-Client", e); + } + } } diff --git a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeResponse.java b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeResponse.java index bad49a1b2..4e95cbf85 100644 --- a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeResponse.java +++ b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeResponse.java @@ -28,14 +28,13 @@ public class SenecHomeResponse implements Serializable { public @SerializedName("PV1") SenecHomePower power = new SenecHomePower(); public @SerializedName("ENERGY") SenecHomeEnergy energy = new SenecHomeEnergy(); public @SerializedName("PM1OBJ1") SenecHomeGrid grid = new SenecHomeGrid(); - public @SerializedName("STATISTIC") SenecHomeStatistics statistics = new SenecHomeStatistics(); public @SerializedName("BMS") SenecHomeBattery battery = new SenecHomeBattery(); public @SerializedName("TEMPMEASURE") SenecHomeTemperature temperature = new SenecHomeTemperature(); public @SerializedName("WALLBOX") SenecHomeWallbox wallbox = new SenecHomeWallbox(); @Override public String toString() { - return "SenecHomeResponse [power=" + power + ", energy=" + energy + ", grid=" + grid + ", statistics=" - + statistics + "battery" + battery + "temperature" + temperature + "wallbox" + wallbox + "]"; + return "SenecHomeResponse [power=" + power + ", energy=" + energy + ", grid=" + grid + ", battery" + battery + + "temperature" + temperature + "wallbox" + wallbox + "]"; } } diff --git a/bundles/org.openhab.binding.senechome/src/main/resources/OH-INF/i18n/senechome.properties b/bundles/org.openhab.binding.senechome/src/main/resources/OH-INF/i18n/senechome.properties index a27af54f3..bde416149 100644 --- a/bundles/org.openhab.binding.senechome/src/main/resources/OH-INF/i18n/senechome.properties +++ b/bundles/org.openhab.binding.senechome/src/main/resources/OH-INF/i18n/senechome.properties @@ -18,6 +18,8 @@ thing-type.config.senechome.senechome.limitationTresholdValue.label = Limitation thing-type.config.senechome.senechome.limitationTresholdValue.description = Treshold in percent, defines when limitation state is enabled thing-type.config.senechome.senechome.refreshInterval.label = Refresh Interval thing-type.config.senechome.senechome.refreshInterval.description = Rate of refreshing details (in s) +thing-type.config.senechome.senechome.useHttp.label = Use HTTP +thing-type.config.senechome.senechome.useHttp.description = Use legacy http access instead of https # channel types 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 4e9e51b59..db42197dd 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,15 +48,6 @@ - - - - - - - - - @@ -101,6 +92,10 @@ + + 1 + + @@ -122,6 +117,11 @@ Duration of stable values until state is changed, defined in seconds 120 + + + Use legacy http access instead of https + false + diff --git a/bundles/org.openhab.binding.senechome/src/main/resources/OH-INF/update/instructions.xml b/bundles/org.openhab.binding.senechome/src/main/resources/OH-INF/update/instructions.xml new file mode 100644 index 000000000..170de1342 --- /dev/null +++ b/bundles/org.openhab.binding.senechome/src/main/resources/OH-INF/update/instructions.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + +