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.alarmdecoder.internal.protocol;
15 import java.util.List;
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.eclipse.jdt.annotation.Nullable;
21 * The {@link KeypadMessage} class represents a parsed keypad (KPM) message.
22 * Based partly on code from the OH1 alarmdecoder binding by Bernd Pfrommer.
24 * @author Bob Adair - Initial contribution
27 public class KeypadMessage extends ADMessage {
29 // Example: [00110011000000003A--],010,[f70700000010808c18020000000000],"ARMED ***STAY** ZONE BYPASSED "
31 public static final int BIT_READY = 17;
32 public static final int BIT_ARMEDAWAY = 16;
33 public static final int BIT_ARMEDHOME = 15;
34 public static final int BIT_BACKLIGHT = 14;
35 public static final int BIT_PRORGAM = 13;
36 public static final int BIT_BYPASSED = 9;
37 public static final int BIT_ACPOWER = 8;
38 public static final int BIT_CHIME = 7;
39 public static final int BIT_ALARMOCCURRED = 6;
40 public static final int BIT_ALARM = 5;
41 public static final int BIT_LOWBAT = 4;
42 public static final int BIT_DELAYOFF = 3;
43 public static final int BIT_FIRE = 2;
44 public static final int BIT_SYSFAULT = 1;
45 public static final int BIT_PERIMETER = 0;
47 public final String bitField;
48 public final int numericCode;
49 public final String rawData;
50 public final String alphaMessage;
51 public final int nbeeps;
52 public final int status;
54 private final int upper;
55 private final int lower;
57 public KeypadMessage(String message) throws IllegalArgumentException {
59 List<String> parts = splitMsg(message.replace("!KPM:", ""));
61 if (parts.size() != 4) {
62 throw new IllegalArgumentException("Invalid number of parts in keypad message");
64 if (parts.get(0).length() != 22) {
65 throw new IllegalArgumentException("Invalid field length in keypad message");
68 bitField = parts.get(0);
69 rawData = parts.get(2);
70 alphaMessage = parts.get(3).replaceAll("^\"|\"$", "");
75 numeric = Integer.parseInt(parts.get(1));
76 } catch (NumberFormatException e) {
77 numeric = Integer.parseInt(parts.get(1), 16);
79 this.numericCode = numeric;
81 this.upper = Integer.parseInt(parts.get(0).substring(1, 6), 2);
82 this.nbeeps = Integer.parseInt(parts.get(0).substring(6, 7));
83 this.lower = Integer.parseInt(parts.get(0).substring(7, 17), 2);
84 this.status = ((upper & 0x1F) << 13) | ((nbeeps & 0x3) << 10) | lower;
86 } catch (NumberFormatException e) {
87 throw new IllegalArgumentException("keypad msg contains invalid number: " + e.getMessage(), e);
91 public int getZone() {
96 * Returns a string containing the keypad text
98 public String getText() {
103 * Returns the value of an individual bit in the status field
105 * @param bit status field bit to test
106 * @return true if bit is 1, false if bit is 0
108 public boolean getStatus(int bit) {
109 int v = (status >> bit) & 0x1;
110 return (v == 0) ? false : true;
114 * Returns true if the READY status bit is set
116 public boolean panelClear() {
117 return ((status & (1 << BIT_READY)) != 0);
121 * Returns a string containing the address mask of the message in hex
123 public String getAddressMask() {
124 return rawData.substring(3, 11);
128 * Returns a long containing the address mask of the message
130 public long getLongAddressMask() {
131 return Long.parseLong(getAddressMask(), 16);
135 * Compares two KeypadMessage objects
137 * @param obj KeypadMessage to compare against
138 * @return true if messages are equal, false if obj is null, messages are not equal, or obj is not a KeypadMessage
142 public boolean equals(@Nullable Object obj) {
145 } else if (this == obj) {
147 } else if (obj instanceof KeypadMessage) {
148 KeypadMessage other = (KeypadMessage) obj;
149 return this.message.equals(other.message);