2 * Copyright (c) 2010-2020 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.netatmo.internal.welcome;
15 import static org.junit.Assert.assertArrayEquals;
16 import static org.junit.Assert.assertEquals;
17 import static org.mockito.ArgumentMatchers.any;
18 import static org.mockito.Mockito.when;
22 import org.eclipse.jdt.annotation.NonNull;
23 import org.openhab.core.i18n.TimeZoneProvider;
24 import org.openhab.core.library.types.StringType;
25 import org.openhab.core.thing.Thing;
26 import org.openhab.core.thing.ThingTypeUID;
27 import org.openhab.core.thing.internal.ThingImpl;
28 import org.openhab.core.types.UnDefType;
29 import org.junit.Before;
30 import org.junit.Test;
31 import org.junit.runner.RunWith;
32 import org.mockito.Mock;
33 import org.mockito.junit.MockitoJUnitRunner;
34 import org.openhab.binding.netatmo.internal.NetatmoBindingConstants;
35 import org.openhab.binding.netatmo.internal.handler.NetatmoBridgeHandler;
36 import org.openhab.binding.netatmo.internal.webhook.NAWebhookCameraEvent;
38 import io.swagger.client.model.NAWelcomeEvent;
39 import io.swagger.client.model.NAWelcomeHome;
40 import io.swagger.client.model.NAWelcomeHomeData;
41 import io.swagger.client.model.NAWelcomeSubEvent;
44 * @author Sven Strohschein - Initial contribution
46 @RunWith(MockitoJUnitRunner.class)
47 public class NAWelcomeHomeHandlerTest {
49 private static final String DUMMY_HOME_ID = "1";
52 private TimeZoneProvider timeZoneProviderMock;
53 private NAWelcomeHomeHandlerAccessible handler;
55 private NetatmoBridgeHandler bridgeHandlerMock;
58 public void before() {
59 Thing welcomeHomeThing = new ThingImpl(new ThingTypeUID("netatmo", "NAWelcomeHome"), "1");
60 handler = new NAWelcomeHomeHandlerAccessible(welcomeHomeThing);
64 public void testUpdateReadingsWithEvents() {
65 NAWelcomeEvent event1 = createEvent(1592661881, NAWebhookCameraEvent.EventTypeEnum.PERSON);
66 NAWelcomeEvent event2 = createEvent(1592661882, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
68 NAWelcomeHome home = new NAWelcomeHome();
69 home.setId(DUMMY_HOME_ID);
70 home.setEvents(Arrays.asList(event1, event2));
72 NAWelcomeHomeData homeData = new NAWelcomeHomeData();
73 homeData.setHomes(Collections.singletonList(home));
75 when(bridgeHandlerMock.getWelcomeDataBody(DUMMY_HOME_ID)).thenReturn(Optional.of(homeData));
77 handler.updateReadings();
79 // the second (last) event is expected
80 assertEquals(new StringType("movement"),
81 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
83 home.setEvents(Arrays.asList(event2, event1));
84 // the second (last) event is still expected (independent from the order of these are added)
85 assertEquals(new StringType("movement"),
86 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
90 public void testUpdateReadingsWith1Event() {
91 NAWelcomeEvent event = createEvent(1592661881, NAWebhookCameraEvent.EventTypeEnum.PERSON);
93 NAWelcomeHome home = new NAWelcomeHome();
94 home.setId(DUMMY_HOME_ID);
95 home.setEvents(Collections.singletonList(event));
97 NAWelcomeHomeData homeData = new NAWelcomeHomeData();
98 homeData.setHomes(Collections.singletonList(home));
100 when(bridgeHandlerMock.getWelcomeDataBody(DUMMY_HOME_ID)).thenReturn(Optional.of(homeData));
102 handler.updateReadings();
104 assertEquals(new StringType("person"),
105 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
109 public void testUpdateReadingsNoEvents() {
110 NAWelcomeHome home = new NAWelcomeHome();
111 home.setId(DUMMY_HOME_ID);
113 NAWelcomeHomeData homeData = new NAWelcomeHomeData();
114 homeData.setHomes(Collections.singletonList(home));
116 when(bridgeHandlerMock.getWelcomeDataBody(DUMMY_HOME_ID)).thenReturn(Optional.of(homeData));
118 handler.updateReadings();
120 assertEquals(UnDefType.UNDEF, handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
124 public void testUpdateReadingsEmptyHomeData() {
125 NAWelcomeHomeData homeData = new NAWelcomeHomeData();
127 when(bridgeHandlerMock.getWelcomeDataBody(any())).thenReturn(Optional.of(homeData));
129 handler.updateReadings();
131 assertEquals(UnDefType.UNDEF, handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
135 public void testUpdateReadingsNoHomeData() {
136 handler.updateReadings();
138 assertEquals(UnDefType.UNDEF, handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
142 public void testTriggerChannelIfRequired() {
143 NAWelcomeEvent event1 = createPresenceEvent(1592661881, NAWelcomeSubEvent.TypeEnum.ANIMAL);
144 NAWelcomeEvent event2 = createPresenceEvent(1592661882, NAWelcomeSubEvent.TypeEnum.HUMAN);
145 NAWelcomeEvent event3 = createEvent(1592661883, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
147 NAWelcomeHome home = new NAWelcomeHome();
148 home.setId(DUMMY_HOME_ID);
149 home.setEvents(Collections.singletonList(event1));
151 NAWelcomeHomeData homeData = new NAWelcomeHomeData();
152 homeData.setHomes(Collections.singletonList(home));
154 when(bridgeHandlerMock.getWelcomeDataBody(DUMMY_HOME_ID)).thenReturn(Optional.of(homeData));
156 triggerCameraEvents();
158 // No triggered event is expected, because the binding is just started (with existing events).
159 assertEquals(0, handler.getTriggerChannelCount());
161 home.setEvents(Arrays.asList(event1, event2));
163 triggerCameraEvents();
165 // 1 triggered event is expected, because there is 1 new event since binding start (outdoor / detected human).
166 assertEquals(1, handler.getTriggerChannelCount());
167 assertEquals(new StringType("outdoor"),
168 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
169 assertEquals("HUMAN", handler.getLastDetectedObject());
171 home.setEvents(Arrays.asList(event1, event2));
173 triggerCameraEvents();
175 // No new triggered event is expected, because there are still the same events as before the refresh.
176 assertEquals(1, handler.getTriggerChannelCount());
177 assertEquals(new StringType("outdoor"),
178 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
179 assertEquals("HUMAN", handler.getLastDetectedObject());
181 home.setEvents(Arrays.asList(event1, event2, event3));
183 triggerCameraEvents();
185 // 1 new triggered event is expected (2 in sum), because there is 1 new event since the last triggered event
186 // (movement after outdoor / detected human).
187 assertEquals(2, handler.getTriggerChannelCount());
188 assertEquals(new StringType("movement"),
189 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
190 assertEquals("MOVEMENT", handler.getLastDetectedObject());
194 public void testTriggerChannelIfRequiredNoEventAvailable() {
195 NAWelcomeHome home = new NAWelcomeHome();
196 home.setId(DUMMY_HOME_ID);
198 NAWelcomeHomeData homeData = new NAWelcomeHomeData();
199 homeData.setHomes(Collections.singletonList(home));
201 when(bridgeHandlerMock.getWelcomeDataBody(DUMMY_HOME_ID)).thenReturn(Optional.of(homeData));
203 triggerCameraEvents();
205 // No triggered event is expected, because there aren't any events (the collection is NULL)
206 assertEquals(0, handler.getTriggerChannelCount());
208 home.setEvents(Collections.emptyList());
210 triggerCameraEvents();
212 // No triggered event is expected, because there aren't any events (the collection is empty)
213 assertEquals(0, handler.getTriggerChannelCount());
217 public void testTriggerChannelIfRequiredPersonMovement() {
218 NAWelcomeHome home = initHome();
220 NAWelcomeEvent event = createEvent(1592661882, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
221 event.setPersonId("1");
223 home.getEvents().add(event);
225 triggerCameraEvents();
227 assertEquals(1, handler.getTriggerChannelCount());
228 assertEquals(new StringType("movement"),
229 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
230 assertEquals("HUMAN", handler.getLastDetectedObject());
234 public void testTriggerChannelIfRequiredHumanMovement() {
235 NAWelcomeHome home = initHome();
237 NAWelcomeEvent event = createEvent(1592661882, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
238 event.setCategory(NAWelcomeEvent.CategoryEnum.HUMAN);
240 home.getEvents().add(event);
242 triggerCameraEvents();
244 assertEquals(1, handler.getTriggerChannelCount());
245 assertEquals(new StringType("movement"),
246 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
247 assertEquals("HUMAN", handler.getLastDetectedObject());
251 public void testTriggerChannelIfRequiredAnimalMovement() {
252 NAWelcomeHome home = initHome();
254 NAWelcomeEvent event = createEvent(1592661882, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
255 event.setCategory(NAWelcomeEvent.CategoryEnum.ANIMAL);
257 home.getEvents().add(event);
259 triggerCameraEvents();
261 assertEquals(1, handler.getTriggerChannelCount());
262 assertEquals(new StringType("movement"),
263 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
264 assertEquals("ANIMAL", handler.getLastDetectedObject());
268 public void testTriggerChannelIfRequiredVehicleMovement() {
269 NAWelcomeHome home = initHome();
271 NAWelcomeEvent event = createEvent(1592661882, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
272 event.setCategory(NAWelcomeEvent.CategoryEnum.VEHICLE);
274 home.getEvents().add(event);
276 triggerCameraEvents();
278 assertEquals(1, handler.getTriggerChannelCount());
279 assertEquals(new StringType("movement"),
280 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
281 assertEquals("VEHICLE", handler.getLastDetectedObject());
285 public void testMatchDetectedObjectEnums() {
287 "The detected object enums aren't equal anymore, that could lead to a bug! Please check the usages!",
288 Arrays.stream(NAWelcomeEvent.CategoryEnum.values()).map(Enum::name).toArray(),
289 Arrays.stream(NAWelcomeSubEvent.TypeEnum.values()).map(Enum::name).toArray());
292 private NAWelcomeHome initHome() {
293 NAWelcomeEvent initLastEvent = createEvent(1592661881, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
295 NAWelcomeHome home = new NAWelcomeHome();
296 home.setId(DUMMY_HOME_ID);
298 List<NAWelcomeEvent> events = new ArrayList<>();
299 events.add(initLastEvent);
300 home.setEvents(events);
302 NAWelcomeHomeData homeData = new NAWelcomeHomeData();
303 homeData.setHomes(Collections.singletonList(home));
305 when(bridgeHandlerMock.getWelcomeDataBody(DUMMY_HOME_ID)).thenReturn(Optional.of(homeData));
307 triggerCameraEvents();
312 private void triggerCameraEvents() {
313 handler.updateReadings();
314 handler.triggerChannelIfRequired(NetatmoBindingConstants.CHANNEL_CAMERA_EVENT);
317 private static NAWelcomeEvent createPresenceEvent(int eventTime, NAWelcomeSubEvent.TypeEnum detectedObjectType) {
318 NAWelcomeSubEvent subEvent = new NAWelcomeSubEvent();
319 subEvent.setTime(eventTime);
320 subEvent.setType(detectedObjectType);
322 NAWelcomeEvent event = createEvent(eventTime, NAWebhookCameraEvent.EventTypeEnum.OUTDOOR);
323 event.setEventList(Collections.singletonList(subEvent));
327 private static NAWelcomeEvent createEvent(int eventTime, NAWebhookCameraEvent.EventTypeEnum eventType) {
328 NAWelcomeEvent event = new NAWelcomeEvent();
329 event.setType(eventType.toString());
330 event.setTime(eventTime);
334 private class NAWelcomeHomeHandlerAccessible extends NAWelcomeHomeHandler {
336 private int triggerChannelCount;
337 private String lastDetectedObject;
339 private NAWelcomeHomeHandlerAccessible(Thing thing) {
340 super(thing, timeZoneProviderMock);
344 protected Optional<NetatmoBridgeHandler> getBridgeHandler() {
345 return Optional.of(bridgeHandlerMock);
349 protected String getId() {
350 return DUMMY_HOME_ID;
354 protected void triggerChannel(@NonNull String channelID, @NonNull String event) {
355 triggerChannelCount++;
356 lastDetectedObject = event;
357 super.triggerChannel(channelID, event);
360 private int getTriggerChannelCount() {
361 return triggerChannelCount;
364 public String getLastDetectedObject() {
365 return lastDetectedObject;