2 * Copyright (c) 2010-2023 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 java.util.Arrays;
20 import org.openhab.binding.rfxcom.internal.config.RFXComDeviceConfiguration;
21 import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
22 import org.openhab.binding.rfxcom.internal.exceptions.RFXComInvalidStateException;
23 import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
24 import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
25 import org.openhab.binding.rfxcom.internal.handler.DeviceState;
26 import org.openhab.core.library.types.OpenClosedType;
27 import org.openhab.core.types.State;
28 import org.openhab.core.types.Type;
31 * RFXCOM data class for Security2 message.
34 * @author Mike Jagdis - Initial contribution
36 public class RFXComSecurity2Message extends RFXComBatteryDeviceMessage<RFXComSecurity2Message.SubType> {
38 public enum SubType implements ByteEnumWrapper {
39 RAW_CLASSIC_KEELOQ(0),
40 ROLLING_CODE_PACKET(1),
42 RAW_CLASS_KEELOQ_WITH_REPEATS(3);
44 private final int subType;
46 SubType(int subType) {
47 this.subType = subType;
51 public byte toByte() {
52 return (byte) subType;
56 public SubType subType;
58 public int buttonStatus;
60 private static final int BUTTON_0_BIT = 0x02;
61 private static final int BUTTON_1_BIT = 0x04;
62 private static final int BUTTON_2_BIT = 0x08;
63 private static final int BUTTON_3_BIT = 0x01;
65 public RFXComSecurity2Message() {
66 super(PacketType.SECURITY2);
69 public RFXComSecurity2Message(byte[] data) throws RFXComException {
74 public String toString() {
75 return super.toString() + ", Sub type = " + subType + ", Device Id = " + getDeviceId() + ", Button status = "
76 + buttonStatus + ", Battery level = " + batteryLevel + ", Signal level = " + signalLevel;
80 public void encodeMessage(byte[] data) throws RFXComException {
81 super.encodeMessage(data);
83 subType = fromByte(SubType.class, super.subType);
85 sensorId = (data[11] & 0x0F) << 24 | (data[10] & 0xFF) << 16 | (data[9] & 0xFF) << 8 | (data[8] & 0xFF);
87 buttonStatus = (data[11] & 0xF0) >> 4;
89 batteryLevel = (byte) ((data[28] & 0xF0) >> 4);
90 signalLevel = (byte) (data[28] & 0x0F);
94 public byte[] decodeMessage() {
95 byte[] data = new byte[29];
97 Arrays.fill(data, (byte) 0);
100 data[1] = RFXComBaseMessage.PacketType.SECURITY2.toByte();
101 data[2] = subType.toByte();
104 data[8] = (byte) (sensorId & 0xFF);
105 data[9] = (byte) ((sensorId >> 8) & 0xFF);
106 data[10] = (byte) ((sensorId >> 16) & 0xFF);
107 data[11] = (byte) ((buttonStatus & 0x0f) << 4 | (sensorId >> 24) & 0x0F);
109 data[28] = (byte) (((batteryLevel & 0x0F) << 4) | (signalLevel & 0x0F));
115 public String getDeviceId() {
116 return String.valueOf(sensorId);
120 public State convertToState(String channelId, RFXComDeviceConfiguration config, DeviceState deviceState)
121 throws RFXComUnsupportedChannelException, RFXComInvalidStateException {
123 case CHANNEL_CONTACT:
124 return ((buttonStatus & BUTTON_0_BIT) == 0) ? OpenClosedType.CLOSED : OpenClosedType.OPEN;
126 case CHANNEL_CONTACT_1:
127 return ((buttonStatus & BUTTON_1_BIT) == 0) ? OpenClosedType.CLOSED : OpenClosedType.OPEN;
129 case CHANNEL_CONTACT_2:
130 return ((buttonStatus & BUTTON_2_BIT) == 0) ? OpenClosedType.CLOSED : OpenClosedType.OPEN;
132 case CHANNEL_CONTACT_3:
133 return ((buttonStatus & BUTTON_3_BIT) == 0) ? OpenClosedType.CLOSED : OpenClosedType.OPEN;
136 return super.convertToState(channelId, config, deviceState);
141 public void setSubType(SubType subType) {
142 this.subType = subType;
146 public void setDeviceId(String deviceId) {
147 sensorId = Integer.parseInt(deviceId);
151 public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
153 case CHANNEL_CONTACT:
154 if (type instanceof OpenClosedType) {
155 if (type == OpenClosedType.CLOSED) {
156 buttonStatus |= BUTTON_0_BIT;
158 buttonStatus &= ~BUTTON_0_BIT;
162 throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
166 case CHANNEL_CONTACT_1:
167 if (type instanceof OpenClosedType) {
168 if (type == OpenClosedType.CLOSED) {
169 buttonStatus |= BUTTON_1_BIT;
171 buttonStatus &= ~BUTTON_1_BIT;
175 throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
179 case CHANNEL_CONTACT_2:
180 if (type instanceof OpenClosedType) {
181 if (type == OpenClosedType.CLOSED) {
182 buttonStatus |= BUTTON_2_BIT;
184 buttonStatus &= ~BUTTON_2_BIT;
188 throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
192 case CHANNEL_CONTACT_3:
193 if (type instanceof OpenClosedType) {
194 if (type == OpenClosedType.CLOSED) {
195 buttonStatus |= BUTTON_3_BIT;
197 buttonStatus &= ~BUTTON_3_BIT;
201 throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
206 throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
211 public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
212 return ByteEnumUtil.convertSubType(SubType.class, subType);