]> git.basschouten.com Git - openhab-addons.git/blob
0a21801e113744fc290a7035d9fc4cc87854875d
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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.hue.internal.handler;
14
15 import static org.junit.jupiter.api.Assertions.*;
16 import static org.mockito.ArgumentMatchers.*;
17 import static org.mockito.Mockito.*;
18 import static org.openhab.binding.hue.internal.HueBindingConstants.*;
19
20 import java.util.Collections;
21
22 import org.junit.jupiter.api.BeforeEach;
23 import org.junit.jupiter.api.Test;
24 import org.mockito.ArgumentCaptor;
25 import org.openhab.binding.hue.internal.FullConfig;
26 import org.openhab.binding.hue.internal.FullLight;
27 import org.openhab.binding.hue.internal.State.ColorMode;
28 import org.openhab.binding.hue.internal.StateUpdate;
29 import org.openhab.core.config.core.Configuration;
30 import org.openhab.core.library.types.HSBType;
31 import org.openhab.core.library.types.IncreaseDecreaseType;
32 import org.openhab.core.library.types.OnOffType;
33 import org.openhab.core.library.types.PercentType;
34 import org.openhab.core.library.types.StringType;
35 import org.openhab.core.thing.Bridge;
36 import org.openhab.core.thing.ChannelUID;
37 import org.openhab.core.thing.Thing;
38 import org.openhab.core.thing.ThingStatus;
39 import org.openhab.core.thing.ThingUID;
40 import org.openhab.core.types.Command;
41
42 import com.google.gson.Gson;
43 import com.google.gson.JsonElement;
44 import com.google.gson.JsonParser;
45
46 /**
47  * Tests for {@link HueLightHandler}.
48  *
49  * @author Oliver Libutzki - Initial contribution
50  * @author Michael Grammling - Initial contribution
51  * @author Markus Mazurczak - Added test for OSRAM Par16 50 TW bulbs
52  * @author Andre Fuechsel - modified tests after introducing the generic thing types
53  * @author Denis Dudnik - switched to internally integrated source of Jue library
54  * @author Simon Kaufmann - migrated to plain Java test
55  * @author Christoph Weitkamp - Added support for bulbs using CIE XY colormode only
56  */
57 public class HueLightHandlerTest {
58
59     private static final int MIN_COLOR_TEMPERATURE = 153;
60     private static final int MAX_COLOR_TEMPERATURE = 500;
61     private static final int COLOR_TEMPERATURE_RANGE = MAX_COLOR_TEMPERATURE - MIN_COLOR_TEMPERATURE;
62
63     private static final String OSRAM_MODEL_TYPE = "PAR16 50 TW";
64     private static final String OSRAM_MODEL_TYPE_ID = "PAR16_50_TW";
65
66     private Gson gson;
67
68     @BeforeEach
69     public void setUp() {
70         gson = new Gson();
71     }
72
73     @Test
74     public void assertCommandForOsramPar1650ForColorTemperatureChannelOn() {
75         String expectedReply = "{\"on\" : true, \"bri\" : 254}";
76         assertSendCommandForColorTempForPar16(OnOffType.ON, new HueLightState(OSRAM_MODEL_TYPE), expectedReply);
77     }
78
79     @Test
80     public void assertCommandForOsramPar1650ForColorTemperatureChannelOff() {
81         String expectedReply = "{\"on\" : false, \"transitiontime\" : 0}";
82         assertSendCommandForColorTempForPar16(OnOffType.OFF, new HueLightState(OSRAM_MODEL_TYPE), expectedReply);
83     }
84
85     @Test
86     public void assertCommandForOsramPar1650ForBrightnessChannelOn() {
87         String expectedReply = "{\"on\" : true, \"bri\" : 254}";
88         assertSendCommandForBrightnessForPar16(OnOffType.ON, new HueLightState(OSRAM_MODEL_TYPE), expectedReply);
89     }
90
91     @Test
92     public void assertCommandForOsramPar1650ForBrightnessChannelOff() {
93         String expectedReply = "{\"on\" : false, \"transitiontime\" : 0}";
94         assertSendCommandForBrightnessForPar16(OnOffType.OFF, new HueLightState(OSRAM_MODEL_TYPE), expectedReply);
95     }
96
97     @Test
98     public void assertCommandForColorChannelOn() {
99         String expectedReply = "{\"on\" : true}";
100         assertSendCommandForColor(OnOffType.ON, new HueLightState(), expectedReply);
101     }
102
103     @Test
104     public void assertCommandForColorTemperatureChannelOn() {
105         String expectedReply = "{\"on\" : true}";
106         assertSendCommandForColorTemp(OnOffType.ON, new HueLightState(), expectedReply);
107     }
108
109     @Test
110     public void assertCommandForColorChannelOff() {
111         String expectedReply = "{\"on\" : false}";
112         assertSendCommandForColor(OnOffType.OFF, new HueLightState(), expectedReply);
113     }
114
115     @Test
116     public void assertCommandForColorTemperatureChannelOff() {
117         String expectedReply = "{\"on\" : false}";
118         assertSendCommandForColorTemp(OnOffType.OFF, new HueLightState(), expectedReply);
119     }
120
121     @Test
122     public void assertCommandForColorTemperatureChannel0Percent() {
123         String expectedReply = "{\"ct\" : 153, \"transitiontime\" : 4}";
124         assertSendCommandForColorTemp(new PercentType(0), new HueLightState(), expectedReply);
125     }
126
127     @Test
128     public void assertCommandForColorTemperatureChannel50Percent() {
129         String expectedReply = "{\"ct\" : 327, \"transitiontime\" : 4}";
130         assertSendCommandForColorTemp(new PercentType(50), new HueLightState(), expectedReply);
131     }
132
133     @Test
134     public void assertCommandForColorTemperatureChannel1000Percent() {
135         String expectedReply = "{\"ct\" : 500, \"transitiontime\" : 4}";
136         assertSendCommandForColorTemp(new PercentType(100), new HueLightState(), expectedReply);
137     }
138
139     @Test
140     public void assertPercentageValueOfColorTemperatureWhenCt153() {
141         int expectedReply = 0;
142         asserttoColorTemperaturePercentType(153, expectedReply);
143     }
144
145     @Test
146     public void assertPercentageValueOfColorTemperatureWhenCt326() {
147         int expectedReply = 50;
148         asserttoColorTemperaturePercentType(326, expectedReply);
149     }
150
151     @Test
152     public void assertPercentageValueOfColorTemperatureWhenCt500() {
153         int expectedReply = 100;
154         asserttoColorTemperaturePercentType(500, expectedReply);
155     }
156
157     @Test
158     public void assertCommandForColorChannel0Percent() {
159         String expectedReply = "{\"on\" : false, \"transitiontime\" : 4}";
160         assertSendCommandForColor(new PercentType(0), new HueLightState(), expectedReply);
161     }
162
163     @Test
164     public void assertCommandForColorChannel50Percent() {
165         String expectedReply = "{\"bri\" : 127, \"on\" : true, \"transitiontime\" : 4}";
166         assertSendCommandForColor(new PercentType(50), new HueLightState(), expectedReply);
167     }
168
169     @Test
170     public void assertCommandForColorChannel100Percent() {
171         String expectedReply = "{\"bri\" : 254, \"on\" : true, \"transitiontime\" : 4}";
172         assertSendCommandForColor(new PercentType(100), new HueLightState(), expectedReply);
173     }
174
175     @Test
176     public void assertCommandForColorChannelBlack() {
177         String expectedReply = "{\"on\" : false}";
178         assertSendCommandForColor(HSBType.BLACK, new HueLightState(), expectedReply);
179     }
180
181     @Test
182     public void assertCommandForColorChannelRed() {
183         String expectedReply = "{\"bri\" : 254, \"sat\" : 254, \"hue\" : 0, \"transitiontime\" : 4}";
184         assertSendCommandForColor(HSBType.RED, new HueLightState(), expectedReply);
185     }
186
187     @Test
188     public void assertCommandForColorChannelGreen() {
189         String expectedReply = "{\"bri\" : 254, \"sat\" : 254, \"hue\" : 21845, \"transitiontime\" : 4}";
190         assertSendCommandForColor(HSBType.GREEN, new HueLightState(), expectedReply);
191     }
192
193     @Test
194     public void assertCommandForColorChannelBlue() {
195         String expectedReply = "{\"bri\" : 254, \"sat\" : 254, \"hue\" : 43690, \"transitiontime\" : 4}";
196         assertSendCommandForColor(HSBType.BLUE, new HueLightState(), expectedReply);
197     }
198
199     @Test
200     public void assertCommandForColorChannelWhite() {
201         String expectedReply = "{\"bri\" : 254, \"sat\" : 0, \"hue\" : 0, \"transitiontime\" : 4}";
202         assertSendCommandForColor(HSBType.WHITE, new HueLightState(), expectedReply);
203     }
204
205     @Test
206     public void assertXYCommandForColorChannelBlack() {
207         String expectedReply = "{\"on\" : false}";
208         assertSendCommandForColor(HSBType.BLACK, new HueLightState().colormode(ColorMode.XY), expectedReply);
209     }
210
211     @Test
212     public void assertXYCommandForColorChannelWhite() {
213         String expectedReply = "{\"xy\" : [ 0.31271592 , 0.32900152 ], \"bri\" : 254, \"transitiontime\" : 4}";
214         assertSendCommandForColor(HSBType.WHITE, new HueLightState().colormode(ColorMode.XY), expectedReply);
215     }
216
217     @Test
218     public void assertXYCommandForColorChannelColorful() {
219         String expectedReply = "{\"xy\" : [ 0.16969365 , 0.12379659 ], \"bri\" : 127, \"transitiontime\" : 4}";
220         assertSendCommandForColor(new HSBType("220,90,50"), new HueLightState().colormode(ColorMode.XY), expectedReply);
221     }
222
223     @Test
224     public void asserCommandForColorChannelIncrease() {
225         HueLightState currentState = new HueLightState().bri(1).on(false);
226         String expectedReply = "{\"bri\" : 30, \"on\" : true, \"transitiontime\" : 4}";
227         assertSendCommandForColor(IncreaseDecreaseType.INCREASE, currentState, expectedReply);
228
229         currentState.bri(200).on(true);
230         expectedReply = "{\"bri\" : 230, \"transitiontime\" : 4}";
231         assertSendCommandForColor(IncreaseDecreaseType.INCREASE, currentState, expectedReply);
232
233         currentState.bri(230);
234         expectedReply = "{\"bri\" : 254, \"transitiontime\" : 4}";
235         assertSendCommandForColor(IncreaseDecreaseType.INCREASE, currentState, expectedReply);
236     }
237
238     @Test
239     public void asserCommandForColorChannelDecrease() {
240         HueLightState currentState = new HueLightState().bri(200);
241         String expectedReply = "{\"bri\" : 170, \"transitiontime\" : 4}";
242         assertSendCommandForColor(IncreaseDecreaseType.DECREASE, currentState, expectedReply);
243
244         currentState.bri(20);
245         expectedReply = "{\"on\" : false, \"transitiontime\" : 4}";
246         assertSendCommandForColor(IncreaseDecreaseType.DECREASE, currentState, expectedReply);
247     }
248
249     @Test
250     public void assertCommandForBrightnessChannel50Percent() {
251         HueLightState currentState = new HueLightState();
252         String expectedReply = "{\"bri\" : 127, \"on\" : true, \"transitiontime\" : 4}";
253         assertSendCommandForBrightness(new PercentType(50), currentState, expectedReply);
254     }
255
256     @Test
257     public void assertCommandForBrightnessChannelIncrease() {
258         HueLightState currentState = new HueLightState().bri(1).on(false);
259         String expectedReply = "{\"bri\" : 30, \"on\" : true, \"transitiontime\" : 4}";
260         assertSendCommandForBrightness(IncreaseDecreaseType.INCREASE, currentState, expectedReply);
261
262         currentState.bri(200).on(true);
263         expectedReply = "{\"bri\" : 230, \"transitiontime\" : 4}";
264         assertSendCommandForBrightness(IncreaseDecreaseType.INCREASE, currentState, expectedReply);
265
266         currentState.bri(230);
267         expectedReply = "{\"bri\" : 254, \"transitiontime\" : 4}";
268         assertSendCommandForBrightness(IncreaseDecreaseType.INCREASE, currentState, expectedReply);
269     }
270
271     @Test
272     public void assertCommandForBrightnessChannelDecrease() {
273         HueLightState currentState = new HueLightState().bri(200);
274         String expectedReply = "{\"bri\" : 170, \"transitiontime\" : 4}";
275         assertSendCommandForBrightness(IncreaseDecreaseType.DECREASE, currentState, expectedReply);
276
277         currentState.bri(20);
278         expectedReply = "{\"on\" : false, \"transitiontime\" : 4}";
279         assertSendCommandForBrightness(IncreaseDecreaseType.DECREASE, currentState, expectedReply);
280     }
281
282     @Test
283     public void assertCommandForBrightnessChannelOff() {
284         HueLightState currentState = new HueLightState();
285         String expectedReply = "{\"on\" : false}";
286         assertSendCommandForBrightness(OnOffType.OFF, currentState, expectedReply);
287     }
288
289     @Test
290     public void assertCommandForBrightnessChannelOn() {
291         HueLightState currentState = new HueLightState();
292         String expectedReply = "{\"on\" : true}";
293         assertSendCommandForBrightness(OnOffType.ON, currentState, expectedReply);
294     }
295
296     @Test
297     public void assertCommandForAlertChannel() {
298         HueLightState currentState = new HueLightState().alert("NONE");
299         String expectedReply = "{\"alert\" : \"none\"}";
300         assertSendCommandForAlert(new StringType("NONE"), currentState, expectedReply);
301
302         currentState.alert("NONE");
303         expectedReply = "{\"alert\" : \"select\"}";
304         assertSendCommandForAlert(new StringType("SELECT"), currentState, expectedReply);
305
306         currentState.alert("LSELECT");
307         expectedReply = "{\"alert\" : \"lselect\"}";
308         assertSendCommandForAlert(new StringType("LSELECT"), currentState, expectedReply);
309     }
310
311     @Test
312     public void assertCommandForEffectChannel() {
313         HueLightState currentState = new HueLightState().effect("ON");
314         String expectedReply = "{\"effect\" : \"colorloop\"}";
315         assertSendCommandForEffect(OnOffType.ON, currentState, expectedReply);
316
317         currentState.effect("OFF");
318         expectedReply = "{\"effect\" : \"none\"}";
319         assertSendCommandForEffect(OnOffType.OFF, currentState, expectedReply);
320     }
321
322     private void assertSendCommandForColorTempForPar16(Command command, HueLightState currentState,
323             String expectedReply) {
324         assertSendCommand(CHANNEL_COLORTEMPERATURE, command, currentState, expectedReply, OSRAM_MODEL_TYPE_ID, "OSRAM");
325     }
326
327     private void assertSendCommandForBrightnessForPar16(Command command, HueLightState currentState,
328             String expectedReply) {
329         assertSendCommand(CHANNEL_BRIGHTNESS, command, currentState, expectedReply, OSRAM_MODEL_TYPE_ID, "OSRAM");
330     }
331
332     private void assertSendCommandForColor(Command command, HueLightState currentState, String expectedReply) {
333         assertSendCommand(CHANNEL_COLOR, command, currentState, expectedReply);
334     }
335
336     private void assertSendCommandForColorTemp(Command command, HueLightState currentState, String expectedReply) {
337         assertSendCommand(CHANNEL_COLORTEMPERATURE, command, currentState, expectedReply);
338     }
339
340     private void asserttoColorTemperaturePercentType(int ctValue, int expectedPercent) {
341         int percent = (int) Math.round(((ctValue - MIN_COLOR_TEMPERATURE) * 100.0) / COLOR_TEMPERATURE_RANGE);
342         assertEquals(percent, expectedPercent);
343     }
344
345     private void assertSendCommandForBrightness(Command command, HueLightState currentState, String expectedReply) {
346         assertSendCommand(CHANNEL_BRIGHTNESS, command, currentState, expectedReply);
347     }
348
349     private void assertSendCommandForAlert(Command command, HueLightState currentState, String expectedReply) {
350         assertSendCommand(CHANNEL_ALERT, command, currentState, expectedReply);
351     }
352
353     private void assertSendCommandForEffect(Command command, HueLightState currentState, String expectedReply) {
354         assertSendCommand(CHANNEL_EFFECT, command, currentState, expectedReply);
355     }
356
357     private void assertSendCommand(String channel, Command command, HueLightState currentState, String expectedReply) {
358         assertSendCommand(channel, command, currentState, expectedReply, "LCT001", "Philips");
359     }
360
361     private void assertSendCommand(String channel, Command command, HueLightState currentState, String expectedReply,
362             String expectedModel, String expectedVendor) {
363         FullLight light = gson.fromJson(currentState.toString(), FullConfig.class).getLights().get(0);
364
365         Bridge mockBridge = mock(Bridge.class);
366         when(mockBridge.getStatus()).thenReturn(ThingStatus.ONLINE);
367
368         Thing mockThing = mock(Thing.class);
369         when(mockThing.getConfiguration()).thenReturn(new Configuration(Collections.singletonMap(LIGHT_ID, "1")));
370
371         HueClient mockClient = mock(HueClient.class);
372         when(mockClient.getLightById(any())).thenReturn(light);
373
374         long fadeTime = 400;
375
376         HueLightHandler hueLightHandler = new HueLightHandler(mockThing) {
377             @Override
378             protected synchronized HueClient getHueClient() {
379                 return mockClient;
380             }
381
382             @Override
383             protected Bridge getBridge() {
384                 return mockBridge;
385             }
386         };
387         hueLightHandler.initialize();
388
389         verify(mockThing).setProperty(eq(Thing.PROPERTY_MODEL_ID), eq(expectedModel));
390         verify(mockThing).setProperty(eq(Thing.PROPERTY_VENDOR), eq(expectedVendor));
391
392         hueLightHandler.handleCommand(new ChannelUID(new ThingUID("hue::test"), channel), command);
393
394         ArgumentCaptor<StateUpdate> captorStateUpdate = ArgumentCaptor.forClass(StateUpdate.class);
395         verify(mockClient).updateLightState(any(LightStatusListener.class), any(FullLight.class),
396                 captorStateUpdate.capture(), eq(fadeTime));
397         assertJson(expectedReply, captorStateUpdate.getValue().toJson());
398     }
399
400     private void assertJson(String expected, String actual) {
401         JsonParser parser = new JsonParser();
402         JsonElement jsonExpected = parser.parse(expected);
403         JsonElement jsonActual = parser.parse(actual);
404         assertEquals(jsonExpected, jsonActual);
405     }
406 }