2 * Copyright (c) 2010-2024 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.mqtt.generic.values;
15 import static org.hamcrest.CoreMatchers.is;
16 import static org.hamcrest.MatcherAssert.assertThat;
17 import static org.junit.jupiter.api.Assertions.*;
19 import java.math.BigDecimal;
20 import java.util.Objects;
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;
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.
46 * The on/off value class should accept a multitude of values including the custom defined ones.
48 * The string value class states are tested.
50 * @author David Graeff - Initial contribution
53 public class ValueTests {
54 private Command p(Value v, String str) {
55 return Objects.requireNonNull(TypeParser.parseCommand(v.getSupportedCommandTypes(), str));
59 public void illegalTextStateUpdate() {
60 TextValue v = new TextValue("one,two".split(","));
61 assertThrows(IllegalArgumentException.class, () -> v.parseCommand(p(v, "three")));
65 public void textStateUpdate() {
66 TextValue v = new TextValue("one,two".split(","));
67 v.parseCommand(p(v, "one"));
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")));
75 HSBType hsb = (HSBType) v.parseCommand(p(v, "OFF"));
76 assertThat(hsb.getBrightness().intValue(), is(0));
78 hsb = (HSBType) v.parseCommand(p(v, "ON"));
79 assertThat(hsb.getBrightness().intValue(), is(77));
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));
86 assertThat(v.parseMessage(new StringType("")), is(UnDefType.NULL));
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")));
96 public void illegalNumberCommand() {
97 NumberValue v = new NumberValue(null, null, null, null);
98 assertThrows(IllegalArgumentException.class, () -> v.parseCommand(OnOffType.OFF));
102 public void illegalPercentCommand() {
103 PercentageValue v = new PercentageValue(null, null, null, null, null);
104 assertThrows(IllegalStateException.class, () -> v.parseCommand(new StringType("demo")));
108 public void illegalOnOffCommand() {
109 OnOffValue v = new OnOffValue(null, null);
110 assertThrows(IllegalArgumentException.class, () -> v.parseCommand(new DecimalType(101.0)));
114 public void illegalPercentUpdate() {
115 PercentageValue v = new PercentageValue(null, null, null, null, null);
116 assertThrows(IllegalArgumentException.class, () -> v.parseCommand(new DecimalType(101.0)));
120 public void onoffUpdate() {
121 OnOffValue v = new OnOffValue("fancyON", "fancyOff");
124 assertThat(v.parseCommand(OnOffType.OFF), is(OnOffType.OFF));
125 assertThat(v.parseCommand(OnOffType.ON), is(OnOffType.ON));
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));
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));
135 // Test basic formatting
136 assertThat(v.getMQTTpublishValue(OnOffType.ON, null), is("fancyON"));
137 assertThat(v.getMQTTpublishValue(OnOffType.OFF, null), is("fancyOff"));
139 // Test custom formatting
140 assertThat(v.getMQTTpublishValue(OnOffType.OFF, "=%s"), is("=fancyOff"));
141 assertThat(v.getMQTTpublishValue(OnOffType.ON, "=%s"), is("=fancyON"));
143 assertThat(v.parseMessage(new StringType("")), is(UnDefType.NULL));
147 public void onoffMultiStates() {
148 OnOffValue v = new OnOffValue(new String[] { "LOCKED" }, new String[] { "UNLOCKED", "JAMMED" }, "LOCK",
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));
157 public void openCloseUpdate() {
158 OpenCloseValue v = new OpenCloseValue("fancyON", "fancyOff");
161 assertThat(v.parseCommand(OpenClosedType.CLOSED), is(OpenClosedType.CLOSED));
162 assertThat(v.parseCommand(OpenClosedType.OPEN), is(OpenClosedType.OPEN));
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));
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));
172 // Test basic formatting
173 assertThat(v.getMQTTpublishValue(OpenClosedType.CLOSED, null), is("fancyOff"));
174 assertThat(v.getMQTTpublishValue(OpenClosedType.OPEN, null), is("fancyON"));
176 assertThat(v.parseMessage(new StringType("")), is(UnDefType.NULL));
180 public void numberUpdate() {
181 NumberValue v = new NumberValue(null, null, new BigDecimal(10), Units.WATT);
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"));
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"));
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));
201 assertThat(v.parseMessage(new StringType("")), is(UnDefType.NULL));
205 public void numberUpdateMireds() {
206 NumberValue v = new NumberValue(null, null, new BigDecimal(10), Units.MIRED);
208 Command command = v.parseCommand(new QuantityType<>(2700, Units.KELVIN));
209 assertThat(v.getMQTTpublishValue(command, "%.0f"), is("370"));
213 public void numberPercentageUpdate() {
214 NumberValue v = new NumberValue(null, null, new BigDecimal(10), Units.PERCENT);
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"));
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"));
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"));
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));
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"));
247 // Test formatting 0/100
248 assertThat(v.getMQTTpublishValue(PercentType.ZERO, null), is("fancyON"));
249 assertThat(v.getMQTTpublishValue(PercentType.HUNDRED, null), is("fancyOff"));
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));
255 assertThat(v.parseMessage(new StringType("")), is(UnDefType.NULL));
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"));
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));
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"));
278 // Test formatting 0/100
279 assertThat(v.getMQTTpublishValue(PercentType.ZERO, null), is("OPEN"));
280 assertThat(v.getMQTTpublishValue(PercentType.HUNDRED, null), is("CLOSE"));
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));
288 public void rollershutterUpdateWithOutStrings() {
289 RollershutterValue v = new RollershutterValue(null, null, "fancyStop");
291 assertThat(v.parseCommand(UpDownType.UP), is(PercentType.ZERO));
292 assertThat(v.parseCommand(UpDownType.DOWN), is(PercentType.HUNDRED));
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"));
301 public void percentCalc() {
302 PercentageValue v = new PercentageValue(new BigDecimal(10.0), new BigDecimal(110.0), new BigDecimal(1.0), 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"));
309 assertThat(v.parseCommand(OnOffType.ON), is(PercentType.HUNDRED));
310 assertThat(v.parseCommand(OnOffType.OFF), is(PercentType.ZERO));
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"));
319 for (int i = 0; i <= 100; i++) {
320 command = v.parseCommand(new DecimalType(i));
321 assertThat(v.getMQTTpublishValue(command, null), is("" + i));
324 assertThat(v.parseMessage(new StringType("")), is(UnDefType.NULL));
328 public void percentCustomOnOff() {
329 PercentageValue v = new PercentageValue(new BigDecimal("0.0"), new BigDecimal("100.0"), new BigDecimal("1.0"),
331 assertThat(v.parseCommand(new StringType("on")), is(PercentType.HUNDRED));
332 assertThat(v.parseCommand(new StringType("off")), is(PercentType.ZERO));
336 public void decimalCalc() {
337 PercentageValue v = new PercentageValue(new BigDecimal("0.1"), new BigDecimal("1.0"), new BigDecimal("0.1"),
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);
346 public void increaseDecreaseCalc() {
347 PercentageValue v = new PercentageValue(new BigDecimal("1.0"), new BigDecimal("11.0"), new BigDecimal("0.5"),
351 PercentType command = (PercentType) v.parseCommand(new DecimalType("6.0"));
352 assertEquals(command.floatValue(), 50.0f, 0.01f);
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);
360 command = (PercentType) v.parseCommand(new DecimalType("1.1"));
361 assertEquals(command.floatValue(), 1.0f, 0.01f);
363 command = (PercentType) v.parseCommand(IncreaseDecreaseType.DECREASE);
364 assertEquals(command.floatValue(), 0.0f, 0.01f);
367 command = (PercentType) v.parseCommand(new DecimalType("10.8"));
368 assertEquals(command.floatValue(), 98.0f, 0.01f);
370 command = (PercentType) v.parseCommand(IncreaseDecreaseType.INCREASE);
371 assertEquals(command.floatValue(), 100.0f, 0.01f);
375 public void upDownCalc() {
376 PercentageValue v = new PercentageValue(new BigDecimal("1.0"), new BigDecimal("11.0"), new BigDecimal("0.5"),
380 PercentType command = (PercentType) v.parseCommand(new DecimalType("6.0"));
381 assertEquals(command.floatValue(), 50.0f, 0.01f);
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);
389 command = (PercentType) v.parseCommand(new DecimalType("1.1"));
390 assertEquals(command.floatValue(), 1.0f, 0.01f);
392 command = (PercentType) v.parseCommand(UpDownType.DOWN);
393 assertEquals(command.floatValue(), 0.0f, 0.01f);
396 command = (PercentType) v.parseCommand(new DecimalType("10.8"));
397 assertEquals(command.floatValue(), 98.0f, 0.01f);
399 command = (PercentType) v.parseCommand(UpDownType.UP);
400 assertEquals(command.floatValue(), 100.0f, 0.01f);
404 public void percentCalcInvalid() {
405 PercentageValue v = new PercentageValue(new BigDecimal(10.0), new BigDecimal(110.0), new BigDecimal(1.0), null,
407 assertThrows(IllegalArgumentException.class, () -> v.parseCommand(new DecimalType(9.0)));
411 public void textUpdate() {
412 TextValue v = new TextValue();
414 assertThat(v.parseMessage(new StringType("")), is(new StringType("")));
415 assertThat(v.parseMessage(new StringType("NULL")), is(new StringType("NULL")));
418 assertThat(v.parseMessage(new StringType("")), is(UnDefType.NULL));
419 assertThat(v.parseMessage(new StringType("NULL")), is(new StringType("NULL")));
421 v.setNullValue("NULL");
422 assertThat(v.parseMessage(new StringType("NULL")), is(UnDefType.NULL));
423 assertThat(v.parseMessage(new StringType("")), is(new StringType("")));