Sim900 + длинное смс
- Войдите на сайт для отправки комментариев
Была как то давно создана подобная тема и никто ничего не ответил.
Собственно, есть вот такой вот примерчик отсюда http://wiki.amperka.ru/%D0%B1%D0%B5%D1%81%D0%BF%D1%80%D0%BE%D0%B2%D0%BE%D0%B4%D0%BD%D0%B0%D1%8F-%D1%81%D0%B2%D1%8F%D0%B7%D1%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 символов ничего кроме вышеупомянутой строки в монитере порта я не увидел. Отослав же сообщение длинной в 100 символов мы видим все красиво
+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
}
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...
Какие идеи?
Отослав же сообщение длинной в 100 символов
Опечатался - не 100, а 60 символов...
Победил проблему, может кому и понадобится...
А смысл вот в чем. Как сказано выше 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; } }