0

Hello I'm trying to find best solution for continuously reading serial-port buffer and parsing data to array, continuously string form serial-port looks like this :

"...G 130 g\r\nG 130 g\r\nG 124 g\r\nG 124 g\r\nG 124 g\r\nG... "

The main idea is read for exaple last 3 data from serial-port broadcasting string, parse to double array [124.0; 124.0; 124.0] and comapre if equals.

Now I'm using this simple code but it is not enough fast :

_serialPortMainForm.DataReceived += new SerialDataReceivedEventHandler(Port_DataReceived);

.....

void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                byte[] data = new byte[_serialPortMainForm.BytesToRead];
                _serialPortMainForm.Read(data, 0, data.Length);
                string str = Encoding.ASCII.GetString(data);
                RawSerialPortData += str;
                if (RawSerialPortData.Length > Properties.Settings.Default.BufferSize) {
                    ProcessSerialPortData(RawSerialPortData);
                    RawSerialPortData = "";
                }
            }

And parsing data like this :

public void ProcessSerialPortData( string DataToProcess) {
            int count = 0;
            string PostFix = "";

            DataToProcess = DataToProcess.Substring(DataToProcess.IndexOf('G') + 1);
            DataToProcess = DataToProcess.Replace(" ", "");
            DataToProcess = DataToProcess.Replace(Environment.NewLine, "|");

            foreach (char c in DataToProcess) if (c == '|') count++;
            ProcessedData = new double[count-1];

            DataToProcess = DataToProcess.Replace("G", "");

            if (DataToProcess.Contains("kg")) { PostFix = "kg"; DataToProcess = DataToProcess.Replace("kg", ""); }
            if (DataToProcess.Contains("g")) { PostFix = "g"; DataToProcess = DataToProcess.Replace("g", ""); }

            UnitsController(PostFix);

            DataToProcess = DataToProcess.Replace(".", ",");
            string[] SplitData = DataToProcess.Split('|');

            int j = 0;
            while (j < count - 1) {

                Double.TryParse(SplitData[j], out ProcessedData[j]);
                j++;
            }
        }

Kg are irelevant for this situation because grams are enough for this situation

Have somenone any idea or simple and best solution how do this better and faster ??

7
  • I assume the buffer size is enough to hold three readings? Commented Jan 8, 2020 at 21:35
  • Also, is it always the same PostFix for all measurements? Or can it vary between measurements? Commented Jan 8, 2020 at 21:50
  • buffer holds aproximetly 10 readings... The data from serial port are stream, only numbers are changes postfix is same for all measurments.. Commented Jan 8, 2020 at 21:58
  • code works widouth any issue but I thing that is not the best way how to parse data from stream. Because as you can see I copy part of stream every "Properties.Settings.Default.BufferSize" now it is set to 100 ... Commented Jan 8, 2020 at 22:02
  • I just posted an answer. Take a look. :-) Commented Jan 8, 2020 at 22:02

1 Answer 1

1

Making certain assumptions about the string in the buffer, one could extract all values using Regex.

Declare a global variable outside the method and compile the Regex for faster results:

Regex _regex = new Regex(@"\d+\s+\w+", RegexOptions.Compiled);

Then in your method, use the following to extract all the values:

var matches = _regex.Matches(DataToProcess)
    .Cast<Match>()
    .Select(m => 
    {
        var parts = m.Value.Split(' ');
        return new { Value = parts[0], Unit = parts[1] };
    });

//This is just for you to see the results in the console.
foreach (var value in matches)
{
    Console.WriteLine(value);
}

Assuming DataToProcess contains this:

var DataToProcess = @"G130 g\r\nG 130 g\r\nG 124 g\r\nG 124 g\r\nG 124 g\r\n";

This would yield the following in the console:

{ Value = 130, Unit = g }

{ Value = 130, Unit = g }

{ Value = 124, Unit = g }

{ Value = 124, Unit = g }

{ Value = 124, Unit = g }

You can then use this enumeration to test for units, values, etc.

If you need the values as an array of doubles, just use:

var ProcessedData = matches.Select(m => Convert.ToDouble(m.Value)).ToArray();

Lastly, camelCase is usually preferred in C# for variable names and your code doesn't seem very thread-safe. Something to think about.

Sign up to request clarification or add additional context in comments.

3 Comments

Only values are enough, but is some possibility to convert string values to array of double values... something like ... TryParse ??
@Oliwer11: Sure. Just add a conversion to the last line. I will modify my answer.
@Oliwer11: My pleasure. :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.