реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> SIM900. Прием команд от TCP сервера., Как исключить коллизии в порту при приеме внешних команд?
Иван Плетнев
сообщение Apr 22 2014, 16:50
Сообщение #1


Участник
*

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



Здравствуйте!

Разрабатываю устройство, которое собирает различные данные с датчиков и с периодичностью в одну минуту отправляет их на сервер посредством SIM900. Использую обычный режим AT-команд, не transparent, то есть команда AT+CIPSEND, приходит приглашение ">", отсылаю в порт строку, дожидаюсь SEND OK, всё. В данный момент добился надежной отсылки данных. Встал вопрос приёма команд от сервера. Все в общем, работает, за исключением случая, когда микроконтроллер ждет ответа от SIM900 и в этот момент приходит команда от сервера. Аппаратное управление потоком в этом случае вряд ли подойдет..
Подскажите, пожалуйста, кто как справился с этой проблемой?
Go to the top of the page
 
+Quote Post
zebrox
сообщение Apr 22 2014, 21:40
Сообщение #2


Частый гость
**

Группа: Участник
Сообщений: 121
Регистрация: 17-04-09
Пользователь №: 47 838



Так понимаю, что процессор ожидает ответ от сима на какую-либо АТ команду?

Думаю у команды с сервера должен быть заголовок, по которому ее можно отличить от ответа сима.
Выполнить ее, и дальше ждать ответа на АТ?
Go to the top of the page
 
+Quote Post
Иван Плетнев
сообщение Apr 23 2014, 03:57
Сообщение #3


Участник
*

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



Цитата(zebrox @ Apr 23 2014, 05:40) *
Так понимаю, что процессор ожидает ответ от сима на какую-либо АТ команду?

Думаю у команды с сервера должен быть заголовок, по которому ее можно отличить от ответа сима.
Выполнить ее, и дальше ждать ответа на АТ?

Ну да, это понятно. У команды действительно есть заголовок, и, кроме этого, по этому признаку я помещаю эти команды в другой буфер для дальнейшего парсинга. Видите ли, у меня конец сообщения от SIM900 определяется по таймауту. То есть, после приема последнего символа ответа, таймер отсчитывает 2мс и поднимается флаг, что ответ готов. Если команда приходит во время ответа, когда SIM900 что-то кидает в порт, или во время этой задержки, то целостность ответа нарушается и, соответственно, парсер ответов не может распознать его. Вот в чем проблема.
Go to the top of the page
 
+Quote Post
V_G
сообщение Apr 23 2014, 04:56
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 818
Регистрация: 15-10-09
Из: Владивосток
Пользователь №: 52 955



Таймаут приема (большой) использую только для защиты от зависаний.
При обычном обмене между процем и GSM-модулем (у меня был SIM700) сообщение разбираю по получении символа ">" (готовность к дальнейшему обмену).

Самостоятельные посылки от SIM700 начинаю разбирать при получении символа ":", далее в зависимости от того, что пришло до двоеточия. Если это "+IPD:" (данные от сервера, работаю только с двоичными (нетекстовыми) посылками), жду прихода длины посылки, после чего завожу счетчик на количество принимаемых байтов)
Go to the top of the page
 
+Quote Post
tdocs.su
сообщение Apr 23 2014, 05:15
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 143
Регистрация: 27-02-14
Из: Москва
Пользователь №: 80 728



Автомат конечный писать надо. Были проблемы когда-то давно с коммуникационной программой для двух модемов, только конечный автомат и позволил добиться устойчивой работы. Его ничем из "седла" не вышибить.


--------------------
Go to the top of the page
 
+Quote Post
Иван Плетнев
сообщение Apr 23 2014, 05:57
Сообщение #6


Участник
*

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



Цитата(tdocs.su @ Apr 23 2014, 13:15) *
Автомат конечный писать надо. Были проблемы когда-то давно с коммуникационной программой для двух модемов, только конечный автомат и позволил добиться устойчивой работы. Его ничем из "седла" не вышибить.

Так у меня вся работа с модемом на конечных автоматах. Иначе с ним вообще невозможно работать. В общем, решил проблему "заплатками". Если команда от сервера приходит в неподходящий момент и возникает коллизия с ответом от модема, по таймауту ожидание ответа прекращается и программа выпадает в "диспетчер задач". И если команда не распозналась, сервер не получает подтверждения принятой команды и отсылает её вновь.
Go to the top of the page
 
+Quote Post
tdocs.su
сообщение Apr 23 2014, 06:19
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 143
Регистрация: 27-02-14
Из: Москва
Пользователь №: 80 728



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

