package io.sloeber.ui.monitor.internal;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.swt.widgets.Display;
import io.sloeber.core.api.MessageConsumer;
import io.sloeber.ui.Activator;
import io.sloeber.ui.monitor.views.Messages;
import io.sloeber.ui.monitor.views.MyPlotter;
public class PlotterListener implements MessageConsumer {
MyPlotter myPlotter;
/**
* myReceivedSerialData is a fixed size buffer holding the bytes that have
* been received from the com port
*
* if we are more than this behind we will loose data
*/
private ByteBuffer myReceivedSerialData = ByteBuffer.allocate(2000);
/**
* myEndPosition points to the last byte that is still valid in the buffer.
* This is needed because myReceivedSerialData is fixed size.
*
*/
private int myEndPosition = 0;
public PlotterListener(MyPlotter plotter) {
this.myReceivedSerialData.order(ByteOrder.LITTLE_ENDIAN);
this.myPlotter = plotter;
}
/**
* Here the message comes in from the serial port. If there is not enough
* place in If there is enough place in myReceivedSerialData the data is
* added to myReceivedSerialData to hold all the data; all the data (that in
* myReceivedSerialData and in s) is ignored and a warning is dumped If
* there is enough place in myReceivedSerialData the data is added to
* myReceivedSerialData and myReceivedSerialData is scanned for plotter data
*
*/
@Override
public synchronized void message(byte[] newData) {
if (this.myPlotter.isDisposed())
return;
if (this.myEndPosition + newData.length >= this.myReceivedSerialData.capacity()) {
this.myEndPosition = 0;
Activator.log(new Status(IStatus.WARNING, Activator.getId(), Messages.serialListenerPlotterSkippingData));
} else {
this.myReceivedSerialData.position(this.myEndPosition);
this.myReceivedSerialData.put(newData, 0, newData.length);
this.myEndPosition = this.myReceivedSerialData.position();
internalExtractAndProcessSerialData();
}
}
@Override
public void dispose() {
this.myPlotter = null;
this.myReceivedSerialData = null;
}
/**
* addValuesToPlotter This method makes the plotter to draw the values that
* have been delivered to the plotter
*/
public void addValuesToPlotter() {
if (this.myPlotter.isDisposed())
return;
// run on the gui thread only
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
try {
// PlotterListener.this.myPlotter.getDispatcher(0).hookPulse(PlotterListener.this.myPlotter,
// 1);
PlotterListener.this.myPlotter.redraw();
} catch (Exception e) {
// ignore as we get errors when closing down
}
}
});
}
/**
* internalExtractAndProcessSerialData scans the incoming serial for plotter
* data in myReceivedSerialData If data is found it is send to the plotter
* all data that has been scanned is removed from myReceivedSerialData
*/
private void internalExtractAndProcessSerialData() {
int lastFoundData = this.myEndPosition - 6;
if (lastFoundData < 0)
return;
// Scan for plotter data
for (int scannnedDataPointer = 0; scannnedDataPointer < this.myEndPosition - 8; scannnedDataPointer++) {
if (this.myReceivedSerialData.getShort(scannnedDataPointer) == Activator.PLOTTER_START_DATA) {
// we have a hit.
lastFoundData = scannnedDataPointer;
scannnedDataPointer = scannnedDataPointer + 2;
int bytestoRead = this.myReceivedSerialData.getShort(scannnedDataPointer);
if ((bytestoRead < 0) || (bytestoRead > 10 * 2)) {
Activator.log(new Status(IStatus.WARNING, Activator.getId(), Messages.serialListenerErrorInputPart1
+ bytestoRead / 2 + ' ' + Messages.serialListenerErrorInputPart2));
} else {
if (bytestoRead + 2 + scannnedDataPointer < this.myEndPosition) {
// all data is available
int myNumDataSetsToReceive = this.myReceivedSerialData.getShort(scannnedDataPointer) / 2 + 0;
for (int CurData = 0; CurData < myNumDataSetsToReceive; CurData++) {
int data = this.myReceivedSerialData.getShort(scannnedDataPointer + 2 + CurData * 2);
this.myPlotter.setValue(CurData, data);
}
addValuesToPlotter();
scannnedDataPointer = scannnedDataPointer + 2 + myNumDataSetsToReceive * 2;
lastFoundData = scannnedDataPointer;
}
}
}
}
// remove all the scanned data
for (int curByte = 0; curByte <= this.myEndPosition - lastFoundData; curByte++) {
try {
this.myReceivedSerialData.put(curByte, this.myReceivedSerialData.get(curByte + lastFoundData));
} catch (IndexOutOfBoundsException e) {
Activator
.log(new Status(IStatus.WARNING, Activator.getId(), Messages.plotterListenerBufferOverflow, e));
}
}
this.myEndPosition -= lastFoundData;
}
@Override
public void event(String event) {
// ignore events
}
}