[robonect] Fix `NullPointerException` on reinitialization (#15003)

* Fix NullPointerException on reinitialization

Fixes #15001
This commit is contained in:
Jacob Laursen 2023-06-18 09:06:19 +02:00 committed by GitHub
parent 801b860c59
commit 3c5ce72397
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 27 deletions

View File

@ -22,7 +22,7 @@ import org.openhab.core.thing.ThingTypeUID;
*/
public class RobonectBindingConstants {
private static final String BINDING_ID = "robonect";
public static final String BINDING_ID = "robonect";
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_AUTOMOWER = new ThingTypeUID(BINDING_ID, "mower");

View File

@ -12,12 +12,12 @@
*/
package org.openhab.binding.robonect.internal;
import static org.openhab.binding.robonect.internal.RobonectBindingConstants.THING_TYPE_AUTOMOWER;
import static org.openhab.binding.robonect.internal.RobonectBindingConstants.*;
import java.util.Collections;
import java.util.Set;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.robonect.internal.handler.RobonectHandler;
import org.openhab.core.i18n.TimeZoneProvider;
import org.openhab.core.io.net.http.HttpClientFactory;
@ -36,18 +36,19 @@ import org.osgi.service.component.annotations.Reference;
*
* @author Marco Meyer - Initial contribution
*/
@NonNullByDefault
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.robonect")
public class RobonectHandlerFactory extends BaseThingHandlerFactory {
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_AUTOMOWER);
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_AUTOMOWER);
private HttpClient httpClient;
private HttpClientFactory httpClientFactory;
private TimeZoneProvider timeZoneProvider;
@Activate
public RobonectHandlerFactory(@Reference HttpClientFactory httpClientFactory,
@Reference TimeZoneProvider timeZoneProvider) {
this.httpClient = httpClientFactory.getCommonHttpClient();
this.httpClientFactory = httpClientFactory;
this.timeZoneProvider = timeZoneProvider;
}
@ -57,11 +58,11 @@ public class RobonectHandlerFactory extends BaseThingHandlerFactory {
}
@Override
protected ThingHandler createHandler(Thing thing) {
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (thingTypeUID.equals(THING_TYPE_AUTOMOWER)) {
return new RobonectHandler(thing, httpClient, timeZoneProvider);
return new RobonectHandler(thing, httpClientFactory, timeZoneProvider);
}
return null;

View File

@ -38,6 +38,7 @@ import org.openhab.binding.robonect.internal.model.RobonectAnswer;
import org.openhab.binding.robonect.internal.model.VersionInfo;
import org.openhab.binding.robonect.internal.model.cmd.ModeCommand;
import org.openhab.core.i18n.TimeZoneProvider;
import org.openhab.core.io.net.http.HttpClientFactory;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
@ -50,6 +51,7 @@ import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.thing.util.ThingWebClientUtil;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
@ -80,9 +82,10 @@ public class RobonectHandler extends BaseThingHandler {
private RobonectClient robonectClient;
public RobonectHandler(Thing thing, HttpClient httpClient, TimeZoneProvider timeZoneProvider) {
public RobonectHandler(Thing thing, HttpClientFactory httpClientFactory, TimeZoneProvider timeZoneProvider) {
super(thing);
this.httpClient = httpClient;
httpClient = httpClientFactory
.createHttpClient(ThingWebClientUtil.buildWebClientConsumerName(thing.getUID(), null));
this.timeZoneProvider = timeZoneProvider;
}
@ -243,7 +246,7 @@ public class RobonectHandler extends BaseThingHandler {
if (info.getHealth() != null) {
updateState(CHANNEL_HEALTH_TEMP,
new QuantityType<>(info.getHealth().getTemperature(), SIUnits.CELSIUS));
updateState(CHANNEL_HEALTH_HUM, new QuantityType(info.getHealth().getHumidity(), Units.PERCENT));
updateState(CHANNEL_HEALTH_HUM, new QuantityType<>(info.getHealth().getHumidity(), Units.PERCENT));
}
if (info.getTimer() != null) {
if (info.getTimer().getNext() != null) {
@ -364,11 +367,12 @@ public class RobonectHandler extends BaseThingHandler {
try {
httpClient.start();
robonectClient = new RobonectClient(httpClient, endpoint);
} catch (Exception e) {
logger.error("Exception while trying to start http client", e);
throw new RuntimeException("Exception while trying to start http client", e);
logger.error("Exception while trying to start HTTP client", e);
throw new IllegalStateException("Could not create HttpClient");
}
robonectClient = new RobonectClient(httpClient, endpoint);
Runnable runnable = new MowerChannelPoller(TimeUnit.SECONDS.toMillis(robonectConfig.getOfflineTimeout()));
int pollInterval = robonectConfig.getPollInterval();
pollingJob = scheduler.scheduleWithFixedDelay(runnable, 0, pollInterval, TimeUnit.SECONDS);
@ -376,12 +380,17 @@ public class RobonectHandler extends BaseThingHandler {
@Override
public void dispose() {
ScheduledFuture<?> pollingJob = this.pollingJob;
if (pollingJob != null) {
pollingJob.cancel(true);
pollingJob = null;
this.pollingJob = null;
}
httpClient = null;
try {
httpClient.stop();
} catch (Exception e) {
logger.warn("Exception while trying to stop HTTP client", e);
}
}
/**

View File

@ -20,7 +20,6 @@ import java.time.Month;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import org.eclipse.jetty.client.HttpClient;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ -42,6 +41,7 @@ import org.openhab.binding.robonect.internal.model.Status;
import org.openhab.binding.robonect.internal.model.Timer;
import org.openhab.binding.robonect.internal.model.Wlan;
import org.openhab.core.i18n.TimeZoneProvider;
import org.openhab.core.io.net.http.HttpClientFactory;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
@ -69,16 +69,17 @@ public class RobonectHandlerTest {
private @Mock Thing robonectThingMock;
private @Mock RobonectClient robonectClientMock;
private @Mock ThingHandlerCallback callbackMock;
private @Mock HttpClient httpClientMock;
private @Mock HttpClientFactory httpClientFactoryMock;
private @Mock TimeZoneProvider timezoneProvider;
@BeforeEach
public void setUp() {
subject = new RobonectHandler(robonectThingMock, httpClientMock, timezoneProvider);
Mockito.when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3"));
Mockito.when(timezoneProvider.getTimeZone()).thenReturn(ZoneId.of("Europe/Berlin"));
subject = new RobonectHandler(robonectThingMock, httpClientFactoryMock, timezoneProvider);
subject.setCallback(callbackMock);
subject.setRobonectClient(robonectClientMock);
Mockito.when(timezoneProvider.getTimeZone()).thenReturn(ZoneId.of("Europe/Berlin"));
}
@Test
@ -97,7 +98,6 @@ public class RobonectHandlerTest {
// when
when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3"));
subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_TIMER_NEXT_TIMER),
RefreshType.REFRESH);
@ -141,7 +141,6 @@ public class RobonectHandlerTest {
// when
when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
when(robonectClientMock.errorList()).thenReturn(errorList);
when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3"));
subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS),
RefreshType.REFRESH);
@ -192,7 +191,6 @@ public class RobonectHandlerTest {
// when
when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3"));
subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS),
RefreshType.REFRESH);
@ -223,7 +221,6 @@ public class RobonectHandlerTest {
// when
when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3"));
subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS),
RefreshType.REFRESH);
@ -259,7 +256,6 @@ public class RobonectHandlerTest {
// when
when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
when(robonectClientMock.errorList()).thenReturn(errorList);
when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3"));
subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS),
RefreshType.REFRESH);