]> git.basschouten.com Git - openhab-addons.git/blob
37fd497d8778d7d31f3e8edf4b9eb26203ef6ef9
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.homematic.internal.converter.type;
14
15 import java.math.BigDecimal;
16
17 import javax.measure.Quantity;
18
19 import org.openhab.binding.homematic.internal.converter.ConverterException;
20 import org.openhab.binding.homematic.internal.model.HmDatapoint;
21 import org.openhab.core.library.types.QuantityType;
22 import org.openhab.core.library.unit.MetricPrefix;
23 import org.openhab.core.library.unit.SIUnits;
24 import org.openhab.core.library.unit.Units;
25 import org.openhab.core.types.Type;
26
27 /**
28  * Converts between a Homematic datapoint value and a {@link DecimalType}.
29  *
30  * @author Michael Reitler - Initial contribution
31  */
32 public class QuantityTypeConverter extends AbstractTypeConverter<QuantityType<? extends Quantity<?>>> {
33
34     // this literal is required because some gateway types are mixing up encodings in their XML-RPC responses
35     private static final String UNCORRECT_ENCODED_CELSIUS = "°C";
36
37     // "100%" is a commonly used "unit" in datapoints. Generated channel-type is of DecimalType,
38     // but clients may define a QuantityType if preferred
39     private static final String HUNDRED_PERCENT = "100%";
40
41     @Override
42     protected boolean toBindingValidation(HmDatapoint dp, Class<? extends Type> typeClass) {
43         return dp.isNumberType() && typeClass.isAssignableFrom(QuantityType.class);
44     }
45
46     @Override
47     protected Object toBinding(QuantityType<? extends Quantity<?>> type, HmDatapoint dp) throws ConverterException {
48         if (dp.isIntegerType()) {
49             return toUnitFromDatapoint(type, dp).intValue();
50         }
51         return round(toUnitFromDatapoint(type, dp).doubleValue()).doubleValue();
52     }
53
54     private QuantityType<? extends Quantity<?>> toUnitFromDatapoint(QuantityType<? extends Quantity<?>> type,
55             HmDatapoint dp) {
56         if (dp == null || dp.getUnit() == null || dp.getUnit().isEmpty()) {
57             // datapoint is dimensionless, nothing to convert
58             return type;
59         }
60
61         // convert the given QuantityType to a QuantityType with the unit of the target datapoint
62         switch (dp.getUnit()) {
63             case "Lux":
64                 return type.toUnit(Units.LUX);
65             case "degree":
66                 return type.toUnit(Units.DEGREE_ANGLE);
67             case HUNDRED_PERCENT:
68                 return type.toUnit(Units.ONE);
69             case UNCORRECT_ENCODED_CELSIUS:
70                 return type.toUnit(SIUnits.CELSIUS);
71             case "dBm":
72             case "minutes":
73             case "day":
74             case "month":
75             case "year":
76             case "":
77                 return type;
78             default:
79                 // According to datapoint documentation, the following values are remaining
80                 // °C, V, %, s, min, mHz, Hz, hPa, km/h, mm, W, m3
81                 return type.toUnit(dp.getUnit());
82         }
83     }
84
85     @Override
86     protected boolean fromBindingValidation(HmDatapoint dp) {
87         return dp.isNumberType() && dp.getValue() instanceof Number;
88     }
89
90     @Override
91     protected QuantityType<? extends Quantity<?>> fromBinding(HmDatapoint dp) throws ConverterException {
92         Number number = null;
93         if (dp.isIntegerType()) {
94             number = new BigDecimal(((Number) dp.getValue()).intValue());
95         } else {
96             number = round(((Number) dp.getValue()).doubleValue());
97         }
98
99         // create a QuantityType from the datapoint's value based on the datapoint's unit
100         String unit = dp.getUnit() != null ? dp.getUnit() : "";
101         switch (unit) {
102             case UNCORRECT_ENCODED_CELSIUS:
103             case "°C":
104                 return new QuantityType<>(number, SIUnits.CELSIUS);
105             case "V":
106                 return new QuantityType<>(number, Units.VOLT);
107             case "% rH":
108             case "% rF":
109             case "%":
110                 return new QuantityType<>(number, Units.PERCENT);
111             case "mHz":
112                 return new QuantityType<>(number, MetricPrefix.MILLI(Units.HERTZ));
113             case "Hz":
114                 return new QuantityType<>(number, Units.HERTZ);
115             case "hPa":
116                 return new QuantityType<>(number, SIUnits.PASCAL.multiply(2));
117             case "Lux":
118                 return new QuantityType<>(number, Units.LUX);
119             case "degree":
120                 return new QuantityType<>(number, Units.DEGREE_ANGLE);
121             case "km/h":
122                 return new QuantityType<>(number, SIUnits.KILOMETRE_PER_HOUR);
123             case "mm":
124                 return new QuantityType<>(number, MetricPrefix.MILLI(SIUnits.METRE));
125             case "W":
126                 return new QuantityType<>(number, Units.WATT);
127             case "Wh":
128                 return new QuantityType<>(number, Units.WATT_HOUR);
129             case "m3":
130                 return new QuantityType<>(number, SIUnits.CUBIC_METRE);
131             case HUNDRED_PERCENT:
132                 return new QuantityType<>(number.doubleValue() * 100.0, Units.PERCENT);
133             case "dBm":
134             case "s":
135             case "min":
136             case "minutes":
137             case "day":
138             case "month":
139             case "year":
140             case "":
141             default:
142                 return new QuantityType<>(number, Units.ONE);
143         }
144     }
145
146     @Override
147     protected LogLevel getDefaultLogLevelForTypeConverter() {
148         // increase logging verbosity for this type of converter
149         return LogLevel.DEBUG;
150     }
151 }