]> git.basschouten.com Git - openhab-addons.git/blob
279e14a54996a04ae73f561f7de0b2be2122547e
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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
18 import org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration;
19 import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
20 import org.openhab.binding.rfxcom.internal.exceptions.RFXComInvalidStateException;
21 import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
22 import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
23 import org.openhab.binding.rfxcom.internal.handler.DeviceState;
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.State;
28 import org.openhab.core.types.Type;
29
30 /**
31  * RFXCOM data class for Security1 message.
32  * (i.e. X10 Security, Visonic PowerCode, Meiantech, etc.)
33  *
34  * @author David Kalff - Initial contribution
35  * @author Pauli Anttila
36  */
37 public class RFXComSecurity1Message extends RFXComBatteryDeviceMessage<RFXComSecurity1Message.SubType> {
38
39     public enum SubType implements ByteEnumWrapper {
40         X10_SECURITY(0),
41         X10_SECURITY_MOTION(1),
42         X10_SECURITY_REMOTE(2),
43         KD101(3),
44         VISONIC_POWERCODE_SENSOR_PRIMARY_CONTACT(4),
45         VISONIC_POWERCODE_MOTION(5),
46         VISONIC_CODESECURE(6),
47         VISONIC_POWERCODE_SENSOR_AUX_CONTACT(7),
48         MEIANTECH(8),
49         SA30(9), // Also SA33
50         RM174RF(10);
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 Status implements ByteEnumWrapper {
65         NORMAL(0),
66         NORMAL_DELAYED(1),
67         ALARM(2),
68         ALARM_DELAYED(3),
69         MOTION(4),
70         NO_MOTION(5),
71         PANIC(6),
72         END_PANIC(7),
73         IR(8),
74         ARM_AWAY(9),
75         ARM_AWAY_DELAYED(10),
76         ARM_HOME(11),
77         ARM_HOME_DELAYED(12),
78         DISARM(13),
79         LIGHT_1_OFF(16),
80         LIGHT_1_ON(17),
81         LIGHT_2_OFF(18),
82         LIGHT_2_ON(19),
83         DARK_DETECTED(20),
84         LIGHT_DETECTED(21),
85         BATLOW(22),
86         PAIR_KD101(23),
87         NORMAL_TAMPER(128),
88         NORMAL_DELAYED_TAMPER(129),
89         ALARM_TAMPER(130),
90         ALARM_DELAYED_TAMPER(131),
91         MOTION_TAMPER(132),
92         NO_MOTION_TAMPER(133);
93
94         private final int status;
95
96         Status(int status) {
97             this.status = status;
98         }
99
100         @Override
101         public byte toByte() {
102             return (byte) status;
103         }
104     }
105
106     /* Added item for ContactTypes */
107     public enum Contact implements ByteEnumWrapper {
108         NORMAL(0),
109         NORMAL_DELAYED(1),
110         ALARM(2),
111         ALARM_DELAYED(3),
112         NORMAL_TAMPER(128),
113         NORMAL_DELAYED_TAMPER(129),
114         ALARM_TAMPER(130),
115         ALARM_DELAYED_TAMPER(131),
116
117         UNKNOWN(255);
118
119         private final int contact;
120
121         Contact(int contact) {
122             this.contact = contact;
123         }
124
125         @Override
126         public byte toByte() {
127             return (byte) contact;
128         }
129
130         public static Contact fromByte(int input) {
131             for (Contact status : Contact.values()) {
132                 if (status.contact == input) {
133                     return status;
134                 }
135             }
136
137             return Contact.UNKNOWN;
138         }
139     }
140
141     /* Added item for MotionTypes */
142     public enum Motion implements ByteEnumWrapper {
143         MOTION(4),
144         NO_MOTION(5),
145         MOTION_TAMPER(132),
146         NO_MOTION_TAMPER(133),
147
148         UNKNOWN(255);
149
150         private final int motion;
151
152         Motion(int motion) {
153             this.motion = motion;
154         }
155
156         @Override
157         public byte toByte() {
158             return (byte) motion;
159         }
160
161         public static Motion fromByte(int input) {
162             for (Motion motion : Motion.values()) {
163                 if (motion.motion == input) {
164                     return motion;
165                 }
166             }
167
168             return Motion.UNKNOWN;
169         }
170     }
171
172     public SubType subType;
173     public int sensorId;
174     public Status status;
175     public Contact contact;
176     public Motion motion;
177
178     public RFXComSecurity1Message() {
179         super(PacketType.SECURITY1);
180     }
181
182     public RFXComSecurity1Message(byte[] data) throws RFXComException {
183         encodeMessage(data);
184     }
185
186     @Override
187     public String toString() {
188         String str = "";
189
190         str += super.toString();
191         str += ", Sub type = " + subType;
192         str += ", Device Id = " + getDeviceId();
193         str += ", Status = " + status;
194         str += ", Battery level = " + batteryLevel;
195         str += ", Signal level = " + signalLevel;
196
197         return str;
198     }
199
200     @Override
201     public void encodeMessage(byte[] data) throws RFXComException {
202         super.encodeMessage(data);
203
204         subType = fromByte(SubType.class, super.subType);
205         sensorId = (data[4] & 0xFF) << 16 | (data[5] & 0xFF) << 8 | (data[6] & 0xFF);
206
207         status = fromByte(Status.class, data[7]);
208         batteryLevel = (byte) ((data[8] & 0xF0) >> 4);
209         signalLevel = (byte) (data[8] & 0x0F);
210
211         contact = Contact.fromByte(data[7]);
212         motion = Motion.fromByte(data[7]);
213     }
214
215     @Override
216     public byte[] decodeMessage() {
217         byte[] data = new byte[9];
218
219         data[0] = 0x08;
220         data[1] = RFXComBaseMessage.PacketType.SECURITY1.toByte();
221         data[2] = subType.toByte();
222         data[3] = seqNbr;
223         data[4] = (byte) ((sensorId >> 16) & 0xFF);
224         data[5] = (byte) ((sensorId >> 8) & 0xFF);
225         data[6] = (byte) (sensorId & 0xFF);
226         data[7] = status.toByte();
227         data[8] = (byte) (((batteryLevel & 0x0F) << 4) | (signalLevel & 0x0F));
228
229         return data;
230     }
231
232     @Override
233     public String getDeviceId() {
234         return String.valueOf(sensorId);
235     }
236
237     @Override
238     public State convertToState(String channelId, RFXComDeviceConfiguration config, DeviceState deviceState)
239             throws RFXComUnsupportedChannelException, RFXComInvalidStateException {
240         switch (channelId) {
241             case CHANNEL_MOTION:
242                 switch (status) {
243                     case MOTION:
244                         return OnOffType.ON;
245                     case NO_MOTION:
246                         return OnOffType.OFF;
247                     default:
248                         throw new RFXComUnsupportedChannelException("Can't convert " + status + " for " + channelId);
249                 }
250
251             case CHANNEL_CONTACT:
252                 switch (status) {
253                     case NORMAL:
254                         return OpenClosedType.CLOSED;
255                     case NORMAL_DELAYED:
256                         return OpenClosedType.CLOSED;
257                     case ALARM:
258                         return OpenClosedType.OPEN;
259                     case ALARM_DELAYED:
260                         return OpenClosedType.OPEN;
261                     default:
262                         throw new RFXComUnsupportedChannelException("Can't convert " + status + " for " + channelId);
263                 }
264
265             case CHANNEL_STATUS:
266                 return new StringType(status.toString());
267
268             default:
269                 return super.convertToState(channelId, config, deviceState);
270         }
271     }
272
273     @Override
274     public void setSubType(SubType subType) {
275         this.subType = subType;
276     }
277
278     @Override
279     public void setDeviceId(String deviceId) {
280         sensorId = Integer.parseInt(deviceId);
281     }
282
283     @Override
284     public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
285         switch (channelId) {
286             case CHANNEL_COMMAND:
287                 if ((type instanceof OnOffType) && (subType == SubType.X10_SECURITY_REMOTE)) {
288                     status = (type == OnOffType.ON ? Status.ARM_AWAY_DELAYED : Status.DISARM);
289
290                 } else {
291                     throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
292                 }
293                 break;
294
295             case CHANNEL_STATUS:
296                 if (type instanceof StringType) {
297                     status = Status.valueOf(type.toString());
298
299                 } else {
300                     throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
301                 }
302                 break;
303
304             default:
305                 throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
306         }
307     }
308
309     @Override
310     public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
311         return ByteEnumUtil.convertSubType(SubType.class, subType);
312     }
313 }