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-14
Revision:
0:a5ae94727346
Child:
1:642a8dbe076c

File content as of revision 0:a5ae94727346:

/*
  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 ERROR(x)						pc.printf("ERROR:%s\r\n",x)
#define DEBUG(x)						pc.printf("DEBUG:%s\r\n",x);

#define DEFALUT_TIMEOUT   	5
#define PHONE_NUMBER 				"13925257382"

Serial 	pc(USBTX,USBRX);
Serial gprsSerial(p9,p10); //software uart
Timer timeCnt;

int gprs::init(void)
{
	pc.baud(19200);
	gprsSerial.baud(19200);
	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;
			pc.putc(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();
			pc.putc(c);
	}
	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)
{
	#if 1
	int len = strlen(resp);
	int sum=0;
	timeCnt.start();  
	#if 0
	while(1){
		if(gprsSerial.readable()){
			break;
		}
		wait(0.5);
	}
	#endif
	while(1){
		if(gprsSerial.readable()){
			char c = gprsSerial.getc();
			pc.putc(c);
			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();
			pc.putc(c);
	}
	#endif
	return 0;
} 



int gprs::sendCmdAndWaitForResp(char *cmd, char *resp, int timeout)
{
	#if 0
		char gprsBuffer[32];
		cleanBuffer(gprsBuffer,32);
    sendCmd(cmd);
		readBuffer(gprsBuffer,4);
		if(0 == strncmp(resp,gprsBuffer,4)){
			return 0;
		}else{
			return -1;
		}
	#endif
		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);
	pc.printf(cmd);
	if(0 != sendCmdAndWaitForResp(cmd,">",DEFALUT_TIMEOUT)){
		ERROR("CMGS");
		return -1;
	}
	wait(0.5);
	gprsSerial.puts(data);// Send Message
	wait(0.5);
	gprsSerial.putc(0x1A);//end mark
	
	return 0;
}

int gprs::sendSMS()
{
	if(0 != sendCmdAndWaitForResp("AT+CMGF=1\r\n","OK",DEFALUT_TIMEOUT)){
			ERROR("CMGF");
			return -1;
	}
	wait(1);
	if(0 != sendCmdAndWaitForResp("AT+CMGS=\"13925257382\"\r\n",">",DEFALUT_TIMEOUT)){
			ERROR("CMGS");
			return -1;
	}
	wait(1);
	gprsSerial.puts("lawiet test\n");
	wait(1);
	gprsSerial.putc(0x1A);
	
	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\"",PHONE_NUMBER); //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?PHONE_NUMBER:number);
	return 0;
}

int gprs::answerWithCheck(char *gprsBuffer, bool check)
{
	if(check){
		if(NULL == strstr(gprsBuffer,PHONE_NUMBER)){
			ERROR("phone number dismatch");
			return -1;
		}
	}
	
	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;
			pc.putc(c);
			i++;
			if(i > 100){
				i = 0;	
				break;
			}
		}
		if(timeCnt.read() > DEFALUT_TIMEOUT){           // time out
		
			timeCnt.stop();
			timeCnt.reset();
			break;
		}
	}	
	
	pc.printf("\r\nDebug message is %s\r\n",gprsBuffer);
	
	if(NULL != strstr(gprsBuffer,"$$RING$$$$+CLIP:")){ //it is Ringing
		if(0 != answerWithCheck(gprsBuffer, TRUE)){
			ERROR("answer");
		}
	}else if(NULL != strstr(gprsBuffer,"$$+CMTI: \"SM\"")){  //SMS: $$+CMTI: "SM",24$$
		char message[64];
		if(0 != readSMS(gprsBuffer, message, TRUE)){
			ERROR("readSMS");
		}
		pc.puts(message);
	}
	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(void)
{	
	char buffer[64];
	int count = 0;
	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());
		}
	}	
}