diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadEventCommand.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadEventCommand.java index 3ccfe9bfc30..d03dc4b0c65 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadEventCommand.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadEventCommand.java @@ -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 diff --git a/bundles/org.openhab.binding.satel/src/test/java/org/openhab/binding/satel/internal/command/ReadEventCommandTest.java b/bundles/org.openhab.binding.satel/src/test/java/org/openhab/binding/satel/internal/command/ReadEventCommandTest.java new file mode 100644 index 00000000000..f3847972c60 --- /dev/null +++ b/bundles/org.openhab.binding.satel/src/test/java/org/openhab/binding/satel/internal/command/ReadEventCommandTest.java @@ -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); + } +}