Перейти к содержанию

Sim900 + Длинное Смс


Рекомендуемые сообщения

Доброго времени суток, уважаемые!

Собственно, есть вот такой вот примерчик отсюда

http://wiki.amperka.ru/%D0%B1%D0%B5%...8C:gprs-shield

Меня интересует прием смс

#include <SoftwareSerial.h>

SoftwareSerial gprsSerial(7, 8);

//для зелёного светодиода будем использовать второй цифровой вход,
//а для жёлтого - третий
int greenPin = 2;
int yellowPin = 3;

void setup()
{
   gprsSerial.begin(19200);
   pinMode(greenPin, OUTPUT);
   pinMode(yellowPin, OUTPUT);

   // Настраиваем приём сообщений с других устройств
   // Между командами даём время на их обработку
   gprsSerial.print("AT+CMGF=1\r");
   delay(300);
   gprsSerial.print("AT+IFC=1, 1\r");
   delay(300);
   gprsSerial.print("AT+CPBS="SM"\r");
   delay(300);
   gprsSerial.print("AT+CNMI=1,2,2,1,0\r");
   delay(500);
}

String currStr = "";
// Переменная принимает значение True, если текущая строка является сообщением
boolean isStringMessage = false;

void loop()
{
   if (!gprsSerial.available())
       return;

   char currSymb = gprsSerial.read();   
   if ('\r' == currSymb) {
       if (isStringMessage) {
           //если текущая строка - SMS-сообщение,
           //отреагируем на него соответствующим образом
           if (!currStr.compareTo("Green on")) {
               digitalWrite(greenPin, HIGH);
           } else if (!currStr.compareTo("Green off")) {
               digitalWrite(greenPin, LOW);
           } else if (!currStr.compareTo("Yellow on")) {
               digitalWrite(yellowPin, HIGH);
           } else if (!currStr.compareTo("Yellow off")) {
               digitalWrite(yellowPin, LOW);
           }
           isStringMessage = false;
       } else {
           if (currStr.startsWith("+CMT")) {
               //если текущая строка начинается с "+CMT",
               //то следующая строка является сообщением
               isStringMessage = true;
           }
       }
       currStr = "";
   } else if ('\n' != currSymb) {
       currStr += String(currSymb);
   }
}

Читаем сериал GSM, собираем строку и отлавливаем по окончании строки флажок - СМС сообщение (+CMT)

Далее читаем продолжение этого самого смс сообщения...Но вот в чем проблема - Когда приходит первая часть смс в виде

+CMT: "+79999999999","NAME","16/01/28,00:36:38+24"

эта самая часть видимо умещается в 64 символа и все бы ничего, если бы вторая часть сообщения умещалась в эти же самые 64 символа. Не знаю почему, но модуль не умеет скорее всего принимать все 160 символов разрешенные на одну смс и пересылает 160 символов частями по 64...

Поэтому запустив данный пример и отослав просто сообщение длинной в 140 символов ничего кроме вышеупомянутой строки в монитере порта я не увидел. Отослав же сообщение длинной в 60 символов мы видим все красиво

+CMT: "+79999999999","NAME","16/01/28,00:36:38+24"

qwerty qwerty qwerty qwerty

Вопрос - каким образом можно собрать строку из этих частей оставшихся, если сообщение больше 64 символов?

Пробовал таким способом, непосредственно с вики

if (gprsSerial.available()) // if date is comming from softwareserial port ==> data is comming from gprs shield
{
  while (gprsSerial.available()) // reading data into char array
  {
    bufGsm[countBufGsm++] = gprsSerial.read(); // writing data into array
    if (countBufGsm == 64)
    {
      break;
    }
  }
   Serial.write(buffer, count);   
  clearBufferArray(); // call clearBufferArray function to clear the storaged data from the array
  countBufGsm = 0; // set counter of while loop to zero
}

И вроде даже в Serial.write(buffer, count); выводится полное сообщение но опять же каким образом тут можно собрать строку?

Пытался сделать следующее

char bufGsm[64]; // buffer array for data recieve over serial port
String inputGsmStr = ""; //входящая строка с gsm модема
int countBufGsm = 0;

void Manage()
{
if (gprsSerial.available()) // if date is comming from softwareserial port ==> data is comming from gprs shield
 {
   while (gprsSerial.available()) // reading data into char array
   {
     bufGsm[countBufGsm++] = gprsSerial.read(); // writing data into array
     if (countBufGsm == 64)
     {
       break;
     }
   }
    inputGsmStr +=   bufGsm;
   clearBufferArray(); // call clearBufferArray function to clear the storaged data from the array
   countBufGsm = 0; // set counter of while loop to zero
 }
}

void clearBufferArray() // function to clear buffer array
{
 for (int i = 0; i < countBufGsm; i++)
 {
   bufGsm[i] = NULL;
 }
}

