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;
53 StringType lastModeState = StringType.EMPTY;
54 StringType modeStateValue = StringType.EMPTY;
56 public SoulissT31Handler(Thing pThing) {
61 // called on every status change or change request
63 public void handleCommand(ChannelUID channelUID, Command command) {
64 if (!(command instanceof RefreshType)) {
65 switch (channelUID.getId()) {
67 case SoulissBindingConstants.T31_SYSTEM_CHANNEL:
68 if (command.equals(OnOffType.OFF)) {
69 commandSEND(SoulissProtocolConstants.SOULISS_T3N_SHUTDOWN);
71 if (modeStateValue.toString()
72 .equals(SoulissBindingConstants.T31_HEATINGMODE_MESSAGE_MODE_CHANNEL)) {
73 commandSEND(SoulissProtocolConstants.SOULISS_T3N_HEATING);
75 commandSEND(SoulissProtocolConstants.SOULISS_T3N_COOLING);
79 case SoulissBindingConstants.T31_MODE_CHANNEL:
80 if (command.toString().equals(SoulissBindingConstants.T31_HEATINGMODE_MESSAGE_MODE_CHANNEL)) {
81 commandSEND(SoulissProtocolConstants.SOULISS_T3N_HEATING);
83 commandSEND(SoulissProtocolConstants.SOULISS_T3N_COOLING);
86 case SoulissBindingConstants.T31_BUTTON_CHANNEL:
87 if (command.equals(OnOffType.ON)) {
88 commandSEND(SoulissProtocolConstants.SOULISS_T3N_AS_MEASURED);
91 case SoulissBindingConstants.T31_FAN_CHANNEL:
92 switch (command.toString()) {
93 case SoulissBindingConstants.T31_FANHIGH_MESSAGE_FAN_CHANNEL:
94 commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_MANUAL);
95 commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_HIGH);
96 fanStateValue = StringType.valueOf(SoulissBindingConstants.T31_FANHIGH_MESSAGE_FAN_CHANNEL);
98 case SoulissBindingConstants.T31_FANMEDIUM_MESSAGE_FAN_CHANNEL:
99 commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_MANUAL);
100 commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_MED);
101 fanStateValue = StringType
102 .valueOf(SoulissBindingConstants.T31_FANMEDIUM_MESSAGE_FAN_CHANNEL);
104 case SoulissBindingConstants.T31_FANLOW_MESSAGE_FAN_CHANNEL:
105 commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_MANUAL);
106 commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_LOW);
107 fanStateValue = StringType.valueOf(SoulissBindingConstants.T31_FANLOW_MESSAGE_FAN_CHANNEL);
109 case SoulissBindingConstants.T31_FANAUTO_MESSAGE_FAN_CHANNEL:
110 commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_AUTO);
111 fanStateValue = StringType.valueOf(SoulissBindingConstants.T31_FANAUTO_MESSAGE_FAN_CHANNEL);
113 case SoulissBindingConstants.T31_FANOFF_MESSAGE_FAN_CHANNEL:
114 commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_OFF);
115 fanStateValue = StringType.valueOf(SoulissBindingConstants.T31_FANOFF_MESSAGE_FAN_CHANNEL);
118 logger.debug("Fan Channel handle not recognized, skipping..");
122 case SoulissBindingConstants.T31_SETPOINT_CHANNEL:
123 if (command instanceof QuantityType<?>) {
124 int uu = HalfFloatUtils.fromFloat(((QuantityType<?>) command).floatValue());
125 byte b2 = (byte) (uu >> 8);
128 commandSEND(SoulissProtocolConstants.SOULISS_T31_USE_OF_SLOT_SETPOINT_COMMAND, b1, b2);
133 logger.debug("state not recognized! skipping..");
140 public void initialize() {
143 updateStatus(ThingStatus.UNKNOWN);
145 var configurationMap = getThing().getConfiguration();
146 if (configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND) != null) {
147 bSecureSend = ((Boolean) configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND)).booleanValue();
151 public void setState(PrimitiveType state) {
152 this.updateState(SoulissBindingConstants.T31_BUTTON_CHANNEL, OnOffType.OFF);
154 super.setLastStatusStored();
155 if (state instanceof StringType) {
156 switch (state.toString()) {
157 case SoulissBindingConstants.T31_FANLOW_MESSAGE_FAN_CHANNEL:
158 case SoulissBindingConstants.T31_FANMEDIUM_MESSAGE_FAN_CHANNEL:
159 case SoulissBindingConstants.T31_FANHIGH_MESSAGE_FAN_CHANNEL:
160 case SoulissBindingConstants.T31_FANAUTO_MESSAGE_FAN_CHANNEL:
161 case SoulissBindingConstants.T31_FANOFF_MESSAGE_FAN_CHANNEL:
162 if (!fanStateValue.equals(state)) {
163 this.updateState(SoulissBindingConstants.T31_FAN_CHANNEL, (StringType) state);
164 fanStateValue = (StringType) state;
168 case SoulissBindingConstants.T31_HEATINGMODE_MESSAGE_MODE_CHANNEL:
169 case SoulissBindingConstants.T31_COOLINGMODE_MESSAGE_MODE_CHANNEL:
170 if (!modeStateValue.equals(state)) {
171 this.updateState(SoulissBindingConstants.T31_MODE_CHANNEL, (StringType) state);
172 modeStateValue = (StringType) state;
176 case SoulissBindingConstants.T31_OFF_MESSAGE_SYSTEM_CHANNEL:
177 if (!powerState.equals(state)) {
178 this.updateState(SoulissBindingConstants.T31_SYSTEM_CHANNEL, OnOffType.OFF);
179 powerState = (StringType) state;
182 case SoulissBindingConstants.T31_ON_MESSAGE_SYSTEM_CHANNEL:
183 if (!powerState.equals(state)) {
184 this.updateState(SoulissBindingConstants.T31_SYSTEM_CHANNEL, OnOffType.ON);
185 powerState = (StringType) state;
189 case SoulissBindingConstants.T31_ON_MESSAGE_FIRE_CHANNEL:
190 if (!fireState.equals(state)) {
191 this.updateState(SoulissBindingConstants.T31_FIRE_CHANNEL, OnOffType.ON);
192 powerState = (StringType) state;
195 case SoulissBindingConstants.T31_OFF_MESSAGE_FIRE_CHANNEL:
196 if (!fireState.equals(state)) {
197 this.updateState(SoulissBindingConstants.T31_FIRE_CHANNEL, OnOffType.OFF);
198 powerState = (StringType) state;
208 public void setMeasuredValue(QuantityType<Temperature> valueOf) {
209 if ((valueOf instanceof QuantityType<?>) && (!setMeasuredValue.equals(valueOf))) {
210 this.updateState(SoulissBindingConstants.T31_VALUE_CHANNEL, valueOf);
211 setMeasuredValue = valueOf;
215 public void setSetpointValue(QuantityType<Temperature> valueOf) {
216 if ((valueOf instanceof QuantityType<?>) && (!setPointValue.equals(valueOf))) {
217 this.updateState(SoulissBindingConstants.T31_SETPOINT_CHANNEL, valueOf);
218 setPointValue = valueOf;
222 public void setRawStateValues(byte rawStateByte0, float valTemp, float valSetPoint) {
224 switch (getBitState(rawStateByte0, 0)) {
226 sMessage = SoulissBindingConstants.T31_OFF_MESSAGE_SYSTEM_CHANNEL;
229 sMessage = SoulissBindingConstants.T31_ON_MESSAGE_SYSTEM_CHANNEL;
232 logger.debug("System Channel on/off not recognized, skipping");
235 this.setState(StringType.valueOf(sMessage));
237 switch (getBitState(rawStateByte0, 7)) {
239 sMessage = SoulissBindingConstants.T31_HEATINGMODE_MESSAGE_MODE_CHANNEL;
242 sMessage = SoulissBindingConstants.T31_COOLINGMODE_MESSAGE_MODE_CHANNEL;
245 logger.debug("Mode not recognized, skipping");
248 this.setState(StringType.valueOf(sMessage));
250 // button indicating whether the system is running or not
251 switch (getBitState(rawStateByte0, 1) + getBitState(rawStateByte0, 2)) {
253 sMessage = SoulissBindingConstants.T31_OFF_MESSAGE_FIRE_CHANNEL;
256 sMessage = SoulissBindingConstants.T31_ON_MESSAGE_FIRE_CHANNEL;
259 logger.debug("Fire not recognized, skipping");
262 this.setState(StringType.valueOf(sMessage));
265 switch (getBitState(rawStateByte0, 3) + getBitState(rawStateByte0, 4) + getBitState(rawStateByte0, 5)) {
267 sMessage = SoulissBindingConstants.T31_FANOFF_MESSAGE_FAN_CHANNEL;
270 sMessage = SoulissBindingConstants.T31_FANLOW_MESSAGE_FAN_CHANNEL;
273 sMessage = SoulissBindingConstants.T31_FANMEDIUM_MESSAGE_FAN_CHANNEL;
276 sMessage = SoulissBindingConstants.T31_FANHIGH_MESSAGE_FAN_CHANNEL;
279 logger.debug("Fan speed not recognized, skipping");
283 this.setState(StringType.valueOf(sMessage));
285 // SLOT 1-2: Temperature Value
286 if (!Float.isNaN(valTemp)) {
287 this.setMeasuredValue(QuantityType.valueOf(valTemp, SIUnits.CELSIUS));
290 // SLOT 3-4: Setpoint Value
291 if (!Float.isNaN(valSetPoint)) {
292 this.setSetpointValue(QuantityType.valueOf(valSetPoint, SIUnits.CELSIUS));
297 public byte getRawState() {
302 public byte getExpectedRawState(byte bCommand) {
306 public byte getBitState(byte vRaw, int iBit) {
307 final var maskBit1 = 0x1;
309 if (((vRaw >>> iBit) & maskBit1) == 0) {
317 public void setRawState(byte rawState) {
318 throw new UnsupportedOperationException("Not Implemented, yet.");