|
SIM900. Прием команд от TCP сервера., Как исключить коллизии в порту при приеме внешних команд? |
|
|
|
Apr 22 2014, 16:50
|
Участник

Группа: Участник
Сообщений: 29
Регистрация: 12-04-14
Пользователь №: 81 340

|
Здравствуйте!
Разрабатываю устройство, которое собирает различные данные с датчиков и с периодичностью в одну минуту отправляет их на сервер посредством SIM900. Использую обычный режим AT-команд, не transparent, то есть команда AT+CIPSEND, приходит приглашение ">", отсылаю в порт строку, дожидаюсь SEND OK, всё. В данный момент добился надежной отсылки данных. Встал вопрос приёма команд от сервера. Все в общем, работает, за исключением случая, когда микроконтроллер ждет ответа от SIM900 и в этот момент приходит команда от сервера. Аппаратное управление потоком в этом случае вряд ли подойдет.. Подскажите, пожалуйста, кто как справился с этой проблемой?
|
|
|
|
3 страниц
1 2 3 >
|
 |
Ответов
(1 - 35)
|
Apr 23 2014, 03:57
|
Участник

Группа: Участник
Сообщений: 29
Регистрация: 12-04-14
Пользователь №: 81 340

|
Цитата(zebrox @ Apr 23 2014, 05:40)  Так понимаю, что процессор ожидает ответ от сима на какую-либо АТ команду?
Думаю у команды с сервера должен быть заголовок, по которому ее можно отличить от ответа сима. Выполнить ее, и дальше ждать ответа на АТ? Ну да, это понятно. У команды действительно есть заголовок, и, кроме этого, по этому признаку я помещаю эти команды в другой буфер для дальнейшего парсинга. Видите ли, у меня конец сообщения от SIM900 определяется по таймауту. То есть, после приема последнего символа ответа, таймер отсчитывает 2мс и поднимается флаг, что ответ готов. Если команда приходит во время ответа, когда SIM900 что-то кидает в порт, или во время этой задержки, то целостность ответа нарушается и, соответственно, парсер ответов не может распознать его. Вот в чем проблема.
|
|
|
|
|
Apr 23 2014, 05:57
|
Участник

Группа: Участник
Сообщений: 29
Регистрация: 12-04-14
Пользователь №: 81 340

|
Цитата(tdocs.su @ Apr 23 2014, 13:15)  Автомат конечный писать надо. Были проблемы когда-то давно с коммуникационной программой для двух модемов, только конечный автомат и позволил добиться устойчивой работы. Его ничем из "седла" не вышибить. Так у меня вся работа с модемом на конечных автоматах. Иначе с ним вообще невозможно работать. В общем, решил проблему "заплатками". Если команда от сервера приходит в неподходящий момент и возникает коллизия с ответом от модема, по таймауту ожидание ответа прекращается и программа выпадает в "диспетчер задач". И если команда не распозналась, сервер не получает подтверждения принятой команды и отсылает её вновь.
|
|
|
|
|
Apr 23 2014, 06:19
|
Частый гость
 
Группа: Участник
Сообщений: 143
Регистрация: 27-02-14
Из: Москва
Пользователь №: 80 728

|
Как-то странно... Ведь в автомате после отправки чего-либо в линию вы принудительно переводите его в новое состояние, в котором он ожидает конкретный ответ из линии, и никакой другой. Может, что-то не так делаете? См. личку. Не принимает ваш ящик личку. См. здесь - http://tdocs.su/4199
Сообщение отредактировал tdocs.su - Apr 23 2014, 06:22
--------------------
|
|
|
|
|
Apr 23 2014, 06:27
|
Участник

Группа: Участник
Сообщений: 29
Регистрация: 12-04-14
Пользователь №: 81 340

|
Цитата(tdocs.su @ Apr 23 2014, 14:19)  Как-то странно... Ведь в автомате после отправки чего-либо в линию вы принудительно переводите его в новое состояние, в котором он ожидает конкретный ответ из линии, и никакой другой. Может, что-то не так делаете? См. личку. Не принимает ваш ящик личку. См. здесь - http://tdocs.su/4199Спасибо, почитаю. Проблема-то как раз в том, что жду одно, а приходит другое ))
|
|
|
|
|
Apr 23 2014, 06:54
|
Частый гость
 
Группа: Участник
Сообщений: 143
Регистрация: 27-02-14
Из: Москва
Пользователь №: 80 728

