16 июня 2019 г
Arduino. Отправка СМС. Отладка
Плата Arduino Uno и SIM900 GPRS/GSM Shield
драйвер для USB-UART CH340/CH341 (Windows)
Блок питания (например, такой)
код скетча.
#define response_size 100
// подключение библиотеки SoftwareSerial
#include <SoftwareSerial.h>
// Выводы для SoftwareSerial
SoftwareSerial Sim900Serial(7, 8); //Sim900Serial(2, 3); // RX, TX
char response[response_size]; // это буфер для служебного текста ответов сервера
uint8_t answer;
char telNumber[15] = "+79119991111";
char textSMS[15] = "Hello, World!";
char messageId[10];
void setup()
{
Sim900Serial.begin(19200);
Serial.begin(19200);
}
void loop()
{
if ( Serial.available() ){
while( Serial.available() > 0)
Serial.read(); // Clean the input buffer
Serial.println("Debug...");
answer = SendTextMessage(telNumber, textSMS, messageId); // отправить sms
if (answer != 0){
Serial.print("error of sending\n");
Serial.println(response); // вывод всего пришедшего ответа
} else{
Serial.print("Sms is sended. id - ");
Serial.println(messageId);
}
}
//debug
delay(3000);
} // main loop
// обработка большинства команд завершается на stepP == 1
uint8_t read_answer_SMS(const char * AtCommand, const char * expected_answer, char * messId, char * text){
unsigned long previous;
uint8_t x, answer;
int avail;
char * istr;
int pars = 0, stepP = 0;
char * cc, * ccEnd;
x = 0;
previous = millis();
size_t sz, sz_ea;
sz = strlen(AtCommand);
sz_ea = strlen(expected_answer);
answer = 1; // error
while( Sim900Serial.available() > 0)
Sim900Serial.read(); // Clean the input buffer
memset(response, '\0', response_size); // Initialize the string
Sim900Serial.print(AtCommand); // Отправка AT команды
Sim900Serial.print("\r");
while ( ((millis() - previous) < 5000) ){ // timeout нужно скидывать, когда получаю байты данных
if ( Sim900Serial.available() > 0 ) {
avail = Sim900Serial.read();
//Serial.println(avail, DEC);
response[x] = avail;
x++;
//парсинг ответа
if ( stepP == 0 ){
istr = strstr ( response + pars, AtCommand);
if ( istr != NULL ){
pars = (istr - response) + sz;
stepP = 1;
}
} else if ( stepP == 1 ){
if (sz_ea == 0){ //передана пустая строка в expected_answer (в этой команде ждем ОК и завершаем обарботку;
//Serial.println(avail, DEC);
istr = strstr ( response + pars , "OK\r\n"); //not "OK\r"
if ( istr != NULL ){
answer = 0;
break;
}else{
istr = strstr ( response + pars , "ERROR\r\n"); // нужно ли это ?
if ( istr != NULL ){
break;
}
}
}else{
// сюда пока попадает только, если отправлена команда AT+CMGS ="+79...", требующая доп обработки
//Serial.println(avail, DEC);
istr = strstr ( response + pars , "> "); /* \62\32 */
if ( istr != NULL ){
/* delay(100);
if ( Sim900Serial.available() > 0){
Serial.print("avail ! : ");
avail = Sim900Serial.read();
Serial.println(avail, DEC);
response[x] = avail;
x++;
}
delay(50);
if ( Sim900Serial.available() > 0){
Serial.println("avail one more! : ");
}
*/
Sim900Serial.print(text); // ??? при \r\n вместо \r можно отправить второе сообщение
// ASCII код ctrl+z - окончание передачи
Sim900Serial.print((char)26);
pars = (istr - response) + 2; // 2 - "> "
stepP = 2;
continue;
}
}
}else if ( stepP == 2 ){
istr = strstr ( response + pars, expected_answer); // +CMGS: // пример: "+CMGS: 60"
if ( istr != NULL ){
pars = (istr - response) + sz_ea + 1; // пропускаем пробел. встаем на начало данных (уид сообщения)
cc = response + pars; // cc - начало данных
stepP = 3;
}
}else if ( stepP == 3 ){
ccEnd = strstr(cc, "\r\n"); // конец
if ( ccEnd != NULL ){
//можно проверить на NULL
strncpy (messId, cc, ccEnd - cc);
messId[ccEnd - cc] = '\0'; // добавить в конец строки символ конца строки
//break;
pars = (ccEnd - response) + 2;
stepP = 4;
continue;
}
}else if ( stepP == 4 ){
istr = strstr ( response + pars , "OK\r\n");
if ( istr != NULL ){
answer = 0;
break;
}
}
}
}
response[x] = '\0';
//Serial.println(response); // вывод всего пришедшего ответа
return answer;
} // read_answer_SMS()
//////////////////////////////////////////////////////////////////////////////////////////////
// процедура отправки sms
uint8_t SendTextMessage(char * telNum, char * text, char * messId){
uint8_t answer = 0; //ok
char fullATCMGS[25];
// AT-команда установки text mode
//Serial.println("send AT+CMGF=1");
answer = read_answer_SMS("AT+CMGF=1", "", NULL, NULL);
if (answer != 0)
return answer;
// ответы приходят в таком виде:
// "AT+CMGF=1\r\r\nOK\r\n" // после команды именно \r\r\n . read_answer_SMS() на это не расчитывает, но это канает
//Serial.println("send AT+CSCS= \"GSM\""); //Выбор ASCII кодировки.
answer = read_answer_SMS("AT+CSCS= \"GSM\"", "", NULL, NULL);
if (answer != 0)
return answer;
/*Sim900Serial.print("AT+CSCS= \"GSM\"\r");
//debug
delay(100);
while ( Sim900Serial.available() )
Serial.write ( Sim900Serial.read() );
//
*/
//delay(100);
// AT+CMGS=<number><CR><message><CTRL-Z> :
// 1. отправляем AT+CMGS=<number><CR>
// 2. ждем приглашения сервера ( "> " ).
// 3. отправляем <message><CTRL-Z>
// 4. ждем подтверждение сервера:
/*<message>
*+CMGS: <mr>
*
*OK
*/
// <mr> is the message reference.
sprintf(fullATCMGS, "AT+CMGS=\"%s\"", telNum); // "AT+CMGS=\"+79111111111\""
answer = read_answer_SMS(fullATCMGS, "+CMGS:", messId, text);
if (answer != 0)
return answer;
return answer;
}
// https://stackoverflow.com/questions/21522794/atcmgs-returns-error
// http://www.2150692.ru/faq/47-at-komandy-a6
//
// про UDP (отправка СМС в т.ч. русскими буквами)
// http://hardisoft.ru/soft/samodelkin-soft/poluchenie-i-dekodirovanie-sms-soobshhenij-v-formate-pdu/
// там и про обычные СМС и про Длинные
Подключаем питания плат(SIM900 GPRS/GSM Shield тоже. На одном общем питании обеих плат через USB шилд не работает на 100%). Прошиваем Arduino. Открываем Монитор порта. Вводим любые символы. Отправляем в порт. Получаем СМС на свой номер и отладочную информацию в мониторе порта. Если есть какие-то ошибки, то корректируем команды (AT), отправляемые на сервер.
СМС :
Комментарии
привет.