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