PDA

View Full Version : I need help Parsing strings in C#



nagmier
10-30-2009, 10:52 AM
I have the following output from a serial connection:

!!!AN0:0,AN1:0,AN2:0,AN3:0,AN4:101,AN5:0,RLL:0.00, PCH:-0.17,YAW:0.09,LAT:279601152,LON:-827158912,ALT:33.59,COG:90.00,SOG:0.00,FIX:1***

I'm reading in the serial Data as "RxString" then I'm trying to "Split" using "comma or ," as the delimiter
When I "AppendText" using tmpString I get results all over the board, When I stick with the original RxString it prints the whole string as read in perfectly fine.


private void DisplayText(object sender, EventArgs e)
{
textBox1.AppendText(tmpString);

}

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
RxString = serialPort1.ReadExisting();
string[] sensorData = RxString.Split(',');
tmpString = sensorData[0];
this.Invoke(new EventHandler(DisplayText));

}

My understanding is that
string[] sensorData = RxString.Split(','); should output strings to the array... I know I'm missing something easy can anyone give me a hand here?

nagmier
10-30-2009, 01:08 PM
Ok I've made some changes to my code and gotten it to parse... here is the new code:



private void DisplayText(object sender, EventArgs e)
{
textBox1.AppendText(RxString);
textBox1.AppendText("\r\n");
string[] an0 = sensorData[0].Split(':');
an0textbox.Text = an0[1];
string[] an1 = sensorData[1].Split(':');
an1textbox.Text = an1[1];
string[] an2 = sensorData[2].Split(':');
an2textbox.Text = an2[1];
string[] an3 = sensorData[3].Split(':');
an3textbox.Text = an3[1];
string[] an4 = sensorData[4].Split(':');
an4textbox.Text = an4[1];
string[] an5 = sensorData[5].Split(':');
an5textbox.Text = an5[1];
string[] rll = sensorData[6].Split(':');
rolltextbox.Text = rll[1];
string[] pch = sensorData[7].Split(':');
pitchtextbox.Text = pch[1];
string[] yaw = sensorData[8].Split(':');
yawtextbox.Text = yaw[1];
string[] lat = sensorData[9].Split(':');
lattextbox.Text = lat[1];
string[] lon = sensorData[10].Split(':');
longtextbox.Text = lon[1];
string[] alt = sensorData[11].Split(':');
alttextbox.Text = alt[1];
string[] cog = sensorData[12].Split(':');
COGtextbox.Text = cog[1];
string[] sog = sensorData[13].Split(':');
SOGtextbox.Text = sog[1];
string[] fix = sensorData[14].Split(':');
fixtextbox.Text = fix[1];
}

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
RxString = serialPort1.ReadLine();
sensorData = RxString.Split(',');
this.Invoke(new EventHandler(DisplayText));

}

Basically I changed from SerialPort.ReadExisting(); to ReadLine();

Unfortunantly it seems to throw an "IOException was Unhandled" randomly when "stopping" on the line:
RxString = serialPort1.ReadLine();

More coming in a sec...

Also seemingly randomly, on "starting" I am getting "IndexOutOfRangeException was unhandeled by user code/Index was outside the bounds of the array" on this line
an0textbox.Text = an0[1];
It seems to occur on this one more often but it does occur on others as well it seems very random, I'm sure I just need some sort of event handler in here somehow or something along those lines but I'm pretty newb when it comes to programming, I have alot of unstructured experience nothing really formal and I'm scatterbrained to boot. Any help would greatly be appreciated.

If Needed I can post the VC# Sln files

Adam
10-30-2009, 05:03 PM
It would be easier to debug if you included more code and the detailed error output.

One thing that comes to mind is that perhaps you should perform some validation on RxString before parsing and displaying it. Maybe there is garbage/noise being read sometimes? At the least you should make sure it's not null or empty after trimming and looks like your data...

Maybe something like this:



// Keep reading until we get good data.
while(RxString == null || RxString.Trim() == "" || !RxString.Trim().StartsWith("!!!AN0") {
RxString = serialPort1.ReadLine();
}
// We got what looks like good data; display it.
sensorData = RxString.Split(',');
this.Invoke(new EventHandler(DisplayText));

Adrenalynn
10-30-2009, 05:17 PM
Probably running right off the edge of the buffer, but I was never good at psychic-debugging...

MikeG
10-30-2009, 09:42 PM
The DataReceived event is not deterministic.

The Microsoft DataReceived Documentation states "Serial received events can be caused by any of the items in the SerialData enumeration. Because the operating system determines whether to raise this event or not, not all parity errors may be reported."


Another way of saying this is... You, as a programmer, have no idea what or how much stuff is in the serial port buffer when the event fires.

So your code...

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
RxString = serialPort1.ReadLine();
sensorData = RxString.Split(',');
this.Invoke(new EventHandler(DisplayText));

}...reads a line of code Microsoft style (0xA 0xD) from the serial port buffer. The reality is the buffer could contain the middle of a line or 2 and 1/3 lines. Your code needs to handle these possibilities in the "DisplayText" event handler.

Happy Threading

Adam
10-31-2009, 12:02 AM
Ok, what MikeG said makes sense. Notice that the data starts with "!!!" and ends with "***". You can use those to piece together a complete string that is spread over multiple events.

MikeG
10-31-2009, 08:31 AM
You might consider using another read method like readexisting or reading a specific number of bytes. When you read the serial data check the position of "!!!" and "***". Now you can determine if you have the tail of one response, the head of another, or neither.

At some point you'll get a start without and end. When that happens place the partial response in a temp object. On successive serial buffer reads determine what you have and build the temp object accordinly. Once the temp variable fits your response pattern... do whatever processing you need. Be careful of threading errors and receiving more than one response pattern in the serial buffer.

MikeG
10-31-2009, 09:25 AM
Also be careful with the ReadLine method. ReadLine waits until a newline is detected but you have no idea how many newlines are in the buffer. You can end up with left over response values. Then at some point during runtime you could get a buffer overrun.

nagmier
10-31-2009, 08:20 PM
Thanks guys that helps out alot.. I'll try a few different error checking routines and I'll try and piece something together...

My main concern is bad coding I wanted to make sure I wasn't trying the impossible... Thanks again for the direction everyone!