/* * GPRS_Shield_Arduino.cpp * A library for SeeedStudio seeeduino GPRS shield * * Copyright (c) 2015 seeed technology inc. * Website : www.seeed.cc * Author : lawliet zou * Create Time: April 2015 * Change Log : * * The MIT License (MIT) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "GPRS_Shield_Arduino.h" GPRS* GPRS::inst; GPRS::GPRS(Stream& serial, uint8_t pkPin) { _pkPin = pkPin; inst = this; stream = &serial; sim900_init(stream); } bool GPRS::init(void) { if (!sim900_check_with_cmd("AT\r\n","OK\r\n",CMD)) return false; if (!sim900_check_with_cmd("AT+CFUN=1\r\n","OK\r\n",CMD)) return false; if (!checkSIMStatus()) return false; if (!sim900_check_with_cmd("AT+CNMI?\r\n", "+CNMI: 2,2,0,0,0\r\nOK\r\n", CMD)) { if (!sim900_check_with_cmd("AT+CNMI=2,2,0,0,0\r\n","OK\r\n", CMD)) { return false; } } if (!sim900_check_with_cmd("AT+CMGF?\r\n", "+CMGF: 1\r\nOK\r\n", CMD)) { if (!sim900_check_with_cmd("AT+CMGF=1\r\n","OK\r\n", CMD)) { return false; } } if (!sim900_check_with_cmd("AT+CLIP=1\r\n","OK\r\n", CMD)) { return false; } return true; } bool GPRS::checkPowerUp(void) { return sim900_check_with_cmd("AT\r\n","OK\r\n", CMD); } // power Up GPRS Shield void GPRS::powerOn() { //delay(1000); pinMode(_pkPin, OUTPUT); digitalWrite(_pkPin, HIGH); delay(500); digitalWrite(_pkPin, LOW); delay(3000); } // power Off GPRS Shield void GPRS::powerOff() { pinMode(_pkPin, OUTPUT); digitalWrite(_pkPin, HIGH); delay(2000); digitalWrite(_pkPin, LOW); delay(3000); } void GPRS::reset() { powerOff(); powerOn(); } bool GPRS::checkSIMStatus(void) { char gprsBuffer[32]; byte count = 0; sim900_clean_buffer(gprsBuffer,32); while(count < 3) { sim900_send_cmd("AT+CPIN?\r\n"); sim900_read_buffer(gprsBuffer,32,DEFAULT_TIMEOUT); if((NULL != strstr(gprsBuffer,"+CPIN: READY"))) { break; } count++; delay(300); } if(count == 3) { return false; } return true; } bool GPRS::sendSMS(char *number, char *data) { // Set message mode to ASCII if(!sim900_check_with_cmd("AT+CMGF=1\r\n", "OK\r\n", CMD)) { return false; } delay(500); sim900_send_cmd("AT+CMGS=\""); sim900_send_cmd(number); if(!sim900_check_with_cmd("\"\r\n",">",CMD)) { return false; } delay(1000); sim900_send_cmd(data); delay(500); sim900_send_End_Mark(); return true; } char GPRS::isSMSunread() { char gprsBuffer[48]; //48 is enough to see +CMGL: char *s; //List of all UNREAD SMS and DON'T change the SMS UNREAD STATUS sim900_send_cmd(F("AT+CMGL=\"REC UNREAD\",1\r\n")); /*If you want to change SMS status to READ you will need to send: AT+CMGL=\"REC UNREAD\"\r\n This command will list all UNREAD SMS and change all of them to READ If there is not SMS, response is (30 chars) AT+CMGL="REC UNREAD",1 --> 22 + 2 --> 2 OK --> 2 + 2 If there is SMS, response is like (>64 chars) AT+CMGL="REC UNREAD",1 +CMGL: 9,"REC UNREAD","XXXXXXXXX","","14/10/16,21:40:08+08" Here SMS text. OK or AT+CMGL="REC UNREAD",1 +CMGL: 9,"REC UNREAD","XXXXXXXXX","","14/10/16,21:40:08+08" Here SMS text. +CMGL: 10,"REC UNREAD","YYYYYYYYY","","14/10/16,21:40:08+08" Here second SMS OK */ sim900_clean_buffer(gprsBuffer,31); sim900_read_buffer(gprsBuffer,30,DEFAULT_TIMEOUT); //Serial.print("Buffer isSMSunread: ");Serial.println(gprsBuffer); if(NULL != ( s = strstr(gprsBuffer,"OK"))) { //In 30 bytes "doesn't" fit whole +CMGL: response, if recieve only "OK" // means you don't have any UNREAD SMS delay(50); return 0; } else { //More buffer to read //We are going to flush serial data until OK is recieved sim900_wait_for_resp("OK\r\n", CMD); //sim900_flush_serial(); //We have to call command again sim900_send_cmd("AT+CMGL=\"REC UNREAD\",1\r\n"); sim900_clean_buffer(gprsBuffer,48); sim900_read_buffer(gprsBuffer,47,DEFAULT_TIMEOUT); //Serial.print("Buffer isSMSunread 2: ");Serial.println(gprsBuffer); if(NULL != ( s = strstr(gprsBuffer,"+CMGL:"))) { //There is at least one UNREAD SMS, get index/position s = strstr(gprsBuffer,":"); if (s != NULL) { //We are going to flush serial data until OK is recieved sim900_wait_for_resp("OK\r\n", CMD); return atoi(s+1); } } else { return -1; } } return -1; } bool GPRS::readSMS(int messageIndex, char *message, byte length) { byte i = 0; char gprsBuffer[100]; char num[4]; char *p,*s; sim900_check_with_cmd("AT+CMGF=1\r\n","OK\r\n",CMD); delay(1000); sim900_send_cmd("AT+CMGR="); itoa(messageIndex, num, 10); sim900_send_cmd(num); sim900_send_cmd("\r\n"); sim900_clean_buffer(gprsBuffer,sizeof(gprsBuffer)); sim900_read_buffer(gprsBuffer,sizeof(gprsBuffer),DEFAULT_TIMEOUT); if(NULL != ( s = strstr(gprsBuffer,"+CMGR:"))){ if(NULL != ( s = strstr(s,"\r\n"))){ p = s + 2; while((*p != '\r')&&(i < length-1)) { message[i++] = *(p++); } message[i] = '\0'; return true; } } return false; } bool GPRS::getSMS(char *message, char *phone, char *datetime) { /* Response is like: +CMT: "+79772941911","","15/12/15,01:51:24+12" SMS text here */ if(!sim900_check_with_cmd("","+CMT: ",CMD)) return false; byte i = 0; char gprsBuffer[80 + 160]; char *p1, *p2; sim900_clean_buffer(gprsBuffer,sizeof(gprsBuffer)); sim900_read_buffer(gprsBuffer,sizeof(gprsBuffer)); int len = strlen(gprsBuffer); // Serial.println("----- buffer -----"); // Serial.println(gprsBuffer); // Serial.println("^^^^^ buffer ^^^^^"); // Extract phone number string p1 = strstr(gprsBuffer, "\"+"); p2 = p1 + 1; //First phone number character p1 = strstr((char *)(p2), "\""); if (p1 != NULL) { i = 0; while (p2 < p1) { phone[i++] = *(p2++); } phone[i] = '\0'; } // Extract date time string p1 = strstr((char *)(p2), ","); p2 = p1 + 1; p1 = strstr((char *)(p2), ","); p2 = p1 + 2; //First date time character p1 = strstr((char *)(p2), "\""); if (p1 != NULL) { i = 0; while (p2 < p1) { datetime[i++] = *(p2++); } datetime[i] = '\0'; } // Extract message p1 = strstr(gprsBuffer, "\r\n"); if (p1 != NULL) { i = 0; p1 = p1 + 2; //First message character while((*p1 != '\r') && (i < len - 1)) { message[i++] = *(p1++); } message[i] = '\0'; } return true; } bool GPRS::deleteSMS(int index) { char num[4]; sim900_send_cmd("AT+CMGD="); itoa(index, num, 10); sim900_send_cmd(num); return sim900_check_with_cmd("\r\n","OK\r\n",CMD); } bool GPRS::callUp(char *number) { if(!sim900_check_with_cmd("AT+COLP=1\r\n","OK\r\n",CMD)) { return false; } delay(1000); sim900_send_cmd("ATD"); sim900_send_cmd(number); sim900_send_cmd(";\r\n"); return true; } void GPRS::answer(void) { //TO CHECK: ATA doesnt return "OK" ???? sim900_send_cmd("ATA\r\n"); } bool GPRS::ifcallNow(void) { return sim900_check_with_cmd("","RING\r\n",CMD); } bool GPRS::ifcallEnd(void) { return sim900_check_with_cmd("","NO CARRIER\r\n",CMD); } void GPRS::callEnd(void) { sim900_send_cmd("ATH0\r\n"); } bool GPRS::hangup(void) { return sim900_check_with_cmd("ATH\r\n","OK\r\n",CMD); } bool GPRS::disableCLIPring(void) { return sim900_check_with_cmd("AT+CLIP=0\r\n","OK\r\n",CMD); } bool GPRS::isCallActive(char *number) { char gprsBuffer[46]; //46 is enough to see +CPAS: and CLCC: char *p, *s; int i = 0; sim900_send_cmd("AT+CPAS\r\n"); /*Result code: 0: ready 2: unknown 3: ringing 4: call in progress AT+CPAS --> 7 + 2 = 9 chars --> 2 char +CPAS: 3 --> 8 + 2 = 10 chars --> 2 char OK --> 2 + 2 = 4 chars AT+CPAS +CPAS: 0 OK */ sim900_clean_buffer(gprsBuffer,29); sim900_read_buffer(gprsBuffer,27); //HACERR cuando haga lo de esperar a OK no me haría falta esto //We are going to flush serial data until OK is recieved sim900_wait_for_resp("OK\r\n", CMD); //Serial.print("Buffer isCallActive 1: ");Serial.println(gprsBuffer); if(NULL != ( s = strstr(gprsBuffer,"+CPAS:"))) { s = s + 7; if (*s != '0') { //There is something "running" (but number 2 that is unknow) if (*s != '2') { //3 or 4, let's go to check for the number sim900_send_cmd("AT+CLCC\r\n"); /* AT+CLCC --> 9 +CLCC: 1,1,4,0,0,"656783741",161,"" OK Without ringing: AT+CLCC OK */ sim900_clean_buffer(gprsBuffer,46); sim900_read_buffer(gprsBuffer,45); //Serial.print("Buffer isCallActive 2: ");Serial.println(gprsBuffer); if(NULL != ( s = strstr(gprsBuffer,"+CLCC:"))) { //There is at least one CALL ACTIVE, get number s = strstr((char *)(s),"\""); s = s + 1; //We are in the first phone number character p = strstr((char *)(s),"\""); //p is last character """ if (NULL != s) { i = 0; while (s < p) { number[i++] = *(s++); } number[i] = '\0'; } //I need to read more buffer //We are going to flush serial data until OK is recieved return sim900_wait_for_resp("OK\r\n", CMD); } } } } return false; } bool GPRS::getDateTime(char *buffer) { //AT+CCLK? --> 8 + CRLF = 10 //+CCLK: "14/11/13,21:14:41+04" --> 29+ CRLF = 31 // --> CRLF = 2 //OK byte i = 0; char gprsBuffer[46]; char *p,*s; sim900_send_cmd("AT+CCLK?\r\n"); sim900_clean_buffer(gprsBuffer,43); sim900_read_buffer(gprsBuffer,43,DEFAULT_TIMEOUT); if(NULL != ( s = strstr(gprsBuffer,"+CCLK:"))) { s = strstr((char *)(s),"\""); s = s + 1; //We are in the first phone number character p = strstr((char *)(s),"\""); //p is last character """ if (NULL != s) { i = 0; while (s < p) { buffer[i++] = *(s++); } buffer[i] = '\0'; } //We are going to flush serial data until OK is recieved return sim900_wait_for_resp("OK\r\n", CMD); } return false; } byte GPRS::getSignalStrength() { //AT+CSQ: 00,00 --> 13 + CRLF = 15 // --> CRLF = 2 //OK --> 2 + CRLF = 4 byte result = 99; char gprsBuffer[21]; sim900_clean_buffer(gprsBuffer,21); char *s; sim900_send_cmd("AT+CSQ\r\n"); sim900_read_buffer(gprsBuffer,21,DEFAULT_TIMEOUT); if(NULL != ( s = strstr(gprsBuffer,"+CSQ: "))) { result = atoi(s+6); sim900_wait_for_resp("OK\r\n", CMD); } return result; } //Here is where we ask for APN configuration, with F() so we can save MEMORY //bool GPRS::join(const __FlashStringHelper *apn, const __FlashStringHelper *userName, const __FlashStringHelper *passWord) bool GPRS::join(char* apn, char* userName, char* passWord, int timeout) { byte i; char *p, *s; char ipAddr[32]; /* if(!sim900_check_with_cmd("AT+CIPSHUT\r\n","SHUT OK\r\n", CMD)) { Serial.write("Error = 1\r\n"); return false; } delay(1000); */ sim900_send_cmd("AT+CIPSHUT\r\n"); delay(500); //Select multiple connection //sim900_check_with_cmd("AT+CIPMUX=1\r\n","OK",DEFAULT_TIMEOUT,CMD); //set APN. OLD VERSION //snprintf(cmd,sizeof(cmd),"AT+CSTT=\"%s\",\"%s\",\"%s\"\r\n",_apn,_userName,_passWord); //sim900_check_with_cmd(cmd, "OK\r\n", DEFAULT_TIMEOUT,CMD); sim900_send_cmd("AT+CSTT=\""); sim900_send_cmd(apn); sim900_send_cmd("\",\""); sim900_send_cmd(userName); sim900_send_cmd("\",\""); sim900_send_cmd(passWord); sim900_send_cmd("\"\r\n"); delay(500); //Brings up wireless connection sim900_send_cmd("AT+CIICR\r\n"); delay(4000); sim900_wait_for_resp("OK\r\n", CMD); delay(500); // sim900_check_with_cmd("AT+CIICR\r\n","OK\r\n", CMD); //Get local IP address sim900_send_cmd("AT+CIFSR\r\n"); delay(500); sim900_clean_buffer(ipAddr,32); sim900_read_buffer(ipAddr,32,DEFAULT_TIMEOUT); //Response: //AT+CIFSR\r\n --> 8 + 2 //\r\n --> 0 + 2 //10.160.57.120\r\n --> 15 + 2 (max) : TOTAL: 29 //Response error: //AT+CIFSR\r\n //\r\n //ERROR\r\n if (NULL != strstr(ipAddr,"ERROR")) { Serial.write("Error = 2\r\n"); return false; } s = ipAddr + 12; p = strstr((char *)(s),"\r\n"); //p is last character \r\n if (NULL != s) { i = 0; while (s < p) { ip_string[i++] = *(s++); } ip_string[i] = '\0'; } _ip = str_to_ip(ip_string); if(_ip != 0) { return true; } Serial.write("Error = 3\r\n"); return false; } void GPRS::disconnect() { sim900_send_cmd("AT+CIPSHUT\r\n"); } bool GPRS::connect(Protocol ptl,const char * host, int port, int timeout) { //char cmd[64]; char num[4]; char resp[96]; //sim900_clean_buffer(cmd,64); if(ptl == TCP) { sim900_send_cmd("AT+CIPSTART=\"TCP\",\""); sim900_send_cmd(host); sim900_send_cmd("\","); itoa(port, num, 10); sim900_send_cmd(num); sim900_send_cmd("\r\n"); // sprintf(cmd, "AT+CIPSTART=\"TCP\",\"%s\",%d\r\n",host, port); } else if(ptl == UDP) { sim900_send_cmd("AT+CIPSTART=\"UDP\",\""); sim900_send_cmd(host); sim900_send_cmd("\","); itoa(port, num, 10); sim900_send_cmd(num); sim900_send_cmd("\r\n"); // sprintf(cmd, "AT+CIPSTART=\"UDP\",\"%s\",%d\r\n",host, port); } else { return false; } delay(2000); //sim900_send_cmd(cmd); sim900_read_buffer(resp,96,timeout); //Serial.print("Connect resp: "); Serial.println(resp); if(NULL != strstr(resp,"CONNECT")) { //ALREADY CONNECT or CONNECT OK return true; } return false; } //Overload with F() macro to SAVE memory bool GPRS::connect(Protocol ptl,const __FlashStringHelper *host, const __FlashStringHelper *port, int timeout) { //char cmd[64]; char resp[96]; //sim900_clean_buffer(cmd,64); if(ptl == TCP) { sim900_send_cmd(F("AT+CIPSTART=\"TCP\",\"")); //%s\",%d\r\n",host, port); } else if(ptl == UDP) { sim900_send_cmd(F("AT+CIPSTART=\"UDP\",\"")); //%s\",%d\r\n",host, port); } else { return false; } sim900_send_cmd(host); sim900_send_cmd(F("\",")); sim900_send_cmd(port); sim900_send_cmd(F("\r\n")); //Serial.print("Connect: "); Serial.println(cmd); sim900_read_buffer(resp, 96, timeout); //Serial.print("Connect resp: "); Serial.println(resp); if(NULL != strstr(resp,"CONNECT")) { //ALREADY CONNECT or CONNECT OK return true; } return false; } bool GPRS::is_connected(void) { char resp[96]; sim900_send_cmd("AT+CIPSTATUS\r\n"); sim900_read_buffer(resp,sizeof(resp),DEFAULT_TIMEOUT); if(NULL != strstr(resp,"CONNECTED")) { //+CIPSTATUS: 1,0,"TCP","216.52.233.120","80","CONNECTED" return true; } else { //+CIPSTATUS: 1,0,"TCP","216.52.233.120","80","CLOSED" //+CIPSTATUS: 0,,"","","","INITIAL" return false; } } bool GPRS::close() { // if not connected, return if (!is_connected()) { return true; } return sim900_check_with_cmd("AT+CIPCLOSE\r\n", "CLOSE OK\r\n", CMD); } int GPRS::readable(void) { return sim900_check_readable(); } int GPRS::wait_readable(int wait_time) { return sim900_wait_readable(wait_time); } int GPRS::wait_writeable(int req_size) { return req_size+1; } int GPRS::send(const char * str, int len) { //char cmd[32]; char num[4]; if(len > 0){ //snprintf(cmd,sizeof(cmd),"AT+CIPSEND=%d\r\n",len); //sprintf(cmd,"AT+CIPSEND=%d\r\n",len); sim900_send_cmd("AT+CIPSEND="); itoa(len, num, 10); sim900_send_cmd(num); if(!sim900_check_with_cmd("\r\n",">",CMD)) { //if(!sim900_check_with_cmd(cmd,">",CMD)) { return 0; } /*if(0 != sim900_check_with_cmd(str,"SEND OK\r\n", DEFAULT_TIMEOUT * 10 ,DATA)) { return 0; }*/ delay(500); sim900_send_cmd(str); delay(500); sim900_send_End_Mark(); if(!sim900_wait_for_resp("SEND OK\r\n", DATA, DEFAULT_TIMEOUT * 10, DEFAULT_INTERCHAR_TIMEOUT * 10)) { return 0; } } return len; } int GPRS::send(const char * str) { //char cmd[32]; int len=strlen(str); char num[4]; if(len > 0){ //snprintf(cmd,sizeof(cmd),"AT+CIPSEND=%d\r\n",len); //sprintf(cmd,"AT+CIPSEND=%d\r\n",len); sim900_send_cmd("AT+CIPSEND="); itoa(len, num, 10); sim900_send_cmd(num); if(!sim900_check_with_cmd("\r\n",">",CMD)) { //if(!sim900_check_with_cmd(cmd,">",CMD)) { return 0; } /*if(0 != sim900_check_with_cmd(str,"SEND OK\r\n", DEFAULT_TIMEOUT * 10 ,DATA)) { return 0; }*/ delay(500); sim900_send_cmd(str); delay(500); sim900_send_End_Mark(); if(!sim900_wait_for_resp("SEND OK\r\n", DATA, DEFAULT_TIMEOUT * 10, DEFAULT_INTERCHAR_TIMEOUT * 10)) { return 0; } } return len; } int GPRS::recv(char* buf, int len) { sim900_clean_buffer(buf,len); sim900_read_buffer(buf,len); //Ya he llamado a la funcion con la longitud del buffer - 1 y luego le estoy añadiendo el 0 return strlen(buf); } uint32_t GPRS::str_to_ip(const char* str) { uint32_t ip = 0; char* p = (char*)str; for(int i = 0; i < 4; i++) { ip |= atoi(p); p = strchr(p, '.'); if (p == NULL) { break; } ip <<= 8; p++; } return ip; } char* GPRS::getIPAddress() { //I have already a buffer with ip_string: snprintf(ip_string, sizeof(ip_string), "%d.%d.%d.%d", (_ip>>24)&0xff,(_ip>>16)&0xff,(_ip>>8)&0xff,_ip&0xff); return ip_string; } unsigned long GPRS::getIPnumber() { return _ip; } bool GPRS::controlGPIO(uint8_t index, uint8_t level) { char num[1]; sim900_send_cmd("AT+SGPIO=0,"); itoa(index, num, 10); sim900_send_cmd(num); sim900_send_cmd(",1,"); itoa(level, num, 10); sim900_send_cmd(num); sim900_send_cmd("\r\n"); return sim900_wait_for_resp("OK\r\n", CMD); } /* NOT USED bool GPRS::gethostbyname(const char* host, uint32_t* ip) { uint32_t addr = str_to_ip(host); char buf[17]; //snprintf(buf, sizeof(buf), "%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8)&0xff, addr&0xff); if (strcmp(buf, host) == 0) { *ip = addr; return true; } return false; } */