2 * Copyright (c) 2010-2023 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.StringType;
33 import org.openhab.core.library.types.UpDownType;
34 import org.openhab.core.library.unit.MetricPrefix;
35 import org.openhab.core.library.unit.Units;
36 import org.openhab.core.types.Command;
37 import org.openhab.core.types.TypeParser;
40 * Test cases for the value classes. They should throw exceptions if the wrong command type is used
41 * for an update. The percent value class should raise an exception if the value is out of range.
43 * The on/off value class should accept a multitude of values including the custom defined ones.
45 * The string value class states are tested.
47 * @author David Graeff - Initial contribution
50 public class ValueTests {
51 private Command p(Value v, String str) {
52 return Objects.requireNonNull(TypeParser.parseCommand(v.getSupportedCommandTypes(), str));
56 public void illegalTextStateUpdate() {
57 TextValue v = new TextValue("one,two".split(","));
58 assertThrows(IllegalArgumentException.class, () -> v.update(p(v, "three")));
61 public void textStateUpdate() {
62 TextValue v = new TextValue("one,two".split(","));
63 v.update(p(v, "one"));
66 public void colorUpdate() {
67 ColorValue v = new ColorValue(ColorMode.RGB, "fancyON", "fancyOFF", 77);
68 v.update(p(v, "255, 255, 255"));
70 v.update(p(v, "OFF"));
71 assertThat(((HSBType) v.getChannelState()).getBrightness().intValue(), is(0));
73 assertThat(((HSBType) v.getChannelState()).getBrightness().intValue(), is(77));
76 assertThat(((HSBType) v.getChannelState()).getBrightness().intValue(), is(0));
78 assertThat(((HSBType) v.getChannelState()).getBrightness().intValue(), is(1));
82 public void illegalColorUpdate() {
83 ColorValue v = new ColorValue(ColorMode.RGB, null, null, 10);
84 assertThrows(IllegalArgumentException.class, () -> v.update(p(v, "255,255,abc")));
88 public void illegalNumberCommand() {
89 NumberValue v = new NumberValue(null, null, null, null);
90 assertThrows(IllegalArgumentException.class, () -> v.update(OnOffType.OFF));
94 public void illegalPercentCommand() {
95 PercentageValue v = new PercentageValue(null, null, null, null, null);
96 assertThrows(IllegalStateException.class, () -> v.update(new StringType("demo")));
100 public void illegalOnOffCommand() {
101 OnOffValue v = new OnOffValue(null, null);
102 assertThrows(IllegalArgumentException.class, () -> v.update(new DecimalType(101.0)));
106 public void illegalPercentUpdate() {
107 PercentageValue v = new PercentageValue(null, null, null, null, null);
108 assertThrows(IllegalArgumentException.class, () -> v.update(new DecimalType(101.0)));
112 public void onoffUpdate() {
113 OnOffValue v = new OnOffValue("fancyON", "fancyOff");
115 v.update(OnOffType.OFF);
116 assertThat(v.getMQTTpublishValue(null), is("fancyOff"));
117 assertThat(v.getChannelState(), is(OnOffType.OFF));
118 v.update(OnOffType.ON);
119 assertThat(v.getMQTTpublishValue(null), is("fancyON"));
120 assertThat(v.getChannelState(), is(OnOffType.ON));
122 // Test with string, representing the command
123 v.update(new StringType("OFF"));
124 assertThat(v.getMQTTpublishValue(null), is("fancyOff"));
125 assertThat(v.getChannelState(), is(OnOffType.OFF));
126 v.update(new StringType("ON"));
127 assertThat(v.getMQTTpublishValue(null), is("fancyON"));
128 assertThat(v.getChannelState(), is(OnOffType.ON));
130 // Test with custom string, setup in the constructor
131 v.update(new StringType("fancyOff"));
132 assertThat(v.getMQTTpublishValue(null), is("fancyOff"));
133 assertThat(v.getMQTTpublishValue("=%s"), is("=fancyOff"));
134 assertThat(v.getChannelState(), is(OnOffType.OFF));
135 v.update(new StringType("fancyON"));
136 assertThat(v.getMQTTpublishValue(null), is("fancyON"));
137 assertThat(v.getMQTTpublishValue("=%s"), is("=fancyON"));
138 assertThat(v.getChannelState(), is(OnOffType.ON));
142 public void openCloseUpdate() {
143 OpenCloseValue v = new OpenCloseValue("fancyON", "fancyOff");
145 v.update(OpenClosedType.CLOSED);
146 assertThat(v.getMQTTpublishValue(null), is("fancyOff"));
147 assertThat(v.getChannelState(), is(OpenClosedType.CLOSED));
148 v.update(OpenClosedType.OPEN);
149 assertThat(v.getMQTTpublishValue(null), is("fancyON"));
150 assertThat(v.getChannelState(), is(OpenClosedType.OPEN));
152 // Test with string, representing the command
153 v.update(new StringType("CLOSED"));
154 assertThat(v.getMQTTpublishValue(null), is("fancyOff"));
155 assertThat(v.getChannelState(), is(OpenClosedType.CLOSED));
156 v.update(new StringType("OPEN"));
157 assertThat(v.getMQTTpublishValue(null), is("fancyON"));
158 assertThat(v.getChannelState(), is(OpenClosedType.OPEN));
160 // Test with custom string, setup in the constructor
161 v.update(new StringType("fancyOff"));
162 assertThat(v.getMQTTpublishValue(null), is("fancyOff"));
163 assertThat(v.getChannelState(), is(OpenClosedType.CLOSED));
164 v.update(new StringType("fancyON"));
165 assertThat(v.getMQTTpublishValue(null), is("fancyON"));
166 assertThat(v.getChannelState(), is(OpenClosedType.OPEN));
170 public void numberUpdate() {
171 NumberValue v = new NumberValue(null, null, new BigDecimal(10), Units.WATT);
173 // Test with command with units
174 v.update(new QuantityType<>(20, Units.WATT));
175 assertThat(v.getMQTTpublishValue(null), is("20"));
176 assertThat(v.getChannelState(), is(new QuantityType<>(20, Units.WATT)));
177 v.update(new QuantityType<>(20, MetricPrefix.KILO(Units.WATT)));
178 assertThat(v.getMQTTpublishValue(null), is("20000"));
179 assertThat(v.getChannelState(), is(new QuantityType<>(20, MetricPrefix.KILO(Units.WATT))));
181 // Test with command without units
182 v.update(new QuantityType<>("20"));
183 assertThat(v.getMQTTpublishValue(null), is("20"));
184 assertThat(v.getChannelState(), is(new QuantityType<>(20, Units.WATT)));
188 public void numberUpdateMireds() {
189 NumberValue v = new NumberValue(null, null, new BigDecimal(10), Units.MIRED);
191 v.update(new QuantityType<>(2700, Units.KELVIN));
192 assertThat(v.getMQTTpublishValue("%.0f"), is("370"));
196 public void numberPercentageUpdate() {
197 NumberValue v = new NumberValue(null, null, new BigDecimal(10), Units.PERCENT);
199 // Test with command with units
200 v.update(new QuantityType<>(20, Units.PERCENT));
201 assertThat(v.getMQTTpublishValue(null), is("20"));
202 assertThat(v.getChannelState(), is(new QuantityType<>(20, Units.PERCENT)));
204 // Test with command without units
205 v.update(new QuantityType<>("20"));
206 assertThat(v.getMQTTpublishValue(null), is("20"));
207 assertThat(v.getChannelState(), is(new QuantityType<>(20, Units.PERCENT)));
211 public void rollershutterUpdateWithStrings() {
212 RollershutterValue v = new RollershutterValue("fancyON", "fancyOff", "fancyStop");
214 v.update(UpDownType.UP);
215 assertThat(v.getMQTTpublishValue(null), is("fancyON"));
216 assertThat(v.getChannelState(), is(PercentType.ZERO));
217 v.update(UpDownType.DOWN);
218 assertThat(v.getMQTTpublishValue(null), is("fancyOff"));
219 assertThat(v.getChannelState(), is(PercentType.HUNDRED));
221 // Test with custom string
222 v.update(new StringType("fancyON"));
223 assertThat(v.getMQTTpublishValue(null), is("fancyON"));
224 assertThat(v.getChannelState(), is(PercentType.ZERO));
225 v.update(new StringType("fancyOff"));
226 assertThat(v.getMQTTpublishValue(null), is("fancyOff"));
227 assertThat(v.getChannelState(), is(PercentType.HUNDRED));
228 v.update(new PercentType(27));
229 assertThat(v.getMQTTpublishValue(null), is("27"));
230 assertThat(v.getChannelState(), is(new PercentType(27)));
234 public void rollershutterUpdateWithOutStrings() {
235 RollershutterValue v = new RollershutterValue(null, null, "fancyStop");
237 v.update(UpDownType.UP);
238 assertThat(v.getMQTTpublishValue(null), is("0"));
239 assertThat(v.getChannelState(), is(PercentType.ZERO));
240 v.update(UpDownType.DOWN);
241 assertThat(v.getMQTTpublishValue(null), is("100"));
242 assertThat(v.getChannelState(), is(PercentType.HUNDRED));
244 // Test with custom string
245 v.update(PercentType.ZERO);
246 assertThat(v.getMQTTpublishValue(null), is("0"));
247 assertThat(v.getChannelState(), is(PercentType.ZERO));
248 v.update(PercentType.HUNDRED);
249 assertThat(v.getMQTTpublishValue(null), is("100"));
250 assertThat(v.getChannelState(), is(PercentType.HUNDRED));
251 v.update(new PercentType(27));
252 assertThat(v.getMQTTpublishValue(null), is("27"));
253 assertThat(v.getChannelState(), is(new PercentType(27)));
257 public void percentCalc() {
258 PercentageValue v = new PercentageValue(new BigDecimal(10.0), new BigDecimal(110.0), new BigDecimal(1.0), null,
260 v.update(new DecimalType("110.0"));
261 assertThat((PercentType) v.getChannelState(), is(new PercentType(100)));
262 assertThat(v.getMQTTpublishValue(null), is("110"));
263 v.update(new DecimalType(10.0));
264 assertThat((PercentType) v.getChannelState(), is(new PercentType(0)));
265 assertThat(v.getMQTTpublishValue(null), is("10"));
267 v.update(OnOffType.ON);
268 assertThat((PercentType) v.getChannelState(), is(new PercentType(100)));
269 v.update(OnOffType.OFF);
270 assertThat((PercentType) v.getChannelState(), is(new PercentType(0)));
274 public void percentMQTTValue() {
275 PercentageValue v = new PercentageValue(null, null, null, null, null);
276 v.update(new DecimalType("10.10000"));
277 assertThat(v.getMQTTpublishValue(null), is("10.1"));
278 for (int i = 0; i <= 100; i++) {
279 v.update(new DecimalType(i));
280 assertThat(v.getMQTTpublishValue(null), is("" + i));
285 public void percentCustomOnOff() {
286 PercentageValue v = new PercentageValue(new BigDecimal("0.0"), new BigDecimal("100.0"), new BigDecimal("1.0"),
288 v.update(new StringType("on"));
289 assertThat((PercentType) v.getChannelState(), is(new PercentType(100)));
290 v.update(new StringType("off"));
291 assertThat((PercentType) v.getChannelState(), is(new PercentType(0)));
295 public void decimalCalc() {
296 PercentageValue v = new PercentageValue(new BigDecimal("0.1"), new BigDecimal("1.0"), new BigDecimal("0.1"),
298 v.update(new DecimalType(1.0));
299 assertThat((PercentType) v.getChannelState(), is(new PercentType(100)));
300 v.update(new DecimalType(0.1));
301 assertThat((PercentType) v.getChannelState(), is(new PercentType(0)));
302 v.update(new DecimalType(0.2));
303 assertEquals(((PercentType) v.getChannelState()).floatValue(), 11.11f, 0.01f);
307 public void increaseDecreaseCalc() {
308 PercentageValue v = new PercentageValue(new BigDecimal("1.0"), new BigDecimal("11.0"), new BigDecimal("0.5"),
312 v.update(new DecimalType("6.0"));
313 assertEquals(((PercentType) v.getChannelState()).floatValue(), 50.0f, 0.01f);
314 v.update(IncreaseDecreaseType.INCREASE);
315 assertEquals(((PercentType) v.getChannelState()).floatValue(), 55.0f, 0.01f);
316 v.update(IncreaseDecreaseType.DECREASE);
317 v.update(IncreaseDecreaseType.DECREASE);
318 assertEquals(((PercentType) v.getChannelState()).floatValue(), 45.0f, 0.01f);
321 v.update(new DecimalType("1.1"));
322 assertEquals(((PercentType) v.getChannelState()).floatValue(), 1.0f, 0.01f);
323 v.update(IncreaseDecreaseType.DECREASE);
324 assertEquals(((PercentType) v.getChannelState()).floatValue(), 0.0f, 0.01f);
327 v.update(new DecimalType("10.8"));
328 assertEquals(((PercentType) v.getChannelState()).floatValue(), 98.0f, 0.01f);
329 v.update(IncreaseDecreaseType.INCREASE);
330 assertEquals(((PercentType) v.getChannelState()).floatValue(), 100.0f, 0.01f);
334 public void upDownCalc() {
335 PercentageValue v = new PercentageValue(new BigDecimal("1.0"), new BigDecimal("11.0"), new BigDecimal("0.5"),
339 v.update(new DecimalType("6.0"));
340 assertEquals(((PercentType) v.getChannelState()).floatValue(), 50.0f, 0.01f);
341 v.update(UpDownType.UP);
342 assertEquals(((PercentType) v.getChannelState()).floatValue(), 55.0f, 0.01f);
343 v.update(UpDownType.DOWN);
344 v.update(UpDownType.DOWN);
345 assertEquals(((PercentType) v.getChannelState()).floatValue(), 45.0f, 0.01f);
348 v.update(new DecimalType("1.1"));
349 assertEquals(((PercentType) v.getChannelState()).floatValue(), 1.0f, 0.01f);
350 v.update(UpDownType.DOWN);
351 assertEquals(((PercentType) v.getChannelState()).floatValue(), 0.0f, 0.01f);
354 v.update(new DecimalType("10.8"));
355 assertEquals(((PercentType) v.getChannelState()).floatValue(), 98.0f, 0.01f);
356 v.update(UpDownType.UP);
357 assertEquals(((PercentType) v.getChannelState()).floatValue(), 100.0f, 0.01f);
361 public void percentCalcInvalid() {
362 PercentageValue v = new PercentageValue(new BigDecimal(10.0), new BigDecimal(110.0), new BigDecimal(1.0), null,
364 assertThrows(IllegalArgumentException.class, () -> v.update(new DecimalType(9.0)));