]> git.basschouten.com Git - openhab-addons.git/blob
27b6b0d54a1deabe25ff454a693adfa9ffd6f221
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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
17 import org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration;
18 import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
19 import org.openhab.binding.rfxcom.internal.exceptions.RFXComInvalidStateException;
20 import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
21 import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
22 import org.openhab.binding.rfxcom.internal.handler.DeviceState;
23 import org.openhab.core.library.types.IncreaseDecreaseType;
24 import org.openhab.core.library.types.OnOffType;
25 import org.openhab.core.library.types.OpenClosedType;
26 import org.openhab.core.library.types.StringType;
27 import org.openhab.core.types.Command;
28 import org.openhab.core.types.State;
29 import org.openhab.core.types.Type;
30 import org.openhab.core.types.UnDefType;
31
32 /**
33  * RFXCOM data class for lighting1 message. See X10, ARC, etc..
34  *
35  * @author Evert van Es, Cycling Engineer - Initial contribution
36  * @author Pauli Anttila
37  */
38 public class RFXComLighting1Message extends RFXComDeviceMessageImpl<RFXComLighting1Message.SubType> {
39
40     public enum SubType implements ByteEnumWrapper {
41         X10(0),
42         ARC(1),
43         AB400D(2),
44         WAVEMAN(3),
45         EMW200(4),
46         IMPULS(5),
47         RISINGSUN(6),
48         PHILIPS(7),
49         ENERGENIE(8),
50         ENERGENIE_5(9),
51         COCO(10),
52         HQ_COCO20(11);
53
54         private final int subType;
55
56         SubType(int subType) {
57             this.subType = subType;
58         }
59
60         @Override
61         public byte toByte() {
62             return (byte) subType;
63         }
64     }
65
66     public enum Commands implements ByteEnumWrapper {
67         OFF(0),
68         ON(1),
69         DIM(2),
70         BRIGHT(3),
71         GROUP_OFF(5),
72         GROUP_ON(6),
73         CHIME(7);
74
75         private final int command;
76
77         Commands(int command) {
78             this.command = command;
79         }
80
81         @Override
82         public byte toByte() {
83             return (byte) command;
84         }
85     }
86
87     public SubType subType;
88     public char houseCode;
89     public byte unitCode;
90     public Commands command;
91     public boolean group;
92
93     private static byte[] lastUnit = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
94
95     public RFXComLighting1Message() {
96         super(PacketType.LIGHTING1);
97     }
98
99     public RFXComLighting1Message(byte[] data) throws RFXComException {
100         encodeMessage(data);
101     }
102
103     @Override
104     public String toString() {
105         String str = "";
106
107         str += super.toString();
108         str += ", Sub type = " + subType;
109         str += ", Device Id = " + getDeviceId();
110         str += ", Command = " + command;
111         str += ", Signal level = " + signalLevel;
112
113         return str;
114     }
115
116     @Override
117     public void encodeMessage(byte[] data) throws RFXComException {
118         super.encodeMessage(data);
119
120         subType = ByteEnumUtil.fromByte(SubType.class, super.subType);
121         houseCode = (char) data[4];
122         command = ByteEnumUtil.fromByte(Commands.class, data[6]);
123
124         if ((command == Commands.GROUP_ON) || (command == Commands.GROUP_OFF)) {
125             unitCode = 0;
126         } else if ((data[5] == 0) && ((command == Commands.DIM) || (command == Commands.BRIGHT))) {
127             // SS13 switches broadcast DIM/BRIGHT to X0 and the dimmers ignore
128             // the message unless the last X<n> ON they saw was for them. So we
129             // redirect an incoming broadcast DIM/BRIGHT to the correct item
130             // based on the last X<n> we saw or sent.
131             unitCode = lastUnit[houseCode - 'A'];
132         } else {
133             unitCode = data[5];
134             if (command == Commands.ON) {
135                 lastUnit[houseCode - 'A'] = unitCode;
136             }
137         }
138
139         signalLevel = (byte) ((data[7] & 0xF0) >> 4);
140     }
141
142     @Override
143     public byte[] decodeMessage() {
144         // Example data 07 10 01 00 42 01 01 70
145         // 07 10 01 00 42 10 06 70
146
147         byte[] data = new byte[8];
148
149         data[0] = 0x07;
150         data[1] = PacketType.LIGHTING1.toByte();
151         data[2] = subType.toByte();
152         data[3] = seqNbr;
153         data[4] = (byte) houseCode;
154         data[5] = unitCode;
155         data[6] = command.toByte();
156         data[7] = (byte) ((signalLevel & 0x0F) << 4);
157
158         return data;
159     }
160
161     @Override
162     public String getDeviceId() {
163         return houseCode + ID_DELIMITER + unitCode;
164     }
165
166     @Override
167     public Command convertToCommand(String channelId, RFXComDeviceConfiguration config, DeviceState deviceState)
168             throws RFXComUnsupportedChannelException, RFXComInvalidStateException {
169         switch (channelId) {
170             case CHANNEL_COMMAND:
171                 switch (command) {
172                     case OFF:
173                     case GROUP_OFF:
174                         return OnOffType.OFF;
175
176                     case ON:
177                     case GROUP_ON:
178                         return OnOffType.ON;
179
180                     case DIM:
181                         return IncreaseDecreaseType.DECREASE;
182
183                     case BRIGHT:
184                         return IncreaseDecreaseType.INCREASE;
185
186                     case CHIME:
187                         return OnOffType.ON;
188
189                     default:
190                         throw new RFXComUnsupportedChannelException(
191                                 "Channel " + channelId + " does not accept " + command);
192                 }
193
194             default:
195                 return super.convertToCommand(channelId, config, deviceState);
196         }
197     }
198
199     @Override
200     public State convertToState(String channelId, RFXComDeviceConfiguration config, DeviceState deviceState)
201             throws RFXComUnsupportedChannelException {
202         switch (channelId) {
203             case CHANNEL_COMMAND:
204                 switch (command) {
205                     case OFF:
206                     case GROUP_OFF:
207                     case DIM:
208                         return OnOffType.OFF;
209
210                     case ON:
211                     case GROUP_ON:
212                     case BRIGHT:
213                     case CHIME:
214                         return OnOffType.ON;
215
216                     default:
217                         throw new RFXComUnsupportedChannelException(
218                                 "Channel " + channelId + " does not accept " + command);
219                 }
220
221             case CHANNEL_COMMAND_STRING:
222                 return command == null ? UnDefType.UNDEF : StringType.valueOf(command.toString());
223
224             case CHANNEL_CONTACT:
225                 switch (command) {
226                     case OFF:
227                     case GROUP_OFF:
228                     case DIM:
229                         return OpenClosedType.CLOSED;
230
231                     case ON:
232                     case GROUP_ON:
233                     case BRIGHT:
234                     case CHIME:
235                         return OpenClosedType.OPEN;
236
237                     default:
238                         throw new RFXComUnsupportedChannelException(
239                                 "Channel " + channelId + " does not accept " + command);
240                 }
241
242             default:
243                 throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
244         }
245     }
246
247     @Override
248     public void setSubType(SubType subType) {
249         this.subType = subType;
250     }
251
252     @Override
253     public void setDeviceId(String deviceId) throws RFXComException {
254         String[] ids = deviceId.split("\\" + ID_DELIMITER);
255         if (ids.length != 2) {
256             throw new RFXComException("Invalid device id '" + deviceId + "'");
257         }
258
259         houseCode = ids[0].charAt(0);
260
261         // Get unitcode, 0 means group
262         unitCode = Byte.parseByte(ids[1]);
263         if (unitCode == 0) {
264             unitCode = 1;
265             group = true;
266         }
267     }
268
269     @Override
270     public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
271         switch (channelId) {
272             case CHANNEL_COMMAND:
273                 if (type instanceof OnOffType) {
274                     if (group) {
275                         command = (type == OnOffType.ON ? Commands.GROUP_ON : Commands.GROUP_OFF);
276
277                     } else {
278                         command = (type == OnOffType.ON ? Commands.ON : Commands.OFF);
279                     }
280                 } else {
281                     throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
282                 }
283                 break;
284
285             case CHANNEL_COMMAND_STRING:
286                 command = Commands.valueOf(type.toString().toUpperCase());
287                 break;
288
289             default:
290                 throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
291         }
292     }
293
294     @Override
295     public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
296         return ByteEnumUtil.convertSubType(SubType.class, subType);
297     }
298 }