]> git.basschouten.com Git - openhab-addons.git/commitdiff
[homematic] Fix for two (re)connection problems (#9692)
authorMartin Herbst <develop@mherbst.de>
Tue, 12 Jan 2021 21:11:52 +0000 (22:11 +0100)
committerGitHub <noreply@github.com>
Tue, 12 Jan 2021 21:11:52 +0000 (22:11 +0100)
* Replace deprecated constructors
* Removed no longer existing settings from the documentation. They were already marked as deprecated since several versions.
* Refactored communication with the HM gateway
- simplified coding for the communication with the gateway
- buffer size for communication is now configurable to avoid problems
with too small buffers
- Previous solution for #6963 was not sufficient. Should be finally done
with these changes
* Retrieving the duty cycle is sufficient to check connection
- ping requests could therefore be safely removed problems with the automatic reconnection were solved.
* Changed to explicit list of Exception

Fixes #8808

Signed-off-by: Martin Herbst <develop@mherbst.de>
bundles/org.openhab.binding.homematic/README.md
bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/common/HomematicConfig.java
bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/AbstractHomematicGateway.java
bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/RpcClient.java
bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/XmlRpcClient.java
bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/message/BinRpcMessage.java
bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/message/XmlRpcResponse.java
bundles/org.openhab.binding.homematic/src/main/resources/OH-INF/thing/bridge.xml

index b00ee7518543210f33d30a9641072a24716f61af..3d331ceb949bcc23dd4cc9b390293a5c32027d67 100644 (file)
@@ -133,24 +133,12 @@ Callback network address of the system runtime, default is auto-discovery
 - **bindAddress**
 The address the XML-/BINRPC server binds to, default is value of "callbackHost"
 
-- **callbackPort** (DEPRECATED, use "binCallbackPort" resp. "xmlCallbackPort")
-Callback port of the binding's server, default is 9125 and counts up for each additional bridge
-
 - **xmlCallbackPort**
 Callback port of the binding's XML-RPC server, default is 9125 and counts up for each additional bridge
 
 - **binCallbackPort**
 Callback port of the binding's BIN-RPC server, default is 9126 and counts up for each additional bridge
 
-- **aliveInterval** (DEPRECATED, not necessary anymore)
-The interval in seconds to check if the communication with the Homematic gateway is still alive. If no message receives from the Homematic gateway, the RPC server restarts (default = 300)
-
-- **reconnectInterval** (DEPRECATED, not necessary anymore)
-The interval in seconds to force a reconnect to the Homematic gateway, disables "aliveInterval"! (0 = disabled, default = disabled).
-If you have no sensors which sends messages in regular intervals and/or you have low communication, the "aliveInterval" may restart the connection to the Homematic gateway to often.
-The "reconnectInterval" disables the "aliveInterval" and reconnects after a fixed period of time.
-Think in hours when configuring (one hour = 3600)
-
 - **timeout**
 The timeout in seconds for connections to a Homematic gateway (default = 15)
 
@@ -183,6 +171,11 @@ If set to true, devices are automatically unpaired from the gateway when their c
 If set to true, devices are automatically factory reset when their corresponding things are removed.
 Due to the factory reset, the device will also be unpaired from the gateway, even if "unpairOnDeletion" is set to false! (default = false)
 
+- **bufferSize** 
+If a large number of devices are connected to the gateway, the default buffersize of 2048 kB may be too small for communication with the gateway. 
+In this case, e.g. the discovery fails. 
+With this setting the buffer size can be adjusted. The value is specified in kB.
+
 The syntax for a bridge is:
 
 ```java
@@ -676,6 +669,11 @@ Var_1.sendCommand(RefreshType.REFRESH)
 **Note:** adding new and removing deleted variables from the GATEWAY-EXTRAS thing is currently not supported.
 You have to delete the thing, start a scan and add it again.
 
+**`openhab.log` contains an exception with message: `Buffering capacity 2097152 exceeded` resp. discovery detects no devices**
+
+In case of problems in the discovery or if above mentioned error message appears in `openhab.log`, the size for the transmission buffer for the communication with the gateway is too small.
+The problem can be solved by increasing the `bufferSize` value in the bridge configuration.
+
 ### Debugging and Tracing
 
 If you want to see what's going on in the binding, switch the log level to DEBUG in the Karaf console
index bd332a91e6ee328c62796df799a36338f886bce8..d90cc66addb266444be1123d838ecf8a3964d95c 100644 (file)
@@ -58,6 +58,7 @@ public class HomematicConfig {
     private long discoveryTimeToLive = -1;
     private boolean unpairOnDeletion = false;
     private boolean factoryResetOnDeletion = false;
+    private int bufferSize = 2048;
 
     private HmGatewayInfo gatewayInfo;
 
@@ -381,6 +382,13 @@ public class HomematicConfig {
         }
     }
 
+    /**
+     * Returns the buffers size used for the communication with the Homematic gateway.
+     */
+    public int getBufferSize() {
+        return bufferSize;
+    }
+
     /**
      * Returns true, if the configured gatewayType is CCU.
      */
index 444f4300c4402c1fb161decb792a2bc8b0a42070..977343afca0ffac1e31bda2499e01596d6098d50 100644 (file)
@@ -730,9 +730,6 @@ public abstract class AbstractHomematicGateway implements RpcEventListener, Home
             logger.debug("Echo event detected, ignoring '{}'", dpInfo);
         } else {
             try {
-                if (connectionTrackerThread != null && dpInfo.isPong() && id.equals(newValue)) {
-                    connectionTrackerThread.pongReceived();
-                }
                 if (initialized) {
                     final HmDatapoint dp = getDatapoint(dpInfo);
                     HmDatapointConfig config = gatewayAdapter.getDatapointConfig(dp);
@@ -900,32 +897,17 @@ public abstract class AbstractHomematicGateway implements RpcEventListener, Home
      */
     private class ConnectionTrackerThread implements Runnable {
         private boolean connectionLost;
-        private boolean ping;
-        private boolean pong;
 
         @Override
         public void run() {
             try {
-                if (ping && !pong) {
-                    handleInvalidConnection("No Pong received!");
-                }
-
-                pong = false;
-                if (config.getGatewayInfo().isCCU1()) {
-                    // the CCU1 does not support the ping command, we need a workaround
-                    getRpcClient(getDefaultInterface()).listBidcosInterfaces(getDefaultInterface());
-                    // if there is no exception, connection is valid
-                    pongReceived();
-                } else {
-                    getRpcClient(getDefaultInterface()).ping(getDefaultInterface(), id);
-                }
-                ping = true;
-
-                try {
-                    updateDutyCycleRatio();
-                } catch (IOException e) {
-                    logger.debug("Could not read the duty cycle ratio: {}", e.getMessage());
+                ListBidcosInterfacesParser parser = getRpcClient(getDefaultInterface())
+                        .listBidcosInterfaces(getDefaultInterface());
+                Integer dutyCycleRatio = parser.getDutyCycleRatio();
+                if (dutyCycleRatio != null) {
+                    gatewayAdapter.onDutyCycleRatioUpdate(dutyCycleRatio);
                 }
+                connectionConfirmed();
             } catch (IOException ex) {
                 try {
                     handleInvalidConnection("IOException " + ex.getMessage());
@@ -935,21 +917,6 @@ public abstract class AbstractHomematicGateway implements RpcEventListener, Home
             }
         }
 
-        public void pongReceived() {
-            pong = true;
-            connectionConfirmed();
-        }
-
-        private void updateDutyCycleRatio() throws IOException {
-            ListBidcosInterfacesParser parser = getRpcClient(getDefaultInterface())
-                    .listBidcosInterfaces(getDefaultInterface());
-            Integer dutyCycleRatio = parser.getDutyCycleRatio();
-
-            if (dutyCycleRatio != null) {
-                gatewayAdapter.onDutyCycleRatioUpdate(dutyCycleRatio);
-            }
-        }
-
         private void connectionConfirmed() {
             if (connectionLost) {
                 connectionLost = false;
@@ -959,7 +926,6 @@ public abstract class AbstractHomematicGateway implements RpcEventListener, Home
         }
 
         private void handleInvalidConnection(String cause) throws IOException {
-            ping = false;
             if (!connectionLost) {
                 connectionLost = true;
                 logger.warn("Connection lost on gateway '{}', cause: \"{}\"", id, cause);
index 040cd83675741e1d8cbf3903716c90e4a4a1ca7b..244c1891c47073362d634c703842f399ae3b6ec2 100644 (file)
@@ -88,7 +88,7 @@ public abstract class RpcClient<T> {
         request.addArg(getRpcCallbackUrl());
         request.addArg(clientId);
         if (config.getGatewayInfo().isHomegear()) {
-            request.addArg(new Integer(0x22));
+            request.addArg(Integer.valueOf(0x22));
         }
         sendMessage(config.getRpcPort(hmInterface), request);
     }
index 448c1d4b80b80a8c016126296c6e35d69b63e8d1..3d82937eb450a6b1d0063be14ea032fe81e12f01 100644 (file)
 package org.openhab.binding.homematic.internal.communicator.client;
 
 import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
@@ -24,12 +21,11 @@ import java.util.concurrent.TimeoutException;
 import javax.xml.parsers.ParserConfigurationException;
 
 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.api.Response;
 import org.eclipse.jetty.client.util.BytesContentProvider;
-import org.eclipse.jetty.client.util.InputStreamResponseListener;
+import org.eclipse.jetty.client.util.FutureResponseListener;
 import org.eclipse.jetty.http.HttpHeader;
-import org.eclipse.jetty.http.HttpStatus;
 import org.openhab.binding.homematic.internal.common.HomematicConfig;
 import org.openhab.binding.homematic.internal.communicator.message.RpcRequest;
 import org.openhab.binding.homematic.internal.communicator.message.XmlRpcRequest;
@@ -111,39 +107,18 @@ public class XmlRpcClient extends RpcClient<String> {
             }
             Request req = httpClient.POST(url).content(content).timeout(config.getTimeout(), TimeUnit.SECONDS)
                     .header(HttpHeader.CONTENT_TYPE, "text/xml;charset=" + config.getEncoding());
-            try {
-                ret = req.send().getContent();
-            } catch (IllegalArgumentException e) { // Returned buffer too large
-                logger.info("Blocking XmlRpcRequest failed: {}, trying non-blocking request", e.getMessage());
-                InputStreamResponseListener respListener = new InputStreamResponseListener();
-                req.send(respListener);
-                Response resp = respListener.get(config.getTimeout(), TimeUnit.SECONDS);
-                ByteArrayOutputStream respData = new ByteArrayOutputStream(RESP_BUFFER_SIZE);
-
-                int httpStatus = resp.getStatus();
-                if (httpStatus == HttpStatus.OK_200) {
-                    byte[] recvBuffer = new byte[RESP_BUFFER_SIZE];
-                    try (InputStream input = respListener.getInputStream()) {
-                        while (true) {
-                            int read = input.read(recvBuffer);
-                            if (read == -1) {
-                                break;
-                            }
-                            respData.write(recvBuffer, 0, read);
-                        }
-                        ret = respData.toByteArray();
-                    }
-                } else {
-                    logger.warn("Non-blocking XmlRpcRequest failed, status code: {} / request: {}", httpStatus,
-                            request);
-                    resp.abort(new IOException());
-                }
+            FutureResponseListener listener = new FutureResponseListener(req, config.getBufferSize() * 1024);
+            req.send(listener);
+            ContentResponse response = listener.get(config.getTimeout(), TimeUnit.SECONDS);
+            ret = response.getContent();
+            if (ret == null || ret.length == 0) {
+                throw new IOException("Received no data from the Homematic gateway");
             }
             if (logger.isTraceEnabled()) {
                 String result = new String(ret, config.getEncoding());
                 logger.trace("Client XmlRpcResponse (port {}):\n{}", port, result);
             }
-        } catch (UnsupportedEncodingException | ExecutionException | TimeoutException | InterruptedException e) {
+        } catch (InterruptedException | ExecutionException | TimeoutException | IllegalArgumentException e) {
             throw new IOException(e);
         }
         return ret;
index 5de0b8235b2a3de4c6a6dcaaf191a864d6cc718c..8f7b3b36849e8c62ac5234cef67922f562c17202 100644 (file)
@@ -221,7 +221,7 @@ public class BinRpcMessage implements RpcRequest<byte[]>, RpcResponse {
         int type = readInt();
         switch (type) {
             case 1:
-                return new Integer(readInt());
+                return Integer.valueOf(readInt());
             case 2:
                 return binRpcData[offset++] != 0 ? Boolean.TRUE : Boolean.FALSE;
             case 3:
@@ -235,7 +235,7 @@ public class BinRpcMessage implements RpcRequest<byte[]>, RpcResponse {
                 return new Date(readInt() * 1000);
             case 0xD1:
                 // Int64
-                return new Long(readInt64());
+                return Long.valueOf(readInt64());
             case 0x100:
                 // Array
                 int numElements = readInt();
index 0ed97cbf8115a15a882a4ebcb3f98e1699448d4e..e2e3006fd1b307b2c74b3c56dced59f514816bd6 100644 (file)
@@ -112,10 +112,10 @@ public class XmlRpcResponse implements RpcResponse {
                     break;
                 case "int":
                 case "i4":
-                    data.add(new Integer(currentValue));
+                    data.add(Integer.valueOf(currentValue));
                     break;
                 case "double":
-                    data.add(new Double(currentValue));
+                    data.add(Double.valueOf(currentValue));
                     break;
                 case "string":
                 case "name":
index 6c8fbf8d6e8e49c47dec6a957b81f430ec25ae25..cd8d9b8bd1705134705523efe34c37213795eddd 100644 (file)
                                <advanced>true</advanced>
                                <default>false</default>
                        </parameter>
-
+                       <parameter name="bufferSize" type="integer" min="0">
+                               <label>Buffer Size</label>
+                               <description>Size of the response buffer retrieved from the gateway (default 2048 kB)</description>
+                               <default>2048</default>
+                               <advanced>true</advanced>
+                       </parameter>
                </config-description>
        </bridge-type>