[robonect] Fix `NullPointerException` on reinitialization (#15003)
* Fix NullPointerException on reinitialization Fixes #15001
This commit is contained in:
parent
801b860c59
commit
3c5ce72397
|
@ -22,7 +22,7 @@ import org.openhab.core.thing.ThingTypeUID;
|
||||||
*/
|
*/
|
||||||
public class RobonectBindingConstants {
|
public class RobonectBindingConstants {
|
||||||
|
|
||||||
private static final String BINDING_ID = "robonect";
|
public static final String BINDING_ID = "robonect";
|
||||||
|
|
||||||
// List of all Thing Type UIDs
|
// List of all Thing Type UIDs
|
||||||
public static final ThingTypeUID THING_TYPE_AUTOMOWER = new ThingTypeUID(BINDING_ID, "mower");
|
public static final ThingTypeUID THING_TYPE_AUTOMOWER = new ThingTypeUID(BINDING_ID, "mower");
|
||||||
|
|
|
@ -12,12 +12,12 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.robonect.internal;
|
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 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.binding.robonect.internal.handler.RobonectHandler;
|
||||||
import org.openhab.core.i18n.TimeZoneProvider;
|
import org.openhab.core.i18n.TimeZoneProvider;
|
||||||
import org.openhab.core.io.net.http.HttpClientFactory;
|
import org.openhab.core.io.net.http.HttpClientFactory;
|
||||||
|
@ -36,18 +36,19 @@ import org.osgi.service.component.annotations.Reference;
|
||||||
*
|
*
|
||||||
* @author Marco Meyer - Initial contribution
|
* @author Marco Meyer - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.robonect")
|
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.robonect")
|
||||||
public class RobonectHandlerFactory extends BaseThingHandlerFactory {
|
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;
|
private TimeZoneProvider timeZoneProvider;
|
||||||
|
|
||||||
@Activate
|
@Activate
|
||||||
public RobonectHandlerFactory(@Reference HttpClientFactory httpClientFactory,
|
public RobonectHandlerFactory(@Reference HttpClientFactory httpClientFactory,
|
||||||
@Reference TimeZoneProvider timeZoneProvider) {
|
@Reference TimeZoneProvider timeZoneProvider) {
|
||||||
this.httpClient = httpClientFactory.getCommonHttpClient();
|
this.httpClientFactory = httpClientFactory;
|
||||||
this.timeZoneProvider = timeZoneProvider;
|
this.timeZoneProvider = timeZoneProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,11 +58,11 @@ public class RobonectHandlerFactory extends BaseThingHandlerFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ThingHandler createHandler(Thing thing) {
|
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||||
|
|
||||||
if (thingTypeUID.equals(THING_TYPE_AUTOMOWER)) {
|
if (thingTypeUID.equals(THING_TYPE_AUTOMOWER)) {
|
||||||
return new RobonectHandler(thing, httpClient, timeZoneProvider);
|
return new RobonectHandler(thing, httpClientFactory, timeZoneProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -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.VersionInfo;
|
||||||
import org.openhab.binding.robonect.internal.model.cmd.ModeCommand;
|
import org.openhab.binding.robonect.internal.model.cmd.ModeCommand;
|
||||||
import org.openhab.core.i18n.TimeZoneProvider;
|
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.DateTimeType;
|
||||||
import org.openhab.core.library.types.DecimalType;
|
import org.openhab.core.library.types.DecimalType;
|
||||||
import org.openhab.core.library.types.OnOffType;
|
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.ThingStatus;
|
||||||
import org.openhab.core.thing.ThingStatusDetail;
|
import org.openhab.core.thing.ThingStatusDetail;
|
||||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
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.Command;
|
||||||
import org.openhab.core.types.RefreshType;
|
import org.openhab.core.types.RefreshType;
|
||||||
import org.openhab.core.types.State;
|
import org.openhab.core.types.State;
|
||||||
|
@ -80,9 +82,10 @@ public class RobonectHandler extends BaseThingHandler {
|
||||||
|
|
||||||
private RobonectClient robonectClient;
|
private RobonectClient robonectClient;
|
||||||
|
|
||||||
public RobonectHandler(Thing thing, HttpClient httpClient, TimeZoneProvider timeZoneProvider) {
|
public RobonectHandler(Thing thing, HttpClientFactory httpClientFactory, TimeZoneProvider timeZoneProvider) {
|
||||||
super(thing);
|
super(thing);
|
||||||
this.httpClient = httpClient;
|
httpClient = httpClientFactory
|
||||||
|
.createHttpClient(ThingWebClientUtil.buildWebClientConsumerName(thing.getUID(), null));
|
||||||
this.timeZoneProvider = timeZoneProvider;
|
this.timeZoneProvider = timeZoneProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +246,7 @@ public class RobonectHandler extends BaseThingHandler {
|
||||||
if (info.getHealth() != null) {
|
if (info.getHealth() != null) {
|
||||||
updateState(CHANNEL_HEALTH_TEMP,
|
updateState(CHANNEL_HEALTH_TEMP,
|
||||||
new QuantityType<>(info.getHealth().getTemperature(), SIUnits.CELSIUS));
|
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() != null) {
|
||||||
if (info.getTimer().getNext() != null) {
|
if (info.getTimer().getNext() != null) {
|
||||||
|
@ -364,11 +367,12 @@ public class RobonectHandler extends BaseThingHandler {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
httpClient.start();
|
httpClient.start();
|
||||||
robonectClient = new RobonectClient(httpClient, endpoint);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("Exception while trying to start http client", e);
|
logger.error("Exception while trying to start HTTP client", e);
|
||||||
throw new RuntimeException("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()));
|
Runnable runnable = new MowerChannelPoller(TimeUnit.SECONDS.toMillis(robonectConfig.getOfflineTimeout()));
|
||||||
int pollInterval = robonectConfig.getPollInterval();
|
int pollInterval = robonectConfig.getPollInterval();
|
||||||
pollingJob = scheduler.scheduleWithFixedDelay(runnable, 0, pollInterval, TimeUnit.SECONDS);
|
pollingJob = scheduler.scheduleWithFixedDelay(runnable, 0, pollInterval, TimeUnit.SECONDS);
|
||||||
|
@ -376,12 +380,17 @@ public class RobonectHandler extends BaseThingHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
|
ScheduledFuture<?> pollingJob = this.pollingJob;
|
||||||
if (pollingJob != null) {
|
if (pollingJob != null) {
|
||||||
pollingJob.cancel(true);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -20,7 +20,6 @@ import java.time.Month;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
import org.eclipse.jetty.client.HttpClient;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
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.Timer;
|
||||||
import org.openhab.binding.robonect.internal.model.Wlan;
|
import org.openhab.binding.robonect.internal.model.Wlan;
|
||||||
import org.openhab.core.i18n.TimeZoneProvider;
|
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.DateTimeType;
|
||||||
import org.openhab.core.library.types.DecimalType;
|
import org.openhab.core.library.types.DecimalType;
|
||||||
import org.openhab.core.library.types.OnOffType;
|
import org.openhab.core.library.types.OnOffType;
|
||||||
|
@ -69,16 +69,17 @@ public class RobonectHandlerTest {
|
||||||
private @Mock Thing robonectThingMock;
|
private @Mock Thing robonectThingMock;
|
||||||
private @Mock RobonectClient robonectClientMock;
|
private @Mock RobonectClient robonectClientMock;
|
||||||
private @Mock ThingHandlerCallback callbackMock;
|
private @Mock ThingHandlerCallback callbackMock;
|
||||||
private @Mock HttpClient httpClientMock;
|
private @Mock HttpClientFactory httpClientFactoryMock;
|
||||||
private @Mock TimeZoneProvider timezoneProvider;
|
private @Mock TimeZoneProvider timezoneProvider;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setUp() {
|
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.setCallback(callbackMock);
|
||||||
subject.setRobonectClient(robonectClientMock);
|
subject.setRobonectClient(robonectClientMock);
|
||||||
|
|
||||||
Mockito.when(timezoneProvider.getTimeZone()).thenReturn(ZoneId.of("Europe/Berlin"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -97,7 +98,6 @@ public class RobonectHandlerTest {
|
||||||
|
|
||||||
// when
|
// when
|
||||||
when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
|
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),
|
subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_TIMER_NEXT_TIMER),
|
||||||
RefreshType.REFRESH);
|
RefreshType.REFRESH);
|
||||||
|
@ -141,7 +141,6 @@ public class RobonectHandlerTest {
|
||||||
// when
|
// when
|
||||||
when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
|
when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
|
||||||
when(robonectClientMock.errorList()).thenReturn(errorList);
|
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),
|
subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS),
|
||||||
RefreshType.REFRESH);
|
RefreshType.REFRESH);
|
||||||
|
@ -192,7 +191,6 @@ public class RobonectHandlerTest {
|
||||||
|
|
||||||
// when
|
// when
|
||||||
when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
|
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),
|
subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS),
|
||||||
RefreshType.REFRESH);
|
RefreshType.REFRESH);
|
||||||
|
@ -223,7 +221,6 @@ public class RobonectHandlerTest {
|
||||||
|
|
||||||
// when
|
// when
|
||||||
when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
|
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),
|
subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS),
|
||||||
RefreshType.REFRESH);
|
RefreshType.REFRESH);
|
||||||
|
@ -259,7 +256,6 @@ public class RobonectHandlerTest {
|
||||||
// when
|
// when
|
||||||
when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
|
when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
|
||||||
when(robonectClientMock.errorList()).thenReturn(errorList);
|
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),
|
subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS),
|
||||||
RefreshType.REFRESH);
|
RefreshType.REFRESH);
|
||||||
|
|
Loading…
Reference in New Issue