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.velbus.internal;
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.util.ArrayList;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.binding.velbus.internal.packets.VelbusPacket;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
26 * The {@link VelbusPacketInputStream} is a wrapper around an InputStream that
27 * aggregates bytes from the input stream to meaningfull packets in the Velbus system.
29 * @author Cedric Boon - Initial contribution
32 public class VelbusPacketInputStream {
33 private final Logger logger = LoggerFactory.getLogger(VelbusPacketInputStream.class);
35 public InputStream inputStream;
37 private ArrayList<Byte> currentData = new ArrayList<Byte>();
38 private @Nullable Byte currentSTX = null;
39 private @Nullable Byte currentPriority = null;
40 private @Nullable Byte currentAddress = null;
41 private @Nullable Byte currentDataLength = null;
42 private @Nullable Byte currentChecksum = null;
44 public VelbusPacketInputStream(InputStream inputStream) {
45 this.inputStream = inputStream;
48 public byte[] readPacket() throws IOException {
51 while ((currentDataByte = inputStream.read()) > -1) {
52 if (currentSTX == null) {
53 if (((byte) currentDataByte) == VelbusPacket.STX) {
54 currentSTX = (byte) currentDataByte;
57 logger.debug("Packet with invalid start byte: {}", currentDataByte);
59 } else if (currentPriority == null) {
60 if (((byte) currentDataByte) == VelbusPacket.PRIO_HI
61 || ((byte) currentDataByte) == VelbusPacket.PRIO_LOW) {
62 currentPriority = (byte) currentDataByte;
65 logger.debug("Packet with invalid priority received: {}", currentDataByte);
67 } else if (currentAddress == null) {
68 currentAddress = (byte) currentDataByte;
69 } else if (currentDataLength == null && currentDataByte <= 8) {
70 currentDataLength = (byte) currentDataByte;
71 } else if (currentDataLength == null) {
72 currentDataLength = 1;
73 currentData.add((byte) currentDataByte);
74 } else if (currentDataLength != null && (currentData.size() < currentDataLength)) {
75 currentData.add((byte) currentDataByte);
76 } else if (currentChecksum == null) {
77 currentChecksum = (byte) currentDataByte;
78 byte[] packet = getCurrentPacket();
79 byte expectedChecksum = VelbusPacket.computeCRCByte(packet);
81 if (currentChecksum != expectedChecksum) {
83 logger.debug("Packet with invalid checksum received: {} instead of {}", currentChecksum,
86 } else if (((byte) currentDataByte) == VelbusPacket.ETX) {
87 byte[] packet = getCurrentPacket();
94 logger.debug("Packet with invalid ETX received: {}", currentDataByte);
101 public void close() throws IOException {
105 protected byte[] getCurrentPacket() {
106 if (currentDataLength != null && currentSTX != null && currentPriority != null && currentAddress != null
107 && currentChecksum != null) {
108 byte[] packet = new byte[6 + currentDataLength];
109 packet[0] = currentSTX;
110 packet[1] = currentPriority;
111 packet[2] = currentAddress;
112 packet[3] = currentDataLength;
114 for (int i = 0; i < currentDataLength; i++) {
115 packet[4 + i] = currentData.get(i);
118 packet[4 + currentDataLength] = currentChecksum;
119 packet[5 + currentDataLength] = VelbusPacket.ETX;
127 protected void resetCurrentState() {
129 currentPriority = null;
130 currentAddress = null;
131 currentDataLength = null;
132 currentData = new ArrayList<>();
133 currentChecksum = null;