]> git.basschouten.com Git - openhab-addons.git/blob
66300987f09f806e9dd0c5291bff87512f210dcf
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.alarmdecoder.internal.protocol;
14
15 import java.util.List;
16
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.eclipse.jdt.annotation.Nullable;
19
20 /**
21  * The {@link KeypadMessage} class represents a parsed keypad (KPM) message.
22  * Based partly on code from the OH1 alarmdecoder binding by Bernd Pfrommer.
23  *
24  * @author Bob Adair - Initial contribution
25  */
26 @NonNullByDefault
27 public class KeypadMessage extends ADMessage {
28
29     // Example: [00110011000000003A--],010,[f70700000010808c18020000000000],"ARMED ***STAY** ZONE BYPASSED "
30
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;
46
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;
53
54     private final int upper;
55     private final int lower;
56
57     public KeypadMessage(String message) throws IllegalArgumentException {
58         super(message);
59         List<String> parts = splitMsg(message.replace("!KPM:", ""));
60
61         if (parts.size() != 4) {
62             throw new IllegalArgumentException("Invalid number of parts in keypad message");
63         }
64         if (parts.get(0).length() != 22) {
65             throw new IllegalArgumentException("Invalid field length in keypad message");
66         }
67
68         bitField = parts.get(0);
69         rawData = parts.get(2);
70         alphaMessage = parts.get(3).replaceAll("^\"|\"$", "");
71
72         try {
73             int numeric = 0;
74             try {
75                 numeric = Integer.parseInt(parts.get(1));
76             } catch (NumberFormatException e) {
77                 numeric = Integer.parseInt(parts.get(1), 16);
78             }
79             this.numericCode = numeric;
80
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;
85
86         } catch (NumberFormatException e) {
87             throw new IllegalArgumentException("keypad msg contains invalid number: " + e.getMessage(), e);
88         }
89     }
90
91     public int getZone() {
92         return numericCode;
93     }
94
95     /**
96      * Returns a string containing the keypad text
97      */
98     public String getText() {
99         return alphaMessage;
100     }
101
102     /**
103      * Returns the value of an individual bit in the status field
104      *
105      * @param bit status field bit to test
106      * @return true if bit is 1, false if bit is 0
107      */
108     public boolean getStatus(int bit) {
109         int v = (status >> bit) & 0x1;
110         return (v == 0) ? false : true;
111     }
112
113     /**
114      * Returns true if the READY status bit is set
115      */
116     public boolean panelClear() {
117         return ((status & (1 << BIT_READY)) != 0);
118     }
119
120     /**
121      * Returns a string containing the address mask of the message in hex
122      */
123     public String getAddressMask() {
124         return rawData.substring(3, 11);
125     }
126
127     /**
128      * Returns a long containing the address mask of the message
129      */
130     public long getLongAddressMask() {
131         return Long.parseLong(getAddressMask(), 16);
132     }
133
134     /**
135      * Compares two KeypadMessage objects
136      *
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
139      *         object.
140      */
141     @Override
142     public boolean equals(@Nullable Object obj) {
143         if (obj == null) {
144             return false;
145         } else if (this == obj) {
146             return true;
147         } else if (obj instanceof KeypadMessage) {
148             KeypadMessage other = (KeypadMessage) obj;
149             return this.message.equals(other.message);
150         } else {
151             return false;
152         }
153     }
154 }