]> git.basschouten.com Git - openhab-addons.git/commitdiff
Fix error handling + migrate to the injected JAX-RS ClientBuilder (#15096)
authorKarel Goderis <karel.goderis@me.com>
Fri, 23 Jun 2023 18:53:03 +0000 (20:53 +0200)
committerGitHub <noreply@github.com>
Fri, 23 Jun 2023 18:53:03 +0000 (20:53 +0200)
Signed-off-by: Karel Goderis <karel.goderis@me.com>
bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/HeliosHandlerFactory.java
bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/handler/HeliosHandler221.java

index 03b448856b521a9d150df95da2aad8d0938cc7ca..586b550cf277db153610b77a05514ebd1081589d 100644 (file)
@@ -15,6 +15,9 @@ package org.openhab.binding.helios.internal;
 import static org.openhab.binding.helios.internal.HeliosBindingConstants.HELIOS_VARIO_IP_2_21_TYPE;
 
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.client.ClientBuilder;
 
 import org.openhab.binding.helios.internal.handler.HeliosHandler221;
 import org.openhab.core.thing.Thing;
@@ -22,7 +25,9 @@ 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.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
 
 /**
  * The {@link HeliosHandlerFactory} is responsible for creating things and thing
@@ -33,8 +38,19 @@ import org.osgi.service.component.annotations.Component;
 @Component(service = ThingHandlerFactory.class, configurationPid = "binding.helios")
 public class HeliosHandlerFactory extends BaseThingHandlerFactory {
 
+    private static final int EVENT_STREAM_CONNECT_TIMEOUT = 3;
+    private static final int EVENT_STREAM_READ_TIMEOUT = 200;
     private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(HELIOS_VARIO_IP_2_21_TYPE);
 
+    private final ClientBuilder clientBuilder;
+
+    @Activate
+    public HeliosHandlerFactory(@Reference ClientBuilder clientBuilder) {
+        this.clientBuilder = clientBuilder //
+                .connectTimeout(EVENT_STREAM_CONNECT_TIMEOUT, TimeUnit.SECONDS)
+                .readTimeout(EVENT_STREAM_READ_TIMEOUT, TimeUnit.SECONDS);
+    }
+
     @Override
     public boolean supportsThingType(ThingTypeUID thingTypeUID) {
         return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
@@ -45,7 +61,7 @@ public class HeliosHandlerFactory extends BaseThingHandlerFactory {
         ThingTypeUID thingTypeUID = thing.getThingTypeUID();
 
         if (thingTypeUID.equals(HELIOS_VARIO_IP_2_21_TYPE)) {
-            return new HeliosHandler221(thing);
+            return new HeliosHandler221(thing, clientBuilder);
         }
 
         return null;
index b7f8c1f3ae815d11e09b273b44ffde2e62cf46c9..7a88f0c151f6250dfb333cc6f593e7f29f646497 100644 (file)
@@ -34,6 +34,7 @@ import java.util.concurrent.TimeUnit;
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.X509TrustManager;
+import javax.ws.rs.ProcessingException;
 import javax.ws.rs.client.Client;
 import javax.ws.rs.client.ClientBuilder;
 import javax.ws.rs.client.ClientRequestContext;
@@ -122,6 +123,7 @@ public class HeliosHandler221 extends BaseThingHandler {
 
     // REST Client API variables
     private Client heliosClient;
+    private final ClientBuilder heliosClientBuilder;
     private WebTarget baseTarget;
     private WebTarget systemTarget;
     private WebTarget logTarget;
@@ -139,8 +141,9 @@ public class HeliosHandler221 extends BaseThingHandler {
 
     private long logSubscriptionID = 0;
 
-    public HeliosHandler221(Thing thing) {
+    public HeliosHandler221(Thing thing, ClientBuilder heliosClientBuilder) {
         super(thing);
+        this.heliosClientBuilder = heliosClientBuilder;
     }
 
     @Override
@@ -169,7 +172,7 @@ public class HeliosHandler221 extends BaseThingHandler {
                 logger.error("An exception occurred while initialising the SSL context : '{}'", e1.getMessage(), e1);
             }
 
-            heliosClient = ClientBuilder.newBuilder().sslContext(sslContext).hostnameVerifier(new HostnameVerifier() {
+            heliosClient = heliosClientBuilder.sslContext(sslContext).hostnameVerifier(new HostnameVerifier() {
                 @Override
                 public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
                     return true;
@@ -177,19 +180,18 @@ public class HeliosHandler221 extends BaseThingHandler {
             }).build();
             heliosClient.register(new Authenticator(username, password));
 
-            baseTarget = heliosClient.target(BASE_URI);
+            baseTarget = heliosClient.target(BASE_URI.replace("{ip}", ipAddress));
             systemTarget = baseTarget.path(SYSTEM_PATH);
             logTarget = baseTarget.path(LOG_PATH);
             switchTarget = baseTarget.path(SWITCH_PATH);
 
             Response response = null;
             try {
-                response = systemTarget.resolveTemplate("ip", ipAddress).resolveTemplate("cmd", INFO)
-                        .request(MediaType.APPLICATION_JSON_TYPE).get();
-            } catch (NullPointerException e) {
+                response = systemTarget.resolveTemplate("cmd", INFO).request(MediaType.APPLICATION_JSON_TYPE).get();
+            } catch (ProcessingException e) {
                 logger.debug("An exception occurred while fetching system info of the Helios IP Vario '{}' : '{}'",
                         getThing().getUID().toString(), e.getMessage(), e);
-                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
                 scheduler.schedule(resetRunnable, RESET_INTERVAL, TimeUnit.SECONDS);
                 return;
             }
@@ -241,6 +243,11 @@ public class HeliosHandler221 extends BaseThingHandler {
     @Override
     public void dispose() {
         logger.debug("Disposing the Helios IP Vario handler for '{}'.", getThing().getUID().toString());
+        tearDown();
+    }
+
+    private void tearDown() {
+        logger.debug("Tearing down the Helios IP Vario handler for '{}'.", getThing().getUID().toString());
 
         if (logSubscriptionID != 0) {
             unsubscribe();
@@ -711,7 +718,7 @@ public class HeliosHandler221 extends BaseThingHandler {
 
     protected Runnable resetRunnable = () -> {
         logger.debug("Resetting the Helios IP Vario handler for '{}'", getThing().getUID());
-        dispose();
+        tearDown();
         initialize();
     };
 
@@ -766,15 +773,26 @@ public class HeliosHandler221 extends BaseThingHandler {
                     ThingBuilder thingBuilder = editThing();
                     ChannelTypeUID enablerUID = new ChannelTypeUID(BINDING_ID, SWITCH_ENABLER);
                     ChannelTypeUID triggerUID = new ChannelTypeUID(BINDING_ID, SWITCH_TRIGGER);
-
-                    Channel channel = ChannelBuilder
-                            .create(new ChannelUID(getThing().getUID(), "switch" + aSwitch.id + "active"), "Switch")
-                            .withType(enablerUID).build();
-                    thingBuilder.withChannel(channel);
-                    channel = ChannelBuilder
-                            .create(new ChannelUID(getThing().getUID(), "switch" + aSwitch.id), "Switch")
-                            .withType(triggerUID).build();
-                    thingBuilder.withChannel(channel);
+                    ChannelUID activeSwitchChannelUID = new ChannelUID(getThing().getUID(),
+                            "switch" + aSwitch.id + "active");
+                    ChannelUID switchChannelUID = new ChannelUID(getThing().getUID(), "switch" + aSwitch.id);
+
+                    if (this.getThing().getChannel(activeSwitchChannelUID) == null) {
+                        logger.trace(
+                                "Adding a channel with id '{}' to the Helios IP Vario '{}' for the switch with id '{}'",
+                                activeSwitchChannelUID, getThing().getUID().toString(), aSwitch.id);
+                        Channel channel = ChannelBuilder.create(activeSwitchChannelUID, "Switch").withType(enablerUID)
+                                .build();
+                        thingBuilder.withChannel(channel);
+                    }
+                    if (this.getThing().getChannel(switchChannelUID) == null) {
+                        logger.trace(
+                                "Adding a channel with id '{}' to the Helios IP Vario '{}' for the switch with id '{}'",
+                                switchChannelUID, getThing().getUID().toString(), aSwitch.id);
+                        Channel channel = ChannelBuilder.create(switchChannelUID, "Switch").withType(triggerUID)
+                                .build();
+                        thingBuilder.withChannel(channel);
+                    }
                     updateThing(thingBuilder.build());
                 }
             }
@@ -788,14 +806,19 @@ public class HeliosHandler221 extends BaseThingHandler {
                         getThing().getUID().toString(), aPort.port);
                 ThingBuilder thingBuilder = editThing();
                 ChannelTypeUID triggerUID = new ChannelTypeUID(BINDING_ID, IO_TRIGGER);
+                ChannelUID ioChannelUID = new ChannelUID(getThing().getUID(), "io" + aPort.port);
 
                 Map<String, String> channelProperties = new HashMap<>();
                 channelProperties.put("type", aPort.type);
 
-                Channel channel = ChannelBuilder
-                        .create(new ChannelUID(getThing().getUID(), "io" + aPort.port), "Switch").withType(triggerUID)
-                        .withProperties(channelProperties).build();
-                thingBuilder.withChannel(channel);
+                if (this.getThing().getChannel(ioChannelUID) == null) {
+                    logger.trace(
+                            "Adding a channel with id '{}' to the Helios IP Vario '{}' for the switch with id '{}'",
+                            ioChannelUID.getId(), getThing().getUID().toString(), aPort.port);
+                    Channel channel = ChannelBuilder.create(ioChannelUID, "Switch").withType(triggerUID)
+                            .withProperties(channelProperties).build();
+                    thingBuilder.withChannel(channel);
+                }
                 updateThing(thingBuilder.build());
             }
         }
@@ -979,6 +1002,11 @@ public class HeliosHandler221 extends BaseThingHandler {
                             logger.trace("No events were retrieved");
                         }
                     }
+                } catch (ProcessingException e) {
+                    updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
+                    logger.trace("An underlying exception forced the Helios IP Vario to go offline : '{}'",
+                            e.getMessage(), e);
+                    scheduler.schedule(resetRunnable, RESET_INTERVAL, TimeUnit.SECONDS);
                 } catch (Exception e) {
                     logger.error("An exception occurred while processing an event : '{}'", e.getMessage(), e);
                 }