/** * Copyright (c) 2010-2016 by the respective copyright holders. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.openhab.binding.stiebelheatpump.protocol; import java.nio.ByteBuffer; import java.nio.ByteOrder; import org.openhab.binding.stiebelheatpump.internal.StiebelHeatPumpException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * CircularByteBuffer class providing a buffer that is synchronized with the * received bytes from heat pump connector * * @author Peter Kreutzer */ public class CircularByteBuffer { private static Logger logger = LoggerFactory.getLogger(CircularByteBuffer.class); private static final int WAIT_MS = 10; private int readPos = 0; private int writePos = 0; private int currentSize = 0; private int markedPos = 0; private byte[] buffer; private boolean running = true; private int retry = 5; public CircularByteBuffer(int size) { buffer = new byte[size]; } public byte get() throws StiebelHeatPumpException { if (!waitForData()) { throw new StiebelHeatPumpException("no data availabel!"); } byte result; synchronized (buffer) { result = buffer[readPos]; currentSize--; readPos++; if (readPos >= buffer.length) { readPos = 0; } } return result; } private boolean waitForData() { int timeOut = 0; while (isEmpty() && timeOut < retry && running) { try { Thread.sleep(WAIT_MS); timeOut++; } catch (Exception e) { logger.error("Error while waiting for new data", e); } } if (timeOut == retry) { return false; } return true; } public short getShort() throws StiebelHeatPumpException { ByteBuffer bb = ByteBuffer.allocate(2); bb.order(ByteOrder.BIG_ENDIAN); bb.put(get()); bb.put(get()); return bb.getShort(0); } public void get(byte[] data) throws StiebelHeatPumpException { for (int i = 0; i < data.length; i++) { data[i] = get(); } } public void put(byte b) { synchronized (buffer) { buffer[writePos] = b; writePos++; currentSize++; if (writePos >= buffer.length) { writePos = 0; } } } public void mark() { markedPos = readPos; } public void reset() { currentSize += Math.abs(readPos - markedPos); readPos = markedPos; } private boolean isEmpty() { return currentSize <= 0; } public void stop() { running = false; } }