|
Цитата(Иван Плетнев @ Apr 23 2014, 10:27)  Спасибо, почитаю.
Проблема-то как раз в том, что жду одно, а приходит другое )) Так вот автомат на другое и реагировать не должен вовсе. Если после перехода в case сразу задать ему новое состояние, он в нем и будет находиться и ждать только то, что надо, все прочее просто игнорировать.
--------------------
|
|
|
|
|
Apr 23 2014, 09:50
|
Участник

Группа: Участник
Сообщений: 29
Регистрация: 12-04-14
Пользователь №: 81 340

|
Все-таки не получается у меня в стандартном, командном режиме принимать сообщения от сервера без грабель. Буду пробовать transparent mode.
|
|
|
|
|
Apr 23 2014, 13:08
|
Частый гость
 
Группа: Участник
Сообщений: 143
Регистрация: 27-02-14
Из: Москва
Пользователь №: 80 728

|
Цитата(Иван Плетнев @ Apr 23 2014, 13:50)  Все-таки не получается у меня в стандартном, командном режиме принимать сообщения от сервера без грабель. Буду пробовать transparent mode. С утра я чё-та не догнал. А сейчас вспомнил детали той своей давней задачки. Обрисую. Было 2 компика с зухелом на каждом из них (через COM-порты) и поганейшая линия связи, чуть ли не АТС с шаговым искателем  В исходном положении модемы были инициализированы и выведены на режим лежачей трубы (командный режим). При вызове одного другим они "договаривались" друг с другом и из командного режима переходили в режим обмена данными. И тоже возникало что-то такое, когда один еще был в режиме обмена, а другой уже бросал трубу и переходил в командный. Тоже пробовал выводить ведомый модем по тайм-ауту, но все это было нестабильно, а к тому же еще были сложные временные требования - ведущий модем мог вызвать ведомого в любой случайный момент времени (напр. в момент инициализации ведомого или во время его попытки обмена данными). Т.е. тайм-аут работал ненадежно. Тут-то автомат и спас. Кажется, что у вас что-то подобное происходит сейчас. Невывод из командного режима в режим обмена данными. Позже еще приходилось решать задачку автоматом - каждое утро высасывать обновленный прайс-лист одного крупного поставщика компьютерной комплектухи, сравнивать его со своим локальным, обходить "старую", уже имеющуюся у нас комплектуху, а затем еще декодировать и конвертировать HTML-код так, чтобы поставщик не мог предъявить претензий по поводу таких ежедневных утренних краж  Задачка четко решалась автоматом. Короче, что-то у вас именно с переключением режимов. Если ждете данные, а приходит от сервера команда, то так и есть. Все вспомнил
--------------------
|
|
|
|
|
Apr 23 2014, 15:21
|
Участник

Группа: Участник
Сообщений: 29
Регистрация: 12-04-14
Пользователь №: 81 340

|
Цитата(zebrox @ Apr 23 2014, 21:18)  И почему конец сообщения определяется таймаутом? Почему не использовать последовательность CR LF? Потому что встречаются ответы модема, в которых есть и две последовательности CR LF, и три.
|
|
|
|
|
Apr 25 2014, 05:59
|
Частый гость
 
Группа: Участник
Сообщений: 125
Регистрация: 13-04-11
Из: Суровый Челябинск
Пользователь №: 64 337

|
Цитата(Иван Плетнев @ Apr 23 2014, 19:21)  Потому что встречаются ответы модема, в которых есть и две последовательности CR LF, и три. Это как раз не страшно. У меня идет работа с голосом (прием звонка, дозвон), SMS (прием и отправка) и GPRS (клиент) , плюс полный набор обслуживающих команд и всего в сумме получается не более 60 вариантов заголовков команд/ответов. Если делать не побуквенное сравнение, а более оптимизированный парсер, то получается быстрое автоматическое определение что пришло. Но с GPRS, да, в непрозрачном режиме приходится выкручиваться, а в прозрачном нет мультисокетов. Как вариант - реализовать режим мультиплексирования (CMUX). Было бы очень удобно, если бы китайцы добавили аналог +CIPRXGET, но не по незапрашиваемому ответу, а по запросу.
|
|
|
|
|
Apr 25 2014, 08:29
|
Профессионал
    
Группа: Свой
Сообщений: 1 241
Регистрация: 15-11-05
Из: Челябинск
Пользователь №: 10 882

