]> git.basschouten.com Git - openhab-addons.git/commitdiff
[Senec] Fix for Senec firmware update (#15535)
authorRobert D <querdenker2k@gmx.de>
Sat, 11 Nov 2023 13:01:37 +0000 (14:01 +0100)
committerGitHub <noreply@github.com>
Sat, 11 Nov 2023 13:01:37 +0000 (14:01 +0100)
* Fix for Senec update

Signed-off-by: querdenker2k <querdenker2k@gmx.de>
bundles/org.openhab.binding.senechome/README.md
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeApi.java
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeBindingConstants.java
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeConfigurationDTO.java
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeHandler.java
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeHandlerFactory.java
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeResponse.java
bundles/org.openhab.binding.senechome/src/main/resources/OH-INF/i18n/senechome.properties
bundles/org.openhab.binding.senechome/src/main/resources/OH-INF/thing/thing-types.xml
bundles/org.openhab.binding.senechome/src/main/resources/OH-INF/update/instructions.xml [new file with mode: 0644]

index 22fad8764cfac38bfde75f75d5520464c979bd0d..c188babea896aef6c635209862604a37e33fddf3 100644 (file)
@@ -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]"            <e
 Number SenecGridVoltagePh3       "Voltage Level on Phase 3 [%d V]"            <energy> { channel="senechome:senechome:pvbattery:gridVoltagePhase3" }
 Number SenecGridFrequency        "Grid Frequency [%.2f Hz]"                   <energy> { channel="senechome:senechome:pvbattery:gridFrequency" }
 Number SenecBatteryVoltage       "Battery Voltage [%.1f V]"                   <energy> { channel="senechome:senechome:pvbattery:batteryVoltage" }
-Number SenecLiveBatCharge        "Live Bat Charge [%d kWh]"                   <energy> { channel="senechome:senechome:pvbattery:liveBatCharge" }
-Number SenecLiveBatDischarge     "Live Bat Discharge [%d kWh]"                <energy> { channel="senechome:senechome:pvbattery:liveBatDischarge" }
-Number SenecLiveGridImport       "Live Grid Import [%d kWh]"                  <energy> { channel="senechome:senechome:pvbattery:liveGridImport" }
-Number SenecLiveGridExport       "Live Grid Export [%d kWh]"                  <energy> { 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
     }
 }
 ```
index da5f773d5b41892d35607ef21f542cc661e1b705..22f57ad935bd2d3183f735e8df10506cb81522ae 100644 (file)
@@ -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();
index 2a73dda009ac1f4b30a48feb1defeb7dbc5b72c9..ad48f43dd41b8177b856c56b326007e64d80786d 100644 (file)
@@ -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";
index af7d25d7c30c000492fd94c229aa292ea5bc144d..58b1d48bc7330329e44eea96f0a3516d97d85e2a 100644 (file)
@@ -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;
 }
index a7b5e757efe3f2747441ba4017d6b7099a035f59..5ac74036047bc7ed78c4a22760340d679359254c 100644 (file)
@@ -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);
index 82757dbde233aadb5a415e7ca0e1b23e84b3c617..df08c8074d30ffe6c4fe18610da4ba963241b960 100644 (file)
@@ -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<ThingTypeUID> 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);
+        }
+    }
 }
index bad49a1b2a03f6121164bfa7c9f9e238318093b6..4e95cbf85ed801a70ac16c11a7fc67c9899db23e 100644 (file)
@@ -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 + "]";
     }
 }
index a27af54f3d3658495e37d0983e392b85e5e1ec23..bde416149b4be8fbf9999270eadfdbde69ebd2cd 100644 (file)
@@ -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
 
index 4e9e51b594d1f4bcbf7982408115b00e3eed1334..db42197ddb32caeac93c7ce3703b349af4e371d5 100644 (file)
                        <channel id="gridVoltagePhase3" typeId="gridVoltagePhase3"/>
                        <channel id="gridFrequency" typeId="gridFrequency"/>
 
-                       <!-- SenecHomeStatistics -->
-                       <channel id="liveBatCharge" typeId="liveBatCharge"/>
-                       <channel id="liveBatDischarge" typeId="liveBatDischarge"/>
-                       <channel id="liveGridImport" typeId="liveGridImport"/>
-                       <channel id="liveGridExport" typeId="liveGridExport"/>
-                       <channel id="liveHouseConsumption" typeId="liveHouseConsumption"/>
-                       <channel id="livePowerGenerator" typeId="livePowerGenerator"/>
-                       <channel id="liveEnergyWallbox1" typeId="liveEnergyWallbox1"/>
-
                        <!-- SenecHomeBattery -->
                        <channel id="chargedEnergyPack1" typeId="chargedEnergyPack1"/>
                        <channel id="chargedEnergyPack2" typeId="chargedEnergyPack2"/>
                        <channel id="wallbox1ChargingPower" typeId="wallbox1ChargingPower"/>
                </channels>
 
+               <properties>
+                       <property name="thingTypeVersion">1</property>
+               </properties>
+
                <config-description>
                        <parameter name="hostname" type="text" required="true">
                                <label>Hostname/IP Address</label>
                                <description>Duration of stable values until state is changed, defined in seconds</description>
                                <default>120</default>
                        </parameter>
+                       <parameter name="useHttp" type="boolean" required="false">
+                               <label>Use HTTP</label>
+                               <description>Use legacy http access instead of https</description>
+                               <default>false</default>
+                       </parameter>
                </config-description>
 
        </thing-type>
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 (file)
index 0000000..170de13
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<update:update-descriptions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:update="https://openhab.org/schemas/update-description/v1.0.0"
+       xsi:schemaLocation="https://openhab.org/schemas/update-description/v1.0.0 https://openhab.org/schemas/update-description-1.0.0.xsd">
+
+       <thing-type uid="senechome:senechome">
+
+               <instruction-set targetVersion="1">
+                       <remove-channel id="liveBatCharge"/>
+                       <remove-channel id="liveBatDischarge"/>
+                       <remove-channel id="liveGridImport"/>
+                       <remove-channel id="liveGridExport"/>
+                       <remove-channel id="liveHouseConsumption"/>
+                       <remove-channel id="livePowerGenerator"/>
+                       <remove-channel id="liveEnergyWallbox1"/>
+               </instruction-set>
+
+       </thing-type>
+
+</update:update-descriptions>