@Override
public void sendAck() {
try {
- byte addr = msg().get(NibeHeatPumpProtocol.OFFSET_ADR);
+ byte addr = msg().get(NibeHeatPumpProtocol.RES_OFFS_ADR);
sendAckToNibe(addr);
} catch (IOException e) {
sendErrorToListeners(e.getMessage());
sendDataToNibe(writeQueue.remove(0));
} else {
// no messages to send, send ack to pump
- byte addr = msg().get(NibeHeatPumpProtocol.OFFSET_ADR);
+ byte addr = msg().get(NibeHeatPumpProtocol.RES_OFFS_ADR);
sendAckToNibe(addr);
}
} catch (IOException e) {
sendDataToNibe(readQueue.remove(0));
} else {
// no messages to send, send ack to pump
- byte addr = msg().get(NibeHeatPumpProtocol.OFFSET_ADR);
+ byte addr = msg().get(NibeHeatPumpProtocol.RES_OFFS_ADR);
sendAckToNibe(addr);
}
} catch (IOException e) {
*/
public class ModbusDataReadOutMessage extends NibeHeatPumpBaseMessage {
- private List<ModbusValue> values;
+ private List<ModbusValue> values = new ArrayList<>();
private ModbusDataReadOutMessage(MessageBuilder builder) {
super.msgType = MessageType.MODBUS_DATA_READ_OUT_MSG;
@Override
public void encodeMessage(byte[] data) throws NibeHeatPumpException {
- values = parseMessage(data);
+ if (NibeHeatPumpProtocol.isModbus40DataReadOut(data)) {
+ super.encodeMessage(data);
+ final int msglen = NibeHeatPumpProtocol.RES_HEADER_LEN + rawMessage[NibeHeatPumpProtocol.RES_OFFS_LEN];
+
+ values.clear();
+
+ try {
+ for (int i = NibeHeatPumpProtocol.RES_OFFS_DATA; i < (msglen - 1); i += 4) {
+
+ int id = ((rawMessage[i + 1] & 0xFF) << 8 | (rawMessage[i + 0] & 0xFF));
+ int value = (rawMessage[i + 3] & 0xFF) << 8 | (rawMessage[i + 2] & 0xFF);
+
+ if (id != 0xFFFF) {
+ values.add(new ModbusValue(id, value));
+ }
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new NibeHeatPumpException("Error occurred during data parsing", e);
+ }
+ } else {
+ throw new NibeHeatPumpException("Not Modbus data readout message");
+ }
}
@Override
public byte[] decodeMessage() {
- return createDataReadOutPdu(values);
- }
-
- private byte[] createDataReadOutPdu(List<ModbusValue> values) {
byte datalen = (byte) (values.size() * 4);
- byte msglen = (byte) (6 + datalen);
+ byte msglen = (byte) (NibeHeatPumpProtocol.RES_HEADER_LEN + datalen + NibeHeatPumpProtocol.PDU_CHECKSUM_LEN);
byte[] data = new byte[msglen];
- data[0] = NibeHeatPumpProtocol.FRAME_START_CHAR_FROM_NIBE;
+ data[0] = NibeHeatPumpProtocol.FRAME_START_CHAR_RES;
data[1] = 0x00;
data[2] = NibeHeatPumpProtocol.ADR_MODBUS40;
data[3] = NibeHeatPumpProtocol.CMD_MODBUS_DATA_MSG;
data[4] = datalen;
- int i = NibeHeatPumpProtocol.OFFSET_DATA;
+ int i = NibeHeatPumpProtocol.RES_OFFS_DATA;
for (ModbusValue value : values) {
}
data[msglen - 1] = NibeHeatPumpProtocol.calculateChecksum(data, 2, msglen);
-
return data;
}
return str;
}
- private List<ModbusValue> parseMessage(byte[] data) throws NibeHeatPumpException {
- if (NibeHeatPumpProtocol.isModbus40DataReadOut(data)) {
- super.encodeMessage(data);
- final int msglen = 5 + rawMessage[NibeHeatPumpProtocol.OFFSET_LEN];
-
- List<ModbusValue> vals = new ArrayList<>();
-
- try {
- for (int i = NibeHeatPumpProtocol.OFFSET_DATA; i < (msglen - 1); i += 4) {
-
- int id = ((rawMessage[i + 1] & 0xFF) << 8 | (rawMessage[i + 0] & 0xFF));
- int value = (rawMessage[i + 3] & 0xFF) << 8 | (rawMessage[i + 2] & 0xFF);
-
- if (id != 0xFFFF) {
- vals.add(new ModbusValue(id, value));
- }
- }
- } catch (ArrayIndexOutOfBoundsException e) {
- throw new NibeHeatPumpException("Error occurred during data parsing", e);
- }
-
- return vals;
-
- } else {
- throw new NibeHeatPumpException("Not Modbus data readout message");
- }
- }
-
public static class MessageBuilder {
private List<ModbusValue> values = new ArrayList<>();
public void encodeMessage(byte[] data) throws NibeHeatPumpException {
if (NibeHeatPumpProtocol.isModbus40ReadRequestPdu(data)) {
super.encodeMessage(data);
- coilAddress = (data[4] & 0xFF) << 8 | (data[3] & 0xFF);
+ coilAddress = (rawMessage[4] & 0xFF) << 8 | (rawMessage[3] & 0xFF);
} else {
throw new NibeHeatPumpException("Not Read Request message");
}
@Override
public byte[] decodeMessage() {
- return createModbus40ReadPdu(coilAddress);
- }
-
- private byte[] createModbus40ReadPdu(int coilAddress) {
byte[] data = new byte[6];
- data[0] = NibeHeatPumpProtocol.FRAME_START_CHAR_TO_NIBE;
+ data[0] = NibeHeatPumpProtocol.FRAME_START_CHAR_REQ;
data[1] = NibeHeatPumpProtocol.CMD_MODBUS_READ_REQ;
data[2] = (byte) 0x02; // data len
data[3] = (byte) (coilAddress & 0xFF);
@Override
public void encodeMessage(byte[] data) throws NibeHeatPumpException {
- super.encodeMessage(data);
+ if (NibeHeatPumpProtocol.isModbus40ReadResponse(data)) {
+ super.encodeMessage(data);
+ coilAddress = ((rawMessage[NibeHeatPumpProtocol.RES_OFFS_DATA + 1] & 0xFF) << 8
+ | (rawMessage[NibeHeatPumpProtocol.RES_OFFS_DATA + 0] & 0xFF));
+ value = (rawMessage[NibeHeatPumpProtocol.RES_OFFS_DATA + 5] & 0xFF) << 24
+ | (rawMessage[NibeHeatPumpProtocol.RES_OFFS_DATA + 4] & 0xFF) << 16
+ | (rawMessage[NibeHeatPumpProtocol.RES_OFFS_DATA + 3] & 0xFF) << 8
+ | (rawMessage[NibeHeatPumpProtocol.RES_OFFS_DATA + 2] & 0xFF);
- coilAddress = (data[3] & 0xFF) << 8 | (data[4] & 0xFF);
- parseMessage(data);
+ } else {
+ throw new NibeHeatPumpException("Not Read Response message");
+ }
}
@Override
public byte[] decodeMessage() {
- return createModbusReadResponsePdu(coilAddress, value);
- }
-
- private byte[] createModbusReadResponsePdu(int coilAddress, int value) {
byte[] data = new byte[12];
- data[0] = NibeHeatPumpProtocol.FRAME_START_CHAR_FROM_NIBE;
+ data[0] = NibeHeatPumpProtocol.FRAME_START_CHAR_RES;
data[1] = 0x00;
data[2] = NibeHeatPumpProtocol.ADR_MODBUS40;
data[3] = NibeHeatPumpProtocol.CMD_MODBUS_READ_RESP;
@Override
public String toString() {
- String str = "";
-
- str += super.toString();
+ String str = super.toString();
str += ", Coil address = " + coilAddress;
str += ", Value = " + value;
return str;
}
- private void parseMessage(byte[] data) throws NibeHeatPumpException {
- if (NibeHeatPumpProtocol.isModbus40ReadResponse(data)) {
- super.encodeMessage(data);
- coilAddress = ((data[NibeHeatPumpProtocol.OFFSET_DATA + 1] & 0xFF) << 8
- | (data[NibeHeatPumpProtocol.OFFSET_DATA + 0] & 0xFF));
- value = (data[NibeHeatPumpProtocol.OFFSET_DATA + 5] & 0xFF) << 24
- | (data[NibeHeatPumpProtocol.OFFSET_DATA + 4] & 0xFF) << 16
- | (data[NibeHeatPumpProtocol.OFFSET_DATA + 3] & 0xFF) << 8
- | (data[NibeHeatPumpProtocol.OFFSET_DATA + 2] & 0xFF);
-
- } else {
- throw new NibeHeatPumpException("Not Read Response message");
- }
- }
-
public static class MessageBuilder {
private int coilAddress;
private int value;
public void encodeMessage(byte[] data) throws NibeHeatPumpException {
if (NibeHeatPumpProtocol.isModbus40WriteRequestPdu(data)) {
super.encodeMessage(data);
- coilAddress = (data[4] & 0xFF) << 8 | (data[3] & 0xFF);
- value = (data[8] & 0xFF) << 24 | (data[7] & 0xFF) << 16 | (data[6] & 0xFF) << 8 | (data[5] & 0xFF);
+ coilAddress = (rawMessage[4] & 0xFF) << 8 | (rawMessage[3] & 0xFF);
+ value = (rawMessage[8] & 0xFF) << 24 | (rawMessage[7] & 0xFF) << 16 | (rawMessage[6] & 0xFF) << 8
+ | (rawMessage[5] & 0xFF);
} else {
throw new NibeHeatPumpException("Not Write Request message");
}
@Override
public byte[] decodeMessage() {
- return createModbus40WritePdu(coilAddress, value);
- }
-
- private byte[] createModbus40WritePdu(int coildAddress, int value) {
byte[] data = new byte[10];
- data[0] = NibeHeatPumpProtocol.FRAME_START_CHAR_TO_NIBE;
+ data[0] = NibeHeatPumpProtocol.FRAME_START_CHAR_REQ;
data[1] = NibeHeatPumpProtocol.CMD_MODBUS_WRITE_REQ;
data[2] = (byte) 0x06; // data len
- data[3] = (byte) (coildAddress & 0xFF);
- data[4] = (byte) ((coildAddress >> 8) & 0xFF);
+ data[3] = (byte) (coilAddress & 0xFF);
+ data[4] = (byte) ((coilAddress >> 8) & 0xFF);
data[5] = (byte) (value & 0xFF);
data[6] = (byte) ((value >> 8) & 0xFF);
data[7] = (byte) ((value >> 16) & 0xFF);
@Override
public String toString() {
- String str = "";
-
- str += super.toString();
+ String str = super.toString();
str += ", Coil address = " + coilAddress;
str += ", Value = " + value;
@Override
public void encodeMessage(byte[] data) throws NibeHeatPumpException {
- result = modbus40WriteSuccess(data);
+ if (NibeHeatPumpProtocol.isModbus40WriteResponsePdu(data)) {
+ super.encodeMessage(data);
+ result = rawMessage[NibeHeatPumpProtocol.RES_OFFS_DATA] == 1;
+ } else {
+ throw new NibeHeatPumpException("Not Write Response message");
+ }
}
public boolean isSuccessfull() {
@Override
public byte[] decodeMessage() {
- return createModbusWriteResponsePdu(result);
- }
-
- private byte[] createModbusWriteResponsePdu(boolean result) {
byte[] data = new byte[7];
- data[0] = NibeHeatPumpProtocol.FRAME_START_CHAR_FROM_NIBE;
+ data[0] = NibeHeatPumpProtocol.FRAME_START_CHAR_RES;
data[1] = 0x00;
data[2] = NibeHeatPumpProtocol.ADR_MODBUS40;
data[3] = NibeHeatPumpProtocol.CMD_MODBUS_WRITE_RESP;
return str;
}
- private boolean modbus40WriteSuccess(byte[] data) throws NibeHeatPumpException {
- if (NibeHeatPumpProtocol.isModbus40WriteResponsePdu(data)) {
- super.encodeMessage(data);
- return data[NibeHeatPumpProtocol.OFFSET_DATA] == 1;
- }
- throw new NibeHeatPumpException("Not Write Response message");
- }
-
public static class MessageBuilder {
private boolean result;
public byte[] rawMessage;
public MessageType msgType = MessageType.UNKNOWN;
- public byte msgId;
public NibeHeatPumpBaseMessage() {
}
@Override
public void encodeMessage(byte[] data) throws NibeHeatPumpException {
- data = NibeHeatPumpProtocol.checkMessageChecksumAndRemoveDoubles(data);
- rawMessage = data;
- msgId = data[1];
+ if (data.length >= NibeHeatPumpProtocol.PDU_MIN_LEN) {
+ byte[] d = NibeHeatPumpProtocol.checkMessageChecksumAndRemoveDoubles(data);
+ rawMessage = d.clone();
- byte messageTypeByte = NibeHeatPumpProtocol.getMessageType(data);
- msgType = NibeHeatPumpBaseMessage.getMessageType(messageTypeByte);
+ byte messageTypeByte = NibeHeatPumpProtocol.getMessageType(d);
+ msgType = NibeHeatPumpBaseMessage.getMessageType(messageTypeByte);
+ } else {
+ throw new NibeHeatPumpException("Too short message");
+ }
}
@Override
*/
package org.openhab.binding.nibeheatpump.internal.protocol;
-import org.apache.commons.lang3.ArrayUtils;
+import java.io.ByteArrayOutputStream;
+
import org.openhab.binding.nibeheatpump.internal.NibeHeatPumpException;
/**
*/
public class NibeHeatPumpProtocol {
- public static final byte FRAME_START_CHAR_FROM_NIBE = (byte) 0x5C;
- public static final byte FRAME_START_CHAR_TO_NIBE = (byte) 0xC0;
+ public static final byte PDU_MIN_LEN = 3;
+
+ public static final byte PDU_CHECKSUM_LEN = 1;
+
+ public static final byte FRAME_START_CHAR_RES = (byte) 0x5C;
+ public static final byte FRAME_START_CHAR_REQ = (byte) 0xC0;
public static final byte OFFSET_START = 0;
- public static final byte OFFSET_ADR = 2;
- public static final byte OFFSET_CMD = 3;
- public static final byte OFFSET_LEN = 4;
- public static final byte OFFSET_DATA = 5;
+ public static final byte RES_OFFS_ADR = 2;
+ public static final byte RES_OFFS_CMD = 3;
+ public static final byte RES_OFFS_LEN = 4;
+ public static final byte RES_OFFS_DATA = 5;
+
+ public static final byte REQ_OFFS_CMD = 1;
+ public static final byte REQ_OFFS_LEN = 2;
+
+ public static final byte RES_HEADER_LEN = 5;
+ public static final byte REQ_HEADER_LEN = 3;
public static final byte CMD_RMU_DATA_MSG = (byte) 0x62;
public static final byte CMD_MODBUS_DATA_MSG = (byte) 0x68;
public static final byte ADR_MODBUS40 = (byte) 0x20;
public static boolean isModbus40DataReadOut(byte[] data) {
- if (data[OFFSET_START] == FRAME_START_CHAR_FROM_NIBE && data[1] == (byte) 0x00
- && data[OFFSET_ADR] == ADR_MODBUS40) {
- return data[OFFSET_CMD] == CMD_MODBUS_DATA_MSG && data[OFFSET_LEN] >= (byte) 0x50;
+ if (data[OFFSET_START] == FRAME_START_CHAR_RES && data[1] == (byte) 0x00
+ && data[RES_OFFS_ADR] == ADR_MODBUS40) {
+ return data[RES_OFFS_CMD] == CMD_MODBUS_DATA_MSG && data[RES_OFFS_LEN] >= (byte) 0x50;
}
return false;
}
public static boolean isModbus40ReadResponse(byte[] data) {
- if (data[OFFSET_START] == FRAME_START_CHAR_FROM_NIBE && data[1] == (byte) 0x00
- && data[OFFSET_ADR] == ADR_MODBUS40) {
- return data[OFFSET_CMD] == CMD_MODBUS_READ_RESP && data[OFFSET_LEN] >= (byte) 0x06;
+ if (data[OFFSET_START] == FRAME_START_CHAR_RES && data[1] == (byte) 0x00
+ && data[RES_OFFS_ADR] == ADR_MODBUS40) {
+ return data[RES_OFFS_CMD] == CMD_MODBUS_READ_RESP && data[RES_OFFS_LEN] >= (byte) 0x06;
}
return false;
}
public static boolean isRmu40DataReadOut(byte[] data) {
- if (data[0] == FRAME_START_CHAR_FROM_NIBE && data[1] == (byte) 0x00 && data[OFFSET_ADR] == ADR_RMU40) {
- return data[OFFSET_CMD] == CMD_RMU_DATA_MSG && data[OFFSET_LEN] >= (byte) 0x18;
+ if (data[0] == FRAME_START_CHAR_RES && data[1] == (byte) 0x00 && data[RES_OFFS_ADR] == ADR_RMU40) {
+ return data[RES_OFFS_CMD] == CMD_RMU_DATA_MSG && data[RES_OFFS_LEN] >= (byte) 0x18;
}
return false;
}
public static boolean isModbus40WriteResponsePdu(byte[] data) {
- return data[OFFSET_START] == FRAME_START_CHAR_FROM_NIBE && data[1] == (byte) 0x00
- && data[OFFSET_ADR] == ADR_MODBUS40 && data[OFFSET_CMD] == CMD_MODBUS_WRITE_RESP;
+ return data[OFFSET_START] == FRAME_START_CHAR_RES && data[1] == (byte) 0x00
+ && data[RES_OFFS_ADR] == ADR_MODBUS40 && data[RES_OFFS_CMD] == CMD_MODBUS_WRITE_RESP;
}
public static boolean isModbus40WriteTokenPdu(byte[] data) {
- return data[0] == FRAME_START_CHAR_FROM_NIBE && data[1] == (byte) 0x00 && data[OFFSET_ADR] == ADR_MODBUS40
- && data[OFFSET_CMD] == CMD_MODBUS_WRITE_REQ && data[OFFSET_LEN] == 0x00;
+ return data[0] == FRAME_START_CHAR_RES && data[1] == (byte) 0x00 && data[RES_OFFS_ADR] == ADR_MODBUS40
+ && data[RES_OFFS_CMD] == CMD_MODBUS_WRITE_REQ && data[RES_OFFS_LEN] == 0x00;
}
public static boolean isModbus40ReadTokenPdu(byte[] data) {
- return data[OFFSET_START] == FRAME_START_CHAR_FROM_NIBE && data[1] == (byte) 0x00
- && data[OFFSET_ADR] == ADR_MODBUS40 && data[OFFSET_CMD] == CMD_MODBUS_READ_REQ
- && data[OFFSET_LEN] == 0x00;
+ return data[OFFSET_START] == FRAME_START_CHAR_RES && data[1] == (byte) 0x00
+ && data[RES_OFFS_ADR] == ADR_MODBUS40 && data[RES_OFFS_CMD] == CMD_MODBUS_READ_REQ
+ && data[RES_OFFS_LEN] == 0x00;
}
public static boolean isModbus40WriteRequestPdu(byte[] data) {
- return data[0] == FRAME_START_CHAR_TO_NIBE && data[1] == CMD_MODBUS_WRITE_REQ;
+ return data[OFFSET_START] == FRAME_START_CHAR_REQ && data[REQ_OFFS_CMD] == CMD_MODBUS_WRITE_REQ;
}
public static boolean isModbus40ReadRequestPdu(byte[] data) {
- return data[OFFSET_START] == FRAME_START_CHAR_TO_NIBE && data[1] == CMD_MODBUS_READ_REQ;
+ return data[OFFSET_START] == FRAME_START_CHAR_REQ && data[REQ_OFFS_CMD] == CMD_MODBUS_READ_REQ;
}
public static byte calculateChecksum(byte[] data) {
public static byte getMessageType(byte[] data) {
byte messageType = 0;
- if (data[NibeHeatPumpProtocol.OFFSET_START] == NibeHeatPumpProtocol.FRAME_START_CHAR_FROM_NIBE) {
- messageType = data[NibeHeatPumpProtocol.OFFSET_CMD];
- } else if (data[NibeHeatPumpProtocol.OFFSET_START] == NibeHeatPumpProtocol.FRAME_START_CHAR_TO_NIBE) {
- messageType = data[1];
+ if (data[NibeHeatPumpProtocol.OFFSET_START] == NibeHeatPumpProtocol.FRAME_START_CHAR_RES) {
+ messageType = data[RES_OFFS_CMD];
+ } else if (data[NibeHeatPumpProtocol.OFFSET_START] == NibeHeatPumpProtocol.FRAME_START_CHAR_REQ) {
+ messageType = data[REQ_OFFS_CMD];
}
return messageType;
if (NibeHeatPumpProtocol.isModbus40ReadRequestPdu(data)
|| NibeHeatPumpProtocol.isModbus40WriteRequestPdu(data)) {
- msglen = 3 + data[2];
+ msglen = REQ_HEADER_LEN + data[REQ_OFFS_LEN];
startIndex = 0;
stopIndex = msglen;
} else {
- msglen = 5 + data[OFFSET_LEN];
+ msglen = RES_HEADER_LEN + data[RES_OFFS_LEN];
startIndex = 2;
stopIndex = msglen;
}
// if checksum is 0x5C (start character), heat pump seems to send 0xC5 checksum
- if (checksum == msgChecksum || (checksum == FRAME_START_CHAR_FROM_NIBE && msgChecksum == (byte) 0xC5)) {
+ if (checksum == msgChecksum || (checksum == FRAME_START_CHAR_RES && msgChecksum == (byte) 0xC5)) {
// if data contains 0x5C (start character), data seems to contains double 0x5C characters
+ return removeEscapedDuplicates(data, msglen);
+ } else {
+ throw new NibeHeatPumpException(
+ "Checksum does not match. Checksum=" + (msgChecksum & 0xFF) + ", expected=" + (checksum & 0xFF));
+ }
+ }
- // let's remove doubles
- for (int i = 1; i < msglen; i++) {
- if (data[i] == FRAME_START_CHAR_FROM_NIBE) {
- data = ArrayUtils.remove(data, i);
- msglen--;
+ private static byte[] removeEscapedDuplicates(byte[] data, int msglen) {
+ if (dataContainsEscapedDuplicates(data, msglen)) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream(msglen);
+ byte newlen = data[RES_OFFS_LEN];
+
+ // write start char
+ out.write(FRAME_START_CHAR_RES);
- // fix message len
- data[OFFSET_LEN]--;
+ // remove all duplicates between start char and checksum bytes
+ // checksum byte can't be 0x5C as it's set to 0xC5 in this case by the heat pump
+ for (int i = 1; i < msglen; i++) {
+ if (data[i] == FRAME_START_CHAR_RES && data[i + 1] == FRAME_START_CHAR_RES) {
+ // write one 0x5C
+ out.write(FRAME_START_CHAR_RES);
+
+ // skip next 0x5C and decrease the length
+ i++;
+ newlen--;
+ } else {
+ out.write(data[i]);
}
}
- } else {
- throw new NibeHeatPumpException(
- "Checksum does not match. Checksum=" + (msgChecksum & 0xFF) + ", expected=" + (checksum & 0xFF));
+
+ // write checksum
+ out.write(data[msglen]);
+
+ // return modified data
+ byte[] newdata = out.toByteArray();
+ newdata[RES_OFFS_LEN] = newlen;
+ return newdata;
}
return data;
}
+
+ private static boolean dataContainsEscapedDuplicates(byte[] data, int msglen) {
+ for (int i = 1; i < msglen; i++) {
+ if (data[i] == FRAME_START_CHAR_RES && data[i + 1] == FRAME_START_CHAR_RES) {
+ return true;
+ }
+ }
+ return false;
+ }
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Received byte: {}", String.format("%02X", b));
}
- if (b == NibeHeatPumpProtocol.FRAME_START_CHAR_FROM_NIBE) {
+ if (b == NibeHeatPumpProtocol.FRAME_START_CHAR_RES) {
LOGGER.trace("Frame start found");
context.msg().clear();
context.msg().put(b);
int len = byteBuffer.remaining();
if (len >= 1) {
- if (byteBuffer.get(0) != NibeHeatPumpProtocol.FRAME_START_CHAR_FROM_NIBE) {
+ if (byteBuffer.get(0) != NibeHeatPumpProtocol.FRAME_START_CHAR_RES) {
return msgStatus.INVALID;
}
}
if (len >= 6) {
- int datalen = byteBuffer.get(NibeHeatPumpProtocol.OFFSET_LEN);
+ int datalen = byteBuffer.get(NibeHeatPumpProtocol.RES_OFFS_LEN);
// check if all bytes received
if (len < datalen + 6) {
checkRegisters(message, expectedValues);
}
+ @Test
+ public void parseHeavilyEscapedModbusDataReadOutMessageTest() throws NibeHeatPumpException {
+ final String message = "5C0020685401A81F0100A86400FDA7D003449C1E004F9CA000509C7800519C0301529C1B01879C14014E9CC601479C010115B9B0FF3AB94B00C9AF0000489C0D014C9CE7004B9C0000FFFF0000FFFF00005C5C5C5C5C5C5C5C41";
+
+ @SuppressWarnings("serial")
+ final ArrayList<ModbusValue> expectedValues = new ArrayList<ModbusValue>() {
+ {
+ add(new ModbusValue(43009, 287));
+ add(new ModbusValue(43008, 100));
+ add(new ModbusValue(43005, 976));
+ add(new ModbusValue(40004, 30));
+ add(new ModbusValue(40015, 160));
+ add(new ModbusValue(40016, 120));
+ add(new ModbusValue(40017, 259));
+ add(new ModbusValue(40018, 283));
+ add(new ModbusValue(40071, 276));
+ add(new ModbusValue(40014, 454));
+ add(new ModbusValue(40007, 257));
+ add(new ModbusValue(47381, 65456));
+ add(new ModbusValue(47418, 75));
+ add(new ModbusValue(45001, 0));
+ add(new ModbusValue(40008, 269));
+ add(new ModbusValue(40012, 231));
+ add(new ModbusValue(40011, 0));
+ add(new ModbusValue(23644, 23644));
+ }
+ };
+
+ checkRegisters(message, expectedValues);
+ }
+
@Test
public void specialLen1Test() throws NibeHeatPumpException {
final String message = "5C00206851449C2500489CFC004C9CF1004E9CC7014D9C0B024F9C2500509C3300519C0B01529C5C5C01569C3100C9AF000001A80C01FDA716FAFAA9070098A91B1BFFFF0000A0A9CA02FFFF00009CA99212FFFF0000BE";
*/
public class ModbusReadResponseMessageTest {
- private final int coilAddress = 513;
- private final int value = 100992003;
- private final String okMessage = "5C00206A060102030405064B";
-
@Test
public void createMessageTest() throws NibeHeatPumpException {
+ final int coilAddress = 513;
+ final int value = 100992003;
+ final String okMessage = "5C00206A060102030405064B";
ModbusReadResponseMessage m = new ModbusReadResponseMessage.MessageBuilder().coilAddress(coilAddress)
.value(value).build();
byte[] byteMessage = m.decodeMessage();
@Test
public void parseMessageTest() throws NibeHeatPumpException {
- byte[] msg = HexUtils.hexToBytes(okMessage);
- ModbusReadResponseMessage m = (ModbusReadResponseMessage) MessageFactory.getMessage(msg);
+ final int coilAddress = 513;
+ final int value = 100992003;
+ final String message = "5C00206A060102030405064B";
+ ModbusReadResponseMessage m = (ModbusReadResponseMessage) MessageFactory
+ .getMessage(HexUtils.hexToBytes(message));
assertEquals(coilAddress, m.getCoilAddress());
assertEquals(value, m.getValue());
}
@Test
public void badCrcTest() {
- final String strMessage = "5C00206A060102030405064C";
- final byte[] byteMessage = HexUtils.hexToBytes(strMessage);
- assertThrows(NibeHeatPumpException.class, () -> MessageFactory.getMessage(byteMessage));
+ final String message = "5C00206A060102030405064C";
+ assertThrows(NibeHeatPumpException.class, () -> MessageFactory.getMessage(HexUtils.hexToBytes(message)));
}
@Test
public void notReadResponseMessageTest() {
- final String strMessage = "5C00206B060102030405064A";
- final byte[] byteMessage = HexUtils.hexToBytes(strMessage);
- assertThrows(NibeHeatPumpException.class, () -> new ModbusReadResponseMessage(byteMessage));
+ final String message = "5C00206B060102030405064A";
+ assertThrows(NibeHeatPumpException.class, () -> new ModbusReadResponseMessage(HexUtils.hexToBytes(message)));
+ }
+
+ @Test
+ public void parseEscapedMessageTest() throws NibeHeatPumpException {
+ final int coilAddress = 513;
+ final int value = 0x05E65C;
+ final String message = "5C00206A0701025C5CE60500AD";
+ ModbusReadResponseMessage m = (ModbusReadResponseMessage) MessageFactory
+ .getMessage(HexUtils.hexToBytes(message));
+ assertEquals(coilAddress, m.getCoilAddress());
+ assertEquals(value, m.getValue());
}
}