|
Цитата(Иван Плетнев @ Apr 23 2014, 21:21)  Потому что встречаются ответы модема, в которых есть и две последовательности CR LF, и три. Самое первое правило - обрабатывать ВСЕ!!! последовательности от модема. Второе - последовательность AT команд четко регламетирована (см GSM 07.07 раздел 4). Заметьте, у всех команд стандарта есть final result code (чего не скажешь творчестве собственных расширений производителей модемов) Все что между - результат выполения команды. И еще есть ансинхронные ответы. Могут влезть куда угодно. либо пропускайте их, либо применяйте. НО РАСПОЗНАТЬ их надо!!
|
|
|
|
|
Apr 25 2014, 08:42
|
Частый гость
 
Группа: Участник
Сообщений: 143
Регистрация: 27-02-14
Из: Москва
Пользователь №: 80 728

|
Цитата(Alechek @ Apr 25 2014, 12:29)  Самое первое правило - обрабатывать ВСЕ!!! последовательности от модема.
Второе - последовательность AT команд четко регламетирована (см GSM 07.07 раздел 4). Заметьте, у всех команд стандарта есть final result code (чего не скажешь творчестве собственных расширений производителей модемов) Все что между - результат выполения команды.
И еще есть ансинхронные ответы. Могут влезть куда угодно. либо пропускайте их, либо применяйте. НО РАСПОЗНАТЬ их надо!! Однозначно! Все прочее (кроме автомата) - просто мертвому припарки. Выкрутиться не получится. Кстати, у оператора case в любом "языковом исполнении" всегда имеется свой else, позволяющий пропустить что-угодно как с распознаванием, так и без, если со стороны пришел некий "невнятный" и не вписывающийся в рамки протокола ответ - команда вместо данных и в таком духе.
--------------------
|
|
|
|
|
Apr 27 2014, 16:21
|
Участник

Группа: Участник
Сообщений: 29
Регистрация: 12-04-14
Пользователь №: 81 340

|
Цитата(tdocs.su @ Apr 25 2014, 16:42)  Однозначно! Все прочее (кроме автомата) - просто мертвому припарки. Выкрутиться не получится. Кстати, у оператора case в любом "языковом исполнении" всегда имеется свой else, позволяющий пропустить что-угодно как с распознаванием, так и без, если со стороны пришел некий "невнятный" и не вписывающийся в рамки протокола ответ - команда вместо данных и в таком духе. Немного не понял про else. Что Вы имеете ввиду? Цитата(zebrox @ Apr 25 2014, 23:24)  Тоже сначала делал обработку по таймауту. Все было очень плохо.
Потом перешел на обработку по концу строки. По приходу строки выставляю сигнал ртс, в основном цикле обрабатываю строку, убираю ртс когда процессор готов к приему. Имею проблему только с командой чтения имея, т.к. имей возвращается во второй строке и без заголовка. В этом случае обрабатываю второую строку и проверяю что-бы ее длинна была 14 символов. При этом эхо включено, и оно не мешает процессору вылавливать необходимые ответы. Кстати, вот что хотел спросить. Если мы выставляем ртс, и за это время в буфере SIM900 накопится, например, три сообщения, то, когда мы отпустим ртс, они вывалятся все разом, без пауз между ними? Цитата(Alechek @ Apr 25 2014, 16:29)  Самое первое правило - обрабатывать ВСЕ!!! последовательности от модема.
Второе - последовательность AT команд четко регламетирована (см GSM 07.07 раздел 4). Заметьте, у всех команд стандарта есть final result code (чего не скажешь творчестве собственных расширений производителей модемов) Все что между - результат выполения команды.
И еще есть ансинхронные ответы. Могут влезть куда угодно. либо пропускайте их, либо применяйте. НО РАСПОЗНАТЬ их надо!! Я всё понимаю, и стараюсь учесть все возможные ответы от модема. Но если пытаться определять конец посылки по CR/LF, учитывая то, что CR/LF может быть несколько, например \r\nOK\r\nблаблабла\r\n, то нам как минимум нужно знать, сколько \r\n будет в ответе от модема. Посчитать их, конечно, легко, но если асинхронное сообщение появилось, с ним как быть? Направьте меня в нужную сторону. Вообще, конечно, то, что форматы ответов так разнятся от команды к команде, сильно осложняет их обработку и даже немного раздражает. Что до меня, то пока особых трудностей с определением конца посылки по таймауту не возникало. Работает достаточно надежно. Кстати, снизил длительность таймаута до 1мс., пока полет нормальный. Кстати, по поводу собственно сабжа. У меня трудности, описанные в первом посте этой темы возникали в основном из-за ошибки переполнения буфера UART, связанной с отключением прерываний в другом, параллельном процессе. Так что проблема, можно сказать, почти решена. Сейчас тестирую прозрачный режим, обсуждение в соседней теме . Буду рад выслушать Ваши мнения. Цитата(RadikX @ Apr 25 2014, 13:59)  Это как раз не страшно. У меня идет работа с голосом (прием звонка, дозвон), SMS (прием и отправка) и GPRS (клиент) , плюс полный набор обслуживающих команд и всего в сумме получается не более 60 вариантов заголовков команд/ответов. Если делать не побуквенное сравнение, а более оптимизированный парсер, то получается быстрое автоматическое определение что пришло. Но с GPRS, да, в непрозрачном режиме приходится выкручиваться, а в прозрачном нет мультисокетов. Как вариант - реализовать режим мультиплексирования (CMUX). Было бы очень удобно, если бы китайцы добавили аналог +CIPRXGET, но не по незапрашиваемому ответу, а по запросу. Мне как раз мультисокет и не нужен, мне достаточно одного соединения. Значит ли это, что мне лучше воспользоваться прозрачным режимом? И второе. Намекните, если можно, про устройство Вашего оптимизированного парсера. Как он работает?
|
|
|
|
|
Apr 27 2014, 22:46
|
Частый гость
 
