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