Не принимает ваш ящик личку. См. здесь - http://tdocs.su/4199

Сообщение отредактировал tdocs.su - Apr 23 2014, 06:22


--------------------
Go to the top of the page
 
+Quote Post
Иван Плетнев
сообщение Apr 23 2014, 06:27
Сообщение #8


Участник
*

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



Цитата(tdocs.su @ Apr 23 2014, 14:19) *
Как-то странно... Ведь в автомате после отправки чего-либо в линию вы принудительно переводите его в новое состояние, в котором он ожидает конкретный ответ из линии, и никакой другой. Может, что-то не так делаете? См. личку.

Не принимает ваш ящик личку. См. здесь - http://tdocs.su/4199


Спасибо, почитаю.

Проблема-то как раз в том, что жду одно, а приходит другое ))
Go to the top of the page
 
+Quote Post
tdocs.su
сообщение Apr 23 2014, 06:54
Сообщение #9


Частый гость
**

Группа: Участник
Сообщений: 143
Регистрация: 27-02-14
Из: Москва
Пользователь №: 80 728



Цитата(Иван Плетнев @ Apr 23 2014, 10:27) *
Спасибо, почитаю.

Проблема-то как раз в том, что жду одно, а приходит другое ))

Так вот автомат на другое и реагировать не должен вовсе. Если после перехода в case сразу задать ему новое состояние, он в нем и будет находиться и ждать только то, что надо, все прочее просто игнорировать.


--------------------
Go to the top of the page
 
+Quote Post
Иван Плетнев
сообщение Apr 23 2014, 09:50
Сообщение #10


Участник
*

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



Все-таки не получается у меня в стандартном, командном режиме принимать сообщения от сервера без грабель. Буду пробовать transparent mode.
Go to the top of the page
 
+Quote Post
tdocs.su
сообщение Apr 23 2014, 13:08
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 143
Регистрация: 27-02-14
Из: Москва
Пользователь №: 80 728



Цитата(Иван Плетнев @ Apr 23 2014, 13:50) *
Все-таки не получается у меня в стандартном, командном режиме принимать сообщения от сервера без грабель. Буду пробовать transparent mode.

С утра я чё-та не догнал. А сейчас вспомнил детали той своей давней задачки. Обрисую.

Было 2 компика с зухелом на каждом из них (через COM-порты) и поганейшая линия связи, чуть ли не АТС с шаговым искателем sm.gif В исходном положении модемы были инициализированы и выведены на режим лежачей трубы (командный режим). При вызове одного другим они "договаривались" друг с другом и из командного режима переходили в режим обмена данными. И тоже возникало что-то такое, когда один еще был в режиме обмена, а другой уже бросал трубу и переходил в командный.

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

Кажется, что у вас что-то подобное происходит сейчас. Невывод из командного режима в режим обмена данными.

Позже еще приходилось решать задачку автоматом - каждое утро высасывать обновленный прайс-лист одного крупного поставщика компьютерной комплектухи, сравнивать его со своим локальным, обходить "старую", уже имеющуюся у нас комплектуху, а затем еще декодировать и конвертировать HTML-код так, чтобы поставщик не мог предъявить претензий по поводу таких ежедневных утренних краж sm.gif Задачка четко решалась автоматом.

Короче, что-то у вас именно с переключением режимов. Если ждете данные, а приходит от сервера команда, то так и есть. Все вспомнил sm.gif



--------------------
Go to the top of the page
 
+Quote Post
zebrox
сообщение Apr 23 2014, 13:18
Сообщение #12


Частый гость
**

Группа: Участник
Сообщений: 121
Регистрация: 17-04-09
Пользователь №: 47 838



И почему конец сообщения определяется таймаутом?
Почему не использовать последовательность CR LF?
Go to the top of the page
 
+Quote Post
Иван Плетнев
сообщение Apr 23 2014, 15:21
Сообщение #13


Участник
*

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



Цитата(zebrox @ Apr 23 2014, 21:18) *
И почему конец сообщения определяется таймаутом?
Почему не использовать последовательность CR LF?

Потому что встречаются ответы модема, в которых есть и две последовательности CR LF, и три.
Go to the top of the page
 
+Quote Post
RadikX
сообщение Apr 25 2014, 05:59
Сообщение #14


Частый гость
**

Группа: Участник
Сообщений: 125
Регистрация: 13-04-11
Из: Суровый Челябинск
Пользователь №: 64 337



Цитата(Иван Плетнев @ Apr 23 2014, 19:21) *
Потому что встречаются ответы модема, в которых есть и две последовательности CR LF, и три.