Группа: Участник
Сообщений: 121
Регистрация: 17-04-09
Пользователь №: 47 838

|
После снятия ртса сим выдаст следующую строку, проц выставит ртс, обработает ее, уберет ртс и так до тех пор, пока сим все строки не выдаст.
Большинство сообщений от сима имею заголовок, +IPR например. В програме заданы все заголовки на которые надо реагировать. Если в пришедшей строке найден один из заголовков, то проц уходит в его обработчик, который знает в какой что читать. ОК и ЕРРОР так-же определены как заголовки. При их приходе проверяется проверяется последняя переданная команда (храню условный номер). Если на эту команду ответ должен быть ОК, а пришел ЕРРОР, то снова передаю ту команду. Если пришел ОК то переход к слудующей команде. Это уже обычная машина сосостояний.
|
|
|
|
|
Apr 28 2014, 06:11
|
Частый гость
 
Группа: Участник
Сообщений: 143
Регистрация: 27-02-14
Из: Москва
Пользователь №: 80 728

|
Цитата(zebrox @ Apr 28 2014, 02:46)  Если пришел ОК то переход к слудующей команде. Это уже обычная машина сосостояний. Не-а. Надо сначала "пропихнуть" автомат в следующее состояние, которое будет ждать прихода именно Ок. Цитата Немного не понял про else. Что Вы имеете ввиду? Вот - http://www.delphisources.ru/forum/showthread.php?t=6547 Обратите внимание, что case намного прозрачнее if. Но это его удобство, проще читать код, все видно хорошо. А ссылку на статью давал, там есть рисунки с кодами автомата. Для возвртата в исходное состояние используется оператор goto. И под каждым case устанавливается следующее состояние. Короче, все просто оказалось, но намучился с этим всем конкретно, когда шел не автоматным путем.
--------------------
|
|
|
|
|
Apr 28 2014, 06:28
|
Местный
  
Группа: Участник
Сообщений: 339
Регистрация: 10-07-08
Из: Херсон
Пользователь №: 38 856

|
Цитата(Иван Плетнев @ Apr 27 2014, 19:21)  Я всё понимаю, и стараюсь учесть все возможные ответы от модема. Но если пытаться определять конец посылки по CR/LF, учитывая то, что CR/LF может быть несколько, например \r\nOK\r\nблаблабла\r\n, то нам как минимум нужно знать, сколько \r\n будет в ответе от модема. Посчитать их, конечно, легко, но если асинхронное сообщение появилось, с ним как быть? Направьте меня в нужную сторону. Вообще, конечно, то, что форматы ответов так разнятся от команды к команде, сильно осложняет их обработку и даже немного раздражает.
Что до меня, то пока особых трудностей с определением конца посылки по таймауту не возникало. Работает достаточно надежно. Кстати, снизил длительность таймаута до 1мс., пока полет нормальный. Тоже определял конец строки по таймауту. Работало. Потом перешел по \r\n. По \r\n оказалось более работоспособно, и нет никакой необходимости в знании сколько их будет в ответе. К примеру посмотрим на строку \r\nOK\r\nблаблабла\r\n, по первому \n мы видим что это начало строки (так как количество принятых байтов равно 2). По второму получаем ответ OK. По третьему получаем ответ блаблабла. Поэтому при разборе ответов, задача сводится к проверке "наборов байтов находящихся между \r\n". Единственное что портит всю картину это приглашение к вводу данных "> ", но и это обходится очень просто.
Сообщение отредактировал alexdos - Apr 28 2014, 07:10
|
|
|
|
|
Apr 28 2014, 09:14
|
Частый гость
 
