I’ve developed a small program that listens to a serial port. My program is receiving data. The problem is, its not displaying it in the desired format (one string). The data my program is receiving comes in two strings, for example:
ID:34242 State:NY
Zip:12345 StreetType:Ave
Its being displayed by chunks and some of the data is passed on to next lines as such:
ID:34242
State:N
Y Zip:12
345 Street
Type:Ave
I have used the SerialDataReceive Event Handler to receive my data and it looks like this:
private static void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort spL = (SerialPort) sender;
int bufSize = 20;
Byte[] dataBuffer = new Byte[bufSize];
Console.WriteLine("Data Received at"+DateTime.Now);
Console.WriteLine(spL.Read(dataBuffer, 0, bufSize));
string s = System.Text.ASCIIEncoding.ASCII.GetString(dataBuffer);
Console.WriteLine(s);
}
As you can see, I retrieve the bytes into the buffer, create a byte array to hold the data and use ASCII encoding to translate the bytes into a string. I tried using ReadLine() but my data doesn’t event get displayed with that function. Does anyone know of any other way to parse and format the data into one string?
The problem is, as you may have guessed, that the event DataReceived is raised as soon as data has been received over the serial port. There may not be a complete record there; the SerialPort object has no clue what you consider to be “enough” data to be significant, or workable.
The usual solution is to maintain another “buffer” of received data, containing any data you have recognized as incomplete. When data comes in over the port and your event fires, it should first take what’s in the buffer and append it to what you have already received. Then, you should start at the beginning of this data buffer and inspect the received data, looking for known patterns of atomic “chunks” of data that have meaning to you; for instance, say the first thing you receive is
"ID: 12". You take this, put it in the buffer, then scan the buffer looking for a pattern defined by a regex"ID: \d*? ". Because the trailing space is not present in your buffer, your pattern fails to find anything of meaning, and so you now know you haven’t received a full message.Then, on the next raising of the DataReceived event, you pull
"453 Sta"out of the serial buffer. You append it to what you already have and get"ID:12453 Sta", and when you apply the regex, you get the match “ID: 12345 “. You pass this into a method for further processing (display to the console, maybe), and remove the same string from the front of the buffer, leaving “Sta”. Scanning again you don’t find anything else of interest, so you leave what you have, and the cycle repeats aws data continues to come in. Obviously, you’ll be testing more patterns than just the ID pattern; you may search for an entire “string” you expect to receive, such as"ID: \d*? State: \w{2} ". You may even keep the data in your buffer until you have both strings for a record:"ID:\d*? State:\w{2} Zip:\d{5} StreetType:\w*? ".Either way, you will need to identify whether the data being received is either reliably “fixed-length” (meaning each string of a particular type will always have the same number of bytes or characters), or reliably “delimited” (meaning there will be some character or character combination that always separates significant elements of data). If neither of these apply, it may be very difficult to parse the data into single-field chunks.
Here’s a sample based on what you have already: