Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Эффективно парсить принимаемые ответы модема
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
sigmaN
Доброго времени суток, господа.

Хочу поинтересоваться как лучше всего организовать работу с модемом(а точнее с моб.телом).
Я объявил структуру, которая описывает состояние телефона
Код
typedef struct {
    unsigned int ATState;
    unsigned int ATError; //Последний код ATResult
    unsigned int UserState;
    unsigned int CallState;
    unsigned int KeyPressed;
    unsigned char* CallNumber; //Номер телефона звонящего или вызываемого абонента
    unsigned int  MenuID;
}PhoneState;

Для каждого State задефайнен набор констант...

Планирую сделать 2 логические части, одна часть принимает данные с тела и соответствующим образом меняет поля структуры, вторая часть выполняет определенные действия, "глядя" только на структуру.
Естественно первая часть, сделав хотя-бы одно изменение, сразу вызывает вторую, чтобы та вызвала определённую реакцию на изменение состояния тела.

Вопрос стоит в эффективном написании первой части,которая принимает данные и парсит их в структуру.
Нужен эффективный алгоритм, позволяющий на лету выявлять нужные строки в непрерывном потоке.
Особенно это актуально в режиме данных, когда нужно поймать \r\nNO CARRIER\r\n в случае разрыва коннекта. Да и вообще.

Посоветуйте что-нибудь по фильтрации
или может быть по концепции в общем.
zltigo
Цитата(sigmaN @ Sep 1 2008, 21:37) *
Особенно это актуально в режиме данных, когда нужно поймать \r\nNO CARRIER\r\n в случае разрыва коннекта.

Это вообще-то ловят по отсутствию/наличию CD
Цитата
Да и вообще.

А "вообще" и не надо, поскольку поблемы нет.
sigmaN
Есть только Rx и Tx, нет в моём распоряжении CD.

Ну если бы не было проблемы - я бы не просил помощи ))
Даже не помощи, совет нужен спеца с опытом.

Я то наваяю чё-ниить по любому, но не хотелось-бы изобретать велосипед лишний раз
ReAl
Цитата(sigmaN @ Sep 1 2008, 23:19) *
Я то наваяю чё-ниить по любому, но не хотелось-бы изобретать велосипед лишний раз
Ну вот что-то наваял навскидку
Код
typedef struct {
    const char * const string;
    const char * current;
} entry;

entry table[] =
{
    { "NO CARRIER", 0},
    { "ERROR", 0},
}

void init()
{
    entry *ent = table;

    for( int i = 0; i < sizeof(table)/sizeof(table[0]); ++i, ++ent)
        ent->current = ent->string;
}

// возвращает номер последнего найденного вхождения или -1
int check( char ch)
{
    entry *ent = table;

    int found = -1;

    for( int i = 0; i < sizeof(table)/sizeof(table[0]); ++i, ++ent) {
        char *p = ent->current;
        if( ch == *p++ ) {
            if(*p == 0) {
                found = i;
                p = ent->string; // опять готовы принимать это слово
            }
        } else {
            p = ent->string; // начнём сначала, раз не совпало
        }
        ent->current = p;
    }
    return found;
}

"возвращает последнее" - это в смысле если в таблице есть
Код
"ERROR"
"ROR"

то на поток "EEERROR" выдаст номер для "ROR", так как оно последнее будет по порядку просмотра таблицы.

Или так:
Код
typedef struct {
    const char * const string;
    const char * current;
} entry;

entry table[] =
{
    { "NO CARRIER", 0},
    { "ERROR", 0},
    { 0, 0}
}

void init()
{
    entry *ent = table;

    while( ent->string ) {
        ent->current = ent->string;
        ++ent;
    }
}

int check( char ch)
{
    entry *ent = table;

    int found = -1;

    while( ent->string) {
        char *p = ent->current;
        if( ch == *p++ ) {
            if(*p == 0) {
                found = i;
                p = ent->string;
            }
        } else {
            p = ent->string;
        }
        ent->current = p;
        ++ent;
    }
    return found;
}