Группа: Участник
Сообщений: 121
Регистрация: 17-04-09
Пользователь №: 47 838

|
Цитата(alexdos @ Apr 28 2014, 08:28)  ...Единственное что портит всю картину это приглашение к вводу данных "> "... Жду 1 сек, и подразумеваю, что пришло приглашение. Не видел ситуации, когда бы приглашение не пришло при отправке смса. А при передаче данных, мне мой сервер подтверждает получение посылки. Немного сложно обрабатывать ответы, которые не содержат заголовка (чтение имей).
|
|
|
|
|
Apr 28 2014, 10:28
|
Местный
  
Группа: Участник
Сообщений: 339
Регистрация: 10-07-08
Из: Херсон
Пользователь №: 38 856

|
Цитата(zebrox @ Apr 28 2014, 12:14)  Жду 1 сек, и подразумеваю, что пришло приглашение. Не видел ситуации, когда бы приглашение не пришло при отправке смса. А при передаче данных, мне мой сервер подтверждает получение посылки.
Немного сложно обрабатывать ответы, которые не содержат заголовка (чтение имей). Аж целую секунду, я не могу позволить себе столько ждать. В случае с \r\n никаких сложностей.
|
|
|
|
|
Apr 28 2014, 12:38
|
Местный
  
Группа: Свой
Сообщений: 476
Регистрация: 3-07-07
Из: Санкт-Петербург
Пользователь №: 28 866

|
Цитата(alexdos @ Apr 28 2014, 10:28)  Единственное что портит всю картину это приглашение к вводу данных "> ", но и это обходится очень просто. А как обходите, просто конечный автомат парсера настраиваете на поиск ">" без обрамления \r\n?
--------------------
Ковырял чукча отверткой в ухе, звук в телевизоре и пропал.
|
|
|
|
|
Apr 28 2014, 13:33
|
Местный
  
Группа: Свой
Сообщений: 476
Регистрация: 3-07-07
Из: Санкт-Петербург
Пользователь №: 28 866

|
Цитата(zebrox @ Apr 28 2014, 17:14)  В прерывании прихода символа из юарта, проверяем, если автомат находится в режиме ожидания приглашения, и пришел символ приглашения, то переходим к следующему состоянию (отправка текста смса, отправка сообщения серверу). У Вас автомат общий - и на отправку и на прием? По крайней мере так понял из сообщения. Мне удобнее иметь отдельный конечный автомат на прием, который периодически запускается и которому можно указать, какой токен в данный момент ожидается. Да и в прерывании уарта лучше просто заполнять кольцевой буфер. Всё imho. =)
--------------------
Ковырял чукча отверткой в ухе, звук в телевизоре и пропал.
|
|
|
|
|
Apr 28 2014, 14:13
|
Частый гость
 
Группа: Участник
Сообщений: 121
Регистрация: 17-04-09
Пользователь №: 47 838

|
Юарт у это разделяемый ресурс. Доступом к нему управляет структура из двух полей, первое это режим работы юарта, второе время в этом режиме. Разным независимым задачам необходим доступ к юарту (0-свободен, 1-залочен (поломан), 2-конфигурация сима, 3-чтение температуры, 4-чтение уровня сигнала, 5-чтение регистрации, 6-подключение с серверу, 7-передача данных ...). Все эти задачи это независымые автоматы. Если в режиме юарта записан 0, значит юарт свободен и любая задача (автомат) может его занять (записать в режим свой номер) и запустить таймер освобождения юарта (на случай если задачу заглючит). Если, допустим, доступ получила задача подключения к серверу, она должна отправить несколько команд. Отослала первую, пришел ок, общий обработчик окея видит, что работает задача подключения, вызывает ее (автомата подключения) обработчик успешной передачи команды. Он (автомат подключения) переходит в следующее состояние, шлет следующую команду, либо начинает сначала, либо завершает работу... Все автоматы завязаны на один хардверный таймер, в тике которго проверяются таймера всех автоматов, если какой-то таймер дотикал до 0, то этот автомт переводится в следующее состояние. В общем, все автоматы переходят в новое состояние либо по получению ответа, либо по обнулению таймера. Надеюсь из этого можно что-то понять
|
|
|
|
|
Apr 28 2014, 14:56
|
Местный
  