Но выходит что каждый раз когда мы отрезаем часть по 64 и дописываем в строку, то в inputGsmStr записываются те самые части по 64, потом 128 и т.д..она растет постоянно до тех пор пока не получим полную строку. В таком случае функция проверки, что это СМС сообщение запустится столько раз, сколько у нас частей по 64...

Какие идеи?

Изменено пользователем KorPaEv
Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

какая версия прошивки и самого модуля?

а вот версию прошивки не проверял...отпишу как проверю...

Изменено пользователем KorPaEv
Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Победил проблему, может кому и понадобится...

А смысл вот в чем. Как сказано выше gsm посылает любую смс - будь то одинарная или составная превышающая 160 для латиницы или 64 для кириллицы символов, частями по 64 символа...

Поэтому ваша смс придет в виде - заголовок + основное тело смс.

Основное тело смс может опять же состоять из нескольких строк, если встретился символ конца строки то его надо добавить в строку которую мы собираем и будем дальше анализировать.

Например пришла смс в виде

\r\n +CMT: "+79999999999","NAME","16/01/28,00:36:38+24" \r\n

1234567890 \n

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

Далее бегу по каждому символу строки и собираю подстроку. Как только отлавливаю конец строки, дописываю кего в подстроку и получаю подстроку вида

+CMT: "+79999999999","NAME","16/01/28,00:36:38+24" \r\n

Анализирую то что в ней лежит и поднимаю флажок, что дальше будет тело самой СМС..

Бежим дальше по циклу, отловили опять конец строки - собрали новую подстроку вида

1234567890 \n

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

Как то так.

#include <SoftwareSerial.h>
SoftwareSerial gprsSerial(10, 11); //На меге работает у меня на 10 и 11 пинах, потому как 7 и 8 занят прерываниями

//инициализация
void setup(void)
{
 // Стартуем порт COM
 Serial.begin(9600);
//Стартуем GSM
 InitGprs();
}

//Инициализация и старт GSM модуля
void InitGprs()
{
 gprsSerial.begin(9600);
 gprsSerial.print("AT+CMGF=1\r");
 delay(300);
 gprsSerial.print("AT+IFC=1, 1\r");
 delay(300);
 gprsSerial.print("AT+CPBS="SM"\r");
 delay(300);
 gprsSerial.print("AT+CNMI=1,2,2,1,0\r");
 delay(500);
 //Включаем GPRS Shield, эмулируя нажатие кнопки POWER
 pinMode(9, OUTPUT);
 digitalWrite(9, HIGH);    // Подаем High на пин 9
 delay(3000);			  // на 3 секунды
 digitalWrite(9, LOW);	 // и отпускаем в Low.
 delay(5000);			  // Ждём 5 секунд для старта шилда
}

void loop(void)
{
 GsmShieldManage();
}