Это как раз не страшно. У меня идет работа с голосом (прием звонка, дозвон), SMS (прием и отправка) и GPRS (клиент) , плюс полный набор обслуживающих команд и всего в сумме получается не более 60 вариантов заголовков команд/ответов. Если делать не побуквенное сравнение, а более оптимизированный парсер, то получается быстрое автоматическое определение что пришло. Но с GPRS, да, в непрозрачном режиме приходится выкручиваться, а в прозрачном нет мультисокетов. Как вариант - реализовать режим мультиплексирования (CMUX).
Было бы очень удобно, если бы китайцы добавили аналог +CIPRXGET, но не по незапрашиваемому ответу, а по запросу.
Go to the top of the page
 
+Quote Post
Alechek
сообщение Apr 25 2014, 08:29
Сообщение #15


Профессионал
*****

Группа: Свой
Сообщений: 1 241
Регистрация: 15-11-05
Из: Челябинск
Пользователь №: 10 882



Цитата(Иван Плетнев @ Apr 23 2014, 21:21) *
Потому что встречаются ответы модема, в которых есть и две последовательности CR LF, и три.

Самое первое правило - обрабатывать ВСЕ!!! последовательности от модема.

Второе - последовательность AT команд четко регламетирована (см GSM 07.07 раздел 4).
Заметьте, у всех команд стандарта есть final result code (чего не скажешь творчестве собственных расширений производителей модемов)
Все что между - результат выполения команды.

И еще есть ансинхронные ответы. Могут влезть куда угодно. либо пропускайте их, либо применяйте. НО РАСПОЗНАТЬ их надо!!
Go to the top of the page
 
+Quote Post
tdocs.su
сообщение Apr 25 2014, 08:42
Сообщение #16


Частый гость
**

Группа: Участник
Сообщений: 143
Регистрация: 27-02-14
Из: Москва
Пользователь №: 80 728



Цитата(Alechek @ Apr 25 2014, 12:29) *
Самое первое правило - обрабатывать ВСЕ!!! последовательности от модема.

Второе - последовательность AT команд четко регламетирована (см GSM 07.07 раздел 4).
Заметьте, у всех команд стандарта есть final result code (чего не скажешь творчестве собственных расширений производителей модемов)
Все что между - результат выполения команды.

И еще есть ансинхронные ответы. Могут влезть куда угодно. либо пропускайте их, либо применяйте. НО РАСПОЗНАТЬ их надо!!

Однозначно! Все прочее (кроме автомата) - просто мертвому припарки. Выкрутиться не получится.
Кстати, у оператора case в любом "языковом исполнении" всегда имеется свой else, позволяющий пропустить что-угодно как с распознаванием, так и без, если со стороны пришел некий "невнятный" и не вписывающийся в рамки протокола ответ - команда вместо данных и в таком духе.


--------------------
Go to the top of the page
 
+Quote Post
zebrox
сообщение Apr 25 2014, 15:24
Сообщение #17


Частый гость
**

Группа: Участник
Сообщений: 121
Регистрация: 17-04-09
Пользователь №: 47 838



Тоже сначала делал обработку по таймауту.
Все было очень плохо.

Потом перешел на обработку по концу строки.
По приходу строки выставляю сигнал ртс, в основном цикле обрабатываю строку, убираю ртс когда процессор готов к приему.
Имею проблему только с командой чтения имея, т.к. имей возвращается во второй строке и без заголовка.
В этом случае обрабатываю второую строку и проверяю что-бы ее длинна была 14 символов.
При этом эхо включено, и оно не мешает процессору вылавливать необходимые ответы.
Go to the top of the page
 
+Quote Post
Иван Плетнев
сообщение Apr 27 2014, 16:21
Сообщение #18


Участник
*

Группа: Участник
Сообщений: 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, но не по незапрашиваемому ответу, а по запросу.

Мне как раз мультисокет и не нужен, мне достаточно одного соединения. Значит ли это, что мне лучше воспользоваться прозрачным режимом?
И второе. Намекните, если можно, про устройство Вашего оптимизированного парсера. Как он работает?
Go to the top of the page
 
+Quote Post
zebrox
сообщение Apr 27 2014, 22:46
Сообщение #19


Частый гость
**

Группа: Участник
Сообщений: 121
Регистрация: 17-04-09
Пользователь №: 47 838



После снятия ртса сим выдаст следующую строку, проц выставит ртс, обработает ее, уберет ртс и так до тех пор, пока сим все строки не выдаст.

