]> git.basschouten.com Git - openhab-addons.git/blob
63a4fd243362aa3725a9bc63fb9923721846158b
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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.communicator.parser;
14
15 import java.io.IOException;
16
17 import org.apache.commons.lang.BooleanUtils;
18 import org.apache.commons.lang.ObjectUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.apache.commons.lang.math.NumberUtils;
21 import org.openhab.binding.homematic.internal.misc.MiscUtils;
22 import org.openhab.binding.homematic.internal.model.HmDatapoint;
23 import org.openhab.binding.homematic.internal.model.HmParamsetType;
24 import org.openhab.binding.homematic.internal.model.HmValueType;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 /**
29  * Abstract base class for all parsers with common methods.
30  *
31  * @author Gerhard Riegler - Initial contribution
32  */
33 public abstract class CommonRpcParser<M, R> implements RpcParser<M, R> {
34
35     private final Logger logger = LoggerFactory.getLogger(CommonRpcParser.class);
36
37     /**
38      * Converts the object to a string.
39      */
40     protected String toString(Object object) {
41         return StringUtils.trimToNull(ObjectUtils.toString(object));
42     }
43
44     /**
45      * Converts the object to a integer.
46      */
47     protected Integer toInteger(Object object) {
48         if (object == null || object instanceof Integer) {
49             return (Integer) object;
50         }
51         try {
52             return Double.valueOf(ObjectUtils.toString(object)).intValue();
53         } catch (NumberFormatException ex) {
54             logger.debug("Failed converting {} to a Double", object, ex);
55             return null;
56         }
57     }
58
59     /**
60      * Converts the object to a double.
61      */
62     protected Double toDouble(Object object) {
63         if (object == null || object instanceof Double) {
64             return (Double) object;
65         }
66         try {
67             return Double.valueOf(ObjectUtils.toString(object));
68         } catch (NumberFormatException ex) {
69             logger.debug("Failed converting {} to a Double", object, ex);
70             return null;
71         }
72     }
73
74     /**
75      * Converts the object to a number.
76      */
77     protected Number toNumber(Object object) {
78         if (object == null || object instanceof Number) {
79             return (Number) object;
80         }
81         try {
82             return NumberUtils.createNumber(ObjectUtils.toString(object));
83         } catch (NumberFormatException ex) {
84             logger.debug("Failed converting {} to a Number", object, ex);
85             return null;
86         }
87     }
88
89     /**
90      * Converts the object to a boolean.
91      */
92     protected Boolean toBoolean(Object object) {
93         if (object == null || object instanceof Boolean) {
94             return (Boolean) object;
95         }
96         return BooleanUtils.toBoolean(ObjectUtils.toString(object));
97     }
98
99     /**
100      * Converts the object to a string array.
101      */
102     protected String[] toOptionList(Object optionList) {
103         if (optionList != null && optionList instanceof Object[]) {
104             Object[] vl = (Object[]) optionList;
105             String[] stringArray = new String[vl.length];
106             for (int i = 0; i < vl.length; i++) {
107                 stringArray[i] = vl[i].toString();
108             }
109             return stringArray;
110         }
111         return null;
112     }
113
114     /**
115      * Returns the address of a device, replacing group address identifier and illegal characters.
116      */
117     protected String getSanitizedAddress(Object object) {
118         String address = StringUtils.trimToNull(StringUtils.replaceOnce(toString(object), "*", "T-"));
119         return MiscUtils.validateCharacters(address, "Address", "_");
120     }
121
122     /**
123      * Adjust uninitialized rssi values to zero.
124      */
125     protected void adjustRssiValue(HmDatapoint dp) {
126         if (dp.getValue() != null && dp.getName().startsWith("RSSI_") && dp.isIntegerType()) {
127             int rssiValue = ((Number) dp.getValue()).intValue();
128             dp.setValue(getAdjustedRssiValue(rssiValue));
129         }
130     }
131
132     /**
133      * Adjust a rssi value if it is out of range.
134      */
135     protected Integer getAdjustedRssiValue(Integer rssiValue) {
136         if (rssiValue == null || rssiValue >= 255 || rssiValue <= -255) {
137             return 0;
138         }
139         return rssiValue;
140     }
141
142     /**
143      * Converts the value to the correct type if necessary.
144      */
145     protected Object convertToType(HmDatapoint dp, Object value) {
146         if (value == null) {
147             return null;
148         } else if (dp.isBooleanType()) {
149             return toBoolean(value);
150         } else if (dp.isIntegerType()) {
151             return toInteger(value);
152         } else if (dp.isFloatType()) {
153             return toNumber(value);
154         } else if (dp.isStringType()) {
155             return toString(value);
156         } else {
157             return value;
158         }
159     }
160
161     /**
162      * Assembles a datapoint with the given parameters.
163      */
164     protected HmDatapoint assembleDatapoint(String name, String unit, String type, String[] options, Object min,
165             Object max, Integer operations, Object defaultValue, HmParamsetType paramsetType, boolean isHmIpDevice)
166             throws IOException {
167         HmDatapoint dp = new HmDatapoint();
168         dp.setName(name);
169         dp.setDescription(name);
170         dp.setUnit(StringUtils.replace(StringUtils.trimToNull(unit), "\ufffd", "°"));
171         if (dp.getUnit() == null && StringUtils.startsWith(dp.getName(), "RSSI_")) {
172             dp.setUnit("dBm");
173         }
174
175         HmValueType valueType = HmValueType.parse(type);
176         if (valueType == null || valueType == HmValueType.UNKNOWN) {
177             throw new IOException("Unknown datapoint type: " + type);
178         } else if (valueType == HmValueType.FLOAT && dp.getUnit() == null
179                 && dp.getName().matches("\\w*_TEMPERATURE(_\\w.*|$)")) {
180             logger.debug("No unit information found for temperature datapoint {}, assuming Number:Temperature",
181                     dp.getName());
182             dp.setUnit("°C"); // Bypass for a problem with HMIP devices where unit of temperature channels is sometimes
183                               // empty
184         }
185         dp.setType(valueType);
186
187         dp.setOptions(options);
188         if (dp.isNumberType() || dp.isEnumType()) {
189             if (isHmIpDevice && dp.isEnumType()) {
190                 dp.setMinValue(dp.getOptionIndex(toString(min)));
191                 dp.setMaxValue(dp.getOptionIndex(toString(max)));
192             } else {
193                 dp.setMinValue(toNumber(min));
194                 dp.setMaxValue(toNumber(max));
195             }
196         }
197         dp.setReadOnly((operations & 2) != 2);
198         dp.setReadable((operations & 1) == 1);
199         dp.setParamsetType(paramsetType);
200         if (isHmIpDevice && dp.isEnumType()) {
201             dp.setDefaultValue(dp.getOptionIndex(toString(defaultValue)));
202         } else {
203             dp.setDefaultValue(convertToType(dp, defaultValue));
204         }
205         dp.setValue(dp.getDefaultValue());
206         return dp;
207     }
208
209     /**
210      * Converts a string value to the type.
211      */
212     protected Object convertToType(String value) {
213         if (StringUtils.isBlank(value)) {
214             return null;
215         }
216         if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("on")) {
217             return (Boolean.TRUE);
218         } else if (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("off")) {
219             return (Boolean.FALSE);
220         } else if (value.matches("(-|\\+)?[0-9]+")) {
221             return (Integer.valueOf(value));
222         } else if (value.matches("[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?")) {
223             return (Double.valueOf(value));
224         } else {
225             return value;
226         }
227     }
228 }