use of org.openhab.core.thing.binding.ThingHandlerFactory in project openhab-core by openhab.
the class ThingManagerImpl method setEnabled.
@Override
public void setEnabled(ThingUID thingUID, boolean enabled) {
Thing thing = getThing(thingUID);
persistThingEnableStatus(thingUID, enabled);
if (thing == null) {
logger.debug("Thing with the UID {} is unknown, cannot set its enabled status.", thingUID);
return;
}
if (enabled) {
// Enable a thing
if (thing.isEnabled()) {
logger.debug("Thing {} is already enabled.", thingUID);
return;
}
logger.debug("Thing {} will be enabled.", thingUID);
if (isHandlerRegistered(thing)) {
// A handler is already registered for that thing. Try to initialize it.
initializeHandler(thing);
} else {
// No handler registered. Try to register handler and initialize the thing.
registerAndInitializeHandler(thing, findThingHandlerFactory(thing.getThingTypeUID()));
// Check if registration was successful
if (!hasBridge(thing) && !isHandlerRegistered(thing)) {
setThingStatus(thing, buildStatusInfo(ThingStatus.UNINITIALIZED, ThingStatusDetail.HANDLER_MISSING_ERROR));
}
}
} else {
if (!thing.isEnabled()) {
logger.debug("Thing {} is already disabled.", thingUID);
return;
}
logger.debug("Thing {} will be disabled.", thingUID);
boolean disposed = false;
if (isHandlerRegistered(thing)) {
// Dispose handler if registered.
ThingHandler thingHandler = thing.getHandler();
ThingHandlerFactory thingHandlerFactory = findThingHandlerFactory(thing.getThingTypeUID());
if (thingHandler != null && thingHandlerFactory != null) {
unregisterAndDisposeHandler(thingHandlerFactory, thing, thingHandler);
disposed = true;
}
}
if (!disposed) {
// Only set the correct status to the thing. There is no handler to be disposed
setThingStatus(thing, buildStatusInfo(ThingStatus.UNINITIALIZED, ThingStatusDetail.DISABLED));
}
if (isBridge(thing)) {
updateChildThingStatusForDisabledBridges((Bridge) thing);
}
}
}
use of org.openhab.core.thing.binding.ThingHandlerFactory in project openhab-core by openhab.
the class ThingManagerImpl method getThingHandlerFactory.
@Nullable
private ThingHandlerFactory getThingHandlerFactory(Thing thing) {
ThingHandlerFactory thingHandlerFactory = findThingHandlerFactory(thing.getThingTypeUID());
if (thingHandlerFactory != null) {
return thingHandlerFactory;
}
logger.debug("Not registering a handler at this point since no handler factory for thing '{}' found.", thing.getUID());
return null;
}
use of org.openhab.core.thing.binding.ThingHandlerFactory in project openhab-core by openhab.
the class ThingManagerImpl method deactivate.
@Deactivate
protected synchronized void deactivate(ComponentContext componentContext) {
thingRegistry.removeThingTracker(this);
for (ThingHandlerFactory factory : thingHandlerFactories) {
removeThingHandlerFactory(factory);
}
readyService.unregisterTracker(this);
}
use of org.openhab.core.thing.binding.ThingHandlerFactory in project openhab-core by openhab.
the class ThingManagerOSGiTest method thingManagerHandlesBridgeThingHandlerLifeCycleCorrectly.
@Test
@SuppressWarnings("null")
public void thingManagerHandlesBridgeThingHandlerLifeCycleCorrectly() {
initCalledCounter = 0;
disposedCalledCounter = 0;
class BridgeHandlerState {
boolean initCalled;
int initCalledOrder;
boolean disposedCalled;
int disposedCalledOrder;
@Nullable
ThingHandlerCallback callback;
boolean callbackWasNull;
}
final BridgeHandlerState bridgeState = new BridgeHandlerState();
Bridge bridge = BridgeBuilder.create(new ThingTypeUID("binding:test"), new ThingUID("binding:test:someBridgeUID-1")).build();
BridgeHandler bridgeHandler = mock(BridgeHandler.class);
doAnswer(new Answer<Void>() {
@Override
@Nullable
public Void answer(InvocationOnMock invocation) throws Throwable {
bridgeState.callback = (ThingHandlerCallback) invocation.getArgument(0);
return null;
}
}).when(bridgeHandler).setCallback(any(ThingHandlerCallback.class));
doAnswer(new Answer<Void>() {
@Override
@Nullable
public Void answer(InvocationOnMock invocation) throws Throwable {
bridgeState.initCalled = true;
bridgeState.initCalledOrder = ++initCalledCounter;
bridgeState.callback.statusUpdated(bridge, ThingStatusInfoBuilder.create(ThingStatus.ONLINE, ThingStatusDetail.NONE).build());
return null;
}
}).when(bridgeHandler).initialize();
doAnswer(new Answer<Void>() {
@Override
@Nullable
public Void answer(InvocationOnMock invocation) throws Throwable {
bridgeState.disposedCalled = true;
bridgeState.disposedCalledOrder = ++disposedCalledCounter;
bridgeState.callbackWasNull = bridgeState.callback == null;
return null;
}
}).when(bridgeHandler).dispose();
when(bridgeHandler.getThing()).thenReturn(bridge);
doAnswer(new Answer<Void>() {
@Override
@Nullable
public Void answer(InvocationOnMock invocation) throws Throwable {
bridgeState.callback.statusUpdated(bridge, ThingStatusInfoBuilder.create(ThingStatus.REMOVED).build());
return null;
}
}).when(bridgeHandler).handleRemoval();
class ThingHandlerState {
boolean initCalled;
int initCalledOrder;
boolean disposedCalled;
int disposedCalledOrder;
@Nullable
ThingHandlerCallback callback;
boolean callbackWasNull;
}
final ThingHandlerState thingState = new ThingHandlerState();
Thing thing = ThingBuilder.create(new ThingTypeUID("binding:test"), new ThingUID("binding:test:someThingUID-1")).withBridge(bridge.getUID()).build();
ThingHandler thingHandler = mock(ThingHandler.class);
doAnswer(new Answer<Void>() {
@Override
@Nullable
public Void answer(InvocationOnMock invocation) throws Throwable {
thingState.callback = (ThingHandlerCallback) invocation.getArgument(0);
return null;
}
}).when(thingHandler).setCallback(any(ThingHandlerCallback.class));
doAnswer(new Answer<Void>() {
@Override
@Nullable
public Void answer(InvocationOnMock invocation) throws Throwable {
thingState.initCalled = true;
thingState.initCalledOrder = ++initCalledCounter;
bridgeState.callback.statusUpdated(thing, ThingStatusInfoBuilder.create(ThingStatus.ONLINE, ThingStatusDetail.NONE).build());
return null;
}
}).when(thingHandler).initialize();
doAnswer(new Answer<Void>() {
@Override
@Nullable
public Void answer(InvocationOnMock invocation) throws Throwable {
thingState.disposedCalled = true;
thingState.disposedCalledOrder = ++disposedCalledCounter;
thingState.callbackWasNull = thingState.callback == null;
return null;
}
}).when(thingHandler).dispose();
when(thingHandler.getThing()).thenReturn(thing);
doAnswer(new Answer<Void>() {
@Override
@Nullable
public Void answer(InvocationOnMock invocation) throws Throwable {
bridgeState.callback.statusUpdated(thing, ThingStatusInfoBuilder.create(ThingStatus.REMOVED).build());
return null;
}
}).when(thingHandler).handleRemoval();
ThingHandlerFactory thingHandlerFactory = mock(ThingHandlerFactory.class);
when(thingHandlerFactory.supportsThingType(any(ThingTypeUID.class))).thenReturn(true);
doAnswer(new Answer<ThingHandler>() {
@Override
@Nullable
public ThingHandler answer(InvocationOnMock invocation) throws Throwable {
Thing thing = (Thing) invocation.getArgument(0);
if (thing instanceof Bridge) {
return bridgeHandler;
} else if (thing instanceof Thing) {
return thingHandler;
}
return null;
}
}).when(thingHandlerFactory).registerHandler(any(Thing.class));
registerService(thingHandlerFactory);
final ThingStatusInfo uninitializedNone = ThingStatusInfoBuilder.create(ThingStatus.UNINITIALIZED, ThingStatusDetail.NONE).build();
assertThat(thing.getStatusInfo(), is(uninitializedNone));
assertThat(bridge.getStatusInfo(), is(uninitializedNone));
assertThat(bridgeState.initCalled, is(false));
assertThat(bridgeState.initCalledOrder, is(0));
assertThat(bridgeState.disposedCalled, is(false));
assertThat(bridgeState.disposedCalledOrder, is(0));
assertThat(thingState.initCalled, is(false));
assertThat(thingState.initCalledOrder, is(0));
assertThat(thingState.disposedCalled, is(false));
assertThat(thingState.disposedCalled, is(false));
assertThat(thingState.disposedCalledOrder, is(0));
ThingRegistry thingRegistry = getService(ThingRegistry.class);
assertThat(thingRegistry, not(nullValue()));
// add thing - no thing initialization, because bridge is not available
thingRegistry.add(thing);
waitForAssert(() -> assertThat(thingState.initCalled, is(false)));
final ThingStatusInfo bridgeUninitialized = ThingStatusInfoBuilder.create(ThingStatus.UNINITIALIZED, ThingStatusDetail.BRIDGE_UNINITIALIZED).build();
waitForAssert(() -> assertThat(thing.getStatusInfo(), is(bridgeUninitialized)));
// add bridge - provokes bridge & thing initialization
thingRegistry.add(bridge);
waitForAssert(() -> assertThat(bridgeState.initCalled, is(true)));
waitForAssert(() -> assertThat(bridgeState.initCalledOrder, is(1)));
waitForAssert(() -> assertThat(thingState.initCalled, is(true)));
waitForAssert(() -> assertThat(thingState.initCalledOrder, is(2)));
bridgeState.initCalled = false;
thingState.initCalled = false;
final ThingStatusInfo onlineNone = ThingStatusInfoBuilder.create(ThingStatus.ONLINE, ThingStatusDetail.NONE).build();
waitForAssert(() -> assertThat(thing.getStatusInfo(), is(onlineNone)));
waitForAssert(() -> assertThat(bridge.getStatusInfo(), is(onlineNone)));
// remove thing - provokes thing disposal
bridgeState.callbackWasNull = false;
thingState.callbackWasNull = false;
thingRegistry.remove(thing.getUID());
waitForAssert(() -> assertThat(thingState.disposedCalled, is(true)));
waitForAssert(() -> assertThat(thingState.disposedCalledOrder, is(1)));
thingState.disposedCalled = false;
waitForAssert(() -> assertThat(bridge.getStatusInfo(), is(onlineNone)));
final ThingStatusInfo thingUninitializedHandlerMissingError = ThingStatusInfoBuilder.create(ThingStatus.UNINITIALIZED, ThingStatusDetail.HANDLER_MISSING_ERROR).build();
waitForAssert(() -> assertThat(thing.getStatusInfo(), is(thingUninitializedHandlerMissingError)));
assertThat(thingState.callbackWasNull, is(false));
// add thing again - provokes thing initialization
thingRegistry.add(thing);
waitForAssert(() -> assertThat(thingState.initCalled, is(true)));
waitForAssert(() -> assertThat(thingState.initCalledOrder, is(3)));
thingState.initCalled = false;
waitForAssert(() -> assertThat(thing.getStatusInfo(), is(onlineNone)));
// remove bridge - provokes thing & bridge disposal
bridgeState.callbackWasNull = false;
thingState.callbackWasNull = false;
thingRegistry.remove(bridge.getUID());
waitForAssert(() -> assertThat(thingState.disposedCalled, is(true)));
waitForAssert(() -> assertThat(thingState.disposedCalledOrder, is(2)));
waitForAssert(() -> assertThat(bridgeState.disposedCalled, is(true)));
waitForAssert(() -> assertThat(bridgeState.disposedCalledOrder, is(3)));
thingState.disposedCalled = false;
bridgeState.disposedCalled = false;
waitForAssert(() -> assertThat(thing.getStatusInfo(), is(thingUninitializedHandlerMissingError)));
waitForAssert(() -> assertThat(bridge.getStatusInfo(), is(thingUninitializedHandlerMissingError)));
assertThat(bridgeState.callbackWasNull, is(false));
assertThat(thingState.callbackWasNull, is(false));
// add bridge again
thingRegistry.add(bridge);
waitForAssert(() -> assertThat(bridgeState.initCalled, is(true)));
waitForAssert(() -> assertThat(bridgeState.initCalledOrder, is(4)));
waitForAssert(() -> assertThat(thingState.initCalled, is(true)));
waitForAssert(() -> assertThat(thingState.initCalledOrder, is(5)));
bridgeState.initCalled = false;
thingState.initCalled = false;
waitForAssert(() -> assertThat(thing.getStatusInfo(), is(onlineNone)));
waitForAssert(() -> assertThat(bridge.getStatusInfo(), is(onlineNone)));
// unregister factory
bridgeState.callbackWasNull = false;
thingState.callbackWasNull = false;
unregisterService(thingHandlerFactory);
waitForAssert(() -> assertThat(thingState.disposedCalled, is(true)));
waitForAssert(() -> assertThat(thingState.disposedCalledOrder, is(4)));
waitForAssert(() -> assertThat(bridgeState.disposedCalled, is(true)));
waitForAssert(() -> assertThat(bridgeState.disposedCalledOrder, is(5)));
waitForAssert(() -> assertThat(thing.getStatusInfo(), is(thingUninitializedHandlerMissingError)));
waitForAssert(() -> assertThat(bridge.getStatusInfo(), is(thingUninitializedHandlerMissingError)));
assertThat(bridgeState.callbackWasNull, is(false));
assertThat(thingState.callbackWasNull, is(false));
}
use of org.openhab.core.thing.binding.ThingHandlerFactory in project openhab-core by openhab.
the class ThingManagerOSGiTest method thingManagerPostsLocalizedThingStatusInfoAndThingStatusInfoChangedEvents.
@Test
@SuppressWarnings("null")
public void thingManagerPostsLocalizedThingStatusInfoAndThingStatusInfoChangedEvents() throws Exception {
registerThingTypeProvider();
class ThingHandlerState {
@Nullable
ThingHandlerCallback callback;
}
final ThingHandlerState state = new ThingHandlerState();
ThingHandler thingHandler = mock(ThingHandler.class);
doAnswer(new Answer<Void>() {
@Override
@Nullable
public Void answer(InvocationOnMock invocation) throws Throwable {
state.callback = (ThingHandlerCallback) invocation.getArgument(0);
return null;
}
}).when(thingHandler).setCallback(any(ThingHandlerCallback.class));
when(thingHandler.getThing()).thenReturn(thing);
ThingHandlerFactory thingHandlerFactory = mock(ThingHandlerFactory.class);
when(thingHandlerFactory.supportsThingType(any(ThingTypeUID.class))).thenReturn(true);
when(thingHandlerFactory.registerHandler(any(Thing.class))).thenReturn(thingHandler);
registerService(thingHandlerFactory);
BundleResolver bundleResolver = mock(BundleResolver.class);
when(bundleResolver.resolveBundle(any())).thenReturn(bundleContext.getBundle());
ThingStatusInfoI18nLocalizationService thingStatusInfoI18nLocalizationService = getService(ThingStatusInfoI18nLocalizationService.class);
thingStatusInfoI18nLocalizationService.setBundleResolver(bundleResolver);
final List<ThingStatusInfoEvent> infoEvents = new ArrayList<>();
@NonNullByDefault EventSubscriber thingStatusInfoEventSubscriber = new EventSubscriber() {
@Override
public Set<String> getSubscribedEventTypes() {
return Set.of(ThingStatusInfoEvent.TYPE);
}
@Override
@Nullable
public EventFilter getEventFilter() {
return null;
}
@Override
public void receive(Event event) {
infoEvents.add((ThingStatusInfoEvent) event);
}
};
registerService(thingStatusInfoEventSubscriber);
final List<ThingStatusInfoChangedEvent> infoChangedEvents = new ArrayList<>();
@NonNullByDefault EventSubscriber thingStatusInfoChangedEventSubscriber = new EventSubscriber() {
@Override
public Set<String> getSubscribedEventTypes() {
return Set.of(ThingStatusInfoChangedEvent.TYPE);
}
@Override
@Nullable
public EventFilter getEventFilter() {
return null;
}
@Override
public void receive(Event event) {
infoChangedEvents.add((ThingStatusInfoChangedEvent) event);
}
};
registerService(thingStatusInfoChangedEventSubscriber);
// add thing (UNINITIALIZED -> INITIALIZING)
managedThingProvider.add(thing);
waitForAssert(() -> {
assertThat(infoEvents.size(), is(1));
assertThat(infoChangedEvents.size(), is(1));
});
assertThat(infoEvents.get(0).getType(), is(ThingStatusInfoEvent.TYPE));
assertThat(infoEvents.get(0).getTopic(), is("openhab/things/binding:type:id/status"));
assertThat(infoEvents.get(0).getStatusInfo().getStatus(), is(ThingStatus.INITIALIZING));
assertThat(infoEvents.get(0).getStatusInfo().getStatusDetail(), is(ThingStatusDetail.NONE));
assertThat(infoEvents.get(0).getStatusInfo().getDescription(), is(nullValue()));
assertThat(infoChangedEvents.get(0).getType(), is(ThingStatusInfoChangedEvent.TYPE));
assertThat(infoChangedEvents.get(0).getTopic(), is("openhab/things/binding:type:id/statuschanged"));
assertThat(infoChangedEvents.get(0).getStatusInfo().getStatus(), is(ThingStatus.INITIALIZING));
assertThat(infoChangedEvents.get(0).getStatusInfo().getStatusDetail(), is(ThingStatusDetail.NONE));
assertThat(infoChangedEvents.get(0).getStatusInfo().getDescription(), is(nullValue()));
assertThat(infoChangedEvents.get(0).getOldStatusInfo().getStatus(), is(ThingStatus.UNINITIALIZED));
assertThat(infoChangedEvents.get(0).getOldStatusInfo().getStatusDetail(), is(ThingStatusDetail.NONE));
assertThat(infoChangedEvents.get(0).getOldStatusInfo().getDescription(), is(nullValue()));
infoEvents.clear();
infoChangedEvents.clear();
LocaleProvider localeProvider = getService(LocaleProvider.class);
assertThat(localeProvider, is(notNullValue()));
Locale defaultLocale = localeProvider.getLocale();
// set status to ONLINE (INITIALIZING -> ONLINE)
new DefaultLocaleSetter(configurationAdmin).setDefaultLocale(Locale.ENGLISH);
waitForAssert(() -> assertThat(localeProvider.getLocale(), is(Locale.ENGLISH)));
ThingStatusInfo onlineNone = ThingStatusInfoBuilder.create(ThingStatus.ONLINE, ThingStatusDetail.NONE).withDescription("@text/online").build();
state.callback.statusUpdated(thing, onlineNone);
waitForAssert(() -> {
assertThat(infoEvents.size(), is(1));
assertThat(infoChangedEvents.size(), is(1));
});
assertThat(infoEvents.get(0).getType(), is(ThingStatusInfoEvent.TYPE));
assertThat(infoEvents.get(0).getTopic(), is("openhab/things/binding:type:id/status"));
assertThat(infoEvents.get(0).getStatusInfo().getStatus(), is(ThingStatus.ONLINE));
assertThat(infoEvents.get(0).getStatusInfo().getStatusDetail(), is(ThingStatusDetail.NONE));
assertThat(infoEvents.get(0).getStatusInfo().getDescription(), is("Thing is online."));
assertThat(infoChangedEvents.get(0).getType(), is(ThingStatusInfoChangedEvent.TYPE));
assertThat(infoChangedEvents.get(0).getTopic(), is("openhab/things/binding:type:id/statuschanged"));
assertThat(infoChangedEvents.get(0).getStatusInfo().getStatus(), is(ThingStatus.ONLINE));
assertThat(infoChangedEvents.get(0).getStatusInfo().getStatusDetail(), is(ThingStatusDetail.NONE));
assertThat(infoChangedEvents.get(0).getStatusInfo().getDescription(), is("Thing is online."));
assertThat(infoChangedEvents.get(0).getOldStatusInfo().getStatus(), is(ThingStatus.INITIALIZING));
assertThat(infoChangedEvents.get(0).getOldStatusInfo().getStatusDetail(), is(ThingStatusDetail.NONE));
assertThat(infoChangedEvents.get(0).getOldStatusInfo().getDescription(), is(nullValue()));
infoEvents.clear();
infoChangedEvents.clear();
// set status to OFFLINE (ONLINE -> OFFLINE)
new DefaultLocaleSetter(configurationAdmin).setDefaultLocale(Locale.GERMAN);
waitForAssert(() -> assertThat(localeProvider.getLocale(), is(Locale.GERMAN)));
ThingStatusInfo offlineNone = ThingStatusInfoBuilder.create(ThingStatus.OFFLINE, ThingStatusDetail.NONE).withDescription("@text/offline.without-param").build();
state.callback.statusUpdated(thing, offlineNone);
waitForAssert(() -> {
assertThat(infoEvents.size(), is(1));
assertThat(infoChangedEvents.size(), is(1));
});
assertThat(infoEvents.get(0).getType(), is(ThingStatusInfoEvent.TYPE));
assertThat(infoEvents.get(0).getTopic(), is("openhab/things/binding:type:id/status"));
assertThat(infoEvents.get(0).getStatusInfo().getStatus(), is(ThingStatus.OFFLINE));
assertThat(infoEvents.get(0).getStatusInfo().getStatusDetail(), is(ThingStatusDetail.NONE));
assertThat(infoEvents.get(0).getStatusInfo().getDescription(), is("Thing ist offline."));
assertThat(infoChangedEvents.get(0).getType(), is(ThingStatusInfoChangedEvent.TYPE));
assertThat(infoChangedEvents.get(0).getTopic(), is("openhab/things/binding:type:id/statuschanged"));
assertThat(infoChangedEvents.get(0).getStatusInfo().getStatus(), is(ThingStatus.OFFLINE));
assertThat(infoChangedEvents.get(0).getStatusInfo().getStatusDetail(), is(ThingStatusDetail.NONE));
assertThat(infoChangedEvents.get(0).getStatusInfo().getDescription(), is("Thing ist offline."));
assertThat(infoChangedEvents.get(0).getOldStatusInfo().getStatus(), is(ThingStatus.ONLINE));
assertThat(infoChangedEvents.get(0).getOldStatusInfo().getStatusDetail(), is(ThingStatusDetail.NONE));
assertThat(infoChangedEvents.get(0).getOldStatusInfo().getDescription(), is("Thing ist online."));
new DefaultLocaleSetter(configurationAdmin).setDefaultLocale(defaultLocale);
waitForAssert(() -> assertThat(localeProvider.getLocale(), is(defaultLocale)));
}
Aggregations