Большинство сообщений от сима имею заголовок, +IPR например. В програме заданы все заголовки на которые надо реагировать.
Если в пришедшей строке найден один из заголовков, то проц уходит в его обработчик, который знает в какой что читать.
ОК и ЕРРОР так-же определены как заголовки. При их приходе проверяется проверяется последняя переданная команда (храню условный номер).
Если на эту команду ответ должен быть ОК, а пришел ЕРРОР, то снова передаю ту команду.
Если пришел ОК то переход к слудующей команде. Это уже обычная машина сосостояний.
Go to the top of the page
 
+Quote Post
Alechek
сообщение Apr 28 2014, 05:38
Сообщение #20


Профессионал
*****

Группа: Свой
Сообщений: 1 241
Регистрация: 15-11-05
Из: Челябинск
Пользователь №: 10 882



Добавлю еще, что большинство ответов можно расматривать как заголовок и набор параметров, разделенных запятыми. параметры могут быть int, hex, str
в большинстве случаев достаточно распознавать не более 4-х параметров.
Go to the top of the page
 
+Quote Post
tdocs.su
сообщение Apr 28 2014, 06:11
Сообщение #21


Частый гость
**

Группа: Участник
Сообщений: 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 устанавливается следующее состояние.
Короче, все просто оказалось, но намучился с этим всем конкретно, когда шел не автоматным путем.


--------------------
Go to the top of the page
 
+Quote Post
alexdos
сообщение Apr 28 2014, 06:28
Сообщение #22


Местный
***

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
tdocs.su
сообщение Apr 28 2014, 06:49
Сообщение #23


Частый гость
**

Группа: Участник
Сообщений: 143
Регистрация: 27-02-14
Из: Москва
Пользователь №: 80 728



Лексема (Lexical) token Lexical unit - Языковая конструкция, по соглашению представляющая элементарную синтаксическую единицу [из п. 2 Табл. 1 ГОСТ 28397-89] sm.gif


--------------------
Go to the top of the page
 
+Quote Post
zebrox
сообщение Apr 28 2014, 09:14
Сообщение #24


Частый гость
**

Группа: Участник
Сообщений: 121
Регистрация: 17-04-09
Пользователь №: 47 838



Цитата(alexdos @ Apr 28 2014, 08:28) *
...Единственное что портит всю картину это приглашение к вводу данных "> "...


Жду 1 сек, и подразумеваю, что пришло приглашение. Не видел ситуации, когда бы приглашение не пришло при отправке смса.
А при передаче данных, мне мой сервер подтверждает получение посылки.

Немного сложно обрабатывать ответы, которые не содержат заголовка (чтение имей).
Go to the top of the page
 
+Quote Post
alexdos
сообщение Apr 28 2014, 10:28
Сообщение #25


Местный
***

Группа: Участник
Сообщений: 339
Регистрация: 10-07-08
Из: Херсон
Пользователь №: 38 856



Цитата(zebrox @ Apr 28 2014, 12:14) *
Жду 1 сек, и подразумеваю, что пришло приглашение. Не видел ситуации, когда бы приглашение не пришло при отправке смса.
А при передаче данных, мне мой сервер подтверждает получение посылки.

Немного сложно обрабатывать ответы, которые не содержат заголовка (чтение имей).

Аж целую секунду, я не могу позволить себе столько ждать.
В случае с \r\n никаких сложностей.
Go to the top of the page
 
+Quote Post
zebrox
сообщение Apr 28 2014, 10:46
Сообщение #26


Частый гость
**

Группа: Участник
Сообщений: 121
Регистрация: 17-04-09
Пользователь №: 47 838



Блокируется только машина юарта, она переходит в состояние ожидания, а все остальные машины продолжают работать.
Go to the top of the page
 
+Quote Post
Lotor
сообщение Apr 28 2014, 12:38
Сообщение #27


Местный
***

Группа: Свой
Сообщений: 476
Регистрация: 3-07-07
Из: Санкт-Петербург
Пользователь №: 28 866



Цитата(alexdos @ Apr 28 2014, 10:28) *
Единственное что портит всю картину это приглашение к вводу данных "> ", но и это обходится очень просто.

А как обходите, просто конечный автомат парсера настраиваете на поиск ">" без обрамления \r\n?


--------------------
Ковырял чукча отверткой в ухе, звук в телевизоре и пропал.
Go to the top of the page
 
+Quote Post
zebrox
сообщение Apr 28 2014, 13:14
Сообщение #28


Частый гость
**

Группа: Участник
Сообщений: 121
Регистрация: 17-04-09
Пользователь №: 47 838



