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.nibeheatpump.internal.message;
15 import static org.junit.jupiter.api.Assertions.*;
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.List;
20 import java.util.concurrent.TimeUnit;
22 import org.junit.jupiter.api.BeforeEach;
23 import org.junit.jupiter.api.Test;
24 import org.junit.jupiter.api.Timeout;
25 import org.openhab.binding.nibeheatpump.internal.protocol.NibeHeatPumpProtocolContext;
26 import org.openhab.binding.nibeheatpump.internal.protocol.NibeHeatPumpProtocolDefaultContext;
27 import org.openhab.core.util.HexUtils;
30 * @author Pauli Anttila - Initial contribution
32 public class NibeHeatPumpProtocolTest {
34 int ackRequestCount = 0;
35 int nakRequestCount = 0;
36 int sendWriteMsgCount = 0;
37 int sendReadMsgCount = 0;
38 List<byte[]> receivedMsgs = null;
40 final NibeHeatPumpProtocolContext mockupContext = new NibeHeatPumpProtocolDefaultContext() {
42 public void sendAck() {
47 public void sendNak() {
52 public void msgReceived(byte[] data) {
53 receivedMsgs.add(Arrays.copyOf(data, data.length));
57 public void sendWriteMsg() {
62 public void sendReadMsg() {
68 public void Before() {
71 sendWriteMsgCount = 0;
73 receivedMsgs = new ArrayList<>();
74 mockupContext.buffer().clear();
75 mockupContext.msg().clear();
79 @Timeout(value = 1, unit = TimeUnit.SECONDS)
82 final String strTestData =
83 // RMU40 message, acknowledge should be send
84 "5C001962189600E1010200000000800000000000020914340001000005B8"
85 // RMU40 message, CRC failure, negative acknowledge should be send
86 + "5C001962189600E1010200000000800000000000020914340001000005B9"
87 // MODBUS40 write request
91 // MODBUS40 read request
95 // MODBUS40 data read out, acknowledge should be send
96 + "5C00206850449C9600489C88014C9C2D014E9CCF004D9CE0014F9C3200509C0400519C8201529C6B02569C3E00C9AF000001A8F600FDA77E02FAA90F0098A9DC27FFFF0000A0A93A04FFFF00009CA9FD19FFFF000081"
99 // MODBUS40 data read out, CRC failure, negative acknowledge should be send
100 + "5C00206850449C9600489C88014C9C2D014E9CCF004D9CE0014F9C3200509C0400519C8201529C6B02569C3E00C9AF000001A8F600FDA77E02FAA90F0098A9DC27FFFF0000A0A93A04FFFF00009CA9FD19FFFF000080"
101 // RMU40 message, acknowledge should be send
102 + "5C001962189600DF01020000000080000000000002091434000100000586"
105 // unknown RMU40 message, acknowledge should be send
107 // MODBUS40 data read out, special len, acknowledge should be send
108 + "5C00206851449C2500489CFC004C9CF1004E9CC7014D9C0B024F9C2500509C3300519C0B01529C5C5C01569C3100C9AF000001A80C01FDA716FAFAA9070098A91B1BFFFF0000A0A9CA02FFFF00009CA99212FFFF0000BE"
109 // MODBUS40 data read out, special len, acknowledge should be send
110 + "5C00206852449C2500489CFE004C9CF2004E9CD4014D9CFB014F9C2500509C3700519C0D01529C5C5C01569C3200C9AF000001A80C01FDA712FAFAA9070098A95C5C1BFFFF0000A0A9D102FFFF00009CA9B412FFFF00007F"
111 // MODBUS40 data read out, special checksum, acknowledge should be send
112 + "5C00206850449C2600489CF6004C9CF1004E9CD6014D9C0C024F9C4500509C3F00519CF100529C0401569CD500C9AF000001A80C01FDA799FAFAA9020098A91A1BFFFF0000A0A9CA02FFFF00009CA99212FFFF0000C5"
113 // 16-bit address (e.g. model F2120 heatpumps), acknowledge should be send
117 // create byte data from hex string
118 final byte[] rawData = HexUtils.hexToBytes(strTestData);
120 // put byte data to protocol state machine
121 mockupContext.buffer().put(rawData);
122 mockupContext.buffer().flip();
124 // run protocol state machine to process test data
125 while (mockupContext.state().process(mockupContext)) {
130 assertEquals(8, ackRequestCount);
131 assertEquals(2, nakRequestCount);
132 assertEquals(1, sendWriteMsgCount);
133 assertEquals(1, sendReadMsgCount);
134 assertEquals(8, receivedMsgs.size());
138 expect = "5C001962189600E1010200000000800000000000020914340001000005B8";
139 assertArrayEquals(HexUtils.hexToBytes(expect), receivedMsgs.get(0));
141 expect = "5C00206850449C9600489C88014C9C2D014E9CCF004D9CE0014F9C3200509C0400519C8201529C6B02569C3E00C9AF000001A8F600FDA77E02FAA90F0098A9DC27FFFF0000A0A93A04FFFF00009CA9FD19FFFF000081";
142 assertArrayEquals(HexUtils.hexToBytes(expect), receivedMsgs.get(1));
144 expect = "5C001962189600DF01020000000080000000000002091434000100000586";
145 assertArrayEquals(HexUtils.hexToBytes(expect), receivedMsgs.get(2));
147 expect = "5C0019600079";
148 assertArrayEquals(HexUtils.hexToBytes(expect), receivedMsgs.get(3));
150 expect = "5C00206851449C2500489CFC004C9CF1004E9CC7014D9C0B024F9C2500509C3300519C0B01529C5C5C01569C3100C9AF000001A80C01FDA716FAFAA9070098A91B1BFFFF0000A0A9CA02FFFF00009CA99212FFFF0000BE";
151 assertArrayEquals(HexUtils.hexToBytes(expect), receivedMsgs.get(4));
153 expect = "5C00206852449C2500489CFE004C9CF2004E9CD4014D9CFB014F9C2500509C3700519C0D01529C5C5C01569C3200C9AF000001A80C01FDA712FAFAA9070098A95C5C1BFFFF0000A0A9D102FFFF00009CA9B412FFFF00007F";
154 assertArrayEquals(HexUtils.hexToBytes(expect), receivedMsgs.get(5));
156 expect = "5C00206850449C2600489CF6004C9CF1004E9CD6014D9C0C024F9C4500509C3F00519CF100529C0401569CD500C9AF000001A80C01FDA799FAFAA9020098A91A1BFFFF0000A0A9CA02FFFF00009CA99212FFFF0000C5";
157 assertArrayEquals(HexUtils.hexToBytes(expect), receivedMsgs.get(6));
159 expect = "5C41C9F7007F";
160 assertArrayEquals(HexUtils.hexToBytes(expect), receivedMsgs.get(7));