Проблема в том, что событие DataReceived возникает, как только вы получили данные по последовательному порту. Там не может быть полной записи; объект SerialPort не имеет понятия, что вы считаете «достаточным», чтобы быть значительным или работоспособным.
Обычным решением является поддержание другого «буфера» полученных данных, содержащих любые данные, которые вы признали неполными. Когда данные поступают через порт и срабатывает событие, он должен сначала взять то, что находится в буфере, и добавить его к тому, что вы уже получили. Затем вы должны начать с начала этого буфера данных и проверить полученные данные, ища известные образцы атомных «кусков» данных, имеющих для вас значение; например, скажем, первое, что вы получаете, это "ID: 12"
. Вы берете это, помещаете его в буфер, затем просматриваете буфер, ища шаблон, определенный регулярным выражением "ID: \d*? "
. Поскольку конечное пространство отсутствует в вашем буфере, ваш шаблон не находит ничего значимого, и теперь вы знаете, что не получили полного сообщения.
Затем, при следующем поднятии события DataReceived, вы вытаскиваете "453 Sta"
из последовательного буфера. Вы добавляете его к тому, что у вас уже есть, и получаете "ID:12453 Sta"
, и когда вы применяете регулярное выражение, вы получаете совпадение «ID: 12345». Вы передаете это в метод для дальнейшей обработки (отобразите консоль, возможно), и удалите ту же строку из передней части буфера, оставив «Sta». Сканирование снова, вы не найдете ничего интересного, поэтому вы оставляете то, что у вас есть, и цикл повторяется. Данные aws продолжают поступать. Очевидно, вы будете тестировать больше шаблонов, чем только шаблон ID; вы можете найти целую «строку», которую вы ожидаете получить, например, "ID: \d*? State: \w{2} "
. Вы даже можете хранить данные в своем буфере, пока у вас нет обеих строк для записи: "ID:\d*? State:\w{2} Zip:\d{5} StreetType:\w*? "
.
В любом случае вам необходимо определить, являются ли получаемые данные надежной «фиксированной длиной» (что означает, что каждая строка определенного типа всегда будет иметь одинаковое количество байтов или символов) или надежно «ограничена», (это означает, что будет некоторая комбинация символов или символов, которая всегда отделяет важные элементы данных). Если ни одно из них не применимо, может быть очень сложно разобрать данные в однополевые куски.
Вот пример основан на том, что у вас есть уже:
private static StringBuilder receiveBuffer = new StringBuilder();
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);
//here's the difference; append what you have to the buffer, then check it front-to-back
//for known patterns indicating fields
receiveBuffer.Append(s);
var regex = new Regex(@"(ID:\d*? State:\w{2} Zip:\d{5} StreetType:\w*?)");
Match match;
do{
match = regex.Match(receiveBuffer.ToString());
if(match.Success)
{
//"Process" the significant chunk of data
Console.WriteLine(match.Captures[0].Value);
//remove what we've processed from the StringBuilder.
receiveBuffer.Remove(match.Captures[0].Index, match.Captures[0].Length);
}
} while (match.Success);
}
Есть ли разделитель в конце каждой записи? Распечатайте числовые байтовые значения и посмотрите особенно после отправки последней записи. Данные поступают как непрерывный поток, но, надеюсь, протокол был разработан с каким-то символом завершения (возврат каретки был бы типичным, но, вероятно, это не так, поскольку ReadLine не сработал для вас). – Justin