A library for the SIM900 module to enable calling, answering, sending and receiving SMS messages

Dependents:   Seeed_GPRS_Shield_GSM BluetoothNONIN HealthCare_Graduation

Fork of GSM by Components

gprs.cpp

Committer:
lawliet
Date:
2013-11-18
Revision:
2:16985da3a446
Parent:
1:642a8dbe076c
Child:
3:48ee24a4b0f3

File content as of revision 2:16985da3a446:

/*
  gprs.cpp
  2013 Copyright (c) Seeed Technology Inc.  All right reserved.

  Author:lawliet.zou@gmail.com
  2013-11-14

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <stdio.h>
#include "mbed.h"
#include "gprs.h"

#define TRUE 					1
#define FALSE 					0

#define UART_DEBUG

#ifdef UART_DEBUG
#define ERROR(x)			printf("ERROR:%s\r\n",x)
#define DEBUG(x)			printf("DEBUG:%s\r\n",x);
#else
#define ERROR(x)
#define DEBUG(x)
#endif

#define DEFALUT_TIMEOUT   	5

int GPRS::init(void)
{
    wait(0.5);
    if(0 != checkSIMStatus()) { //check SIM card status
        ERROR("checkSIMStatus");
        return -1;
    }
    if(checkSignalStrength()<1) { //check Signal Strength
        ERROR("Signal too weak");
        return -1;
    }

    if(0 != networkInit()) {
        ERROR("Network Init error");
        return -1;
    }
    return 0;
}

int GPRS::readBuffer(char *buffer,int count)
{
    int i = 0;
    timeCnt.start();  // start timer
    while(1) {
        while (gprsSerial.readable()) {
            char c = gprsSerial.getc();
            if (c == '\r' || c == '\n') c = '$';
            buffer[i++] = c;
            if(i > count)break;
        }
        if(i > count)break;
        if(timeCnt.read() > DEFALUT_TIMEOUT) {
            timeCnt.stop();
            timeCnt.reset();
            break;
        }
    }
    wait(0.5);
    while(gprsSerial.readable()) {	// display the other thing..
        char c = gprsSerial.getc();
    }
    return 0;
}

void cleanBuffer(char *buffer, int count)
{
    for(int i=0; i < count; i++) {
        buffer[i] = '\0';
    }
}

void GPRS::sendCmd(char *cmd)
{
    gprsSerial.puts(cmd);
}

int GPRS::waitForResp(char *resp, int timeout)
{
    int len = strlen(resp);
    int sum=0;
    timeCnt.start();

    while(1) {
        if(gprsSerial.readable()) {
            char c = gprsSerial.getc();
            sum = (c==resp[sum]) ? sum+1 : 0;
            if(sum == len)break;
        }
        if(timeCnt.read() > timeout) {	// time out
            timeCnt.stop();
            timeCnt.reset();
            ERROR("time out");
            return -1;
        }
    }
    timeCnt.stop();                	// stop timer
    timeCnt.reset();             		// clear timer
    while(gprsSerial.readable()) {  	// display the other thing..
        char c = gprsSerial.getc();
    }

    return 0;
}



int GPRS::sendCmdAndWaitForResp(char *cmd, char *resp, int timeout)
{
    sendCmd(cmd);
    return waitForResp(resp,timeout);
}

int GPRS::checkSIMStatus(void)
{
    char gprsBuffer[30];
    int count = 0;
    cleanBuffer(gprsBuffer,30);
    while(count < 3) {
        sendCmd("AT+CPIN?\r\n");
        readBuffer(gprsBuffer,30);
        //DEBUG(gprsBuffer);
        if((NULL != strstr(gprsBuffer,"+CPIN: READY"))) {
            break;
        }
        count++;
        wait(1);
    }

    if(count == 3) {
        ERROR("Bad SIM Status");
        return -1;
    }
    return 0;
}

int GPRS::checkSignalStrength(void)
{
    char gprsBuffer[100];
    int index,count = 0;
    cleanBuffer(gprsBuffer,100);
    while(count < 3) {
        sendCmd("AT+CSQ\r\n");
        readBuffer(gprsBuffer,25);
        //DEBUG(gprsBuffer);
        if(sscanf(gprsBuffer, "AT+CSQ$$$$+CSQ: %d", &index)>0) {
            break;
        }
        ERROR("checking signal strenght error, try again...");
        count++;
        wait(1);
    }
    if(count == 3) {
        ERROR("AT+CSQ");
        return -1;
    }
    return index;
}

int GPRS::networkInit(void)
{
    //for GPRS
    if(0 != sendCmdAndWaitForResp("AT+CGREG?\r\n","+CGREG: 0,1",DEFALUT_TIMEOUT)) { //Open GPRS
        ERROR("CGREG");
        return -1;
    }
    wait(1);
    if(0 != sendCmdAndWaitForResp("AT+CGATT?\r\n","+CGATT: 1",DEFALUT_TIMEOUT)) { //Set GPRS
        ERROR("CGATT");
        return -1;
    }
    return 0;
}

int GPRS::sendSMS(char *number, char *data)
{
    char cmd[64];
    if(0 != sendCmdAndWaitForResp("AT+CMGF=1\r\n", "OK", DEFALUT_TIMEOUT)) { // Set message mode to ASCII
        ERROR("CMGF");
        return -1;
    }
    wait(0.5);
    // Set the phone number
    snprintf(cmd, sizeof(cmd),"AT+CMGS=\"%s\"\r\n", number);
    if(0 != sendCmdAndWaitForResp(cmd,">",DEFALUT_TIMEOUT)) {
        ERROR("CMGS");
        return -1;
    }
    wait(1);
    gprsSerial.puts(data);// Send Message
    wait(0.5);
    gprsSerial.putc(0x1A);//end mark
    return 0;
}

int GPRS::readSMS(char *buffer, char *message, bool check)
{
    int index,i = 0;
    char gprsBuffer[100];
    char *p,*s;

    if(sscanf(buffer, "$$+CMTI: \"SM\",%d", &index)>0) {
        DEBUG("Opening message...");
        gprsSerial.printf("AT+CMGR=%d\r\n", index);
    } else {
        ERROR("get Message");
    }
    cleanBuffer(gprsBuffer,100);
    readBuffer(gprsBuffer,100);
    //pc.printf(gprsBuffer); //AT+CMGR=17$$$$+CMGR: "REC UNREAD","+8613925257382","","13/11/11,10:36:13+32"$$Hello$$$$OK$$
    DEBUG(gprsBuffer);
    if(NULL == ( s = strstr(gprsBuffer,"+CMGR: \"REC UNREAD\""))) {
        ERROR("get CMGR error");
        return -1;
    }

    //check phone number
    if(check) {
        char number[20];
        snprintf(number,sizeof(number),"\"+86%s\"",phoneNumber); //for China
        p = s + 20;
        if(0 != (strncmp(number,p,14))) {
            ERROR("Phone Number error");
            return -1;
        }
    }
    p = s + 64;
    while(*p != '$') {
        message[i++] = *(p++);
    }
    message[i] = '\0';
    DEBUG(message);
    return 0;
}

int GPRS::deleteSMS(int index)
{
    char cmd[64];
    snprintf(cmd,sizeof(cmd),"AT+CMGD=%d\r\n",index);
    sendCmd(cmd);
    return 0;
}

int GPRS::callUp(char *number)
{
    if(0 != sendCmdAndWaitForResp("AT+COLP=1\r\n","OK",5)) {
        ERROR("COLP");
        return -1;
    }
    wait(1);
    gprsSerial.printf("\r\nATD%s;\r\n",NULL==number?phoneNumber:number);
    return 0;
}

int GPRS::answer(void)
{
    gprsSerial.printf("ATA\r\n");
    return 0;
}

int GPRS::loop(bool check)
{
    char gprsBuffer[100];
    int i = 0;
    cleanBuffer(gprsBuffer,100);
    while(1) {
        if(gprsSerial.readable()) {
            break;
        }
        wait(1);
    }

    timeCnt.start();  // start timer
    while(1) {
        while (gprsSerial.readable()) {
            char c = gprsSerial.getc();
            if (c == '\r' || c == '\n') c = '$';
            gprsBuffer[i] = c;
            i++;
            if(i > 100) {
                i = 0;
                break;
            }
        }
        if(timeCnt.read() > 5) {          // time out
            timeCnt.stop();
            timeCnt.reset();
            break;
        }
    }

    if(NULL != strstr(gprsBuffer,"RING")) {
        if(0 != answer()) {
            ERROR("answer");
        }
    } else if(NULL != strstr(gprsBuffer,"$$+CMTI: \"SM\"")) { //SMS: $$+CMTI: "SM",24$$
        char message[64];
        if(0 != readSMS(gprsBuffer, message, check)) {
            ERROR("readSMS");
        }
    }
    return 0;
}


/****************************************GPRS TCP CONNECT************************************/

