Fix event log partition keypad decoding (#18192)

Other minor changes

Signed-off-by: Krzysztof Goworek <krzysztof.goworek@gmail.com>
Co-authored-by: Krzysztof Goworek <krzysztof.goworek@gmail.com>
pull/18324/head
druciak 2025-02-24 18:26:45 +01:00 committed by GitHub
parent cd40d051f7
commit dcac0a4d47
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 226 additions and 7 deletions

View File

@ -12,6 +12,7 @@
*/
package org.openhab.binding.satel.internal.command;
import java.time.Clock;
import java.time.LocalDateTime;
import org.eclipse.jdt.annotation.NonNullByDefault;
@ -29,6 +30,8 @@ public class ReadEventCommand extends SatelCommandBase {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final Clock clock;
public static final byte COMMAND_CODE = (byte) 0x8c;
/**
@ -47,7 +50,7 @@ public class ReadEventCommand extends SatelCommandBase {
USER_FUNCTIONS("user functions"),
SYSTEM_EVENTS("system events");
private String description;
private final String description;
EventClass(String description) {
this.description = description;
@ -64,7 +67,18 @@ public class ReadEventCommand extends SatelCommandBase {
* @param eventIndex index of event record to retrieve, -1 for the most recent one
*/
public ReadEventCommand(int eventIndex) {
this(eventIndex, Clock.systemDefaultZone());
}
/**
* Creates new command class instance to read a record under given index.
*
* @param eventIndex index of event record to retrieve, -1 for the most recent one
* @param clock clock for getting event timestamp
*/
public ReadEventCommand(int eventIndex, Clock clock) {
super(COMMAND_CODE, getIndexBytes(eventIndex));
this.clock = clock;
}
private static byte[] getIndexBytes(int index) {
@ -97,7 +111,7 @@ public class ReadEventCommand extends SatelCommandBase {
*/
public LocalDateTime getTimestamp() {
final byte[] payload = getResponse().getPayload();
final int currentYear = LocalDateTime.now().getYear();
final int currentYear = LocalDateTime.now(clock).getYear();
final int yearBase = currentYear / 4;
final int yearMarker = (payload[0] >> 6) & 0x03;
int year = 4 * yearBase + yearMarker;
@ -121,7 +135,7 @@ public class ReadEventCommand extends SatelCommandBase {
}
/**
* Returns number of partion the event is about.
* Returns number of partition the event is about.
*
* @return partition number
*/
@ -135,7 +149,7 @@ public class ReadEventCommand extends SatelCommandBase {
* @return partition keypad number
*/
public int getPartitionKeypad() {
return ((getResponse().getPayload()[4] >> 2) & 0x3f) + 1;
return ((getResponse().getPayload()[4] << 3) & 0x20) + ((getResponse().getPayload()[4] >> 3) & 0x1f) + 1;
}
/**
@ -188,13 +202,13 @@ public class ReadEventCommand extends SatelCommandBase {
}
/**
* Return index of previous event in the log. Can be used to iterate over tha event log.
* Return index of previous event in the log. Can be used to iterate over the event log.
*
* @return index of previous event record in the log
*/
public int getNextIndex() {
final byte[] payload = getResponse().getPayload();
return (payload[8] << 16) + ((payload[9] & 0xff) << 8) + (payload[10] & 0xff);
return ((payload[8] & 0xff) << 16) + ((payload[9] & 0xff) << 8) + (payload[10] & 0xff);
}
/**
@ -204,7 +218,7 @@ public class ReadEventCommand extends SatelCommandBase {
*/
public int getCurrentIndex() {
final byte[] payload = getResponse().getPayload();
return (payload[11] << 16) + ((payload[12] & 0xff) << 8) + (payload[13] & 0xff);
return ((payload[11] & 0xff) << 16) + ((payload[12] & 0xff) << 8) + (payload[13] & 0xff);
}
@Override

View File

@ -0,0 +1,205 @@
/*
* Copyright (c) 2010-2025 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.satel.internal.command;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.openhab.binding.satel.internal.command.ReadEventCommand.COMMAND_CODE;
import static org.openhab.binding.satel.internal.command.ReadEventCommand.EventClass;
import java.time.Clock;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openhab.binding.satel.internal.event.EventDispatcher;
import org.openhab.binding.satel.internal.protocol.SatelMessage;
/**
* @author Krzysztof Goworek - Initial contribution
*/
class ReadEventCommandTest {
private final EventDispatcher eventDispatcher = new EventDispatcher();
private final Clock clock = mock(Clock.class);
private final ReadEventCommand testSubject = new ReadEventCommand(-1, clock);
@BeforeEach
void setupClock() {
when(clock.getZone()).thenReturn(ZoneId.systemDefault());
when(clock.instant()).thenReturn(Instant.parse("2012-01-01T00:00:00Z"));
}
@Test
void handleResponseShouldFailIfResponseHasWrongSize() {
SatelMessage response = new SatelMessage(COMMAND_CODE, new byte[13]);
assertFalse(testSubject.handleResponse(eventDispatcher, response));
}
@Test
void handleResponseShouldSucceedIfResponseHasCorrectSize() {
SatelMessage response = new SatelMessage(COMMAND_CODE, new byte[14]);
assertTrue(testSubject.handleResponse(eventDispatcher, response));
}
@Test
void isEmptyShouldReturnTrueForEmptyResponse() {
SatelMessage response = new SatelMessage(COMMAND_CODE, new byte[14]);
testSubject.handleResponse(eventDispatcher, response);
assertTrue(testSubject.isEmpty());
}
@Test
void isEmptyShouldReturnFalseForNonEmptyResponse() {
SatelMessage response = createMessageWithBytes(0, 0x20);
testSubject.handleResponse(eventDispatcher, response);
assertFalse(testSubject.isEmpty());
}
@Test
void isPresentShouldReturnFalseForEmptyResponse() {
SatelMessage response = new SatelMessage(COMMAND_CODE, new byte[14]);
testSubject.handleResponse(eventDispatcher, response);
assertFalse(testSubject.isEventPresent());
}
@Test
void isPresentShouldReturnTrueForNonEmptyResponse() {
SatelMessage response = createMessageWithBytes(0, 0x10);
testSubject.handleResponse(eventDispatcher, response);
assertTrue(testSubject.isEventPresent());
}
@Test
void getTimestampShouldReturnCorrectDateAndTime1() {
SatelMessage response = createMessageWithBytes(0, 0xc0, 0x1f, 0x74, 0xc7);
testSubject.handleResponse(eventDispatcher, response);
assertEquals(LocalDateTime.of(2011, 7, 31, 20, 23), testSubject.getTimestamp());
}
@Test
void getTimestampShouldReturnCorrectDateAndTime2() {
SatelMessage response = createMessageWithBytes(0, 0x00, 0x07, 0xc0, 0xff);
testSubject.handleResponse(eventDispatcher, response);
assertEquals(LocalDateTime.of(2012, 12, 7, 4, 15), testSubject.getTimestamp());
}
@Test
void getEventClassShouldReturnEventClass() {
SatelMessage response = createMessageWithBytes(1, 0xa0);
testSubject.handleResponse(eventDispatcher, response);
assertEquals(EventClass.TROUBLES, testSubject.getEventClass());
}
@Test
void getPartitionShouldReturnPartitionNumber() {
SatelMessage response = createMessageWithBytes(4, 0xf8);
testSubject.handleResponse(eventDispatcher, response);
assertEquals(32, testSubject.getPartition());
}
@Test
void getPartitionKeypadShouldReturnPartitionKeypadNumber() {
SatelMessage response = createMessageWithBytes(4, 0x7c);
testSubject.handleResponse(eventDispatcher, response);
assertEquals(48, testSubject.getPartitionKeypad());
}
@Test
void getEventCodeShouldReturnEventCode() {
SatelMessage response = createMessageWithBytes(4, 0x3, 0xff);
testSubject.handleResponse(eventDispatcher, response);
assertEquals(0x3ff, testSubject.getEventCode());
}
@Test
void isRestoreShouldReturnFalseForEmptyResponse() {
SatelMessage response = new SatelMessage(COMMAND_CODE, new byte[14]);
testSubject.handleResponse(eventDispatcher, response);
assertFalse(testSubject.isRestore());
}
@Test
void isRestoreShouldReturnRestoreFlagSet() {
SatelMessage response = createMessageWithBytes(4, 0x4);
testSubject.handleResponse(eventDispatcher, response);
assertTrue(testSubject.isRestore());
}
@Test
void getSourceShouldReturnSourceNumber() {
SatelMessage response = createMessageWithBytes(6, 0xff);
testSubject.handleResponse(eventDispatcher, response);
assertEquals(255, testSubject.getSource());
}
@Test
void getObjectShouldReturnObjectNumber() {
SatelMessage response = createMessageWithBytes(7, 0xe0);
testSubject.handleResponse(eventDispatcher, response);
assertEquals(7, testSubject.getObject());
}
@Test
void getUserControlNumberShouldReturnUserControlNumber() {
SatelMessage response = createMessageWithBytes(7, 0x1f);
testSubject.handleResponse(eventDispatcher, response);
assertEquals(31, testSubject.getUserControlNumber());
}
@Test
void getNextIndexShouldReturnNextIndex() {
SatelMessage response = createMessageWithBytes(8, 0xff, 0xff, 0xff);
testSubject.handleResponse(eventDispatcher, response);
assertEquals(0xffffff, testSubject.getNextIndex());
}
@Test
void getCurrentIndexShouldReturnCurrentIndex() {
SatelMessage response = createMessageWithBytes(11, 0xff, 0xff, 0xff);
testSubject.handleResponse(eventDispatcher, response);
assertEquals(0xffffff, testSubject.getCurrentIndex());
}
private SatelMessage createMessageWithBytes(int offset, int... data) {
byte[] payload = new byte[14];
for (int i = 0; i < data.length; ++i) {
payload[offset + i] = (byte) data[i];
}
return new SatelMessage(COMMAND_CODE, payload);
}
}