├── GSM.cpp ├── GSM.h ├── HWSerial.cpp ├── HWSerial.h ├── LICENSE ├── LOG.cpp ├── LOG.h ├── README ├── README.md ├── SIM900.cpp ├── SIM900.h ├── Streaming.h ├── WideTextFinder.cpp ├── WideTextFinder.h ├── bluetooth.cpp ├── bluetooth.h ├── call.cpp ├── call.h ├── doc ├── Instructions.txt ├── InstructionsBlueTooth.txt ├── InstructionsForGBoardPro800.txt └── List.txt ├── examples ├── GSM_GPRSLibrary_AT │ └── GSM_GPRSLibrary_AT.ino ├── GSM_GPRSLibrary_BlueTooth_Connect │ └── GSM_GPRSLibrary_BlueTooth_Connect.ino ├── GSM_GPRSLibrary_BlueTooth_SPP │ └── GSM_GPRSLibrary_BlueTooth_SPP.ino ├── GSM_GPRSLibrary_Call │ └── GSM_GPRSLibrary_Call.ino ├── GSM_GPRSLibrary_Client │ └── GSM_GPRSLibrary_Client.ino ├── GSM_GPRSLibrary_DTMF │ └── GSM_GPRSLibrary_DTMF.ino ├── GSM_GPRSLibrary_GPS │ └── GSM_GPRSLibrary_GPS.ino ├── GSM_GPRSLibrary_SMS │ └── GSM_GPRSLibrary_SMS.ino └── GSM_GPRSLibrary_Server │ └── GSM_GPRSLibrary_Server.ino ├── gps.cpp ├── gps.h ├── inetGSM.cpp ├── inetGSM.h ├── sms.cpp └── sms.h /GSM.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This is a Beta version. 3 | last modified 18/08/2012. 4 | 5 | This library is based on one developed by Arduino Labs 6 | and it is modified to preserve the compability 7 | with the Arduino's product. 8 | 9 | The library is modified to use the GSM Shield, 10 | developed by www.open-electronics.org 11 | (http://www.open-electronics.org/arduino-gsm-shield/) 12 | and based on SIM900 chip, 13 | with the same commands of Arduino Shield, 14 | based on QuectelM10 chip. 15 | */ 16 | 17 | #include "GSM.h" 18 | #include "WideTextFinder.h" 19 | 20 | //De-comment this two lines below if you have the 21 | //first version of GSM GPRS Shield 22 | //#define _GSM_TXPIN_ 4 23 | //#define _GSM_RXPIN_ 5 24 | 25 | //De-comment this two lines below if you have the 26 | //second version og GSM GPRS Shield 27 | #define _GSM_TXPIN_ 2 28 | #define _GSM_RXPIN_ 3 29 | 30 | #ifdef UNO 31 | GSM::GSM():_cell(_GSM_TXPIN_,_GSM_RXPIN_),_tf(_cell, 10),_status(IDLE) 32 | { 33 | }; 34 | #endif 35 | #ifdef MEGA 36 | GSM::GSM() 37 | { 38 | _cell.begin(9600); 39 | }; 40 | #endif 41 | 42 | 43 | int GSM::begin(long baud_rate) 44 | { 45 | // Set pin modes 46 | pinMode(GSM_ON,OUTPUT); 47 | pinMode(GSM_RESET,OUTPUT); 48 | 49 | #ifdef UNO 50 | if (baud_rate==115200) { 51 | Serial.println(F("Don't use baudrate 115200 with Software Serial.\nAutomatically changed at 9600.")); 52 | baud_rate=9600; 53 | } 54 | #endif 55 | int response=-1; 56 | int cont=0; 57 | boolean norep=true; 58 | boolean turnedON=false; 59 | SetCommLineStatus(CLS_ATCMD); 60 | _cell.begin(baud_rate); 61 | p_comm_buf = &comm_buf[0]; 62 | setStatus(IDLE); 63 | 64 | // if no-reply we turn to turn on the module 65 | for (cont=0; cont<3; cont++) { 66 | if (AT_RESP_ERR_NO_RESP == SendATCmdWaitResp(str_at, 500, 100, str_ok, 5)&&!turnedON) { //check power 67 | // there is no response => turn on the module 68 | #ifdef DEBUG_ON 69 | Serial.println(F("DB:NO RESP")); 70 | #endif 71 | // generate turn on pulse 72 | digitalWrite(GSM_ON, HIGH); 73 | delay(1200); 74 | digitalWrite(GSM_ON, LOW); 75 | delay(10000); 76 | WaitResp(1000, 1000); 77 | } else { 78 | #ifdef DEBUG_ON 79 | Serial.println(F("DB:ELSE")); 80 | #endif 81 | WaitResp(1000, 1000); 82 | } 83 | } 84 | 85 | 86 | if (AT_RESP_OK == SendATCmdWaitResp(str_at, 500, 100, str_ok, 5)) { 87 | #ifdef DEBUG_ON 88 | Serial.println(F("DB:CORRECT BR")); 89 | #endif 90 | turnedON=true; 91 | norep=false; 92 | } 93 | 94 | 95 | if (AT_RESP_ERR_DIF_RESP == SendATCmdWaitResp(str_at, 500, 100, str_ok, 5)&&!turnedON) { //check OK 96 | #ifdef DEBUG_ON 97 | Serial.println(F("DB:AUTO BAUD RATE")); 98 | #endif 99 | for (int i=0; i<8; i++) { 100 | switch (i) { 101 | case 0: 102 | _cell.begin(1200); 103 | break; 104 | 105 | case 1: 106 | _cell.begin(2400); 107 | break; 108 | 109 | case 2: 110 | _cell.begin(4800); 111 | break; 112 | 113 | case 3: 114 | _cell.begin(9600); 115 | break; 116 | 117 | case 4: 118 | _cell.begin(19200); 119 | break; 120 | 121 | case 5: 122 | _cell.begin(38400); 123 | break; 124 | 125 | case 6: 126 | _cell.begin(57600); 127 | break; 128 | 129 | case 7: 130 | _cell.begin(115200); 131 | break; 132 | 133 | // if nothing else matches, do the default 134 | // default is optional 135 | } 136 | 137 | delay(100); 138 | 139 | #ifdef DEBUG_PRINT 140 | // parameter 0 - because module is off so it is not necessary 141 | // to send finish AT here 142 | DebugPrint(F("DEBUG: Stringa "), 0); 143 | DebugPrint(buff, 0); 144 | #endif 145 | 146 | 147 | if (AT_RESP_OK == SendATCmdWaitResp(str_at, 500, 100, str_ok, 5)) { 148 | #ifdef DEBUG_ON 149 | Serial.println(F("DB:FOUND PREV BR")); 150 | #endif 151 | _cell.print("AT+IPR="); 152 | _cell.print(baud_rate); 153 | _cell.print("\r"); // send 154 | delay(500); 155 | _cell.begin(baud_rate); 156 | delay(100); 157 | if (AT_RESP_OK == SendATCmdWaitResp(str_at, 500, 100, str_ok, 5)) { 158 | #ifdef DEBUG_ON 159 | Serial.println(F("DB:OK BR")); 160 | #endif 161 | } 162 | turnedON=true; 163 | break; 164 | } 165 | #ifdef DEBUG_ON 166 | Serial.println(F("DB:NO BR")); 167 | #endif 168 | } 169 | // communication line is not used yet = free 170 | SetCommLineStatus(CLS_FREE); 171 | // pointer is initialized to the first item of comm. buffer 172 | p_comm_buf = &comm_buf[0]; 173 | } 174 | 175 | if(norep==true&&!turnedON) { 176 | Serial.println(F("Trying to force the baud-rate to 9600\n")); 177 | for (int i=0; i<8; i++) { 178 | switch (i) { 179 | case 0: 180 | _cell.begin(1200); 181 | delay(1000); 182 | Serial.println(F("1200")); 183 | _cell.print(F("AT+IPR=9600\r")); 184 | delay(1000); 185 | _cell.begin(9600); 186 | delay(1000); 187 | SendATCmdWaitResp(str_at, 500, 100, str_ok, 5); 188 | delay(1000); 189 | WaitResp(1000,1000); 190 | break; 191 | 192 | case 1: 193 | _cell.begin(2400); 194 | delay(1000); 195 | Serial.println(F("2400")); 196 | _cell.print(F("AT+IPR=9600\r")); 197 | delay(1000); 198 | _cell.begin(9600); 199 | delay(1000); 200 | SendATCmdWaitResp(str_at, 500, 100, str_ok, 5); 201 | delay(1000); 202 | WaitResp(1000,1000); 203 | break; 204 | 205 | case 2: 206 | _cell.begin(4800); 207 | delay(1000); 208 | Serial.println(F("4800")); 209 | _cell.print(F("AT+IPR=9600\r")); 210 | delay(1000); 211 | _cell.begin(9600); 212 | delay(1000); 213 | SendATCmdWaitResp(str_at, 500, 100, str_ok, 5); 214 | delay(1000); 215 | WaitResp(1000,1000); 216 | break; 217 | 218 | case 3: 219 | _cell.begin(9600); 220 | delay(1000); 221 | Serial.println(F("9600")); 222 | _cell.print(F("AT+IPR=9600\r")); 223 | delay(1000); 224 | _cell.begin(9600); 225 | delay(1000); 226 | SendATCmdWaitResp(str_at, 500, 100, str_ok, 5); 227 | delay(1000); 228 | WaitResp(1000,1000); 229 | break; 230 | 231 | case 4: 232 | _cell.begin(19200); 233 | delay(1000); 234 | Serial.println(F("19200")); 235 | _cell.print(F("AT+IPR=9600\r")); 236 | delay(1000); 237 | _cell.begin(9600); 238 | delay(1000); 239 | SendATCmdWaitResp(str_at, 500, 100, str_ok, 5); 240 | delay(1000); 241 | WaitResp(1000,1000); 242 | break; 243 | 244 | case 5: 245 | _cell.begin(38400); 246 | delay(1000); 247 | Serial.println(F("38400")); 248 | _cell.print(F("AT+IPR=9600\r")); 249 | delay(1000); 250 | _cell.begin(9600); 251 | delay(1000); 252 | SendATCmdWaitResp(str_at, 500, 100, str_ok, 5); 253 | delay(1000); 254 | WaitResp(1000,1000); 255 | break; 256 | 257 | case 6: 258 | _cell.begin(57600); 259 | delay(1000); 260 | Serial.println(F("57600")); 261 | _cell.print(F("AT+IPR=9600\r")); 262 | delay(1000); 263 | _cell.begin(9600); 264 | delay(1000); 265 | SendATCmdWaitResp(str_at, 500, 100, str_ok, 5); 266 | delay(1000); 267 | WaitResp(1000,1000); 268 | break; 269 | 270 | case 7: 271 | _cell.begin(115200); 272 | delay(1000); 273 | Serial.println(F("115200")); 274 | _cell.print(F("AT+IPR=9600\r")); 275 | delay(1000); 276 | _cell.begin(9600); 277 | delay(1000); 278 | SendATCmdWaitResp(str_at, 500, 100, str_ok, 5); 279 | delay(1000); 280 | WaitResp(1000,1000); 281 | break; 282 | } 283 | } 284 | 285 | Serial.println(F("ERROR: SIM900 doesn't answer. Check power and serial pins in GSM.cpp")); 286 | digitalWrite(GSM_ON, HIGH); 287 | delay(1200); 288 | digitalWrite(GSM_ON, LOW); 289 | delay(10000); 290 | return 0; 291 | } 292 | 293 | SetCommLineStatus(CLS_FREE); 294 | 295 | if(turnedON) { 296 | WaitResp(50, 50); 297 | InitParam(PARAM_SET_0); 298 | InitParam(PARAM_SET_1);//configure the module 299 | Echo(0); //enable AT echo 300 | setStatus(READY); 301 | return(1); 302 | 303 | } else { 304 | //just to try to fix some problems with 115200 baudrate 305 | _cell.begin(115200); 306 | delay(1000); 307 | _cell.print("AT+IPR="); 308 | _cell.print(baud_rate); 309 | _cell.print("\r"); // send 310 | return(0); 311 | } 312 | } 313 | 314 | 315 | void GSM::InitParam(byte group) 316 | { 317 | switch (group) { 318 | case PARAM_SET_0: 319 | // check comm line 320 | //if (CLS_FREE != GetCommLineStatus()) return; 321 | 322 | SetCommLineStatus(CLS_ATCMD); 323 | // Reset to the factory settings 324 | SendATCmdWaitResp(F("AT&F"), 1000, 50, str_ok, 5); 325 | // switch off echo 326 | SendATCmdWaitResp(F("ATE0"), 500, 50, str_ok, 5); 327 | // setup fixed baud rate 328 | //SendATCmdWaitResp("AT+IPR=9600", 500, 50, str_ok, 5); 329 | // setup mode 330 | //SendATCmdWaitResp("AT#SELINT=1", 500, 50, str_ok, 5); 331 | // Switch ON User LED - just as signalization we are here 332 | //SendATCmdWaitResp("AT#GPIO=8,1,1", 500, 50, str_ok, 5); 333 | // Sets GPIO9 as an input = user button 334 | //SendATCmdWaitResp("AT#GPIO=9,0,0", 500, 50, str_ok, 5); 335 | // allow audio amplifier control 336 | //SendATCmdWaitResp("AT#GPIO=5,0,2", 500, 50, str_ok, 5); 337 | // Switch OFF User LED- just as signalization we are finished 338 | //SendATCmdWaitResp("AT#GPIO=8,0,1", 500, 50, str_ok, 5); 339 | SetCommLineStatus(CLS_FREE); 340 | break; 341 | 342 | case PARAM_SET_1: 343 | // check comm line 344 | //if (CLS_FREE != GetCommLineStatus()) return; 345 | SetCommLineStatus(CLS_ATCMD); 346 | // Request calling line identification 347 | SendATCmdWaitResp(F("AT+CLIP=1"), 500, 50, str_ok, 5); 348 | // Mobile Equipment Error Code 349 | SendATCmdWaitResp(F("AT+CMEE=0"), 500, 50, str_ok, 5); 350 | // Echo canceller enabled 351 | //SendATCmdWaitResp("AT#SHFEC=1", 500, 50, str_ok, 5); 352 | // Ringer tone select (0 to 32) 353 | //SendATCmdWaitResp("AT#SRS=26,0", 500, 50, str_ok, 5); 354 | // Microphone gain (0 to 7) - response here sometimes takes 355 | // more than 500msec. so 1000msec. is more safety 356 | //SendATCmdWaitResp("AT#HFMICG=7", 1000, 50, str_ok, 5); 357 | // set the SMS mode to text 358 | SendATCmdWaitResp(F("AT+CMGF=1"), 500, 50, str_ok, 5); 359 | // Auto answer after first ring enabled 360 | // auto answer is not used 361 | //SendATCmdWaitResp("ATS0=1", 500, 50, str_ok, 5); 362 | // select ringer path to handsfree 363 | //SendATCmdWaitResp("AT#SRP=1", 500, 50, str_ok, 5); 364 | // select ringer sound level 365 | //SendATCmdWaitResp("AT+CRSL=2", 500, 50, str_ok, 5); 366 | // we must release comm line because SetSpeakerVolume() 367 | // checks comm line if it is free 368 | SetCommLineStatus(CLS_FREE); 369 | // select speaker volume (0 to 14) 370 | //SetSpeakerVolume(9); 371 | // init SMS storage 372 | InitSMSMemory(); 373 | // select phonebook memory storage 374 | SendATCmdWaitResp(F("AT+CPBS=\"SM\""), 1000, 50, str_ok, 5); 375 | SendATCmdWaitResp(F("AT+CIPSHUT"), 500, 50, "SHUT OK", 5); 376 | break; 377 | } 378 | } 379 | 380 | byte GSM::WaitResp(uint16_t start_comm_tmout, uint16_t max_interchar_tmout, 381 | char const *expected_resp_string) 382 | { 383 | byte status; 384 | byte ret_val; 385 | 386 | RxInit(start_comm_tmout, max_interchar_tmout); 387 | // wait until response is not finished 388 | do { 389 | status = IsRxFinished(); 390 | } while (status == RX_NOT_FINISHED); 391 | 392 | if (status == RX_FINISHED) { 393 | // something was received but what was received? 394 | // --------------------------------------------- 395 | 396 | if(IsStringReceived(expected_resp_string)) { 397 | // expected string was received 398 | // ---------------------------- 399 | ret_val = RX_FINISHED_STR_RECV; 400 | } else { 401 | ret_val = RX_FINISHED_STR_NOT_RECV; 402 | } 403 | } else { 404 | // nothing was received 405 | // -------------------- 406 | ret_val = RX_TMOUT_ERR; 407 | } 408 | return (ret_val); 409 | } 410 | 411 | 412 | /********************************************************** 413 | Method sends AT command and waits for response 414 | 415 | return: 416 | AT_RESP_ERR_NO_RESP = -1, // no response received 417 | AT_RESP_ERR_DIF_RESP = 0, // response_string is different from the response 418 | AT_RESP_OK = 1, // response_string was included in the response 419 | **********************************************************/ 420 | char GSM::SendATCmdWaitResp(char const *AT_cmd_string, 421 | uint16_t start_comm_tmout, uint16_t max_interchar_tmout, 422 | char const *response_string, 423 | byte no_of_attempts) 424 | { 425 | byte status; 426 | char ret_val = AT_RESP_ERR_NO_RESP; 427 | byte i; 428 | 429 | for (i = 0; i < no_of_attempts; i++) { 430 | // delay 500 msec. before sending next repeated AT command 431 | // so if we have no_of_attempts=1 tmout will not occurred 432 | if (i > 0) delay(500); 433 | 434 | _cell.println(AT_cmd_string); 435 | status = WaitResp(start_comm_tmout, max_interchar_tmout); 436 | if (status == RX_FINISHED) { 437 | // something was received but what was received? 438 | // --------------------------------------------- 439 | if(IsStringReceived(response_string)) { 440 | ret_val = AT_RESP_OK; 441 | break; // response is OK => finish 442 | } else ret_val = AT_RESP_ERR_DIF_RESP; 443 | } else { 444 | // nothing was received 445 | // -------------------- 446 | ret_val = AT_RESP_ERR_NO_RESP; 447 | } 448 | 449 | } 450 | 451 | WaitResp(1000, 5000); 452 | return (ret_val); 453 | } 454 | 455 | 456 | /********************************************************** 457 | Method sends AT command and waits for response 458 | 459 | return: 460 | AT_RESP_ERR_NO_RESP = -1, // no response received 461 | AT_RESP_ERR_DIF_RESP = 0, // response_string is different from the response 462 | AT_RESP_OK = 1, // response_string was included in the response 463 | **********************************************************/ 464 | char GSM::SendATCmdWaitResp(const __FlashStringHelper *AT_cmd_string, 465 | uint16_t start_comm_tmout, uint16_t max_interchar_tmout, 466 | char const *response_string, 467 | byte no_of_attempts) 468 | { 469 | byte status; 470 | char ret_val = AT_RESP_ERR_NO_RESP; 471 | byte i; 472 | 473 | for (i = 0; i < no_of_attempts; i++) { 474 | // delay 500 msec. before sending next repeated AT command 475 | // so if we have no_of_attempts=1 tmout will not occurred 476 | if (i > 0) delay(500); 477 | 478 | _cell.println(AT_cmd_string); 479 | status = WaitResp(start_comm_tmout, max_interchar_tmout); 480 | if (status == RX_FINISHED) { 481 | // something was received but what was received? 482 | // --------------------------------------------- 483 | if(IsStringReceived(response_string)) { 484 | ret_val = AT_RESP_OK; 485 | break; // response is OK => finish 486 | } else ret_val = AT_RESP_ERR_DIF_RESP; 487 | } else { 488 | // nothing was received 489 | // -------------------- 490 | ret_val = AT_RESP_ERR_NO_RESP; 491 | } 492 | 493 | } 494 | 495 | return (ret_val); 496 | } 497 | 498 | byte GSM::WaitResp(uint16_t start_comm_tmout, uint16_t max_interchar_tmout) 499 | { 500 | byte status; 501 | 502 | RxInit(start_comm_tmout, max_interchar_tmout); 503 | // wait until response is not finished 504 | do { 505 | status = IsRxFinished(); 506 | } while (status == RX_NOT_FINISHED); 507 | return (status); 508 | } 509 | 510 | byte GSM::IsRxFinished(void) 511 | { 512 | byte num_of_bytes; 513 | byte ret_val = RX_NOT_FINISHED; // default not finished 514 | 515 | // Rx state machine 516 | // ---------------- 517 | 518 | if (rx_state == RX_NOT_STARTED) { 519 | // Reception is not started yet - check tmout 520 | if (!_cell.available()) { 521 | // still no character received => check timeout 522 | /* 523 | #ifdef DEBUG_GSMRX 524 | 525 | DebugPrint("\r\nDEBUG: reception timeout", 0); 526 | Serial.print((unsigned long)(millis() - prev_time)); 527 | DebugPrint("\r\nDEBUG: start_reception_tmout\r\n", 0); 528 | Serial.print(start_reception_tmout); 529 | 530 | 531 | #endif 532 | */ 533 | if ((unsigned long)(millis() - prev_time) >= start_reception_tmout) { 534 | // timeout elapsed => GSM module didn't start with response 535 | // so communication is takes as finished 536 | /* 537 | #ifdef DEBUG_GSMRX 538 | DebugPrint("\r\nDEBUG: RECEPTION TIMEOUT", 0); 539 | #endif 540 | */ 541 | comm_buf[comm_buf_len] = 0x00; 542 | ret_val = RX_TMOUT_ERR; 543 | } 544 | } else { 545 | // at least one character received => so init inter-character 546 | // counting process again and go to the next state 547 | prev_time = millis(); // init tmout for inter-character space 548 | rx_state = RX_ALREADY_STARTED; 549 | } 550 | } 551 | 552 | if (rx_state == RX_ALREADY_STARTED) { 553 | // Reception already started 554 | // check new received bytes 555 | // only in case we have place in the buffer 556 | num_of_bytes = _cell.available(); 557 | // if there are some received bytes postpone the timeout 558 | if (num_of_bytes) prev_time = millis(); 559 | 560 | // read all received bytes 561 | while (num_of_bytes) { 562 | num_of_bytes--; 563 | if (comm_buf_len < COMM_BUF_LEN) { 564 | // we have still place in the GSM internal comm. buffer => 565 | // move available bytes from circular buffer 566 | // to the rx buffer 567 | *p_comm_buf = _cell.read(); 568 | 569 | p_comm_buf++; 570 | comm_buf_len++; 571 | comm_buf[comm_buf_len] = 0x00; // and finish currently received characters 572 | // so after each character we have 573 | // valid string finished by the 0x00 574 | } else { 575 | // comm buffer is full, other incoming characters 576 | // will be discarded 577 | // but despite of we have no place for other characters 578 | // we still must to wait until 579 | // inter-character tmout is reached 580 | 581 | // so just readout character from circular RS232 buffer 582 | // to find out when communication id finished(no more characters 583 | // are received in inter-char timeout) 584 | _cell.read(); 585 | } 586 | } 587 | 588 | // finally check the inter-character timeout 589 | /* 590 | #ifdef DEBUG_GSMRX 591 | 592 | DebugPrint("\r\nDEBUG: intercharacter", 0); 593 | < Serial.print((unsigned long)(millis() - prev_time)); 594 | DebugPrint("\r\nDEBUG: interchar_tmout\r\n", 0); 595 | Serial.print(interchar_tmout); 596 | 597 | 598 | #endif 599 | */ 600 | if ((unsigned long)(millis() - prev_time) >= interchar_tmout) { 601 | // timeout between received character was reached 602 | // reception is finished 603 | // --------------------------------------------- 604 | 605 | /* 606 | #ifdef DEBUG_GSMRX 607 | 608 | DebugPrint("\r\nDEBUG: OVER INTER TIMEOUT", 0); 609 | #endif 610 | */ 611 | comm_buf[comm_buf_len] = 0x00; // for sure finish string again 612 | // but it is not necessary 613 | ret_val = RX_FINISHED; 614 | } 615 | } 616 | 617 | 618 | return (ret_val); 619 | } 620 | 621 | /********************************************************** 622 | Method checks received bytes 623 | 624 | compare_string - pointer to the string which should be find 625 | 626 | return: 0 - string was NOT received 627 | 1 - string was received 628 | **********************************************************/ 629 | byte GSM::IsStringReceived(char const *compare_string) 630 | { 631 | char *ch; 632 | byte ret_val = 0; 633 | 634 | if(comm_buf_len) { 635 | /* 636 | #ifdef DEBUG_GSMRX 637 | DebugPrint("DEBUG: Compare the string: \r\n", 0); 638 | for (int i=0; i,,,,, 718 | if (AT_RESP_OK == SendATCmdWaitResp(F("AT+CPMS=\"SM\",\"SM\",\"SM\""), 1000, 1000, "+CPMS:", 10)) { 719 | ret_val = 1; 720 | } else ret_val = 0; 721 | 722 | SetCommLineStatus(CLS_FREE); 723 | return (ret_val); 724 | } 725 | 726 | int GSM::isIP(const char* cadena) 727 | { 728 | int i; 729 | for (i=0; i=48 && cadena[i] <=57))) 731 | return 0; 732 | return 1; 733 | } 734 | 735 | 736 | 737 | 738 | 739 | 740 | -------------------------------------------------------------------------------- /GSM.h: -------------------------------------------------------------------------------- 1 | #ifndef GSM_H 2 | #define GSM_H 3 | 4 | #define UNO 5 | //#define MEGA 6 | 7 | #include 8 | #include 9 | #include "WideTextFinder.h" 10 | 11 | 12 | #define ctrlz 26 //Ascii character for ctr+z. End of a SMS. 13 | #define cr 13 //Ascii character for carriage return. 14 | #define lf 10 //Ascii character for line feed. 15 | #define ctrlz 26 //Ascii character for ctr+z. End of a SMS. 16 | #define cr 13 //Ascii character for carriage return. 17 | #define lf 10 //Ascii character for line feed. 18 | #define GSM_LIB_VERSION 308 // library version X.YY (e.g. 1.00) 19 | 20 | #define DEBUG_ON 21 | 22 | 23 | #ifdef MEGA 24 | #include "HWSerial.h" 25 | #endif 26 | 27 | // if defined - debug print is enabled with possibility to print out 28 | // debug texts to the terminal program 29 | //#define DEBUG_PRINT 30 | 31 | // if defined - debug print is enabled with possibility to print out 32 | // the data recived from gsm module 33 | //#define DEBUG_GSMRX 34 | 35 | // if defined - debug LED is enabled, otherwise debug LED is disabled 36 | //#define DEBUG_LED_ENABLED 37 | 38 | // if defined - SMSs are not send(are finished by the character 0x1b 39 | // which causes that SMS are not send) 40 | // by this way it is possible to develop program without paying for the SMSs 41 | //#define DEBUG_SMS_ENABLED 42 | 43 | 44 | // pins definition 45 | #define GSM_ON 8 // connect GSM Module turn ON to pin 77 46 | #define GSM_RESET 9 // connect GSM Module RESET to pin 35 47 | //#define DTMF_OUTPUT_ENABLE 71 // connect DTMF Output Enable not used 48 | #define DTMF_DATA_VALID 14 // connect DTMF Data Valid to pin 14 49 | #define DTMF_DATA0 72 // connect DTMF Data0 to pin 72 50 | #define DTMF_DATA1 73 // connect DTMF Data1 to pin 73 51 | #define DTMF_DATA2 74 // connect DTMF Data2 to pin 74 52 | #define DTMF_DATA3 75 // connect DTMF Data3 to pin 75 53 | 54 | // length for the internal communication buffer 55 | #define COMM_BUF_LEN 200 56 | 57 | // some constants for the IsRxFinished() method 58 | #define RX_NOT_STARTED 0 59 | #define RX_ALREADY_STARTED 1 60 | 61 | // some constants for the InitParam() method 62 | #define PARAM_SET_0 0 63 | #define PARAM_SET_1 1 64 | 65 | // DTMF signal is NOT valid 66 | //#define DTMF_NOT_VALID 0x10 67 | 68 | 69 | // status bits definition 70 | #define STATUS_NONE 0 71 | #define STATUS_INITIALIZED 1 72 | #define STATUS_REGISTERED 2 73 | #define STATUS_USER_BUTTON_ENABLE 4 74 | 75 | // GPRS status 76 | #define CHECK_AND_OPEN 0 77 | #define CLOSE_AND_REOPEN 1 78 | 79 | // Common string used 80 | #define str_ok "OK" //string to reduce stack usage 81 | #define str_at "AT" //string to reduce stack usage 82 | 83 | // SMS type 84 | // use by method IsSMSPresent() 85 | enum sms_type_enum { 86 | SMS_UNREAD, 87 | SMS_READ, 88 | SMS_ALL, 89 | 90 | SMS_LAST_ITEM 91 | }; 92 | 93 | enum comm_line_status_enum { 94 | // CLS like CommunicationLineStatus 95 | CLS_FREE, // line is free - not used by the communication and can be used 96 | CLS_ATCMD, // line is used by AT commands, includes also time for response 97 | CLS_DATA, // for the future - line is used in the CSD or GPRS communication 98 | CLS_LAST_ITEM 99 | }; 100 | 101 | enum rx_state_enum { 102 | RX_NOT_FINISHED = 0, // not finished yet 103 | RX_FINISHED, // finished, some character was received 104 | RX_FINISHED_STR_RECV, // finished and expected string received 105 | RX_FINISHED_STR_NOT_RECV, // finished, but expected string not received 106 | RX_TMOUT_ERR, // finished, no character received 107 | // initial communication tmout occurred 108 | RX_LAST_ITEM 109 | }; 110 | 111 | 112 | enum at_resp_enum { 113 | AT_RESP_ERR_NO_RESP = -1, // nothing received 114 | AT_RESP_ERR_DIF_RESP = 0, // response_string is different from the response 115 | AT_RESP_OK = 1, // response_string was included in the response 116 | 117 | AT_RESP_LAST_ITEM 118 | }; 119 | 120 | enum registration_ret_val_enum { 121 | REG_NOT_REGISTERED = 0, 122 | REG_REGISTERED, 123 | REG_NO_RESPONSE, 124 | REG_COMM_LINE_BUSY, 125 | 126 | REG_LAST_ITEM 127 | }; 128 | 129 | enum call_ret_val_enum { 130 | CALL_NONE = 0, 131 | CALL_INCOM_VOICE, 132 | CALL_ACTIVE_VOICE, 133 | CALL_INCOM_VOICE_AUTH, 134 | CALL_INCOM_VOICE_NOT_AUTH, 135 | CALL_INCOM_DATA_AUTH, 136 | CALL_INCOM_DATA_NOT_AUTH, 137 | CALL_ACTIVE_DATA, 138 | CALL_OTHERS, 139 | CALL_NO_RESPONSE, 140 | CALL_COMM_LINE_BUSY, 141 | 142 | CALL_LAST_ITEM 143 | }; 144 | 145 | 146 | enum getsms_ret_val_enum { 147 | GETSMS_NO_SMS = 0, 148 | GETSMS_UNREAD_SMS, 149 | GETSMS_READ_SMS, 150 | GETSMS_OTHER_SMS, 151 | 152 | GETSMS_NOT_AUTH_SMS, 153 | GETSMS_AUTH_SMS, 154 | 155 | GETSMS_LAST_ITEM 156 | }; 157 | 158 | 159 | class GSM { 160 | public: 161 | enum GSM_st_e { ERROR, IDLE, READY, ATTACHED, TCPSERVERWAIT, TCPCONNECTEDSERVER, TCPCONNECTEDCLIENT }; 162 | byte comm_buf[COMM_BUF_LEN+1]; // communication buffer +1 for 0x00 termination 163 | void InitParam (byte group); 164 | 165 | private: 166 | int _status; 167 | byte comm_line_status; 168 | 169 | // global status - bits are used for representation of states 170 | byte module_status; 171 | 172 | // variables connected with communication buffer 173 | 174 | byte *p_comm_buf; // pointer to the communication buffer 175 | byte comm_buf_len; // num. of characters in the buffer 176 | byte rx_state; // internal state of rx state machine 177 | uint16_t start_reception_tmout; // max tmout for starting reception 178 | uint16_t interchar_tmout; // previous time in msec. 179 | unsigned long prev_time; // previous time in msec. 180 | 181 | // last value of speaker volume 182 | byte last_speaker_volume; 183 | char InitSMSMemory(void); 184 | 185 | protected: 186 | #ifdef MEGA 187 | HWSerial _cell; 188 | #endif 189 | #ifdef UNO 190 | SoftwareSerial _cell; 191 | #endif 192 | int isIP(const char* cadena); 193 | 194 | public: 195 | #ifdef UNO 196 | WideTextFinder _tf; 197 | #endif 198 | inline void setStatus(GSM_st_e status) { 199 | _status = status; 200 | } 201 | GSM(); 202 | inline int getStatus() { 203 | return _status; 204 | }; 205 | virtual int begin(long baud_rate); 206 | inline void SetCommLineStatus(byte new_status) { 207 | comm_line_status = new_status; 208 | }; 209 | inline byte GetCommLineStatus(void) { 210 | return comm_line_status; 211 | }; 212 | void RxInit(uint16_t start_comm_tmout, uint16_t max_interchar_tmout); 213 | byte IsRxFinished(void); 214 | byte IsStringReceived(char const *compare_string); 215 | byte WaitResp(uint16_t start_comm_tmout, uint16_t max_interchar_tmout); 216 | byte WaitResp(uint16_t start_comm_tmout, uint16_t max_interchar_tmout, 217 | char const *expected_resp_string); 218 | char SendATCmdWaitResp(char const *AT_cmd_string, 219 | uint16_t start_comm_tmout, uint16_t max_interchar_tmout, 220 | char const *response_string, 221 | byte no_of_attempts); 222 | char SendATCmdWaitResp(const __FlashStringHelper *AT_cmd_string, 223 | uint16_t start_comm_tmout, uint16_t max_interchar_tmout, 224 | char const *response_string, 225 | byte no_of_attempts); 226 | void Echo(byte state); 227 | 228 | 229 | //----------------------- 230 | // turns off/on the speaker 231 | void SetSpeaker(byte off_on); 232 | // checks if module is registered in the GSM network 233 | // must be called regularly 234 | byte CheckRegistration(void); 235 | 236 | // User button methods 237 | inline byte IsUserButtonEnable(void) { 238 | return (module_status & STATUS_USER_BUTTON_ENABLE); 239 | }; 240 | inline void DisableUserButton(void) { 241 | module_status &= ~STATUS_USER_BUTTON_ENABLE; 242 | }; 243 | inline void EnableUserButton(void) { 244 | module_status |= STATUS_USER_BUTTON_ENABLE; 245 | }; 246 | byte IsUserButtonPushed(void); 247 | 248 | // Phonebook's methods 249 | char GetPhoneNumber(byte position, char *phone_number); 250 | char WritePhoneNumber(byte position, char *phone_number); 251 | char DelPhoneNumber(byte position); 252 | char ComparePhoneNumber(byte position, char *phone_number); 253 | 254 | // returns registration state 255 | byte IsRegistered(void); 256 | // returns whether complete initialization was made 257 | byte IsInitialized(void); 258 | //----------------------- 259 | 260 | // debug methods 261 | #ifdef DEBUG_LED_ENABLED 262 | void BlinkDebugLED (byte num_of_blink); 263 | #endif 264 | 265 | #ifdef DEBUG_PRINT 266 | void DebugPrint(const char *string_to_print, byte last_debug_print); 267 | void DebugPrint(int number_to_print, byte last_debug_print); 268 | #endif 269 | }; 270 | 271 | #endif 272 | -------------------------------------------------------------------------------- /HWSerial.cpp: -------------------------------------------------------------------------------- 1 | #include "HWSerial.h" 2 | #ifdef MEGA 3 | HWSerial::HWSerial() 4 | { 5 | Serial1.begin(9600); 6 | 7 | } 8 | /* 9 | bool HWSerial::listen(){ 10 | return Serial1.listen(); 11 | } 12 | */ 13 | void HWSerial::end() 14 | { 15 | Serial1.end(); 16 | } 17 | /* 18 | bool HWSerial::isListening(){ 19 | return Serial1.isListening(); 20 | } 21 | 22 | bool HWSerial::overflow(){ 23 | return Serial1.overflow(); 24 | } 25 | */ 26 | void HWSerial::begin(long baud_rate) 27 | { 28 | Serial1.begin(baud_rate); 29 | } 30 | 31 | int HWSerial::peek() 32 | { 33 | return Serial1.peek(); 34 | } 35 | 36 | size_t HWSerial::write(uint8_t byte) 37 | { 38 | return Serial1.write(byte); 39 | } 40 | 41 | int HWSerial::read() 42 | { 43 | return Serial1.read(); 44 | } 45 | 46 | int HWSerial::available() 47 | { 48 | return Serial1.available(); 49 | } 50 | 51 | void HWSerial::flush() 52 | { 53 | Serial1.flush(); 54 | } 55 | 56 | 57 | /**************************************/ 58 | 59 | 60 | 61 | size_t HWSerial::print(const __FlashStringHelper *ifsh) 62 | { 63 | const prog_char *p = (const prog_char *)ifsh; 64 | size_t n = 0; 65 | while (1) { 66 | unsigned char c = pgm_read_byte(p++); 67 | if (c == 0) break; 68 | n += write(c); 69 | } 70 | return n; 71 | } 72 | 73 | size_t HWSerial::print(const String &s) 74 | { 75 | size_t n = 0; 76 | for (uint16_t i = 0; i < s.length(); i++) { 77 | n += write(s[i]); 78 | } 79 | return n; 80 | } 81 | 82 | size_t HWSerial::print(const char str[]) 83 | { 84 | return write(str); 85 | } 86 | 87 | size_t HWSerial::print(char c) 88 | { 89 | return write(c); 90 | } 91 | 92 | size_t HWSerial::print(unsigned char b, int base) 93 | { 94 | return print((unsigned long) b, base); 95 | } 96 | 97 | size_t HWSerial::print(int n, int base) 98 | { 99 | return print((long) n, base); 100 | } 101 | 102 | size_t HWSerial::print(unsigned int n, int base) 103 | { 104 | return print((unsigned long) n, base); 105 | } 106 | 107 | size_t HWSerial::print(long n, int base) 108 | { 109 | if (base == 0) { 110 | return write(n); 111 | } else if (base == 10) { 112 | if (n < 0) { 113 | int t = print('-'); 114 | n = -n; 115 | return printNumber(n, 10) + t; 116 | } 117 | return printNumber(n, 10); 118 | } else { 119 | return printNumber(n, base); 120 | } 121 | } 122 | 123 | size_t HWSerial::print(unsigned long n, int base) 124 | { 125 | if (base == 0) return write(n); 126 | else return printNumber(n, base); 127 | } 128 | 129 | size_t HWSerial::print(double n, int digits) 130 | { 131 | return printFloat(n, digits); 132 | } 133 | 134 | size_t HWSerial::println(const __FlashStringHelper *ifsh) 135 | { 136 | size_t n = print(ifsh); 137 | n += println(); 138 | return n; 139 | } 140 | 141 | 142 | size_t HWSerial::println(void) 143 | { 144 | size_t n = print('\r'); 145 | n += print('\n'); 146 | return n; 147 | } 148 | 149 | size_t HWSerial::println(const String &s) 150 | { 151 | size_t n = print(s); 152 | n += println(); 153 | return n; 154 | } 155 | 156 | 157 | size_t HWSerial::println(const char c[]) 158 | { 159 | size_t n = print(c); 160 | n += println(); 161 | return n; 162 | } 163 | 164 | size_t HWSerial::println(char c) 165 | { 166 | size_t n = print(c); 167 | n += println(); 168 | return n; 169 | } 170 | 171 | size_t HWSerial::println(unsigned char b, int base) 172 | { 173 | size_t n = print(b, base); 174 | n += println(); 175 | return n; 176 | } 177 | 178 | size_t HWSerial::println(int num, int base) 179 | { 180 | size_t n = print(num, base); 181 | n += println(); 182 | return n; 183 | } 184 | 185 | size_t HWSerial::println(unsigned int num, int base) 186 | { 187 | size_t n = print(num, base); 188 | n += println(); 189 | return n; 190 | } 191 | 192 | size_t HWSerial::println(long num, int base) 193 | { 194 | size_t n = print(num, base); 195 | n += println(); 196 | return n; 197 | } 198 | 199 | size_t HWSerial::println(unsigned long num, int base) 200 | { 201 | size_t n = print(num, base); 202 | n += println(); 203 | return n; 204 | } 205 | 206 | size_t HWSerial::println(double num, int digits) 207 | { 208 | size_t n = print(num, digits); 209 | n += println(); 210 | return n; 211 | } 212 | 213 | 214 | /******************************/ 215 | size_t HWSerial::write(const uint8_t *buffer, size_t size) 216 | { 217 | size_t n = 0; 218 | while (size--) { 219 | n += write(*buffer++); 220 | } 221 | return n; 222 | } 223 | 224 | size_t HWSerial::printNumber(unsigned long n, uint8_t base) 225 | { 226 | char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. 227 | char *str = &buf[sizeof(buf) - 1]; 228 | 229 | *str = '\0'; 230 | 231 | // prevent crash if called with base == 1 232 | if (base < 2) base = 10; 233 | 234 | do { 235 | unsigned long m = n; 236 | n /= base; 237 | char c = m - base * n; 238 | *--str = c < 10 ? c + '0' : c + 'A' - 10; 239 | } while(n); 240 | 241 | return write(str); 242 | } 243 | 244 | size_t HWSerial::printFloat(double number, uint8_t digits) 245 | { 246 | size_t n = 0; 247 | 248 | // Handle negative numbers 249 | if (number < 0.0) { 250 | n += print('-'); 251 | number = -number; 252 | } 253 | 254 | // Round correctly so that print(1.999, 2) prints as "2.00" 255 | double rounding = 0.5; 256 | for (uint8_t i=0; i 0) { 268 | n += print("."); 269 | } 270 | 271 | // Extract digits from the remainder one at a time 272 | while (digits-- > 0) { 273 | remainder *= 10.0; 274 | int toPrint = int(remainder); 275 | n += print(toPrint); 276 | remainder -= toPrint; 277 | } 278 | 279 | return n; 280 | } 281 | 282 | 283 | 284 | boolean HWSerial::find(char *target) 285 | { 286 | return findUntil(target, NULL); 287 | } 288 | 289 | 290 | boolean HWSerial::findUntil(char *target, char *terminate) 291 | { 292 | byte targetLen = strlen(target); 293 | byte index = 0; // maximum target string length is 255 bytes 294 | byte termIndex = 0; 295 | byte termLen = (terminate == NULL ? 0 : strlen(terminate)); 296 | char c; 297 | 298 | if( *target == 0) 299 | return true; // return true if target is a null string 300 | while( (c = read()) != 0) { 301 | if( c == target[index]) { 302 | if(++index >= targetLen) { // return true if all chars in the target match 303 | return true; 304 | } 305 | } else { 306 | index = 0; // reset index if any char does not match 307 | } 308 | if(termLen > 0 && c == terminate[termIndex]) { 309 | if(++termIndex >= termLen) 310 | return false; // return false if terminate string found before target string 311 | } else 312 | termIndex = 0; 313 | } 314 | return false; 315 | } 316 | 317 | 318 | 319 | int HWSerial::getString( char *pre_string, char *post_string, char *buffer, int length) 320 | { 321 | if( find(pre_string) ) { 322 | int index = 0; 323 | *buffer = 0; 324 | while(index < length-1 ) { 325 | char c = read(); 326 | if( c == 0 ) { 327 | return 0; // timeout returns 0 ! 328 | } else if( c == *post_string ) { 329 | 330 | while (index < length) { 331 | buffer[index] = '\0'; // terminate the string !!!!!!!!!!!IT DOESN'T WORK!!!!!!!!!!!!!!!!! 332 | index++; 333 | } 334 | 335 | //buffer[index]=0; 336 | return index; // data got successfully 337 | } else { 338 | buffer[index++] = c; 339 | } 340 | } 341 | buffer[index] = 0; 342 | return index; // Note: buffer full before the closing post_string encountered 343 | } 344 | return 0; //failed to find the prestring 345 | } 346 | #endif -------------------------------------------------------------------------------- /HWSerial.h: -------------------------------------------------------------------------------- 1 | //#define MEGA 2 | 3 | #ifndef _HWSERIAL_H_ 4 | #define _HWSERIAL_H_ 5 | 6 | #include "Arduino.h" 7 | #include "Streaming.h" 8 | #include 9 | 10 | 11 | class HWSerial { 12 | #ifdef MEGA 13 | private: 14 | int write_error; 15 | size_t printNumber(unsigned long, uint8_t); 16 | size_t printFloat(double, uint8_t); 17 | 18 | public: 19 | HWSerial(); 20 | 21 | //bool listen(); 22 | void end(); 23 | /* 24 | bool isListening(); 25 | bool overflow(); 26 | */ 27 | int peek(); 28 | virtual void begin(long baud_rate); 29 | 30 | virtual size_t write(uint8_t byte); 31 | size_t write(const char *str) { 32 | return write((const uint8_t *)str, strlen(str)); 33 | } 34 | virtual size_t write(const uint8_t *buffer, size_t size); 35 | 36 | virtual int read(); 37 | virtual int available(); 38 | virtual void flush(); 39 | 40 | size_t print(const __FlashStringHelper *); 41 | size_t print(const String &); 42 | size_t print(const char[]); 43 | size_t print(char); 44 | size_t print(unsigned char, int = DEC); 45 | size_t print(int, int = DEC); 46 | size_t print(unsigned int, int = DEC); 47 | size_t print(long, int = DEC); 48 | size_t print(unsigned long, int = DEC); 49 | size_t print(double, int = 2); 50 | 51 | 52 | size_t println(const __FlashStringHelper *); 53 | size_t println(const String &s); 54 | size_t println(const char[]); 55 | size_t println(char); 56 | size_t println(unsigned char, int = DEC); 57 | size_t println(int, int = DEC); 58 | size_t println(unsigned int, int = DEC); 59 | size_t println(long, int = DEC); 60 | size_t println(unsigned long, int = DEC); 61 | size_t println(double, int = 2); 62 | 63 | size_t println(void); 64 | 65 | int getString( char *pre_string, char *post_string, char *buffer, int length); 66 | boolean find(char *target); 67 | boolean findUntil(char *target, char *terminate); 68 | 69 | #endif 70 | 71 | }; 72 | #endif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /LOG.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LOG.cpp - Library for standard logging convention. 3 | Created by Meir Michanie, June 9, 2010. 4 | Released into the public domain. 5 | Version 0.1 6 | */ 7 | 8 | #include "LOG.h" 9 | 10 | LOG::LOG(int level) 11 | { 12 | setLevel(level); 13 | } 14 | 15 | void LOG::DATA(const char* string) 16 | { 17 | if (_level > 4) { 18 | Serial.print(string); 19 | } 20 | } 21 | 22 | void LOG::DATA(int number) 23 | { 24 | if (_level > 4) { 25 | Serial.print(number); 26 | } 27 | } 28 | 29 | void LOG::DEBUG(const char* string) 30 | { 31 | if (_level > 3) { 32 | Serial.print("\n[DEBUG]: "); 33 | Serial.println(string); 34 | } 35 | } 36 | 37 | void LOG::INFO(const char* string) 38 | { 39 | if (_level > 2) { 40 | Serial.print("\n[INFO]: "); 41 | Serial.println(string); 42 | } 43 | } 44 | 45 | void LOG::WARNING(const char* string) 46 | { 47 | if (_level > 1) { 48 | Serial.print("\n[WARNING]: "); 49 | Serial.println(string); 50 | } 51 | } 52 | 53 | void LOG::CRITICAL(const char* string) 54 | { 55 | if (_level > 0) { 56 | Serial.print("\n[CRITICAL]: "); 57 | Serial.println(string); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /LOG.h: -------------------------------------------------------------------------------- 1 | /* 2 | LOG.h - Library for standard logging convention. 3 | Created by Meir Michanie, June 9, 2010. 4 | Released into the public domain. 5 | Version 0.1 6 | */ 7 | 8 | #ifndef LOG_h 9 | #define LOG_h 10 | #include "Arduino.h" 11 | 12 | class LOG { 13 | public: 14 | LOG(int level); 15 | void DEBUG(const char* string); 16 | void INFO(const char* string); 17 | void WARNING(const char* string); 18 | void CRITICAL(const char* string); 19 | void DATA(const char* string); 20 | void DATA(int number); 21 | 22 | inline int getLevel(void) { 23 | return _level; 24 | } 25 | inline void setLevel(int level) { 26 | _level = level; 27 | } 28 | 29 | private: 30 | int _level; 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | GSM GPRS Shield for Arduino Uno 2 | 3 | For informations and support: 4 | http://www.gsmlib.org 5 | http://code.google.com/p/gsm-shield-arduino/ (no longer supported) 6 | http://www.open-electronics.org/arduino-gsm-shield/ 7 | http://www.futurashop.it/ 8 | 9 | The below functions are always available in the library. 10 | 11 | int attachGPRS(char* domain, char* dom1, char* dom2) 12 | establishes a GPRS connection with domain using authentication (if needed) 13 | parameters and return values: 14 | domain: pointer to a string that contains the domain address of GPRS connection 15 | dom1: pointer to the username string (don't use if not needed) 16 | dom2: pointer to the password string (don't use if not needed) 17 | return: 18 | 0 - unable to establish a GPRS connection 19 | 1 - connection successfully established 20 | 21 | int dettachGPRS() 22 | disconnects the GPRS connection 23 | 24 | int connectTCP(const char* server, int port) 25 | starts a socket connection to the server at specific port 26 | parameters and return values: 27 | server: pointer to the server address string, it can be the IP or normal address 28 | port: port used to establish a connection 29 | e.g. gsm.connectTCP("www.google.it",80) 30 | e.g. gsm.connectTCP("74.125.39.106",80) 31 | return: 32 | 0 - unable to start the TCP connection 33 | 1 - connected to the server as client 34 | Sample: GSM_GPRSLibrary_Client 35 | 36 | int disconnectTCP() 37 | stops the TCP connection to the server 38 | 39 | int connectTCPServer(int port) 40 | puts the SIM900 into server mode, waiting for TCP client connection on the specified port. 41 | parameters and return values: 42 | port: port used for establish a connection 43 | return: 44 | 0 - unable to start server connection 45 | 1 - server started successfully, waiting for client connection 46 | Sample: GSM_GPRSLibrary_Server 47 | 48 | void SimpleRead() 49 | simple way to read from the newsoftserial and print the value on the hardware serial 50 | Sample: GSM_GPRSLibrary_AT 51 | 52 | void SimpleWrite(char *comm) 53 | simple way to write a string on newsoftserial 54 | parameters and return values: 55 | comm: pointer to the string to write 56 | Sample: GSM_GPRSLibrary_AT 57 | 58 | For memory saving, next functions are included in a class, so before use them is needed to include the header and to create the class. 59 | 60 | For calling functions is necessary to include the next two lines 61 | include "call.h"; 62 | CallGSM call_classname; //the name you choose must be the same in the functions below 63 | 64 | void Call(char *number_string) 65 | calls the specific number 66 | e.g. call_classname.Call(“+390123456789″); 67 | 68 | void Call(int sim_position) 69 | calls the number stored at the specified SIM position 70 | e.g. call_classname.Call(1); // call to the number stored at the 1st SIM position 71 | 72 | void HangUp(void) 73 | hangs up call(incoming or active) 74 | e.g. call_classname.HangUp(); 75 | 76 | void PickUp(void) 77 | picks up the incoming call 78 | e.g. call_classname.PickUp(); 79 | 80 | For using SMS functions is necessary to include the next two lines 81 | include "sms.h"; 82 | SMSGSM sms_classname; //the name you choose must be the same in the functions below 83 | 84 | char SendSMS(char *number_str, char *message_str) 85 | sends SMS to the specific phone number 86 | parameters and return values: 87 | number_str: pointer to the phone number string 88 | message_str: pointer to the SMS text string 89 | return: 90 | ERROR ret. val: 91 | ————— 92 | -1 – comm. line to the GSM module is not free 93 | -2 – GSM module didn’t answer in timeout 94 | -3 – GSM module has answered “ERROR” string 95 | OK ret val: 96 | ———– 97 | 0 – SMS was not sent 98 | 1 – SMS was sent 9/15 99 | example of use: 100 | sms_classname.SendSMS(“00XXXYYYYYYYYY”, “SMS text”); 101 | 102 | char SendSMS(byte sim_phonebook_position, char *message_str) 103 | sends SMS to the specified SIM phonebook position 104 | parameters and return values: 105 | sim_phonebook_position: SIM phonebook position <1..20> 106 | message_str: pointer to the SMS text string 107 | return: 108 | ERROR ret. val: 109 | ————— 110 | -1 – comm. line to the GSM module is not free 111 | -2 – GSM module didn’t answer in timeout 112 | -3 – specified position must be > 0 113 | OK ret val: 114 | ———– 115 | 0 – SMS was not sent 116 | 1 – SMS was sent 117 | an example of usage: 118 | GSM gsm; 119 | include "sms.h"; 120 | SMSGSM sms_classname; 121 | sms_classname.SendSMS(1, “SMS text”); 122 | 123 | char IsSMSPresent(byte required_status) 124 | finds out if there is present at least one SMS with specified status 125 | if there is new SMS before IsSMSPresent() is executed this SMS has a status UNREAD and then after calling IsSMSPresent() method status of SMS is automatically changed to READ 126 | parameters and return values: 127 | required_status: 128 | SMS_UNREAD – new SMS – not read yet 129 | SMS_READ – already read SMS 130 | SMS_ALL – all stored SMS 131 | return: 132 | ERROR ret. val: 133 | ————— 134 | -1 – comm. line to the GSM module is not free 135 | -2 – GSM module didn’t answer in timeout 136 | OK ret val: 137 | ———– 138 | 0 – there is no SMS with specified status 139 | 1..20 – position where SMS is stored 140 | example of use: 141 | char position; 142 | char phone_number[20]; // array for the phone number string 143 | char *sms_text; 144 | position = sms_classname.IsSMSPresent(SMS_UNREAD); 145 | if (position) { // read new SMS 146 | sms_classname.GetGSM(position, tel_number, &sms_text); 147 | } 148 | 149 | char GetSMS(byte position, char *phone_number, char *SMS_text, byte max_SMS_len) 150 | reads SMS from specified memory(SIM) position 151 | parameters and return values: 152 | position: SMS position <1..20> 153 | phone_number: a pointer where the phone number string of received SMS will be placed 154 | so the space for the phone number string must be reserved – see example 155 | SMS_text : a pointer where SMS text will be placed 156 | max_SMS_len: maximum length of SMS text excluding also string terminating 0×00 character 157 | return: 158 | ERROR ret. val: 159 | ————— 160 | -1 – comm. line to the GSM module is not free 161 | -2 – GSM module didn’t answer in timeout 162 | -3 – specified position must be > 0 163 | OK ret val: 164 | ———– 165 | GETSMS_NO_SMS – no SMS was found at the specified position 166 | GETSMS_UNREAD_SMS – new SMS was found at the specified position 167 | GETSMS_READ_SMS – already read SMS was found at the specified position 168 | GETSMS_OTHER_SMS – other type of SMS was found an example of usage: 169 | GSM gsm; 170 | include "sms.h"; 171 | SMSGSM sms_classname; 172 | char position; 173 | char phone_num[20]; // array for the phone number string 174 | char sms_text[100]; // array for the SMS text string 175 | position = sms_classname.IsSMSPresent(SMS_UNREAD); 176 | if (position) { 177 | // there is new SMS => read it 178 | sms_classname.GetGSM(position, phone_num, sms_text, 100); 179 | Serial.println(“DEBUG SMS phone number: “, 0); 180 | Serial.println(phone_num, 0); 181 | Serial.println(“\r\n SMS text: “, 0); 182 | Serial.println(sms_text, 1); 183 | } 184 | 185 | char GetAuthorizedSMS( byte position, char *phone_number, char *SMS_text, byte max_SMS_len, byte first_authorized_pos, byte last_authorized_pos) 186 | reads SMS from specified memory(SIM) position and makes authorization - 187 | it means SMS phone number is compared with specified SIM phonebook position(s) and in case numbers match GETSMS_AUTH_SMS is returned, otherwise GETSMS_NOT_AUTH_SMS is returned 188 | parameters and return values: 189 | position: SMS position to be read <1..20> 190 | phone_number: a pointer where the tel. number string of received SMS will be placed so the space for the phone number string must be reserved – see example 191 | SMS_text : a pointer where SMS text will be placed 192 | max_SMS_len: maximum length of SMS text excluding terminating 0×00 character 193 | first_authorized_pos: initial SIM phonebook position where the authorization process starts 194 | last_authorized_pos: last SIM phonebook position where the authorization proces finishes 195 | Note(important): 196 | ================ 197 | In case first_authorized_pos=0 and also last_authorized_pos=0 198 | the received SMS phone number is NOT authorized at all, so every 199 | SMS is considered as authorized (GETSMS_AUTH_SMS is returned) 200 | return: 201 | ERROR ret. val: 202 | ————— 203 | -1 – comm. line to the GSM module is not free 204 | -2 – GSM module didn’t answer in timeout 205 | -3 – position must be > 0 206 | OK ret val: 207 | ———– 208 | GETSMS_NO_SMS – no SMS was found at the specified position 209 | GETSMS_NOT_AUTH_SMS – NOT authorized SMS found at the specified position 210 | GETSMS_AUTH_SMS – authorized SMS found at the specified position 211 | an example of usage: 212 | GSM gsm; 213 | include "sms.h"; 214 | SMSGSM sms_classname; 215 | char phone_num[20]; // array for the phone number string 12/15 216 | char sms_text[100]; // array for the SMS text string 217 | // authorize SMS with SIM phonebook positions 1..3 218 | if (GETSMS_AUTH_SMS == sms_classname.GetAuthorizedSMS(1, phone_num, sms_text, 100, 1, 3)) { 219 | // new authorized SMS was detected at the SMS position 1 220 | Serial.println(“DEBUG SMS phone number: “, 0); 221 | Serial.println(phone_num, 0); 222 | Serial.println(“\r\n SMS text: “, 0); 223 | Serial.println(sms_text, 1); 224 | } 225 | // don’t authorize SMS with SIM phonebook at all 226 | if (GETSMS_AUTH_SMS == sms_classname.GetAuthorizedSMS(1, phone_num, sms_text, 100, 0, 0)) { 227 | // new SMS was detected at the SMS position 1 228 | // because authorization was not required 229 | // SMS is considered authorized 230 | Serial.println(“DEBUG SMS phone number: “, 0); 231 | Serial.println(phone_num, 0); 232 | Serial.println(“\r\n SMS text: “, 0); 233 | Serial.println(sms_text, 1); 234 | } 235 | 236 | char DeleteSMS(byte position) 237 | deletes SMS from specified SMS position 238 | parameters and return values: 239 | position: SMS position <1..20> 240 | return: 241 | ERROR ret. val: 242 | ————— 243 | -1 – comm. line to the GSM module is not free 244 | -2 – GSM module didn’t answer in timeout 245 | -3 – position must be > 0 246 | OK ret val: 247 | ———– 248 | 0 – SMS was not deleted 249 | 1 – SMS was deleted 250 | 251 | For HTTP functions is necessary to include the next two lines 252 | include "inetGSM.h"; 253 | inetGSM inet_classname; //the name you choose must be the same in the functions below 254 | 255 | int httpGET(const char* server, int port, const char* path, char* result, int resultlength) 256 | Send a GET request to server, at specified port, for the requested path and save the reply in a string 257 | parameters and return values: 258 | server: the name or IP address of the server 259 | port: number of port used for the connection 260 | path: pointer to the string that contains the requested path e.g. / or /test/test.html 261 | result: pointer to the reply string from the server 262 | resultlength: size of the string with result 263 | return: 264 | 0 - nothing received, maybe there is an error 265 | other - number of byte received 266 | Sample: GSM_GPRSLibrary_Client 267 | 268 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GSM GPRS GPS Bluetooth for SIM800/808/900/908 Library 2 | ====== 3 | 4 | # Related Product 5 | 6 | ## Mainboard: 7 | 8 | - Gboard (no bluetooth) http://imall.iteadstudio.com/im120411004.html 9 | - Gboard Pro (no bluetooth) http://imall.iteadstudio.com/im130514001.html 10 | - Gboard 800 http://imall.iteadstudio.com/im141125007.html 11 | - Gboard Pro 800 http://imall.iteadstudio.com/im141125008.html 12 | 13 | ## Module: 14 | 15 | - SIM900/SIM900A GSM/GPRS Minimum System Module (no bluetooth) http://imall.iteadstudio.com/im140318007.html 16 | - SIM808 GSM/GPRS/GPS Module http://imall.iteadstudio.com/im141125004.html 17 | - SIM908 GSM/GPRS/GPS Module (no bluetooth) http://imall.iteadstudio.com/sim908-gsm-gprs-gps-module.html 18 | 19 | 20 | 21 | ### LICENSE: 22 | GNU GPL v3 except where noted otherwise. 23 | 24 | This program is free software: you can redistribute it and/or modify 25 | it under the terms of the GNU General Public License as published by 26 | the Free Software Foundation, either version 3 of the License. 27 | 28 | This program is distributed in the hope that it will be useful, 29 | but WITHOUT ANY WARRANTY; without even the implied warranty of 30 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 31 | GNU General Public License for more details. 32 | 33 | You should have received a copy of the GNU General Public License 34 | along with this program. If not, see . 35 | 36 | ### Contributers: 37 | 38 | Contributions have been made by the following organizations: 39 | - [GSMLIB.org](http://www.gsmlib.org) 40 | - [Open-Electronics](http://www.open-electronics.org/arduino-gsm-shield/) 41 | - [Futura Elettronica](http://www.futurashop.it) 42 | - [Hwkitchen](http://www.hwkitchen.com) 43 | 44 | As well as, but not limited to, the following individuals: 45 | - [@MarcoMartines](https://github.com/MarcoMartines) 46 | - [@madmaze](https://github.com/madmaze) 47 | - commiters from google code: https://code.google.com/p/gsm-shield-arduino/people/list 48 | names listed in no particular order. 49 | -------------------------------------------------------------------------------- /SIM900.h: -------------------------------------------------------------------------------- 1 | #ifndef SIMCOM900_H 2 | #define SIMCOM900_H 3 | #include 4 | #include "HWSerial.h" 5 | #include "GSM.h" 6 | class SIMCOM900 : public virtual GSM { 7 | 8 | private: 9 | int configandwait(char* pin); 10 | int setPIN(char *pin); 11 | int changeNSIPmode(char); 12 | 13 | public: 14 | SIMCOM900(); 15 | ~SIMCOM900(); 16 | int getCCI(char* cci); 17 | int getIMEI(char* imei); 18 | int sendSMS(const char* to, const char* msg); 19 | boolean readSMS(char* msg, int msglength, char* number, int nlength); 20 | boolean readCall(char* number, int nlength); 21 | boolean call(char* number, unsigned int milliseconds); 22 | char forceON(); 23 | virtual int read(char* result, int resultlength); 24 | virtual uint8_t read(); 25 | virtual int available(); 26 | int readCellData(int &mcc, int &mnc, long &lac, long &cellid); 27 | void SimpleRead(); 28 | void WhileSimpleRead(); 29 | void SimpleWrite(char *comm); 30 | void SimpleWrite(char const *comm); 31 | void SimpleWrite(int comm); 32 | void SimpleWrite(const __FlashStringHelper *pgmstr); 33 | void SimpleWriteln(char *comm); 34 | void SimpleWriteln(char const *comm); 35 | void SimpleWriteln(const __FlashStringHelper *pgmstr); 36 | void SimpleWriteln(int comm); 37 | }; 38 | 39 | extern SIMCOM900 gsm; 40 | 41 | #endif 42 | 43 | -------------------------------------------------------------------------------- /Streaming.h: -------------------------------------------------------------------------------- 1 | /* 2 | Streaming.h - Arduino library for supporting the << streaming operator 3 | Copyright (c) 2010 Mikal Hart. All rights reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef ARDUINO_STREAMING 21 | #define ARDUINO_STREAMING 22 | 23 | #include 24 | #include "LOG.h" 25 | 26 | #define __ST_LOG_LEVEL 3 27 | static LOG _st_logme(__ST_LOG_LEVEL); 28 | 29 | // Generic template 30 | template 31 | inline Print &operator <<(Print &stream, T arg) 32 | { 33 | stream.print(arg); 34 | _st_logme.DATA(arg); 35 | return stream; 36 | } 37 | 38 | struct _BASED { 39 | long val; 40 | int base; 41 | _BASED(long v, int b): val(v), base(b) 42 | {} 43 | }; 44 | 45 | #define _HEX(a) _BASED(a, HEX) 46 | #define _DEC(a) _BASED(a, DEC) 47 | #define _OCT(a) _BASED(a, OCT) 48 | #define _BIN(a) _BASED(a, BIN) 49 | 50 | // Specialization for class _BASED 51 | // Thanks to Arduino forum user Ben Combee who suggested this 52 | // clever technique to allow for expressions like 53 | // Serial << _HEX(a); 54 | 55 | inline Print &operator <<(Print &obj, const _BASED &arg) 56 | { 57 | obj.print(arg.val); 58 | return obj; 59 | } 60 | 61 | #if ARDUINO >= 18 62 | // Specialization for class _FLOAT 63 | // Thanks to Michael Margolis for suggesting a way 64 | // to accommodate Arduino 0018's floating point precision 65 | // feature like this: 66 | // Serial << _FLOAT(gps_latitude, 6); // 6 digits of precision 67 | 68 | struct _FLOAT { 69 | float val; 70 | int digits; 71 | _FLOAT(double v, int d): val(v), digits(d) 72 | {} 73 | }; 74 | 75 | inline Print &operator <<(Print &obj, const _FLOAT &arg) 76 | { 77 | obj.print(arg.val, arg.digits); 78 | return obj; 79 | } 80 | #endif 81 | 82 | // Specialization for enum _EndLineCode 83 | // Thanks to Arduino forum user Paul V. who suggested this 84 | // clever technique to allow for expressions like 85 | // Serial << "Hello!" << endl; 86 | 87 | enum _EndLineCode { endl }; 88 | 89 | inline Print &operator <<(Print &obj, _EndLineCode arg) 90 | { 91 | obj.println(); 92 | return obj; 93 | } 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /WideTextFinder.cpp: -------------------------------------------------------------------------------- 1 | #include "WideTextFinder.h" 2 | 3 | #define NO_SKIP_CHAR 1 // a magic char not found in a valid numeric field 4 | 5 | // private function to read characters from stream 6 | // the constructors allow one and only one of the streams to be initialized 7 | char WideTextFinder::read() 8 | { 9 | char r; 10 | startMillis = millis(); 11 | if (nSerialStream != NULL) { 12 | while(millis() < (startMillis + timeout)) { 13 | if (nSerialStream->available() > 0) { 14 | r=nSerialStream->read(); 15 | //if(debug) 16 | //Serial.print(r); 17 | return r; 18 | } 19 | } 20 | } 21 | return 0; // 0 indicates timeout 22 | } 23 | 24 | // constructors 25 | //default timeout is 5 seconds 26 | 27 | WideTextFinder::WideTextFinder(SoftwareSerial &stream, int timeout) : 28 | nSerialStream(&stream) 29 | { 30 | this->timeout = timeout * 1000L; 31 | debug=true; 32 | } 33 | 34 | void WideTextFinder::setDebug(boolean d) 35 | { 36 | debug=d; 37 | } 38 | 39 | // public methods 40 | // 41 | // find returns true if the target string is found 42 | boolean WideTextFinder::find(char *target) 43 | { 44 | return findUntil(target, NULL); 45 | } 46 | 47 | // as above but search ends if the terminate string is found 48 | boolean WideTextFinder::findUntil(char *target, char *terminate) 49 | { 50 | byte targetLen = strlen(target); 51 | byte index = 0; // maximum target string length is 255 bytes 52 | byte termIndex = 0; 53 | byte termLen = (terminate == NULL ? 0 : strlen(terminate)); 54 | char c; 55 | 56 | if( *target == 0) 57 | return true; // return true if target is a null string 58 | while( (c = read()) != 0) { 59 | if( c == target[index]) { 60 | if(++index >= targetLen) { // return true if all chars in the target match 61 | return true; 62 | } 63 | } else { 64 | index = 0; // reset index if any char does not match 65 | } 66 | if(termLen > 0 && c == terminate[termIndex]) { 67 | if(++termIndex >= termLen) 68 | return false; // return false if terminate string found before target string 69 | } else 70 | termIndex = 0; 71 | } 72 | return false; 73 | } 74 | 75 | // places the string between the prestring and poststring in the given buffer 76 | // buffer must be one more than the longest string to get 77 | // the string will be truncated to fit the buffer length 78 | // end of string determined by a single character match to the first char of poststring 79 | // returns the number of characters placed in the buffer (0 means no valid data found) 80 | int WideTextFinder::getString( char *pre_string, char *post_string, char *buffer, int length) 81 | { 82 | if( find(pre_string) ) { 83 | int index = 0; 84 | *buffer = 0; 85 | while(index < length-1 ) { 86 | char c = read(); 87 | if( c == 0 ) { 88 | return 0; // timeout returns 0 ! 89 | } else if( c == *post_string ) { 90 | 91 | while (index < length) { 92 | buffer[index] = '\0'; // terminate the string !!!!!!!!!!!IT DOESN'T WORK!!!!!!!!!!!!!!!!! 93 | index++; 94 | } 95 | 96 | //buffer[index]=0; 97 | return index; // data got successfully 98 | } else { 99 | buffer[index++] = c; 100 | } 101 | } 102 | buffer[index] = 0; 103 | return index; // Note: buffer full before the closing post_string encountered 104 | } 105 | return 0; //failed to find the prestring 106 | } 107 | 108 | // getValue method: 109 | // returns the first valid (long) integer value from the current position. 110 | // initial characters that are not digits (or the minus sign) are skipped 111 | // function is terminated by the first character that is not a digit. 112 | long WideTextFinder::getValue() 113 | { 114 | return getValue(NO_SKIP_CHAR); // terminate on first non-digit character 115 | } 116 | 117 | // as above but a given skipChar is ignored 118 | // this allows format characters (typically commas) in values to be ignored 119 | long WideTextFinder::getValue(char skipChar) 120 | { 121 | boolean isNegative = false; 122 | long value = 0; 123 | char c; 124 | 125 | while( (c = read()) != '-' && (c < '0' || c > '9') && (c!=0) ) 126 | ;// ignore non numeric leading characters 127 | do { 128 | if(c == skipChar ) 129 | ; // ignore this charactor 130 | else if (c==0) // Timeout 131 | return 0; 132 | else if(c == '-') 133 | isNegative = true; 134 | else if(c >= '0' && c <= '9') // is c a digit? 135 | value = value * 10 + c - '0'; 136 | c = read(); 137 | } while( (c >= '0' && c <= '9') || c == skipChar ); 138 | if(isNegative) 139 | value = -value; 140 | return value; 141 | } 142 | 143 | // float version of getValue method: 144 | // as integer version but returns a floating point value 145 | float WideTextFinder::getFloat() 146 | { 147 | getFloat(NO_SKIP_CHAR); 148 | } 149 | 150 | // as above but the given skipChar is ignored 151 | // this allows format characters (typically commas) in values to be ignored 152 | float WideTextFinder::getFloat(char skipChar) 153 | { 154 | boolean isNegative = false; 155 | boolean isFraction = false; 156 | long value = 0; 157 | float fValue; 158 | char c; 159 | float fraction = 1.0; 160 | 161 | while( (c = read()) != '-' && (c < '0' || c > '9') ) 162 | ; // ignore non numeric leading characters 163 | do { 164 | if(c == skipChar) 165 | ; // ignore 166 | else if(c == '-') 167 | isNegative = true; 168 | else if (c == '.') 169 | isFraction = true; 170 | else if(c >= '0' && c <= '9') { // is c a digit? 171 | value = value * 10 + c - '0'; 172 | if(isFraction) 173 | fraction *= 0.1; 174 | } 175 | c = read(); 176 | } while( (c >= '0' && c <= '9') || c == '.' || c == skipChar ); 177 | if(isNegative) 178 | value = -value; 179 | if(isFraction) 180 | return value * fraction; 181 | else 182 | return value; 183 | } 184 | 185 | 186 | // returns the number of seconds to wait for the next char before aborting read 187 | unsigned long WideTextFinder::getTimeout() 188 | { 189 | return timeout; 190 | } 191 | 192 | // set a new value for the wait timeout 193 | void WideTextFinder::setTimeout(unsigned long timeout) 194 | { 195 | this->timeout = timeout * 1000L; 196 | } 197 | -------------------------------------------------------------------------------- /WideTextFinder.h: -------------------------------------------------------------------------------- 1 | #ifndef WideTextFinder_h 2 | #define WideTextFinder_h 3 | 4 | //#include 5 | #include 6 | #include 7 | 8 | 9 | class WideTextFinder { 10 | private: 11 | SoftwareSerial* nSerialStream; 12 | 13 | unsigned long timeout; // number of seconds to wait for the next char before aborting read 14 | unsigned long startMillis; // used for timeout measurement 15 | boolean debug; 16 | 17 | char read(); // private function to read from the stream 18 | 19 | public: 20 | // constructor: 21 | // default timeout is 5 seconds 22 | WideTextFinder(SoftwareSerial &stream, int timeout = 5); // Ethernet constructor 23 | 24 | // Manage debug 25 | void setDebug(boolean d); 26 | 27 | // find methods - these seek through the data but do not return anything 28 | // they are useful to skip past unwanted data 29 | // 30 | boolean find(char *target); // reads data from the stream until the target string is found 31 | // returns true if target string is found 32 | 33 | boolean findUntil(char *target, char *terminate); // as above but search ends if the terminate string is found 34 | 35 | 36 | // get methods - these get a numeric value or string from the data stream 37 | // 38 | long getValue(); // returns the first valid (long) integer value from the current position. 39 | // initial characters that are not digits (or the minus sign) are skipped 40 | // integer is terminated by the first character that is not a digit. 41 | 42 | long getValue(char skipChar); // as above but the given skipChar is ignored 43 | // this allows format characters (typically commas) in values to be ignored 44 | 45 | float getFloat(); // float version of getValue 46 | float getFloat(char skipChar); // as above but the given skipChar is ignored 47 | 48 | int getString( char *pre_string, char *post_string, char *buffer, int length); //puts string found between given delimiters in buffer 49 | // string will be truncated to fit the buffer length 50 | // end of string determined by a match of a character to the first char of close delimiter 51 | // returns the number of characters placed in the buffer (0 means no valid data found) 52 | 53 | unsigned long getTimeout(); // returns the number of seconds to wait for the next char before aborting read 54 | 55 | // set methods 56 | // 57 | void setTimeout(unsigned long timeout); // set a new value for the wait timeout 58 | 59 | }; 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /bluetooth.cpp: -------------------------------------------------------------------------------- 1 | #include "bluetooth.h" 2 | bool BlueTooth::powerOn(void) 3 | { 4 | bool ret_val = false; 5 | gsm.SimpleWriteln("AT+BTPOWER=1"); 6 | gsm.WaitResp(1000, 500, "OK"); 7 | if(gsm.IsStringReceived("OK")) 8 | ret_val = true; 9 | else if(gsm.IsStringReceived("ERROR")) 10 | ret_val = false; 11 | 12 | return ret_val; 13 | } 14 | 15 | bool BlueTooth::powerOff(void) 16 | { 17 | bool ret_val = false; 18 | gsm.SimpleWriteln("AT+BTPOWER=0"); 19 | gsm.WaitResp(1000, 500, "OK"); 20 | if(gsm.IsStringReceived("OK")) 21 | ret_val = true; 22 | else if(gsm.IsStringReceived("ERROR")) 23 | ret_val = false; 24 | 25 | return ret_val; 26 | } 27 | 28 | int BlueTooth::getHostDeviceName(char* deviceName) 29 | { 30 | char *s,*p; 31 | int i = 0; 32 | int ret_val = -1; 33 | gsm.SimpleWriteln("AT+BTHOST?"); 34 | gsm.WaitResp(1000, 500, "OK"); 35 | if (gsm.IsStringReceived("OK")) 36 | ret_val = 1; 37 | else 38 | return 0; 39 | if(gsm.IsStringReceived("+BTHOST:")) 40 | { 41 | s = strchr((char *)gsm.comm_buf,':'); 42 | 43 | if(NULL == (s = strchr((char *)gsm.comm_buf,':'))) 44 | { 45 | return -1; 46 | } 47 | p = s + 9;/*+BTHOST: SIM800,33:7d:77:18:62:60*/ 48 | while(*(p) != ',') 49 | { 50 | deviceName[i++] = *p; 51 | p++; 52 | } 53 | deviceName[i] = '\0'; 54 | } 55 | 56 | return i; 57 | } 58 | 59 | int BlueTooth::scanForTargetDevice(char* deviceName) 60 | { 61 | char *s; 62 | gsm.SimpleWriteln("AT+BTSCAN=1,20"); 63 | /*gsm.RxInit(5000, 1500);*/ 64 | if (RX_FINISHED_STR_RECV == gsm.WaitResp(10000, 10000, "+BTSCAN:")) 65 | { 66 | if(NULL == (s = strstr((char *)gsm.comm_buf,deviceName))) 67 | { 68 | return 0; 69 | } 70 | else 71 | targetDeviceID = atoi(s-3); 72 | } 73 | 74 | return targetDeviceID; 75 | } 76 | 77 | int BlueTooth::sendPairingRequestToDevice(int deviceID) 78 | { 79 | if(0 == deviceID) 80 | return -1; 81 | 82 | gsm.SimpleWrite("AT+BTPAIR=0,"); 83 | gsm.SimpleWrite(deviceID); 84 | gsm.SimpleWrite("\r\n"); 85 | if (RX_FINISHED_STR_RECV == gsm.WaitResp(2000, 1000, "+BTPAIRING")) { 86 | gsm.SimpleWriteln("AT+BTPAIR=1,1"); 87 | 88 | } 89 | return 0; 90 | } 91 | 92 | int BlueTooth::unPair(void) 93 | { 94 | int ret_val = -1; 95 | if(0 == targetDeviceID) 96 | return -1; 97 | gsm.SimpleWrite("AT+BTUNPAIR=0"); 98 | /*gsm.SimpleWrite(targetDeviceID);*/ 99 | gsm.SimpleWrite("\r\n"); 100 | gsm.WaitResp(1000, 500, "OK"); 101 | if(gsm.IsStringReceived("OK")) 102 | ret_val = 1; 103 | else 104 | ret_val = 0; 105 | 106 | return ret_val; 107 | } 108 | 109 | int BlueTooth::acceptPairing(void) 110 | { 111 | char *s = NULL; 112 | if (RX_FINISHED_STR_RECV == gsm.WaitResp(2000, 1000, "+BTPAIRING")) 113 | { 114 | gsm.SimpleWriteln("AT+BTPAIR=1,1"); 115 | Serial.println("+++pair ok+++");/*it indicates device pair ok*/ 116 | if (RX_FINISHED_STR_RECV == gsm.WaitResp(10000, 10000, "+BTPAIR")) 117 | { 118 | if(NULL == (s = strstr((char *)gsm.comm_buf,":"))) 119 | { 120 | return 0; 121 | } 122 | else 123 | targetDeviceID = atoi(s+1); 124 | } 125 | return targetDeviceID; 126 | } 127 | else 128 | { 129 | Serial.println("zlnonono"); /*it indicates that there is no device try to pair with SIM800*/ 130 | return 0; 131 | } 132 | } 133 | int BlueTooth::acceptConnect(void) 134 | { 135 | int ret_val = -1; 136 | gsm.SimpleWriteln("AT+BTACPT=1"); 137 | gsm.WaitResp(1000, 500, "OK"); 138 | 139 | if(gsm.IsStringReceived("OK")) 140 | ret_val = 1; 141 | else 142 | ret_val = 0; 143 | 144 | return ret_val; 145 | } 146 | int BlueTooth::disconnect(int deviceID) 147 | { 148 | int ret_val = -1; 149 | if(0 == targetDeviceID) 150 | return -1; 151 | gsm.SimpleWrite("AT+BTDISCONN="); 152 | gsm.SimpleWrite(targetDeviceID); 153 | gsm.SimpleWrite("\r\n"); 154 | gsm.WaitResp(1000, 500, "OK"); 155 | if(gsm.IsStringReceived("OK")) 156 | ret_val = 1; 157 | else 158 | ret_val = 0; 159 | 160 | return ret_val; 161 | } 162 | /* 163 | int BlueTooth::loopHandle(void) 164 | { 165 | char gprsBuffer[100]; 166 | cleanBuffer(gprsBuffer,100); 167 | while(1) { 168 | if(serialSIM800.available()) 169 | { 170 | break; 171 | } 172 | delay(1000); 173 | } 174 | readBuffer(gprsBuffer,100,DEFAULT_TIMEOUT); 175 | 176 | if(NULL != strstr(gprsBuffer,"+BTPAIRING:")) 177 | { 178 | if(0 != acceptPairing()) 179 | { 180 | return -1; 181 | ERROR("\r\nERROR:bluetoothAcceptPairing\r\n"); 182 | } 183 | } 184 | if((NULL != strstr(gprsBuffer,"+BTCONNECTING:")) && (NULL != strstr(gprsBuffer,"SPP"))) 185 | { 186 | if(0 != acceptConnect()) 187 | { 188 | return -1; 189 | ERROR("\r\nERROR:bluetoothAcceptConnecting\r\n"); 190 | } 191 | } 192 | return 0; 193 | } 194 | */ 195 | 196 | /*int BlueTooth::getDeviceId(void) 197 | { 198 | return 1; 199 | }*/ 200 | 201 | int BlueTooth::connectInSPP(int deviceID) /*Serial Port Profile*/ 202 | { 203 | int ret_val = 1; 204 | if(0 == targetDeviceID) 205 | return -1; 206 | 207 | /*gsm.SimpleWriteln("AT+BTGETPROF);*/ 208 | gsm.SimpleWrite("AT+BTCONNECT="); 209 | gsm.SimpleWrite(targetDeviceID); 210 | gsm.SimpleWrite(",4\r\n"); 211 | Serial.println("***connetc SPP***"); /*it means connect to SPP*/ 212 | if (RX_FINISHED_STR_RECV == gsm.WaitResp(10000, 500, "OK")) 213 | { 214 | return 1; 215 | } 216 | /*gsm.SetCommLineStatus(CLS_FREE); */ 217 | return ret_val; 218 | } 219 | 220 | int BlueTooth::recvInSPP(char* data) 221 | { 222 | char * p = NULL; 223 | int count = 0; 224 | if (RX_FINISHED_STR_RECV == gsm.WaitResp(1000, 500, "+BTSPPDATA:")) 225 | { 226 | p = strchr((char *)gsm.comm_buf,':'); 227 | if(NULL != p) 228 | { 229 | p += 5; 230 | int i = 0; 231 | while(*(p++) != 0x0D) 232 | { 233 | data[i++] = *p; 234 | } 235 | data[i]='+'; 236 | return 1; 237 | } 238 | else 239 | return 0; 240 | } 241 | else 242 | return 0; 243 | } 244 | 245 | int BlueTooth::sendInSPP(char* data) 246 | { 247 | int ret_val = -1; 248 | char end[2]; 249 | end[0]=0x1a; 250 | end[1]='\0'; 251 | gsm.SimpleWriteln("AT+BTSPPSEND"); 252 | 253 | if (RX_FINISHED_STR_RECV == gsm.WaitResp(1000, 500, ">")) 254 | { 255 | gsm.SimpleWrite(data); 256 | gsm.SimpleWriteln(end); 257 | if (RX_FINISHED_STR_RECV == gsm.WaitResp(2000, 2000, "SEND OK")) 258 | ret_val = 1; 259 | } 260 | else 261 | ret_val = 0; 262 | 263 | return ret_val; 264 | } 265 | -------------------------------------------------------------------------------- /bluetooth.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLUETOOTH_H__ 2 | #define __BLUETOOTH_H__ 3 | 4 | #include "SIM900.h" 5 | 6 | /** 7 | * BlueTooth class. 8 | * 9 | * used to communicate with BlueTooth Module. 10 | */ 11 | class BlueTooth 12 | { 13 | public: 14 | 15 | /** 16 | * Power on BlueTooth module. 17 | * 18 | * @retval true - success. 19 | * @retval false - failure. 20 | * 21 | */ 22 | bool powerOn(void); 23 | 24 | /** 25 | * Power off BlueTooth module. 26 | * 27 | * @retval true - success. 28 | * @retval false - failure. 29 | * 30 | */ 31 | bool powerOff(void); 32 | 33 | /** 34 | * Get host device name of BlueTooth module. 35 | * 36 | * @param deviceName - buffer array to save device name. 37 | * @retval 1 - success. 38 | * @retval <=0 - failure. 39 | * 40 | */ 41 | int getHostDeviceName(char* deviceName); 42 | 43 | /** 44 | * Scan for target device according to device name. 45 | * 46 | * @param deviceName - device which will be scanned for. 47 | * @retval >0 - success. 48 | * @retval <=0 - failure. 49 | * @return targetDeviceID. 50 | * 51 | */ 52 | int scanForTargetDevice(char* deviceName); 53 | 54 | /** 55 | * Send pairing request to device according to deviceID. 56 | * 57 | * @param deviceID - device ID. 58 | * @retval 0 - success. 59 | * @retval -1 - failure. 60 | * 61 | */ 62 | int sendPairingRequestToDevice(int deviceID); 63 | 64 | /** 65 | * Accept other BlueTooth module's pairing request. 66 | * 67 | * @retval >0 - success. 68 | * @retval <=0 - failure. 69 | * @return targetDeviceID. 70 | * 71 | */ 72 | int acceptPairing(void); 73 | 74 | /** 75 | * UnPair with paired BlueTooth device. 76 | * 77 | * @retval 1 - success. 78 | * @retval <=0 - failure. 79 | * 80 | */ 81 | int unPair(void); 82 | 83 | /** 84 | * Accept other BlueTooth device's connecting request. 85 | * 86 | * @retval 1 - success. 87 | * @retval <=0 - failure. 88 | * 89 | */ 90 | int acceptConnect(void); 91 | 92 | /** 93 | * Wait to handle other BlueTooth device's pairing or connecting request. 94 | * 95 | * @retval 0 - success. 96 | * @retval -1 - failure. 97 | * 98 | */ 99 | int loopHandle(void); 100 | 101 | /** 102 | * Disconnect with connected BlueTooth device. 103 | * 104 | * @param deviceID - device that will be disconnected. 105 | * @retval 1 - success. 106 | * @retval <=0 - failure. 107 | * 108 | */ 109 | int disconnect(int deviceID); 110 | 111 | /** 112 | * Connect with other BlueTooth device in SPP profile. 113 | * 114 | * @param deviceID - device that will be connect in SPP profile. 115 | * @retval 1 - success. 116 | * @retval <=0 - failure. 117 | * 118 | */ 119 | int connectInSPP(int deviceID); 120 | 121 | /** 122 | * Receive data in SPP profile. 123 | * 124 | * @param data - buffer array to receive data from other BlueTooth device in SPP profile. 125 | * @retval 1 - success. 126 | * @retval 0 - failure. 127 | * 128 | */ 129 | int recvInSPP(char* data); 130 | 131 | /** 132 | * Send data in SPP profile. 133 | * 134 | * @param data - buffer array to send data to other BlueTooth device in SPP profile. 135 | * @reval 1 - success. 136 | * @retal <=0 - failure. 137 | * 138 | */ 139 | int sendInSPP(char* data); 140 | 141 | private: 142 | 143 | /** 144 | * BlueTooth power flag 145 | */ 146 | bool bluetoothPower; 147 | 148 | /** 149 | * target device ID 150 | */ 151 | int targetDeviceID; 152 | }; 153 | 154 | #endif -------------------------------------------------------------------------------- /call.cpp: -------------------------------------------------------------------------------- 1 | #include "call.h" 2 | 3 | /********************************************************** 4 | Method checks status of call 5 | 6 | return: 7 | CALL_NONE - no call activity 8 | CALL_INCOM_VOICE - incoming voice 9 | CALL_ACTIVE_VOICE - active voice 10 | CALL_NO_RESPONSE - no response to the AT command 11 | CALL_COMM_LINE_BUSY - comm line is not free 12 | **********************************************************/ 13 | byte CallGSM::CallStatus(void) 14 | { 15 | byte ret_val = CALL_NONE; 16 | 17 | if (CLS_FREE != gsm.GetCommLineStatus()) return (CALL_COMM_LINE_BUSY); 18 | gsm.SetCommLineStatus(CLS_ATCMD); 19 | gsm.SimpleWriteln(F("AT+CPAS")); 20 | 21 | // 5 sec. for initial comm tmout 22 | // 50 msec. for inter character timeout 23 | if (RX_TMOUT_ERR == gsm.WaitResp(5000, 50)) { 24 | // nothing was received (RX_TMOUT_ERR) 25 | // ----------------------------------- 26 | ret_val = CALL_NO_RESPONSE; 27 | } else { 28 | // something was received but what was received? 29 | // --------------------------------------------- 30 | // ready (device allows commands from TA/TE) 31 | // +CPAS: 0 OK 32 | // unavailable (device does not allow commands from TA/TE) 33 | // +CPAS: 1 OK 34 | // unknown (device is not guaranteed to respond to instructions) 35 | // +CPAS: 2 OK - NO CALL 36 | // ringing 37 | // +CPAS: 3 OK - NO CALL 38 | // call in progress 39 | // +CPAS: 4 OK - NO CALL 40 | if(gsm.IsStringReceived("+CPAS: 0")) { 41 | // ready - there is no call 42 | // ------------------------ 43 | ret_val = CALL_NONE; 44 | } else if(gsm.IsStringReceived("+CPAS: 3")) { 45 | // incoming call 46 | // -------------- 47 | ret_val = CALL_INCOM_VOICE; 48 | } else if(gsm.IsStringReceived("+CPAS: 4")) { 49 | // active call 50 | // ----------- 51 | ret_val = CALL_ACTIVE_VOICE; 52 | } 53 | } 54 | 55 | gsm.SetCommLineStatus(CLS_FREE); 56 | return (ret_val); 57 | 58 | } 59 | 60 | /********************************************************** 61 | Method checks status of call(incoming or active) 62 | and makes authorization with specified SIM positions range 63 | 64 | phone_number: a pointer where the tel. number string of current call will be placed 65 | so the space for the phone number string must be reserved - see example 66 | first_authorized_pos: initial SIM phonebook position where the authorization process 67 | starts 68 | last_authorized_pos: last SIM phonebook position where the authorization process 69 | finishes 70 | 71 | Note(important): 72 | ================ 73 | In case first_authorized_pos=0 and also last_authorized_pos=0 74 | the received incoming phone number is NOT authorized at all, so every 75 | incoming is considered as authorized (CALL_INCOM_VOICE_NOT_AUTH is returned) 76 | 77 | return: 78 | CALL_NONE - no call activity 79 | CALL_INCOM_VOICE_AUTH - incoming voice - authorized 80 | CALL_INCOM_VOICE_NOT_AUTH - incoming voice - not authorized 81 | CALL_ACTIVE_VOICE - active voice 82 | CALL_INCOM_DATA_AUTH - incoming data call - authorized 83 | CALL_INCOM_DATA_NOT_AUTH - incoming data call - not authorized 84 | CALL_ACTIVE_DATA - active data call 85 | CALL_NO_RESPONSE - no response to the AT command 86 | CALL_COMM_LINE_BUSY - comm line is not free 87 | **********************************************************/ 88 | byte CallGSM::CallStatusWithAuth(char *phone_number, 89 | byte first_authorized_pos, byte last_authorized_pos) 90 | { 91 | byte ret_val = CALL_NONE; 92 | byte search_phone_num = 0; 93 | byte i; 94 | byte status; 95 | char *p_char; 96 | char *p_char1; 97 | 98 | phone_number[0] = 0x00; // no phonr number so far 99 | if (CLS_FREE != gsm.GetCommLineStatus()) return (CALL_COMM_LINE_BUSY); 100 | gsm.SetCommLineStatus(CLS_ATCMD); 101 | gsm.SimpleWriteln(F("AT+CLCC")); 102 | 103 | // 5 sec. for initial comm tmout 104 | // and max. 1500 msec. for inter character timeout 105 | gsm.RxInit(5000, 1500); 106 | // wait response is finished 107 | do { 108 | if (gsm.IsStringReceived("OK\r\n")) { 109 | // perfect - we have some response, but what: 110 | 111 | // there is either NO call: 112 | // OK 113 | 114 | // or there is at least 1 call 115 | // +CLCC: 1,1,4,0,0,"+420XXXXXXXXX",145 116 | // OK 117 | status = RX_FINISHED; 118 | break; // so finish receiving immediately and let's go to 119 | // to check response 120 | } 121 | status = gsm.IsRxFinished(); 122 | } while (status == RX_NOT_FINISHED); 123 | 124 | // generate tmout 30msec. before next AT command 125 | delay(30); 126 | 127 | if (status == RX_FINISHED) { 128 | // something was received but what was received? 129 | // example: //+CLCC: 1,1,4,0,0,"+420XXXXXXXXX",145 130 | // --------------------------------------------- 131 | if(gsm.IsStringReceived("+CLCC: 1,1,4,0,0")) { 132 | // incoming VOICE call - not authorized so far 133 | // ------------------------------------------- 134 | search_phone_num = 1; 135 | ret_val = CALL_INCOM_VOICE_NOT_AUTH; 136 | } else if(gsm.IsStringReceived("+CLCC: 1,1,4,1,0")) { 137 | // incoming DATA call - not authorized so far 138 | // ------------------------------------------ 139 | search_phone_num = 1; 140 | ret_val = CALL_INCOM_DATA_NOT_AUTH; 141 | } else if(gsm.IsStringReceived("+CLCC: 1,0,0,0,0")) { 142 | // active VOICE call - GSM is caller 143 | // ---------------------------------- 144 | search_phone_num = 1; 145 | ret_val = CALL_ACTIVE_VOICE; 146 | } else if(gsm.IsStringReceived("+CLCC: 1,1,0,0,0")) { 147 | // active VOICE call - GSM is listener 148 | // ----------------------------------- 149 | search_phone_num = 1; 150 | ret_val = CALL_ACTIVE_VOICE; 151 | } else if(gsm.IsStringReceived("+CLCC: 1,1,0,1,0")) { 152 | // active DATA call - GSM is listener 153 | // ---------------------------------- 154 | search_phone_num = 1; 155 | ret_val = CALL_ACTIVE_DATA; 156 | } else if(gsm.IsStringReceived("+CLCC:")) { 157 | // other string is not important for us - e.g. GSM module activate call 158 | // etc. 159 | // IMPORTANT - each +CLCC:xx response has also at the end 160 | // string OK 161 | ret_val = CALL_OTHERS; 162 | } else if(gsm.IsStringReceived("OK")) { 163 | // only "OK" => there is NO call activity 164 | // -------------------------------------- 165 | ret_val = CALL_NONE; 166 | } 167 | 168 | 169 | // now we will search phone num string 170 | if (search_phone_num) { 171 | // extract phone number string 172 | // --------------------------- 173 | p_char = strchr((char *)(gsm.comm_buf),'"'); 174 | p_char1 = p_char+1; // we are on the first phone number character 175 | p_char = strchr((char *)(p_char1),'"'); 176 | if (p_char != NULL) { 177 | *p_char = 0; // end of string 178 | strcpy(phone_number, (char *)(p_char1)); 179 | Serial.print("ATTESO: "); 180 | Serial.println(phone_number); 181 | } else 182 | //Serial.println(gsm.comm_buf); 183 | Serial.println("NULL"); 184 | 185 | if ( (ret_val == CALL_INCOM_VOICE_NOT_AUTH) 186 | || (ret_val == CALL_INCOM_DATA_NOT_AUTH)) { 187 | 188 | if ((first_authorized_pos == 0) && (last_authorized_pos == 0)) { 189 | // authorization is not required => it means authorization is OK 190 | // ------------------------------------------------------------- 191 | if (ret_val == CALL_INCOM_VOICE_NOT_AUTH) ret_val = CALL_INCOM_VOICE_AUTH; 192 | else ret_val = CALL_INCOM_DATA_AUTH; 193 | } else { 194 | // make authorization 195 | // ------------------ 196 | gsm.SetCommLineStatus(CLS_FREE); 197 | for (i = first_authorized_pos; i <= last_authorized_pos; i++) { 198 | if (gsm.ComparePhoneNumber(i, phone_number)) { 199 | // phone numbers are identical 200 | // authorization is OK 201 | // --------------------------- 202 | if (ret_val == CALL_INCOM_VOICE_NOT_AUTH) ret_val = CALL_INCOM_VOICE_AUTH; 203 | else ret_val = CALL_INCOM_DATA_AUTH; 204 | break; // and finish authorization 205 | } 206 | } 207 | } 208 | } 209 | } 210 | 211 | } else { 212 | // nothing was received (RX_TMOUT_ERR) 213 | // ----------------------------------- 214 | ret_val = CALL_NO_RESPONSE; 215 | } 216 | 217 | gsm.SetCommLineStatus(CLS_FREE); 218 | return (ret_val); 219 | } 220 | 221 | /********************************************************** 222 | Method picks up an incoming call 223 | 224 | return: 225 | **********************************************************/ 226 | void CallGSM::PickUp(void) 227 | { 228 | //if (CLS_FREE != gsm.GetCommLineStatus()) return; 229 | //gsm.SetCommLineStatus(CLS_ATCMD); 230 | gsm.SendATCmdWaitResp("ATA", 10, 10, "OK", 3); 231 | gsm.SimpleWriteln("ATA"); 232 | //gsm.SetCommLineStatus(CLS_FREE); 233 | } 234 | 235 | /********************************************************** 236 | Method hangs up incoming or active call 237 | 238 | return: 239 | **********************************************************/ 240 | void CallGSM::HangUp(void) 241 | { 242 | //if (CLS_FREE != gsm.GetCommLineStatus()) return; 243 | //gsm.SetCommLineStatus(CLS_ATCMD); 244 | gsm.SendATCmdWaitResp("ATH", 500, 100, "OK", 5); 245 | //gsm.SetCommLineStatus(CLS_FREE); 246 | } 247 | 248 | /********************************************************** 249 | Method calls the specific number 250 | 251 | number_string: pointer to the phone number string 252 | e.g. gsm.Call("+420123456789"); 253 | 254 | **********************************************************/ 255 | void CallGSM::Call(char *number_string) 256 | { 257 | if (CLS_FREE != gsm.GetCommLineStatus()) return; 258 | gsm.SetCommLineStatus(CLS_ATCMD); 259 | // ATDxxxxxx; 260 | gsm.SimpleWrite(F("ATD")); 261 | gsm.SimpleWrite(number_string); 262 | gsm.SimpleWriteln(F(";")); 263 | // 10 sec. for initial comm tmout 264 | // 50 msec. for inter character timeout 265 | gsm.WaitResp(10000, 50); 266 | gsm.SetCommLineStatus(CLS_FREE); 267 | } 268 | 269 | /********************************************************** 270 | Method calls the number stored at the specified SIM position 271 | 272 | sim_position: position in the SIM <1...> 273 | e.g. gsm.Call(1); 274 | **********************************************************/ 275 | void CallGSM::Call(int sim_position) 276 | { 277 | if (CLS_FREE != gsm.GetCommLineStatus()) return; 278 | gsm.SetCommLineStatus(CLS_ATCMD); 279 | // ATD>"SM" 1; 280 | gsm.SimpleWrite(F("ATD>\"SM\" ")); 281 | gsm.SimpleWrite(sim_position); 282 | gsm.SimpleWriteln(F(";")); 283 | 284 | // 10 sec. for initial comm tmout 285 | // 50 msec. for inter character timeout 286 | gsm.WaitResp(10000, 50); 287 | 288 | gsm.SetCommLineStatus(CLS_FREE); 289 | } 290 | 291 | void CallGSM::SendDTMF(char *number_string, int time) 292 | { 293 | if (CLS_FREE != gsm.GetCommLineStatus()) return; 294 | gsm.SetCommLineStatus(CLS_ATCMD); 295 | 296 | gsm.SimpleWrite(F("AT+VTD=")); 297 | gsm.SimpleWriteln(time); 298 | gsm.WaitResp(1000, 100, "OK"); 299 | 300 | gsm.SimpleWrite(F("AT+VTS=\"")); 301 | gsm.SimpleWrite(number_string); 302 | gsm.SimpleWriteln(F("\"")); 303 | 304 | gsm.WaitResp(5000, 100, "OK"); 305 | gsm.SetCommLineStatus(CLS_FREE); 306 | } 307 | 308 | void CallGSM::SetDTMF(int DTMF_status) 309 | { 310 | if(DTMF_status==1) 311 | gsm.SendATCmdWaitResp("AT+DDET=1", 500, 50, "OK", 5); 312 | else 313 | gsm.SendATCmdWaitResp("AT+DDET=0", 500, 50, "OK", 5); 314 | } 315 | 316 | 317 | char CallGSM::DetDTMF() 318 | { 319 | char *p_char; 320 | char *p_char1; 321 | char dtmf_char='-'; 322 | gsm.WaitResp(1000, 500); 323 | { 324 | //Serial.print("BUF: "); 325 | //Serial.println((char *)gsm.comm_buf); 326 | //Serial.println("end"); 327 | p_char = strstr((char *)(gsm.comm_buf),"+DTMF:"); 328 | if (p_char != NULL) { 329 | p_char1 = p_char+6; //we are on the first char of BCS 330 | dtmf_char = *p_char1; 331 | } 332 | } 333 | return dtmf_char; 334 | } -------------------------------------------------------------------------------- /call.h: -------------------------------------------------------------------------------- 1 | #ifndef _CALL_H_ 2 | #define _CALL_H_ 3 | 4 | #include "SIM900.h" 5 | 6 | class CallGSM { 7 | public: 8 | // finds out the status of call 9 | byte CallStatus(void); 10 | byte CallStatusWithAuth(char *phone_number, 11 | byte first_authorized_pos, byte last_authorized_pos); 12 | // picks up an incoming call 13 | void PickUp(void); 14 | // hangs up an incomming call 15 | void HangUp(void); 16 | // calls the specific number 17 | void Call(char *number_string); 18 | // makes a call to the number stored at the specified SIM position 19 | void Call(int sim_position); 20 | void SendDTMF(char *number_string, int time); 21 | 22 | void SetDTMF(int DTMF_status); 23 | char DetDTMF(); 24 | 25 | }; 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /doc/Instructions.txt: -------------------------------------------------------------------------------- 1 | *************************************************** 2 | GSM/GPRS/GPS Shield of Futura/Open-electronics 3 | 4 | http://www.open-electronics.org/ 5 | 6 | http://store.open-electronics.org/index.php?route=common/home 7 | 8 | *************************************************** 9 | 10 | 11 | 12 | 13 | 14 | *************************************************** 15 | For support use the issues' page on google code: 16 | 17 | http://code.google.com/p/gsm-shield-arduino/issues/ 18 | 19 | or Arduino Forum 20 | 21 | *************************************************** 22 | 23 | 24 | 25 | 26 | 27 | *************************************************** 28 | Library created by: 29 | 30 | Marco Martines 31 | 32 | martines[ dot ]marco[ at ]gmail[ dot ]com 33 | *************************************************** 34 | 35 | 36 | 37 | 38 | [1] How to switch between Arduino Mega and Arduino Uno? 39 | 40 | 1) 41 | Open GSM.h and comment-decomment the appropriate lines like below 42 | e.g. for Arduino Mega 43 | //#define UNO 44 | #define MEGA 45 | 46 | 2) 47 | If you use Arduino Uno comment the line in HWSerial.h or decomment if 48 | you are using Arduino Mega 49 | e.g. for Arduino Mega 50 | #define MEGA 51 | 52 | 3) 53 | Save and compile 54 | 55 | [2] How to switch between the old shield (that uses 4 and 5 pins for 56 | SoftwareSerial and the new (that used 2 and 3 pins)? 57 | 58 | 1) 59 | Open GSM.cpp and comment-decomment the appropriate lines like below 60 | e.g. for the new one 61 | 62 | //#define _GSM_TXPIN_ 4 63 | //#define _GSM_RXPIN_ 5 64 | #define _GSM_TXPIN_ 2 65 | #define _GSM_RXPIN_ 3 66 | 67 | 2) 68 | Save and compile 69 | 70 | [3] My shield doesn't work. Why? 71 | 72 | Check this steps and then ask for support on the issues' page on google 73 | code. 74 | 75 | 1) SIM900 and SIM908 require about 1 A during the hardest tasks. 76 | You should have an external power source that can provide about 77 | 1 A at 8-12 V 78 | 79 | 2) If the SIM90X blinks (1 Hz) for some seconds and then turn off, 80 | probably it's a communication's problem. Check the switch/jumpers 81 | for Serial communication. 82 | 83 | 3) Arduino Uno has 2 KB of RAM. Library takes about 80% (we are working 84 | to reduce it), if you use more than 20% left, Arduino can restart 85 | or print on serial strange strings. 86 | 87 | 4) Check the jumper of communication, power source (battery or externel) and charge. -------------------------------------------------------------------------------- /doc/InstructionsBlueTooth.txt: -------------------------------------------------------------------------------- 1 | /*BASIC FUNCTIONS in BlueTooth class*/ 2 | 3 | /** 4 | * Power on BlueTooth module. 5 | * 6 | * @retval true - success. 7 | * @retval false - failure. 8 | * 9 | */ 10 | bool powerOn(void); 11 | 12 | /** 13 | * Power off BlueTooth module. 14 | * 15 | * @retval true - success. 16 | * @retval false - failure. 17 | * 18 | */ 19 | bool powerOff(void); 20 | 21 | /** 22 | * Get host device name of BlueTooth module. 23 | * 24 | * @param deviceName - buffer array to save device name. 25 | * @retval 1 - success. 26 | * @retval <=0 - failure. 27 | * 28 | */ 29 | int getHostDeviceName(char* deviceName); 30 | 31 | /** 32 | * Scan for target device according to device name. 33 | * 34 | * @param deviceName - device which will be scanned for. 35 | * @retval >0 - success. 36 | * @retval <=0 - failure. 37 | * @return targetDeviceID. 38 | * 39 | */ 40 | int scanForTargetDevice(char* deviceName); 41 | 42 | /** 43 | * Send pairing request to device according to deviceID. 44 | * 45 | * @param deviceID - device ID. 46 | * @retval 0 - success. 47 | * @retval -1 - failure. 48 | * 49 | */ 50 | int sendPairingRequestToDevice(int deviceID); 51 | 52 | /** 53 | * Accept other BlueTooth module's pairing request. 54 | * 55 | * @retval >0 - success. 56 | * @retval <=0 - failure. 57 | * @return targetDeviceID. 58 | * 59 | */ 60 | int acceptPairing(void); 61 | 62 | /** 63 | * UnPair with paired BlueTooth device. 64 | * 65 | * @retval 1 - success. 66 | * @retval <=0 - failure. 67 | * 68 | */ 69 | int unPair(void); 70 | 71 | /** 72 | * Accept other BlueTooth device's connecting request. 73 | * 74 | * @retval 1 - success. 75 | * @retval <=0 - failure. 76 | * 77 | */ 78 | int acceptConnect(void); 79 | 80 | /** 81 | * Wait to handle other BlueTooth device's pairing or connecting request. 82 | * 83 | * @retval 0 - success. 84 | * @retval -1 - failure. 85 | * 86 | */ 87 | int loopHandle(void); 88 | 89 | /** 90 | * Disconnect with connected BlueTooth device. 91 | * 92 | * @param deviceID - device that will be disconnected. 93 | * @retval 1 - success. 94 | * @retval <=0 - failure. 95 | * 96 | */ 97 | int disconnect(int deviceID); 98 | 99 | /** 100 | * Connect with other BlueTooth device in SPP profile. 101 | * 102 | * @param deviceID - device that will be connect in SPP profile. 103 | * @retval 1 - success. 104 | * @retval <=0 - failure. 105 | * 106 | */ 107 | int connectInSPP(int deviceID); 108 | 109 | /** 110 | * Receive data in SPP profile. 111 | * 112 | * @param data - buffer array to receive data from other BlueTooth device in SPP profile. 113 | * @retval 1 - success. 114 | * @retval 0 - failure. 115 | * 116 | */ 117 | int recvInSPP(char* data); 118 | 119 | /** 120 | * Send data in SPP profile. 121 | * 122 | * @param data - buffer array to send data to other BlueTooth device in SPP profile. 123 | * @reval 1 - success. 124 | * @retal <=0 - failure. 125 | * 126 | */ 127 | int sendInSPP(char* data); -------------------------------------------------------------------------------- /doc/InstructionsForGBoardPro800.txt: -------------------------------------------------------------------------------- 1 | /* 2 | *If your board is "Gboard Pro 800" you should edit the following files 3 | */ 4 | 5 | step1: HWSerial.cpp 6 | /* 7 | * all the string "Serial1" should be changed to "Serial2" ,for example: 8 | * HWSerial::HWSerial(){ 9 | * // Serial1.begin(9600); 10 | * Serial2.begin(9600); 11 | * } 12 | */ 13 | 14 | step2: HWSerial.h 15 | /* 16 | * //#define UNO 17 | * #define MEGA 18 | * 19 | */ 20 | 21 | step3: GSM.h 22 | /* 23 | * //#define UNO 24 | * #define MEGA 25 | * 26 | */ 27 | 28 | step4: GSM.cpp 29 | /* 30 | * //#define _GSM_TXPIN_ 2 31 | * //#define _GSM_RXPIN_ 3 32 | * #define _GSM_TXPIN_ 16 33 | * #define _GSM_RXPIN_ 17 34 | */ 35 | -------------------------------------------------------------------------------- /doc/List.txt: -------------------------------------------------------------------------------- 1 | *************************************************** 2 | BASIC FUNCTIONS in GSM class. 3 | To call a function the code is: gsm.function_name(); 4 | There is no need to create a class object for GSM class. 5 | It'already done inside the library itself. 6 | *************************************************** 7 | 8 | int begin(long baud_rate); 9 | Function to turn on the module and set the baudrate of communication 10 | at specified baud_rate. 11 | 12 | char forceON(); 13 | When you are using the SIM908 and you need to turn the module on the network mode. 14 | It's possible that SIM908 starts itself on charging mode, without network. 15 | 16 | int getIMEI(char* imei); 17 | Get the IMEI code of the phone and save it on the imei string. 18 | 19 | boolean readSMS(char* msg, int msglength, char* number, int nlength); 20 | Read the first msglength byte of the SMS string and save it to the msg string. 21 | Save the first nlenght numbers of the sender number to the number string. 22 | 23 | boolean readCall(char* number, int nlength); 24 | 25 | boolean call(char* number, unsigned int milliseconds); 26 | Call the specified number after the milliseconds specified. 27 | 28 | int readCellData(int &mcc, int &mnc, long &lac, long &cellid); 29 | Read information about the network data. 30 | 31 | void SimpleRead(); 32 | To read, and print on hardware serial, the first byte of the software serial buffer. 33 | 34 | void WhileSimpleRead(); 35 | As SimpleRead() but read until the buffer is empty. 36 | 37 | void SimpleWrite(char *comm); 38 | Write on software serial the specified char. 39 | 40 | void SimpleWrite(char const *comm); 41 | Write on software serial the specified const char. 42 | 43 | void SimpleWrite(int comm); 44 | Write on software serial the specified int. 45 | 46 | void SimpleWriteln(char *comm); 47 | Write on software serial the specified char 48 | and append to the end the return char "\n\r". 49 | 50 | void SimpleWriteln(char const *comm); 51 | Write on software serial the specified const char 52 | and append to the end the return char "\n\r". 53 | 54 | void SimpleWriteln(int comm); 55 | Write on software serial the specified int 56 | and append to the end the return char "\n\r". 57 | 58 | void RxInit(uint16_t start_comm_tmout, uint16_t max_interchar_tmout); 59 | To set the timout during the serial communication, for the entire string 60 | and for the time between two char. 61 | 62 | byte IsRxFinished(void); 63 | To check if the communication is finished, comparing the time 64 | with the timeout selected with the RxInit() function. 65 | 66 | byte IsStringReceived(char const *compare_string); 67 | To check if the received string from software serial is 68 | the same of the specified string. 69 | 70 | byte WaitResp(uint16_t start_comm_tmout, uint16_t max_interchar_tmout, 71 | char const *expected_resp_string); 72 | It merges the RxInit() and IsStringReceived() functions. 73 | 74 | char SendATCmdWaitResp(char const *AT_cmd_string, 75 | uint16_t start_comm_tmout, uint16_t max_interchar_tmout, 76 | char const *response_string, 77 | byte no_of_attempts); 78 | It's a very important function to send a command, wait the response 79 | and check if it is the same of the aspected response. If not retry 80 | for number of attempts specified. 81 | 82 | *************************************************** 83 | SMS FUNCTIONS in SMS class. 84 | It's need to create a class object for SMS class with 85 | SMS sms_obj_name (in the examples it's used SMS sms) 86 | In the examples, to call a function the code is: sms.function_name(); 87 | *************************************************** 88 | 89 | char SendSMS(char *number_str, char *message_str); 90 | Send a SMS to the specified number with the specified string. 91 | 92 | char SendSMS(byte sim_phonebook_position, char *message_str); 93 | Send a SMS to the specified phonebook position with the specified string. 94 | 95 | char IsSMSPresent(byte required_status); 96 | Check if there is a message with the specified attribute like: 97 | SMS_UNREAD 98 | SMS_READ 99 | SMS_ALL 100 | 101 | char GetSMS(byte position, char *phone_number, char *SMS_text, byte max_SMS_len); 102 | Save the SMS content and sender of the SMS in specified SIM position. 103 | Save the first max_SMS_len byte of the SMS string to the SMS_text string and 104 | the sender to the phone_number string. 105 | 106 | char GetAuthorizedSMS(byte position, char *phone_number, char *SMS_text, byte max_SMS_len, 107 | byte first_authorized_pos, byte last_authorized_pos); 108 | Method reads SMS from specified SIM position and 109 | makes authorization. It means SMS phone number is compared 110 | with specified SIM phonebook position(s) and in case numbers 111 | match GETSMS_AUTH_SMS is returned, otherwise GETSMS_NOT_AUTH_SMS 112 | is returned. 113 | 114 | char DeleteSMS(byte position); 115 | Method deletes SMS from the specified SMS position 116 | 117 | *************************************************** 118 | CALL FUNCTIONS in CALL class. 119 | It's need to create a class object for SMS class with 120 | CALL call_obj_name (in the examples it's used CALL call) 121 | In the examples, to call a function the code is: call.function_name(); 122 | *************************************************** 123 | 124 | byte CallStatus(void); 125 | Method checks status of call 126 | 127 | return: 128 | CALL_NONE - no call activity 129 | CALL_INCOM_VOICE - incoming voice 130 | CALL_ACTIVE_VOICE - active voice 131 | CALL_NO_RESPONSE - no response to the AT command 132 | CALL_COMM_LINE_BUSY - comm line is not free 133 | 134 | byte CallStatusWithAuth(char *phone_number, 135 | byte first_authorized_pos, byte last_authorized_pos); 136 | Method checks status of call(incoming or active) 137 | and makes authorization with specified SIM positions range 138 | 139 | phone_number: a pointer where the tel. number string of current call will be placed 140 | so the space for the phone number string must be reserved - see example 141 | first_authorized_pos: initial SIM phonebook position where the authorization process 142 | starts 143 | last_authorized_pos: last SIM phonebook position where the authorization process 144 | finishes 145 | 146 | Note(important): 147 | In case first_authorized_pos=0 and also last_authorized_pos=0 148 | the received incoming phone number is NOT authorized at all, so every 149 | incoming is considered as authorized (CALL_INCOM_VOICE_NOT_AUTH is returned). 150 | 151 | return: 152 | CALL_NONE - no call activity 153 | CALL_INCOM_VOICE_AUTH - incoming voice - authorized 154 | CALL_INCOM_VOICE_NOT_AUTH - incoming voice - not authorized 155 | CALL_ACTIVE_VOICE - active voice 156 | CALL_INCOM_DATA_AUTH - incoming data call - authorized 157 | CALL_INCOM_DATA_NOT_AUTH - incoming data call - not authorized 158 | CALL_ACTIVE_DATA - active data call 159 | CALL_NO_RESPONSE - no response to the AT command 160 | CALL_COMM_LINE_BUSY - comm line is not free 161 | 162 | 163 | void PickUp(void); 164 | To pick up an incoming call. 165 | 166 | void HangUp(void); 167 | To hang up and active call. 168 | 169 | void Call(char *number_string); 170 | To call the specified number; 171 | 172 | void Call(int sim_position); 173 | To call the contact saved on the specified SIM position. 174 | 175 | void SendDTMF(char *number_string, int time); 176 | Send a combination of DTMF stymbols separated by commas. 177 | But a single character does not require quotes. 178 | Time indicates the duration in seconds of each sound. 179 | An example: 180 | call.SendDTMF("1,2,3,4",1); 181 | 182 | *************************************************** 183 | GPRS FUNCTIONS in InetGSM class. 184 | It's need to create a class object for SMS class with 185 | InetGSM inet_obj_name (in the examples it's used InetGSM inet) 186 | In the examples, to call a function the code is: inet.function_name(); 187 | *************************************************** 188 | int attachGPRS(char* domain, char* dom1, char* dom2); 189 | Start a GPRS connection to the specified domain. 190 | It is needs authetication, dom1 is the username, dom2 is the password. 191 | If it is no need, left it blank with. 192 | An example: 193 | inet.attachGPRS("internet.wind","",""); 194 | 195 | int httpGET(const char* server, int port, const char* path, char* result, int resultlength); 196 | Save the first resultlength byte of the server response, after a GET request. 197 | An example: 198 | char response[200]; 199 | inet.httpGET("www.google.com",80,"/news",response,200); 200 | 201 | int dettachGPRS(); 202 | Close the GPRS connection. 203 | 204 | int connectTCP(const char* server, int port); 205 | Start a TCP connection with the server on the specified port. 206 | 207 | int disconnectTCP(); 208 | Close the TCP connection. 209 | 210 | int connectTCPServer(int port); 211 | Put the module on the listening mode, waiting for a TCP connection 212 | on the selected port. 213 | 214 | boolean connectedClient(); 215 | Return true if a client is connected to the module, during the 216 | server mode. -------------------------------------------------------------------------------- /examples/GSM_GPRSLibrary_AT/GSM_GPRSLibrary_AT.ino: -------------------------------------------------------------------------------- 1 | #include "SIM900.h" 2 | #include 3 | //#include "inetGSM.h" 4 | //#include "sms.h" 5 | //#include "call.h" 6 | 7 | //To change pins for Software Serial, use the two lines in GSM.cpp. 8 | 9 | //GSM Shield for Arduino 10 | //www.open-electronics.org 11 | //this code is based on the example of Arduino Labs. 12 | 13 | //Simple sketch to communicate with SIM900 through AT commands. 14 | 15 | //InetGSM inet; 16 | //CallGSM call; 17 | //SMSGSM sms; 18 | 19 | int numdata; 20 | char inSerial[40]; 21 | int i=0; 22 | 23 | 24 | void setup() 25 | { 26 | //Serial connection. 27 | Serial.begin(9600); 28 | Serial.println("GSM Shield testing."); 29 | //Start configuration of shield with baudrate. 30 | //For http uses is raccomanded to use 4800 or slower. 31 | if (gsm.begin(9600)) 32 | Serial.println("\nstatus=READY"); 33 | else Serial.println("\nstatus=IDLE"); 34 | }; 35 | 36 | void loop() 37 | { 38 | //Read for new byte on serial hardware, 39 | //and write them on NewSoftSerial. 40 | serialhwread(); 41 | //Read for new byte on NewSoftSerial. 42 | serialswread(); 43 | }; 44 | 45 | void serialhwread() 46 | { 47 | i=0; 48 | if (Serial.available() > 0) { 49 | while (Serial.available() > 0) { 50 | inSerial[i]=(Serial.read()); 51 | delay(10); 52 | i++; 53 | } 54 | 55 | inSerial[i]='\0'; 56 | if(!strcmp(inSerial,"/END")) { 57 | Serial.println("_"); 58 | inSerial[0]=0x1a; 59 | inSerial[1]='\0'; 60 | gsm.SimpleWriteln(inSerial); 61 | } 62 | //Send a saved AT command using serial port. 63 | if(!strcmp(inSerial,"TEST")) { 64 | Serial.println("SIGNAL QUALITY"); 65 | gsm.SimpleWriteln("AT+CSQ"); 66 | } else { 67 | Serial.println(inSerial); 68 | gsm.SimpleWriteln(inSerial); 69 | } 70 | inSerial[0]='\0'; 71 | } 72 | } 73 | 74 | void serialswread() 75 | { 76 | gsm.SimpleRead(); 77 | } 78 | -------------------------------------------------------------------------------- /examples/GSM_GPRSLibrary_BlueTooth_Connect/GSM_GPRSLibrary_BlueTooth_Connect.ino: -------------------------------------------------------------------------------- 1 | #include "bluetooth.h" 2 | #include 3 | /*create a BlueTooth object*/ 4 | BlueTooth blue; 5 | void setup() 6 | { 7 | /*Serial connection.*/ 8 | Serial.begin(9600); 9 | Serial.println("GSM Shield testing."); 10 | 11 | /*Start configuration of shield with baudrate.*/ 12 | /*For http uses is raccomanded to use 4800 or slower.*/ 13 | if (gsm.begin(9600)) 14 | { 15 | Serial.println("\nstatus=READY"); 16 | } 17 | else 18 | Serial.println("\nstatus=IDLE"); 19 | 20 | }; 21 | 22 | void loop() 23 | { 24 | if(blue.powerOff() == true) 25 | Serial.println("close ok"); 26 | else 27 | Serial.println("close failed "); 28 | 29 | if(blue.powerOn() == true) 30 | Serial.println("open ok "); 31 | else 32 | Serial.println("open failed"); 33 | 34 | int bluetemp = 0; 35 | delay(2000); 36 | while((bluetemp=blue.acceptPairing()) == 0); 37 | while(1); 38 | }; 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /examples/GSM_GPRSLibrary_BlueTooth_SPP/GSM_GPRSLibrary_BlueTooth_SPP.ino: -------------------------------------------------------------------------------- 1 | #include "bluetooth.h" 2 | #include 3 | 4 | /*create a BlueTooth object*/ 5 | BlueTooth blue; 6 | void setup() 7 | { 8 | /*Serial connection.*/ 9 | Serial.begin(9600); 10 | Serial.println("GSM Shield testing."); 11 | 12 | /*Start configuration of shield with baudrate. */ 13 | /*For http uses is raccomanded to use 4800 or slower.*/ 14 | if (gsm.begin(9600)) 15 | { 16 | Serial.println("\nstatus=READY"); 17 | } 18 | else 19 | Serial.println("\nstatus=IDLE"); 20 | 21 | }; 22 | 23 | void loop() 24 | { 25 | if(blue.powerOff() == true) 26 | Serial.println("close ok"); 27 | else 28 | Serial.println("close failed "); 29 | 30 | if(blue.powerOn() == true) 31 | Serial.println("open ok "); 32 | else 33 | Serial.println("open failed"); 34 | 35 | int bluetemp = 0; 36 | delay(2000); 37 | while((bluetemp=blue.acceptPairing()) == 0); 38 | while(blue.connectInSPP(bluetemp)) 39 | { 40 | char data[20]={0}; 41 | if(blue.recvInSPP(data) == 1) 42 | Serial.println(data); 43 | if(strlen(data)!=0) 44 | { 45 | blue.sendInSPP(data); 46 | } 47 | } 48 | }; 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /examples/GSM_GPRSLibrary_Call/GSM_GPRSLibrary_Call.ino: -------------------------------------------------------------------------------- 1 | #include "SIM900.h" 2 | #include 3 | //We don't need the http functions. So we can disable the next line. 4 | //#include "inetGSM.h" 5 | #include "sms.h" 6 | #include "call.h" 7 | 8 | //To change pins for Software Serial, use the two lines in GSM.cpp. 9 | 10 | //GSM Shield for Arduino 11 | //www.open-electronics.org 12 | //this code is based on the example of Arduino Labs. 13 | 14 | //Simple sketch to check if an incoming call is from an authorized 15 | //number and in this case, send to this number an SMS with the value 16 | //of a digital input. 17 | 18 | //We have to create the classes for SMSs and calls. 19 | CallGSM call; 20 | SMSGSM sms; 21 | 22 | char number[20]; 23 | byte stat=0; 24 | int value=0; 25 | int pin=1; 26 | char value_str[5]; 27 | 28 | void setup() 29 | { 30 | pinMode(pin,INPUT); 31 | //Serial connection. 32 | Serial.begin(9600); 33 | Serial.println("GSM Shield testing."); 34 | //Start configuration of shield with baudrate. 35 | //For http uses is raccomanded to use 4800 or slower. 36 | if (gsm.begin(2400)) 37 | Serial.println("\nstatus=READY"); 38 | else Serial.println("\nstatus=IDLE"); 39 | }; 40 | 41 | void loop() 42 | { 43 | //Chekcs status of call 44 | stat=call.CallStatusWithAuth(number,1,3); 45 | //If the incoming call is from an authorized number 46 | //saved on SIM in the positions range from 1 to 3. 47 | if(stat==CALL_INCOM_VOICE_AUTH) { 48 | //Hang up the call. 49 | call.HangUp(); 50 | delay(2000); 51 | //Check the value of the input. 52 | value=digitalRead(1); 53 | //Convert the int to a string. 54 | itoa(value,value_str,10); 55 | //Send an SMS to the previous number with 56 | //the value read previously. 57 | sms.SendSMS(number,value_str); 58 | } 59 | delay(1000); 60 | }; 61 | -------------------------------------------------------------------------------- /examples/GSM_GPRSLibrary_Client/GSM_GPRSLibrary_Client.ino: -------------------------------------------------------------------------------- 1 | #include "SIM900.h" 2 | #include 3 | #include "inetGSM.h" 4 | //#include "sms.h" 5 | //#include "call.h" 6 | 7 | //To change pins for Software Serial, use the two lines in GSM.cpp. 8 | 9 | //GSM Shield for Arduino 10 | //www.open-electronics.org 11 | //this code is based on the example of Arduino Labs. 12 | 13 | //Simple sketch to start a connection as client. 14 | 15 | InetGSM inet; 16 | //CallGSM call; 17 | //SMSGSM sms; 18 | 19 | char msg[50]; 20 | int numdata; 21 | char inSerial[50]; 22 | int i=0; 23 | boolean started=false; 24 | 25 | void setup() 26 | { 27 | //Serial connection. 28 | Serial.begin(9600); 29 | Serial.println("GSM Shield testing."); 30 | //Start configuration of shield with baudrate. 31 | //For http uses is raccomanded to use 4800 or slower. 32 | if (gsm.begin(2400)) { 33 | Serial.println("\nstatus=READY"); 34 | started=true; 35 | } else Serial.println("\nstatus=IDLE"); 36 | 37 | if(started) { 38 | //GPRS attach, put in order APN, username and password. 39 | //If no needed auth let them blank. 40 | if (inet.attachGPRS("internet.wind", "", "")) 41 | Serial.println("status=ATTACHED"); 42 | else Serial.println("status=ERROR"); 43 | delay(1000); 44 | 45 | //Read IP address. 46 | gsm.SimpleWriteln("AT+CIFSR"); 47 | delay(5000); 48 | //Read until serial buffer is empty. 49 | gsm.WhileSimpleRead(); 50 | 51 | //TCP Client GET, send a GET request to the server and 52 | //save the reply. 53 | numdata=inet.httpGET("www.google.com", 80, "/", msg, 50); 54 | //Print the results. 55 | Serial.println("\nNumber of data received:"); 56 | Serial.println(numdata); 57 | Serial.println("\nData received:"); 58 | Serial.println(msg); 59 | } 60 | }; 61 | 62 | void loop() 63 | { 64 | //Read for new byte on serial hardware, 65 | //and write them on NewSoftSerial. 66 | serialhwread(); 67 | //Read for new byte on NewSoftSerial. 68 | serialswread(); 69 | }; 70 | 71 | void serialhwread() 72 | { 73 | i=0; 74 | if (Serial.available() > 0) { 75 | while (Serial.available() > 0) { 76 | inSerial[i]=(Serial.read()); 77 | delay(10); 78 | i++; 79 | } 80 | 81 | inSerial[i]='\0'; 82 | if(!strcmp(inSerial,"/END")) { 83 | Serial.println("_"); 84 | inSerial[0]=0x1a; 85 | inSerial[1]='\0'; 86 | gsm.SimpleWriteln(inSerial); 87 | } 88 | //Send a saved AT command using serial port. 89 | if(!strcmp(inSerial,"TEST")) { 90 | Serial.println("SIGNAL QUALITY"); 91 | gsm.SimpleWriteln("AT+CSQ"); 92 | } 93 | //Read last message saved. 94 | if(!strcmp(inSerial,"MSG")) { 95 | Serial.println(msg); 96 | } else { 97 | Serial.println(inSerial); 98 | gsm.SimpleWriteln(inSerial); 99 | } 100 | inSerial[0]='\0'; 101 | } 102 | } 103 | 104 | void serialswread() 105 | { 106 | gsm.SimpleRead(); 107 | } 108 | -------------------------------------------------------------------------------- /examples/GSM_GPRSLibrary_DTMF/GSM_GPRSLibrary_DTMF.ino: -------------------------------------------------------------------------------- 1 | #include "SIM900.h" 2 | #include 3 | //We don't need the http functions. So we can disable the next line. 4 | //#include "inetGSM.h" 5 | #include "sms.h" 6 | #include "call.h" 7 | 8 | //To change pins for Software Serial, use the two lines in GSM.cpp. 9 | 10 | //GSM Shield for Arduino 11 | //www.open-electronics.org 12 | //this code is based on the example of Arduino Labs. 13 | 14 | //Simple sketch to detect DTMF tones during a call 15 | 16 | //We have to create the classes for calls. 17 | CallGSM call; 18 | 19 | char number[20]; 20 | byte stat=0; 21 | int value=0; 22 | int pin=1; 23 | char value_str[5]; 24 | char DTMF_char='_'; 25 | int count=0; 26 | 27 | void setup() 28 | { 29 | pinMode(pin,INPUT); 30 | //Serial connection. 31 | Serial.begin(9600); 32 | Serial.println("GSM Shield testing."); 33 | //Start configuration of shield with baudrate. 34 | //For http uses is raccomanded to use 4800 or slower. 35 | if (gsm.begin(9600)) 36 | Serial.println("\nstatus=READY"); 37 | else Serial.println("\nstatus=IDLE"); 38 | //Enable DTMF detection for SIM900 39 | call.SetDTMF(1); 40 | }; 41 | 42 | void loop() 43 | { 44 | //Chekcs status of call 45 | stat=call.CallStatus(); 46 | //If the incoming call is from an authorized number 47 | //saved on SIM in the positions range from 1 to 3. 48 | if(stat==CALL_INCOM_VOICE) { 49 | Serial.println("Pick Up"); 50 | delay(50); 51 | call.PickUp(); 52 | } 53 | while(stat==CALL_ACTIVE_VOICE) { 54 | for (int k=0; k<100; k++) { 55 | DTMF_char=call.DetDTMF(); 56 | if(DTMF_char!='-') 57 | Serial.println(DTMF_char); 58 | } 59 | stat=call.CallStatus(); 60 | 61 | } 62 | delay(1000); 63 | }; 64 | -------------------------------------------------------------------------------- /examples/GSM_GPRSLibrary_GPS/GSM_GPRSLibrary_GPS.ino: -------------------------------------------------------------------------------- 1 | #include "SIM900.h" 2 | #include 3 | //#include "inetGSM.h" 4 | //#include "sms.h" 5 | //#include "call.h" 6 | #include "gps.h" 7 | 8 | //To change pins for Software Serial, use the two lines in GSM.cpp. 9 | 10 | //GSM Shield for Arduino 11 | //www.open-electronics.org 12 | //this code is based on the example of Arduino Labs. 13 | 14 | //Simple sketch to start a connection as client. 15 | 16 | //InetGSM inet; 17 | //CallGSM call; 18 | //SMSGSM sms; 19 | GPSGSM gps; 20 | 21 | char lon[15]; 22 | char lat[15]; 23 | char alt[15]; 24 | char time[20]; 25 | char vel[15]; 26 | char msg1[5]; 27 | char msg2[5]; 28 | 29 | char stat; 30 | char inSerial[20]; 31 | int i=0; 32 | boolean started=false; 33 | 34 | void setup() 35 | { 36 | //Serial connection. 37 | Serial.begin(9600); 38 | Serial.println("GSM Shield testing."); 39 | //Start configuration of shield with baudrate. 40 | //For http uses is raccomanded to use 4800 or slower. 41 | if (gsm.begin(2400)) { 42 | Serial.println("\nstatus=READY"); 43 | gsm.forceON(); //To ensure that SIM908 is not only in charge mode 44 | started=true; 45 | } else Serial.println("\nstatus=IDLE"); 46 | 47 | if(started) { 48 | //GPS attach 49 | if (gps.attachGPS()) 50 | Serial.println("status=GPSREADY"); 51 | else Serial.println("status=ERROR"); 52 | 53 | delay(20000); //Time for fixing 54 | stat=gps.getStat(); 55 | if(stat==1) 56 | Serial.println("NOT FIXED"); 57 | else if(stat==0) 58 | Serial.println("GPS OFF"); 59 | else if(stat==2) 60 | Serial.println("2D FIXED"); 61 | else if(stat==3) 62 | Serial.println("3D FIXED"); 63 | delay(5000); 64 | //Get data from GPS 65 | gps.getPar(lon,lat,alt,time,vel); 66 | Serial.println(lon); 67 | Serial.println(lat); 68 | Serial.println(alt); 69 | Serial.println(time); 70 | Serial.println(vel); 71 | } 72 | }; 73 | 74 | void loop() 75 | { 76 | //Read for new byte on serial hardware, 77 | //and write them on NewSoftSerial. 78 | serialhwread(); 79 | //Read for new byte on NewSoftSerial. 80 | serialswread(); 81 | }; 82 | 83 | void serialhwread() 84 | { 85 | i=0; 86 | if (Serial.available() > 0) { 87 | while (Serial.available() > 0) { 88 | inSerial[i]=(Serial.read()); 89 | delay(10); 90 | i++; 91 | } 92 | 93 | inSerial[i]='\0'; 94 | if(!strcmp(inSerial,"/END")) { 95 | Serial.println("_"); 96 | inSerial[0]=0x1a; 97 | inSerial[1]='\0'; 98 | gsm.SimpleWriteln(inSerial); 99 | } 100 | //Send a saved AT command using serial port. 101 | if(!strcmp(inSerial,"TEST")) { 102 | // Serial.println("BATTERY TEST 1"); 103 | // gps.getBattInf(msg1,msg2); 104 | // Serial.println(msg1); 105 | // Serial.println(msg2); 106 | // Serial.println("BATTERY TEST 2"); 107 | // gps.getBattTVol(msg1); 108 | // Serial.println(msg1); 109 | stat=gps.getStat(); 110 | if(stat==1) 111 | Serial.println("NOT FIXED"); 112 | else if(stat==0) 113 | Serial.println("GPS OFF"); 114 | else if(stat==2) 115 | Serial.println("2D FIXED"); 116 | else if(stat==3) 117 | Serial.println("3D FIXED"); 118 | } 119 | //Read last message saved. 120 | if(!strcmp(inSerial,"MSG")) { 121 | Serial.println(msg1); 122 | } else { 123 | Serial.println(inSerial); 124 | gsm.SimpleWriteln(inSerial); 125 | } 126 | inSerial[0]='\0'; 127 | } 128 | } 129 | 130 | void serialswread() 131 | { 132 | gsm.SimpleRead(); 133 | } 134 | -------------------------------------------------------------------------------- /examples/GSM_GPRSLibrary_SMS/GSM_GPRSLibrary_SMS.ino: -------------------------------------------------------------------------------- 1 | #include "SIM900.h" 2 | #include 3 | //If not used, is better to exclude the HTTP library, 4 | //for RAM saving. 5 | //If your sketch reboots itself proprably you have finished, 6 | //your memory available. 7 | //#include "inetGSM.h" 8 | 9 | //If you want to use the Arduino functions to manage SMS, uncomment the lines below. 10 | #include "sms.h" 11 | SMSGSM sms; 12 | 13 | //To change pins for Software Serial, use the two lines in GSM.cpp. 14 | 15 | //GSM Shield for Arduino 16 | //www.open-electronics.org 17 | //this code is based on the example of Arduino Labs. 18 | 19 | //Simple sketch to send and receive SMS. 20 | 21 | int numdata; 22 | boolean started=false; 23 | char smsbuffer[160]; 24 | char n[20]; 25 | 26 | void setup() 27 | { 28 | //Serial connection. 29 | Serial.begin(9600); 30 | Serial.println("GSM Shield testing."); 31 | //Start configuration of shield with baudrate. 32 | //For http uses is raccomanded to use 4800 or slower. 33 | if (gsm.begin(2400)) { 34 | Serial.println("\nstatus=READY"); 35 | started=true; 36 | } else Serial.println("\nstatus=IDLE"); 37 | 38 | if(started) { 39 | //Enable this two lines if you want to send an SMS. 40 | //if (sms.SendSMS("3471234567", "Arduino SMS")) 41 | //Serial.println("\nSMS sent OK"); 42 | } 43 | 44 | }; 45 | 46 | void loop() 47 | { 48 | if(started) { 49 | //Read if there are messages on SIM card and print them. 50 | if(gsm.readSMS(smsbuffer, 160, n, 20)) { 51 | Serial.println(n); 52 | Serial.println(smsbuffer); 53 | } 54 | delay(1000); 55 | } 56 | }; 57 | -------------------------------------------------------------------------------- /examples/GSM_GPRSLibrary_Server/GSM_GPRSLibrary_Server.ino: -------------------------------------------------------------------------------- 1 | #include "SIM900.h" 2 | #include 3 | #include "inetGSM.h" 4 | //#include "sms.h" 5 | //#include "call.h" 6 | 7 | //To change pins for Software Serial, use the two lines in GSM.cpp. 8 | 9 | //GSM Shield for Arduino 10 | //www.open-electronics.org 11 | //this code is based on the example of Arduino Labs. 12 | 13 | //Simple sketch to start a connection as server. 14 | 15 | InetGSM inet; 16 | //CallGSM call; 17 | //SMSGSM sms; 18 | 19 | char msg[50]; 20 | int numdata; 21 | char inSerial[50]; 22 | int i=0; 23 | boolean started=false; 24 | long lasttime=millis(); 25 | 26 | void setup() 27 | { 28 | //Serial connection. 29 | Serial.begin(9600); 30 | Serial.println("GSM Shield testing."); 31 | //Start configuration of shield with baudrate. 32 | //For http uses is raccomanded to use 4800 or slower. 33 | if (gsm.begin(2400)) { 34 | Serial.println("\nstatus=READY"); 35 | started=true; 36 | } else Serial.println("\nstatus=IDLE"); 37 | 38 | if(started) { 39 | //GPRS attach, put in order APN, username and password. 40 | //If no needed auth let them blank. 41 | if (inet.attachGPRS("internet.wind", "", "")) 42 | Serial.println("status=ATTACHED"); 43 | else Serial.println("status=ERROR"); 44 | delay(1000); 45 | 46 | //Read IP address. 47 | gsm.SimpleWriteln("AT+CIFSR"); 48 | delay(5000); 49 | int i=0; 50 | while(i<20) { 51 | gsm.SimpleRead(); 52 | i++; 53 | } 54 | 55 | //TCP Server. Start the socket connection 56 | //as server on the assigned port. 57 | Serial.println(msg); 58 | delay(5000); 59 | if (inet.connectTCPServer(80)) 60 | Serial.println("status=TCPSERVERWAIT"); 61 | else Serial.println("ERROR in Server"); 62 | lasttime=millis(); 63 | } 64 | }; 65 | 66 | 67 | void loop() 68 | { 69 | if(started) { 70 | //Check if there is an active connection. 71 | if (inet.connectedClient()) { 72 | //Read and print the last message received. 73 | gsm.read(msg, 50); 74 | Serial.println(msg); 75 | } 76 | } else { 77 | serialhwread(); 78 | serialswread(); 79 | } 80 | }; 81 | 82 | void serialhwread() 83 | { 84 | i=0; 85 | if (Serial.available() > 0) { 86 | while (Serial.available() > 0) { 87 | inSerial[i]=(Serial.read()); 88 | delay(10); 89 | i++; 90 | } 91 | 92 | inSerial[i]='\0'; 93 | if(!strcmp(inSerial,"/END")) { 94 | Serial.println("_"); 95 | inSerial[0]=0x1a; 96 | inSerial[1]='\0'; 97 | gsm.SimpleWriteln(inSerial); 98 | } 99 | //Send a saved AT command using serial port. 100 | if(!strcmp(inSerial,"TEST")) { 101 | Serial.println("SIGNAL QUALITY"); 102 | gsm.SimpleWriteln("AT+CSQ"); 103 | } 104 | //Read last message saved. 105 | if(!strcmp(inSerial,"MSG")) { 106 | Serial.println(msg); 107 | } else { 108 | Serial.println(inSerial); 109 | gsm.SimpleWriteln(inSerial); 110 | } 111 | inSerial[0]='\0'; 112 | } 113 | } 114 | 115 | void serialswread() 116 | { 117 | gsm.SimpleRead(); 118 | } -------------------------------------------------------------------------------- /gps.cpp: -------------------------------------------------------------------------------- 1 | #include "gps.h" 2 | char GPSGSM::getBattInf(char *str_perc, char *str_vol) 3 | { 4 | char ret_val=0; 5 | char *p_char; 6 | char *p_char1; 7 | 8 | gsm.SimpleWriteln("AT+CBC"); 9 | gsm.WaitResp(5000, 100, "OK"); 10 | if(gsm.IsStringReceived("+CBC")) 11 | ret_val=1; 12 | 13 | //BCL 14 | p_char = strchr((char *)(gsm.comm_buf),','); 15 | p_char1 = p_char+1; //we are on the first char of BCS 16 | p_char = strchr((char *)(p_char1), ','); 17 | if (p_char != NULL) { 18 | *p_char = 0; 19 | } 20 | strcpy(str_perc, (char *)(p_char1)); 21 | 22 | //Voltage 23 | p_char++; 24 | p_char1 = strchr((char *)(p_char), '\r'); 25 | if (p_char1 != NULL) { 26 | *p_char1 = 0; 27 | } 28 | strcpy(str_vol, (char *)(p_char)); 29 | return ret_val; 30 | } 31 | 32 | char GPSGSM::getBattTVol(char *str_vol) 33 | { 34 | char *p_char; 35 | char *p_char1; 36 | char ret_val=0; 37 | 38 | gsm.SimpleWriteln("AT+CBTE?"); 39 | gsm.WaitResp(5000, 100, "OK"); 40 | if(gsm.IsStringReceived("+CBTE")) 41 | ret_val=1; 42 | 43 | //BCL 44 | p_char = strchr((char *)(gsm.comm_buf),':'); 45 | p_char1 = p_char+2; //we are on the first char of BCS 46 | p_char = strchr((char *)(p_char1), '\r'); 47 | if (p_char != NULL) { 48 | *p_char = 0; 49 | } 50 | strcpy(str_vol, (char *)(p_char1)); 51 | return ret_val; 52 | } 53 | 54 | char GPSGSM::attachGPS() 55 | { 56 | if(AT_RESP_ERR_DIF_RESP == gsm.SendATCmdWaitResp("AT+CGPSPWR=1", 500, 100, "OK", 5)) 57 | return 0; 58 | if(AT_RESP_ERR_DIF_RESP == gsm.SendATCmdWaitResp("AT+CGPSRST=1", 500, 100, "OK", 5)) 59 | return 0; 60 | return 1; 61 | } 62 | 63 | char GPSGSM::deattachGPS() 64 | { 65 | if(AT_RESP_ERR_DIF_RESP == gsm.SendATCmdWaitResp("AT+CGPSPWR=0", 500, 100, "OK", 5)) 66 | return 0; 67 | return 1; 68 | } 69 | 70 | char GPSGSM::getStat() 71 | { 72 | char ret_val=-1; 73 | gsm.SimpleWriteln("AT+CGPSSTATUS?"); 74 | gsm.WaitResp(5000, 100, "OK"); 75 | if(gsm.IsStringReceived("Unknown")||gsm.IsStringReceived("unknown")) 76 | ret_val=0; 77 | else if(gsm.IsStringReceived("Not")) 78 | ret_val=1; 79 | else if(gsm.IsStringReceived("2D")||gsm.IsStringReceived("2d")) 80 | ret_val=2; 81 | else if(gsm.IsStringReceived("3D")||gsm.IsStringReceived("3d")) 82 | ret_val=3; 83 | return ret_val; 84 | } 85 | 86 | char GPSGSM::getPar(char *str_long, char *str_lat, char *str_alt, char *str_time, char *str_speed) 87 | { 88 | char ret_val=0; 89 | char *p_char; 90 | char *p_char1; 91 | gsm.SimpleWriteln("AT+CGPSINF=0"); 92 | gsm.WaitResp(5000, 100, "OK"); 93 | if(gsm.IsStringReceived("OK")) 94 | ret_val=1; 95 | 96 | //longitude 97 | p_char = strchr((char *)(gsm.comm_buf),','); 98 | p_char1 = p_char+1; //we are on the first char of longitude 99 | p_char = strchr((char *)(p_char1), ','); 100 | if (p_char != NULL) { 101 | *p_char = 0; 102 | } 103 | strcpy(str_long, (char *)(p_char1)); 104 | 105 | // latitude 106 | p_char++; 107 | p_char1 = strchr((char *)(p_char), ','); 108 | if (p_char1 != NULL) { 109 | *p_char1 = 0; 110 | } 111 | strcpy(str_lat, (char *)(p_char)); 112 | 113 | // altitude 114 | p_char1++; 115 | p_char = strchr((char *)(p_char1), ','); 116 | if (p_char != NULL) { 117 | *p_char = 0; 118 | } 119 | strcpy(str_alt, (char *)(p_char1)); 120 | 121 | // UTC time 122 | p_char++; 123 | p_char1 = strchr((char *)(p_char), ','); 124 | if (p_char1 != NULL) { 125 | *p_char1 = 0; 126 | } 127 | strcpy(str_time, (char *)(p_char)); 128 | 129 | // TTFF 130 | p_char1++; 131 | p_char = strchr((char *)(p_char1), ','); 132 | if (p_char != NULL) { 133 | *p_char = 0; 134 | } 135 | 136 | // num 137 | p_char++; 138 | p_char1 = strchr((char *)(p_char), ','); 139 | if (p_char1 != NULL) { 140 | *p_char1 = 0; 141 | } 142 | 143 | // speed 144 | p_char1++; 145 | p_char = strchr((char *)(p_char1), ','); 146 | if (p_char != NULL) { 147 | *p_char = 0; 148 | } 149 | strcpy(str_speed, (char *)(p_char1)); 150 | 151 | return ret_val; 152 | } 153 | 154 | void parseTime(char *field, int *time) 155 | { 156 | ////////////////Time//////////// 157 | char tmp[4]; 158 | tmp[2]=0; // Init tmp and null terminate 159 | tmp[0] = field[8]; 160 | tmp[1] = field[9]; 161 | time[0] = atoi(tmp); // Hours 162 | tmp[0] = field[10]; 163 | tmp[1] = field[11]; 164 | time[1] = atoi(tmp); // Minutes 165 | tmp[0] = field[12]; 166 | tmp[1] = field[13]; 167 | time[2] = atoi(tmp); // Seconds 168 | /////////////Date/////////////// 169 | tmp[0] = field[0]; 170 | tmp[1] = field[1]; 171 | tmp[2] = field[2]; 172 | tmp[3] = field[3]; 173 | tmp[4]=0; // Init tmp and null terminate 174 | time[3] = atoi(tmp); // year 175 | tmp[0] = field[4]; 176 | tmp[1] = field[5]; 177 | tmp[2]=0; // Init tmp and null terminate 178 | time[4] = atoi(tmp); // month 179 | tmp[0] = field[6]; 180 | tmp[1] = field[7]; 181 | tmp[2]=0; // Init tmp and null terminate 182 | time[5] = atoi(tmp); // day 183 | } 184 | 185 | // Read the latitude in decimal format from a GGA string 186 | double convertLat(char* latString) 187 | { 188 | double latitude = atof(latString); // convert to a double (precise) 189 | int deg = (int) latitude / 100; // extract the number of degrees 190 | double min = latitude - (100 * deg); // work out the number of minutes 191 | latitude = deg + (double) min/60.0; // convert to decimal format 192 | return latitude; 193 | } 194 | 195 | // Read the longitude in decimal format from a GGA string 196 | double convertLong(char* longString) 197 | { 198 | double longitude = atof(longString); // convert to a double 199 | int deg = (int) longitude / 100; // extract the number of degrees 200 | double min = longitude - (100 * deg); // work out the number of minutes 201 | longitude = deg + (double) min/60.00; // convert to decimal format 202 | return longitude; 203 | } -------------------------------------------------------------------------------- /gps.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPS_H_ 2 | #define _GPS_H_ 3 | 4 | #include "SIM900.h" 5 | 6 | class GPSGSM { 7 | public: 8 | char getBattInf(char *str_perc, char *str_vol); 9 | char getBattTVol(char *str_vol); 10 | char attachGPS(); 11 | char deattachGPS(); 12 | char getStat(); 13 | char getPar(char *str_long, char *str_lat, char *str_alt, char *str_time, char *speed); 14 | void parseTime(char *field, int *time); 15 | double convertLat(void); 16 | double convertLong(void); 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /inetGSM.cpp: -------------------------------------------------------------------------------- 1 | #include "inetGSM.h" 2 | #define _GSM_CONNECTION_TOUT_ 5 3 | #define _TCP_CONNECTION_TOUT_ 20 4 | #define _GSM_DATA_TOUT_ 10 5 | 6 | int InetGSM::httpGET(const char* server, int port, const char* path, char* result, int resultlength) 7 | { 8 | boolean connected=false; 9 | int n_of_at=0; 10 | int length_write; 11 | char end_c[2]; 12 | end_c[0]=0x1a; 13 | end_c[1]='\0'; 14 | 15 | /* 16 | Status = ATTACHED. 17 | if(gsm.getStatus()!=GSM::ATTACHED) 18 | return 0; 19 | */ 20 | while(n_of_at<3) { 21 | if(!connectTCP(server, port)) { 22 | #ifdef DEBUG_ON 23 | Serial.println("DB:NOT CONN"); 24 | #endif 25 | n_of_at++; 26 | } else { 27 | connected=true; 28 | n_of_at=3; 29 | } 30 | } 31 | 32 | if(!connected) return 0; 33 | 34 | gsm.SimpleWrite("GET "); 35 | gsm.SimpleWrite(path); 36 | gsm.SimpleWrite(" HTTP/1.0\r\nHost: "); 37 | gsm.SimpleWrite(server); 38 | gsm.SimpleWrite("\r\n"); 39 | gsm.SimpleWrite("User-Agent: Arduino"); 40 | gsm.SimpleWrite("\r\n\r\n"); 41 | gsm.SimpleWrite(end_c); 42 | 43 | switch(gsm.WaitResp(10000, 10, "SEND OK")) { 44 | case RX_TMOUT_ERR: 45 | return 0; 46 | break; 47 | case RX_FINISHED_STR_NOT_RECV: 48 | return 0; 49 | break; 50 | } 51 | 52 | 53 | delay(50); 54 | #ifdef DEBUG_ON 55 | Serial.println("DB:SENT"); 56 | #endif 57 | int res = gsm.read(result, resultlength); 58 | 59 | //gsm.disconnectTCP(); 60 | 61 | //int res=1; 62 | return res; 63 | } 64 | 65 | int InetGSM::httpPOST(const char* server, int port, const char* path, const char* parameters, char* result, int resultlength) 66 | { 67 | boolean connected=false; 68 | int n_of_at=0; 69 | char itoaBuffer[8]; 70 | int num_char; 71 | char end_c[2]; 72 | end_c[0]=0x1a; 73 | end_c[1]='\0'; 74 | 75 | while(n_of_at<3) { 76 | if(!connectTCP(server, port)) { 77 | #ifdef DEBUG_ON 78 | Serial.println("DB:NOT CONN"); 79 | #endif 80 | n_of_at++; 81 | } else { 82 | connected=true; 83 | n_of_at=3; 84 | } 85 | } 86 | 87 | if(!connected) return 0; 88 | 89 | gsm.SimpleWrite("POST "); 90 | gsm.SimpleWrite(path); 91 | gsm.SimpleWrite(" HTTP/1.1\r\nHost: "); 92 | gsm.SimpleWrite(server); 93 | gsm.SimpleWrite("\r\n"); 94 | gsm.SimpleWrite("User-Agent: Arduino\r\n"); 95 | gsm.SimpleWrite("Content-Type: application/x-www-form-urlencoded\r\n"); 96 | gsm.SimpleWrite("Content-Length: "); 97 | itoa(strlen(parameters),itoaBuffer,10); 98 | gsm.SimpleWrite(itoaBuffer); 99 | gsm.SimpleWrite("\r\n\r\n"); 100 | gsm.SimpleWrite(parameters); 101 | gsm.SimpleWrite("\r\n\r\n"); 102 | gsm.SimpleWrite(end_c); 103 | 104 | switch(gsm.WaitResp(10000, 10, "SEND OK")) { 105 | case RX_TMOUT_ERR: 106 | return 0; 107 | break; 108 | case RX_FINISHED_STR_NOT_RECV: 109 | return 0; 110 | break; 111 | } 112 | 113 | delay(50); 114 | #ifdef DEBUG_ON 115 | Serial.println("DB:SENT"); 116 | #endif 117 | 118 | int res= gsm.read(result, resultlength); 119 | //gsm.disconnectTCP(); 120 | return res; 121 | } 122 | 123 | int InetGSM::openmail(char* server, char* loginbase64, char* passbase64, char* from, char* to, char* subj) 124 | { 125 | boolean connected=false; 126 | int n_of_at=0; 127 | char end_c[2]; 128 | end_c[0]=0x1a; 129 | end_c[1]='\0'; 130 | 131 | while(n_of_at<3) { 132 | if(!connectTCP(server, 25)) { 133 | #ifdef DEBUG_ON 134 | Serial.println("DB:NOT CONN"); 135 | #endif 136 | n_of_at++; 137 | } else { 138 | connected=true; 139 | n_of_at=3; 140 | } 141 | } 142 | 143 | if(!connected) return 0; 144 | 145 | delay(100); 146 | gsm.SimpleWrite("HELO "); 147 | gsm.SimpleWrite(server); 148 | gsm.SimpleWrite("\n"); 149 | gsm.SimpleWrite(end_c); 150 | gsm.WaitResp(5000, 100, "OK"); 151 | if(!gsm.IsStringReceived("SEND OK")) 152 | return 0; 153 | delay(500); 154 | gsm.WaitResp(5000, 100); 155 | 156 | delay(100); 157 | gsm.SimpleWriteln("AT+CIPSEND"); 158 | switch(gsm.WaitResp(5000, 200, ">")) { 159 | case RX_TMOUT_ERR: 160 | return 0; 161 | break; 162 | case RX_FINISHED_STR_NOT_RECV: 163 | return 0; 164 | break; 165 | } 166 | gsm.SimpleWrite("AUTH LOGIN\n"); 167 | gsm.SimpleWrite(end_c); 168 | gsm.WaitResp(5000, 100, "OK"); 169 | if(!gsm.IsStringReceived("OK")) 170 | return 0; 171 | delay(500); 172 | gsm.WaitResp(5000, 100); 173 | 174 | delay(100); 175 | gsm.SimpleWriteln("AT+CIPSEND"); 176 | switch(gsm.WaitResp(5000, 200, ">")) { 177 | case RX_TMOUT_ERR: 178 | return 0; 179 | break; 180 | case RX_FINISHED_STR_NOT_RECV: 181 | return 0; 182 | break; 183 | } 184 | gsm.SimpleWrite(loginbase64); 185 | gsm.SimpleWrite("\n"); 186 | gsm.SimpleWrite(end_c); 187 | gsm.WaitResp(5000, 100, "OK"); 188 | if(!gsm.IsStringReceived("OK")) 189 | return 0; 190 | delay(500); 191 | gsm.WaitResp(5000, 100); 192 | 193 | delay(100); 194 | gsm.SimpleWriteln("AT+CIPSEND"); 195 | switch(gsm.WaitResp(5000, 200, ">")) { 196 | case RX_TMOUT_ERR: 197 | return 0; 198 | break; 199 | case RX_FINISHED_STR_NOT_RECV: 200 | return 0; 201 | break; 202 | } 203 | gsm.SimpleWrite(passbase64); 204 | gsm.SimpleWrite("\n"); 205 | gsm.SimpleWrite(end_c); 206 | gsm.WaitResp(5000, 100, "OK"); 207 | if(!gsm.IsStringReceived("OK")) 208 | return 0; 209 | delay(500); 210 | gsm.WaitResp(5000, 100); 211 | 212 | 213 | delay(100); 214 | gsm.SimpleWriteln("AT+CIPSEND"); 215 | switch(gsm.WaitResp(5000, 200, ">")) { 216 | case RX_TMOUT_ERR: 217 | return 0; 218 | break; 219 | case RX_FINISHED_STR_NOT_RECV: 220 | return 0; 221 | break; 222 | } 223 | gsm.SimpleWrite("MAIL From: <"); 224 | gsm.SimpleWrite(from); 225 | gsm.SimpleWrite(">\n"); 226 | gsm.SimpleWrite(end_c); 227 | gsm.WaitResp(5000, 100, "OK"); 228 | if(!gsm.IsStringReceived("OK")) 229 | return 0; 230 | delay(500); 231 | gsm.WaitResp(5000, 100, ""); 232 | 233 | delay(100); 234 | gsm.SimpleWriteln("AT+CIPSEND"); 235 | switch(gsm.WaitResp(5000, 200, ">")) { 236 | case RX_TMOUT_ERR: 237 | return 0; 238 | break; 239 | case RX_FINISHED_STR_NOT_RECV: 240 | return 0; 241 | break; 242 | } 243 | gsm.SimpleWrite("RCPT TO: <"); 244 | gsm.SimpleWrite(to); 245 | gsm.SimpleWrite(">\n"); 246 | gsm.SimpleWrite(end_c); 247 | gsm.WaitResp(5000, 100, "OK"); 248 | if(!gsm.IsStringReceived("OK")) 249 | return 0; 250 | delay(500); 251 | gsm.WaitResp(5000, 100, ""); 252 | 253 | delay(100); 254 | gsm.SimpleWriteln("AT+CIPSEND"); 255 | switch(gsm.WaitResp(5000, 200, ">")) { 256 | case RX_TMOUT_ERR: 257 | return 0; 258 | break; 259 | case RX_FINISHED_STR_NOT_RECV: 260 | return 0; 261 | break; 262 | } 263 | gsm.SimpleWrite("Data\n"); 264 | gsm.SimpleWrite(end_c); 265 | gsm.WaitResp(5000, 100, "OK"); 266 | if(!gsm.IsStringReceived("OK")) 267 | return 0; 268 | delay(500); 269 | gsm.WaitResp(5000, 100, ""); 270 | 271 | delay(100); 272 | gsm.SimpleWriteln("AT+CIPSEND"); 273 | switch(gsm.WaitResp(5000, 200, ">")) { 274 | case RX_TMOUT_ERR: 275 | return 0; 276 | break; 277 | case RX_FINISHED_STR_NOT_RECV: 278 | return 0; 279 | break; 280 | } 281 | gsm.SimpleWrite("Subject: "); 282 | gsm.SimpleWrite(subj); 283 | gsm.SimpleWrite("\n\n"); 284 | 285 | return 1; 286 | } 287 | int InetGSM::closemail() 288 | { 289 | char end_c[2]; 290 | end_c[0]=0x1a; 291 | end_c[1]='\0'; 292 | 293 | gsm.SimpleWrite("\n.\n"); 294 | gsm.SimpleWrite(end_c); 295 | disconnectTCP(); 296 | return 1; 297 | } 298 | 299 | 300 | int InetGSM::attachGPRS(char* domain, char* dom1, char* dom2) 301 | { 302 | int i=0; 303 | delay(5000); 304 | 305 | //gsm._tf.setTimeout(_GSM_DATA_TOUT_); //Timeout for expecting modem responses. 306 | gsm.WaitResp(50, 50); 307 | gsm.SimpleWriteln("AT+CIFSR"); 308 | if(gsm.WaitResp(5000, 50, "ERROR")!=RX_FINISHED_STR_RECV) { 309 | #ifdef DEBUG_ON 310 | Serial.println("DB:ALREADY HAVE AN IP"); 311 | #endif 312 | gsm.SimpleWriteln("AT+CIPCLOSE"); 313 | gsm.WaitResp(5000, 50, "ERROR"); 314 | delay(2000); 315 | gsm.SimpleWriteln("AT+CIPSERVER=0"); 316 | gsm.WaitResp(5000, 50, "ERROR"); 317 | return 1; 318 | } else { 319 | 320 | #ifdef DEBUG_ON 321 | Serial.println("DB:STARTING NEW CONNECTION"); 322 | #endif 323 | 324 | gsm.SimpleWriteln("AT+CIPSHUT"); 325 | 326 | switch(gsm.WaitResp(500, 50, "SHUT OK")) { 327 | 328 | case RX_TMOUT_ERR: 329 | return 0; 330 | break; 331 | case RX_FINISHED_STR_NOT_RECV: 332 | return 0; 333 | break; 334 | } 335 | #ifdef DEBUG_ON 336 | Serial.println("DB:SHUTTED OK"); 337 | #endif 338 | delay(1000); 339 | 340 | gsm.SimpleWrite("AT+CSTT=\""); 341 | gsm.SimpleWrite(domain); 342 | gsm.SimpleWrite("\",\""); 343 | gsm.SimpleWrite(dom1); 344 | gsm.SimpleWrite("\",\""); 345 | gsm.SimpleWrite(dom2); 346 | gsm.SimpleWrite("\"\r"); 347 | 348 | 349 | switch(gsm.WaitResp(500, 50, "OK")) { 350 | 351 | case RX_TMOUT_ERR: 352 | return 0; 353 | break; 354 | case RX_FINISHED_STR_NOT_RECV: 355 | return 0; 356 | break; 357 | } 358 | #ifdef DEBUG_ON 359 | Serial.println("DB:APN OK"); 360 | #endif 361 | delay(5000); 362 | 363 | gsm.SimpleWriteln("AT+CIICR"); 364 | 365 | switch(gsm.WaitResp(10000, 50, "OK")) { 366 | case RX_TMOUT_ERR: 367 | return 0; 368 | break; 369 | case RX_FINISHED_STR_NOT_RECV: 370 | return 0; 371 | break; 372 | } 373 | #ifdef DEBUG_ON 374 | Serial.println("DB:CONNECTION OK"); 375 | #endif 376 | 377 | delay(1000); 378 | 379 | 380 | gsm.SimpleWriteln("AT+CIFSR"); 381 | if(gsm.WaitResp(5000, 50, "ERROR")!=RX_FINISHED_STR_RECV) { 382 | #ifdef DEBUG_ON 383 | Serial.println("DB:ASSIGNED AN IP"); 384 | #endif 385 | gsm.setStatus(gsm.ATTACHED); 386 | return 1; 387 | } 388 | #ifdef DEBUG_ON 389 | Serial.println("DB:NO IP AFTER CONNECTION"); 390 | #endif 391 | return 0; 392 | } 393 | } 394 | 395 | int InetGSM::dettachGPRS() 396 | { 397 | if (gsm.getStatus()==gsm.IDLE) return 0; 398 | 399 | //gsm._tf.setTimeout(_GSM_CONNECTION_TOUT_); 400 | 401 | //_cell.flush(); 402 | 403 | //GPRS dettachment. 404 | gsm.SimpleWriteln("AT+CGATT=0"); 405 | if(gsm.WaitResp(5000, 50, "OK")!=RX_FINISHED_STR_NOT_RECV) { 406 | gsm.setStatus(gsm.ERROR); 407 | return 0; 408 | } 409 | delay(500); 410 | 411 | // Commented in initial trial code!! 412 | //Stop IP stack. 413 | //_cell << "AT+WIPCFG=0" << _DEC(cr) << endl; 414 | // if(!gsm._tf.find("OK")) return 0; 415 | //Close GPRS bearer. 416 | //_cell << "AT+WIPBR=0,6" << _DEC(cr) << endl; 417 | 418 | gsm.setStatus(gsm.READY); 419 | return 1; 420 | } 421 | 422 | int InetGSM::connectTCP(const char* server, int port) 423 | { 424 | //gsm._tf.setTimeout(_TCP_CONNECTION_TOUT_); 425 | 426 | //Status = ATTACHED. 427 | //if (getStatus()!=ATTACHED) 428 | //return 0; 429 | 430 | //_cell.flush(); 431 | 432 | //Visit the remote TCP server. 433 | gsm.SimpleWrite("AT+CIPSTART=\"TCP\",\""); 434 | gsm.SimpleWrite(server); 435 | gsm.SimpleWrite("\","); 436 | gsm.SimpleWriteln(port); 437 | 438 | switch(gsm.WaitResp(1000, 200, "OK")) { 439 | case RX_TMOUT_ERR: 440 | return 0; 441 | break; 442 | case RX_FINISHED_STR_NOT_RECV: 443 | return 0; 444 | break; 445 | } 446 | #ifdef DEBUG_ON 447 | Serial.println("DB:RECVD CMD"); 448 | #endif 449 | if (!gsm.IsStringReceived("CONNECT OK")) { 450 | switch(gsm.WaitResp(15000, 200, "OK")) { 451 | case RX_TMOUT_ERR: 452 | return 0; 453 | break; 454 | case RX_FINISHED_STR_NOT_RECV: 455 | return 0; 456 | break; 457 | } 458 | } 459 | 460 | #ifdef DEBUG_ON 461 | Serial.println("DB:OK TCP"); 462 | #endif 463 | 464 | delay(3000); 465 | gsm.SimpleWriteln("AT+CIPSEND"); 466 | switch(gsm.WaitResp(5000, 200, ">")) { 467 | case RX_TMOUT_ERR: 468 | return 0; 469 | break; 470 | case RX_FINISHED_STR_NOT_RECV: 471 | return 0; 472 | break; 473 | } 474 | 475 | #ifdef DEBUG_ON 476 | Serial.println("DB:>"); 477 | #endif 478 | delay(4000); 479 | return 1; 480 | } 481 | 482 | int InetGSM::disconnectTCP() 483 | { 484 | //Status = TCPCONNECTEDCLIENT or TCPCONNECTEDSERVER. 485 | /* 486 | if ((getStatus()!=TCPCONNECTEDCLIENT)&&(getStatus()!=TCPCONNECTEDSERVER)) 487 | return 0; 488 | */ 489 | //gsm._tf.setTimeout(_GSM_CONNECTION_TOUT_); 490 | 491 | 492 | //_cell.flush(); 493 | 494 | //Switch to AT mode. 495 | //_cell << "+++" << endl; 496 | 497 | //delay(200); 498 | 499 | //Close TCP client and deact. 500 | gsm.SimpleWriteln("AT+CIPCLOSE"); 501 | 502 | //If remote server close connection AT+QICLOSE generate ERROR 503 | /*if(gsm._tf.find("OK")) 504 | { 505 | if(getStatus()==TCPCONNECTEDCLIENT) 506 | gsm.setStatus(ATTACHED); 507 | else 508 | gsm.setStatus(TCPSERVERWAIT); 509 | return 1; 510 | } 511 | gsm.setStatus(ERROR); 512 | 513 | return 0; */ 514 | if(gsm.getStatus()==gsm.TCPCONNECTEDCLIENT) 515 | gsm.setStatus(gsm.ATTACHED); 516 | else 517 | gsm.setStatus(gsm.TCPSERVERWAIT); 518 | return 1; 519 | } 520 | 521 | int InetGSM::connectTCPServer(int port) 522 | { 523 | /* 524 | if (getStatus()!=ATTACHED) 525 | return 0; 526 | */ 527 | //gsm._tf.setTimeout(_GSM_CONNECTION_TOUT_); 528 | 529 | //_cell.flush(); 530 | 531 | // Set port 532 | 533 | gsm.SimpleWrite("AT+CIPSERVER=1,"); 534 | gsm.SimpleWriteln(port); 535 | /* 536 | switch(gsm.WaitResp(5000, 50, "OK")){ 537 | case RX_TMOUT_ERR: 538 | return 0; 539 | break; 540 | case RX_FINISHED_STR_NOT_RECV: 541 | return 0; 542 | break; 543 | } 544 | 545 | switch(gsm.WaitResp(5000, 50, "SERVER")){ //Try SERVER OK 546 | case RX_TMOUT_ERR: 547 | return 0; 548 | break; 549 | case RX_FINISHED_STR_NOT_RECV: 550 | return 0; 551 | break; 552 | } 553 | */ 554 | //delay(200); 555 | 556 | return 1; 557 | 558 | } 559 | 560 | boolean InetGSM::connectedClient() 561 | { 562 | /* 563 | if (getStatus()!=TCPSERVERWAIT) 564 | return 0; 565 | */ 566 | 567 | gsm.SimpleWriteln("AT+CIPSTATUS"); 568 | // Alternative: AT+QISTAT, although it may be necessary to call an AT 569 | // command every second,which is not wise 570 | /* 571 | switch(gsm.WaitResp(1000, 200, "OK")){ 572 | case RX_TMOUT_ERR: 573 | return 0; 574 | break; 575 | case RX_FINISHED_STR_NOT_RECV: 576 | return 0; 577 | break; 578 | }*/ 579 | //gsm._tf.setTimeout(1); 580 | if(gsm.WaitResp(5000, 50, "CONNECT OK")!=RX_FINISHED_STR_RECV) { 581 | gsm.setStatus(gsm.TCPCONNECTEDSERVER); 582 | return true; 583 | } else 584 | return false; 585 | } 586 | 587 | -------------------------------------------------------------------------------- /inetGSM.h: -------------------------------------------------------------------------------- 1 | #ifndef _INETGSM_H_ 2 | #define _INETGSM_H_ 3 | 4 | #define BUFFERSIZE 1 5 | 6 | #include "SIM900.h" 7 | 8 | class InetGSM { 9 | private: 10 | char _buffer[BUFFERSIZE]; 11 | 12 | public: 13 | int httpGET(const char* server, int port, const char* path, char* result, int resultlength); 14 | int httpPOST(const char* server, int port, const char* path, const char* parameters, char* result, int resultlength); 15 | 16 | // Fast and dirty solution. Should make a "mail" object. And by the moment it does not run. 17 | int openmail(char* server, char* loginbase64, char* passbase64, char* from, char* to, char* subj); 18 | int closemail(); 19 | int attachGPRS(char* domain, char* dom1, char* dom2); 20 | int dettachGPRS(); 21 | int connectTCP(const char* server, int port); 22 | int disconnectTCP(); 23 | int connectTCPServer(int port); 24 | boolean connectedClient(); 25 | 26 | // This runs, yes 27 | //int tweet(const char* token, const char* msg); 28 | 29 | }; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /sms.cpp: -------------------------------------------------------------------------------- 1 | #include "sms.h" 2 | 3 | /********************************************************** 4 | Method sends SMS 5 | 6 | number_str: pointer to the phone number string 7 | message_str: pointer to the SMS text string 8 | 9 | 10 | return: 11 | ERROR ret. val: 12 | --------------- 13 | -1 - comm. line to the GSM module is not free 14 | -2 - GSM module didn't answer in timeout 15 | -3 - GSM module has answered "ERROR" string 16 | 17 | OK ret val: 18 | ----------- 19 | 0 - SMS was not sent 20 | 1 - SMS was sent 21 | 22 | 23 | an example of usage: 24 | GSM gsm; 25 | gsm.SendSMS("00XXXYYYYYYYYY", "SMS text"); 26 | **********************************************************/ 27 | char SMSGSM::SendSMS(char *number_str, char *message_str) 28 | { 29 | if(strlen(message_str)>159) 30 | Serial.println(F("Don't send message longer than 160 characters")); 31 | char ret_val = -1; 32 | byte i; 33 | char end[2]; 34 | end[0]=0x1a; 35 | end[1]='\0'; 36 | /* 37 | if (CLS_FREE != gsm.GetCommLineStatus()) return (ret_val); 38 | gsm.SetCommLineStatus(CLS_ATCMD); 39 | ret_val = 0; // still not send 40 | */ 41 | // try to send SMS 3 times in case there is some problem 42 | for (i = 0; i < 1; i++) { 43 | // send AT+CMGS="number_str" 44 | 45 | gsm.SimpleWrite(F("AT+CMGS=\"")); 46 | gsm.SimpleWrite(number_str); 47 | gsm.SimpleWriteln("\""); 48 | 49 | #ifdef DEBUG_ON 50 | Serial.println("DEBUG:SMS TEST"); 51 | #endif 52 | // 1000 msec. for initial comm tmout 53 | // 50 msec. for inter character timeout 54 | if (RX_FINISHED_STR_RECV == gsm.WaitResp(1000, 500, ">")) { 55 | #ifdef DEBUG_ON 56 | Serial.println("DEBUG:>"); 57 | #endif 58 | // send SMS text 59 | gsm.SimpleWrite(message_str); 60 | gsm.SimpleWriteln(end); 61 | //_cell.flush(); // erase rx circular buffer 62 | if (RX_FINISHED_STR_RECV == gsm.WaitResp(7000, 5000, "+CMGS")) { 63 | // SMS was send correctly 64 | ret_val = 1; 65 | 66 | break; 67 | } else continue; 68 | } else { 69 | // try again 70 | continue; 71 | 72 | } 73 | } 74 | 75 | gsm.SetCommLineStatus(CLS_FREE); 76 | return (ret_val); 77 | } 78 | 79 | /********************************************************** 80 | Method sends SMS to the specified SIM phonebook position 81 | 82 | sim_phonebook_position: SIM phonebook position <1..20> 83 | message_str: pointer to the SMS text string 84 | 85 | 86 | return: 87 | ERROR ret. val: 88 | --------------- 89 | -1 - comm. line to the GSM module is not free 90 | -2 - GSM module didn't answer in timeout 91 | -3 - specified position must be > 0 92 | 93 | OK ret val: 94 | ----------- 95 | 0 - SMS was not sent 96 | 1 - SMS was sent 97 | 98 | 99 | an example of usage: 100 | GSM gsm; 101 | gsm.SendSMS(1, "SMS text"); 102 | **********************************************************/ 103 | char SMSGSM::SendSMS(byte sim_phonebook_position, char *message_str) 104 | { 105 | char ret_val = -1; 106 | char sim_phone_number[20]; 107 | 108 | ret_val = 0; // SMS is not send yet 109 | if (sim_phonebook_position == 0) return (-3); 110 | if (1 == gsm.GetPhoneNumber(sim_phonebook_position, sim_phone_number)) { 111 | // there is a valid number at the spec. SIM position 112 | // => send SMS 113 | // ------------------------------------------------- 114 | ret_val = SendSMS(sim_phone_number, message_str); 115 | } 116 | return (ret_val); 117 | 118 | } 119 | 120 | 121 | /********************************************************** 122 | Method finds out if there is present at least one SMS with 123 | specified status 124 | 125 | Note: 126 | if there is new SMS before IsSMSPresent() is executed 127 | this SMS has a status UNREAD and then 128 | after calling IsSMSPresent() method status of SMS 129 | is automatically changed to READ 130 | 131 | required_status: SMS_UNREAD - new SMS - not read yet 132 | SMS_READ - already read SMS 133 | SMS_ALL - all stored SMS 134 | 135 | return: 136 | ERROR ret. val: 137 | --------------- 138 | -1 - comm. line to the GSM module is not free 139 | -2 - GSM module didn't answer in timeout 140 | 141 | OK ret val: 142 | ----------- 143 | 0 - there is no SMS with specified status 144 | 1..20 - position where SMS is stored 145 | (suitable for the function GetSMS()) 146 | 147 | 148 | an example of use: 149 | GSM gsm; 150 | char position; 151 | char phone_number[20]; // array for the phone number string 152 | char sms_text[100]; 153 | 154 | position = gsm.IsSMSPresent(SMS_UNREAD); 155 | if (position) { 156 | // read new SMS 157 | gsm.GetSMS(position, phone_num, sms_text, 100); 158 | // now we have phone number string in phone_num 159 | // and SMS text in sms_text 160 | } 161 | **********************************************************/ 162 | char SMSGSM::IsSMSPresent(byte required_status) 163 | { 164 | char ret_val = -1; 165 | char *p_char; 166 | byte status; 167 | 168 | if (CLS_FREE != gsm.GetCommLineStatus()) return (ret_val); 169 | gsm.SetCommLineStatus(CLS_ATCMD); 170 | ret_val = 0; // still not present 171 | 172 | switch (required_status) { 173 | case SMS_UNREAD: 174 | gsm.SimpleWriteln(F("AT+CMGL=\"REC UNREAD\"")); 175 | break; 176 | case SMS_READ: 177 | gsm.SimpleWriteln(F("AT+CMGL=\"REC READ\"")); 178 | break; 179 | case SMS_ALL: 180 | gsm.SimpleWriteln(F("AT+CMGL=\"ALL\"")); 181 | break; 182 | } 183 | 184 | // 5 sec. for initial comm tmout 185 | // and max. 1500 msec. for inter character timeout 186 | gsm.RxInit(5000, 1500); 187 | // wait response is finished 188 | do { 189 | if (gsm.IsStringReceived("OK")) { 190 | // perfect - we have some response, but what: 191 | 192 | // there is either NO SMS: 193 | // OK 194 | 195 | // or there is at least 1 SMS 196 | // +CMGL: ,,,,[,,] 197 | // OK 198 | status = RX_FINISHED; 199 | break; // so finish receiving immediately and let's go to 200 | // to check response 201 | } 202 | status = gsm.IsRxFinished(); 203 | } while (status == RX_NOT_FINISHED); 204 | 205 | 206 | 207 | 208 | switch (status) { 209 | case RX_TMOUT_ERR: 210 | // response was not received in specific time 211 | ret_val = -2; 212 | break; 213 | 214 | case RX_FINISHED: 215 | // something was received but what was received? 216 | // --------------------------------------------- 217 | if(gsm.IsStringReceived("+CMGL:")) { 218 | // there is some SMS with status => get its position 219 | // response is: 220 | // +CMGL: ,,,,[,,] 221 | // OK 222 | p_char = strchr((char *)gsm.comm_buf,':'); 223 | if (p_char != NULL) { 224 | ret_val = atoi(p_char+1); 225 | } 226 | } else { 227 | // other response like OK or ERROR 228 | ret_val = 0; 229 | } 230 | 231 | // here we have gsm.WaitResp() just for generation tmout 20msec. in case OK was detected 232 | // not due to receiving 233 | gsm.WaitResp(20, 20); 234 | break; 235 | } 236 | 237 | gsm.SetCommLineStatus(CLS_FREE); 238 | return (ret_val); 239 | } 240 | 241 | 242 | /********************************************************** 243 | Method reads SMS from specified memory(SIM) position 244 | 245 | position: SMS position <1..20> 246 | phone_number: a pointer where the phone number string of received SMS will be placed 247 | so the space for the phone number string must be reserved - see example 248 | SMS_text : a pointer where SMS text will be placed 249 | max_SMS_len: maximum length of SMS text excluding also string terminating 0x00 character 250 | 251 | return: 252 | ERROR ret. val: 253 | --------------- 254 | -1 - comm. line to the GSM module is not free 255 | -2 - GSM module didn't answer in timeout 256 | -3 - specified position must be > 0 257 | 258 | OK ret val: 259 | ----------- 260 | GETSMS_NO_SMS - no SMS was not found at the specified position 261 | GETSMS_UNREAD_SMS - new SMS was found at the specified position 262 | GETSMS_READ_SMS - already read SMS was found at the specified position 263 | GETSMS_OTHER_SMS - other type of SMS was found 264 | 265 | 266 | an example of usage: 267 | GSM gsm; 268 | char position; 269 | char phone_num[20]; // array for the phone number string 270 | char sms_text[100]; // array for the SMS text string 271 | 272 | position = gsm.IsSMSPresent(SMS_UNREAD); 273 | if (position) { 274 | // there is new SMS => read it 275 | gsm.GetSMS(position, phone_num, sms_text, 100); 276 | #ifdef DEBUG_PRINT 277 | gsm.DebugPrint("DEBUG SMS phone number: ", 0); 278 | gsm.DebugPrint(phone_num, 0); 279 | gsm.DebugPrint("\r\n SMS text: ", 0); 280 | gsm.DebugPrint(sms_text, 1); 281 | #endif 282 | } 283 | **********************************************************/ 284 | char SMSGSM::GetSMS(byte position, char *phone_number, char *SMS_text, byte max_SMS_len) 285 | { 286 | char ret_val = -1; 287 | char *p_char; 288 | char *p_char1; 289 | byte len; 290 | 291 | if (position == 0) return (-3); 292 | if (CLS_FREE != gsm.GetCommLineStatus()) return (ret_val); 293 | gsm.SetCommLineStatus(CLS_ATCMD); 294 | phone_number[0] = 0; // end of string for now 295 | ret_val = GETSMS_NO_SMS; // still no SMS 296 | 297 | //send "AT+CMGR=X" - where X = position 298 | gsm.SimpleWrite(F("AT+CMGR=")); 299 | gsm.SimpleWriteln((int)position); 300 | 301 | // 5000 msec. for initial comm tmout 302 | // 100 msec. for inter character tmout 303 | switch (gsm.WaitResp(5000, 100, "+CMGR")) { 304 | case RX_TMOUT_ERR: 305 | // response was not received in specific time 306 | ret_val = -2; 307 | break; 308 | 309 | case RX_FINISHED_STR_NOT_RECV: 310 | // OK was received => there is NO SMS stored in this position 311 | if(gsm.IsStringReceived("OK")) { 312 | // there is only response OK 313 | // => there is NO SMS 314 | ret_val = GETSMS_NO_SMS; 315 | } else if(gsm.IsStringReceived("ERROR")) { 316 | // error should not be here but for sure 317 | ret_val = GETSMS_NO_SMS; 318 | } 319 | break; 320 | 321 | case RX_FINISHED_STR_RECV: 322 | // find out what was received exactly 323 | 324 | //response for new SMS: 325 | //+CMGR: "REC UNREAD","+XXXXXXXXXXXX",,"02/03/18,09:54:28+40" 326 | //There is SMS textOK 327 | if(gsm.IsStringReceived("\"REC UNREAD\"")) { 328 | // get phone number of received SMS: parse phone number string 329 | // +XXXXXXXXXXXX 330 | // ------------------------------------------------------- 331 | ret_val = GETSMS_UNREAD_SMS; 332 | } 333 | //response for already read SMS = old SMS: 334 | //+CMGR: "REC READ","+XXXXXXXXXXXX",,"02/03/18,09:54:28+40" 335 | //There is SMS text 336 | else if(gsm.IsStringReceived("\"REC READ\"")) { 337 | // get phone number of received SMS 338 | // -------------------------------- 339 | ret_val = GETSMS_READ_SMS; 340 | } else { 341 | // other type like stored for sending.. 342 | ret_val = GETSMS_OTHER_SMS; 343 | } 344 | 345 | // extract phone number string 346 | // --------------------------- 347 | p_char = strchr((char *)(gsm.comm_buf),','); 348 | p_char1 = p_char+2; // we are on the first phone number character 349 | p_char = strchr((char *)(p_char1),'"'); 350 | if (p_char != NULL) { 351 | *p_char = 0; // end of string 352 | strcpy(phone_number, (char *)(p_char1)); 353 | } 354 | 355 | 356 | // get SMS text and copy this text to the SMS_text buffer 357 | // ------------------------------------------------------ 358 | p_char = strchr(p_char+1, 0x0a); // find 359 | if (p_char != NULL) { 360 | // next character after is the first SMS character 361 | p_char++; // now we are on the first SMS character 362 | 363 | // find as the end of SMS string 364 | p_char1 = strchr((char *)(p_char), 0x0d); 365 | if (p_char1 != NULL) { 366 | // finish the SMS text string 367 | // because string must be finished for right behaviour 368 | // of next strcpy() function 369 | *p_char1 = 0; 370 | } 371 | // in case there is not finish sequence because the SMS is 372 | // too long (more then 130 characters) sms text is finished by the 0x00 373 | // directly in the gsm.WaitResp() routine 374 | 375 | // find out length of the SMS (excluding 0x00 termination character) 376 | len = strlen(p_char); 377 | 378 | if (len < max_SMS_len) { 379 | // buffer SMS_text has enough place for copying all SMS text 380 | // so copy whole SMS text 381 | // from the beginning of the text(=p_char position) 382 | // to the end of the string(= p_char1 position) 383 | strcpy(SMS_text, (char *)(p_char)); 384 | } else { 385 | // buffer SMS_text doesn't have enough place for copying all SMS text 386 | // so cut SMS text to the (max_SMS_len-1) 387 | // (max_SMS_len-1) because we need 1 position for the 0x00 as finish 388 | // string character 389 | memcpy(SMS_text, (char *)(p_char), (max_SMS_len-1)); 390 | SMS_text[max_SMS_len] = 0; // finish string 391 | } 392 | } 393 | break; 394 | } 395 | 396 | gsm.SetCommLineStatus(CLS_FREE); 397 | return (ret_val); 398 | } 399 | 400 | /********************************************************** 401 | Method reads SMS from specified memory(SIM) position and 402 | makes authorization - it means SMS phone number is compared 403 | with specified SIM phonebook position(s) and in case numbers 404 | match GETSMS_AUTH_SMS is returned, otherwise GETSMS_NOT_AUTH_SMS 405 | is returned 406 | 407 | position: SMS position to be read <1..20> 408 | phone_number: a pointer where the tel. number string of received SMS will be placed 409 | so the space for the phone number string must be reserved - see example 410 | SMS_text : a pointer where SMS text will be placed 411 | max_SMS_len: maximum length of SMS text excluding terminating 0x00 character 412 | 413 | first_authorized_pos: initial SIM phonebook position where the authorization process 414 | starts 415 | last_authorized_pos: last SIM phonebook position where the authorization process 416 | finishes 417 | 418 | Note(important): 419 | ================ 420 | In case first_authorized_pos=0 and also last_authorized_pos=0 421 | the received SMS phone number is NOT authorized at all, so every 422 | SMS is considered as authorized (GETSMS_AUTH_SMS is returned) 423 | 424 | return: 425 | ERROR ret. val: 426 | --------------- 427 | -1 - comm. line to the GSM module is not free 428 | -2 - GSM module didn't answer in timeout 429 | -3 - position must be > 0 430 | 431 | OK ret val: 432 | ----------- 433 | GETSMS_NO_SMS - no SMS was found at the specified position 434 | GETSMS_NOT_AUTH_SMS - NOT authorized SMS found at the specified position 435 | GETSMS_AUTH_SMS - authorized SMS found at the specified position 436 | 437 | 438 | an example of usage: 439 | GSM gsm; 440 | char phone_num[20]; // array for the phone number string 441 | char sms_text[100]; // array for the SMS text string 442 | 443 | // authorize SMS with SIM phonebook positions 1..3 444 | if (GETSMS_AUTH_SMS == gsm.GetAuthorizedSMS(1, phone_num, sms_text, 100, 1, 3)) { 445 | // new authorized SMS was detected at the SMS position 1 446 | #ifdef DEBUG_PRINT 447 | gsm.DebugPrint("DEBUG SMS phone number: ", 0); 448 | gsm.DebugPrint(phone_num, 0); 449 | gsm.DebugPrint("\r\n SMS text: ", 0); 450 | gsm.DebugPrint(sms_text, 1); 451 | #endif 452 | } 453 | 454 | // don't authorize SMS with SIM phonebook at all 455 | if (GETSMS_AUTH_SMS == gsm.GetAuthorizedSMS(1, phone_num, sms_text, 100, 0, 0)) { 456 | // new SMS was detected at the SMS position 1 457 | // because authorization was not required 458 | // SMS is considered authorized 459 | #ifdef DEBUG_PRINT 460 | gsm.DebugPrint("DEBUG SMS phone number: ", 0); 461 | gsm.DebugPrint(phone_num, 0); 462 | gsm.DebugPrint("\r\n SMS text: ", 0); 463 | gsm.DebugPrint(sms_text, 1); 464 | #endif 465 | } 466 | **********************************************************/ 467 | char SMSGSM::GetAuthorizedSMS(byte position, char *phone_number, char *SMS_text, byte max_SMS_len, 468 | byte first_authorized_pos, byte last_authorized_pos) 469 | { 470 | char ret_val = -1; 471 | byte i; 472 | 473 | ret_val = GetSMS(position, phone_number, SMS_text, max_SMS_len); 474 | if (ret_val < 0) { 475 | // here is ERROR return code => finish 476 | // ----------------------------------- 477 | } else if (ret_val == GETSMS_NO_SMS) { 478 | // no SMS detected => finish 479 | // ------------------------- 480 | } else if (ret_val == GETSMS_READ_SMS) { 481 | // now SMS can has only READ attribute because we have already read 482 | // this SMS at least once by the previous function GetSMS() 483 | // 484 | // new READ SMS was detected on the specified SMS position => 485 | // make authorization now 486 | // --------------------------------------------------------- 487 | if ((first_authorized_pos == 0) && (last_authorized_pos == 0)) { 488 | // authorization is not required => it means authorization is OK 489 | // ------------------------------------------------------------- 490 | ret_val = GETSMS_AUTH_SMS; 491 | } else { 492 | ret_val = GETSMS_NOT_AUTH_SMS; // authorization not valid yet 493 | for (i = first_authorized_pos; i <= last_authorized_pos; i++) { 494 | if (gsm.ComparePhoneNumber(i, phone_number)) { 495 | // phone numbers are identical 496 | // authorization is OK 497 | // --------------------------- 498 | ret_val = GETSMS_AUTH_SMS; 499 | break; // and finish authorization 500 | } 501 | } 502 | } 503 | } 504 | return (ret_val); 505 | } 506 | 507 | 508 | /********************************************************** 509 | Method deletes SMS from the specified SMS position 510 | 511 | position: SMS position <1..20> 512 | 513 | return: 514 | ERROR ret. val: 515 | --------------- 516 | -1 - comm. line to the GSM module is not free 517 | -2 - GSM module didn't answer in timeout 518 | -3 - position must be > 0 519 | 520 | OK ret val: 521 | ----------- 522 | 0 - SMS was not deleted 523 | 1 - SMS was deleted 524 | **********************************************************/ 525 | char SMSGSM::DeleteSMS(byte position) 526 | { 527 | char ret_val = -1; 528 | 529 | if (position == 0) return (-3); 530 | if (CLS_FREE != gsm.GetCommLineStatus()) return (ret_val); 531 | gsm.SetCommLineStatus(CLS_ATCMD); 532 | ret_val = 0; // not deleted yet 533 | 534 | //send "AT+CMGD=XY" - where XY = position 535 | gsm.SimpleWrite(F("AT+CMGD=")); 536 | gsm.SimpleWriteln((int)position); 537 | 538 | 539 | // 5000 msec. for initial comm tmout 540 | // 20 msec. for inter character timeout 541 | switch (gsm.WaitResp(5000, 50, "OK")) { 542 | case RX_TMOUT_ERR: 543 | // response was not received in specific time 544 | ret_val = -2; 545 | break; 546 | 547 | case RX_FINISHED_STR_RECV: 548 | // OK was received => SMS deleted 549 | ret_val = 1; 550 | break; 551 | 552 | case RX_FINISHED_STR_NOT_RECV: 553 | // other response: e.g. ERROR => SMS was not deleted 554 | ret_val = 0; 555 | break; 556 | } 557 | 558 | gsm.SetCommLineStatus(CLS_FREE); 559 | return (ret_val); 560 | } 561 | 562 | -------------------------------------------------------------------------------- /sms.h: -------------------------------------------------------------------------------- 1 | #ifndef _SMS_H_ 2 | #define _SMS_H_ 3 | 4 | #include "SIM900.h" 5 | 6 | class SMSGSM { 7 | public: 8 | // SMS's methods 9 | char SendSMS(char *number_str, char *message_str); 10 | char SendSMS(byte sim_phonebook_position, char *message_str); 11 | char IsSMSPresent(byte required_status); 12 | char GetSMS(byte position, char *phone_number, char *SMS_text, byte max_SMS_len); 13 | 14 | char GetAuthorizedSMS(byte position, char *phone_number, char *SMS_text, byte max_SMS_len, 15 | byte first_authorized_pos, byte last_authorized_pos); 16 | char DeleteSMS(byte position); 17 | 18 | }; 19 | 20 | #endif 21 | 22 | --------------------------------------------------------------------------------