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
14 package org.openhab.binding.souliss.internal.handler;
16 import javax.measure.quantity.Temperature;
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.openhab.binding.souliss.internal.SoulissBindingConstants;
20 import org.openhab.binding.souliss.internal.SoulissProtocolConstants;
21 import org.openhab.binding.souliss.internal.protocol.HalfFloatUtils;
22 import org.openhab.core.library.types.OnOffType;
23 import org.openhab.core.library.types.QuantityType;
24 import org.openhab.core.library.types.StringType;
25 import org.openhab.core.library.unit.SIUnits;
26 import org.openhab.core.thing.ChannelUID;
27 import org.openhab.core.thing.Thing;
28 import org.openhab.core.thing.ThingStatus;
29 import org.openhab.core.types.Command;
30 import org.openhab.core.types.PrimitiveType;
31 import org.openhab.core.types.RefreshType;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
36 * The {@link SoulissT31Handler} is responsible for handling commands, which are
37 * sent to one of the channels.
39 * @author Luca Remigio - Initial contribution
40 * @author Luca Calcaterra - Refactor for OH3
43 public class SoulissT31Handler extends SoulissGenericHandler {
45 private final Logger logger = LoggerFactory.getLogger(SoulissT31Handler.class);
47 QuantityType<Temperature> setMeasuredValue = new QuantityType<>("0");
48 QuantityType<Temperature> setPointValue = new QuantityType<>("0");
49 StringType fanStateValue = StringType.EMPTY;
50 StringType powerState = StringType.EMPTY;
51 StringType fireState = StringType.EMPTY;
52 StringType lastModeState = StringType.EMPTY;
53 StringType modeStateValue = StringType.EMPTY;
55 public SoulissT31Handler(Thing pThing) {
60 // called on every status change or change request
62 public void handleCommand(ChannelUID channelUID, Command command) {
63 if (!(command instanceof RefreshType)) {
64 switch (channelUID.getId()) {
66 case SoulissBindingConstants.T31_SYSTEM_CHANNEL:
67 if (command.equals(OnOffType.OFF)) {
68 commandSEND(SoulissProtocolConstants.SOULISS_T3N_SHUTDOWN);
70 if (modeStateValue.toString()
71 .equals(SoulissBindingConstants.T31_HEATINGMODE_MESSAGE_MODE_CHANNEL)) {
72 commandSEND(SoulissProtocolConstants.SOULISS_T3N_HEATING);
74 commandSEND(SoulissProtocolConstants.SOULISS_T3N_COOLING);
78 case SoulissBindingConstants.T31_MODE_CHANNEL:
79 if (command.toString().equals(SoulissBindingConstants.T31_HEATINGMODE_MESSAGE_MODE_CHANNEL)) {
80 commandSEND(SoulissProtocolConstants.SOULISS_T3N_HEATING);
82 commandSEND(SoulissProtocolConstants.SOULISS_T3N_COOLING);
85 case SoulissBindingConstants.T31_BUTTON_CHANNEL:
86 if (command.equals(OnOffType.ON)) {
87 commandSEND(SoulissProtocolConstants.SOULISS_T3N_AS_MEASURED);
90 case SoulissBindingConstants.T31_FAN_CHANNEL:
91 switch (command.toString()) {
92 case SoulissBindingConstants.T31_FANHIGH_MESSAGE_FAN_CHANNEL:
93 commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_MANUAL);
94 commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_HIGH);
95 fanStateValue = StringType.valueOf(SoulissBindingConstants.T31_FANHIGH_MESSAGE_FAN_CHANNEL);
97 case SoulissBindingConstants.T31_FANMEDIUM_MESSAGE_FAN_CHANNEL:
98 commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_MANUAL);
99 commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_MED);
100 fanStateValue = StringType
101 .valueOf(SoulissBindingConstants.T31_FANMEDIUM_MESSAGE_FAN_CHANNEL);
103 case SoulissBindingConstants.T31_FANLOW_MESSAGE_FAN_CHANNEL:
104 commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_MANUAL);
105 commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_LOW);
106 fanStateValue = StringType.valueOf(SoulissBindingConstants.T31_FANLOW_MESSAGE_FAN_CHANNEL);
108 case SoulissBindingConstants.T31_FANAUTO_MESSAGE_FAN_CHANNEL:
109 commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_AUTO);
110 fanStateValue = StringType.valueOf(SoulissBindingConstants.T31_FANAUTO_MESSAGE_FAN_CHANNEL);
112 case SoulissBindingConstants.T31_FANOFF_MESSAGE_FAN_CHANNEL:
113 commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_OFF);
114 fanStateValue = StringType.valueOf(SoulissBindingConstants.T31_FANOFF_MESSAGE_FAN_CHANNEL);
117 logger.debug("Fan Channel handle not recognized, skipping..");
121 case SoulissBindingConstants.T31_SETPOINT_CHANNEL:
122 if (command instanceof QuantityType<?>) {
123 int uu = HalfFloatUtils.fromFloat(((QuantityType<?>) command).floatValue());
124 byte b2 = (byte) (uu >> 8);
127 commandSEND(SoulissProtocolConstants.SOULISS_T31_USE_OF_SLOT_SETPOINT_COMMAND, b1, b2);
132 logger.debug("state not recognized! skipping..");
139 public void initialize() {
142 updateStatus(ThingStatus.UNKNOWN);
144 var configurationMap = getThing().getConfiguration();
145 if (configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND) != null) {
146 bSecureSend = ((Boolean) configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND)).booleanValue();
150 public void setState(PrimitiveType state) {
151 this.updateState(SoulissBindingConstants.T31_BUTTON_CHANNEL, OnOffType.OFF);
153 super.setLastStatusStored();
154 if (state instanceof StringType) {
155 switch (state.toString()) {
156 case SoulissBindingConstants.T31_FANLOW_MESSAGE_FAN_CHANNEL:
157 case SoulissBindingConstants.T31_FANMEDIUM_MESSAGE_FAN_CHANNEL:
158 case SoulissBindingConstants.T31_FANHIGH_MESSAGE_FAN_CHANNEL:
159 case SoulissBindingConstants.T31_FANAUTO_MESSAGE_FAN_CHANNEL:
160 case SoulissBindingConstants.T31_FANOFF_MESSAGE_FAN_CHANNEL:
161 if (!fanStateValue.equals(state)) {
162 this.updateState(SoulissBindingConstants.T31_FAN_CHANNEL, (StringType) state);
163 fanStateValue = (StringType) state;
167 case SoulissBindingConstants.T31_HEATINGMODE_MESSAGE_MODE_CHANNEL:
168 if (!modeStateValue.equals(state)) {
169 this.updateState(SoulissBindingConstants.T31_MODE_CHANNEL, (StringType) state);
170 modeStateValue = (StringType) state;
174 case SoulissBindingConstants.T31_COOLINGMODE_MESSAGE_MODE_CHANNEL:
175 if (!modeStateValue.equals(state)) {
176 this.updateState(SoulissBindingConstants.T31_MODE_CHANNEL, (StringType) state);
177 modeStateValue = (StringType) state;
181 case SoulissBindingConstants.T31_OFF_MESSAGE_SYSTEM_CHANNEL:
182 if (!powerState.equals(state)) {
183 this.updateState(SoulissBindingConstants.T31_SYSTEM_CHANNEL, OnOffType.OFF);
184 powerState = (StringType) state;
187 case SoulissBindingConstants.T31_ON_MESSAGE_SYSTEM_CHANNEL:
188 if (!powerState.equals(state)) {
189 this.updateState(SoulissBindingConstants.T31_SYSTEM_CHANNEL, OnOffType.ON);
190 powerState = (StringType) state;
194 case SoulissBindingConstants.T31_ON_MESSAGE_FIRE_CHANNEL:
195 if (!fireState.equals(state)) {
196 this.updateState(SoulissBindingConstants.T31_FIRE_CHANNEL, OnOffType.ON);
197 fireState = (StringType) state;
200 case SoulissBindingConstants.T31_OFF_MESSAGE_FIRE_CHANNEL:
201 if (!fireState.equals(state)) {
202 this.updateState(SoulissBindingConstants.T31_FIRE_CHANNEL, OnOffType.OFF);
203 fireState = (StringType) state;
213 public void setMeasuredValue(QuantityType<Temperature> valueOf) {
214 if ((valueOf instanceof QuantityType<?>) && (!setMeasuredValue.equals(valueOf))) {
215 this.updateState(SoulissBindingConstants.T31_VALUE_CHANNEL, valueOf);
216 setMeasuredValue = valueOf;
220 public void setSetpointValue(QuantityType<Temperature> valueOf) {
221 if ((valueOf instanceof QuantityType<?>) && (!setPointValue.equals(valueOf))) {
222 this.updateState(SoulissBindingConstants.T31_SETPOINT_CHANNEL, valueOf);
223 setPointValue = valueOf;
227 public void setRawStateValues(byte rawStateByte0, float valTemp, float valSetPoint) {
229 switch (getBitState(rawStateByte0, 0)) {
231 sMessage = SoulissBindingConstants.T31_OFF_MESSAGE_SYSTEM_CHANNEL;
234 sMessage = SoulissBindingConstants.T31_ON_MESSAGE_SYSTEM_CHANNEL;
237 logger.debug("System Channel on/off not recognized, skipping");
240 this.setState(StringType.valueOf(sMessage));
242 switch (getBitState(rawStateByte0, 7)) {
244 sMessage = SoulissBindingConstants.T31_HEATINGMODE_MESSAGE_MODE_CHANNEL;
247 sMessage = SoulissBindingConstants.T31_COOLINGMODE_MESSAGE_MODE_CHANNEL;
250 logger.debug("Mode not recognized, skipping");
253 this.setState(StringType.valueOf(sMessage));
255 // button indicating whether the system is running or not
256 switch (getBitState(rawStateByte0, 1) + getBitState(rawStateByte0, 2)) {
258 sMessage = SoulissBindingConstants.T31_OFF_MESSAGE_FIRE_CHANNEL;
261 sMessage = SoulissBindingConstants.T31_ON_MESSAGE_FIRE_CHANNEL;
264 logger.debug("Fire not recognized, skipping");
267 this.setState(StringType.valueOf(sMessage));
270 switch (getBitState(rawStateByte0, 3) + getBitState(rawStateByte0, 4) + getBitState(rawStateByte0, 5)) {
272 sMessage = SoulissBindingConstants.T31_FANOFF_MESSAGE_FAN_CHANNEL;
275 sMessage = SoulissBindingConstants.T31_FANLOW_MESSAGE_FAN_CHANNEL;
278 sMessage = SoulissBindingConstants.T31_FANMEDIUM_MESSAGE_FAN_CHANNEL;
281 sMessage = SoulissBindingConstants.T31_FANHIGH_MESSAGE_FAN_CHANNEL;
284 logger.debug("Fan speed not recognized, skipping");
288 this.setState(StringType.valueOf(sMessage));
290 // SLOT 1-2: Temperature Value
291 if (!Float.isNaN(valTemp)) {
292 this.setMeasuredValue(QuantityType.valueOf(valTemp, SIUnits.CELSIUS));
295 // SLOT 3-4: Setpoint Value
296 if (!Float.isNaN(valSetPoint)) {
297 this.setSetpointValue(QuantityType.valueOf(valSetPoint, SIUnits.CELSIUS));
302 public byte getRawState() {
307 public byte getExpectedRawState(byte bCommand) {
311 public byte getBitState(byte vRaw, int iBit) {
312 final var maskBit1 = 0x1;
314 if (((vRaw >>> iBit) & maskBit1) == 0) {
322 public void setRawState(byte rawState) {
323 throw new UnsupportedOperationException("Not Implemented, yet.");