int GPRS::connectTCP(char *ip, char *port)
{
    char cipstart[50];
    //char ipaddr[20];
#if 0
    wait(1);
    if(0 != sendCmdAndWaitForResp("AT+CSTT\r\n","OK",20)) { //Set GPRS
        ERROR("CSTT");
        return -1;
    }
    wait(1);
    if(0 != sendCmdAndWaitForResp("AT+CIICR\r\n","OK",10)) { //Set APN
        ERROR("CIICR");
        return -1;
    }
    wait(2);
    sendCmd("AT+CIFSR\r\n");
    readBuffer(ipaddr,20);
    DEBUG("ipaddr=");
    DEBUG(ipaddr);
    wait(1);
#endif
#if 1
    sprintf(cipstart, "AT+CIPSTART=\"TCP\",\"%s\",\"%s\"\r\n", ip, port);
    DEBUG(cipstart);
    if(0 != sendCmdAndWaitForResp(cipstart, "CONNECT OK", 10)) {	// connect tcp
        ERROR("CIPSTART");
        return -1;
    }
#endif
    return 0;
}
int GPRS::sendTCPData(char *data)
{
    char cmd[64];
    int len = strlen(data);
    snprintf(cmd,sizeof(cmd),"AT+CIPSEND=%d\r\n",len);
    DEBUG(cmd);
    if(0 != sendCmdAndWaitForResp(cmd,">",DEFALUT_TIMEOUT)) {
        ERROR("CIPSEND");
        return -1;
    }
    if(0 != sendCmdAndWaitForResp(data,"SEND OK",DEFALUT_TIMEOUT)) {
        ERROR("SendTCPData");
        return -1;
    }
    return 0;
}

int GPRS::closeTCP(void)
{
    sendCmd("AT+CIPCLOSE\r\n");
    return 0;
}

int GPRS::shutTCP(void)
{
    sendCmd("AT+CIPSHUT\r\n");
    return 0;
}

/****************************************GPRS DEBUG******************************************/
void GPRS::serialDebug(PinName tx, PinName rx)
{
    char buffer[64];
    int count = 0;
    Serial pc(tx,rx);
    while(1) {
        if(gprsSerial.readable()) {
            while(gprsSerial.readable()) {
                char c = gprsSerial.getc();
                buffer[count++] = c;
                if(count == 64) break;
            }
            pc.puts(buffer);
            for(int i = 0; i < count; i++) {
                buffer[i] = NULL;
            }
            count = 0;
        }

        if(pc.readable()) {
            gprsSerial.putc(pc.getc());
        }
    }
}