Группа: Участник
Сообщений: 339
Регистрация: 10-07-08
Из: Херсон
Пользователь №: 38 856

|
Цитата(Lotor @ Apr 28 2014, 15:38)  А как обходите, просто конечный автомат парсера настраиваете на поиск ">" без обрамления \r\n? Да, ожидаю с таймаутом: Код case While_Prigl: if ((Bufer_Rx_GPRS[0] == '>') && (Bufer_Rx_GPRS[1] == ' ')) { Main_cicle = Send_String3;} else if ((Ticks_20ms - curTicks) > 10) Main_cicle = Power_off; break;
Сообщение отредактировал alexdos - Apr 28 2014, 14:57
|
|
|
|
|
Apr 28 2014, 15:38
|
Участник

Группа: Участник
Сообщений: 29
Регистрация: 12-04-14
Пользователь №: 81 340

|
Цитата(tdocs.su @ Apr 28 2014, 14:11)  Не-а. Надо сначала "пропихнуть" автомат в следующее состояние, которое будет ждать прихода именно Ок. Вот - http://www.delphisources.ru/forum/showthread.php?t=6547 Обратите внимание, что case намного прозрачнее if. Но это его удобство, проще читать код, все видно хорошо. А ссылку на статью давал, там есть рисунки с кодами автомата. Для возвртата в исходное состояние используется оператор goto. И под каждым case устанавливается следующее состояние. Короче, все просто оказалось, но намучился с этим всем конкретно, когда шел не автоматным путем. Да я ж говорю, что тоже на автоматах всё у меня Код case 0: ExtraBufferCopyFlag = 1; //флаг копирования нужного фрагмента буфера (со смещением) send_command0(CIPSTATUS); gprsstate++; response_timeout=2000; break; case 1: if (!response_wait) { //если дождались ответа switch (response_code) { case 15: // INITIAL STATE gprsstate++; ready_to_send=0; break; case 17: // PDP DEACT STATE (Отключен сетью) gprsstate = 100; //закрываем все подключения ready_to_send=0; break; case 16: //TCP CLOSED gprsstate = 12; // gsm_delay=300; ready_to_send=0; break; case 18: //CONNECT OK gprsstate = 20; send_flag=1; break; case 20: //CONNECTING gprsstate = 30; break; case 3: gprsstate=30; break; } } Ну и так далее. Цитата(alexdos @ Apr 28 2014, 14:28)  Тоже определял конец строки по таймауту. Работало. Потом перешел по \r\n. По \r\n оказалось более работоспособно, и нет никакой необходимости в знании сколько их будет в ответе. К примеру посмотрим на строку \r\nOK\r\nблаблабла\r\n, по первому \n мы видим что это начало строки (так как количество принятых байтов равно 2). По второму получаем ответ OK. По третьему получаем ответ блаблабла. Поэтому при разборе ответов, задача сводится к проверке "наборов байтов находящихся между \r\n". Единственное что портит всю картину это приглашение к вводу данных "> ", но и это обходится очень просто. Это Вы в прерывании всё делаете? Если так, то приличный такой обработчик в прерывании будет крутиться. А если нет, тогда опять не ясно, как конец сообщения определить?
|
|
|
|
|
Apr 28 2014, 17:45
|
Местный
  
Группа: Участник
Сообщений: 339
Регистрация: 10-07-08
Из: Херсон
Пользователь №: 38 856

