]> git.basschouten.com Git - openhab-addons.git/commitdiff
[freeboxos] Fix websocket registration (#17124)
authorlolodomo <lg.hc@free.fr>
Thu, 25 Jul 2024 07:38:26 +0000 (09:38 +0200)
committerGitHub <noreply@github.com>
Thu, 25 Jul 2024 07:38:26 +0000 (09:38 +0200)
Fix #17098

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
bundles/org.openhab.binding.freeboxos/src/main/java/org/openhab/binding/freeboxos/internal/api/rest/WebSocketManager.java

index 4ffb8678f7b7733af47c84c6fd9b8865c1de5809..99aca9298ff717236fbf8baed1cf90121a3e63e1 100644 (file)
@@ -60,6 +60,7 @@ public class WebSocketManager extends RestManager implements WebSocketListener {
     private static final String HOST_REACHABLE = "lan_host_l3addr_reachable";
     private static final String VM_CHANGED = "vm_state_changed";
     private static final Register REGISTRATION = new Register(VM_CHANGED, HOST_REACHABLE, HOST_UNREACHABLE);
+    private static final Register REGISTRATION_WITHOUT_VM = new Register(HOST_REACHABLE, HOST_UNREACHABLE);
     private static final String WS_PATH = "ws/event";
 
     private final Logger logger = LoggerFactory.getLogger(WebSocketManager.class);
@@ -69,6 +70,11 @@ public class WebSocketManager extends RestManager implements WebSocketListener {
     private final WebSocketClient client;
     private Optional<ScheduledFuture<?>> reconnectJob = Optional.empty();
     private volatile @Nullable Session wsSession;
+    @Nullable
+    private String sessionToken;
+    private int reconnectInterval;
+    private boolean vmSupported = true;
+    private boolean retryConnectWithoutVm = false;
 
     private record Register(String action, List<String> events) {
         Register(String... events) {
@@ -88,40 +94,45 @@ public class WebSocketManager extends RestManager implements WebSocketListener {
         UNKNOWN
     }
 
-    private static record WebSocketResponse(boolean success, Action action, String event, String source,
-            @Nullable JsonElement result) {
+    private static record WebSocketResponse(boolean success, @Nullable String msg, Action action, String event,
+            String source, @Nullable JsonElement result) {
         public String getEvent() {
             return source + "_" + event;
         }
     }
 
     public void openSession(@Nullable String sessionToken, int reconnectInterval) {
+        this.sessionToken = sessionToken;
+        this.reconnectInterval = reconnectInterval;
         if (reconnectInterval > 0) {
-            URI uri = getUriBuilder().scheme(getUriBuilder().build().getScheme().contains("s") ? "wss" : "ws").build();
-            ClientUpgradeRequest request = new ClientUpgradeRequest();
-            request.setHeader(ApiHandler.AUTH_HEADER, sessionToken);
             try {
                 client.start();
-                stopReconnect();
-                reconnectJob = Optional.of(scheduler.scheduleWithFixedDelay(() -> {
-                    try {
-                        closeSession();
-                        client.connect(this, uri, request);
-                        // Update listeners in case we would have lost data while disconnecting / reconnecting
-                        listeners.values()
-                                .forEach(host -> host.handleCommand(new ChannelUID(host.getThing().getUID(), REACHABLE),
-                                        RefreshType.REFRESH));
-                        logger.debug("Websocket manager connected to {}", uri);
-                    } catch (IOException e) {
-                        logger.warn("Error connecting websocket client: {}", e.getMessage());
-                    }
-                }, 0, reconnectInterval, TimeUnit.MINUTES));
+                startReconnect();
             } catch (Exception e) {
                 logger.warn("Error starting websocket client: {}", e.getMessage());
             }
         }
     }
 
+    private void startReconnect() {
+        URI uri = getUriBuilder().scheme(getUriBuilder().build().getScheme().contains("s") ? "wss" : "ws").build();
+        ClientUpgradeRequest request = new ClientUpgradeRequest();
+        request.setHeader(ApiHandler.AUTH_HEADER, sessionToken);
+        stopReconnect();
+        reconnectJob = Optional.of(scheduler.scheduleWithFixedDelay(() -> {
+            try {
+                closeSession();
+                client.connect(this, uri, request);
+                // Update listeners in case we would have lost data while disconnecting / reconnecting
+                listeners.values().forEach(host -> host
+                        .handleCommand(new ChannelUID(host.getThing().getUID(), REACHABLE), RefreshType.REFRESH));
+                logger.debug("Websocket manager connected to {}", uri);
+            } catch (IOException e) {
+                logger.warn("Error connecting websocket client: {}", e.getMessage());
+            }
+        }, 0, reconnectInterval, TimeUnit.MINUTES));
+    }
+
     private void stopReconnect() {
         reconnectJob.ifPresent(job -> job.cancel(true));
         reconnectJob = Optional.empty();
@@ -151,7 +162,8 @@ public class WebSocketManager extends RestManager implements WebSocketListener {
         this.wsSession = wsSession;
         logger.debug("Websocket connection establisehd");
         try {
-            wsSession.getRemote().sendString(apiHandler.serialize(REGISTRATION));
+            wsSession.getRemote()
+                    .sendString(apiHandler.serialize(vmSupported ? REGISTRATION : REGISTRATION_WITHOUT_VM));
         } catch (IOException e) {
             logger.warn("Error registering to websocket: {}", e.getMessage());
         }
@@ -159,6 +171,7 @@ public class WebSocketManager extends RestManager implements WebSocketListener {
 
     @Override
     public void onWebSocketText(@NonNullByDefault({}) String message) {
+        logger.debug("Websocket: received message: {}", message);
         Session localSession = wsSession;
         if (message.toLowerCase(Locale.US).contains("bye") && localSession != null) {
             localSession.close(StatusCode.NORMAL, "Thanks");
@@ -177,6 +190,12 @@ public class WebSocketManager extends RestManager implements WebSocketListener {
                 default:
                     logger.warn("Unhandled notification received: {}", result.action);
             }
+        } else if (result.action == Action.REGISTER) {
+            logger.debug("Event registration failed!");
+            if (vmSupported && "unsupported event vm_state_changed".equals(result.msg)) {
+                vmSupported = false;
+                retryConnectWithoutVm = true;
+            }
         }
     }
 
@@ -196,6 +215,9 @@ public class WebSocketManager extends RestManager implements WebSocketListener {
                     LanHost host = apiHandler.deserialize(LanHost.class, json.toString());
                     ApiConsumerHandler handler2 = listeners.get(host.getMac());
                     if (handler2 instanceof HostHandler hostHandler) {
+                        logger.debug("Received notification for mac {} : thing {} is {}reachable",
+                                host.getMac().toColonDelimitedString(), hostHandler.getThing().getUID(),
+                                host.reachable() ? "" : "not ");
                         hostHandler.updateConnectivityChannels(host);
                     }
                     break;
@@ -211,6 +233,11 @@ public class WebSocketManager extends RestManager implements WebSocketListener {
     public void onWebSocketClose(int statusCode, @NonNullByDefault({}) String reason) {
         logger.debug("Socket Closed: [{}] - reason {}", statusCode, reason);
         this.wsSession = null;
+        if (retryConnectWithoutVm) {
+            logger.debug("Retry connecting websocket client without VM support");
+            retryConnectWithoutVm = false;
+            startReconnect();
+        }
     }
 
     @Override