]> git.basschouten.com Git - openhab-addons.git/blob
de6f5c6f28ca1d2099713e0750b94fab44acb94f
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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 java.math.BigDecimal;
16 import java.util.stream.Collectors;
17 import java.util.stream.Stream;
18
19 import javax.measure.Unit;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.core.library.CoreItemFactory;
24 import org.openhab.core.library.types.DecimalType;
25 import org.openhab.core.library.types.IncreaseDecreaseType;
26 import org.openhab.core.library.types.QuantityType;
27 import org.openhab.core.library.types.UpDownType;
28 import org.openhab.core.library.unit.Units;
29 import org.openhab.core.types.Command;
30 import org.openhab.core.types.StateDescriptionFragmentBuilder;
31 import org.openhab.core.types.UnDefType;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 /**
36  * Implements a number value.
37  *
38  * If min / max limits are set, values below / above are (almost) silently ignored.
39  *
40  * <p>
41  * Accepts user updates and MQTT state updates from a DecimalType, IncreaseDecreaseType and UpDownType.
42  * </p>
43  *
44  * @author David Graeff - Initial contribution
45  */
46 @NonNullByDefault
47 public class NumberValue extends Value {
48     private final Logger logger = LoggerFactory.getLogger(NumberValue.class);
49     private final @Nullable BigDecimal min;
50     private final @Nullable BigDecimal max;
51     private final BigDecimal step;
52     private final Unit<?> unit;
53
54     public NumberValue(@Nullable BigDecimal min, @Nullable BigDecimal max, @Nullable BigDecimal step,
55             @Nullable Unit<?> unit) {
56         super(CoreItemFactory.NUMBER, Stream.of(QuantityType.class, IncreaseDecreaseType.class, UpDownType.class)
57                 .collect(Collectors.toList()));
58         this.min = min;
59         this.max = max;
60         this.step = step == null ? BigDecimal.ONE : step;
61         this.unit = unit != null ? unit : Units.ONE;
62     }
63
64     protected boolean checkConditions(BigDecimal newValue) {
65         BigDecimal min = this.min;
66         if (min != null && newValue.compareTo(min) == -1) {
67             logger.trace("Number not accepted as it is below the configured minimum");
68             return false;
69         }
70         BigDecimal max = this.max;
71         if (max != null && newValue.compareTo(max) == 1) {
72             logger.trace("Number not accepted as it is above the configured maximum");
73             return false;
74         }
75
76         return true;
77     }
78
79     @Override
80     public String getMQTTpublishValue(@Nullable String pattern) {
81         if (state == UnDefType.UNDEF) {
82             return "";
83         }
84
85         String formatPattern = pattern;
86         if (formatPattern == null) {
87             formatPattern = "%s";
88         }
89
90         return state.format(formatPattern);
91     }
92
93     @Override
94     public void update(Command command) throws IllegalArgumentException {
95         BigDecimal newValue = null;
96         if (command instanceof DecimalType) {
97             newValue = ((DecimalType) command).toBigDecimal();
98         } else if (command instanceof IncreaseDecreaseType || command instanceof UpDownType) {
99             BigDecimal oldValue = getOldValue();
100             if (command == IncreaseDecreaseType.INCREASE || command == UpDownType.UP) {
101                 newValue = oldValue.add(step);
102             } else {
103                 newValue = oldValue.subtract(step);
104             }
105         } else if (command instanceof QuantityType<?>) {
106             newValue = getQuantityTypeAsDecimal((QuantityType<?>) command);
107         } else {
108             newValue = new BigDecimal(command.toString());
109         }
110         if (!checkConditions(newValue)) {
111             return;
112         }
113         // items with units specified in the label in the UI but no unit on mqtt are stored as
114         // DecimalType to avoid conversions (e.g. % expects 0-1 rather than 0-100)
115         if (!Units.ONE.equals(unit)) {
116             state = new QuantityType<>(newValue, unit);
117         } else {
118             state = new DecimalType(newValue);
119         }
120     }
121
122     private BigDecimal getOldValue() {
123         BigDecimal val = BigDecimal.ZERO;
124         if (state instanceof DecimalType) {
125             val = ((DecimalType) state).toBigDecimal();
126         } else if (state instanceof QuantityType<?>) {
127             val = ((QuantityType<?>) state).toBigDecimal();
128         }
129         return val;
130     }
131
132     private BigDecimal getQuantityTypeAsDecimal(QuantityType<?> qType) {
133         BigDecimal val = qType.toBigDecimal();
134         if (!qType.getUnit().isCompatible(Units.ONE)) {
135             QuantityType<?> convertedType = qType.toUnit(unit);
136             if (convertedType != null) {
137                 val = convertedType.toBigDecimal();
138             }
139         }
140         return val;
141     }
142
143     @Override
144     public StateDescriptionFragmentBuilder createStateDescription(boolean readOnly) {
145         StateDescriptionFragmentBuilder builder = super.createStateDescription(readOnly);
146         BigDecimal max = this.max;
147         if (max != null) {
148             builder = builder.withMaximum(max);
149         }
150         BigDecimal min = this.min;
151         if (min != null) {
152             builder = builder.withMinimum(min);
153         }
154         return builder.withStep(step).withPattern("%s %unit%");
155     }
156 }