]> git.basschouten.com Git - openhab-addons.git/blob
8bb5365abefcf32f16ecbefa8db41c55c075a055
[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
87     @Test
88     public void illegalColorUpdate() {
89         ColorValue v = new ColorValue(ColorMode.RGB, null, null, 10);
90         assertThrows(IllegalArgumentException.class, () -> v.parseCommand(p(v, "255,255,abc")));
91     }
92
93     @Test
94     public void illegalNumberCommand() {
95         NumberValue v = new NumberValue(null, null, null, null);
96         assertThrows(IllegalArgumentException.class, () -> v.parseCommand(OnOffType.OFF));
97     }
98
99     @Test
100     public void illegalPercentCommand() {
101         PercentageValue v = new PercentageValue(null, null, null, null, null);
102         assertThrows(IllegalStateException.class, () -> v.parseCommand(new StringType("demo")));
103     }
104
105     @Test
106     public void illegalOnOffCommand() {
107         OnOffValue v = new OnOffValue(null, null);
108         assertThrows(IllegalArgumentException.class, () -> v.parseCommand(new DecimalType(101.0)));
109     }
110
111     @Test
112     public void illegalPercentUpdate() {
113         PercentageValue v = new PercentageValue(null, null, null, null, null);
114         assertThrows(IllegalArgumentException.class, () -> v.parseCommand(new DecimalType(101.0)));
115     }
116
117     @Test
118     public void onoffUpdate() {
119         OnOffValue v = new OnOffValue("fancyON", "fancyOff");
120
121         // Test with command
122         assertThat(v.parseCommand(OnOffType.OFF), is(OnOffType.OFF));
123         assertThat(v.parseCommand(OnOffType.ON), is(OnOffType.ON));
124
125         // Test with string, representing the command
126         assertThat(v.parseCommand(new StringType("OFF")), is(OnOffType.OFF));
127         assertThat(v.parseCommand(new StringType("ON")), is(OnOffType.ON));
128
129         // Test with custom string, setup in the constructor
130         assertThat(v.parseCommand(new StringType("fancyOff")), is(OnOffType.OFF));
131         assertThat(v.parseCommand(new StringType("fancyON")), is(OnOffType.ON));
132
133         // Test basic formatting
134         assertThat(v.getMQTTpublishValue(OnOffType.ON, null), is("fancyON"));
135         assertThat(v.getMQTTpublishValue(OnOffType.OFF, null), is("fancyOff"));
136
137         // Test custom formatting
138         assertThat(v.getMQTTpublishValue(OnOffType.OFF, "=%s"), is("=fancyOff"));
139         assertThat(v.getMQTTpublishValue(OnOffType.ON, "=%s"), is("=fancyON"));
140     }
141
142     @Test
143     public void onoffMultiStates() {
144         OnOffValue v = new OnOffValue(new String[] { "LOCKED" }, new String[] { "UNLOCKED", "JAMMED" }, "LOCK",
145                 "UNLOCK");
146
147         assertThat(v.parseCommand(new StringType("LOCKED")), is(OnOffType.ON));
148         assertThat(v.parseCommand(new StringType("UNLOCKED")), is(OnOffType.OFF));
149         assertThat(v.parseCommand(new StringType("JAMMED")), is(OnOffType.OFF));
150     }
151
152     @Test
153     public void openCloseUpdate() {
154         OpenCloseValue v = new OpenCloseValue("fancyON", "fancyOff");
155
156         // Test with command
157         assertThat(v.parseCommand(OpenClosedType.CLOSED), is(OpenClosedType.CLOSED));
158         assertThat(v.parseCommand(OpenClosedType.OPEN), is(OpenClosedType.OPEN));
159
160         // Test with string, representing the command
161         assertThat(v.parseCommand(new StringType("CLOSED")), is(OpenClosedType.CLOSED));
162         assertThat(v.parseCommand(new StringType("OPEN")), is(OpenClosedType.OPEN));
163
164         // Test with custom string, setup in the constructor
165         assertThat(v.parseCommand(new StringType("fancyOff")), is(OpenClosedType.CLOSED));
166         assertThat(v.parseCommand(new StringType("fancyON")), is(OpenClosedType.OPEN));
167
168         // Test basic formatting
169         assertThat(v.getMQTTpublishValue(OpenClosedType.CLOSED, null), is("fancyOff"));
170         assertThat(v.getMQTTpublishValue(OpenClosedType.OPEN, null), is("fancyON"));
171     }
172
173     @Test
174     public void numberUpdate() {
175         NumberValue v = new NumberValue(null, null, new BigDecimal(10), Units.WATT);
176
177         // Test with command with units
178         Command command = v.parseCommand(new QuantityType<>(20, Units.WATT));
179         assertThat(command, is(new QuantityType<>(20, Units.WATT)));
180         assertThat(v.getMQTTpublishValue(command, null), is("20"));
181         command = v.parseCommand(new QuantityType<>(20, MetricPrefix.KILO(Units.WATT)));
182         assertThat(command, is(new QuantityType<>(20, MetricPrefix.KILO(Units.WATT))));
183         assertThat(v.getMQTTpublishValue(command, null), is("20000"));
184
185         // Test with command without units
186         command = v.parseCommand(new QuantityType<>("20"));
187         assertThat(command, is(new QuantityType<>(20, Units.WATT)));
188         assertThat(v.getMQTTpublishValue(command, null), is("20"));
189
190         assertThat(v.parseMessage(new StringType("NaN")), is(UnDefType.UNDEF));
191         assertThat(v.parseMessage(new StringType("nan")), is(UnDefType.UNDEF));
192         assertThat(v.parseMessage(new StringType("-NaN")), is(UnDefType.UNDEF));
193         assertThat(v.parseMessage(new StringType("-nan")), is(UnDefType.UNDEF));
194     }
195
196     @Test
197     public void numberUpdateMireds() {
198         NumberValue v = new NumberValue(null, null, new BigDecimal(10), Units.MIRED);
199
200         Command command = v.parseCommand(new QuantityType<>(2700, Units.KELVIN));
201         assertThat(v.getMQTTpublishValue(command, "%.0f"), is("370"));
202     }
203
204     @Test
205     public void numberPercentageUpdate() {
206         NumberValue v = new NumberValue(null, null, new BigDecimal(10), Units.PERCENT);
207
208         // Test with command with units
209         Command command = v.parseCommand(new QuantityType<>(20, Units.PERCENT));
210         assertThat(command, is(new QuantityType<>(20, Units.PERCENT)));
211         assertThat(v.getMQTTpublishValue(command, null), is("20"));
212
213         // Test with command without units
214         command = v.parseCommand(new QuantityType<>("20"));
215         assertThat(command, is(new QuantityType<>(20, Units.PERCENT)));
216         assertThat(v.getMQTTpublishValue(command, null), is("20"));
217     }
218
219     @Test
220     public void rollershutterUpdateWithStrings() {
221         RollershutterValue v = new RollershutterValue("fancyON", "fancyOff", "fancyStop");
222         // Test with UP/DOWN/STOP command
223         assertThat(v.parseCommand(UpDownType.UP), is(UpDownType.UP));
224         assertThat(v.getMQTTpublishValue(UpDownType.UP, null), is("fancyON"));
225         assertThat(v.parseCommand(UpDownType.DOWN), is(UpDownType.DOWN));
226         assertThat(v.getMQTTpublishValue(UpDownType.DOWN, null), is("fancyOff"));
227         assertThat(v.parseCommand(StopMoveType.STOP), is(StopMoveType.STOP));
228         assertThat(v.getMQTTpublishValue(StopMoveType.STOP, null), is("fancyStop"));
229
230         // Test with custom string
231         assertThat(v.parseCommand(new StringType("fancyON")), is(UpDownType.UP));
232         assertThat(v.parseCommand(new StringType("fancyOff")), is(UpDownType.DOWN));
233
234         // Test with exact percent
235         Command command = new PercentType(27);
236         assertThat(v.parseCommand((Command) command), is(command));
237         assertThat(v.getMQTTpublishValue(command, null), is("27"));
238
239         // Test formatting 0/100
240         assertThat(v.getMQTTpublishValue(PercentType.ZERO, null), is("fancyON"));
241         assertThat(v.getMQTTpublishValue(PercentType.HUNDRED, null), is("fancyOff"));
242
243         // Test parsing from MQTT
244         assertThat(v.parseMessage(new StringType("fancyON")), is(UpDownType.UP));
245         assertThat(v.parseMessage(new StringType("fancyOff")), is(UpDownType.DOWN));
246     }
247
248     @Test
249     public void rollershutterUpdateWithDiscreteCommandAndStateStrings() {
250         RollershutterValue v = new RollershutterValue("OPEN", "CLOSE", "STOP", "open", "closed", false, true);
251         // Test with UP/DOWN/STOP command
252         assertThat(v.parseCommand(UpDownType.UP), is(UpDownType.UP));
253         assertThat(v.getMQTTpublishValue(UpDownType.UP, null), is("OPEN"));
254         assertThat(v.parseCommand(UpDownType.DOWN), is(UpDownType.DOWN));
255         assertThat(v.getMQTTpublishValue(UpDownType.DOWN, null), is("CLOSE"));
256         assertThat(v.parseCommand(StopMoveType.STOP), is(StopMoveType.STOP));
257         assertThat(v.getMQTTpublishValue(StopMoveType.STOP, null), is("STOP"));
258
259         // Test with custom string
260         assertThat(v.parseCommand(new StringType("OPEN")), is(UpDownType.UP));
261         assertThat(v.parseCommand(new StringType("CLOSE")), is(UpDownType.DOWN));
262
263         // Test with exact percent
264         Command command = new PercentType(27);
265         assertThat(v.parseCommand((Command) command), is(command));
266         assertThat(v.getMQTTpublishValue(command, null), is("27"));
267
268         // Test formatting 0/100
269         assertThat(v.getMQTTpublishValue(PercentType.ZERO, null), is("OPEN"));
270         assertThat(v.getMQTTpublishValue(PercentType.HUNDRED, null), is("CLOSE"));
271
272         // Test parsing from MQTT
273         assertThat(v.parseMessage(new StringType("open")), is(UpDownType.UP));
274         assertThat(v.parseMessage(new StringType("closed")), is(UpDownType.DOWN));
275     }
276
277     @Test
278     public void rollershutterUpdateWithOutStrings() {
279         RollershutterValue v = new RollershutterValue(null, null, "fancyStop");
280         // Test with command
281         assertThat(v.parseCommand(UpDownType.UP), is(PercentType.ZERO));
282         assertThat(v.parseCommand(UpDownType.DOWN), is(PercentType.HUNDRED));
283
284         // Test with custom string
285         // Test formatting 0/100
286         assertThat(v.getMQTTpublishValue(PercentType.ZERO, null), is("0"));
287         assertThat(v.getMQTTpublishValue(PercentType.HUNDRED, null), is("100"));
288     }
289
290     @Test
291     public void percentCalc() {
292         PercentageValue v = new PercentageValue(new BigDecimal(10.0), new BigDecimal(110.0), new BigDecimal(1.0), null,
293                 null);
294         assertThat(v.parseCommand(new DecimalType("110.0")), is(PercentType.HUNDRED));
295         assertThat(v.getMQTTpublishValue(PercentType.HUNDRED, null), is("110"));
296         assertThat(v.parseCommand(new DecimalType(10.0)), is(PercentType.ZERO));
297         assertThat(v.getMQTTpublishValue(PercentType.ZERO, null), is("10"));
298
299         assertThat(v.parseCommand(OnOffType.ON), is(PercentType.HUNDRED));
300         assertThat(v.parseCommand(OnOffType.OFF), is(PercentType.ZERO));
301     }
302
303     @Test
304     public void percentMQTTValue() {
305         PercentageValue v = new PercentageValue(null, null, null, null, null);
306         assertThat(v.parseCommand(new DecimalType("10.10000")), is(new PercentType("10.1")));
307         assertThat(v.getMQTTpublishValue(new PercentType("10.1"), null), is("10.1"));
308         Command command;
309         for (int i = 0; i <= 100; i++) {
310             command = v.parseCommand(new DecimalType(i));
311             assertThat(v.getMQTTpublishValue(command, null), is("" + i));
312         }
313     }
314
315     @Test
316     public void percentCustomOnOff() {
317         PercentageValue v = new PercentageValue(new BigDecimal("0.0"), new BigDecimal("100.0"), new BigDecimal("1.0"),
318                 "on", "off");
319         assertThat(v.parseCommand(new StringType("on")), is(PercentType.HUNDRED));
320         assertThat(v.parseCommand(new StringType("off")), is(PercentType.ZERO));
321     }
322
323     @Test
324     public void decimalCalc() {
325         PercentageValue v = new PercentageValue(new BigDecimal("0.1"), new BigDecimal("1.0"), new BigDecimal("0.1"),
326                 null, null);
327         assertThat(v.parseCommand(new DecimalType(1.0)), is(PercentType.HUNDRED));
328         assertThat(v.parseCommand(new DecimalType(0.1)), is(PercentType.ZERO));
329         PercentType command = (PercentType) v.parseCommand(new DecimalType(0.2));
330         assertEquals(command.floatValue(), 11.11f, 0.01f);
331     }
332
333     @Test
334     public void increaseDecreaseCalc() {
335         PercentageValue v = new PercentageValue(new BigDecimal("1.0"), new BigDecimal("11.0"), new BigDecimal("0.5"),
336                 null, null);
337
338         // Normal operation.
339         PercentType command = (PercentType) v.parseCommand(new DecimalType("6.0"));
340         assertEquals(command.floatValue(), 50.0f, 0.01f);
341         v.update(command);
342         command = (PercentType) v.parseCommand(IncreaseDecreaseType.INCREASE);
343         assertEquals(command.floatValue(), 55.0f, 0.01f);
344         command = (PercentType) v.parseCommand(IncreaseDecreaseType.DECREASE);
345         assertEquals(command.floatValue(), 45.0f, 0.01f);
346
347         // Lower limit.
348         command = (PercentType) v.parseCommand(new DecimalType("1.1"));
349         assertEquals(command.floatValue(), 1.0f, 0.01f);
350         v.update(command);
351         command = (PercentType) v.parseCommand(IncreaseDecreaseType.DECREASE);
352         assertEquals(command.floatValue(), 0.0f, 0.01f);
353
354         // Upper limit.
355         command = (PercentType) v.parseCommand(new DecimalType("10.8"));
356         assertEquals(command.floatValue(), 98.0f, 0.01f);
357         v.update(command);
358         command = (PercentType) v.parseCommand(IncreaseDecreaseType.INCREASE);
359         assertEquals(command.floatValue(), 100.0f, 0.01f);
360     }
361
362     @Test
363     public void upDownCalc() {
364         PercentageValue v = new PercentageValue(new BigDecimal("1.0"), new BigDecimal("11.0"), new BigDecimal("0.5"),
365                 null, null);
366
367         // Normal operation.
368         PercentType command = (PercentType) v.parseCommand(new DecimalType("6.0"));
369         assertEquals(command.floatValue(), 50.0f, 0.01f);
370         v.update(command);
371         command = (PercentType) v.parseCommand(UpDownType.UP);
372         assertEquals(command.floatValue(), 55.0f, 0.01f);
373         command = (PercentType) v.parseCommand(UpDownType.DOWN);
374         assertEquals(command.floatValue(), 45.0f, 0.01f);
375
376         // Lower limit.
377         command = (PercentType) v.parseCommand(new DecimalType("1.1"));
378         assertEquals(command.floatValue(), 1.0f, 0.01f);
379         v.update(command);
380         command = (PercentType) v.parseCommand(UpDownType.DOWN);
381         assertEquals(command.floatValue(), 0.0f, 0.01f);
382
383         // Upper limit.
384         command = (PercentType) v.parseCommand(new DecimalType("10.8"));
385         assertEquals(command.floatValue(), 98.0f, 0.01f);
386         v.update(command);
387         command = (PercentType) v.parseCommand(UpDownType.UP);
388         assertEquals(command.floatValue(), 100.0f, 0.01f);
389     }
390
391     @Test
392     public void percentCalcInvalid() {
393         PercentageValue v = new PercentageValue(new BigDecimal(10.0), new BigDecimal(110.0), new BigDecimal(1.0), null,
394                 null);
395         assertThrows(IllegalArgumentException.class, () -> v.parseCommand(new DecimalType(9.0)));
396     }
397 }