|
Цитата(Иван Плетнев @ Apr 28 2014, 18:38)  Это Вы в прерывании всё делаете? Если так, то приличный такой обработчик в прерывании будет крутиться. А если нет, тогда опять не ясно, как конец сообщения определить? Да нет, в прерывании я мало что делаю Код /* завершим текстовую строку*/ if(Bufer_Rx_GPRS[Count_Byte_Rx_GPRS - 1] == '\r') { Bufer_Rx_GPRS[Count_Byte_Rx_GPRS - 1] = 0; strncpy(Bufer_Rx_GPRS_Parser, Bufer_Rx_GPRS, Count_Byte_Rx_GPRS); /* скопируем строку в буфер парсера*/ } else { Bufer_Rx_GPRS[Count_Byte_Rx_GPRS] = 0; strncpy(Bufer_Rx_GPRS_Parser, Bufer_Rx_GPRS, Count_Byte_Rx_GPRS + 1); /* скопируем строку в буфер парсерв*/ }
Count_Byte_Rx_GPRS = 0; GPRS_rxgap = 1; } else Bufer_Rx_GPRS[Count_Byte_Rx_GPRS++] = GPRS_Byte_in; /* принятый байт сохраним в приемный буфер */ if (Count_Byte_Rx_GPRS >= 512) Count_Byte_Rx_GPRS = 0; }
Сообщение отредактировал alexdos - Apr 28 2014, 17:46
|
|
|
|
|
Apr 29 2014, 04:07
|
Частый гость
 
Группа: Участник
Сообщений: 125
Регистрация: 13-04-11
Из: Суровый Челябинск
Пользователь №: 64 337

