use of org.openhab.core.thing.binding.ThingHandlerCallback 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)));
}
use of org.openhab.core.thing.binding.ThingHandlerCallback in project openhab-core by openhab.
the class ThingManagerOSGiTest method thingManagerPostsThingStatusChangedEventsIfTheStatusOfAThingIsChanged.
@Test
public void thingManagerPostsThingStatusChangedEventsIfTheStatusOfAThingIsChanged() 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);
final List<ThingStatusInfoChangedEvent> infoChangedEvents = new ArrayList<>();
@NonNullByDefault EventSubscriber thingStatusEventSubscriber = 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(thingStatusEventSubscriber);
// add thing (UNINITIALIZED -> INITIALIZING)
managedThingProvider.add(thing);
waitForAssert(() -> assertThat(infoChangedEvents.size(), is(1)));
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).getOldStatusInfo().getStatus(), is(ThingStatus.UNINITIALIZED));
infoChangedEvents.clear();
// set status to ONLINE (INITIALIZING -> ONLINE)
ThingStatusInfo onlineNone = ThingStatusInfoBuilder.create(ThingStatus.ONLINE, ThingStatusDetail.NONE).build();
state.callback.statusUpdated(thing, onlineNone);
waitForAssert(() -> assertThat(infoChangedEvents.size(), is(1)));
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).getOldStatusInfo().getStatus(), is(ThingStatus.INITIALIZING));
infoChangedEvents.clear();
// set status to ONLINE again
state.callback.statusUpdated(thing, onlineNone);
// make sure no event has been sent
Thread.sleep(500);
assertThat(infoChangedEvents.size(), is(0));
}
use of org.openhab.core.thing.binding.ThingHandlerCallback in project openhab-core by openhab.
the class ThingManagerOSGiTest method thingManagerHandlesStateUpdatesCorrectly.
@Test
public void thingManagerHandlesStateUpdatesCorrectly() {
registerThingTypeProvider();
class ThingHandlerState {
boolean thingUpdatedWasCalled;
@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));
doAnswer(new Answer<Void>() {
@Override
@Nullable
public Void answer(InvocationOnMock invocation) throws Throwable {
state.thingUpdatedWasCalled = true;
return null;
}
}).when(thingHandler).thingUpdated(any(Thing.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);
// Create item
String itemName = "name";
Item item = new StringItem(itemName);
itemRegistry.add(item);
managedThingProvider.add(thing);
managedItemChannelLinkProvider.add(new ItemChannelLink(itemName, CHANNEL_UID));
state.callback.statusUpdated(thing, ThingStatusInfoBuilder.create(ThingStatus.ONLINE).build());
final List<Event> receivedEvents = new ArrayList<>();
@NonNullByDefault EventSubscriber itemUpdateEventSubscriber = new EventSubscriber() {
@Override
public void receive(Event event) {
receivedEvents.add(event);
}
@Override
public Set<String> getSubscribedEventTypes() {
return Set.of(ItemStateEvent.TYPE);
}
@Override
@Nullable
public EventFilter getEventFilter() {
return new TopicEventFilter("openhab/items/.*/state");
}
};
registerService(itemUpdateEventSubscriber);
// thing manager posts the update to the event bus via EventPublisher
state.callback.stateUpdated(CHANNEL_UID, new StringType("Value"));
waitForAssert(() -> assertThat(receivedEvents.size(), is(1)));
assertThat(receivedEvents.get(0), is(instanceOf(ItemStateEvent.class)));
ItemStateEvent itemUpdateEvent = (ItemStateEvent) receivedEvents.get(0);
assertThat(itemUpdateEvent.getTopic(), is("openhab/items/name/state"));
assertThat(itemUpdateEvent.getItemName(), is(itemName));
assertThat(itemUpdateEvent.getSource(), is(CHANNEL_UID.toString()));
assertThat(itemUpdateEvent.getItemState(), is(instanceOf(StringType.class)));
assertThat(itemUpdateEvent.getItemState(), is("Value"));
receivedEvents.clear();
Thing thing = ThingBuilder.create(THING_TYPE_UID, THING_UID).withChannel(ChannelBuilder.create(CHANNEL_UID, CoreItemFactory.SWITCH).build()).build();
managedThingProvider.update(thing);
state.callback.stateUpdated(CHANNEL_UID, new StringType("Value"));
waitForAssert(() -> assertThat(receivedEvents.size(), is(1)));
assertThat(receivedEvents.get(0), is(instanceOf(ItemStateEvent.class)));
itemUpdateEvent = (ItemStateEvent) receivedEvents.get(0);
assertThat(itemUpdateEvent.getTopic(), is("openhab/items/name/state"));
assertThat(itemUpdateEvent.getItemName(), is(itemName));
assertThat(itemUpdateEvent.getSource(), is(CHANNEL_UID.toString()));
assertThat(itemUpdateEvent.getItemState(), is(instanceOf(StringType.class)));
assertThat(itemUpdateEvent.getItemState(), is("Value"));
waitForAssert(() -> assertThat(state.thingUpdatedWasCalled, is(true)));
}
use of org.openhab.core.thing.binding.ThingHandlerCallback in project openhab-core by openhab.
the class ThingManagerOSGiTest method thingManagerCallsInitializeForAddedThingCorrectly.
@Test
public void thingManagerCallsInitializeForAddedThingCorrectly() {
// register ThingTypeProvider & ConfigurationDescriptionProvider with 'required' parameter
registerThingTypeProvider();
registerConfigDescriptionProvider(true);
ThingImpl thing = (ThingImpl) ThingBuilder.create(THING_TYPE_UID, THING_UID).build();
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);
ThingStatusInfo uninitializedNone = ThingStatusInfoBuilder.create(ThingStatus.UNINITIALIZED, ThingStatusDetail.NONE).build();
assertThat(thing.getStatusInfo(), is(uninitializedNone));
// add thing with empty configuration
managedThingProvider.add(thing);
// ThingHandler.initialize() not called, thing status is UNINITIALIZED.HANDLER_CONFIGURATION_PENDING
ThingStatusInfo uninitializedPending = ThingStatusInfoBuilder.create(ThingStatus.UNINITIALIZED, ThingStatusDetail.HANDLER_CONFIGURATION_PENDING).withDescription("@text/missing-or-invalid-configuration").build();
verify(thingHandler, never()).initialize();
assertThat(thing.getStatusInfo(), is(uninitializedPending));
// set required configuration parameter
Configuration configuration = new Configuration();
configuration.put("parameter", "value");
thing.setConfiguration(configuration);
ThingStatusInfo onlineNone = ThingStatusInfoBuilder.create(ThingStatus.ONLINE, ThingStatusDetail.NONE).build();
state.callback.configurationUpdated(thing);
state.callback.statusUpdated(thing, onlineNone);
// ThingHandler.initialize() called, thing status is ONLINE.NONE
waitForAssert(() -> {
verify(thingHandler, times(1)).initialize();
assertThat(thing.getStatusInfo(), is(onlineNone));
});
}
use of org.openhab.core.thing.binding.ThingHandlerCallback in project openhab-core by openhab.
the class ThingManagerOSGiTest method thingManagerHandlesThingStatusUpdatesOnlineAndOfflineCorrectly.
@Test
public void thingManagerHandlesThingStatusUpdatesOnlineAndOfflineCorrectly() {
class ThingHandlerState {
@Nullable
ThingHandlerCallback callback;
}
final ThingHandlerState state = new ThingHandlerState();
ThingHandler thingHandler = mock(ThingHandler.class);
managedThingProvider.add(thing);
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);
ThingStatusInfo statusInfo = ThingStatusInfoBuilder.create(ThingStatus.UNKNOWN, ThingStatusDetail.NONE).build();
state.callback.statusUpdated(thing, statusInfo);
assertThat(thing.getStatusInfo(), is(statusInfo));
statusInfo = ThingStatusInfoBuilder.create(ThingStatus.ONLINE, ThingStatusDetail.NONE).build();
state.callback.statusUpdated(thing, statusInfo);
assertThat(thing.getStatusInfo(), is(statusInfo));
statusInfo = ThingStatusInfoBuilder.create(ThingStatus.UNKNOWN, ThingStatusDetail.NONE).build();
state.callback.statusUpdated(thing, statusInfo);
assertThat(thing.getStatusInfo(), is(statusInfo));
statusInfo = ThingStatusInfoBuilder.create(ThingStatus.OFFLINE, ThingStatusDetail.NONE).build();
state.callback.statusUpdated(thing, statusInfo);
assertThat(thing.getStatusInfo(), is(statusInfo));
statusInfo = ThingStatusInfoBuilder.create(ThingStatus.UNKNOWN, ThingStatusDetail.NONE).build();
state.callback.statusUpdated(thing, statusInfo);
assertThat(thing.getStatusInfo(), is(statusInfo));
final ThingStatusInfo removingNone = ThingStatusInfoBuilder.create(ThingStatus.REMOVING, ThingStatusDetail.NONE).build();
expectException(() -> state.callback.statusUpdated(thing, removingNone), IllegalArgumentException.class);
final ThingStatusInfo uninitializedNone = ThingStatusInfoBuilder.create(ThingStatus.UNINITIALIZED, ThingStatusDetail.NONE).build();
expectException(() -> state.callback.statusUpdated(thing, uninitializedNone), IllegalArgumentException.class);
final ThingStatusInfo initializingNone = ThingStatusInfoBuilder.create(ThingStatus.INITIALIZING, ThingStatusDetail.NONE).build();
expectException(() -> state.callback.statusUpdated(thing, initializingNone), IllegalArgumentException.class);
thing.setStatusInfo(ThingStatusInfoBuilder.create(ThingStatus.ONLINE, ThingStatusDetail.NONE).build());
final ThingStatusInfo removedNone = ThingStatusInfoBuilder.create(ThingStatus.REMOVED, ThingStatusDetail.NONE).build();
expectException(() -> state.callback.statusUpdated(thing, removedNone), IllegalArgumentException.class);
}
Aggregations