2 * Copyright (c) 2010-2021 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.rfxcom.internal.messages;
15 import static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
16 import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
18 import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
19 import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
20 import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
21 import org.openhab.binding.rfxcom.internal.handler.DeviceState;
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.State;
26 import org.openhab.core.types.Type;
29 * RFXCOM data class for Security1 message.
30 * (i.e. X10 Security, Visonic PowerCode, Meiantech, etc.)
32 * @author David Kalff - Initial contribution
33 * @author Pauli Anttila
35 public class RFXComSecurity1Message extends RFXComBatteryDeviceMessage<RFXComSecurity1Message.SubType> {
37 public enum SubType implements ByteEnumWrapper {
39 X10_SECURITY_MOTION(1),
40 X10_SECURITY_REMOTE(2),
42 VISONIC_POWERCODE_SENSOR_PRIMARY_CONTACT(4),
43 VISONIC_POWERCODE_MOTION(5),
44 VISONIC_CODESECURE(6),
45 VISONIC_POWERCODE_SENSOR_AUX_CONTACT(7),
50 private final int subType;
52 SubType(int subType) {
53 this.subType = subType;
57 public byte toByte() {
58 return (byte) subType;
62 public enum Status implements ByteEnumWrapper {
86 NORMAL_DELAYED_TAMPER(129),
88 ALARM_DELAYED_TAMPER(131),
90 NO_MOTION_TAMPER(133);
92 private final int status;
99 public byte toByte() {
100 return (byte) status;
104 /* Added item for ContactTypes */
105 public enum Contact implements ByteEnumWrapper {
111 NORMAL_DELAYED_TAMPER(129),
113 ALARM_DELAYED_TAMPER(131),
117 private final int contact;
119 Contact(int contact) {
120 this.contact = contact;
124 public byte toByte() {
125 return (byte) contact;
128 public static Contact fromByte(int input) {
129 for (Contact status : Contact.values()) {
130 if (status.contact == input) {
135 return Contact.UNKNOWN;
139 /* Added item for MotionTypes */
140 public enum Motion implements ByteEnumWrapper {
144 NO_MOTION_TAMPER(133),
148 private final int motion;
151 this.motion = motion;
155 public byte toByte() {
156 return (byte) motion;
159 public static Motion fromByte(int input) {
160 for (Motion motion : Motion.values()) {
161 if (motion.motion == input) {
166 return Motion.UNKNOWN;
170 public SubType subType;
172 public Status status;
173 public Contact contact;
174 public Motion motion;
176 public RFXComSecurity1Message() {
177 super(PacketType.SECURITY1);
180 public RFXComSecurity1Message(byte[] data) throws RFXComException {
185 public String toString() {
188 str += super.toString();
189 str += ", Sub type = " + subType;
190 str += ", Device Id = " + getDeviceId();
191 str += ", Status = " + status;
192 str += ", Battery level = " + batteryLevel;
193 str += ", Signal level = " + signalLevel;
199 public void encodeMessage(byte[] data) throws RFXComException {
200 super.encodeMessage(data);
202 subType = fromByte(SubType.class, super.subType);
203 sensorId = (data[4] & 0xFF) << 16 | (data[5] & 0xFF) << 8 | (data[6] & 0xFF);
205 status = fromByte(Status.class, data[7]);
206 batteryLevel = (byte) ((data[8] & 0xF0) >> 4);
207 signalLevel = (byte) (data[8] & 0x0F);
209 contact = Contact.fromByte(data[7]);
210 motion = Motion.fromByte(data[7]);
214 public byte[] decodeMessage() {
215 byte[] data = new byte[9];
218 data[1] = RFXComBaseMessage.PacketType.SECURITY1.toByte();
219 data[2] = subType.toByte();
221 data[4] = (byte) ((sensorId >> 16) & 0xFF);
222 data[5] = (byte) ((sensorId >> 8) & 0xFF);
223 data[6] = (byte) (sensorId & 0xFF);
224 data[7] = status.toByte();
225 data[8] = (byte) (((batteryLevel & 0x0F) << 4) | (signalLevel & 0x0F));
231 public String getDeviceId() {
232 return String.valueOf(sensorId);
236 public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
243 return OnOffType.OFF;
245 throw new RFXComUnsupportedChannelException("Can't convert " + status + " for " + channelId);
248 case CHANNEL_CONTACT:
251 return OpenClosedType.CLOSED;
253 return OpenClosedType.CLOSED;
255 return OpenClosedType.OPEN;
257 return OpenClosedType.OPEN;
259 throw new RFXComUnsupportedChannelException("Can't convert " + status + " for " + channelId);
263 return new StringType(status.toString());
266 return super.convertToState(channelId, deviceState);
271 public void setSubType(SubType subType) {
272 this.subType = subType;
276 public void setDeviceId(String deviceId) {
277 sensorId = Integer.parseInt(deviceId);
281 public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
283 case CHANNEL_COMMAND:
284 if ((type instanceof OnOffType) && (subType == SubType.X10_SECURITY_REMOTE)) {
285 status = (type == OnOffType.ON ? Status.ARM_AWAY_DELAYED : Status.DISARM);
288 throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
293 if (type instanceof StringType) {
294 status = Status.valueOf(type.toString());
297 throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
302 throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
307 public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
308 return ByteEnumUtil.convertSubType(SubType.class, subType);