I have an incoming byte array in real-time that has the following format:
Header : 3 bytes
message: 10 bytes
Header : 3 bytes
message: 10 bytes
and so on
The problem is it is a continuous stream that I can not predict when the header comes as I could start reading incoming bytes at a portion of the message or header. So I would appreciate it if someone could assist me in how to trap a header and then stay in sync using dataReceived event.
Edit: I tried using a counter for checking each incoming byte as a header, then set the threshold to trigger after the payload is received.
- Set Incoming threshold trigger to 1 byte
- Check first, second headers
- Get the payload if headers are detected and set the incoming threshold trigger to the payload.
- Parse payload, set threshold again to 1 byte.
Although it is not bad, it is not reliable with each incoming frames unlike software like serialplot
private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte data = 0;
if (_syncCounter < 3)
{
data = (byte)_serialPort.ReadByte();
}
switch (_syncCounter)
{
case 0: // First Byte in Header
_syncCounter = data == (byte)0xAA ? (byte) 1 : (byte) 0;
break;
case 1: // Second Byte in Header
_syncCounter = data == (byte)0xBB ? (byte)2 : (byte)0;
break;
case 2:
// Payload
_syncCounter = data == (byte)data ? (byte)3 : (byte)0;
if (_syncCounter == 3)
{
_serialPort.ReceivedBytesThreshold = data;
_payload = data;
}
break;
case 3:
// Packet
var packet = Enumerable.Repeat((byte)0x00, _payload).ToArray();
byte[] fieldBytes;
float fieldFloat;
_serialPort.Read(packet, 0, _payload);
if (packet.Length < _payload)
{
_serialPort.ReceivedBytesThreshold = 1;
_syncCounter = 0;
_payload = 0;
}
else
{
if (_isFirstPayload)
{
_syncCounter = 0;
_payload = 0;
_isFirstPayload = false;
break;
}
for (uint i = 0; i <= (_payload-1); i += 4)
{
fieldBytes = Slice(packet, i, i+4);
fieldFloat = ReadSingleBigEndian(fieldBytes, 0);
if (fieldFloat < 0)
fieldFloat = 0;
_sb.Append(fieldFloat.ToString(CultureInfo.InvariantCulture));
_sb.Append(",");
}
IncomingFrame.BeginInvoke(() =>
{
IncomingFrame.Text = ByteArrayToString(packet);
if (_sb.Length > 0)
{
_sb.Remove(_sb.Length - 1, 1);
FloatFields.Text = _sb.ToString();
}
_sb.Clear();
_serialPort.ReceivedBytesThreshold = 1;
_syncCounter = 0;
});
}
break;
}
}
The problem is, sometimes I receive the header as part of the payload although, from the code I wrote, it should be filtered before reading the payload.
I checked the same response using serialplot and it is syncing meaning the hardware is sending data as expected and parsed correctly.