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.echonetlite.internal.protocol;
15 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
16 import static org.junit.jupiter.api.Assertions.assertEquals;
17 import static org.openhab.binding.echonetlite.internal.LangUtil.b;
19 import java.nio.ByteBuffer;
20 import java.nio.ByteOrder;
21 import java.util.concurrent.TimeUnit;
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.junit.jupiter.api.Test;
25 import org.openhab.binding.echonetlite.internal.StateCodec;
26 import org.openhab.binding.echonetlite.internal.StateCodec.HexStringCodec;
27 import org.openhab.binding.echonetlite.internal.StateCodec.OperatingTimeDecode;
28 import org.openhab.binding.echonetlite.internal.StateCodec.Option;
29 import org.openhab.binding.echonetlite.internal.StateCodec.OptionCodec;
30 import org.openhab.binding.echonetlite.internal.StateCodec.StandardVersionInformationCodec;
31 import org.openhab.binding.echonetlite.internal.StateDecode;
32 import org.openhab.core.library.types.DecimalType;
33 import org.openhab.core.library.types.OnOffType;
34 import org.openhab.core.library.types.QuantityType;
35 import org.openhab.core.library.types.StringType;
36 import org.openhab.core.library.unit.SIUnits;
37 import org.openhab.core.types.State;
40 * @author Michael Barker - Initial contribution
43 class StateCodecTest {
44 private void assertEncodeDecode(StateCodec stateCodec, State state, byte[] expectedOutput) {
45 final ByteBuffer buffer = ByteBuffer.allocate(1024);
46 stateCodec.encodeState(state, buffer);
49 final byte[] encoded = new byte[buffer.remaining()];
51 assertArrayEquals(expectedOutput, encoded);
55 assertEquals(state, stateCodec.decodeState(buffer));
58 private void assertDecode(StateDecode stateDecode, State expectedState, byte[] data) {
59 assertEquals(expectedState, stateDecode.decodeState(ByteBuffer.wrap(data)));
63 void shouldEncodeOnOff() {
66 final StateCodec.OnOffCodec onOffCodec = new StateCodec.OnOffCodec(on, off);
68 assertEncodeDecode(onOffCodec, OnOffType.ON, new byte[] { b(on) });
69 assertEncodeDecode(onOffCodec, OnOffType.OFF, new byte[] { b(off) });
73 void shouldDecodeStandardVersionInformation() {
74 assertDecode(StandardVersionInformationCodec.INSTANCE, StringType.EMPTY, new byte[0]);
75 assertDecode(StandardVersionInformationCodec.INSTANCE, StringType.EMPTY, new byte[1]);
76 assertDecode(StandardVersionInformationCodec.INSTANCE, StringType.EMPTY, new byte[2]);
77 assertDecode(StandardVersionInformationCodec.INSTANCE, StringType.EMPTY, new byte[3]);
78 assertDecode(StandardVersionInformationCodec.INSTANCE, StringType.EMPTY, new byte[5]);
79 assertDecode(StandardVersionInformationCodec.INSTANCE, new StringType("A"), new byte[] { 0, 0, 'A', 0 });
80 assertDecode(StandardVersionInformationCodec.INSTANCE, new StringType("Z"), new byte[] { 0, 0, 'Z', 0 });
84 void shouldDecodeHexString() {
85 assertDecode(HexStringCodec.INSTANCE, new StringType("000102030467"), new byte[] { 0, 1, 2, 3, 4, b(0x67) });
89 void shouldDecodeCumulativeOperatingTime() {
90 final ByteBuffer buffer = ByteBuffer.wrap(new byte[5]);
91 buffer.order(ByteOrder.BIG_ENDIAN);
93 final int valueInSeconds = 484260;
94 final long valueInMinutes = TimeUnit.SECONDS.toMinutes(valueInSeconds);
96 buffer.putInt((int) valueInMinutes);
99 buffer.order(ByteOrder.LITTLE_ENDIAN);
100 assertEquals(valueInSeconds, ((QuantityType<?>) OperatingTimeDecode.INSTANCE.decodeState(buffer)).intValue());
103 buffer.order(ByteOrder.BIG_ENDIAN);
104 assertEquals(valueInSeconds, ((QuantityType<?>) OperatingTimeDecode.INSTANCE.decodeState(buffer)).intValue());
108 void shouldEncodeDecodeOption() {
109 final OptionCodec optionCodec = new OptionCodec(new Option("ABC", 123), new Option("DEF", 101));
110 assertEncodeDecode(optionCodec, new StringType("ABC"), new byte[] { 123 });
111 assertEncodeDecode(optionCodec, new StringType("DEF"), new byte[] { 101 });
115 void shouldEncodeAndDecode8Bit() {
116 assertEncodeDecode(StateCodec.Decimal8bitCodec.INSTANCE, new DecimalType(123), new byte[] { 123 });
117 assertEncodeDecode(StateCodec.Decimal8bitCodec.INSTANCE, new DecimalType(1), new byte[] { 1 });
118 assertEncodeDecode(StateCodec.Decimal8bitCodec.INSTANCE, new DecimalType(-1), new byte[] { b(255) });
122 void shouldEncodeAndDecodeTemperature() {
123 assertEncodeDecode(StateCodec.Temperature8bitCodec.INSTANCE, new QuantityType<>(123, SIUnits.CELSIUS),
125 assertEncodeDecode(StateCodec.Temperature8bitCodec.INSTANCE, new QuantityType<>(1, SIUnits.CELSIUS),
127 assertEncodeDecode(StateCodec.Temperature8bitCodec.INSTANCE, new QuantityType<>(-1, SIUnits.CELSIUS),
128 new byte[] { b(255) });