Написал я парсер на ответ модема WaitOK(const char *S) . Работает исправно, но представляется мне кривым.
Во - первых это отдельная функция, где по таймеру ожидается ответ модема и основной поток не выполняется. Во - вторых получилось громоздко.
Код
int WaitOK(const char *S) {//Ожидание символа (*S) от модема
timer1.timerId=1;//таймера
int j;//Для копирования буфера
s8 *i=0;//Для strstr
int C = 5;//Ждем 5*3с
while (C){//Выполняется пока Сikl <> 0
eat1_02GetEvent(&flEventBuffer);//Проверка событий
switch(flEventBuffer.eventTyp) {//
case EVENT_TIMER://Событие - прерывание от таймера
if (flEventBuffer.eventData.timer_evt.timer_id == 1)//Если индекс таймера 1:
{ebdat8_01StartTimer(timer1); if (C) {C--;}
}//if (flEventBuffer.eventData.timer_evt.timer_id == 1)
break; //case EVENT_TIMER:
case EVENT_MODEMDATA://
if(flEventBuffer.eventData.modemdata_evt.type == MODEM_CMD){//Если есть ответ от модема
//Поиск символа в строке
i=(s8*)strstr((const char *)flEventBuffer.eventData.modemdata_evt.data,S);
if(i){C = 0;}//Если ответ есть - ВЫХОД
//Нижние три строчки кода должны быть именно здесь, поскольку в буфер складывается все до прихода строки *S Нужно для декодирования
for (j = 0; j < flEventBuffer.eventData.modemdata_evt.length; j++)//копирование буфера
{RecieveBuf[RecieveBufIndex]=flEventBuffer.eventData.modemdata_evt.data[j];//модема
if (RecieveBufIndex<250) {RecieveBufIndex++;}}
}//if(flEventBuffer.eventData.modemdata_evt.type == MODEM_CMD)
break;//EVENT_MODEMDATA:
default:
break;
}//switch(flEventBuffer.eventTyp)
}//while (C)
if (!i) {ErrLog("WaitOKNR\n",9);}
return (int)(i);
}
Написал я другой парсер с кольцевым буфером. В ветке case EVENT_MODEMDATA я заполняю кольцевой буфер, оъявленный глобально:
Код
char ModemRBUF[256]; //Кольцевой буфер приема ответов модема
int ModemRBUFTail=0; //Хвост кольцевого буфера модема
int ModemRBUFHead=0; //Голова кольцевого буфера модема
Код
{if(flEventBuffer.eventData.modemdata_evt.type == MODEM_CMD)//Если принят ответ
{int i;//
int length = flEventBuffer.eventData.modemdata_evt.length;//Длина принятой строки
char *string = (char *)flEventBuffer.eventData.modemdata_evt.data;//Данные в string
for (i=0; i<length; i++) {//Копирование содержимого
ModemRBUFTail = (ModemRBUFTail + 1)&255;//принятого буфера в
ModemRBUF[ModemRBUFTail] = string[i];}//кольцевой буфер. Вставить memcpy!!!
ebdat9_02SendToSerialPort(string, length);}//Вывод в порт 0
В основном потоке функцией if(read_line(ModemLBUF)) я проверяю наличие информации в кольцевом буфере и перекладываю если есть в линейный:
Код
while (TRUE){//Прием команд. printf("\n%s\n", buf); - Эхо
char *read_line(char buf[]); //Чтение в линейный буфер принятых символов
//Анализ приема строки от модема
if(read_line(ModemLBUF)) //read_line( buf ) читает в buf принятые символы
{parseCmd(ModemLBUF);}//Разбор принятой строки если read_line( buf ) <> 0
Если функция read_line( buf ) обнаруживает символы \n или \r в потоке, вызывается функция void parseCmd(char *cmd);
Код
char *read_line(char buf[])//
{ static int cnt = 0; //Индекс приёмного буфера
char c; //Принимаемый символ
if(ModemRBUFTail == ModemRBUFHead) //Если нет принятых символов
{return (char *) 0;} //Возвратить нуль
ModemRBUFTail = (ModemRBUFTail + 1) & 255; //Перемещение по кольцевому буферу
c = ModemRBUF[ModemRBUFTail]; //Читать символ
if(c == '\n' || c == '\r') //Если принято 0xD или 0xA:
{ buf[cnt] = 0; //записываем ноль в конец принятой строки в буфере
cnt = 0; //Обнуляем счётчик
return buf;} //Возвращаем указатель на буфер
else //Если не принято 0xD или 0xA:
{ if(cnt < 199) //80 - длина строки CONFIG_CONSOLE_LINE_SIZE. Если индекс буфера не вышел за предел
{buf[cnt++] = c;} //записать принятый символ в буфер.
return (char *) 0;} //
}//char *read_line(char buf[])
А в функцию parseCmd уже легко добавляется все что нужно:
Код
void parseCmd(char *cmd){ //cmd указывает на принятый с консоли буфер
char *pKey=0; //
if( cmd == 0 ) {return;} //Если принятая строка 0, выход
pKey = strstr(cmd,"OK"); //Поиск строки
if (pKey) {OKFLAG = 1; return;} //ответа ОК
pKey = strstr(cmd,"ERROR"); //Поиск строки
if (pKey) {ERRORFlag = 1; return;} //ответа ERROR
if (SendSMS==2) { //Если первая часть СМС уже отправлена
pKey = strstr(cmd,">"); //Ловим приглашение ввести СМС
if (pKey) {Skoba = 1;} //Если приглашение обнаружено
return;} //
if (CheckKey) { //Если включена проверка ключей
pKey = strstr(cmd, "FtvgQ6mELE5G6nQJSVxO7icAmfip7");//Поиск в линейном буфере
if (pKey) {KEY1 = 1; CheckKey = 0; return;} //KEY1 = 1 - отправка СМС
pKey = strstr(cmd, "AhY3K7E65L987NT6Z98w53sdr39"); //Поиск в линейном буфере
if (pKey) {KEY2 = 1; CheckKey = 0; return;} //KEY2 = 1 - Дозвон
pKey = strstr(cmd, "LQN45rMFR"); //Поиск в линейном буфере
if (pKey) {KEY3 = 1; CheckKey = 0; return;} //KEY3 = 1 - снятие с охраны
}//if (CheckKey)
Преимущество такого метода - гибкость и отсутствие зацикливания. Если кто расскажет про недостатки - буду благодарен.
Прямо беда с этими комментариями. Никак ровно не получается.
Сообщение отредактировал Димон Безпарольный - Oct 7 2014, 15:10