но это мало повлияет на скорость, да и на объём кода тоже.
sigmaN
ReAl, огромное спасибо за код!
Полностью понимаю Линуса, который говорит: "show me the code"
Код это лучший ответ на вопрос программиста:-)
zltigo
Цитата(ReAl @ Sep 1 2008, 23:05) *
Ну вот что-то наваял навскидку

Сразу верю, что работоспособно, но если кто-то не удосужился CD использовать, то "NO CARRIER" ищется не в потоке, а только в случае таймаута в потоке/ошибки в протоколе верхнего уровня поиском назад от CR.Поток при этом без всяких тормозов складыватся в буфер, а поиски идут во время битья баклуш. С прочими сообщениями и того проще - они возникают на самом деле не по инициативе модема. Жевать весь поток - лобовое решение - очень понятное, но не эффективное.
DpInRock
Согласен с zltigo. Хуже того, строка NO CARRIER имеет полное право легально находится во входном потоке. И при этом никаких потерь несущей... К примеру, при передаче данного текста...

А проверить, в случае ахтунга, в каком состоянии находится модем без CD ( да и без анализа буфера)- способов масса. К примеру "+++".
sigmaN
Цитата
С прочими сообщениями и того проще - они возникают на самом деле не по инициативе модема.

Возникают и по инициативе модема(а точнее телефона).
Не в режиме данных, конечно.
К примеру, пользователь вызывает абонента - в порт телефон стучит номер телефона, по которому звонит абонент(SonyEricsson Call monitor)
И мне это нужно ловить. Также, при входящем звонке будет сначала сообщение Callмонитора с номером звонящего, а потом RING.
Это тоже надо ловить и парсить. Может быть в процессе передачи данных и нет смысла всё время искать NO CARRIER, но вот в режиме команд мне будут приходить данные(причём целыми пачками) по инициативе телефона.
В потоке NO CARRIER встретится никак не может в силу специфики передаваемых данных.

Примерно прикину на сколько решение в лоб займёт проц.
Скорость у меня всего 9600..Может быть прокатит и так )
ReAl
Цитата(zltigo @ Sep 2 2008, 01:22) *
Сразу верю, что работоспособно, но если кто-то не удосужился CD использовать,
"а мне пофиг", я отвечал на часть вопроса "как эффективнео парсить" smile.gif (типа Райкинского "кто сшил костюм?" - "к пуговицам претензии есть?" - "нет, пришито намертво, не оторвёшь" wink.gif )

Цитата(zltigo @ Sep 2 2008, 01:22) *
"NO CARRIER" ищется не в потоке, а только в случае таймаута в потоке/ошибки в протоколе верхнего уровня поиском назад от CR.
Ну значит занести в таблицу
Код
"REIRRAC ON"

и на случай ещё чего-то в буфере после NO CARRIER топать указателем
Код
ptr = buffer_end;
...
check( *ptr--)

smile.gif

Ну не имею я опыта непосредственно поток модема смотреть, глубже логов dmail/DOS UUPC не рылся никогда.
А как вопрошавший применит довольно эффективный, надеюсь, код поиска разных подстрок - его проблемы.
DpInRock
Цитата
В потоке NO CARRIER встретится никак не может в силу специфики передаваемых данных


Цитата
Особенно это актуально в режиме данных, когда нужно поймать \r\nNO CARRIER\r\n в случае разрыва коннекта.


Это ваши слова. Это вы ищите это слово во входном потоке. А люди руководствуются протокольными таймаутами.

Модем вообще вам может ничего не выдавать по причине удара по нему кирпичом. И по массе других причин.
sigmaN
Цитата
Модем вообще вам может ничего не выдавать по причине удара по нему кирпичом. И по массе других причин.

Таймаут в протоколе уже взят на вооружение )))
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.