]> git.basschouten.com Git - openhab-addons.git/blob
c0a8e1b9ce5e09a9ff8c20d1cf37962d8382469a
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.netatmo.internal.welcome;
14
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;
19
20 import java.util.*;
21
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;
37
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;
42
43 /**
44  * @author Sven Strohschein - Initial contribution
45  */
46 @RunWith(MockitoJUnitRunner.class)
47 public class NAWelcomeHomeHandlerTest {
48
49     private static final String DUMMY_HOME_ID = "1";
50
51     @Mock
52     private TimeZoneProvider timeZoneProviderMock;
53     private NAWelcomeHomeHandlerAccessible handler;
54     @Mock
55     private NetatmoBridgeHandler bridgeHandlerMock;
56
57     @Before
58     public void before() {
59         Thing welcomeHomeThing = new ThingImpl(new ThingTypeUID("netatmo", "NAWelcomeHome"), "1");
60         handler = new NAWelcomeHomeHandlerAccessible(welcomeHomeThing);
61     }
62
63     @Test
64     public void testUpdateReadingsWithEvents() {
65         NAWelcomeEvent event1 = createEvent(1592661881, NAWebhookCameraEvent.EventTypeEnum.PERSON);
66         NAWelcomeEvent event2 = createEvent(1592661882, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
67
68         NAWelcomeHome home = new NAWelcomeHome();
69         home.setId(DUMMY_HOME_ID);
70         home.setEvents(Arrays.asList(event1, event2));
71
72         NAWelcomeHomeData homeData = new NAWelcomeHomeData();
73         homeData.setHomes(Collections.singletonList(home));
74
75         when(bridgeHandlerMock.getWelcomeDataBody(DUMMY_HOME_ID)).thenReturn(Optional.of(homeData));
76
77         handler.updateReadings();
78
79         // the second (last) event is expected
80         assertEquals(new StringType("movement"),
81                 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
82
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));
87     }
88
89     @Test
90     public void testUpdateReadingsWith1Event() {
91         NAWelcomeEvent event = createEvent(1592661881, NAWebhookCameraEvent.EventTypeEnum.PERSON);
92
93         NAWelcomeHome home = new NAWelcomeHome();
94         home.setId(DUMMY_HOME_ID);
95         home.setEvents(Collections.singletonList(event));
96
97         NAWelcomeHomeData homeData = new NAWelcomeHomeData();
98         homeData.setHomes(Collections.singletonList(home));
99
100         when(bridgeHandlerMock.getWelcomeDataBody(DUMMY_HOME_ID)).thenReturn(Optional.of(homeData));
101
102         handler.updateReadings();
103
104         assertEquals(new StringType("person"),
105                 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
106     }
107
108     @Test
109     public void testUpdateReadingsNoEvents() {
110         NAWelcomeHome home = new NAWelcomeHome();
111         home.setId(DUMMY_HOME_ID);
112
113         NAWelcomeHomeData homeData = new NAWelcomeHomeData();
114         homeData.setHomes(Collections.singletonList(home));
115
116         when(bridgeHandlerMock.getWelcomeDataBody(DUMMY_HOME_ID)).thenReturn(Optional.of(homeData));
117
118         handler.updateReadings();
119
120         assertEquals(UnDefType.UNDEF, handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
121     }
122
123     @Test
124     public void testUpdateReadingsEmptyHomeData() {
125         NAWelcomeHomeData homeData = new NAWelcomeHomeData();
126
127         when(bridgeHandlerMock.getWelcomeDataBody(any())).thenReturn(Optional.of(homeData));
128
129         handler.updateReadings();
130
131         assertEquals(UnDefType.UNDEF, handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
132     }
133
134     @Test
135     public void testUpdateReadingsNoHomeData() {
136         handler.updateReadings();
137
138         assertEquals(UnDefType.UNDEF, handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
139     }
140
141     @Test
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);
146
147         NAWelcomeHome home = new NAWelcomeHome();
148         home.setId(DUMMY_HOME_ID);
149         home.setEvents(Collections.singletonList(event1));
150
151         NAWelcomeHomeData homeData = new NAWelcomeHomeData();
152         homeData.setHomes(Collections.singletonList(home));
153
154         when(bridgeHandlerMock.getWelcomeDataBody(DUMMY_HOME_ID)).thenReturn(Optional.of(homeData));
155
156         triggerCameraEvents();
157
158         // No triggered event is expected, because the binding is just started (with existing events).
159         assertEquals(0, handler.getTriggerChannelCount());
160
161         home.setEvents(Arrays.asList(event1, event2));
162
163         triggerCameraEvents();
164
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());
170
171         home.setEvents(Arrays.asList(event1, event2));
172
173         triggerCameraEvents();
174
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());
180
181         home.setEvents(Arrays.asList(event1, event2, event3));
182
183         triggerCameraEvents();
184
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());
191     }
192
193     @Test
194     public void testTriggerChannelIfRequiredNoEventAvailable() {
195         NAWelcomeHome home = new NAWelcomeHome();
196         home.setId(DUMMY_HOME_ID);
197
198         NAWelcomeHomeData homeData = new NAWelcomeHomeData();
199         homeData.setHomes(Collections.singletonList(home));
200
201         when(bridgeHandlerMock.getWelcomeDataBody(DUMMY_HOME_ID)).thenReturn(Optional.of(homeData));
202
203         triggerCameraEvents();
204
205         // No triggered event is expected, because there aren't any events (the collection is NULL)
206         assertEquals(0, handler.getTriggerChannelCount());
207
208         home.setEvents(Collections.emptyList());
209
210         triggerCameraEvents();
211
212         // No triggered event is expected, because there aren't any events (the collection is empty)
213         assertEquals(0, handler.getTriggerChannelCount());
214     }
215
216     @Test
217     public void testTriggerChannelIfRequiredPersonMovement() {
218         NAWelcomeHome home = initHome();
219
220         NAWelcomeEvent event = createEvent(1592661882, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
221         event.setPersonId("1");
222
223         home.getEvents().add(event);
224
225         triggerCameraEvents();
226
227         assertEquals(1, handler.getTriggerChannelCount());
228         assertEquals(new StringType("movement"),
229                 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
230         assertEquals("HUMAN", handler.getLastDetectedObject());
231     }
232
233     @Test
234     public void testTriggerChannelIfRequiredHumanMovement() {
235         NAWelcomeHome home = initHome();
236
237         NAWelcomeEvent event = createEvent(1592661882, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
238         event.setCategory(NAWelcomeEvent.CategoryEnum.HUMAN);
239
240         home.getEvents().add(event);
241
242         triggerCameraEvents();
243
244         assertEquals(1, handler.getTriggerChannelCount());
245         assertEquals(new StringType("movement"),
246                 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
247         assertEquals("HUMAN", handler.getLastDetectedObject());
248     }
249
250     @Test
251     public void testTriggerChannelIfRequiredAnimalMovement() {
252         NAWelcomeHome home = initHome();
253
254         NAWelcomeEvent event = createEvent(1592661882, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
255         event.setCategory(NAWelcomeEvent.CategoryEnum.ANIMAL);
256
257         home.getEvents().add(event);
258
259         triggerCameraEvents();
260
261         assertEquals(1, handler.getTriggerChannelCount());
262         assertEquals(new StringType("movement"),
263                 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
264         assertEquals("ANIMAL", handler.getLastDetectedObject());
265     }
266
267     @Test
268     public void testTriggerChannelIfRequiredVehicleMovement() {
269         NAWelcomeHome home = initHome();
270
271         NAWelcomeEvent event = createEvent(1592661882, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
272         event.setCategory(NAWelcomeEvent.CategoryEnum.VEHICLE);
273
274         home.getEvents().add(event);
275
276         triggerCameraEvents();
277
278         assertEquals(1, handler.getTriggerChannelCount());
279         assertEquals(new StringType("movement"),
280                 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
281         assertEquals("VEHICLE", handler.getLastDetectedObject());
282     }
283
284     @Test
285     public void testMatchDetectedObjectEnums() {
286         assertArrayEquals(
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());
290     }
291
292     private NAWelcomeHome initHome() {
293         NAWelcomeEvent initLastEvent = createEvent(1592661881, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
294
295         NAWelcomeHome home = new NAWelcomeHome();
296         home.setId(DUMMY_HOME_ID);
297
298         List<NAWelcomeEvent> events = new ArrayList<>();
299         events.add(initLastEvent);
300         home.setEvents(events);
301
302         NAWelcomeHomeData homeData = new NAWelcomeHomeData();
303         homeData.setHomes(Collections.singletonList(home));
304
305         when(bridgeHandlerMock.getWelcomeDataBody(DUMMY_HOME_ID)).thenReturn(Optional.of(homeData));
306
307         triggerCameraEvents();
308
309         return home;
310     }
311
312     private void triggerCameraEvents() {
313         handler.updateReadings();
314         handler.triggerChannelIfRequired(NetatmoBindingConstants.CHANNEL_CAMERA_EVENT);
315     }
316
317     private static NAWelcomeEvent createPresenceEvent(int eventTime, NAWelcomeSubEvent.TypeEnum detectedObjectType) {
318         NAWelcomeSubEvent subEvent = new NAWelcomeSubEvent();
319         subEvent.setTime(eventTime);
320         subEvent.setType(detectedObjectType);
321
322         NAWelcomeEvent event = createEvent(eventTime, NAWebhookCameraEvent.EventTypeEnum.OUTDOOR);
323         event.setEventList(Collections.singletonList(subEvent));
324         return event;
325     }
326
327     private static NAWelcomeEvent createEvent(int eventTime, NAWebhookCameraEvent.EventTypeEnum eventType) {
328         NAWelcomeEvent event = new NAWelcomeEvent();
329         event.setType(eventType.toString());
330         event.setTime(eventTime);
331         return event;
332     }
333
334     private class NAWelcomeHomeHandlerAccessible extends NAWelcomeHomeHandler {
335
336         private int triggerChannelCount;
337         private String lastDetectedObject;
338
339         private NAWelcomeHomeHandlerAccessible(Thing thing) {
340             super(thing, timeZoneProviderMock);
341         }
342
343         @Override
344         protected Optional<NetatmoBridgeHandler> getBridgeHandler() {
345             return Optional.of(bridgeHandlerMock);
346         }
347
348         @Override
349         protected String getId() {
350             return DUMMY_HOME_ID;
351         }
352
353         @Override
354         protected void triggerChannel(@NonNull String channelID, @NonNull String event) {
355             triggerChannelCount++;
356             lastDetectedObject = event;
357             super.triggerChannel(channelID, event);
358         }
359
360         private int getTriggerChannelCount() {
361             return triggerChannelCount;
362         }
363
364         public String getLastDetectedObject() {
365             return lastDetectedObject;
366         }
367     }
368 }