//Обработка смс приемника-передатчика
//----------------------------------
boolean isStringMessage = false;
String currentNumber = ""; //Текущий номер с которого пришло смс
char bufGsm[64]; // Буфер для данных из смс поому что модуль GSM посылает кусками любую смс
String inputGsmFullStr = ""; //входящая строка с gsm модема - полная
String lineFullStr = ""; // Входная строка построчно из inputGsmFullStr
int countBufGsm = 0; // счетчик символов для буфера
//----------------------------------
void GsmShieldManage()
{
 // Если что то начало падать в GSM
 if (gprsSerial.available())
 {
   // Читаем данные частями в буфер
   while (gprsSerial.available())
   {
  // Пишем буфер по 64 символа
  bufGsm[countBufGsm++] = gprsSerial.read();
  if (countBufGsm == 64)
  {
    break;
  }
   }
   // Собираем строку полную - в том числе и заголовок
   inputGsmFullStr += bufGsm;
   // Функция очистки буфера
   clearBufferArray();
   // Сбрасываем счетчик символов
   countBufGsm = 0;
 }
 // иначе если прекращена передача данных то строка собрана
 else
 {
   //Если строка не пустая
   if (inputGsmFullStr != "")
   {
  //Очистили подстроку главной строки
  lineFullStr = "";
Serial.println("Curr str = " + inputGsmFullStr);
  //Читаем посимвольно нашу полную СМС и выдергиваем оттуда подстроки
  //А вид она имеет следующий  \r\n +CMT: "+79999999999","NAME","16/01/28,00:36:38+24" \r\n
  //						    1234567890 \n
  //						    1234567890 \r\n
  for (int i = 0; i < inputGsmFullStr.length(); i++)
  {
    //Если находим символ возврата каретки
    if (inputGsmFullStr.charAt(i) == '\r')
    {
Serial.println("SEPARATOR END LINE (R) FOUND");
	  // если это продолжение полной смс - само тело без заголовка - 1234567890 \n - то обрабатываем то что внутри (команды)
	  if (isStringMessage)
	  {		 
Serial.println("IS STR MESSAGE OK: " + lineFullStr);
	    //Обработка команд
	    if (!lineFullStr.compareTo("BAL"))
	    {
		  // делаем запрос баланса (мтс), а ответ ловится в блоке ниже...
		  gprsSerial.print("ATD#100#;\r");
	    }
		 //Если входная строка содержит "ADD" значит там команда может  быть составной
	    //Она имеет вид ADDNUM;1;+79999999999;1;1;1
	    //					 ADDINF;Ard001; SomeTEXT
	    else if (StringContains(lineFullStr, "ADD"))
	    {
		  //Ищем количество разделителей в lineFullStr (Тело смс) - это может быть и несколько строк
		  byte countStr = 0;
		  for (int j = 0; j < lineFullStr.length(); j++)
		  {
		    if (lineFullStr.charAt(j) == '\n')
			  countStr++;
		  }
		  String subLineFullStr = ""; // отдельная подстрока lineFullStr
		  for (int i = 0; i < countStr; i++)
		  {
		    //Нашли строку по символу конца строки
		    subLineFullStr = splitString(lineFullStr, '\n', i);
		    //Смотрим команду
		    if (StringContains(subLineFullStr, "ADDNUM"))
		    {
			  //ЧТО ТО ДЕЛАЕМ
		    }
		    //Если строка содержит "ADDINF"
		    if (StringContains(currSubStr, "ADDINF"))
		    {
			  //ЧТО ТО ДЕЛАЕМ
		    }
		  }
	    }
	    isStringMessage = false;
	  }
	  else
	  {
	    // если это текстовое сообщение
	    if (StringContains(lineFullStr, "+CMT"))
	    {			
Serial.println("IS MESSAGE: " + lineFullStr);			
		  // читаем текущий номер с которого смс пришло
		  currentNumber = lineFullStr.substring(lineFullStr.indexOf(""") + 1, lineFullStr.indexOf(",") - 1);
Serial.println(currentNumber);	 
		  //Подняли флажок что это текстовое сообщение	  
		  isStringMessage = true;
	    }
	    // если это звонок
	    if (lineFullStr.startsWith("+CLIP"))
	    {
Serial.println("CALL");
		  //считали текущий номер и просто ждем 3 сек и скидываем
		  currentNumber = lineFullStr.substring(lineFullStr.indexOf("""), lineFullStr.indexOf(","));
Serial.println(currentNumber);
		  delay(3000);
		  gprsSerial.println("ATH0");
	    }
	    // этот блок отлавливает ответ на запрос баланса и отправляет его смской
	    if (lineFullStr.startsWith("+CUSD"))
	    {
		  lineFullStr = lineFullStr.substring(lineFullStr.indexOf("Balance"), lineFullStr.indexOf("r"));
		  delay(1500);
		  lineFullStr += " is your balance of number " + currentNumber;
		  SendSms(currentNumber, lineFullStr);
	    }
	  }
	  lineFullStr = "";
    } // end if (inputGsmFullStr.charAt(i) == '\r')
    else if ('\n' != inputGsmFullStr.charAt(i))
    {
	  lineFullStr += inputGsmFullStr.charAt(i);
    }
    else if ('\n' == inputGsmFullStr.charAt(i))
    {
	  lineFullStr += '\n';
    }
  }
   }
   inputGsmFullStr = ""; //Очищаем то что пришло с GSM
 }
}

void clearBufferArray() // function to clear buffer array
{
 for (int i = 0; i < countBufGsm; i++)
 {
   bufGsm[i] = NULL;
 }
}

Ссылка на комментарий
Поделиться на другие сайты

  • 2 месяца спустя...

Победил проблему, может кому и понадобится...

А смысл вот в чем. Как сказано выше gsm посылает любую смс - будь то одинарная или составная превышающая 160 для латиницы или 64 для кириллицы символов, частями по 64 символа...

Поэтому ваша смс придет в виде - заголовок + основное тело смс.

[/code]

Тоже бился с этим.

Оказывается в библиотеке - SoftwareSerial library included with the distribution (instead of NewSoftSerial). However, you must be aware that the buffer reserved for incoming messages are hardcoded to 64 bytes in the library header, "SoftwareSerial.h": 1.define _SS_MAX_RX_BUFF 64 // RX buffer size

вот откуда эти 64 бита, можно _SS_MAX_RX_BUFF изменить размер

НО!! только кратно 64, ставил 100, 120 - получаю кракозябры, поставил 128 - все норм, и СМС длинные приходят.

Ссылка на комментарий
Поделиться на другие сайты

  • 3 месяца спустя...

Добрый день. Подскажите пожалуйста люди добрые, как сделать автоматический ответ на смс. То есть написал смс ардуино прочитала, проверила команду, выполнила действие, и ответила смс-кой на номер с которого пришел запрос. Все по отдельности реализовал, прием сообщения, проверка команды, отработка команды и отдельно смог реализовать автоответ смс-кой через библиотеку sim900. А в одно целое собрать не получается.

Arduino Uno r3

Shield Sim900

За ранее благодарен.

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы публикуете как гость. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...