2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.wundergroundupdatereceiver.internal;
15 import static org.hamcrest.MatcherAssert.assertThat;
16 import static org.hamcrest.Matchers.*;
17 import static org.hamcrest.core.Is.is;
18 import static org.mockito.Mockito.*;
19 import static org.mockito.MockitoAnnotations.openMocks;
20 import static org.openhab.binding.wundergroundupdatereceiver.internal.WundergroundUpdateReceiverBindingConstants.*;
22 import java.io.IOException;
23 import java.util.Arrays;
24 import java.util.List;
26 import java.util.stream.Collectors;
28 import javax.servlet.ServletException;
29 import javax.servlet.http.HttpServletResponse;
31 import org.eclipse.jdt.annotation.NonNullByDefault;
32 import org.eclipse.jetty.http.HttpFields;
33 import org.eclipse.jetty.http.HttpURI;
34 import org.eclipse.jetty.http.HttpVersion;
35 import org.eclipse.jetty.http.MetaData;
36 import org.eclipse.jetty.server.HttpChannel;
37 import org.eclipse.jetty.server.Request;
38 import org.hamcrest.Matcher;
39 import org.junit.jupiter.api.BeforeEach;
40 import org.junit.jupiter.api.Test;
41 import org.mockito.Answers;
42 import org.openhab.core.config.core.Configuration;
43 import org.openhab.core.thing.Channel;
44 import org.openhab.core.thing.ChannelUID;
45 import org.openhab.core.thing.DefaultSystemChannelTypeProvider;
46 import org.openhab.core.thing.ManagedThingProvider;
47 import org.openhab.core.thing.Thing;
48 import org.openhab.core.thing.ThingUID;
49 import org.openhab.core.thing.binding.ThingHandlerCallback;
50 import org.openhab.core.thing.binding.builder.ThingBuilder;
51 import org.openhab.core.thing.internal.type.StateChannelTypeBuilderImpl;
52 import org.openhab.core.thing.internal.type.TriggerChannelTypeBuilderImpl;
53 import org.openhab.core.thing.type.ChannelKind;
54 import org.openhab.core.thing.type.ChannelTypeProvider;
55 import org.openhab.core.thing.type.ChannelTypeRegistry;
56 import org.openhab.core.thing.type.ChannelTypeUID;
57 import org.osgi.service.http.NamespaceException;
60 * @author Daniel Demus - Initial contribution
63 class WundergroundUpdateReceiverDiscoveryServiceTest {
65 private static final String STATION_ID_1 = "abcd1234";
66 private static final String REQ_STATION_ID = "dfggger";
67 private static final ThingUID TEST_THING_UID = new ThingUID(THING_TYPE_UPDATE_RECEIVER, "test-receiver");
75 void programmaticChannelsAreAddedCorrectlyOnce() {
77 final String queryString = """
83 dateutc=2021-02-07%2014:04:03&\
84 softwaretype=WH2600%20V2.2.8&\
89 MetaData.Request request = new MetaData.Request("GET",
90 new HttpURI("http://localhost" + WundergroundUpdateReceiverServlet.SERVLET_URL + "?" + queryString),
91 HttpVersion.HTTP_1_1, new HttpFields());
92 HttpChannel httpChannel = mock(HttpChannel.class);
93 Request req = new Request(httpChannel, null);
94 req.setMetaData(request);
96 TestChannelTypeRegistry channelTypeRegistry = new TestChannelTypeRegistry();
97 WundergroundUpdateReceiverDiscoveryService discoveryService = new WundergroundUpdateReceiverDiscoveryService(
99 WundergroundUpdateReceiverServlet sut = new WundergroundUpdateReceiverServlet(discoveryService);
100 discoveryService.addUnhandledStationId(REQ_STATION_ID, sut.normalizeParameterMap(req.getParameterMap()));
101 Thing thing = ThingBuilder.create(SUPPORTED_THING_TYPES_UIDS.stream().findFirst().get(), TEST_THING_UID)
102 .withConfiguration(new Configuration(Map.of(REPRESENTATION_PROPERTY, REQ_STATION_ID)))
103 .withLabel("test thing").withLocation("location").build();
104 ManagedThingProvider managedThingProvider = mock(ManagedThingProvider.class);
105 when(managedThingProvider.get(any())).thenReturn(thing);
106 WundergroundUpdateReceiverHandler handler = new WundergroundUpdateReceiverHandler(thing, sut, discoveryService,
107 new WundergroundUpdateReceiverUnknownChannelTypeProvider(), channelTypeRegistry, managedThingProvider);
108 handler.setCallback(mock(ThingHandlerCallback.class));
111 handler.initialize();
112 var actual = handler.getThing().getChannels();
115 assertThat(actual.size(), is(9));
117 assertChannel(actual, METADATA_GROUP, LAST_RECEIVED, LAST_RECEIVED_DATETIME_CHANNELTYPEUID, ChannelKind.STATE,
119 assertChannel(actual, METADATA_GROUP, LAST_QUERY_TRIGGER, LAST_QUERY_TRIGGER_CHANNELTYPEUID,
120 ChannelKind.TRIGGER, nullValue());
121 assertChannel(actual, METADATA_GROUP, LAST_QUERY_STATE, LAST_QUERY_STATE_CHANNELTYPEUID, ChannelKind.STATE,
123 assertChannel(actual, METADATA_GROUP, DATEUTC, DATEUTC_CHANNELTYPEUID, ChannelKind.STATE, is("String"));
124 assertChannel(actual, METADATA_GROUP, REALTIME_FREQUENCY, REALTIME_FREQUENCY_CHANNELTYPEUID, ChannelKind.STATE,
126 assertChannel(actual, METADATA_GROUP, SOFTWARE_TYPE, SOFTWARETYPE_CHANNELTYPEUID, ChannelKind.STATE,
128 assertChannel(actual, HUMIDITY_GROUP, HUMIDITY, HUMIDITY_CHANNELTYPEUID, ChannelKind.STATE,
129 is("Number:Dimensionless"));
130 assertChannel(actual, WIND_GROUP, WIND_SPEED_AVG_2MIN, WIND_SPEED_AVG_2MIN_CHANNELTYPEUID, ChannelKind.STATE,
132 assertChannel(actual, POLLUTION_GROUP, AQ_PM2_5, PM2_5_MASS_CHANNELTYPEUID, ChannelKind.STATE,
133 is("Number:Density"));
137 void aRequestWithAnUnregisteredStationidIsAddedToTheQueueOnce()
138 throws ServletException, NamespaceException, IOException {
140 final String queryString = """
155 solarradiation=42.24&\
156 UV=1&indoortempf=69.3&\
161 dateutc=2021-02-07%2014:04:03&\
162 softwaretype=WH2600%20V2.2.8&\
167 WundergroundUpdateReceiverDiscoveryService discoveryService = mock(
168 WundergroundUpdateReceiverDiscoveryService.class);
169 WundergroundUpdateReceiverServlet sut = new WundergroundUpdateReceiverServlet(discoveryService);
170 WundergroundUpdateReceiverHandler handler = mock(WundergroundUpdateReceiverHandler.class);
171 when(handler.getStationId()).thenReturn(STATION_ID_1);
172 sut.addHandler(handler);
173 when(discoveryService.isBackgroundDiscoveryEnabled()).thenReturn(false);
176 assertThat(sut.isActive(), is(true));
178 HttpChannel httpChannel = mock(HttpChannel.class);
179 MetaData.Request request = new MetaData.Request("GET",
180 new HttpURI("http://localhost" + WundergroundUpdateReceiverServlet.SERVLET_URL + "?" + queryString),
181 HttpVersion.HTTP_1_1, new HttpFields());
182 Request req = new Request(httpChannel, null);
183 req.setMetaData(request);
186 sut.doGet(req, mock(HttpServletResponse.class, Answers.RETURNS_MOCKS));
189 verify(handler, never()).updateChannelStates(any());
190 verify(discoveryService).addUnhandledStationId(eq("dfggger"), any());
191 assertThat(sut.isActive(), is(true));
195 void multipleIndexedParametersOfTheSameChanneltypeAreCorrectlyDiscovered() throws IOException {
197 final String queryString = """
206 dateutc=2021-02-07%2014:04:03&\
207 softwaretype=WH2600%20V2.2.8&\
212 MetaData.Request request = new MetaData.Request("GET",
213 new HttpURI("http://localhost" + WundergroundUpdateReceiverServlet.SERVLET_URL + "?" + queryString),
214 HttpVersion.HTTP_1_1, new HttpFields());
215 HttpChannel httpChannel = mock(HttpChannel.class);
216 Request req = new Request(httpChannel, null);
217 req.setMetaData(request);
219 TestChannelTypeRegistry channelTypeRegistry = new TestChannelTypeRegistry();
220 WundergroundUpdateReceiverDiscoveryService discoveryService = new WundergroundUpdateReceiverDiscoveryService(
222 WundergroundUpdateReceiverServlet sut = new WundergroundUpdateReceiverServlet(discoveryService);
223 discoveryService.addUnhandledStationId(REQ_STATION_ID, sut.normalizeParameterMap(req.getParameterMap()));
224 Thing thing = ThingBuilder.create(SUPPORTED_THING_TYPES_UIDS.stream().findFirst().get(), TEST_THING_UID)
225 .withConfiguration(new Configuration(Map.of(REPRESENTATION_PROPERTY, REQ_STATION_ID)))
226 .withLabel("test thing").withLocation("location").build();
227 ManagedThingProvider managedThingProvider = mock(ManagedThingProvider.class);
228 when(managedThingProvider.get(TEST_THING_UID)).thenReturn(thing);
229 WundergroundUpdateReceiverHandler handler = new WundergroundUpdateReceiverHandler(thing, sut, discoveryService,
230 new WundergroundUpdateReceiverUnknownChannelTypeProvider(), channelTypeRegistry, managedThingProvider);
231 handler.setCallback(mock(ThingHandlerCallback.class));
232 handler.initialize();
233 sut.addHandler(handler);
239 assertThat(sut.isActive(), is(true));
242 sut.doGet(req, mock(HttpServletResponse.class, Answers.RETURNS_MOCKS));
245 assertThat(sut.getHandlers().size(), is(1));
246 assertThat(sut.getHandlers().containsKey(REQ_STATION_ID), is(true));
247 assertThat(handler.getThing().getChannels().stream()
248 .filter(channel -> channel.getChannelTypeUID() == TEMPERATURE_CHANNELTYPEUID).count(), is(2L));
252 void unregisteredChannelsAreAddedOnTheFlyWhenDiscovered() throws IOException {
254 final String firstDeviceQueryString = """
259 dateutc=2021-02-07%2014:04:03&\
260 softwaretype=WH2600%20V2.2.8&\
265 MetaData.Request request1 = new MetaData.Request("GET", new HttpURI(
266 "http://localhost" + WundergroundUpdateReceiverServlet.SERVLET_URL + "?" + firstDeviceQueryString),
267 HttpVersion.HTTP_1_1, new HttpFields());
268 HttpChannel httpChannel = mock(HttpChannel.class);
269 Request req1 = new Request(httpChannel, null);
270 req1.setMetaData(request1);
272 TestChannelTypeRegistry channelTypeRegistry = new TestChannelTypeRegistry();
273 WundergroundUpdateReceiverDiscoveryService discoveryService = new WundergroundUpdateReceiverDiscoveryService(
275 WundergroundUpdateReceiverServlet sut = new WundergroundUpdateReceiverServlet(discoveryService);
276 discoveryService.addUnhandledStationId(REQ_STATION_ID, sut.normalizeParameterMap(req1.getParameterMap()));
277 Thing thing = ThingBuilder.create(SUPPORTED_THING_TYPES_UIDS.stream().findFirst().get(), TEST_THING_UID)
278 .withConfiguration(new Configuration(Map.of(REPRESENTATION_PROPERTY, REQ_STATION_ID)))
279 .withLabel("test thing").withLocation("location").build();
280 ManagedThingProvider managedThingProvider = mock(ManagedThingProvider.class);
281 when(managedThingProvider.get(any())).thenReturn(thing);
282 WundergroundUpdateReceiverHandler handler = new WundergroundUpdateReceiverHandler(thing, sut, discoveryService,
283 new WundergroundUpdateReceiverUnknownChannelTypeProvider(), channelTypeRegistry, managedThingProvider);
284 handler.setCallback(mock(ThingHandlerCallback.class));
287 handler.initialize();
288 sut.addHandler(handler);
291 ChannelTypeUID[] expectedBefore = new ChannelTypeUID[] { TEMPERATURE_CHANNELTYPEUID, HUMIDITY_CHANNELTYPEUID,
292 DATEUTC_CHANNELTYPEUID, SOFTWARETYPE_CHANNELTYPEUID, REALTIME_FREQUENCY_CHANNELTYPEUID,
293 LAST_QUERY_STATE_CHANNELTYPEUID, LAST_RECEIVED_DATETIME_CHANNELTYPEUID,
294 LAST_QUERY_TRIGGER_CHANNELTYPEUID };
295 List<ChannelTypeUID> before = handler.getThing().getChannels().stream().map(Channel::getChannelTypeUID)
296 .collect(Collectors.toList());
297 assertThat(before, hasItems(expectedBefore));
300 final String secondDeviceQueryString = """
306 solarradiation=42.24&\
307 dateutc=2021-02-07%2014:04:03&\
308 softwaretype=WH2600%20V2.2.8&\
313 MetaData.Request request = new MetaData.Request("GET", new HttpURI(
314 "http://localhost" + WundergroundUpdateReceiverServlet.SERVLET_URL + "?" + secondDeviceQueryString),
315 HttpVersion.HTTP_1_1, new HttpFields());
316 Request req2 = new Request(httpChannel, null);
317 req2.setMetaData(request);
321 assertThat(sut.isActive(), is(true));
324 sut.doGet(req2, mock(HttpServletResponse.class, Answers.RETURNS_MOCKS));
327 ChannelTypeUID[] expectedActual = Arrays.copyOf(expectedBefore, expectedBefore.length + 3);
328 System.arraycopy(new ChannelTypeUID[] { LOW_BATTERY_CHANNELTYPEUID, SOIL_MOISTURE_CHANNELTYPEUID,
329 SOLARRADIATION_CHANNELTYPEUID }, 0, expectedActual, expectedBefore.length, 3);
330 List<ChannelTypeUID> actual = handler.getThing().getChannels().stream().map(Channel::getChannelTypeUID)
331 .collect(Collectors.toList());
332 assertThat(actual, hasItems(expectedActual));
336 void unregisteredChannelsAreNotAddedOnUnmanagedThings() throws IOException {
338 final String firstDeviceQueryString = """
343 dateutc=2021-02-07%2014:04:03&\
344 softwaretype=WH2600%20V2.2.8&\
349 MetaData.Request request1 = new MetaData.Request("GET", new HttpURI(
350 "http://localhost" + WundergroundUpdateReceiverServlet.SERVLET_URL + "?" + firstDeviceQueryString),
351 HttpVersion.HTTP_1_1, new HttpFields());
352 HttpChannel httpChannel = mock(HttpChannel.class);
353 Request req1 = new Request(httpChannel, null);
354 req1.setMetaData(request1);
356 TestChannelTypeRegistry channelTypeRegistry = new TestChannelTypeRegistry();
357 WundergroundUpdateReceiverDiscoveryService discoveryService = new WundergroundUpdateReceiverDiscoveryService(
359 WundergroundUpdateReceiverServlet sut = new WundergroundUpdateReceiverServlet(discoveryService);
360 discoveryService.addUnhandledStationId(REQ_STATION_ID, sut.normalizeParameterMap(req1.getParameterMap()));
361 Thing thing = ThingBuilder.create(SUPPORTED_THING_TYPES_UIDS.stream().findFirst().get(), TEST_THING_UID)
362 .withConfiguration(new Configuration(Map.of(REPRESENTATION_PROPERTY, REQ_STATION_ID)))
363 .withLabel("test thing").withLocation("location").build();
364 ManagedThingProvider managedThingProvider = mock(ManagedThingProvider.class);
365 when(managedThingProvider.get(any())).thenReturn(null);
366 WundergroundUpdateReceiverHandler handler = new WundergroundUpdateReceiverHandler(thing, sut, discoveryService,
367 new WundergroundUpdateReceiverUnknownChannelTypeProvider(), channelTypeRegistry, managedThingProvider);
368 handler.setCallback(mock(ThingHandlerCallback.class));
371 handler.initialize();
372 sut.addHandler(handler);
375 ChannelTypeUID[] expectedBefore = new ChannelTypeUID[] { TEMPERATURE_CHANNELTYPEUID, HUMIDITY_CHANNELTYPEUID,
376 DATEUTC_CHANNELTYPEUID, SOFTWARETYPE_CHANNELTYPEUID, REALTIME_FREQUENCY_CHANNELTYPEUID,
377 LAST_QUERY_STATE_CHANNELTYPEUID, LAST_RECEIVED_DATETIME_CHANNELTYPEUID,
378 LAST_QUERY_TRIGGER_CHANNELTYPEUID };
379 List<ChannelTypeUID> before = handler.getThing().getChannels().stream().map(Channel::getChannelTypeUID)
380 .collect(Collectors.toList());
381 assertThat(before, hasItems(expectedBefore));
384 final String secondDeviceQueryString = """
390 solarradiation=42.24&\
391 dateutc=2021-02-07%2014:04:03&\
392 softwaretype=WH2600%20V2.2.8&\
397 MetaData.Request request = new MetaData.Request("GET", new HttpURI(
398 "http://localhost" + WundergroundUpdateReceiverServlet.SERVLET_URL + "?" + secondDeviceQueryString),
399 HttpVersion.HTTP_1_1, new HttpFields());
400 Request req2 = new Request(httpChannel, null);
401 req2.setMetaData(request);
405 assertThat(sut.isActive(), is(true));
408 sut.doGet(req2, mock(HttpServletResponse.class, Answers.RETURNS_MOCKS));
411 List<ChannelTypeUID> actual = handler.getThing().getChannels().stream().map(Channel::getChannelTypeUID)
412 .collect(Collectors.toList());
413 assertThat(actual, equalTo(before));
417 void lastQueryTriggerIsMigratedSuccessfully() throws IOException {
419 final String firstDeviceQueryString = """
424 dateutc=2021-02-07%2014:04:03&\
425 softwaretype=WH2600%20V2.2.8&\
430 MetaData.Request request1 = new MetaData.Request("GET", new HttpURI(
431 "http://localhost" + WundergroundUpdateReceiverServlet.SERVLET_URL + "?" + firstDeviceQueryString),
432 HttpVersion.HTTP_1_1, new HttpFields());
433 HttpChannel httpChannel = mock(HttpChannel.class);
434 Request req1 = new Request(httpChannel, null);
435 req1.setMetaData(request1);
437 UpdatingChannelTypeRegistry channelTypeRegistry = new UpdatingChannelTypeRegistry();
438 WundergroundUpdateReceiverDiscoveryService discoveryService = new WundergroundUpdateReceiverDiscoveryService(
440 WundergroundUpdateReceiverServlet sut = new WundergroundUpdateReceiverServlet(discoveryService);
441 discoveryService.addUnhandledStationId(REQ_STATION_ID, sut.normalizeParameterMap(req1.getParameterMap()));
442 Thing thing = ThingBuilder.create(SUPPORTED_THING_TYPES_UIDS.stream().findFirst().get(), TEST_THING_UID)
443 .withConfiguration(new Configuration(Map.of(REPRESENTATION_PROPERTY, REQ_STATION_ID)))
444 .withLabel("test thing").withLocation("location").build();
445 ManagedThingProvider managedThingProvider = mock(ManagedThingProvider.class);
446 when(managedThingProvider.get(any())).thenReturn(null);
447 WundergroundUpdateReceiverHandler handler = new WundergroundUpdateReceiverHandler(thing, sut, discoveryService,
448 new WundergroundUpdateReceiverUnknownChannelTypeProvider(), channelTypeRegistry, managedThingProvider);
449 handler.setCallback(mock(ThingHandlerCallback.class));
452 handler.initialize();
453 sut.addHandler(handler);
456 ChannelTypeUID[] expectedBefore = new ChannelTypeUID[] { TEMPERATURE_CHANNELTYPEUID, HUMIDITY_CHANNELTYPEUID,
457 DATEUTC_CHANNELTYPEUID, SOFTWARETYPE_CHANNELTYPEUID, REALTIME_FREQUENCY_CHANNELTYPEUID,
458 LAST_QUERY_STATE_CHANNELTYPEUID, LAST_RECEIVED_DATETIME_CHANNELTYPEUID,
459 LAST_QUERY_TRIGGER_CHANNELTYPEUID };
460 List<ChannelTypeUID> before = handler.getThing().getChannels().stream().map(Channel::getChannelTypeUID)
461 .collect(Collectors.toList());
462 assertThat(before, hasItems(expectedBefore));
465 var actual = handler.getThing().getChannels();
468 assertThat(actual.size(), is(8));
469 assertChannel(actual, METADATA_GROUP, LAST_QUERY_TRIGGER, LAST_QUERY_TRIGGER_CHANNELTYPEUID, ChannelKind.STATE,
474 handler.initialize();
476 final String secondDeviceQueryString = """
482 solarradiation=42.24&\
483 dateutc=2021-02-07%2014:04:03&\
484 softwaretype=WH2600%20V2.2.8&\
489 MetaData.Request request = new MetaData.Request("GET", new HttpURI(
490 "http://localhost" + WundergroundUpdateReceiverServlet.SERVLET_URL + "?" + secondDeviceQueryString),
491 HttpVersion.HTTP_1_1, new HttpFields());
492 Request req2 = new Request(httpChannel, null);
493 req2.setMetaData(request);
497 assertThat(sut.isActive(), is(true));
500 sut.doGet(req2, mock(HttpServletResponse.class, Answers.RETURNS_MOCKS));
501 actual = handler.getThing().getChannels();
504 assertThat(actual.size(), is(8));
505 assertChannel(actual, METADATA_GROUP, LAST_QUERY_TRIGGER, LAST_QUERY_TRIGGER_CHANNELTYPEUID,
506 ChannelKind.TRIGGER, nullValue());
509 private void assertChannel(List<Channel> channels, String expectedGroup, String expectedName,
510 ChannelTypeUID expectedUid, ChannelKind expectedKind, Matcher<Object> expectedItemType) {
511 ChannelUID channelUID = new ChannelUID(TEST_THING_UID, expectedGroup, expectedName);
512 Channel actual = channels.stream().filter(c -> channelUID.equals(c.getUID())).findFirst().orElse(null);
513 assertThat(actual, is(notNullValue()));
514 assertThat(actual.getLabel() + " UID", actual.getUID(), is(channelUID));
515 assertThat(actual.getLabel() + " ChannelTypeUID", actual.getChannelTypeUID(), is(expectedUid));
516 assertThat(actual.getLabel() + " Kind", actual.getKind(), is(expectedKind));
517 assertThat(actual.getLabel() + " AcceptedItemType", actual.getAcceptedItemType(), expectedItemType);
520 abstract class AbstractTestChannelTypeRegistry extends ChannelTypeRegistry {
522 protected final ChannelTypeProvider provider;
524 AbstractTestChannelTypeRegistry(ChannelTypeProvider mock) {
526 this.provider = mock;
527 when(provider.getChannelType(eq(SOFTWARETYPE_CHANNELTYPEUID), any())).thenReturn(
528 new StateChannelTypeBuilderImpl(SOFTWARETYPE_CHANNELTYPEUID, "Software type", "String").build());
529 when(provider.getChannelType(eq(TEMPERATURE_CHANNELTYPEUID), any()))
530 .thenReturn(DefaultSystemChannelTypeProvider.SYSTEM_OUTDOOR_TEMPERATURE);
531 when(provider.getChannelType(eq(SOIL_MOISTURE_CHANNELTYPEUID), any()))
532 .thenReturn(new StateChannelTypeBuilderImpl(SOIL_MOISTURE_CHANNELTYPEUID, "Soilmoisture",
533 "Number:Dimensionless").build());
534 when(provider.getChannelType(eq(SOLARRADIATION_CHANNELTYPEUID), any()))
535 .thenReturn(new StateChannelTypeBuilderImpl(SOLARRADIATION_CHANNELTYPEUID, "Solar Radiation",
536 "Number:Intensity").build());
537 when(provider.getChannelType(eq(HUMIDITY_CHANNELTYPEUID), any())).thenReturn(
538 new StateChannelTypeBuilderImpl(HUMIDITY_CHANNELTYPEUID, "Humidity", "Number:Dimensionless")
540 when(provider.getChannelType(eq(WIND_SPEED_AVG_2MIN_CHANNELTYPEUID), any()))
541 .thenReturn(new StateChannelTypeBuilderImpl(WIND_SPEED_AVG_2MIN_CHANNELTYPEUID,
542 "Wind Speed 2min Average", "Number:Speed").build());
543 when(provider.getChannelType(eq(PM2_5_MASS_CHANNELTYPEUID), any())).thenReturn(
544 new StateChannelTypeBuilderImpl(PM2_5_MASS_CHANNELTYPEUID, "PM2.5 Mass", "Number:Density").build());
545 when(provider.getChannelType(eq(DATEUTC_CHANNELTYPEUID), any())).thenReturn(
546 new StateChannelTypeBuilderImpl(DATEUTC_CHANNELTYPEUID, "Last Updated", "String").build());
547 when(provider.getChannelType(eq(LOW_BATTERY_CHANNELTYPEUID), any()))
548 .thenReturn(DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_LOW_BATTERY);
549 when(provider.getChannelType(eq(REALTIME_FREQUENCY_CHANNELTYPEUID), any())).thenReturn(
550 new StateChannelTypeBuilderImpl(REALTIME_FREQUENCY_CHANNELTYPEUID, "Realtime frequency", "Number")
552 when(provider.getChannelType(eq(LAST_QUERY_STATE_CHANNELTYPEUID), any())).thenReturn(
553 new StateChannelTypeBuilderImpl(LAST_QUERY_STATE_CHANNELTYPEUID, "The last query", "String")
555 when(provider.getChannelType(eq(LAST_RECEIVED_DATETIME_CHANNELTYPEUID), any())).thenReturn(
556 new StateChannelTypeBuilderImpl(LAST_RECEIVED_DATETIME_CHANNELTYPEUID, "Last Received", "DateTime")
558 this.addChannelTypeProvider(provider);
559 this.addChannelTypeProvider(new WundergroundUpdateReceiverUnknownChannelTypeProvider());
563 class TestChannelTypeRegistry extends AbstractTestChannelTypeRegistry {
565 TestChannelTypeRegistry() {
566 super(mock(ChannelTypeProvider.class));
567 when(provider.getChannelType(eq(LAST_QUERY_TRIGGER_CHANNELTYPEUID), any())).thenReturn(
568 new TriggerChannelTypeBuilderImpl(LAST_QUERY_TRIGGER_CHANNELTYPEUID, "The last query").build());
572 class UpdatingChannelTypeRegistry extends AbstractTestChannelTypeRegistry {
574 UpdatingChannelTypeRegistry() {
575 super(mock(ChannelTypeProvider.class));
576 when(provider.getChannelType(eq(LAST_QUERY_TRIGGER_CHANNELTYPEUID), any()))
577 .thenReturn(new StateChannelTypeBuilderImpl(LAST_QUERY_TRIGGER_CHANNELTYPEUID, "The last query",
579 .thenReturn(new StateChannelTypeBuilderImpl(LAST_QUERY_TRIGGER_CHANNELTYPEUID, "The last query",
581 .thenReturn(new TriggerChannelTypeBuilderImpl(LAST_QUERY_TRIGGER_CHANNELTYPEUID, "The last query")