2 * Copyright (c) 2010-2022 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 numberPercentageUpdate() {
189 NumberValue v = new NumberValue(null, null, new BigDecimal(10), Units.PERCENT);
191 // Test with command with units
192 v.update(new QuantityType<>(20, Units.PERCENT));
193 assertThat(v.getMQTTpublishValue(null), is("20"));
194 assertThat(v.getChannelState(), is(new QuantityType<>(20, Units.PERCENT)));
196 // Test with command without units
197 v.update(new QuantityType<>("20"));
198 assertThat(v.getMQTTpublishValue(null), is("20"));
199 assertThat(v.getChannelState(), is(new QuantityType<>(20, Units.PERCENT)));
203 public void rollershutterUpdateWithStrings() {
204 RollershutterValue v = new RollershutterValue("fancyON", "fancyOff", "fancyStop");
206 v.update(UpDownType.UP);
207 assertThat(v.getMQTTpublishValue(null), is("fancyON"));
208 assertThat(v.getChannelState(), is(PercentType.ZERO));
209 v.update(UpDownType.DOWN);
210 assertThat(v.getMQTTpublishValue(null), is("fancyOff"));
211 assertThat(v.getChannelState(), is(PercentType.HUNDRED));
213 // Test with custom string
214 v.update(new StringType("fancyON"));
215 assertThat(v.getMQTTpublishValue(null), is("fancyON"));
216 assertThat(v.getChannelState(), is(PercentType.ZERO));
217 v.update(new StringType("fancyOff"));
218 assertThat(v.getMQTTpublishValue(null), is("fancyOff"));
219 assertThat(v.getChannelState(), is(PercentType.HUNDRED));
220 v.update(new PercentType(27));
221 assertThat(v.getMQTTpublishValue(null), is("27"));
222 assertThat(v.getChannelState(), is(new PercentType(27)));
226 public void rollershutterUpdateWithOutStrings() {
227 RollershutterValue v = new RollershutterValue(null, null, "fancyStop");
229 v.update(UpDownType.UP);
230 assertThat(v.getMQTTpublishValue(null), is("0"));
231 assertThat(v.getChannelState(), is(PercentType.ZERO));
232 v.update(UpDownType.DOWN);
233 assertThat(v.getMQTTpublishValue(null), is("100"));
234 assertThat(v.getChannelState(), is(PercentType.HUNDRED));
236 // Test with custom string
237 v.update(PercentType.ZERO);
238 assertThat(v.getMQTTpublishValue(null), is("0"));
239 assertThat(v.getChannelState(), is(PercentType.ZERO));
240 v.update(PercentType.HUNDRED);
241 assertThat(v.getMQTTpublishValue(null), is("100"));
242 assertThat(v.getChannelState(), is(PercentType.HUNDRED));
243 v.update(new PercentType(27));
244 assertThat(v.getMQTTpublishValue(null), is("27"));
245 assertThat(v.getChannelState(), is(new PercentType(27)));
249 public void percentCalc() {
250 PercentageValue v = new PercentageValue(new BigDecimal(10.0), new BigDecimal(110.0), new BigDecimal(1.0), null,
252 v.update(new DecimalType("110.0"));
253 assertThat((PercentType) v.getChannelState(), is(new PercentType(100)));
254 assertThat(v.getMQTTpublishValue(null), is("110"));
255 v.update(new DecimalType(10.0));
256 assertThat((PercentType) v.getChannelState(), is(new PercentType(0)));
257 assertThat(v.getMQTTpublishValue(null), is("10"));
259 v.update(OnOffType.ON);
260 assertThat((PercentType) v.getChannelState(), is(new PercentType(100)));
261 v.update(OnOffType.OFF);
262 assertThat((PercentType) v.getChannelState(), is(new PercentType(0)));
266 public void percentMQTTValue() {
267 PercentageValue v = new PercentageValue(null, null, null, null, null);
268 v.update(new DecimalType("10.10000"));
269 assertThat(v.getMQTTpublishValue(null), is("10.1"));
270 for (int i = 0; i <= 100; i++) {
271 v.update(new DecimalType(i));
272 assertThat(v.getMQTTpublishValue(null), is("" + i));
277 public void percentCustomOnOff() {
278 PercentageValue v = new PercentageValue(new BigDecimal("0.0"), new BigDecimal("100.0"), new BigDecimal("1.0"),
280 v.update(new StringType("on"));
281 assertThat((PercentType) v.getChannelState(), is(new PercentType(100)));
282 v.update(new StringType("off"));
283 assertThat((PercentType) v.getChannelState(), is(new PercentType(0)));
287 public void decimalCalc() {
288 PercentageValue v = new PercentageValue(new BigDecimal("0.1"), new BigDecimal("1.0"), new BigDecimal("0.1"),
290 v.update(new DecimalType(1.0));
291 assertThat((PercentType) v.getChannelState(), is(new PercentType(100)));
292 v.update(new DecimalType(0.1));
293 assertThat((PercentType) v.getChannelState(), is(new PercentType(0)));
294 v.update(new DecimalType(0.2));
295 assertEquals(((PercentType) v.getChannelState()).floatValue(), 11.11f, 0.01f);
299 public void increaseDecreaseCalc() {
300 PercentageValue v = new PercentageValue(new BigDecimal("1.0"), new BigDecimal("11.0"), new BigDecimal("0.5"),
304 v.update(new DecimalType("6.0"));
305 assertEquals(((PercentType) v.getChannelState()).floatValue(), 50.0f, 0.01f);
306 v.update(IncreaseDecreaseType.INCREASE);
307 assertEquals(((PercentType) v.getChannelState()).floatValue(), 55.0f, 0.01f);
308 v.update(IncreaseDecreaseType.DECREASE);
309 v.update(IncreaseDecreaseType.DECREASE);
310 assertEquals(((PercentType) v.getChannelState()).floatValue(), 45.0f, 0.01f);
313 v.update(new DecimalType("1.1"));
314 assertEquals(((PercentType) v.getChannelState()).floatValue(), 1.0f, 0.01f);
315 v.update(IncreaseDecreaseType.DECREASE);
316 assertEquals(((PercentType) v.getChannelState()).floatValue(), 0.0f, 0.01f);
319 v.update(new DecimalType("10.8"));
320 assertEquals(((PercentType) v.getChannelState()).floatValue(), 98.0f, 0.01f);
321 v.update(IncreaseDecreaseType.INCREASE);
322 assertEquals(((PercentType) v.getChannelState()).floatValue(), 100.0f, 0.01f);
326 public void upDownCalc() {
327 PercentageValue v = new PercentageValue(new BigDecimal("1.0"), new BigDecimal("11.0"), new BigDecimal("0.5"),
331 v.update(new DecimalType("6.0"));
332 assertEquals(((PercentType) v.getChannelState()).floatValue(), 50.0f, 0.01f);
333 v.update(UpDownType.UP);
334 assertEquals(((PercentType) v.getChannelState()).floatValue(), 55.0f, 0.01f);
335 v.update(UpDownType.DOWN);
336 v.update(UpDownType.DOWN);
337 assertEquals(((PercentType) v.getChannelState()).floatValue(), 45.0f, 0.01f);
340 v.update(new DecimalType("1.1"));
341 assertEquals(((PercentType) v.getChannelState()).floatValue(), 1.0f, 0.01f);
342 v.update(UpDownType.DOWN);
343 assertEquals(((PercentType) v.getChannelState()).floatValue(), 0.0f, 0.01f);
346 v.update(new DecimalType("10.8"));
347 assertEquals(((PercentType) v.getChannelState()).floatValue(), 98.0f, 0.01f);
348 v.update(UpDownType.UP);
349 assertEquals(((PercentType) v.getChannelState()).floatValue(), 100.0f, 0.01f);
353 public void percentCalcInvalid() {
354 PercentageValue v = new PercentageValue(new BigDecimal(10.0), new BigDecimal(110.0), new BigDecimal(1.0), null,
356 assertThrows(IllegalArgumentException.class, () -> v.update(new DecimalType(9.0)));