C ++ - обеспечение полного последовательного ответа - PullRequest
1 голос
/ 10 октября 2011

Я пытаюсь прочитать последовательный ответ от устройства. Строка, которую я читаю, длинная, и мне нужна только ее часть. Чтобы добраться до нужной части строки, я использую std::string.substr(x,y);. Проблема, с которой я сталкиваюсь, однако, иногда я получаю ошибку исключения, потому что буфер, из которого я читаю, не имеет y символов. Вот код, который я сейчас использую для чтения значений:

while(1)
{
char szBuff[50+1] = {0};
char wzBuff[14] = {"AT+CSQ\r"};

DWORD dZBytesRead = 0;
DWORD dwBytesRead = 0;


if(!WriteFile(hSerial, wzBuff, 7, &dZBytesRead, NULL))
    std::cout << "Write error";

if(!ReadFile(hSerial, szBuff, 50, &dwBytesRead, NULL))
    std::cout << "Read Error";



std:: cout << szBuff;
std::string test = std::string(szBuff).substr(8,10);
std::cout << test;
Sleep(500);

Я выдаю команду "AT + CSQ". Это возвращает:

N, N

OK

Возвращает два целочисленных значения, разделенных запятой, за которой следует новая строка, после которой следует «ОК».

Мой вопрос: как я могу убедиться, что я прочитал все значения из последовательного порта перед захватом подстроки? Из того, что я понимаю, последний полученный символ должен быть новой строкой.

Ответы [ 4 ]

1 голос
/ 10 октября 2011

Интерфейс вашей функции ReadFile обеспечивает количество прочитанных байтов. Если вы знаете ожидаемую длину, вам следует зацикливаться на попытке чтения из файла (возможно, дескриптора порта) до тех пор, пока не будет прочитано ожидаемое количество байтов.

Если длина ответа неизвестна, вам, возможно, придется прочитать и проверить в буфере чтения, был ли прочитан токен-разделитель (в этом случае ваш протокол указывает на возможность использования новой строки). определить EOM - конец сообщения)

Если вы можете использовать другие библиотеки, я бы подумал об использовании boost::asio и функциональности read_until (или эквивалентных в любых библиотеках, которые вы используете). Хотя код для управления этим не является ракетостроением, в большинстве случаев нет смысла изобретать велосипед.

0 голосов
/ 19 марта 2017

Старый вопрос, но я изменил код @Eli Iser на:

while (ReadFile(hSerial, myBigBuff + indexToBuff, 1, &dwBytesRead, NULL)) {
            if (strchr(myBigBuff, '-') != NULL || dwBytesRead < 1)
                break;
            // Move forward in the buffer. This should be done cyclically
            indexToBuff += dwBytesRead; 
        }
        if (indexToBuff != 0) {
            //Do whatever with the code, it received successfully.
        }
0 голосов
/ 10 октября 2011

Как вы сказали в последней строке, вы знаете, что терминатор для ответа - это символ новой строки.Вам нужно читать с серийного номера, пока вы не получите новую строку где-то на входе.Все, что вы получили от предыдущей новой строки до текущей новой строки, является ответом, а все, что находится после текущей новой строки, является частью следующего ответа.Это достигается за счет чтения в цикле, обработки каждого ответа, как он обнаружен:

char* myBigBuff;
int indexToBuff = 0;
int startNewLine = 0;

while (ReadFile(hSerial, myBigBuff + indexToBuff, 100, &dwBytesRead, NULL))
{
    if (strchr(myBigBuff, '\n') != NULL)
    {
        handleResponse(myBigBuff + startNewLine, indexToBuff + dwBytesRead);
        startNewLine = indexToBuff + dwBytesRead;
    }

    // Move forward in the buffer. This should be done cyclically
    indexToBuff += dwBytesRead; 
}

Это основная идея.Вы должны обрабатывать оставленные символы за кадром любым способом, который вы выберете (циклический буфер, простое копирование во временный массив и т. Д.)

0 голосов
/ 10 октября 2011

Вы должны использовать ReadFile для чтения определенного количества байтов за цикл в ваш буфер. Этот буфер должен быть заполнен до тех пор, пока ReadFile не прочитает 0 байтов, вы не наберете свои \n или \r\n символов или не заполните свой буфер до максимума.

Как только вы это сделаете, вам не понадобится substr ваша строка, и вы сможете перебирать свой буфер символов.

Например,

while (awaitResponse) {
    ReadFile(hSerial, szBuff, 50, &dwBytesRead, NULL);

    if (dwBytesRead != 0) {
        // move memory from szBuff to your class member (e.g. mySerialBuff)

    } else {
        // nothing to read
        if (buffCounter > 0) {
            // process buffer
        }
        else {
            // zero out all buffers
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...