]> git.basschouten.com Git - openhab-addons.git/blob
f91c919f567865563ce101ae7c7782b6e08cb06c
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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.mqtt.generic.values;
14
15 import static org.hamcrest.CoreMatchers.is;
16 import static org.hamcrest.MatcherAssert.assertThat;
17 import static org.junit.jupiter.api.Assertions.*;
18
19 import java.math.BigDecimal;
20 import java.util.Objects;
21
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.junit.jupiter.api.Test;
24 import org.openhab.binding.mqtt.generic.mapping.ColorMode;
25 import org.openhab.core.library.types.DecimalType;
26 import org.openhab.core.library.types.HSBType;
27 import org.openhab.core.library.types.IncreaseDecreaseType;
28 import org.openhab.core.library.types.OnOffType;
29 import org.openhab.core.library.types.OpenClosedType;
30 import org.openhab.core.library.types.PercentType;
31 import org.openhab.core.library.types.QuantityType;
32 import org.openhab.core.library.types.StopMoveType;
33 import org.openhab.core.library.types.StringType;
34 import org.openhab.core.library.types.UpDownType;
35 import org.openhab.core.library.unit.MetricPrefix;
36 import org.openhab.core.library.unit.Units;
37 import org.openhab.core.types.Command;
38 import org.openhab.core.types.State;
39 import org.openhab.core.types.TypeParser;
40 import org.openhab.core.types.UnDefType;
41
42 /**
43  * Test cases for the value classes. They should throw exceptions if the wrong command type is used
44  * for an update. The percent value class should raise an exception if the value is out of range.
45  *
46  * The on/off value class should accept a multitude of values including the custom defined ones.
47  *
48  * The string value class states are tested.
49  *
50  * @author David Graeff - Initial contribution
51  */
52 @NonNullByDefault
53 public class ValueTests {
54     private Command p(Value v, String str) {
55         return Objects.requireNonNull(TypeParser.parseCommand(v.getSupportedCommandTypes(), str));
56     }
57
58     @Test
59     public void illegalTextStateUpdate() {
60         TextValue v = new TextValue("one,two".split(","));
61         assertThrows(IllegalArgumentException.class, () -> v.parseCommand(p(v, "three")));
62     }
63
64     @Test
65     public void textStateUpdate() {
66         TextValue v = new TextValue("one,two".split(","));
67         v.parseCommand(p(v, "one"));
68     }
69
70     @Test
71     public void colorUpdate() {
72         ColorValue v = new ColorValue(ColorMode.RGB, "fancyON", "fancyOFF", 77);
73         v.update((State) v.parseCommand(p(v, "255,255,255")));
74
75         HSBType hsb = (HSBType) v.parseCommand(p(v, "OFF"));
76         assertThat(hsb.getBrightness().intValue(), is(0));
77         v.update(hsb);
78         hsb = (HSBType) v.parseCommand(p(v, "ON"));
79         assertThat(hsb.getBrightness().intValue(), is(77));
80
81         hsb = (HSBType) v.parseCommand(p(v, "0"));
82         assertThat(hsb.getBrightness().intValue(), is(0));
83         hsb = (HSBType) v.parseCommand(p(v, "1"));
84         assertThat(hsb.getBrightness().intValue(), is(1));
85
86         assertThat(v.parseMessage(new StringType("")), is(UnDefType.NULL));
87     }
88
89     @Test
90     public void illegalColorUpdate() {
91         ColorValue v = new ColorValue(ColorMode.RGB, null, null, 10);
92         assertThrows(IllegalArgumentException.class, () -> v.parseCommand(p(v, "255,255,abc")));
93     }
94
95     @Test
96     public void illegalNumberCommand() {
97         NumberValue v = new NumberValue(null, null, null, null);
98         assertThrows(IllegalArgumentException.class, () -> v.parseCommand(OnOffType.OFF));
99     }
100
101     @Test
102     public void illegalPercentCommand() {
103         PercentageValue v = new PercentageValue(null, null, null, null, null);
104         assertThrows(IllegalStateException.class, () -> v.parseCommand(new StringType("demo")));
105     }
106
107     @Test
108     public void illegalOnOffCommand() {
109         OnOffValue v = new OnOffValue(null, null);
110         assertThrows(IllegalArgumentException.class, () -> v.parseCommand(new DecimalType(101.0)));
111     }
112
113     @Test
114     public void illegalPercentUpdate() {
115         PercentageValue v = new PercentageValue(null, null, null, null, null);
116         assertThrows(IllegalArgumentException.class, () -> v.parseCommand(new DecimalType(101.0)));
117     }
118
119     @Test
120     public void onoffUpdate() {
121         OnOffValue v = new OnOffValue("fancyON", "fancyOff");
122
123         // Test with command
124         assertThat(v.parseCommand(OnOffType.OFF), is(OnOffType.OFF));
125         assertThat(v.parseCommand(OnOffType.ON), is(OnOffType.ON));
126
127         // Test with string, representing the command
128         assertThat(v.parseCommand(new StringType("OFF")), is(OnOffType.OFF));
129         assertThat(v.parseCommand(new StringType("ON")), is(OnOffType.ON));
130
131         // Test with custom string, setup in the constructor
132         assertThat(v.parseCommand(new StringType("fancyOff")), is(OnOffType.OFF));
133         assertThat(v.parseCommand(new StringType("fancyON")), is(OnOffType.ON));
134
135         // Test basic formatting
136         assertThat(v.getMQTTpublishValue(OnOffType.ON, null), is("fancyON"));
137         assertThat(v.getMQTTpublishValue(OnOffType.OFF, null), is("fancyOff"));
138
139         // Test custom formatting
140         assertThat(v.getMQTTpublishValue(OnOffType.OFF, "=%s"), is("=fancyOff"));
141         assertThat(v.getMQTTpublishValue(OnOffType.ON, "=%s"), is("=fancyON"));
142
143         assertThat(v.parseMessage(new StringType("")), is(UnDefType.NULL));
144     }
145
146     @Test
147     public void onoffMultiStates() {
148         OnOffValue v = new OnOffValue(new String[] { "LOCKED" }, new String[] { "UNLOCKED", "JAMMED" }, "LOCK",
149                 "UNLOCK");
150
151         assertThat(v.parseCommand(new StringType("LOCKED")), is(OnOffType.ON));
152         assertThat(v.parseCommand(new StringType("UNLOCKED")), is(OnOffType.OFF));
153         assertThat(v.parseCommand(new StringType("JAMMED")), is(OnOffType.OFF));
154     }
155
156     @Test
157     public void openCloseUpdate() {
158         OpenCloseValue v = new OpenCloseValue("fancyON", "fancyOff");
159
160         // Test with command
161         assertThat(v.parseCommand(OpenClosedType.CLOSED), is(OpenClosedType.CLOSED));
162         assertThat(v.parseCommand(OpenClosedType.OPEN), is(OpenClosedType.OPEN));
163
164         // Test with string, representing the command
165         assertThat(v.parseCommand(new StringType("CLOSED")), is(OpenClosedType.CLOSED));
166         assertThat(v.parseCommand(new StringType("OPEN")), is(OpenClosedType.OPEN));
167
168         // Test with custom string, setup in the constructor
169         assertThat(v.parseCommand(new StringType("fancyOff")), is(OpenClosedType.CLOSED));
170         assertThat(v.parseCommand(new StringType("fancyON")), is(OpenClosedType.OPEN));
171
172         // Test basic formatting
173         assertThat(v.getMQTTpublishValue(OpenClosedType.CLOSED, null), is("fancyOff"));
174         assertThat(v.getMQTTpublishValue(OpenClosedType.OPEN, null), is("fancyON"));
175
176         assertThat(v.parseMessage(new StringType("")), is(UnDefType.NULL));
177     }
178
179     @Test
180     public void numberUpdate() {
181         NumberValue v = new NumberValue(null, null, new BigDecimal(10), Units.WATT);
182
183         // Test with command with units
184         Command command = v.parseCommand(new QuantityType<>(20, Units.WATT));
185         assertThat(command, is(new QuantityType<>(20, Units.WATT)));
186         assertThat(v.getMQTTpublishValue(command, null), is("20"));
187         command = v.parseCommand(new QuantityType<>(20, MetricPrefix.KILO(Units.WATT)));
188         assertThat(command, is(new QuantityType<>(20, MetricPrefix.KILO(Units.WATT))));
189         assertThat(v.getMQTTpublishValue(command, null), is("20000"));
190
191         // Test with command without units
192         command = v.parseCommand(new QuantityType<>("20"));
193         assertThat(command, is(new QuantityType<>(20, Units.WATT)));
194         assertThat(v.getMQTTpublishValue(command, null), is("20"));
195
196         assertThat(v.parseMessage(new StringType("NaN")), is(UnDefType.UNDEF));
197         assertThat(v.parseMessage(new StringType("nan")), is(UnDefType.UNDEF));
198         assertThat(v.parseMessage(new StringType("-NaN")), is(UnDefType.UNDEF));
199         assertThat(v.parseMessage(new StringType("-nan")), is(UnDefType.UNDEF));
200
201         assertThat(v.parseMessage(new StringType("")), is(UnDefType.NULL));
202     }
203
204     @Test
205     public void numberUpdateMireds() {
206         NumberValue v = new NumberValue(null, null, new BigDecimal(10), Units.MIRED);
207
208         Command command = v.parseCommand(new QuantityType<>(2700, Units.KELVIN));
209         assertThat(v.getMQTTpublishValue(command, "%.0f"), is("370"));
210     }
211
212     @Test
213     public void numberPercentageUpdate() {
214         NumberValue v = new NumberValue(null, null, new BigDecimal(10), Units.PERCENT);
215
216         // Test with command with units
217         Command command = v.parseCommand(new QuantityType<>(20, Units.PERCENT));
218         assertThat(command, is(new QuantityType<>(20, Units.PERCENT)));
219         assertThat(v.getMQTTpublishValue(command, null), is("20"));
220
221         // Test with command without units
222         command = v.parseCommand(new QuantityType<>("20"));
223         assertThat(command, is(new QuantityType<>(20, Units.PERCENT)));
224         assertThat(v.getMQTTpublishValue(command, null), is("20"));
225     }
226
227     @Test
228     public void rollershutterUpdateWithStrings() {
229         RollershutterValue v = new RollershutterValue("fancyON", "fancyOff", "fancyStop");
230         // Test with UP/DOWN/STOP command
231         assertThat(v.parseCommand(UpDownType.UP), is(UpDownType.UP));
232         assertThat(v.getMQTTpublishValue(UpDownType.UP, null), is("fancyON"));
233         assertThat(v.parseCommand(UpDownType.DOWN), is(UpDownType.DOWN));
234         assertThat(v.getMQTTpublishValue(UpDownType.DOWN, null), is("fancyOff"));
235         assertThat(v.parseCommand(StopMoveType.STOP), is(StopMoveType.STOP));
236         assertThat(v.getMQTTpublishValue(StopMoveType.STOP, null), is("fancyStop"));
237
238         // Test with custom string
239         assertThat(v.parseCommand(new StringType("fancyON")), is(UpDownType.UP));
240         assertThat(v.parseCommand(new StringType("fancyOff")), is(UpDownType.DOWN));
241
242         // Test with exact percent
243         Command command = new PercentType(27);
244         assertThat(v.parseCommand((Command) command), is(command));
245         assertThat(v.getMQTTpublishValue(command, null), is("27"));
246
247         // Test formatting 0/100
248         assertThat(v.getMQTTpublishValue(PercentType.ZERO, null), is("fancyON"));
249         assertThat(v.getMQTTpublishValue(PercentType.HUNDRED, null), is("fancyOff"));
250
251         // Test parsing from MQTT
252         assertThat(v.parseMessage(new StringType("fancyON")), is(UpDownType.UP));
253         assertThat(v.parseMessage(new StringType("fancyOff")), is(UpDownType.DOWN));
254
255         assertThat(v.parseMessage(new StringType("")), is(UnDefType.NULL));
256     }
257
258     @Test
259     public void rollershutterUpdateWithDiscreteCommandAndStateStrings() {
260         RollershutterValue v = new RollershutterValue("OPEN", "CLOSE", "STOP", "open", "closed", false, true);
261         // Test with UP/DOWN/STOP command
262         assertThat(v.parseCommand(UpDownType.UP), is(UpDownType.UP));
263         assertThat(v.getMQTTpublishValue(UpDownType.UP, null), is("OPEN"));
264         assertThat(v.parseCommand(UpDownType.DOWN), is(UpDownType.DOWN));
265         assertThat(v.getMQTTpublishValue(UpDownType.DOWN, null), is("CLOSE"));
266         assertThat(v.parseCommand(StopMoveType.STOP), is(StopMoveType.STOP));
267         assertThat(v.getMQTTpublishValue(StopMoveType.STOP, null), is("STOP"));
268
269         // Test with custom string
270         assertThat(v.parseCommand(new StringType("OPEN")), is(UpDownType.UP));
271         assertThat(v.parseCommand(new StringType("CLOSE")), is(UpDownType.DOWN));
272
273         // Test with exact percent
274         Command command = new PercentType(27);
275         assertThat(v.parseCommand((Command) command), is(command));
276         assertThat(v.getMQTTpublishValue(command, null), is("27"));
277
278         // Test formatting 0/100
279         assertThat(v.getMQTTpublishValue(PercentType.ZERO, null), is("OPEN"));
280         assertThat(v.getMQTTpublishValue(PercentType.HUNDRED, null), is("CLOSE"));
281
282         // Test parsing from MQTT
283         assertThat(v.parseMessage(new StringType("open")), is(UpDownType.UP));
284         assertThat(v.parseMessage(new StringType("closed")), is(UpDownType.DOWN));
285     }
286
287     @Test
288     public void rollershutterUpdateWithOutStrings() {
289         RollershutterValue v = new RollershutterValue(null, null, "fancyStop");
290         // Test with command
291         assertThat(v.parseCommand(UpDownType.UP), is(PercentType.ZERO));
292         assertThat(v.parseCommand(UpDownType.DOWN), is(PercentType.HUNDRED));
293
294         // Test with custom string
295         // Test formatting 0/100
296         assertThat(v.getMQTTpublishValue(PercentType.ZERO, null), is("0"));
297         assertThat(v.getMQTTpublishValue(PercentType.HUNDRED, null), is("100"));
298     }
299
300     @Test
301     public void percentCalc() {
302         PercentageValue v = new PercentageValue(new BigDecimal(10.0), new BigDecimal(110.0), new BigDecimal(1.0), null,
303                 null);
304         assertThat(v.parseCommand(new DecimalType("110.0")), is(PercentType.HUNDRED));
305         assertThat(v.getMQTTpublishValue(PercentType.HUNDRED, null), is("110"));
306         assertThat(v.parseCommand(new DecimalType(10.0)), is(PercentType.ZERO));
307         assertThat(v.getMQTTpublishValue(PercentType.ZERO, null), is("10"));
308
309         assertThat(v.parseCommand(OnOffType.ON), is(PercentType.HUNDRED));
310         assertThat(v.parseCommand(OnOffType.OFF), is(PercentType.ZERO));
311     }
312
313     @Test
314     public void percentMQTTValue() {
315         PercentageValue v = new PercentageValue(null, null, null, null, null);
316         assertThat(v.parseCommand(new DecimalType("10.10000")), is(new PercentType("10.1")));
317         assertThat(v.getMQTTpublishValue(new PercentType("10.1"), null), is("10.1"));
318         Command command;
319         for (int i = 0; i <= 100; i++) {
320             command = v.parseCommand(new DecimalType(i));
321             assertThat(v.getMQTTpublishValue(command, null), is("" + i));
322         }
323
324         assertThat(v.parseMessage(new StringType("")), is(UnDefType.NULL));
325     }
326
327     @Test
328     public void percentCustomOnOff() {
329         PercentageValue v = new PercentageValue(new BigDecimal("0.0"), new BigDecimal("100.0"), new BigDecimal("1.0"),
330                 "on", "off");
331         assertThat(v.parseCommand(new StringType("on")), is(PercentType.HUNDRED));
332         assertThat(v.parseCommand(new StringType("off")), is(PercentType.ZERO));
333     }
334
335     @Test
336     public void decimalCalc() {
337         PercentageValue v = new PercentageValue(new BigDecimal("0.1"), new BigDecimal("1.0"), new BigDecimal("0.1"),
338                 null, null);
339         assertThat(v.parseCommand(new DecimalType(1.0)), is(PercentType.HUNDRED));
340         assertThat(v.parseCommand(new DecimalType(0.1)), is(PercentType.ZERO));
341         PercentType command = (PercentType) v.parseCommand(new DecimalType(0.2));
342         assertEquals(command.floatValue(), 11.11f, 0.01f);
343     }
344
345     @Test
346     public void increaseDecreaseCalc() {
347         PercentageValue v = new PercentageValue(new BigDecimal("1.0"), new BigDecimal("11.0"), new BigDecimal("0.5"),
348                 null, null);
349
350         // Normal operation.
351         PercentType command = (PercentType) v.parseCommand(new DecimalType("6.0"));
352         assertEquals(command.floatValue(), 50.0f, 0.01f);
353         v.update(command);
354         command = (PercentType) v.parseCommand(IncreaseDecreaseType.INCREASE);
355         assertEquals(command.floatValue(), 55.0f, 0.01f);
356         command = (PercentType) v.parseCommand(IncreaseDecreaseType.DECREASE);
357         assertEquals(command.floatValue(), 45.0f, 0.01f);
358
359         // Lower limit.
360         command = (PercentType) v.parseCommand(new DecimalType("1.1"));
361         assertEquals(command.floatValue(), 1.0f, 0.01f);
362         v.update(command);
363         command = (PercentType) v.parseCommand(IncreaseDecreaseType.DECREASE);
364         assertEquals(command.floatValue(), 0.0f, 0.01f);
365
366         // Upper limit.
367         command = (PercentType) v.parseCommand(new DecimalType("10.8"));
368         assertEquals(command.floatValue(), 98.0f, 0.01f);
369         v.update(command);
370         command = (PercentType) v.parseCommand(IncreaseDecreaseType.INCREASE);
371         assertEquals(command.floatValue(), 100.0f, 0.01f);
372     }
373
374     @Test
375     public void upDownCalc() {
376         PercentageValue v = new PercentageValue(new BigDecimal("1.0"), new BigDecimal("11.0"), new BigDecimal("0.5"),
377                 null, null);
378
379         // Normal operation.
380         PercentType command = (PercentType) v.parseCommand(new DecimalType("6.0"));
381         assertEquals(command.floatValue(), 50.0f, 0.01f);
382         v.update(command);
383         command = (PercentType) v.parseCommand(UpDownType.UP);
384         assertEquals(command.floatValue(), 55.0f, 0.01f);
385         command = (PercentType) v.parseCommand(UpDownType.DOWN);
386         assertEquals(command.floatValue(), 45.0f, 0.01f);
387
388         // Lower limit.
389         command = (PercentType) v.parseCommand(new DecimalType("1.1"));
390         assertEquals(command.floatValue(), 1.0f, 0.01f);
391         v.update(command);
392         command = (PercentType) v.parseCommand(UpDownType.DOWN);
393         assertEquals(command.floatValue(), 0.0f, 0.01f);
394
395         // Upper limit.
396         command = (PercentType) v.parseCommand(new DecimalType("10.8"));
397         assertEquals(command.floatValue(), 98.0f, 0.01f);
398         v.update(command);
399         command = (PercentType) v.parseCommand(UpDownType.UP);
400         assertEquals(command.floatValue(), 100.0f, 0.01f);
401     }
402
403     @Test
404     public void percentCalcInvalid() {
405         PercentageValue v = new PercentageValue(new BigDecimal(10.0), new BigDecimal(110.0), new BigDecimal(1.0), null,
406                 null);
407         assertThrows(IllegalArgumentException.class, () -> v.parseCommand(new DecimalType(9.0)));
408     }
409
410     @Test
411     public void textUpdate() {
412         TextValue v = new TextValue();
413
414         assertThat(v.parseMessage(new StringType("")), is(new StringType("")));
415         assertThat(v.parseMessage(new StringType("NULL")), is(new StringType("NULL")));
416
417         v.setNullValue("");
418         assertThat(v.parseMessage(new StringType("")), is(UnDefType.NULL));
419         assertThat(v.parseMessage(new StringType("NULL")), is(new StringType("NULL")));
420
421         v.setNullValue("NULL");
422         assertThat(v.parseMessage(new StringType("NULL")), is(UnDefType.NULL));
423         assertThat(v.parseMessage(new StringType("")), is(new StringType("")));
424     }
425 }