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