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.homematic.internal.converter.type;
15 import java.math.BigDecimal;
17 import javax.measure.Quantity;
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;
28 * Converts between a Homematic datapoint value and a {@link DecimalType}.
30 * @author Michael Reitler - Initial contribution
32 public class QuantityTypeConverter extends AbstractTypeConverter<QuantityType<? extends Quantity<?>>> {
34 // this literal is required because some gateway types are mixing up encodings in their XML-RPC responses
35 private final String UNCORRECT_ENCODED_CELSIUS = "°C";
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 final String HUNDRED_PERCENT = "100%";
42 protected boolean toBindingValidation(HmDatapoint dp, Class<? extends Type> typeClass) {
43 return dp.isNumberType() && typeClass.isAssignableFrom(QuantityType.class);
47 protected Object toBinding(QuantityType<? extends Quantity<?>> type, HmDatapoint dp) throws ConverterException {
48 if (dp.isIntegerType()) {
49 return toUnitFromDatapoint(type, dp).intValue();
51 return round(toUnitFromDatapoint(type, dp).doubleValue()).doubleValue();
54 private QuantityType<? extends Quantity<?>> toUnitFromDatapoint(QuantityType<? extends Quantity<?>> type,
56 if (dp == null || dp.getUnit() == null || dp.getUnit().isEmpty()) {
57 // datapoint is dimensionless, nothing to convert
61 // convert the given QuantityType to a QuantityType with the unit of the target datapoint
62 switch (dp.getUnit()) {
64 return type.toUnit(Units.LUX);
66 return type.toUnit(Units.DEGREE_ANGLE);
68 return type.toUnit(Units.ONE);
69 case UNCORRECT_ENCODED_CELSIUS:
70 return type.toUnit(SIUnits.CELSIUS);
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());
86 protected boolean fromBindingValidation(HmDatapoint dp) {
87 return dp.isNumberType() && dp.getValue() instanceof Number;
91 protected QuantityType<? extends Quantity<?>> fromBinding(HmDatapoint dp) throws ConverterException {
93 if (dp.isIntegerType()) {
94 number = new BigDecimal(((Number) dp.getValue()).intValue());
96 number = round(((Number) dp.getValue()).doubleValue());
99 // create a QuantityType from the datapoint's value based on the datapoint's unit
100 String unit = dp.getUnit() != null ? dp.getUnit() : "";
102 case UNCORRECT_ENCODED_CELSIUS:
104 return new QuantityType<>(number, SIUnits.CELSIUS);
106 return new QuantityType<>(number, Units.VOLT);
110 return new QuantityType<>(number, Units.PERCENT);
112 return new QuantityType<>(number, MetricPrefix.MILLI(Units.HERTZ));
114 return new QuantityType<>(number, Units.HERTZ);
116 return new QuantityType<>(number, SIUnits.PASCAL.multiply(2));
118 return new QuantityType<>(number, Units.LUX);
120 return new QuantityType<>(number, Units.DEGREE_ANGLE);
122 return new QuantityType<>(number, SIUnits.KILOMETRE_PER_HOUR);
124 return new QuantityType<>(number, MetricPrefix.MILLI(SIUnits.METRE));
126 return new QuantityType<>(number, Units.WATT);
128 return new QuantityType<>(number, Units.WATT_HOUR);
130 return new QuantityType<>(number, SIUnits.CUBIC_METRE);
131 case HUNDRED_PERCENT:
132 return new QuantityType<>(number.doubleValue() * 100.0, Units.PERCENT);
142 return new QuantityType<>(number, Units.ONE);
147 protected LogLevel getDefaultLogLevelForTypeConverter() {
148 // increase logging verbosity for this type of converter
149 return LogLevel.DEBUG;