2 * Copyright (c) 2010-2021 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.openwebnet.internal.handler;
15 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.*;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants;
21 import org.openhab.core.library.types.DecimalType;
22 import org.openhab.core.library.types.QuantityType;
23 import org.openhab.core.library.types.StringType;
24 import org.openhab.core.library.unit.SIUnits;
25 import org.openhab.core.thing.ChannelUID;
26 import org.openhab.core.thing.Thing;
27 import org.openhab.core.thing.ThingStatus;
28 import org.openhab.core.thing.ThingStatusInfo;
29 import org.openhab.core.thing.ThingTypeUID;
30 import org.openhab.core.types.Command;
31 import org.openhab.core.types.UnDefType;
32 import org.openwebnet4j.communication.OWNException;
33 import org.openwebnet4j.message.BaseOpenMessage;
34 import org.openwebnet4j.message.FrameException;
35 import org.openwebnet4j.message.MalformedFrameException;
36 import org.openwebnet4j.message.Thermoregulation;
37 import org.openwebnet4j.message.Where;
38 import org.openwebnet4j.message.WhereThermo;
39 import org.openwebnet4j.message.Who;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
44 * The {@link OpenWebNetThermoregulationHandler} is responsible for handling commands/messages for Thermoregulation
45 * Things. It extends the abstract {@link OpenWebNetThingHandler}.
47 * @author Massimo Valla - Initial contribution
48 * @author Andrea Conte - Thermoregulation
49 * @author Gilberto Cocchi - Thermoregulation
52 public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
54 private final Logger logger = LoggerFactory.getLogger(OpenWebNetThermoregulationHandler.class);
56 public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = OpenWebNetBindingConstants.THERMOREGULATION_SUPPORTED_THING_TYPES;
58 private boolean isTempSensor = false; // is the thing a sensor ?
60 private double currentSetPointTemp = 11.5d; // 11.5 is the default setTemp used in MyHomeUP mobile app
62 private Thermoregulation.Function currentFunction = Thermoregulation.Function.GENERIC;
64 public OpenWebNetThermoregulationHandler(Thing thing) {
69 public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
70 super.bridgeStatusChanged(bridgeStatusInfo);
71 // when the bridge is ONLINE request for thing states (temp, setTemp, fanSpeed...)
72 if (bridgeStatusInfo.getStatus().equals(ThingStatus.ONLINE)) {
78 protected void handleChannelCommand(ChannelUID channel, Command command) {
79 switch (channel.getId()) {
80 case CHANNEL_TEMP_SETPOINT:
81 handleSetpoint(command);
83 case CHANNEL_FUNCTION:
84 handleFunction(command);
89 case CHANNEL_FAN_SPEED:
90 handleSetFanSpeed(command);
93 logger.warn("handleChannelCommand() Unsupported ChannelUID {}", channel.getId());
99 protected void requestChannelState(ChannelUID channel) {
100 refreshDevice(false);
104 protected Where buildBusWhere(String wStr) throws IllegalArgumentException {
105 WhereThermo wt = new WhereThermo(wStr);
113 protected String ownIdPrefix() {
114 return Who.THERMOREGULATION.value().toString();
117 private void handleSetFanSpeed(Command command) {
118 if (command instanceof StringType) {
119 Where w = deviceWhere;
122 Thermoregulation.FanCoilSpeed speed = Thermoregulation.FanCoilSpeed.valueOf(command.toString());
123 send(Thermoregulation.requestWriteFanCoilSpeed(w.value(), speed));
124 } catch (OWNException e) {
125 logger.warn("handleSetFanSpeed() {}", e.getMessage());
126 } catch (IllegalArgumentException e) {
127 logger.warn("handleSetFanSpeed() Unsupported command {} for thing {}", command,
128 getThing().getUID());
133 logger.warn("handleSetFanSpeed() Unsupported command {} for thing {}", command, getThing().getUID());
137 private void handleSetpoint(Command command) {
138 if (command instanceof QuantityType || command instanceof DecimalType) {
139 Where w = deviceWhere;
142 if (command instanceof QuantityType) {
143 QuantityType<?> tempCelsius = ((QuantityType<?>) command).toUnit(SIUnits.CELSIUS);
144 if (tempCelsius != null) {
145 newTemp = tempCelsius.doubleValue();
148 newTemp = ((DecimalType) command).doubleValue();
151 send(Thermoregulation.requestWriteSetpointTemperature(w.value(), newTemp, currentFunction));
152 } catch (MalformedFrameException | OWNException e) {
153 logger.warn("handleSetpoint() {}", e.getMessage());
157 logger.warn("handleSetpoint() Unsupported command {} for thing {}", command, getThing().getUID());
161 private void handleMode(Command command) {
162 if (command instanceof StringType) {
163 Where w = deviceWhere;
166 Thermoregulation.OperationMode mode = Thermoregulation.OperationMode.valueOf(command.toString());
167 send(Thermoregulation.requestWriteMode(w.value(), mode, currentFunction, currentSetPointTemp));
168 } catch (OWNException e) {
169 logger.warn("handleMode() {}", e.getMessage());
170 } catch (IllegalArgumentException e) {
171 logger.warn("handleMode() Unsupported command {} for thing {}", command, getThing().getUID());
176 logger.warn("handleMode() Unsupported command {} for thing {}", command, getThing().getUID());
180 private void handleFunction(Command command) {
181 if (command instanceof StringType) {
182 Where w = deviceWhere;
185 Thermoregulation.Function function = Thermoregulation.Function.valueOf(command.toString());
186 send(Thermoregulation.requestWriteFunction(w.value(), function));
187 } catch (OWNException e) {
188 logger.warn("handleFunction() {}", e.getMessage());
189 } catch (IllegalArgumentException e) {
190 logger.warn("handleFunction() Unsupported command {} for thing {}", command, getThing().getUID());
195 logger.warn("handleFunction() Unsupported command {} for thing {}", command, getThing().getUID());
200 protected void handleMessage(BaseOpenMessage msg) {
201 super.handleMessage(msg);
202 if (msg.isCommand()) {
203 updateModeAndFunction((Thermoregulation) msg);
205 if (msg.getDim() == null) {
208 if (msg.getDim() == Thermoregulation.DimThermo.TEMPERATURE
209 || msg.getDim() == Thermoregulation.DimThermo.PROBE_TEMPERATURE) {
210 updateTemperature((Thermoregulation) msg);
211 } else if (msg.getDim() == Thermoregulation.DimThermo.TEMP_SETPOINT
212 || msg.getDim() == Thermoregulation.DimThermo.COMPLETE_PROBE_STATUS) {
213 updateSetpoint((Thermoregulation) msg);
214 } else if (msg.getDim() == Thermoregulation.DimThermo.VALVES_STATUS) {
215 updateValveStatus((Thermoregulation) msg);
216 } else if (msg.getDim() == Thermoregulation.DimThermo.ACTUATOR_STATUS) {
217 updateActuatorStatus((Thermoregulation) msg);
218 } else if (msg.getDim() == Thermoregulation.DimThermo.FAN_COIL_SPEED) {
219 updateFanCoilSpeed((Thermoregulation) msg);
221 logger.debug("handleMessage() Ignoring unsupported DIM {} for thing {}. Frame={}", msg.getDim(),
222 getThing().getUID(), msg);
227 private void updateModeAndFunction(Thermoregulation tmsg) {
228 if (tmsg.getWhat() == null) {
229 logger.debug("updateModeAndFunction() Could not parse Mode or Function from {} (what is null)",
230 tmsg.getFrameValue());
234 Thermoregulation.WhatThermo w = Thermoregulation.WhatThermo.fromValue(tmsg.getWhat().value());
236 if (w.mode() == null) {
237 logger.debug("updateModeAndFunction() Could not parse Mode from: {}", tmsg.getFrameValue());
240 if (w.function() == null) {
241 logger.debug("updateModeAndFunction() Could not parse Function from: {}", tmsg.getFrameValue());
245 Thermoregulation.OperationMode mode = w.mode();
246 Thermoregulation.Function function = w.function();
248 if (w == Thermoregulation.WhatThermo.HEATING) {
249 function = Thermoregulation.Function.HEATING;
250 } else if (w == Thermoregulation.WhatThermo.CONDITIONING) {
251 function = Thermoregulation.Function.COOLING;
254 updateState(CHANNEL_MODE, new StringType(mode.toString()));
255 updateState(CHANNEL_FUNCTION, new StringType(function.toString()));
257 // store current function
258 currentFunction = function;
261 private void updateTemperature(Thermoregulation tmsg) {
263 double temp = Thermoregulation.parseTemperature(tmsg);
264 updateState(CHANNEL_TEMPERATURE, getAsQuantityTypeOrNull(temp, SIUnits.CELSIUS));
265 } catch (FrameException e) {
266 logger.warn("updateTemperature() FrameException on frame {}: {}", tmsg, e.getMessage());
267 updateState(CHANNEL_TEMPERATURE, UnDefType.UNDEF);
271 private void updateSetpoint(Thermoregulation tmsg) {
273 double temp = Thermoregulation.parseTemperature(tmsg);
274 updateState(CHANNEL_TEMP_SETPOINT, getAsQuantityTypeOrNull(temp, SIUnits.CELSIUS));
275 currentSetPointTemp = temp;
276 } catch (FrameException e) {
277 logger.warn("updateSetpoint() FrameException on frame {}: {}", tmsg, e.getMessage());
278 updateState(CHANNEL_TEMP_SETPOINT, UnDefType.UNDEF);
282 private void updateFanCoilSpeed(Thermoregulation tmsg) {
284 Thermoregulation.FanCoilSpeed speed = Thermoregulation.parseFanCoilSpeed(tmsg);
285 updateState(CHANNEL_FAN_SPEED, new StringType(speed.toString()));
286 } catch (FrameException e) {
287 logger.warn("updateFanCoilSpeed() FrameException on frame {}: {}", tmsg, e.getMessage());
288 updateState(CHANNEL_FAN_SPEED, UnDefType.UNDEF);
292 private void updateValveStatus(Thermoregulation tmsg) {
294 Thermoregulation.ValveOrActuatorStatus cv = Thermoregulation.parseValveStatus(tmsg,
295 Thermoregulation.WhatThermo.CONDITIONING);
296 updateState(CHANNEL_CONDITIONING_VALVES, new StringType(cv.toString()));
298 Thermoregulation.ValveOrActuatorStatus hv = Thermoregulation.parseValveStatus(tmsg,
299 Thermoregulation.WhatThermo.HEATING);
300 updateState(CHANNEL_HEATING_VALVES, new StringType(hv.toString()));
301 } catch (FrameException e) {
302 logger.warn("updateValveStatus() FrameException on frame {}: {}", tmsg, e.getMessage());
303 updateState(CHANNEL_CONDITIONING_VALVES, UnDefType.UNDEF);
304 updateState(CHANNEL_HEATING_VALVES, UnDefType.UNDEF);
308 private void updateActuatorStatus(Thermoregulation tmsg) {
310 Thermoregulation.ValveOrActuatorStatus hv = Thermoregulation.parseActuatorStatus(tmsg);
311 updateState(CHANNEL_ACTUATORS, new StringType(hv.toString()));
312 } catch (FrameException e) {
313 logger.warn("updateActuatorStatus() FrameException on frame {}: {}", tmsg, e.getMessage());
314 updateState(CHANNEL_ACTUATORS, UnDefType.UNDEF);
319 protected void refreshDevice(boolean refreshAll) {
320 if (deviceWhere != null) {
321 String w = deviceWhere.value();
323 send(Thermoregulation.requestTemperature(w));
324 if (!this.isTempSensor) {
325 // for bus_thermo_zone request also other single channels updates
326 send(Thermoregulation.requestSetPointTemperature(w));
327 send(Thermoregulation.requestFanCoilSpeed(w));
328 send(Thermoregulation.requestMode(w));
329 send(Thermoregulation.requestValvesStatus(w));
330 send(Thermoregulation.requestActuatorsStatus(w));
332 } catch (OWNException e) {
333 logger.warn("refreshDevice() where='{}' returned OWNException {}", w, e.getMessage());