]> git.basschouten.com Git - openhab-addons.git/blob
b9270ed2a5d8b0ca6341e73ae1fa518dd6e426d1
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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.jupiter.api.Assertions.*;
16 import static org.mockito.ArgumentMatchers.any;
17 import static org.mockito.Mockito.when;
18
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Collections;
22 import java.util.List;
23 import java.util.Optional;
24
25 import org.eclipse.jdt.annotation.NonNull;
26 import org.junit.jupiter.api.BeforeEach;
27 import org.junit.jupiter.api.Test;
28 import org.junit.jupiter.api.extension.ExtendWith;
29 import org.mockito.Mock;
30 import org.mockito.junit.jupiter.MockitoExtension;
31 import org.mockito.junit.jupiter.MockitoSettings;
32 import org.mockito.quality.Strictness;
33 import org.openhab.binding.netatmo.internal.NetatmoBindingConstants;
34 import org.openhab.binding.netatmo.internal.handler.NetatmoBridgeHandler;
35 import org.openhab.binding.netatmo.internal.webhook.NAWebhookCameraEvent;
36 import org.openhab.core.i18n.TimeZoneProvider;
37 import org.openhab.core.library.types.StringType;
38 import org.openhab.core.thing.Thing;
39 import org.openhab.core.thing.ThingTypeUID;
40 import org.openhab.core.thing.internal.ThingImpl;
41 import org.openhab.core.types.UnDefType;
42
43 import io.swagger.client.model.NAWelcomeEvent;
44 import io.swagger.client.model.NAWelcomeHome;
45 import io.swagger.client.model.NAWelcomeHomeData;
46 import io.swagger.client.model.NAWelcomeSubEvent;
47
48 /**
49  * @author Sven Strohschein - Initial contribution
50  */
51 @ExtendWith(MockitoExtension.class)
52 @MockitoSettings(strictness = Strictness.WARN)
53 public class NAWelcomeHomeHandlerTest {
54
55     private static final String DUMMY_HOME_ID = "1";
56
57     private NAWelcomeHomeHandlerAccessible handler;
58
59     private @Mock NetatmoBridgeHandler bridgeHandlerMock;
60     private @Mock TimeZoneProvider timeZoneProviderMock;
61
62     @BeforeEach
63     public void before() {
64         Thing welcomeHomeThing = new ThingImpl(new ThingTypeUID("netatmo", "NAWelcomeHome"), "1");
65         handler = new NAWelcomeHomeHandlerAccessible(welcomeHomeThing);
66     }
67
68     @Test
69     public void testUpdateReadingsWithEvents() {
70         NAWelcomeEvent event1 = createEvent(1592661881, NAWebhookCameraEvent.EventTypeEnum.PERSON);
71         NAWelcomeEvent event2 = createEvent(1592661882, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
72
73         NAWelcomeHome home = new NAWelcomeHome();
74         home.setId(DUMMY_HOME_ID);
75         home.setEvents(Arrays.asList(event1, event2));
76
77         NAWelcomeHomeData homeData = new NAWelcomeHomeData();
78         homeData.setHomes(Collections.singletonList(home));
79
80         when(bridgeHandlerMock.getWelcomeDataBody(DUMMY_HOME_ID)).thenReturn(Optional.of(homeData));
81
82         handler.updateReadings();
83
84         // the second (last) event is expected
85         assertEquals(new StringType("movement"),
86                 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
87
88         home.setEvents(Arrays.asList(event2, event1));
89         // the second (last) event is still expected (independent from the order of these are added)
90         assertEquals(new StringType("movement"),
91                 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
92     }
93
94     @Test
95     public void testUpdateReadingsWith1Event() {
96         NAWelcomeEvent event = createEvent(1592661881, NAWebhookCameraEvent.EventTypeEnum.PERSON);
97
98         NAWelcomeHome home = new NAWelcomeHome();
99         home.setId(DUMMY_HOME_ID);
100         home.setEvents(Collections.singletonList(event));
101
102         NAWelcomeHomeData homeData = new NAWelcomeHomeData();
103         homeData.setHomes(Collections.singletonList(home));
104
105         when(bridgeHandlerMock.getWelcomeDataBody(DUMMY_HOME_ID)).thenReturn(Optional.of(homeData));
106
107         handler.updateReadings();
108
109         assertEquals(new StringType("person"),
110                 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
111     }
112
113     @Test
114     public void testUpdateReadingsNoEvents() {
115         NAWelcomeHome home = new NAWelcomeHome();
116         home.setId(DUMMY_HOME_ID);
117
118         NAWelcomeHomeData homeData = new NAWelcomeHomeData();
119         homeData.setHomes(Collections.singletonList(home));
120
121         when(bridgeHandlerMock.getWelcomeDataBody(DUMMY_HOME_ID)).thenReturn(Optional.of(homeData));
122
123         handler.updateReadings();
124
125         assertEquals(UnDefType.UNDEF, handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
126     }
127
128     @Test
129     public void testUpdateReadingsEmptyHomeData() {
130         NAWelcomeHomeData homeData = new NAWelcomeHomeData();
131
132         when(bridgeHandlerMock.getWelcomeDataBody(any())).thenReturn(Optional.of(homeData));
133
134         handler.updateReadings();
135
136         assertEquals(UnDefType.UNDEF, handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
137     }
138
139     @Test
140     public void testUpdateReadingsNoHomeData() {
141         handler.updateReadings();
142
143         assertEquals(UnDefType.UNDEF, handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
144     }
145
146     @Test
147     public void testTriggerChannelIfRequired() {
148         NAWelcomeEvent event1 = createPresenceEvent(1592661881, NAWelcomeSubEvent.TypeEnum.ANIMAL);
149         NAWelcomeEvent event2 = createPresenceEvent(1592661882, NAWelcomeSubEvent.TypeEnum.HUMAN);
150         NAWelcomeEvent event3 = createEvent(1592661883, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
151
152         NAWelcomeHome home = new NAWelcomeHome();
153         home.setId(DUMMY_HOME_ID);
154         home.setEvents(Collections.singletonList(event1));
155
156         NAWelcomeHomeData homeData = new NAWelcomeHomeData();
157         homeData.setHomes(Collections.singletonList(home));
158
159         when(bridgeHandlerMock.getWelcomeDataBody(DUMMY_HOME_ID)).thenReturn(Optional.of(homeData));
160
161         triggerCameraEvents();
162
163         // No triggered event is expected, because the binding is just started (with existing events).
164         assertEquals(0, handler.getTriggerChannelCount());
165
166         home.setEvents(Arrays.asList(event1, event2));
167
168         triggerCameraEvents();
169
170         // 1 triggered event is expected, because there is 1 new event since binding start (outdoor / detected human).
171         assertEquals(1, handler.getTriggerChannelCount());
172         assertEquals(new StringType("outdoor"),
173                 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
174         assertEquals("HUMAN", handler.getLastDetectedObject());
175
176         home.setEvents(Arrays.asList(event1, event2));
177
178         triggerCameraEvents();
179
180         // No new triggered event is expected, because there are still the same events as before the refresh.
181         assertEquals(1, handler.getTriggerChannelCount());
182         assertEquals(new StringType("outdoor"),
183                 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
184         assertEquals("HUMAN", handler.getLastDetectedObject());
185
186         home.setEvents(Arrays.asList(event1, event2, event3));
187
188         triggerCameraEvents();
189
190         // 1 new triggered event is expected (2 in sum), because there is 1 new event since the last triggered event
191         // (movement after outdoor / detected human).
192         assertEquals(2, handler.getTriggerChannelCount());
193         assertEquals(new StringType("movement"),
194                 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
195         assertEquals("MOVEMENT", handler.getLastDetectedObject());
196     }
197
198     @Test
199     public void testTriggerChannelIfRequiredNoEventAvailable() {
200         NAWelcomeHome home = new NAWelcomeHome();
201         home.setId(DUMMY_HOME_ID);
202
203         NAWelcomeHomeData homeData = new NAWelcomeHomeData();
204         homeData.setHomes(Collections.singletonList(home));
205
206         when(bridgeHandlerMock.getWelcomeDataBody(DUMMY_HOME_ID)).thenReturn(Optional.of(homeData));
207
208         triggerCameraEvents();
209
210         // No triggered event is expected, because there aren't any events (the collection is NULL)
211         assertEquals(0, handler.getTriggerChannelCount());
212
213         home.setEvents(Collections.emptyList());
214
215         triggerCameraEvents();
216
217         // No triggered event is expected, because there aren't any events (the collection is empty)
218         assertEquals(0, handler.getTriggerChannelCount());
219     }
220
221     @Test
222     public void testTriggerChannelIfRequiredPersonMovement() {
223         NAWelcomeHome home = initHome();
224
225         NAWelcomeEvent event = createEvent(1592661882, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
226         event.setPersonId("1");
227
228         home.getEvents().add(event);
229
230         triggerCameraEvents();
231
232         assertEquals(1, handler.getTriggerChannelCount());
233         assertEquals(new StringType("movement"),
234                 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
235         assertEquals("HUMAN", handler.getLastDetectedObject());
236     }
237
238     @Test
239     public void testTriggerChannelIfRequiredHumanMovement() {
240         NAWelcomeHome home = initHome();
241
242         NAWelcomeEvent event = createEvent(1592661882, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
243         event.setCategory(NAWelcomeEvent.CategoryEnum.HUMAN);
244
245         home.getEvents().add(event);
246
247         triggerCameraEvents();
248
249         assertEquals(1, handler.getTriggerChannelCount());
250         assertEquals(new StringType("movement"),
251                 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
252         assertEquals("HUMAN", handler.getLastDetectedObject());
253     }
254
255     @Test
256     public void testTriggerChannelIfRequiredAnimalMovement() {
257         NAWelcomeHome home = initHome();
258
259         NAWelcomeEvent event = createEvent(1592661882, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
260         event.setCategory(NAWelcomeEvent.CategoryEnum.ANIMAL);
261
262         home.getEvents().add(event);
263
264         triggerCameraEvents();
265
266         assertEquals(1, handler.getTriggerChannelCount());
267         assertEquals(new StringType("movement"),
268                 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
269         assertEquals("ANIMAL", handler.getLastDetectedObject());
270     }
271
272     @Test
273     public void testTriggerChannelIfRequiredVehicleMovement() {
274         NAWelcomeHome home = initHome();
275
276         NAWelcomeEvent event = createEvent(1592661882, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
277         event.setCategory(NAWelcomeEvent.CategoryEnum.VEHICLE);
278
279         home.getEvents().add(event);
280
281         triggerCameraEvents();
282
283         assertEquals(1, handler.getTriggerChannelCount());
284         assertEquals(new StringType("movement"),
285                 handler.getNAThingProperty(NetatmoBindingConstants.CHANNEL_WELCOME_EVENT_TYPE));
286         assertEquals("VEHICLE", handler.getLastDetectedObject());
287     }
288
289     @Test
290     public void testMatchDetectedObjectEnums() {
291         assertArrayEquals(Arrays.stream(NAWelcomeEvent.CategoryEnum.values()).map(Enum::name).toArray(),
292                 Arrays.stream(NAWelcomeSubEvent.TypeEnum.values()).map(Enum::name).toArray(),
293                 "The detected object enums aren't equal anymore, that could lead to a bug! Please check the usages!");
294     }
295
296     private NAWelcomeHome initHome() {
297         NAWelcomeEvent initLastEvent = createEvent(1592661881, NAWebhookCameraEvent.EventTypeEnum.MOVEMENT);
298
299         NAWelcomeHome home = new NAWelcomeHome();
300         home.setId(DUMMY_HOME_ID);
301
302         List<NAWelcomeEvent> events = new ArrayList<>();
303         events.add(initLastEvent);
304         home.setEvents(events);
305
306         NAWelcomeHomeData homeData = new NAWelcomeHomeData();
307         homeData.setHomes(Collections.singletonList(home));
308
309         when(bridgeHandlerMock.getWelcomeDataBody(DUMMY_HOME_ID)).thenReturn(Optional.of(homeData));
310
311         triggerCameraEvents();
312
313         return home;
314     }
315
316     private void triggerCameraEvents() {
317         handler.updateReadings();
318         handler.triggerChannelIfRequired(NetatmoBindingConstants.CHANNEL_CAMERA_EVENT);
319     }
320
321     private static NAWelcomeEvent createPresenceEvent(int eventTime, NAWelcomeSubEvent.TypeEnum detectedObjectType) {
322         NAWelcomeSubEvent subEvent = new NAWelcomeSubEvent();
323         subEvent.setTime(eventTime);
324         subEvent.setType(detectedObjectType);
325
326         NAWelcomeEvent event = createEvent(eventTime, NAWebhookCameraEvent.EventTypeEnum.OUTDOOR);
327         event.setEventList(Collections.singletonList(subEvent));
328         return event;
329     }
330
331     private static NAWelcomeEvent createEvent(int eventTime, NAWebhookCameraEvent.EventTypeEnum eventType) {
332         NAWelcomeEvent event = new NAWelcomeEvent();
333         event.setType(eventType.toString());
334         event.setTime(eventTime);
335         return event;
336     }
337
338     private class NAWelcomeHomeHandlerAccessible extends NAWelcomeHomeHandler {
339
340         private int triggerChannelCount;
341         private String lastDetectedObject;
342
343         private NAWelcomeHomeHandlerAccessible(Thing thing) {
344             super(thing, timeZoneProviderMock);
345         }
346
347         @Override
348         protected Optional<NetatmoBridgeHandler> getBridgeHandler() {
349             return Optional.of(bridgeHandlerMock);
350         }
351
352         @Override
353         protected String getId() {
354             return DUMMY_HOME_ID;
355         }
356
357         @Override
358         protected void triggerChannel(@NonNull String channelID, @NonNull String event) {
359             triggerChannelCount++;
360             lastDetectedObject = event;
361             super.triggerChannel(channelID, event);
362         }
363
364         private int getTriggerChannelCount() {
365             return triggerChannelCount;
366         }
367
368         public String getLastDetectedObject() {
369             return lastDetectedObject;
370         }
371     }
372 }