How to copy a data snippet from a string?

Asked

Viewed 650 times

-2

I’m starting in the programming area and I’m developing a serial communication application, where, I receive data strings with some information in which I need to separate them by categories, for example:

A connection string : STX8abcdefETX<CRC>

A string of Parameters: STXNabcdefETX<CRC>

where, the CRC has two characters.

What I need to do is monitor the serial port and when the string arrives, identify the start (STX), continue reading the same until you find the (ETX), count two more characters and insert into one listbox, the content read.

Strings come all together, for example:

STX8abcdefETX<CRC>STXNabcdefETX<CRC>

Which method to use ? Because I have already used Substring, split, but as sizes may vary, sometimes I get the content wrong.

Follow modified code (SOLVED).

    while (true)
        {
            posicaoSTX = bufferRx.IndexOf("STX");

            if (posicaoSTX != -1)
            {
                posicaoETX = bufferRx.IndexOf("ETX");
                if (posicaoETX != -1 && (bufferRx.Length >= (posicaoETX + 5)))
                {
                    posicaoETX += 3;
                    stringFinal = bufferRx.Substring(posicaoSTX, (posicaoETX - posicaoSTX) + 2);
                    bufferRx = bufferRx.Remove(0, posicaoETX);
                    trataProtocolo(stringFinal);
                }
                else break;
            }
            else break;
        }
  • you are receiving this STX as string, or the STX char ? char STX = '\u0002'; ??

  • Good afternoon Francisco. I receive serial data as string.

  • you have an example string of a complete communication cycle ?

  • The best way to do this is with the Regex.Split, since I’m a bit of a layman with regex, I won’t risk making an answer just yet, but here’s the tip.

  • So that means that after the whole string has 2 characters left?

  • Yes, after all ETX, it has two characters, however, they are part of the protocol and should be considered.

Show 1 more comment

3 answers

0

Surely there are several ways to do this, I tried to make a didactic code so you understand the logic, I hope I can help:

        //Exemplo da mensagem recebida
        string mensagem = "STXMEnsagem1ETXSTXMEnsagem2ETXSTXMEnsagem3ETXSTXMEnsagem4ETXSTXMEnsagem5ETXSTXMEnsagem6ETX";
        //Lista para armazenar as mensagens
        List<string> mensagens = new List<string>();


        while (mensagem.Length > 0)
        {
            //Encontra o próximo STX
            int i1 = mensagem.IndexOf("STX");
            //Encontra o próximo ETX a partir do STX anterior
            int i2 = mensagem.IndexOf("ETX",i1);


            //Pega a SubString
            string sub = mensagem.Substring(i1+3,i2-3);
            //Retira a parte já processada da mensagem
            mensagem = mensagem.Remove(0, sub.Length+6);
            //Adiciona a mensagem à lista de mensagens
            mensagens.Add(sub);
        }

        //Quantidade de mensagens recebidas
        int count = mensagens.Count;

        //Imprime as mensagens na tela
        foreach (string s in mensagens)
            Console.WriteLine(s);

ps. I have not made any error handling.

I repeat: I believe that the STX and ETX should be just a char, thus avoiding the calculations +3, -3, +6, etc.

  • Good afternoon to all! Thank you for your support so far. The ideal would be a solution similar to Rovann, which reads the beginning and end of the string, but the string that will be inserted in my listbox, should contain the "STX" <data> and the "ETX" + <CRC> 2 characters.Ex of a received string: STX80000000000ETX{-STX60000000000ETX ~, for example, should be inserted into the listbox in this way: (line1) STX80000000000ETX{- and in (Linha2) STX60000000000ETX ~. However, when the string is too large, 310 characters, and comes along with others, for example, gives Startindex error, is outside the string.

  • @Lapnasc I believe that Startindex errors can be solved only in mensagem.Substring(i1+3,i2-3) and mensagem.Remove(0, sub.Length+6)

  • Rovann, I’ve already adjusted these values and the application even works well, I can get the strings the way I need them. I debugged the routine and realized that it gives the error whenever a "dirt" comes through the serial port before a valid string, example: "#0 " before the string and then the string. You can read the serial port only when you receive an STX, for example?

  • that \0 is the string ending in C, you can deal with an if or give a replace by removing all at once: mensagem = mensagem.Replace("\0","");

  • Rovann, I created a form to test the strings, and I realized that the error occurs whenever, it receives a string that does not even have STX and ETX, whatever the size and when it does not have in the string after ETX the two characters that refer to CRC. As I changed the calculations of the lines you mentioned, the error occurs with these characteristics.

  • yes, as I mentioned in the answer, I did not do any error handling, in case the string does not have the start and end indicators, I1 and I2 will always give -1, causing errors. The ideal is to define a protocol for communication, so that you can accept or refuse incoming messages and treat them correctly

  • I get it. I tried the solution indicated by Francisco, using Regex, but when the string is added to the listbox, a blank line is created for each inserted string.

  • then it becomes easy to treat the array by removing the blank lines only

  • After several attempts...rsrs..., I was able to adjust the code to receive the data. I changed the code I sent earlier to the code that is already running and working 100%... The same was also inserted here in the forum to help others who may also have the same problem...valeu pela força..

  • @Lapnasc good that solved, if any of the answers helped you, do not forget to mark it as an answer and/ or evaluate. Hugs

Show 5 more comments

0

I believe the best way to do that is with Regex, see how it would look:

string[] arr = Regex.Split(valores, @"(?=STX)");
arr =  arr.Where(x => !string.IsNullOrEmpty(x)).ToArray();
listBox1.Items.AddRange(arr);

Don’t forget to add the namespaces to the project:

using System.Linq;
using System.Text.RegularExpressions;

See working on Ideone.

See also the documentation of Regex to better understand how it works.

  • Good morning Francisco. I tried your option, but when the data is inserted in the listbox, also create a blank line between the strings. You can filter that?

  • Yes, it’s easy to do this using LINQ, I edited my answer, give a look.

0

One more way to do it:

 public IEnumerable<string> ParseMessages( string messages )
 {
     //Separa o texto por STX....ETX
     var msgs = System.Text.RegularExpressions.Regex.Matches( messages, "STX.+?ETX" );

     foreach( var message in msgs ) 
         yield return message.Value;

     //Pega os dois ultimos digitos do crc
     yield return messages.Substring( messages.Length - 2 );
 }
  • Good afternoon to all!

  • Good afternoon to all! Thank you for your support so far. The ideal would be a solution similar to Rovann, which reads the beginning and end of the string, but the string that will be inserted in my listbox, should contain the "STX" <data> and the "ETX" + <CRC> 2 characters.Ex of a received string: STX80000000000ETX{-STX60000000000ETX ~, for example, should be inserted into the listbox in this way: (line1) STX80000000000ETX{- and in (Linha2) STX60000000000ETX ~. However, when the string is too large, 310 characters, for example, gives Startindex error, Parameter cannot be negative, etc..

  • @Lapnasc edited response.

  • Good afternoon Dunno, as I’m new to this programming business.rsr.. how do I apply your routine? I’m using a form with a textbox to insert the strings and a button that in the click event adds the string in the listbox. Thanks.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.