]> git.basschouten.com Git - openhab-addons.git/commitdiff
[yioremote] Fixed reconnection and thing creation issues (#8596)
authormiloit <MichaelLoercher@web.de>
Tue, 29 Sep 2020 17:48:11 +0000 (19:48 +0200)
committerGitHub <noreply@github.com>
Tue, 29 Sep 2020 17:48:11 +0000 (19:48 +0200)
Signed-off-by: Michael Loercher <MichaelLoercher@web.de>
bundles/org.openhab.binding.yioremote/README.md
bundles/org.openhab.binding.yioremote/src/main/java/org/openhab/binding/yioremote/internal/YIOremoteBindingConstants.java
bundles/org.openhab.binding.yioremote/src/main/java/org/openhab/binding/yioremote/internal/YIOremoteDockHandler.java
bundles/org.openhab.binding.yioremote/src/main/java/org/openhab/binding/yioremote/internal/utils/Websocket.java
bundles/org.openhab.binding.yioremote/src/main/java/org/openhab/binding/yioremote/internal/utils/WebsocketInterface.java

index 673ef6409ac0f0fe57bce13fafce6198161aef04..539009f45fac27ea349d94ed12b75d2b8dca9fe3 100644 (file)
@@ -8,7 +8,7 @@ Since this binding allows actual you to trigger IR send/receive actions on YIO D
 
 ## Supported Things
 
-* Thing Type ID: `yioremotedock`
+* Thing Type ID: `yioRemoteDock`
 
 The following are the configurations available to each of the bridges/things:
 
@@ -41,7 +41,7 @@ rule "yioremote Action Example"
 when
   ...
 then
-       val actions = getActions("yioremote", "yioremote:yioremotedock:livingroom")
+       val actions = getActions("yioremote", "yioremote:yioRemoteDock:livingroom")
        if (actions === null)
        {
                ......
@@ -58,22 +58,20 @@ end
 .things
 
 ```
-yioremote:yioremotedock:livingroom [   host="192.168.178.21",  accesstoken="0"  ]
+yioremote:yioRemoteDock:livingroom [   host="xxx.xxx.xxx.xxx", accesstoken="0"  ]
 ```
 
 .items
 
 ```
-String         sendircode              "IR CODE [%s]"                  {channel="yioremote:yioremotedock:livingroom:input#     sendircode"}
-Switch         receiverswitch  "IR recieving switch"   {channel="yioremote:yioremotedock:livingroom:input#     receiverswitch"}
-String         status                  "YIO Dock status[%s]"   {channel="yioremote:yioremotedock:livingroom:output#    status"}
+Switch         receiverswitch  "IR recieving switch"   {channel="yioremote:yioRemoteDock:livingroom:input#     receiverswitch"}
+String         status                  "YIO Dock status[%s]"   {channel="yioremote:yioRemoteDock:livingroom:output#    status"}
 ```
 
 .sitemap
 
 ```
 sitemap Basic label="YIO Dock" {
-        Text item=     sendircode
         Switch item=   receiverswitch
         Text item=     status
 }
index caef352e8fa7354aafce22cce1c57aa44ebe11c8..66ef1cc7e0a033e4873d4fece42faf7ef6424885 100644 (file)
@@ -33,7 +33,9 @@ public class YIOremoteBindingConstants {
         AUTHENTICATION_FAILED,
         AUTHENTICATION_COMPLETE,
         CONNECTION_FAILED,
-        CONNECTION_ESTABLISHED;
+        CONNECTION_ESTABLISHED,
+        COMMUNICATION_ERROR,
+        RECONNECTION_PROCESS;
     }
 
     public static enum YioRemoteMessages {
@@ -45,7 +47,7 @@ public class YIOremoteBindingConstants {
     }
 
     // List of all Thing Type UIDs
-    public static final ThingTypeUID THING_TYPE_YIOREMOTEDOCK = new ThingTypeUID(BINDING_ID, "yioremotedock");
+    public static final ThingTypeUID THING_TYPE_YIOREMOTEDOCK = new ThingTypeUID(BINDING_ID, "yioRemoteDock");
 
     // List of all Channel Groups Group Channel ids
     public static final String GROUP_INPUT = "input";
index 6b1f4518762e1500c534237a3279327a0f6202b1..c90a2cbaae251fd439d4ff4e84ed2fd319faeb90 100644 (file)
@@ -69,6 +69,7 @@ public class YIOremoteDockHandler extends BaseThingHandler {
     private @Nullable URI websocketAddress;
     private YioRemoteDockHandleStatus yioRemoteDockActualStatus = YioRemoteDockHandleStatus.UNINITIALIZED_STATE;
     private @Nullable Future<?> webSocketPollingJob;
+    private @Nullable Future<?> webSocketReconnectionPollingJob;
     public String receivedMessage = "";
     private JsonObject recievedJson = new JsonObject();
     private boolean heartBeat = false;
@@ -119,7 +120,10 @@ public class YIOremoteDockHandler extends BaseThingHandler {
                             switch (yioRemoteDockActualStatus) {
                                 case CONNECTION_ESTABLISHED:
                                 case AUTHENTICATION_PROCESS:
-                                    authenticate();
+                                    authenticateWebsocket();
+                                    break;
+                                case COMMUNICATION_ERROR:
+                                    reconnectWebsocket();
                                     break;
                                 default:
                                     break;
@@ -132,13 +136,15 @@ public class YIOremoteDockHandler extends BaseThingHandler {
                 }
 
                 @Override
-                public void onError() {
-                    if (webSocketPollingJob != null) {
-                        webSocketPollingJob.cancel(true);
-                    }
+                public void onClose() {
+                    reconnectWebsocket();
+                }
+
+                @Override
+                public void onError(Throwable cause) {
+                    yioRemoteDockActualStatus = YioRemoteDockHandleStatus.COMMUNICATION_ERROR;
                     updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                            "Connection lost no ping from YIO DOCK");
-                    updateState(GROUP_OUTPUT, STATUS_STRING_CHANNEL, UnDefType.UNDEF);
+                            "Communication lost no ping from YIO DOCK");
                 }
             });
 
@@ -174,8 +180,9 @@ public class YIOremoteDockHandler extends BaseThingHandler {
                         heartBeat = true;
                         success = true;
                     } else {
-                        if (irCodeSendHandler.getCode().equalsIgnoreCase("\"0;0x0;0;0\"")) {
+                        if (irCodeSendHandler.getCode().equalsIgnoreCase("0;0x0;0;0")) {
                             logger.debug("Send heartBeat Code success");
+                            receivedStatus = "Send heartBeat Code success";
                         } else {
                             receivedStatus = "Send IR Code failure";
                         }
@@ -242,8 +249,12 @@ public class YIOremoteDockHandler extends BaseThingHandler {
 
     @Override
     public void dispose() {
-        if (webSocketPollingJob != null) {
-            webSocketPollingJob.cancel(true);
+        disposeWebsocketPollingJob();
+        if (webSocketReconnectionPollingJob != null) {
+            if (!webSocketReconnectionPollingJob.isCancelled() && webSocketReconnectionPollingJob != null) {
+                webSocketReconnectionPollingJob.cancel(true);
+            }
+            webSocketReconnectionPollingJob = null;
         }
     }
 
@@ -287,7 +298,7 @@ public class YIOremoteDockHandler extends BaseThingHandler {
         updateState(id, new StringType(value));
     }
 
-    private void authenticate() {
+    private void authenticateWebsocket() {
         switch (yioRemoteDockActualStatus) {
             case CONNECTION_ESTABLISHED:
                 authenticationMessageHandler.setToken(localConfig.accessToken);
@@ -298,13 +309,15 @@ public class YIOremoteDockHandler extends BaseThingHandler {
                 if (authenticationOk) {
                     yioRemoteDockActualStatus = YioRemoteDockHandleStatus.AUTHENTICATION_COMPLETE;
                     updateStatus(ThingStatus.ONLINE);
-                    webSocketPollingJob = scheduler.scheduleWithFixedDelay(this::pollingWebsocket, 0, 30,
+                    webSocketPollingJob = scheduler.scheduleWithFixedDelay(this::pollingWebsocketJob, 0, 150,
                             TimeUnit.SECONDS);
                 } else {
                     yioRemoteDockActualStatus = YioRemoteDockHandleStatus.AUTHENTICATION_FAILED;
                 }
                 break;
             default:
+                disposeWebsocketPollingJob();
+                yioRemoteDockActualStatus = YioRemoteDockHandleStatus.COMMUNICATION_ERROR;
                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
                         "Connection lost no ping from YIO DOCK");
                 updateState(GROUP_OUTPUT, STATUS_STRING_CHANNEL, UnDefType.UNDEF);
@@ -312,7 +325,16 @@ public class YIOremoteDockHandler extends BaseThingHandler {
         }
     }
 
-    private void pollingWebsocket() {
+    private void disposeWebsocketPollingJob() {
+        if (webSocketPollingJob != null) {
+            if (!webSocketPollingJob.isCancelled() && webSocketPollingJob != null) {
+                webSocketPollingJob.cancel(true);
+            }
+            webSocketPollingJob = null;
+        }
+    }
+
+    private void pollingWebsocketJob() {
         switch (yioRemoteDockActualStatus) {
             case AUTHENTICATION_COMPLETE:
                 if (getAndResetHeartbeat()) {
@@ -321,19 +343,16 @@ public class YIOremoteDockHandler extends BaseThingHandler {
                     logger.debug("heartBeat ok");
                     sendMessage(YioRemoteMessages.HEARTBEAT_MESSAGE, "");
                 } else {
-                    yioRemoteDockActualStatus = YioRemoteDockHandleStatus.CONNECTION_FAILED;
+                    yioRemoteDockActualStatus = YioRemoteDockHandleStatus.COMMUNICATION_ERROR;
                     updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
                             "Connection lost no ping from YIO DOCK");
-                    updateState(GROUP_OUTPUT, STATUS_STRING_CHANNEL, UnDefType.UNDEF);
-                    if (webSocketPollingJob != null) {
-                        webSocketPollingJob.cancel(true);
-                    }
+                    disposeWebsocketPollingJob();
+                    reconnectWebsocket();
                 }
                 break;
             default:
-                if (webSocketPollingJob != null) {
-                    webSocketPollingJob.cancel(true);
-                }
+                disposeWebsocketPollingJob();
+                yioRemoteDockActualStatus = YioRemoteDockHandleStatus.COMMUNICATION_ERROR;
                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
                         "Connection lost no ping from YIO DOCK");
                 updateState(GROUP_OUTPUT, STATUS_STRING_CHANNEL, UnDefType.UNDEF);
@@ -347,6 +366,55 @@ public class YIOremoteDockHandler extends BaseThingHandler {
         return result;
     }
 
+    public void reconnectWebsocket() {
+        if (webSocketReconnectionPollingJob == null) {
+            webSocketReconnectionPollingJob = scheduler.scheduleWithFixedDelay(this::reconnectWebsocketJob, 0, 30,
+                    TimeUnit.SECONDS);
+        }
+    }
+
+    public void reconnectWebsocketJob() {
+        switch (yioRemoteDockActualStatus) {
+            case COMMUNICATION_ERROR:
+                logger.debug("Reconnecting YIORemoteHandler");
+                try {
+                    disposeWebsocketPollingJob();
+                    updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                            "Connection lost no ping from YIO DOCK");
+                    yioremoteDockwebSocketClient.closeWebsocketSession();
+                    webSocketClient.stop();
+                    yioRemoteDockActualStatus = YioRemoteDockHandleStatus.RECONNECTION_PROCESS;
+                } catch (Exception e) {
+                    logger.debug("Connection error {}", e.getMessage());
+                }
+                try {
+                    websocketAddress = new URI("ws://" + localConfig.host + ":946");
+                    yioRemoteDockActualStatus = YioRemoteDockHandleStatus.AUTHENTICATION_PROCESS;
+                } catch (URISyntaxException e) {
+                    updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR,
+                            "Initialize web socket failed: " + e.getMessage());
+                }
+                try {
+                    webSocketClient.start();
+                    webSocketClient.connect(yioremoteDockwebSocketClient, websocketAddress,
+                            yioremoteDockwebSocketClientrequest);
+                } catch (Exception e) {
+                    logger.debug("Connection error {}", e.getMessage());
+                }
+                break;
+            case AUTHENTICATION_COMPLETE:
+                if (webSocketReconnectionPollingJob != null) {
+                    if (!webSocketReconnectionPollingJob.isCancelled() && webSocketReconnectionPollingJob != null) {
+                        webSocketReconnectionPollingJob.cancel(true);
+                    }
+                    webSocketReconnectionPollingJob = null;
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
     public void sendMessage(YioRemoteMessages messageType, String messagePayload) {
         switch (messageType) {
             case AUTHENTICATE_MESSAGE:
index 13f40fdb86c1e845ffc81bf1b11be911e0d9ed5d..053292b6bb5ed03ad04f102565b07276c27e3c69 100644 (file)
@@ -17,6 +17,8 @@ import java.io.IOException;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.jetty.websocket.api.Session;
+import org.eclipse.jetty.websocket.api.StatusCode;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
 import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
 import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
 import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
@@ -61,7 +63,25 @@ public class Websocket {
     public void onError(Throwable cause) {
         logger.warn("WebSocketError {}", cause.getMessage());
         if (websocketHandler != null) {
-            websocketHandler.onError();
+            websocketHandler.onError(cause);
+        }
+    }
+
+    @OnWebSocketClose
+    public void onClose(int statusCode, String reason) {
+        if (statusCode != StatusCode.NORMAL) {
+            logger.debug("WebSocket Connection closed: {} - {}", statusCode, reason);
+        }
+        if (session != null) {
+            if (!session.isOpen()) {
+                if (session != null) {
+                    session.close();
+                }
+            }
+            session = null;
+        }
+        if (websocketHandler != null) {
+            websocketHandler.onClose();
         }
     }
 
@@ -74,4 +94,10 @@ public class Websocket {
             }
         }
     }
+
+    public void closeWebsocketSession() {
+        if (session != null) {
+            session.close();
+        }
+    }
 }
index 8002992b9008bbbec29bd870652407dad2318414..9ec02a08de5e8076065b1c616d787aef975f2161 100644 (file)
@@ -24,7 +24,9 @@ public interface WebsocketInterface {
 
     public void onConnect(boolean connected);
 
+    public void onClose();
+
     public void onMessage(String decodedmessage);
 
-    public void onError();
+    public void onError(Throwable cause);
 }