|
Цитата(Иван Плетнев @ Apr 27 2014, 20:21)  Мне как раз мультисокет и не нужен, мне достаточно одного соединения. Значит ли это, что мне лучше воспользоваться прозрачным режимом? И второе. Намекните, если можно, про устройство Вашего оптимизированного парсера. Как он работает? В прозрачном режиме проще: могут придти только данные. Устройство парсера CODE typedef enum { ANSWER_PARAM_TYPE_UNKNOWN =0, // Тип параметра не определился ANSWER_PARAM_TYPE_STRING =1, // Строка выделенная кавычками ANSWER_PARAM_TYPE_CONSTANT =2, // Строка - константа, заменяем на значение их дефйна ANSWER_PARAM_TYPE_INTEGER =3, // Целое ANSWER_PARAM_TYPE_LIST =4, // Список возможных значений - строка в круглых скобках ANSWER_PARAM_TYPE_COMMAND =5 // Заголовок-опознаватель команды } TEnum_AnswerParamType;
typedef struct { TEnum_AnswerParamType ParamType; uint8_t IsCmd; char* Value; uint16_t IntVal; uint16_t Len; } TStruct_AnswerParam; char* GetAnswerParam(char * Buf, TStruct_AnswerParam *AnswerParam); На вход подается указатель на входную строку и на заполняемую структуру. На выходе возвращает указатель на следующий за последним обработанным байт. Можно вызывать циклически для разбора всей команды. CR LF заменяется на \0. CODE char* GetAnswerParam(char * Buf, TStruct_AnswerParam *AnswerParam) { AnswerParam->ParamType = ANSWER_PARAM_TYPE_UNKNOWN; AnswerParam->IsCmd = 0; int8_t BracketCnt=0; int8_t QuotesCnt=0; uint8_t FlagNewParam=1; uint8_t FlagCmd=0; uint16_t Len=0; char tmp; Buf=ReMapRxBufferPoint(Buf); AnswerParam->IntVal = 0; AnswerParam->Value =Buf; do { switch (*Buf) { case ':': FlagCmd=1; break; case ' ': if (FlagCmd) { AnswerParam->IsCmd=1; Buf++; Buf=ReMapRxBufferPoint(Buf); } else { FlagCmd=0; break; } Len++; case ',': if ((BracketCnt)||(QuotesCnt%2)) { FlagCmd=0; break; } case 0: { if ((AnswerParam->ParamType == ANSWER_PARAM_TYPE_LIST)&&BracketCnt) AnswerParam->ParamType = ANSWER_PARAM_TYPE_UNKNOWN; if ((AnswerParam->ParamType == ANSWER_PARAM_TYPE_STRING)&&(*ReMapRxBufferPoint(Buf-1)!='\"')) AnswerParam->ParamType = ANSWER_PARAM_TYPE_UNKNOWN;
if ((AnswerParam->ParamType == ANSWER_PARAM_TYPE_CONSTANT)||(AnswerParam->ParamType == ANSWER_PARAM_TYPE_STRING)) { if (AnswerParam->IsCmd) Len-=2; AnswerParam->IntVal=0; AnswerParam->Len=Len; for (uint8_t i=1; i<(sizeof(strCmdArray)/sizeof(strCmdArray[0])); i++) { if (AnswerParam->ParamType == ANSWER_PARAM_TYPE_CONSTANT) { if (Len == strCmdArray[i].Len) if (CompareStrFStr(AnswerParam->Value, strCmdArray[i].Val)) { AnswerParam->IntVal = strCmdArray[i].Code; break; } } else { if (Len-2 == strCmdArray[i].Len) if (CompareStrFStr(AnswerParam->Value+1, strCmdArray[i].Val)) { AnswerParam->IntVal = strCmdArray[i].Code; break; } } } if (AnswerParam->IntVal == 0) { } } return Buf; } case '(': { if (FlagNewParam) { AnswerParam->ParamType = ANSWER_PARAM_TYPE_LIST; AnswerParam->Value = Buf; } if ((AnswerParam->ParamType == ANSWER_PARAM_TYPE_INTEGER) ||(AnswerParam->ParamType == ANSWER_PARAM_TYPE_CONSTANT)) AnswerParam->ParamType = ANSWER_PARAM_TYPE_UNKNOWN; BracketCnt++; break; } case ')': { if ((AnswerParam->ParamType == ANSWER_PARAM_TYPE_INTEGER) ||(AnswerParam->ParamType == ANSWER_PARAM_TYPE_CONSTANT)) AnswerParam->ParamType = ANSWER_PARAM_TYPE_UNKNOWN; BracketCnt--; break; } case '\"': { if (FlagNewParam) { AnswerParam->ParamType = ANSWER_PARAM_TYPE_STRING; AnswerParam->Value = Buf; } if ((AnswerParam->ParamType == ANSWER_PARAM_TYPE_INTEGER) ||(AnswerParam->ParamType == ANSWER_PARAM_TYPE_CONSTANT)) AnswerParam->ParamType = ANSWER_PARAM_TYPE_UNKNOWN; QuotesCnt++; break; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { if (FlagNewParam) { AnswerParam->ParamType = ANSWER_PARAM_TYPE_INTEGER; AnswerParam->Value = Buf; } if (AnswerParam->ParamType == ANSWER_PARAM_TYPE_INTEGER) { AnswerParam->IntVal = AnswerParam->IntVal * 10; AnswerParam->IntVal += *Buf-0x30; } break; } default: { if (FlagNewParam) { AnswerParam->ParamType = ANSWER_PARAM_TYPE_CONSTANT; AnswerParam->Value = Buf; } if (AnswerParam->ParamType == ANSWER_PARAM_TYPE_INTEGER) AnswerParam->ParamType = ANSWER_PARAM_TYPE_CONSTANT; } } if (*Buf!=' ') FlagNewParam=0; if (*Buf!=':') FlagCmd=0; tmp=*Buf; if (!((tmp==' ')&&(FlagNewParam))) Len++; Buf++; Buf=ReMapRxBufferPoint(Buf); // Пересчет указателя, т.к буфер кольцевой } while (tmp);
return Buf; }
|
|
|
|
|
Apr 29 2014, 04:14
|
Частый гость
 
Группа: Участник
Сообщений: 143
Регистрация: 27-02-14
Из: Москва
Пользователь №: 80 728

|
Вспомнил. Делал еще какую-то буферизацию для хвоста сообщения, остававшегося неразобранным с прошлого "сеанса". Т.е. то, что приходило и оказывалось неполным, не игнорировалось, а сохранялось в tile, а потом, когда дополнялось, разбиралось полностью. Жаль вот кодов не осталось, а то бы сейчас проблем не было. Но кодам почти 20 лет уже, все хранилось в архивах, а потом винда эти архивы грохнула. Работало все безупречно...
--------------------
|
|
|
|
|
Apr 30 2014, 10:46
|
Местный
  
Группа: Свой
Сообщений: 476
Регистрация: 3-07-07
Из: Санкт-Петербург
Пользователь №: 28 866

|
Цитата(tdocs.su @ Apr 29 2014, 08:14)  Вспомнил. Делал еще какую-то буферизацию для хвоста сообщения, остававшегося неразобранным с прошлого "сеанса". Неразобранное обязательно надо проверять. У меня конечный автомат парсера помимо ожидаемых сообщений еще и проверяет на unsolicted. И если таковые имеются - вызываются их обработчики.
--------------------
Ковырял чукча отверткой в ухе, звук в телевизоре и пропал.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|