Fix error handling + migrate to the injected JAX-RS ClientBuilder (#15096)

Signed-off-by: Karel Goderis <karel.goderis@me.com>
This commit is contained in:
Karel Goderis 2023-06-23 20:53:03 +02:00 committed by GitHub
parent b193493f8e
commit 8a67d0ad94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 65 additions and 21 deletions

View 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 static org.openhab.binding.helios.internal.HeliosBindingConstants.HELIOS_VARIO_IP_2_21_TYPE;
import java.util.Set; 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.binding.helios.internal.handler.HeliosHandler221;
import org.openhab.core.thing.Thing; 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.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler; import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory; 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.Component;
import org.osgi.service.component.annotations.Reference;
/** /**
* The {@link HeliosHandlerFactory} is responsible for creating things and thing * 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") @Component(service = ThingHandlerFactory.class, configurationPid = "binding.helios")
public class HeliosHandlerFactory extends BaseThingHandlerFactory { 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 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 @Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) { public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
@ -45,7 +61,7 @@ public class HeliosHandlerFactory extends BaseThingHandlerFactory {
ThingTypeUID thingTypeUID = thing.getThingTypeUID(); ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (thingTypeUID.equals(HELIOS_VARIO_IP_2_21_TYPE)) { if (thingTypeUID.equals(HELIOS_VARIO_IP_2_21_TYPE)) {
return new HeliosHandler221(thing); return new HeliosHandler221(thing, clientBuilder);
} }
return null; return null;

View File

@ -34,6 +34,7 @@ import java.util.concurrent.TimeUnit;
import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager; import javax.net.ssl.X509TrustManager;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.client.Client; import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.ClientRequestContext;
@ -122,6 +123,7 @@ public class HeliosHandler221 extends BaseThingHandler {
// REST Client API variables // REST Client API variables
private Client heliosClient; private Client heliosClient;
private final ClientBuilder heliosClientBuilder;
private WebTarget baseTarget; private WebTarget baseTarget;
private WebTarget systemTarget; private WebTarget systemTarget;
private WebTarget logTarget; private WebTarget logTarget;
@ -139,8 +141,9 @@ public class HeliosHandler221 extends BaseThingHandler {
private long logSubscriptionID = 0; private long logSubscriptionID = 0;
public HeliosHandler221(Thing thing) { public HeliosHandler221(Thing thing, ClientBuilder heliosClientBuilder) {
super(thing); super(thing);
this.heliosClientBuilder = heliosClientBuilder;
} }
@Override @Override
@ -169,7 +172,7 @@ public class HeliosHandler221 extends BaseThingHandler {
logger.error("An exception occurred while initialising the SSL context : '{}'", e1.getMessage(), e1); 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 @Override
public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) { public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
return true; return true;
@ -177,19 +180,18 @@ public class HeliosHandler221 extends BaseThingHandler {
}).build(); }).build();
heliosClient.register(new Authenticator(username, password)); heliosClient.register(new Authenticator(username, password));
baseTarget = heliosClient.target(BASE_URI); baseTarget = heliosClient.target(BASE_URI.replace("{ip}", ipAddress));
systemTarget = baseTarget.path(SYSTEM_PATH); systemTarget = baseTarget.path(SYSTEM_PATH);
logTarget = baseTarget.path(LOG_PATH); logTarget = baseTarget.path(LOG_PATH);
switchTarget = baseTarget.path(SWITCH_PATH); switchTarget = baseTarget.path(SWITCH_PATH);
Response response = null; Response response = null;
try { try {
response = systemTarget.resolveTemplate("ip", ipAddress).resolveTemplate("cmd", INFO) response = systemTarget.resolveTemplate("cmd", INFO).request(MediaType.APPLICATION_JSON_TYPE).get();
.request(MediaType.APPLICATION_JSON_TYPE).get(); } catch (ProcessingException e) {
} catch (NullPointerException e) {
logger.debug("An exception occurred while fetching system info of the Helios IP Vario '{}' : '{}'", logger.debug("An exception occurred while fetching system info of the Helios IP Vario '{}' : '{}'",
getThing().getUID().toString(), e.getMessage(), e); 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); scheduler.schedule(resetRunnable, RESET_INTERVAL, TimeUnit.SECONDS);
return; return;
} }
@ -241,6 +243,11 @@ public class HeliosHandler221 extends BaseThingHandler {
@Override @Override
public void dispose() { public void dispose() {
logger.debug("Disposing the Helios IP Vario handler for '{}'.", getThing().getUID().toString()); 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) { if (logSubscriptionID != 0) {
unsubscribe(); unsubscribe();
@ -711,7 +718,7 @@ public class HeliosHandler221 extends BaseThingHandler {
protected Runnable resetRunnable = () -> { protected Runnable resetRunnable = () -> {
logger.debug("Resetting the Helios IP Vario handler for '{}'", getThing().getUID()); logger.debug("Resetting the Helios IP Vario handler for '{}'", getThing().getUID());
dispose(); tearDown();
initialize(); initialize();
}; };
@ -766,15 +773,26 @@ public class HeliosHandler221 extends BaseThingHandler {
ThingBuilder thingBuilder = editThing(); ThingBuilder thingBuilder = editThing();
ChannelTypeUID enablerUID = new ChannelTypeUID(BINDING_ID, SWITCH_ENABLER); ChannelTypeUID enablerUID = new ChannelTypeUID(BINDING_ID, SWITCH_ENABLER);
ChannelTypeUID triggerUID = new ChannelTypeUID(BINDING_ID, SWITCH_TRIGGER); ChannelTypeUID triggerUID = new ChannelTypeUID(BINDING_ID, SWITCH_TRIGGER);
ChannelUID activeSwitchChannelUID = new ChannelUID(getThing().getUID(),
"switch" + aSwitch.id + "active");
ChannelUID switchChannelUID = new ChannelUID(getThing().getUID(), "switch" + aSwitch.id);
Channel channel = ChannelBuilder if (this.getThing().getChannel(activeSwitchChannelUID) == null) {
.create(new ChannelUID(getThing().getUID(), "switch" + aSwitch.id + "active"), "Switch") logger.trace(
.withType(enablerUID).build(); "Adding a channel with id '{}' to the Helios IP Vario '{}' for the switch with id '{}'",
thingBuilder.withChannel(channel); activeSwitchChannelUID, getThing().getUID().toString(), aSwitch.id);
channel = ChannelBuilder Channel channel = ChannelBuilder.create(activeSwitchChannelUID, "Switch").withType(enablerUID)
.create(new ChannelUID(getThing().getUID(), "switch" + aSwitch.id), "Switch") .build();
.withType(triggerUID).build(); thingBuilder.withChannel(channel);
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()); updateThing(thingBuilder.build());
} }
} }
@ -788,14 +806,19 @@ public class HeliosHandler221 extends BaseThingHandler {
getThing().getUID().toString(), aPort.port); getThing().getUID().toString(), aPort.port);
ThingBuilder thingBuilder = editThing(); ThingBuilder thingBuilder = editThing();
ChannelTypeUID triggerUID = new ChannelTypeUID(BINDING_ID, IO_TRIGGER); ChannelTypeUID triggerUID = new ChannelTypeUID(BINDING_ID, IO_TRIGGER);
ChannelUID ioChannelUID = new ChannelUID(getThing().getUID(), "io" + aPort.port);
Map<String, String> channelProperties = new HashMap<>(); Map<String, String> channelProperties = new HashMap<>();
channelProperties.put("type", aPort.type); channelProperties.put("type", aPort.type);
Channel channel = ChannelBuilder if (this.getThing().getChannel(ioChannelUID) == null) {
.create(new ChannelUID(getThing().getUID(), "io" + aPort.port), "Switch").withType(triggerUID) logger.trace(
.withProperties(channelProperties).build(); "Adding a channel with id '{}' to the Helios IP Vario '{}' for the switch with id '{}'",
thingBuilder.withChannel(channel); ioChannelUID.getId(), getThing().getUID().toString(), aPort.port);
Channel channel = ChannelBuilder.create(ioChannelUID, "Switch").withType(triggerUID)
.withProperties(channelProperties).build();
thingBuilder.withChannel(channel);
}
updateThing(thingBuilder.build()); updateThing(thingBuilder.build());
} }
} }
@ -979,6 +1002,11 @@ public class HeliosHandler221 extends BaseThingHandler {
logger.trace("No events were retrieved"); 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) { } catch (Exception e) {
logger.error("An exception occurred while processing an event : '{}'", e.getMessage(), e); logger.error("An exception occurred while processing an event : '{}'", e.getMessage(), e);
} }