Я думаю.
В прерывании прихода символа из юарта, проверяем, если автомат находится в режиме ожидания приглашения, и пришел символ приглашения, то переходим к следующему состоянию (отправка текста смса, отправка сообщения серверу).
Параллельно тикает таймер, если таймер истек, значит приглашение не пришло, снова пробуем.
Go to the top of the page
 
+Quote Post
Lotor
сообщение Apr 28 2014, 13:33
Сообщение #29


Местный
***

Группа: Свой
Сообщений: 476
Регистрация: 3-07-07
Из: Санкт-Петербург
Пользователь №: 28 866



Цитата(zebrox @ Apr 28 2014, 17:14) *
В прерывании прихода символа из юарта, проверяем, если автомат находится в режиме ожидания приглашения, и пришел символ приглашения, то переходим к следующему состоянию (отправка текста смса, отправка сообщения серверу).

У Вас автомат общий - и на отправку и на прием? По крайней мере так понял из сообщения.
Мне удобнее иметь отдельный конечный автомат на прием, который периодически запускается и которому можно указать, какой токен в данный момент ожидается. Да и в прерывании уарта лучше просто заполнять кольцевой буфер. Всё imho. =)


--------------------
Ковырял чукча отверткой в ухе, звук в телевизоре и пропал.
Go to the top of the page
 
+Quote Post
zebrox
сообщение Apr 28 2014, 14:13
Сообщение #30


Частый гость
**

Группа: Участник
Сообщений: 121
Регистрация: 17-04-09
Пользователь №: 47 838



Юарт у это разделяемый ресурс. Доступом к нему управляет структура из двух полей, первое это режим работы юарта, второе время в этом режиме.
Разным независимым задачам необходим доступ к юарту (0-свободен, 1-залочен (поломан), 2-конфигурация сима, 3-чтение температуры, 4-чтение уровня сигнала, 5-чтение регистрации, 6-подключение с серверу, 7-передача данных ...).
Все эти задачи это независымые автоматы.

Если в режиме юарта записан 0, значит юарт свободен и любая задача (автомат) может его занять (записать в режим свой номер) и запустить таймер освобождения юарта (на случай если задачу заглючит).

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

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

Надеюсь из этого можно что-то понять sm.gif

Go to the top of the page
 
+Quote Post
alexdos
сообщение Apr 28 2014, 14:56
Сообщение #31


Местный
***

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
Иван Плетнев
сообщение Apr 28 2014, 15:38
Сообщение #32


Участник
*

Группа: Участник
Сообщений: 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". Единственное что портит всю картину это приглашение к вводу данных "> ", но и это обходится очень просто.


Это Вы в прерывании всё делаете? Если так, то приличный такой обработчик в прерывании будет крутиться. А если нет, тогда опять не ясно, как конец сообщения определить?
Go to the top of the page
 
+Quote Post
alexdos
сообщение Apr 28 2014, 17:45
Сообщение #33


Местный
***

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
RadikX
сообщение Apr 29 2014, 04:07
Сообщение #34


Частый гость
**

Группа: Участник
Сообщений: 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;
}
Go to the top of the page
 
+Quote Post
tdocs.su
сообщение Apr 29 2014, 04:14
Сообщение #35


Частый гость
**

Группа: Участник
Сообщений: 143
Регистрация: 27-02-14
Из: Москва
Пользователь №: 80 728



Вспомнил. Делал еще какую-то буферизацию для хвоста сообщения, остававшегося неразобранным с прошлого "сеанса". Т.е. то, что приходило и оказывалось неполным, не игнорировалось, а сохранялось в tile, а потом, когда дополнялось, разбиралось полностью. Жаль вот кодов не осталось, а то бы сейчас проблем не было. Но кодам почти 20 лет уже, все хранилось в архивах, а потом винда эти архивы грохнула. Работало все безупречно...


--------------------
Go to the top of the page
 
+Quote Post
Lotor
сообщение Apr 30 2014, 10:46
Сообщение #36


Местный
***

Группа: Свой
Сообщений: 476
Регистрация: 3-07-07
Из: Санкт-Петербург
Пользователь №: 28 866



Цитата(tdocs.su @ Apr 29 2014, 08:14) *
Вспомнил. Делал еще какую-то буферизацию для хвоста сообщения, остававшегося неразобранным с прошлого "сеанса".

Неразобранное обязательно надо проверять. У меня конечный автомат парсера помимо ожидаемых сообщений еще и проверяет на unsolicted. И если таковые имеются - вызываются их обработчики.


--------------------
Ковырял чукча отверткой в ухе, звук в телевизоре и пропал.
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th August 2025 - 07:54
Рейтинг@Mail.ru


Страница сгенерированна за 0.03149 секунд с 7
ELECTRONIX ©2004-2016