Как разобрать строку смс сообщения
- Войдите на сайт для отправки комментариев
Пнд, 05/12/2016 - 21:37
Здравствуйте!!!
Появилась проблема недостатка памяти при использовании библиотек GSM для ардуино. Библиотеки ЖРУТ память дуньки неоставляя места для "не очень" большого проекта, начал изучать работу связки ардуино и GSM модуля посредством АТ команд. Помогите с разбором текста входящей смс на: 1 - "номер" с котрого пришло смс и 2 - "текст" во входящем смс, переменным присвоить номер - char phone[20]; текст - char message[30];. Скетч такой
#include <SoftwareSerial.h> SoftwareSerial mySerial(2, 3); // RX, TX int ch = 0; String text = ""; char phone[20]; char message[30]; void setup() { Serial.begin(9600); mySerial.begin(19200); } void loop() { if (mySerial.available()) { //если есть данные от GSM модуля while (mySerial.available()) { //жду пока строка считается ch = mySerial.read(); text += char(ch); //сохраняем входную строку в переменную val delay(10); } Serial.println(text); // дублируем сообщение в терминал } }
в сериал порт приходят данные
+CMT: "+7963xxxxxxx","","16/12/05,22:17:28+20" // номер с которого пришло смс и время
Privet // тект сообщения
Избавляйтесь от String.
Прошу помощи!!!
Сообщение читаю в сериал такого формата
Избавляйтесь от String.
У меня вопрос, а как избавляться то?
У String масса возможностей, чем плох то?
У String масса возможностей, чем плох то?
Так вот этим же
проблема недостатка памяти
Я тут (хотя некоторые уже не верят) таки пишу этюд про память. Так вот, вставил в класс String, а именно в то место, где он память запрашивает, печать, что мол запросил столько-то. Хотите посмотреть, что выдаёт вот такая вот программа?
Таки хотим
Ну, чуть позже выложу, у меня этот String с доп. печатаями на другом компьютере. Доберусь - выложу.
Окей, добрался. Смотрите
Как видите этот скетч создаёт две строки и 7 (семь!!!) раз запрашивает память.
Есть нюанс. Пример, конечно показательный, но видно, что автор против Стринга :) Если создать стринг и сразу присвоить ему длинну , скажем, для даного примера 26 символов, то выделение памяти будет всего два раза :)
Если Стринг объявлен глобально, то он выделяет под себя оптимальный размер памяти. То есть, стринг выделяет память только если его длинна увеличивается и не освобождает ее пока его явно не разрушат. Получается, что если стринговый буфер выделен для анализа строк приходящих с какого нибудь GSMного модуля, то лишние дергания на выделение памяти происходят только в начале работы кода.
Что же касается обработки стринга, то многие не знают, или принебрегают c_str() :) А зря.
PS Я тоже суржик не люблю, но на нем под час целые народы говорят.
автор против Стринга :)
Нет, я не против ничего. Всегда и везде пишу, что всякий инструмент хорош, если его по уму использовать и всегда против заявлений, что "что-то там использовать нельзя". Просто всё нужно использовать к месту и по уму, а данный пример как раз показывает использование без ума. Особенно даже не запросы памяти, а передача по значению, которая приводит к созданию второго, нахрен не нужного экземпляра.
В моем проекте используются три библиотеки
даже при компиляции пустого скетча с ними уходит почти 70% памяти выделенной для глобальных переменных и просто места для кода совсем грамм остается. Бьюсь с приемом смс, а именно разобрать текст и вытащить номер и текст сообщения уже получается. Помогите если есть соображения. Вот кусок кода гляньте может лишнего нагородил?
переменные для номера и текста
строку не стал использовать - выше посоветовали
Для того, чтобы что-то оптимизировать (память или ещё чего) необходимо сначала понять чего Вам не хватает и что подлежит оптимизации.
Пока де Вы пишете нечто странное
даже при компиляции пустого скетча с ними уходит почти 70% памяти выделенной для глобальных переменных и просто места для кода совсем грамм остается.
дело в том, что память под глобальные переменные и память под код - это РАЗНЫЕ памяти и они никак друг с другом не конкурируют и друг другу не мешают.
Так чего у Вас не хватает? Памяти под код? Или памяти под переменные?
Пока Вы этого не поймёте, любые Ваши оптимизации будут на уровне "пойди туда, не знаю куда, принеси то, не знаю что".
Точно! извиняюсь, сам не написал какой именно не хватает. Именно глобальные переменные которые используются библиотеками и занимают динамическую память на 78% (дуня ругается) а проект еще не дописан. Память устройства пока что на уровне 47%. Библиотеки урезал уже но больших результатов не принесло, максимум на 10-15% уменьшается
у меня этот String с доп. печатаями создаёт две строки и 7 (семь!!!) раз запрашивает память.
Евгений, а как еще можно хранить строку, кроме String и char[] ? чтоб потом можно было с ней работать , выдерать маску, отсекать по маске и тд ?
у меня этот String с доп. печатаями создаёт две строки и 7 (семь!!!) раз запрашивает память.
Евгений, а как еще можно хранить строку, кроме String и char[] ? чтоб потом можно было с ней работать , выдерать маску, отсекать по маске и тд ?
Как вариант - отрабатывать побайтно online, и хранить не надо. Подробности в поиске по форумам и в интернете.
andycat побайтно хорошо но хранить то потом надо гдето эти байты ? вот я и спрашиваю где их хранить одной строкой если не в чаре и Стринге ?
Евгений, вы же сами говорите Стринг моветон. а к чару у меня личная неприязнь. вот в раздумьях чем заменить?
Хранить для чего и как долго?
Любое устройство делается для какой то цели, мне вот сложно представить зачем в устройстве на arduino хранить SMS, получили, выполнили команду, забыли.
http://arduino.ru/forum/apparatnye-voprosy/vse-o-sim800l-i-vse-chto-s-ni...
sadman41andycat
не :) не смс хранить на ардуине, а результат работы с смс, и хранить не как сторадж. а как переменная для работы. ну вот например получили смс, выдрать из него номер, команду. номер записать на сим, команду выполнить. так до тех пор пока я выполню команду и/или запишу на сим я должен в чем то хранить это всё ? или как?
//пока писал, andycat как в воду глядел :) сейчас почитаю
Аднака, лексический онализатор надо городить
Неизвестно, что там аффтар имеет в виду под строкой, но номер не "упаковать", команда... наврядли длинная. Временно 50 байт в памяти не выделить что ли?
БОльшая проблема в его масках - он, поди, думает, что тут с regexp можно так же жонглировать, как на PC.
Даа... Когда большие программисты вдруг начинают писать под маленькие процессоры, они такое городят. Столкнулся тут с библиотекой для "ESP32 arduino BLE" ( https://github.com/nkolban/ESP32_BLE_Arduino), вот это беда :( Там чел плотно юзает string из std и не только его но и контейнеры :), даже там где и без этого можно обойтись. Как результат - работают только примеры, шаг влево, шаг в право - крах :) Просто цирк.
работают только примеры
Но, работают же! Зато всё кошерно - используется стандартная библиотека :) Первый закон Скотта никто не отменял: «Неважно, что что-то идет неправильно. Возможно, это хорошо выглядит»
Я говорю??? Вы меня с кем-то путаете. Я как раз говорю, что использовать надо всё, но с умом и к месту: «всякий инструмент хорош, когда его используют умело и по назначению. Нельзя отказывать от инструмента потому, что в какой-то ситуации он неприменим. Нужно просто не применять его в той ситуации, а применять там, где от него наибольшая польза. Из того, что молотком неудобно красить стены, ещё не следует, что надо забивать гвозди малярной кистью»
Попробуйте какие-нибудь антиаллергены или психотерапию. Это базовый тип, и если у Вас на него аллергия, Вам будет очень трудно.
Да, выглядит это волшебно !!! Причем любой пример отжирает 95% флеша, если ESP используется в стандартной конфигурации. Это просто песня, а если учесть, что ESP как BLE совсем не экономит электричество, то эта библиотека просто не нужный мусор :(
А вот личная неприязнь к чару требует срочного посещения личного психолога, поскольку с такой неприязнью нужно забыть про си.
Брукли, а там с BLE-то как - полный фарш или только свиной? Произвольные характеристики можно со стороннего устройства читать (не как в HM-xx - только пару-тройку предустановленных) ?
В теории читать можно, можно даже список получить. Но оно постоянно рушится :( Причем, поскольку явных ошибок в отладке нет, есть подозрение, что это связано с переполнением стека. Но есть проблеммы и хужее... Оно виснет внутри библиотеки :) Причем глухо и безвозвратно. Похоже, что поток в котором обрабатываются данные просто засыпает или уничтожается. В общем эта библа просто муть. Но альтернатив нет, если только из ардуино вылезать в ESP. Кстати этот же автор и "родные" библиотеки писал, так что туда даже смотреть не хочется :(
Мне просто нужна была блешная кнопка, с iTAG ом вроде справился, но через такие грабли, самому аж страшно :(
sir, sadman41 #25 ?
sir, sadman41 #25 ?
Да это я так, для общего развития интересуюсь тенденциями приспособленчества ESP к нуждам ардуинщиков..
https://www.espressif.com/sites/default/files/documentation/esp32_bluetooth_networking_user_guide_en.pdf
1 ESP32 == the cost of a cup of coffee at Starbucks and the cost of BLE module == 24$
посмотрел ваш пример. у вас как _минимум_ три переменные для хранения ответа с Serialю о какой онлайн работе идёт речь ?
sadman41 тоже удивляется зачем чтото хранить. пока что все скетчи _хранят_. кто больше кто меньше. кто лучше кто хуже. пока не увидел ни одного примера работы с ответом без промежуточного хранения
Я не удивляюсь, а интересуюсь: что предполагается хранить и сколько времени.
Могу на пальцах описать три способа разбора входящего потока разной степени упоротости и с разными ресурсными затратами. Но надо чётко понимать, что экономя RAM теряем ROM.
Подброшу и я немного г**а в тему. Похоже народ уже давно забыл что такое потоки и данные. И что из чего получается. Идем на кухню и смотрим на мойку. Открыли кран , потекла вода . Итак это выдающий поток. Вода потекла на слив в канализацию - поглощающий поток. И все это замечательно работает на кухне когда у вас есть целая водокачка воды и развитая канализация эту воду убрать. Но в случае с маленьким процессором , то уже это дача без подачи воды и большой канализации. Что дождик накапал и вы сохранили то это ваша вода. А если дождик стал ливнем то уже проблема не в сохранении воды, а что бы дачку не смыло.
ПС: Это я все к тому , прежде чем экономить память, надо смотреть на погоду. Если идет мощный поток то выбирать только сливки. А если поток маленький то можно хранить все с пошлого года. И да фиксируйте время получения данных, и если данные устарели, то их можно сразу в унитаз , получив в результате лишнюю емкость для хранения.
сразу в унитаз , получив в результате лишнюю емкость для хранения.
Нещитова! Емкость дырявая и, стало быть в ней может храниться бесконечно количество данных. Это уже не контроллер, а машина Тьюринга получаецца!
Ну это понятно.На бесптичье и жопа и соловей. Но что бы не засыпать и не просыпаться под звук жопы, лучше приобрести что-то получше. Хотя может и есть любители такого пения.
в сериал порт приходят данные
Вам нужен алгоритм анализа? Ок, давайте по порядку:
1. Имеем некие строки для анализа;
2. По факту анализа надо что-то сделать;
3. Желательно избегать избыточного расхода памяти.
Анализируем входные данные: у нас есть подстрока "+CMT:", которая говорит нам, что с какого-то номера телефона пришло СМС, далее - сам номер телефона, далее - дата/время, текст СМС. В практически каждой прикладной задаче одним из условий является анализ номера телефона на список разрешённых, поэтому, не мудрствуя лукаво, мы примем необходимый размер промежуточного буфера в длину номера телефона, при этом считая, что СМС с командами - у нас тоже будет укладываться в выделенную длину.
По итогу получаем следующее:
Это один из примеров конечного автомата (просто пример логики, не законченный код) с ограниченным буфером для данных. Если же вам надо выкусить номер телефона и СМС в отдельные переменные, то подход примерно такой же - вам надо понять, что в начале строки пришло +CMT, далее выкусывать номер телефона в одну переменную, дождаться перевода строки, и с новой пришедшей строки до её конца - складывать всё в другую переменную - это будет текст СМС.
посмотрел ваш пример. у вас как _минимум_ три переменные для хранения ответа с Serialю о какой онлайн работе идёт речь ?
sadman41 тоже удивляется зачем чтото хранить. пока что все скетчи _хранят_. кто больше кто меньше. кто лучше кто хуже. пока не увидел ни одного примера работы с ответом без промежуточного хранения
"не нравится - не еште"
Где ж там три переменных то) аж самому интересно)
Используется два буфера char, 24 байта (кажется, не помню +-несколько байт) для общего буфера ответа модема, и буфер (16 байт вроде) для непосредственно команд (текст смс). Т е размер буферов чуть больше самой длинной возможной команды. Для разбора PDU формата там переменных дохрена.
Если закомментируете define которые отображение смс, лога, работа с экраном и с ds18b20, то если правильно помню займёт ~35 процентов памяти при полном функционале работы с смс - если сделаете меньше - просьба поделится - взять на вооружение.
пока что все скетчи _хранят_. кто больше кто меньше. кто лучше кто хуже. пока не увидел ни одного примера работы с ответом без промежуточного хранения
да никто с вами не спорит , если надо - храните. Если у вас куча лишнего места в программе - используйте String, если хотите экономить - переходите на char[]. "Личную непрязнь" придется как-то преодолеть, ибо практически вся работа со строками в микроконтроллерах построена на char[]
Иных вариантов, кроме этих двух - вообще не знаю.
Пух, тебе нада срочно преподавать аратарское искусство. Я аж всплакнулъ, как прецтавил унитаз и нещасные, упирающиеся данные.
По байтно раскладывать строчку и можно номера телефонов в память писать, значения переменных также всех видов вплоть до записи в память и присвоение значения переменной из текста смс
andycat я без притензий. думал есть какойто "налету" выдераем номер/команды.
"~35 процентов памяти при полном функционале работы с смс " что входит в полный функционал ? номр/команда/отправка что еще ?
да я уже понял что придеться всётаки работать с char. надеялся а в друг магия С может чтото еще :) в руби например красота работать со строками- imho
b707это я не смею ни с кем тут спорить :) чёто этот си с одной стороны какой простой такойже с другой и сложный :) вот например не понимаю. что за магия?
DIYMan а что разве у нас не вся строка +CMT: "+7963xxxxxxx","","16/12/05,22:17:28+20" разом приходит из буфера ?
char
ch = mySerial.read();
в буфер вроде помещяется 64 байта и они сразу все(<=64) оттуда вылеваються ?в буфер вроде помещяется 64 байта
А сколько помещается в Ваш
char
ch
?sizeof(int) = 2 [байта]. sizeof( 3 x int ) = ??? [байт]
DIYMan а что разве у нас не вся строка +CMT: "+7963xxxxxxx","","16/12/05,22:17:28+20" разом приходит из буфера ?
char
ch = mySerial.read();
в буфер вроде помещяется 64 байта и они сразу все(<=64) оттуда вылеваються ?А при чём тут 64 байта внутреннего буфера UART, который тащит Wiring? Я просто продемонстрировал, как можно _по_факту_ прихода байта в UART (а это может быть и без всяких буферов "из коробки" быть) - реагировать в зависимости от состояния системы. Для этого тащить буфер в 64 байта - необязательно, зачастую. Всё зависит от задачи.
andycat я представлял чтото подобное (на других платформах вполне реализуемое , незнаю как тут) я конечно не O`Reilly и могу ошибаться но на лету в моём понимании это так
без единой переменной. с учетом правильных команд конечно.
...щяз как закидают меня помидорами :)
...щяз как закидают меня помидорами :)
конечно закидают - как то тут уже говорили -> "поколение java/web, которое не в состоянии решить простейшую логическую задачу, т.к. привыкли одна команда==половина программы написана"
b707это я не смею ни с кем тут спорить :) чёто этот си с одной стороны какой простой такойже с другой и сложный :) вот например не понимаю. что за магия?
для тех кто буквы не разумеет - и чтение магия. Намек понятен?
Почитайте, что именно возвращает sizeof() , если вы ожидали. что он вернет число элементов в массиве - то это не так.
char
ch = mySerial.read();
в буфер вроде помещяется 64 байта и они сразу все(<=64) оттуда вылеваються ?Никогда (даже так - НИКОГДА) не стоит ожидать, что буфер Сериал вернет вам строку целиком. Это бывает, иногда, но если вы напишете программу в расчете на полную строку - она будет глючить два раза из трех. Всегда нужно закладыватся на то. что из Сериала вернется только кусок строчки - ваша программа должна проверить, вся ли строка получена - и если не вся, ждать продолжения и потом собирать полученную строчку из частей.
Да, такси и девочек вызывать не умеет :(
Поди, и корованы грабить тоже? :(
А зачем тогда такой код?
на лету в моём понимании это так
вы, наверно, сюда пришли из перла или из питона? или руби - тот же перл? - я на перле 20 лет пишу
Должен вас огорчить - по сравнению с Перлом работа со строками в Си для МК - это как перекапывание огорода лопатой вместо трактора... даже не лопатой. а детским совочком. Все нужно делать вручную с каждым символом отдельно.