]> git.basschouten.com Git - openhab-addons.git/blob
b721846ff3e3d224400d9ded376123443c04227c
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.rfxcom.internal.messages;
14
15 import static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
16 import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
17 import static org.openhab.binding.rfxcom.internal.messages.RFXComThermostat3Message.SubType.*;
18
19 import java.util.Arrays;
20 import java.util.List;
21
22 import org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration;
23 import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
24 import org.openhab.binding.rfxcom.internal.exceptions.RFXComInvalidStateException;
25 import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
26 import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
27 import org.openhab.binding.rfxcom.internal.handler.DeviceState;
28 import org.openhab.core.library.types.OnOffType;
29 import org.openhab.core.library.types.PercentType;
30 import org.openhab.core.library.types.StopMoveType;
31 import org.openhab.core.library.types.StringType;
32 import org.openhab.core.library.types.UpDownType;
33 import org.openhab.core.types.State;
34 import org.openhab.core.types.Type;
35 import org.openhab.core.types.UnDefType;
36
37 /**
38  * RFXCOM data class for thermostat3message.
39  *
40  * Mertik G6R-XXX Thermostat RF sensor operational
41  *
42  * @author Sander Biesenbeek - Initial contribution
43  * @author Ruud Beukema - Initial contribution (parallel development)
44  * @author Martin van Wingerden - Joined contribution of Sander & Ruud
45  */
46 public class RFXComThermostat3Message extends RFXComDeviceMessageImpl<RFXComThermostat3Message.SubType> {
47     public enum SubType implements ByteEnumWrapper {
48         MERTIK__G6R_H4T1(0),
49         MERTIK__G6R_H4TB__G6R_H4T__G6R_H4T21_Z22(1),
50         MERTIK__G6R_H4TD__G6R_H4T16(2),
51         MERTIK__G6R_H4S_TRANSMIT_ONLY(3);
52
53         private final int subType;
54
55         SubType(int subType) {
56             this.subType = subType;
57         }
58
59         @Override
60         public byte toByte() {
61             return (byte) subType;
62         }
63     }
64
65     public enum Commands implements ByteEnumWrapperWithSupportedSubTypes<SubType> {
66         OFF(0),
67         ON(1),
68         UP(2),
69         DOWN(3),
70         RUN_UP(4, MERTIK__G6R_H4T1),
71         SECOND_OFF(4, MERTIK__G6R_H4TB__G6R_H4T__G6R_H4T21_Z22),
72         RUN_DOWN(5, MERTIK__G6R_H4T1),
73         SECOND_ON(5, MERTIK__G6R_H4TB__G6R_H4T__G6R_H4T21_Z22),
74         STOP(6, MERTIK__G6R_H4T1);
75
76         private final int command;
77         private final List<SubType> supportedBySubTypes;
78
79         Commands(int command) {
80             this(command, SubType.values());
81         }
82
83         Commands(int command, SubType... supportedBySubTypes) {
84             this.command = command;
85             this.supportedBySubTypes = Arrays.asList(supportedBySubTypes);
86         }
87
88         @Override
89         public byte toByte() {
90             return (byte) command;
91         }
92
93         @Override
94         public List<SubType> supportedBySubTypes() {
95             return supportedBySubTypes;
96         }
97     }
98
99     public SubType subType;
100     private int unitId;
101     public Commands command;
102
103     public RFXComThermostat3Message() {
104         super(PacketType.THERMOSTAT3);
105     }
106
107     public RFXComThermostat3Message(byte[] data) throws RFXComException {
108         encodeMessage(data);
109     }
110
111     @Override
112     public String toString() {
113         String str = "";
114
115         str += super.toString();
116         str += ", Sub type = " + subType;
117         str += ", Device Id = " + getDeviceId();
118         str += ", Command = " + command;
119         str += ", Signal level = " + signalLevel;
120
121         return str;
122     }
123
124     @Override
125     public String getDeviceId() {
126         return String.valueOf(unitId);
127     }
128
129     @Override
130     public void encodeMessage(byte[] data) throws RFXComException {
131         super.encodeMessage(data);
132
133         subType = fromByte(SubType.class, super.subType);
134         unitId = (data[4] & 0xFF) << 16 | (data[5] & 0xFF) << 8 | (data[6] & 0xFF);
135         command = fromByte(Commands.class, data[7], subType);
136         signalLevel = (byte) ((data[8] & 0xF0) >> 4);
137     }
138
139     @Override
140     public byte[] decodeMessage() {
141         byte[] data = new byte[9];
142
143         data[0] = 0x08;
144         data[1] = RFXComBaseMessage.PacketType.THERMOSTAT3.toByte();
145         data[2] = subType.toByte();
146         data[3] = seqNbr;
147         data[4] = (byte) ((unitId >> 16) & 0xFF);
148         data[5] = (byte) ((unitId >> 8) & 0xFF);
149         data[6] = (byte) (unitId & 0xFF);
150         data[7] = command.toByte();
151         data[8] = (byte) ((signalLevel & 0x0F) << 4);
152
153         return data;
154     }
155
156     @Override
157     public State convertToState(String channelId, RFXComDeviceConfiguration config, DeviceState deviceState)
158             throws RFXComUnsupportedChannelException, RFXComInvalidStateException {
159         switch (channelId) {
160             case CHANNEL_COMMAND:
161                 switch (command) {
162                     case RUN_DOWN:
163                     case OFF:
164                         return OnOffType.OFF;
165                     case ON:
166                     case RUN_UP:
167                     case UP:
168                         return OnOffType.ON;
169                     case SECOND_ON:
170                     case SECOND_OFF:
171                         return null;
172                     default:
173                         return UnDefType.UNDEF;
174
175                 }
176             case CHANNEL_CONTROL:
177                 switch (command) {
178                     case ON:
179                         return OnOffType.ON;
180                     case UP:
181                     case RUN_UP:
182                         return UpDownType.UP;
183                     case OFF:
184                         return OnOffType.OFF;
185                     case DOWN:
186                     case RUN_DOWN:
187                         return UpDownType.DOWN;
188                     case SECOND_ON:
189                     case SECOND_OFF:
190                     case STOP:
191                         return null;
192                     default:
193                         throw new RFXComUnsupportedChannelException("Can't convert " + command + " for " + channelId);
194                 }
195             case CHANNEL_COMMAND_SECOND:
196                 switch (command) {
197                     case SECOND_OFF:
198                         return OnOffType.OFF;
199                     case SECOND_ON:
200                         return OnOffType.ON;
201                     default:
202                         return null;
203                 }
204             case CHANNEL_COMMAND_STRING:
205                 return command == null ? UnDefType.UNDEF : StringType.valueOf(command.toString());
206
207             default:
208                 return super.convertToState(channelId, config, deviceState);
209         }
210     }
211
212     @Override
213     public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
214         switch (channelId) {
215             case CHANNEL_COMMAND:
216                 if (type instanceof OnOffType) {
217                     command = (type == OnOffType.ON ? Commands.ON : Commands.OFF);
218                 } else {
219                     throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
220                 }
221                 break;
222
223             case CHANNEL_COMMAND_SECOND:
224                 if (type instanceof OnOffType) {
225                     command = (type == OnOffType.ON ? Commands.SECOND_ON : Commands.SECOND_OFF);
226                 } else {
227                     throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
228                 }
229                 break;
230
231             case CHANNEL_CONTROL:
232                 if (type instanceof UpDownType) {
233                     command = (type == UpDownType.UP ? Commands.UP : Commands.DOWN);
234                 } else if (type == StopMoveType.STOP) {
235                     command = Commands.STOP;
236                 } else if (type instanceof PercentType percentCommand) {
237                     command = percentCommand.as(UpDownType.class) == UpDownType.UP ? Commands.UP : Commands.DOWN;
238                 } else {
239                     throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
240                 }
241                 break;
242
243             case CHANNEL_COMMAND_STRING:
244                 command = Commands.valueOf(type.toString().toUpperCase());
245                 break;
246
247             default:
248                 throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
249         }
250     }
251
252     @Override
253     public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
254         return ByteEnumUtil.convertSubType(SubType.class, subType);
255     }
256
257     @Override
258     public void setSubType(SubType subType) {
259         this.subType = subType;
260     }
261
262     @Override
263     public void setDeviceId(String deviceId) {
264         this.unitId = Integer.parseInt(deviceId);
265     }
266 }