правильный парсинг данных приходящих с com порта.

Помидор
Дата: 10.07.2017 06:49:16
Добрый день форумчане программисты. Нужна ваша помощь.
Устройство подключено к компьютеру через com порт. Данные получаю, с этим проблем нету.
Код читается этим блоком.
#region comPort_DataReceived
        /// <summary>
        /// method that will be called when theres data waiting in the buffer
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            //determine the mode the user selected (binary/string)
            switch (CurrentTransmissionType)
            {
                //user chose string
                case TransmissionType.Text:
                    //read data waiting in the buffer
                    string msg = comPort.ReadExisting();
                    //display the data to the user
                    DisplayData(MessageType.Incoming, msg + "\n");
                    break;
                //user chose binary
                case TransmissionType.Hex:
                    //retrieve number of bytes in the buffer
                    int bytes = comPort.BytesToRead;
                    //create a byte array to hold the awaiting data
                    byte[] comBuffer = new byte[bytes];
                    //read the data and store it
                    comPort.Read(comBuffer, 0, bytes);
                    //display the data to the user
                    DisplayData(MessageType.Incoming, ByteToHex(comBuffer) + "\n");
                    break;
                default:
                    //read data waiting in the buffer
                    string str = comPort.ReadExisting();
                    //display the data to the user
                    DisplayData(MessageType.Incoming, str + "\n");
                    break;
            }
        }
        #endregion


А именно этой строкой
//read data waiting in the buffer
                    string msg = comPort.ReadExisting();
                    //display the data to the user
                    DisplayData(MessageType.Incoming, msg + "\n");


Вот как выглядит одно целое сообщение отправляемое устройством

QDSNO 40
DATE 20170626
TIME 113900
DOC
OPID 0
MODE 32
WRN 0
PM1 11
PM2 131
RM1 33

WM1 19
WM2 41
WM3 65
PART 5
EM1 41
BM1 59
PARN 29
P01 5,58 0
P02 4,90 0
P03 129 0
P04 37,31 0
P05 76 0
P06 26,2 2
P07 345 0
{!!!!!}
P08 244 0
P09 0,17 0
P10 6,9 2
P11 8,0 0
P12 35,2 0
P13 44,5 1
P14 14,1 0
P15 3,11 0
P16 0,47 0
P17 1,85 2
P18 55,8 1
P19 8,
{!!!!!}
5 1
P20 33,1 2
P21 8,0 0
P22 5,0 2
P24 0,08 0
P25 0,06 0
P26 1,5 0
P27 1,1 0
P28 4900 0
P29 4900 0
AGE 0

Там где видите знак {!!!!!} означает что буфер чтения заполнился и данные считались в переменную. Это произошло в три раза, то есть одно сообщение считалось тремя блоками. А если больше одного сообщения отправит устройство, то в буфер могут попасть конец одного сообщения и начала другого сообщения.
Как мне правильно распарсить данные, найти нужный момент для этого? Ведь нужное мне сообщение разделилось в 3 три блока, а размер сообщения пока неизвестно.
Любые идеи, размышления будут полезны. У меня самого опыта работы с com портами нету. Но работу надо сделать.
Barlone
Дата: 10.07.2017 09:18:09
Спросить у разработчиков устройства (найти в документации по устройству), как определить конец сообщения для этого конкретного устройства...
Dima T
Дата: 10.07.2017 10:43:22
COM-порт выдает поток байт, а дальше сам режь/клей сообщения.
Полученный блок данных может обрываться на любом символе.
Как понимаю это текст с переводами строк, парси буфер построчно выискивая "\n". Если буфер кончился, а "\n" не было, значит это часть строки, ставь ее в начало следующего буфера и дальше читай из порта.
Siemargl
Дата: 10.07.2017 11:05:01
Помидор,

Изучить технологию конечного автомата. Помнить указатель на буфер и шаг парсинга независимо от состояния читающего потока.
Помидор
Дата: 10.07.2017 11:23:14
Barlone
Спросить у разработчиков устройства (найти в документации по устройству), как определить конец сообщения для этого конкретного устройства...

Сейчас занимаюсь этим, но они точно в эту неделю не ответят. А хочется быстрее, время поджимает.

Dima T
COM-порт выдает поток байт, а дальше сам режь/клей сообщения.
Полученный блок данных может обрываться на любом символе.
Как понимаю это текст с переводами строк, парси буфер построчно выискивая "\n". Если буфер кончился, а "\n" не было, значит это часть строки, ставь ее в начало следующего буфера и дальше читай из порта.

Текст перевода строки я вставляю сам, а чтобы здесь это было заметно я обозначил конец буфера знаком {!!!!!}.
Вашу идею понял, буду искать конец сообщения. Она у меня выходила как абракадабра, до него есть строка age. Получается можно ориентироваться на это поле. Попробую.
Помидор
Дата: 10.07.2017 11:33:43
Siemargl
Помидор,

Изучить технологию конечного автомата. Помнить указатель на буфер и шаг парсинга независимо от состояния читающего потока.

Попробую. Хотел быстрым наскоком, ничего не понял.
Akina
Дата: 10.07.2017 11:39:59
Помидор
А если больше одного сообщения отправит устройство, то в буфер могут попасть конец одного сообщения и начала другого сообщения.
Ну обычно устройства предпочитают отправлять данные в некоем предопределённом порядке... и зачастую этого достаточно для идентификации границы пакета данных. Тупо каждому полю пакета ставим в соответствие некий внутренний псевдономер, и уменьшение этого номера для текущего поля по сравнению с предыдущим означает, что пройдена граница пакета данных. Это даже при условии, что в пакете отсутствуют поля и/или маркеры начала/конца пакета.
Помидор
Дата: 10.07.2017 15:38:56
Вот полное сообщение.

VDSNO 120
DATE 20170707
TIME 112100
SID 17
PID 2074
NAME
BIRTH 00000000
SEX 0
DOC
OPID 0
MODE 32
WRN 0
PM1 11
PM2 158
RM1 40
WM1 17
WM2 42
WM3 67
PART 5
EM1 42
BM1 59
PARN 29
P01 5,01 0
P02 5,17 0
P03 160 0
P04 45,42 0
P05 88 0
P06 31,1 0
P07 353 1
P08 220 0
P09 0,20 0
P10 9,1 0
P11 13,1 0
P12 41,0 0
P13 49,2 1
P14 13,2 0
P15 1,20 2
P16 0,31 0
P17 3,42 0
P18 23,9 2
P19 6,1 0
P20 68,2 0
P21 8,0 0
P22 5,0 2
P24 0,04 0
P25 0,05 0
P26 0,7 0
P27 1,0 0
P28 4900 0
P29 4900 0
AGE 0
1F

Вроде есть начало (VDSNO 120) и конец (1F) сообщения. Только что они значат и как их ловить?
wadman
Дата: 10.07.2017 16:07:11
Помидор
Вроде есть начало (VDSNO 120) и конец (1F) сообщения.

Скорее VD и 1F
Помидор
Только что они значат и как их ловить?

Алгоритм следующий:
1. Читаешь, пока не поймаешь [начало]
2. Очистка приемного буфера
3. Читаешь и складываешь в буфер, пока не поймаешь [конец]
4. Передаешь буфер на обработку (можно без символов [начало] и [конец])
5. Переход к п.1