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.satel.internal.command;
15 import java.time.LocalDateTime;
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.openhab.binding.satel.internal.protocol.SatelMessage;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
23 * Command class for command that reads one record from the event log.
25 * @author Krzysztof Goworek - Initial contribution
28 public class ReadEventCommand extends SatelCommandBase {
30 private final Logger logger = LoggerFactory.getLogger(this.getClass());
32 public static final byte COMMAND_CODE = (byte) 0x8c;
35 * Event class: zone alarms, partition alarms, arming, troubles, etc.
37 * @author Krzysztof Goworek - Initial contribution
40 public enum EventClass {
41 ZONE_ALARMS("zone and tamper alarms"),
42 PARTITION_ALARMS("partition and expander alarms"),
43 ARMING("arming, disarming, alarm clearing"),
44 BYPASSES("zone bypasses and unbypasses"),
45 ACCESS_CONTROL("access control"),
47 USER_FUNCTIONS("user functions"),
48 SYSTEM_EVENTS("system events");
50 private String description;
52 EventClass(String description) {
53 this.description = description;
56 public String getDescription() {
62 * Creates new command class instance to read a record under given index.
64 * @param eventIndex index of event record to retrieve, -1 for the most recent one
66 public ReadEventCommand(int eventIndex) {
67 super(COMMAND_CODE, getIndexBytes(eventIndex));
70 private static byte[] getIndexBytes(int index) {
71 return new byte[] { (byte) ((index >> 16) & 0xff), (byte) ((index >> 8) & 0xff), (byte) (index & 0xff) };
75 * Checks whether response data contains valid event record.
77 * @return <code>true</code> if returned record is empty (likely the last
80 public boolean isEmpty() {
81 return (getResponse().getPayload()[0] & 0x20) == 0;
85 * Checks whether event record is present in the response data.
87 * @return <code>true</code> if event data is present in the response
89 public boolean isEventPresent() {
90 return (getResponse().getPayload()[0] & 0x10) != 0;
94 * Returns date and time of the event.
96 * @return date and time of the event
98 public LocalDateTime getTimestamp() {
99 final byte[] payload = getResponse().getPayload();
100 final int currentYear = LocalDateTime.now().getYear();
101 final int yearBase = currentYear / 4;
102 final int yearMarker = (payload[0] >> 6) & 0x03;
103 int year = 4 * yearBase + yearMarker;
104 final int minutes = ((payload[2] & 0x0f) << 8) + (payload[3] & 0xff);
106 if (year > currentYear) {
109 LocalDateTime result = LocalDateTime.of(year, (payload[2] >> 4) & 0x0f, payload[1] & 0x1f, minutes / 60,
115 * Returns class of the event.
117 * @return event class of the event
120 public EventClass getEventClass() {
121 final int eventClassIdx = (getResponse().getPayload()[1] >> 5) & 0x07;
122 return EventClass.values()[eventClassIdx];
126 * Returns number of partion the event is about.
128 * @return partition number
130 public int getPartition() {
131 return ((getResponse().getPayload()[4] >> 3) & 0x1f) + 1;
135 * Returns number of partition keypad related to the event.
137 * @return partition keypad number
139 public int getPartitionKeypad() {
140 return ((getResponse().getPayload()[4] >> 2) & 0x3f) + 1;
144 * Returns event code the describes the event. It can be used to retrieve description text for this event.
147 * @see ReadEventDescCommand
149 public int getEventCode() {
150 final byte[] payload = getResponse().getPayload();
151 return ((payload[4] & 0x03) << 8) + (payload[5] & 0xff);
155 * Returns state restoration flag.
157 * @return <code>true</code> if this is restoration of some state (i.e.
158 * arming and disarming have the same code but different restoration
161 public boolean isRestore() {
162 return (getResponse().getPayload()[4] & 0x04) != 0;
166 * Return source of the event.
168 * @return event source (zone number, user number, etc depending on event)
170 public int getSource() {
171 return getResponse().getPayload()[6] & 0xff;
175 * Returns object number for the event.
177 * @return object number (0..7)
179 public int getObject() {
180 return (getResponse().getPayload()[7] >> 5) & 0x07;
184 * Returns user control number for the event.
186 * @return user control number
188 public int getUserControlNumber() {
189 return getResponse().getPayload()[7] & 0x1f;
193 * Return index of previous event in the log. Can be used to iterate over tha event log.
195 * @return index of previous event record in the log
197 public int getNextIndex() {
198 final byte[] payload = getResponse().getPayload();
199 return (payload[8] << 16) + ((payload[9] & 0xff) << 8) + (payload[10] & 0xff);
203 * Returns current event index.
205 * @return index of current record echoed by communication module
207 public int getCurrentIndex() {
208 final byte[] payload = getResponse().getPayload();
209 return (payload[11] << 16) + ((payload[12] & 0xff) << 8) + (payload[13] & 0xff);
213 protected boolean isResponseValid(SatelMessage response) {
215 if (response.getPayload().length != 14) {
216 logger.debug("Invalid payload length: {}", response.getPayload().length);