]> git.basschouten.com Git - openhab-addons.git/blob
3dbb357d62f9dd8b0bd86155607086e3397c604e
[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 import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
17
18 import java.util.Arrays;
19
20 import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
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.OpenClosedType;
25 import org.openhab.core.types.State;
26 import org.openhab.core.types.Type;
27
28 /**
29  * RFXCOM data class for Security2 message.
30  * (i.e. KEELOQ.)
31  *
32  * @author Mike Jagdis - Initial contribution
33  */
34 public class RFXComSecurity2Message extends RFXComBatteryDeviceMessage<RFXComSecurity2Message.SubType> {
35
36     public enum SubType implements ByteEnumWrapper {
37         RAW_CLASSIC_KEELOQ(0),
38         ROLLING_CODE_PACKET(1),
39         RAW_AES_KEELOQ(2),
40         RAW_CLASS_KEELOQ_WITH_REPEATS(3);
41
42         private final int subType;
43
44         SubType(int subType) {
45             this.subType = subType;
46         }
47
48         @Override
49         public byte toByte() {
50             return (byte) subType;
51         }
52     }
53
54     public SubType subType;
55     public int sensorId;
56     public int buttonStatus;
57
58     private static final int BUTTON_0_BIT = 0x02;
59     private static final int BUTTON_1_BIT = 0x04;
60     private static final int BUTTON_2_BIT = 0x08;
61     private static final int BUTTON_3_BIT = 0x01;
62
63     public RFXComSecurity2Message() {
64         super(PacketType.SECURITY2);
65     }
66
67     public RFXComSecurity2Message(byte[] data) throws RFXComException {
68         encodeMessage(data);
69     }
70
71     @Override
72     public String toString() {
73         return super.toString() + ", Sub type = " + subType + ", Device Id = " + getDeviceId() + ", Button status = "
74                 + buttonStatus + ", Battery level = " + batteryLevel + ", Signal level = " + signalLevel;
75     }
76
77     @Override
78     public void encodeMessage(byte[] data) throws RFXComException {
79         super.encodeMessage(data);
80
81         subType = fromByte(SubType.class, super.subType);
82
83         sensorId = (data[11] & 0x0F) << 24 | (data[10] & 0xFF) << 16 | (data[9] & 0xFF) << 8 | (data[8] & 0xFF);
84
85         buttonStatus = (data[11] & 0xF0) >> 4;
86
87         batteryLevel = (byte) ((data[28] & 0xF0) >> 4);
88         signalLevel = (byte) (data[28] & 0x0F);
89     }
90
91     @Override
92     public byte[] decodeMessage() {
93         byte[] data = new byte[29];
94
95         Arrays.fill(data, (byte) 0);
96
97         data[0] = 0x1C;
98         data[1] = RFXComBaseMessage.PacketType.SECURITY2.toByte();
99         data[2] = subType.toByte();
100         data[3] = seqNbr;
101
102         data[8] = (byte) (sensorId & 0xFF);
103         data[9] = (byte) ((sensorId >> 8) & 0xFF);
104         data[10] = (byte) ((sensorId >> 16) & 0xFF);
105         data[11] = (byte) ((buttonStatus & 0x0f) << 4 | (sensorId >> 24) & 0x0F);
106
107         data[28] = (byte) (((batteryLevel & 0x0F) << 4) | (signalLevel & 0x0F));
108
109         return data;
110     }
111
112     @Override
113     public String getDeviceId() {
114         return String.valueOf(sensorId);
115     }
116
117     @Override
118     public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
119         switch (channelId) {
120             case CHANNEL_CONTACT:
121                 return ((buttonStatus & BUTTON_0_BIT) == 0) ? OpenClosedType.CLOSED : OpenClosedType.OPEN;
122
123             case CHANNEL_CONTACT_1:
124                 return ((buttonStatus & BUTTON_1_BIT) == 0) ? OpenClosedType.CLOSED : OpenClosedType.OPEN;
125
126             case CHANNEL_CONTACT_2:
127                 return ((buttonStatus & BUTTON_2_BIT) == 0) ? OpenClosedType.CLOSED : OpenClosedType.OPEN;
128
129             case CHANNEL_CONTACT_3:
130                 return ((buttonStatus & BUTTON_3_BIT) == 0) ? OpenClosedType.CLOSED : OpenClosedType.OPEN;
131
132             default:
133                 return super.convertToState(channelId, deviceState);
134         }
135     }
136
137     @Override
138     public void setSubType(SubType subType) {
139         this.subType = subType;
140     }
141
142     @Override
143     public void setDeviceId(String deviceId) {
144         sensorId = Integer.parseInt(deviceId);
145     }
146
147     @Override
148     public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
149         switch (channelId) {
150             case CHANNEL_CONTACT:
151                 if (type instanceof OpenClosedType) {
152                     if (type == OpenClosedType.CLOSED) {
153                         buttonStatus |= BUTTON_0_BIT;
154                     } else {
155                         buttonStatus &= ~BUTTON_0_BIT;
156                     }
157
158                 } else {
159                     throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
160                 }
161                 break;
162
163             case CHANNEL_CONTACT_1:
164                 if (type instanceof OpenClosedType) {
165                     if (type == OpenClosedType.CLOSED) {
166                         buttonStatus |= BUTTON_1_BIT;
167                     } else {
168                         buttonStatus &= ~BUTTON_1_BIT;
169                     }
170
171                 } else {
172                     throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
173                 }
174                 break;
175
176             case CHANNEL_CONTACT_2:
177                 if (type instanceof OpenClosedType) {
178                     if (type == OpenClosedType.CLOSED) {
179                         buttonStatus |= BUTTON_2_BIT;
180                     } else {
181                         buttonStatus &= ~BUTTON_2_BIT;
182                     }
183
184                 } else {
185                     throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
186                 }
187                 break;
188
189             case CHANNEL_CONTACT_3:
190                 if (type instanceof OpenClosedType) {
191                     if (type == OpenClosedType.CLOSED) {
192                         buttonStatus |= BUTTON_3_BIT;
193                     } else {
194                         buttonStatus &= ~BUTTON_3_BIT;
195                     }
196
197                 } else {
198                     throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
199                 }
200                 break;
201
202             default:
203                 throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
204         }
205     }
206
207     @Override
208     public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
209         return ByteEnumUtil.convertSubType(SubType.class, subType);
210     }
211 }