diff --git a/GSM.cpp b/GSM.cpp index 3f40f25..b399388 100644 --- a/GSM.cpp +++ b/GSM.cpp @@ -1,739 +1,879 @@ -/* -This is a Beta version. -last modified 18/08/2012. - -This library is based on one developed by Arduino Labs -and it is modified to preserve the compability -with the Arduino's product. - -The library is modified to use the GSM Shield, -developed by www.open-electronics.org -(http://www.open-electronics.org/arduino-gsm-shield/) -and based on SIM900 chip, -with the same commands of Arduino Shield, -based on QuectelM10 chip. -*/ - -#include "GSM.h" -#include "WideTextFinder.h" - -//De-comment this two lines below if you have the -//first version of GSM GPRS Shield -//#define _GSM_TXPIN_ 4 -//#define _GSM_RXPIN_ 5 - -//De-comment this two lines below if you have the -//second version og GSM GPRS Shield -#define _GSM_TXPIN_ 2 -#define _GSM_RXPIN_ 3 - -#ifdef UNO -GSM::GSM():_cell(_GSM_TXPIN_,_GSM_RXPIN_),_tf(_cell, 10),_status(IDLE) -{ -}; -#endif -#ifdef MEGA -GSM::GSM() -{ - _cell.begin(9600); -}; -#endif - - -int GSM::begin(long baud_rate) -{ - // Set pin modes - pinMode(GSM_ON,OUTPUT); - pinMode(GSM_RESET,OUTPUT); - -#ifdef UNO - if (baud_rate==115200) { - Serial.println(F("Don't use baudrate 115200 with Software Serial.\nAutomatically changed at 9600.")); - baud_rate=9600; - } -#endif - int response=-1; - int cont=0; - boolean norep=true; - boolean turnedON=false; - SetCommLineStatus(CLS_ATCMD); - _cell.begin(baud_rate); - p_comm_buf = &comm_buf[0]; - setStatus(IDLE); - - // if no-reply we turn to turn on the module - for (cont=0; cont<3; cont++) { - if (AT_RESP_ERR_NO_RESP == SendATCmdWaitResp(str_at, 500, 100, str_ok, 5)&&!turnedON) { //check power - // there is no response => turn on the module -#ifdef DEBUG_ON - Serial.println(F("DB:NO RESP")); -#endif - // generate turn on pulse - digitalWrite(GSM_ON, HIGH); - delay(1200); - digitalWrite(GSM_ON, LOW); - delay(10000); - WaitResp(1000, 1000); - } else { -#ifdef DEBUG_ON - Serial.println(F("DB:ELSE")); -#endif - WaitResp(1000, 1000); - } - } - - - if (AT_RESP_OK == SendATCmdWaitResp(str_at, 500, 100, str_ok, 5)) { -#ifdef DEBUG_ON - Serial.println(F("DB:CORRECT BR")); -#endif - turnedON=true; - norep=false; - } - - - if (AT_RESP_ERR_DIF_RESP == SendATCmdWaitResp(str_at, 500, 100, str_ok, 5)&&!turnedON) { //check OK -#ifdef DEBUG_ON - Serial.println(F("DB:AUTO BAUD RATE")); -#endif - for (int i=0; i<8; i++) { - switch (i) { - case 0: - _cell.begin(1200); - break; - - case 1: - _cell.begin(2400); - break; - - case 2: - _cell.begin(4800); - break; - - case 3: - _cell.begin(9600); - break; - - case 4: - _cell.begin(19200); - break; - - case 5: - _cell.begin(38400); - break; - - case 6: - _cell.begin(57600); - break; - - case 7: - _cell.begin(115200); - break; - - // if nothing else matches, do the default - // default is optional - } - - delay(100); - -#ifdef DEBUG_PRINT - // parameter 0 - because module is off so it is not necessary - // to send finish AT here - DebugPrint(F("DEBUG: Stringa "), 0); - DebugPrint(buff, 0); -#endif - - - if (AT_RESP_OK == SendATCmdWaitResp(str_at, 500, 100, str_ok, 5)) { -#ifdef DEBUG_ON - Serial.println(F("DB:FOUND PREV BR")); -#endif - _cell.print("AT+IPR="); - _cell.print(baud_rate); - _cell.print("\r"); // send - delay(500); - _cell.begin(baud_rate); - delay(100); - if (AT_RESP_OK == SendATCmdWaitResp(str_at, 500, 100, str_ok, 5)) { -#ifdef DEBUG_ON - Serial.println(F("DB:OK BR")); -#endif - } - turnedON=true; - break; - } -#ifdef DEBUG_ON - Serial.println(F("DB:NO BR")); -#endif - } - // communication line is not used yet = free - SetCommLineStatus(CLS_FREE); - // pointer is initialized to the first item of comm. buffer - p_comm_buf = &comm_buf[0]; - } - - if(norep==true&&!turnedON) { - Serial.println(F("Trying to force the baud-rate to 9600\n")); - for (int i=0; i<8; i++) { - switch (i) { - case 0: - _cell.begin(1200); - delay(1000); - Serial.println(F("1200")); - _cell.print(F("AT+IPR=9600\r")); - delay(1000); - _cell.begin(9600); - delay(1000); - SendATCmdWaitResp(str_at, 500, 100, str_ok, 5); - delay(1000); - WaitResp(1000,1000); - break; - - case 1: - _cell.begin(2400); - delay(1000); - Serial.println(F("2400")); - _cell.print(F("AT+IPR=9600\r")); - delay(1000); - _cell.begin(9600); - delay(1000); - SendATCmdWaitResp(str_at, 500, 100, str_ok, 5); - delay(1000); - WaitResp(1000,1000); - break; - - case 2: - _cell.begin(4800); - delay(1000); - Serial.println(F("4800")); - _cell.print(F("AT+IPR=9600\r")); - delay(1000); - _cell.begin(9600); - delay(1000); - SendATCmdWaitResp(str_at, 500, 100, str_ok, 5); - delay(1000); - WaitResp(1000,1000); - break; - - case 3: - _cell.begin(9600); - delay(1000); - Serial.println(F("9600")); - _cell.print(F("AT+IPR=9600\r")); - delay(1000); - _cell.begin(9600); - delay(1000); - SendATCmdWaitResp(str_at, 500, 100, str_ok, 5); - delay(1000); - WaitResp(1000,1000); - break; - - case 4: - _cell.begin(19200); - delay(1000); - Serial.println(F("19200")); - _cell.print(F("AT+IPR=9600\r")); - delay(1000); - _cell.begin(9600); - delay(1000); - SendATCmdWaitResp(str_at, 500, 100, str_ok, 5); - delay(1000); - WaitResp(1000,1000); - break; - - case 5: - _cell.begin(38400); - delay(1000); - Serial.println(F("38400")); - _cell.print(F("AT+IPR=9600\r")); - delay(1000); - _cell.begin(9600); - delay(1000); - SendATCmdWaitResp(str_at, 500, 100, str_ok, 5); - delay(1000); - WaitResp(1000,1000); - break; - - case 6: - _cell.begin(57600); - delay(1000); - Serial.println(F("57600")); - _cell.print(F("AT+IPR=9600\r")); - delay(1000); - _cell.begin(9600); - delay(1000); - SendATCmdWaitResp(str_at, 500, 100, str_ok, 5); - delay(1000); - WaitResp(1000,1000); - break; - - case 7: - _cell.begin(115200); - delay(1000); - Serial.println(F("115200")); - _cell.print(F("AT+IPR=9600\r")); - delay(1000); - _cell.begin(9600); - delay(1000); - SendATCmdWaitResp(str_at, 500, 100, str_ok, 5); - delay(1000); - WaitResp(1000,1000); - break; - } - } - - Serial.println(F("ERROR: SIM900 doesn't answer. Check power and serial pins in GSM.cpp")); - digitalWrite(GSM_ON, HIGH); - delay(1200); - digitalWrite(GSM_ON, LOW); - delay(10000); - return 0; - } - - SetCommLineStatus(CLS_FREE); - - if(turnedON) { - WaitResp(50, 50); - InitParam(PARAM_SET_0); - InitParam(PARAM_SET_1);//configure the module - Echo(0); //enable AT echo - setStatus(READY); - return(1); - - } else { - //just to try to fix some problems with 115200 baudrate - _cell.begin(115200); - delay(1000); - _cell.print("AT+IPR="); - _cell.print(baud_rate); - _cell.print("\r"); // send - return(0); - } -} - - -void GSM::InitParam(byte group) -{ - switch (group) { - case PARAM_SET_0: - // check comm line - //if (CLS_FREE != GetCommLineStatus()) return; - - SetCommLineStatus(CLS_ATCMD); - // Reset to the factory settings - SendATCmdWaitResp(F("AT&F"), 1000, 50, str_ok, 5); - // switch off echo - SendATCmdWaitResp(F("ATE0"), 500, 50, str_ok, 5); - // setup fixed baud rate - //SendATCmdWaitResp("AT+IPR=9600", 500, 50, str_ok, 5); - // setup mode - //SendATCmdWaitResp("AT#SELINT=1", 500, 50, str_ok, 5); - // Switch ON User LED - just as signalization we are here - //SendATCmdWaitResp("AT#GPIO=8,1,1", 500, 50, str_ok, 5); - // Sets GPIO9 as an input = user button - //SendATCmdWaitResp("AT#GPIO=9,0,0", 500, 50, str_ok, 5); - // allow audio amplifier control - //SendATCmdWaitResp("AT#GPIO=5,0,2", 500, 50, str_ok, 5); - // Switch OFF User LED- just as signalization we are finished - //SendATCmdWaitResp("AT#GPIO=8,0,1", 500, 50, str_ok, 5); - SetCommLineStatus(CLS_FREE); - break; - - case PARAM_SET_1: - // check comm line - //if (CLS_FREE != GetCommLineStatus()) return; - SetCommLineStatus(CLS_ATCMD); - // Request calling line identification - SendATCmdWaitResp(F("AT+CLIP=1"), 500, 50, str_ok, 5); - // Mobile Equipment Error Code - SendATCmdWaitResp(F("AT+CMEE=0"), 500, 50, str_ok, 5); - // Echo canceller enabled - //SendATCmdWaitResp("AT#SHFEC=1", 500, 50, str_ok, 5); - // Ringer tone select (0 to 32) - //SendATCmdWaitResp("AT#SRS=26,0", 500, 50, str_ok, 5); - // Microphone gain (0 to 7) - response here sometimes takes - // more than 500msec. so 1000msec. is more safety - //SendATCmdWaitResp("AT#HFMICG=7", 1000, 50, str_ok, 5); - // set the SMS mode to text - SendATCmdWaitResp(F("AT+CMGF=1"), 500, 50, str_ok, 5); - // Auto answer after first ring enabled - // auto answer is not used - //SendATCmdWaitResp("ATS0=1", 500, 50, str_ok, 5); - // select ringer path to handsfree - //SendATCmdWaitResp("AT#SRP=1", 500, 50, str_ok, 5); - // select ringer sound level - //SendATCmdWaitResp("AT+CRSL=2", 500, 50, str_ok, 5); - // we must release comm line because SetSpeakerVolume() - // checks comm line if it is free - SetCommLineStatus(CLS_FREE); - // select speaker volume (0 to 14) - //SetSpeakerVolume(9); - // init SMS storage - InitSMSMemory(); - // select phonebook memory storage - SendATCmdWaitResp(F("AT+CPBS=\"SM\""), 1000, 50, str_ok, 5); - SendATCmdWaitResp(F("AT+CIPSHUT"), 500, 50, "SHUT OK", 5); - break; - } -} - -byte GSM::WaitResp(uint16_t start_comm_tmout, uint16_t max_interchar_tmout, - char const *expected_resp_string) -{ - byte status; - byte ret_val; - - RxInit(start_comm_tmout, max_interchar_tmout); - // wait until response is not finished - do { - status = IsRxFinished(); - } while (status == RX_NOT_FINISHED); - - if (status == RX_FINISHED) { - // something was received but what was received? - // --------------------------------------------- - - if(IsStringReceived(expected_resp_string)) { - // expected string was received - // ---------------------------- - ret_val = RX_FINISHED_STR_RECV; - } else { - ret_val = RX_FINISHED_STR_NOT_RECV; - } - } else { - // nothing was received - // -------------------- - ret_val = RX_TMOUT_ERR; - } - return (ret_val); -} - - -/********************************************************** -Method sends AT command and waits for response - -return: - AT_RESP_ERR_NO_RESP = -1, // no response received - AT_RESP_ERR_DIF_RESP = 0, // response_string is different from the response - AT_RESP_OK = 1, // response_string was included in the response -**********************************************************/ -char GSM::SendATCmdWaitResp(char const *AT_cmd_string, - uint16_t start_comm_tmout, uint16_t max_interchar_tmout, - char const *response_string, - byte no_of_attempts) -{ - byte status; - char ret_val = AT_RESP_ERR_NO_RESP; - byte i; - - for (i = 0; i < no_of_attempts; i++) { - // delay 500 msec. before sending next repeated AT command - // so if we have no_of_attempts=1 tmout will not occurred - if (i > 0) delay(500); - - _cell.println(AT_cmd_string); - status = WaitResp(start_comm_tmout, max_interchar_tmout); - if (status == RX_FINISHED) { - // something was received but what was received? - // --------------------------------------------- - if(IsStringReceived(response_string)) { - ret_val = AT_RESP_OK; - break; // response is OK => finish - } else ret_val = AT_RESP_ERR_DIF_RESP; - } else { - // nothing was received - // -------------------- - ret_val = AT_RESP_ERR_NO_RESP; - } - - } - - WaitResp(1000, 5000); - return (ret_val); -} - - -/********************************************************** -Method sends AT command and waits for response - -return: - AT_RESP_ERR_NO_RESP = -1, // no response received - AT_RESP_ERR_DIF_RESP = 0, // response_string is different from the response - AT_RESP_OK = 1, // response_string was included in the response -**********************************************************/ -char GSM::SendATCmdWaitResp(const __FlashStringHelper *AT_cmd_string, - uint16_t start_comm_tmout, uint16_t max_interchar_tmout, - char const *response_string, - byte no_of_attempts) -{ - byte status; - char ret_val = AT_RESP_ERR_NO_RESP; - byte i; - - for (i = 0; i < no_of_attempts; i++) { - // delay 500 msec. before sending next repeated AT command - // so if we have no_of_attempts=1 tmout will not occurred - if (i > 0) delay(500); - - _cell.println(AT_cmd_string); - status = WaitResp(start_comm_tmout, max_interchar_tmout); - if (status == RX_FINISHED) { - // something was received but what was received? - // --------------------------------------------- - if(IsStringReceived(response_string)) { - ret_val = AT_RESP_OK; - break; // response is OK => finish - } else ret_val = AT_RESP_ERR_DIF_RESP; - } else { - // nothing was received - // -------------------- - ret_val = AT_RESP_ERR_NO_RESP; - } - - } - - return (ret_val); -} - -byte GSM::WaitResp(uint16_t start_comm_tmout, uint16_t max_interchar_tmout) -{ - byte status; - - RxInit(start_comm_tmout, max_interchar_tmout); - // wait until response is not finished - do { - status = IsRxFinished(); - } while (status == RX_NOT_FINISHED); - return (status); -} - -byte GSM::IsRxFinished(void) -{ - byte num_of_bytes; - byte ret_val = RX_NOT_FINISHED; // default not finished - - // Rx state machine - // ---------------- - - if (rx_state == RX_NOT_STARTED) { - // Reception is not started yet - check tmout - if (!_cell.available()) { - // still no character received => check timeout - /* - #ifdef DEBUG_GSMRX - - DebugPrint("\r\nDEBUG: reception timeout", 0); - Serial.print((unsigned long)(millis() - prev_time)); - DebugPrint("\r\nDEBUG: start_reception_tmout\r\n", 0); - Serial.print(start_reception_tmout); - - - #endif - */ - if ((unsigned long)(millis() - prev_time) >= start_reception_tmout) { - // timeout elapsed => GSM module didn't start with response - // so communication is takes as finished - /* - #ifdef DEBUG_GSMRX - DebugPrint("\r\nDEBUG: RECEPTION TIMEOUT", 0); - #endif - */ - comm_buf[comm_buf_len] = 0x00; - ret_val = RX_TMOUT_ERR; - } - } else { - // at least one character received => so init inter-character - // counting process again and go to the next state - prev_time = millis(); // init tmout for inter-character space - rx_state = RX_ALREADY_STARTED; - } - } - - if (rx_state == RX_ALREADY_STARTED) { - // Reception already started - // check new received bytes - // only in case we have place in the buffer - num_of_bytes = _cell.available(); - // if there are some received bytes postpone the timeout - if (num_of_bytes) prev_time = millis(); - - // read all received bytes - while (num_of_bytes) { - num_of_bytes--; - if (comm_buf_len < COMM_BUF_LEN) { - // we have still place in the GSM internal comm. buffer => - // move available bytes from circular buffer - // to the rx buffer - *p_comm_buf = _cell.read(); - - p_comm_buf++; - comm_buf_len++; - comm_buf[comm_buf_len] = 0x00; // and finish currently received characters - // so after each character we have - // valid string finished by the 0x00 - } else { - // comm buffer is full, other incoming characters - // will be discarded - // but despite of we have no place for other characters - // we still must to wait until - // inter-character tmout is reached - - // so just readout character from circular RS232 buffer - // to find out when communication id finished(no more characters - // are received in inter-char timeout) - _cell.read(); - } - } - - // finally check the inter-character timeout - /* - #ifdef DEBUG_GSMRX - - DebugPrint("\r\nDEBUG: intercharacter", 0); - < Serial.print((unsigned long)(millis() - prev_time)); - DebugPrint("\r\nDEBUG: interchar_tmout\r\n", 0); - Serial.print(interchar_tmout); - - - #endif - */ - if ((unsigned long)(millis() - prev_time) >= interchar_tmout) { - // timeout between received character was reached - // reception is finished - // --------------------------------------------- - - /* - #ifdef DEBUG_GSMRX - - DebugPrint("\r\nDEBUG: OVER INTER TIMEOUT", 0); - #endif - */ - comm_buf[comm_buf_len] = 0x00; // for sure finish string again - // but it is not necessary - ret_val = RX_FINISHED; - } - } - - - return (ret_val); -} - -/********************************************************** -Method checks received bytes - -compare_string - pointer to the string which should be find - -return: 0 - string was NOT received - 1 - string was received -**********************************************************/ -byte GSM::IsStringReceived(char const *compare_string) -{ - char *ch; - byte ret_val = 0; - - if(comm_buf_len) { - /* - #ifdef DEBUG_GSMRX - DebugPrint("DEBUG: Compare the string: \r\n", 0); - for (int i=0; i,,,,, - if (AT_RESP_OK == SendATCmdWaitResp(F("AT+CPMS=\"SM\",\"SM\",\"SM\""), 1000, 1000, "+CPMS:", 10)) { - ret_val = 1; - } else ret_val = 0; - - SetCommLineStatus(CLS_FREE); - return (ret_val); -} - -int GSM::isIP(const char* cadena) -{ - int i; - for (i=0; i=48 && cadena[i] <=57))) - return 0; - return 1; -} - - - - - - +/* +This is a Beta version. +last modified 18/08/2012. + +This library is based on one developed by Arduino Labs +and it is modified to preserve the compability +with the Arduino's product. + +The library is modified to use the CGSM Shield, +developed by www.open-electronics.org +(http://www.open-electronics.org/arduino-gsm-shield/) +and based on SIM900 chip, +with the same commands of Arduino Shield, +based on QuectelM10 chip. +*/ + +#include "GSM.h" +#include "SWSerial.h" + +CGSM::CGSM() +{ + m_pStream = NULL; +} + +CGSM::CGSM(const SoftwareSerial *pStream): m_nStatus(IDLE) +{ + m_pStream = (Stream*)pStream; + m_nSizeofStream = sizeof *pStream; +} + +CGSM::CGSM(const HardwareSerial *pStream): m_nStatus(IDLE) +{ + m_pStream = (Stream*)pStream; + m_nSizeofStream = sizeof *pStream; +} + +bool CGSM::isUsingSS() +{ + return m_nSizeofStream == sizeof(SoftwareSerial); +} + +bool CGSM::isUsingHS() +{ + return m_nSizeofStream == sizeof(HardwareSerial); +} + +void CGSM::beginSerial(const uint32_t nBaud) +{ + if (m_nSizeofStream == sizeof(HardwareSerial)) + { + ((HardwareSerial*)m_pStream)->begin(nBaud); + } + else if (m_nSizeofStream == sizeof(SoftwareSerial)) + { + ((SoftwareSerial*)m_pStream)->begin(nBaud); + } +} + +void CGSM::turnOn() +{ + pinMode(GSM_ON, OUTPUT); + digitalWrite(GSM_ON, LOW); + delay(2000); + digitalWrite(GSM_ON, HIGH); + pinMode(GSM_ON, INPUT); +} + +bool CGSM::begin(const uint32_t nBaudRate) +{ + bool bResult = false; + char cResp = 0; + + beginSerial(nBaudRate); + SetCommLineStatus(CLS_ATCMD); + m_pCommBuff = &m_arrayCommBuff[0]; + setStatus(IDLE); + + // If no-reply we turn to turn on the module + #ifdef DEBUG_ON + Serial.println(F("Checking if GSM is turned on...")); + #endif + + for (uint8_t nI = 0; nI < 3; nI++) + { + cResp = SendATCmdWaitResp(F("AT"), 500, 100, F("OK"), 5); + + if (AT_RESP_ERR_NO_RESP == cResp) + { + // Check power - if there is no nResp then turn on the module + #ifdef DEBUG_ON + Serial.println(F("No response - turning GSM on...")); + #endif + // Generate turn on pulse + turnOn(); + } + else + break; + } + if (AT_RESP_OK == cResp) + { + InitParam(PARAM_SET_0); + InitParam(PARAM_SET_1); + setStatus(READY); + bResult = true; + #ifdef DEBUG_ON + Serial.println(F("GSM is on & ready!")); + #endif + } + else + { + #ifdef DEBUG_ON + Serial.println(F("GSM is not responding!")); + #endif + } + return bResult; +} + +void CGSM::InitParam(uint8_t group) +{ + switch (group) + { + case PARAM_SET_0: + SetCommLineStatus(CLS_ATCMD); + // Reset to the factory settings + SendATCmdWaitResp(F("AT&F"), 1000, 50, F("OK"), 5); + // Switch off echo + SendATCmdWaitResp(F("ATE0"), 500, 50, F("OK"), 5); + SetCommLineStatus(CLS_FREE); + break; + case PARAM_SET_1: + SetCommLineStatus(CLS_ATCMD); + // Request calling line identification + SendATCmdWaitResp(F("AT+CLIP=1"), 500, 50, F("OK"), 5); + // Mobile Equipment Error Code + SendATCmdWaitResp(F("AT+CMEE=0"), 500, 50, F("OK"), 5); + // Set the SMS mode to text + SendATCmdWaitResp(F("AT+CMGF=1"), 500, 50, F("OK"), 5); + // Checks comm line if it is free + SetCommLineStatus(CLS_FREE); + // Init SMS storage + InitSMSMemory(); + // Select phone book memory storage + SendATCmdWaitResp(F("AT+CPBS=\"SM\""), 1000, 50, F("OK"), 5); + SendATCmdWaitResp(F("AT+CIPSHUT"), 500, 50, F("SHUT OK"), 5); + break; + } +} + +uint8_t CGSM::WaitResp(uint16_t nSartCommTimeout, uint16_t nInterCharTimeout, const __FlashStringHelper *fstrExpectedResp) +{ + const uint16_t nLength = strlen_P((PGM_P)fstrExpectedResp) + 1; + char *strExpectedResp = new char[nLength]; + + memcpy(strExpectedResp, 0, nLength); + strcpy_P(strExpectedResp, (PGM_P)fstrExpectedResp); + uint8_t nRetVal = WaitResp(nSartCommTimeout, nInterCharTimeout, strExpectedResp); + delete strExpectedResp; + return nRetVal; +} + +uint8_t CGSM::WaitResp(uint16_t nSartCommTimeout, uint16_t nInterCharTimeout, const char *strExpectedResp) +{ + uint8_t nStatus = 0; + uint8_t nRetVal = 0; + + RxInit(nSartCommTimeout, nInterCharTimeout); + // Wait until nResp is not finished + do + { + nStatus = IsRxFinished(); + } + while (nStatus == RX_NOT_FINISHED); + + if (nStatus == RX_FINISHED) + { + // Something was received but what was received? + if (IsStringReceived(strExpectedResp)) + { + // Expected string was received + nRetVal = RX_FINISHED_STR_RECV; + } + else + { + nRetVal = RX_FINISHED_STR_NOT_RECV; + } + } + else + { + // Nothing was received + nRetVal = RX_TMOUT_ERR; + } + return (nRetVal); +} + + +/********************************************************** +Method sends AT command and waits for nResp + +return: + AT_RESP_ERR_NO_RESP = -1, // no nResp received + AT_RESP_ERR_DIF_RESP = 0, // strResp is different from the nResp + AT_RESP_OK = 1, // strResp was included in the nResp +**********************************************************/ +uint8_t CGSM::SendATCmdWaitResp(const char *strATCommStr, uint16_t nSartCommTimeout, uint16_t nInterCharTimeout, const __FlashStringHelper *fstrResp, uint8_t nNumAttempts) +{ + uint8_t nStatus = 0; + uint8_t nRetVal = AT_RESP_ERR_NO_RESP; + + for (uint8_t nI = 0; nI < nNumAttempts; nI++) + { + #ifdef DEBUG_ON + Serial.print(strATCommStr); + Serial.print(F("...")); + #endif + + // Delay 500 milliseconds. before sending next repeated AT command so if we have nNumAttempts=1 time out will not occurred + if (nI > 0) + delay(500); + + m_pStream->println(strATCommStr); + nStatus = WaitResp(nSartCommTimeout, nInterCharTimeout); + + if (nStatus == RX_FINISHED) + { + // Something was received but what was received? + if (IsStringReceived(fstrResp)) + { + #ifdef DEBUG_ON + Serial.println(fstrResp); + #endif + nRetVal = AT_RESP_OK; + break; // nResp is OK => finish + } + else + { + #ifdef DEBUG_ON + Serial.print(fstrResp); + Serial.println(F("...invalid response!")); + #endif + nRetVal = AT_RESP_ERR_DIF_RESP; + } + } + else + { + #ifdef DEBUG_ON + Serial.println(F("...no response!")); + #endif + // Nothing was received + nRetVal = AT_RESP_ERR_NO_RESP; + } + + } + return nRetVal; +} + + +/********************************************************** +Method sends AT command and waits for nResp + +return: + AT_RESP_ERR_NO_RESP = -1, // no nResp received + AT_RESP_ERR_DIF_RESP = 0, // strResp is different from the nResp + AT_RESP_OK = 1, // strResp was included in the nResp +**********************************************************/ +uint8_t CGSM::SendATCmdWaitResp(const __FlashStringHelper *fstrATCommStr, uint16_t nSartCommTimeout, uint16_t nInterCharTimeout, const __FlashStringHelper *fstrResp, uint8_t nNumAttempts) +{ + const uint16_t nLength = strlen_P((PGM_P)fstrATCommStr) + 1; + char *strATCommStr = new char[nLength]; + + memcpy(strATCommStr, 0, nLength); + strcpy_P(strATCommStr, (PGM_P)fstrATCommStr); + uint8_t nRetVal = SendATCmdWaitResp(strATCommStr, nSartCommTimeout, nInterCharTimeout, fstrResp, nNumAttempts); + delete strATCommStr; + return nRetVal; +} + +uint8_t CGSM::WaitResp(uint16_t nSartCommTimeout, uint16_t nInterCharTimeout) +{ + uint8_t nStatus = 0; + + RxInit(nSartCommTimeout, nInterCharTimeout); + + // Wait until nResp is not finished + do + { + nStatus = IsRxFinished(); + } + while (nStatus == RX_NOT_FINISHED); + + return (nStatus); +} + +uint8_t CGSM::IsRxFinished(void) +{ + uint8_t nNumBytes = 0; + uint8_t nRetVal = RX_NOT_FINISHED; // default not finished + + // Rx nState machine + if (m_nRxState == RX_NOT_STARTED) + { + // Reception is not started yet - check time out + if (!m_pStream->available()) + { + // Still no character received => check time out + if ((uint32_t)(millis() - m_nPrevTime) >= m_nStartRecTimeout) + { + // Time out elapsed => CGSM module didn't start with nResp so communication is takes as finished + m_arrayCommBuff[m_nCommBuffLen] = 0x00; + nRetVal = RX_TMOUT_ERR; + } + } + else + { + // At least one character received => so init inter-character counting process again and go to the next nState + m_nPrevTime = millis(); // init time out for inter-character space + m_nRxState = RX_ALREADY_STARTED; + } + } + if (m_nRxState == RX_ALREADY_STARTED) + { + // Reception already started check new received bytes only in case we have place in the buffer + nNumBytes = m_pStream->available(); + // If there are some received bytes postpone the time out + if (nNumBytes) + m_nPrevTime = millis(); + + // Read all received bytes + while (nNumBytes) + { + nNumBytes--; + if (m_nCommBuffLen < COMM_BUF_LEN) + { + // We have still place in the CGSM internal comm. buffer => move available bytes from circular buffer to the rx buffer + *m_pCommBuff = m_pStream->read(); + m_pCommBuff++; + m_nCommBuffLen++; + // And finish currently received characters so after each character we have valid string finished by the 0x00 + m_arrayCommBuff[m_nCommBuffLen] = 0x00; + } + else + { + // Comm buffer is full, other incoming characters will be discarded but despite of we have no place for other characters we still must to wait until inter-character time out + // is reached so just readout character from circular RS232 buffer to find out when communication id finished(no more characters are received in inter-char time out) + m_pStream->read(); + } + } + // Finally check the inter-character time out + if ((uint32_t)(millis() - m_nPrevTime) >= m_nInterCharTimeout) + { + // Time out between received character was reached reception is finished + m_arrayCommBuff[m_nCommBuffLen] = 0x00; + nRetVal = RX_FINISHED; + } + } + return (nRetVal); +} + +/********************************************************** +Method checks received bytes + +strCompare - pointer to the string which should be find + +return: 0 - string was NOT received + 1 - string was received +**********************************************************/ +uint8_t CGSM::IsStringReceived(const __FlashStringHelper *fstrCompare) +{ + const uint16_t nLength = strlen_P((PGM_P)fstrCompare) + 1; + char *strCompare = new char[nLength]; + + memcpy(strCompare, 0, nLength); + strcpy_P(strCompare, (PGM_P)fstrCompare); + uint8_t nRetVal = IsStringReceived(strCompare); + delete strCompare; + return nRetVal; +} + +uint8_t CGSM::IsStringReceived(const char *strCompare) +{ + char *strCh = NULL; + uint8_t nRetVal = 0; + + if (m_nCommBuffLen) + { +/* + #ifdef DEBUG_ON + Serial.print(F("ATT: ")); + Serial.println(strCompare); + Serial.print(F("RIC: ")); + Serial.println((char *)m_arrayCommBuff); + #endif +*/ + strCh = strstr((char *)m_arrayCommBuff, strCompare); + if (strCh != NULL) + nRetVal = 1; + } + else + { +/* + #ifdef DEBUG_ON + Serial.print(F("ATT: ")); + Serial.println(strCompare); + Serial.print(F("RIC: NO STRING RCVD")); + #endif +*/ + } + return (nRetVal); +} + + +void CGSM::RxInit(uint16_t nSartCommTimeout, uint16_t nInterCharTimeout) +{ + m_nRxState = RX_NOT_STARTED; + m_nStartRecTimeout = nSartCommTimeout; + m_nInterCharTimeout = nInterCharTimeout; + m_nPrevTime = millis(); + m_arrayCommBuff[0] = 0x00; + m_pCommBuff = &m_arrayCommBuff[0]; + m_nCommBuffLen = 0; + m_pStream->flush(); +} + +char CGSM::InitSMSMemory(void) +{ + char nRetVal = -1; + + if (CLS_FREE != GetCommLineStatus()) + return (nRetVal); + + SetCommLineStatus(CLS_ATCMD); + nRetVal = 0; // not initialized yet + + // Disable messages about new SMS from the CGSM module + SendATCmdWaitResp(F("AT+CNMI=2,0"), 1000, 50, F("OK"), 2); + + // Send AT command to init memory for SMS in the SIM card + // Resp: +CPMS: ,,,,, + if (AT_RESP_OK == SendATCmdWaitResp(F("AT+CPMS=\"SM\",\"SM\",\"SM\""), 1000, 1000, F("+CPMS:"), 10)) + nRetVal = 1; + else + nRetVal = 0; + + SetCommLineStatus(CLS_FREE); + return (nRetVal); +} + +bool CGSM::isIP(const char* strCadena) +{ + for (uint8_t nI = 0; nI < strlen(strCadena); nI++) + { + if (!(strCadena[nI] == '.' || ( strCadena[nI] >= 48 && strCadena[nI] <= 57))) + return false; + } + return true; +} + +/********************************************************** +Turns on/off the speaker + +nOnOff: 0 - off + 1 - on +**********************************************************/ +void CGSM::SetSpeaker(const bool nOnOff) +{ + if (CLS_FREE != GetCommLineStatus()) + return; + + SetCommLineStatus(CLS_ATCMD); + SetCommLineStatus(CLS_FREE); +} + + +bool CGSM::IsRegistered(void) +{ + return (m_nModuleStatus & STATUS_REGISTERED) > 0; +} + +bool CGSM::IsInitialized(void) +{ + return (m_nModuleStatus & STATUS_INITIALIZED) > 0; +} + + +/********************************************************** +Method checks if the CGSM module is registered in the CGSM net +- this method communicates directly with the CGSM module + in contrast to the method IsRegistered() which reads the + flag from the m_nModuleStatus (this flag is set inside this method) + +- must be called regularly - from 1seconds to cca. 10 seconds + +return values: + REG_NOT_REGISTERED - not registered + REG_REGISTERED - CGSM module is registered + REG_NO_RESPONSE - CGSM doesn't response + REG_COMM_LINE_BUSY - strComm line between CGSM module and Arduino is not free + for communication +**********************************************************/ +uint8_t CGSM::CheckRegistration(void) +{ + uint8_t nStatus = 0; + uint8_t nRetVal = REG_NOT_REGISTERED; + + if (CLS_FREE != GetCommLineStatus()) + return (REG_COMM_LINE_BUSY); + + SetCommLineStatus(CLS_ATCMD); + m_pStream->println(F("AT+CREG?")); + + // 5 seconds for initial strComm time out + // 50 milliseconds. for inter character time out + nStatus = WaitResp(5000, 50); + + if (nStatus == RX_FINISHED) + { + // Something was received but what was received? + if (IsStringReceived(F("+CREG: 0,1")) || IsStringReceived(F("+CREG: 0,5"))) + { + // It means module is registered + m_nModuleStatus |= STATUS_REGISTERED; + + + // In case CGSM module is registered first time after reset sets flag STATUS_INITIALIZED it is used for sending some init commands which must be sent only after registration + if (!IsInitialized()) + { + m_nModuleStatus |= STATUS_INITIALIZED; + SetCommLineStatus(CLS_FREE); + InitParam(PARAM_SET_1); + } + nRetVal = REG_REGISTERED; + } + else + { + // NOT registered + m_nModuleStatus &= ~STATUS_REGISTERED; + nRetVal = REG_NOT_REGISTERED; + } + } + else + { + // nothing was received + nRetVal = REG_NO_RESPONSE; + } + SetCommLineStatus(CLS_FREE); + + return (nRetVal); +} + + +/********************************************************** +Method returns state of user button + + +return: 0 - not pushed = released + 1 - pushed +**********************************************************/ +uint8_t CGSM::IsUserButtonPushed(void) +{ + uint8_t nRetVal = 0; + + if (CLS_FREE != GetCommLineStatus()) + nRetVal = 0; + else + { + SetCommLineStatus(CLS_ATCMD); + if (AT_RESP_OK == SendATCmdWaitResp(F("AT#GPIO=9,2"), 500, 50, F("#GPIO: 0,0"), 1)) + { + // User button is pushed + nRetVal = 1; + } + else + nRetVal = 0; + SetCommLineStatus(CLS_FREE); + } + return nRetVal; +} + + + +/********************************************************** +Method reads phone strNumber string from specified SIM nPos + +nPos: SMS nPos <1..20> + +return: + ERROR ret. val: + --------------- + -1 - strComm. line to the CGSM module is not free + -2 - CGSM module didn't answer in time out + -3 - nPos must be > 0 + strPhoneNumber is empty string + + OK ret val: + ----------- + 0 - there is no phone strNumber on the nPos + 1 - phone strNumber was found + strPhoneNumber is filled by the phone strNumber string finished by 0x00 + so it is necessary to define string with at least + 15 bytes(including also 0x00 termination character) + +an example of usage: + CGSM gsm; + char phone_num[20]; // array for the phone strNumber string + + if (1 == GetPhoneNumber(1, phone_num)) { + // valid phone strNumber on SIM pos. #1 + // phone strNumber string is copied to the phone_num array + #ifdef DEBUG_PRINT + DebugPrint("DEBUG phone strNumber: ", 0); + DebugPrint(phone_num, 1); + #endif + } + else { + // there is not valid phone strNumber on the SIM pos.#1 + #ifdef DEBUG_PRINT + DebugPrint("DEBUG there is no phone strNumber", 1); + #endif + } +**********************************************************/ + + +int8_t CGSM::GetPhoneNumber(const uint8_t nPos, char* strPhoneNumber) +{ + int8_t nRetVal = -1; + + char* str1 = NULL; + char* str2 = NULL; + + if (nPos == 0) + return (-3); + + if (CLS_FREE != GetCommLineStatus()) + return (nRetVal); + + SetCommLineStatus(CLS_ATCMD); + // Not found yet + nRetVal = 0; + // Phone strNumber not found yet => empty string + strPhoneNumber[0] = 0; + + // Send "AT+CPBR=XY" - where XY = nPos + m_pStream->print(F("AT+CPBR=")); + m_pStream->print((int16_t)nPos); + m_pStream->print(F("\r")); + + // 5000 milliseconds. for initial strComm time out + // 50 milliseconds. for inter character time out + switch (WaitResp(5000, 50, F("+CPBR"))) + { + case RX_TMOUT_ERR: + // Response was not received in specific time + nRetVal = -2; + break; + + case RX_FINISHED_STR_RECV: + // Response in case valid phone strNumber stored: + // +CPBR: ,,, + // OK + // Response in case there is not phone strNumber: + // OK + str1 = strstr_P(m_arrayCommBuff, (PGM_P)F(",\"")); + if (str1 != NULL) + { + str1++; + str1++; + // We are on the first phone number character - find out '"' as finish character of phone strNumber string + str2 = strchr(str1, '"'); + if (str2 != NULL) + { + *str2 = 0; + } + // Extract phone strNumber string + strcpy(strPhoneNumber, str1); + // Output value = we have found out phone strNumber string + nRetVal = 1; + } + break; + + case RX_FINISHED_STR_NOT_RECV: + // Only OK or ERROR => no phone strNumber + nRetVal = 0; + break; + } + SetCommLineStatus(CLS_FREE); + return (nRetVal); +} + +/********************************************************** +Method writes phone strNumber string to the specified SIM nPos + +nPos: SMS nPos <1..20> +strPhoneNumber: phone strNumber string for the writing + +return: + ERROR ret. val: + --------------- + -1 - strComm. line to the CGSM module is not free + -2 - CGSM module didn't answer in time out + -3 - nPos must be > 0 + + OK ret val: + ----------- + 0 - phone strNumber was not written + 1 - phone strNumber was written +**********************************************************/ +int8_t CGSM::WritePhoneNumber(const uint8_t nPos, char* strPhoneNumber) +{ + char nRetVal = -1; + + if (nPos == 0) + return (-3); + + if (CLS_FREE != GetCommLineStatus()) + return (nRetVal); + + SetCommLineStatus(CLS_ATCMD); + // Phone strNumber was not written yet + nRetVal = 0; + + // Send: AT+CPBW=XY,"00420123456789" + // where XY = nPos, "00420123456789" = phone number string + m_pStream->print(F("AT+CPBW=")); + m_pStream->print((int16_t)nPos); + m_pStream->print(F(",\"")); + m_pStream->print(strPhoneNumber); + m_pStream->print(F("\"\r")); + + // 5000 milliseconds. for initial comm time out + // 50 milliseconds. for inter character time out + switch (WaitResp(5000, 50, F("OK"))) + { + case RX_TMOUT_ERR: + // Response was not received in specific time + break; + + case RX_FINISHED_STR_RECV: + // Response is OK = has been written + nRetVal = 1; + break; + + case RX_FINISHED_STR_NOT_RECV: + // Other response: e.g. ERROR + break; + } + + SetCommLineStatus(CLS_FREE); + return (nRetVal); +} + + +/********************************************************** +Method del phone strNumber from the specified SIM nPos + +nPos: SMS nPos <1..20> + +return: + ERROR ret. val: + --------------- + -1 - strComm. line to the CGSM module is not free + -2 - CGSM module didn't answer in time out + -3 - nPos must be > 0 + + OK ret val: + ----------- + 0 - phone strNumber was not deleted + 1 - phone strNumber was deleted +**********************************************************/ +int8_t CGSM::DelPhoneNumber(const uint8_t nPos) +{ + int8_t nRetVal = -1; + + if (nPos == 0) + return (-3); + + if (CLS_FREE != GetCommLineStatus()) + return (nRetVal); + + SetCommLineStatus(CLS_ATCMD); + // Phone strNumber was not written yet + nRetVal = 0; + + // Send: AT+CPBW=XY, where XY = nPos + m_pStream->print(F("AT+CPBW=")); + m_pStream->print((int16_t)nPos); + m_pStream->print(F("\r")); + + // 5000 milliseconds. for initial strComm time out + // 50 milliseconds. for inter character time out + switch (WaitResp(5000, 50, F("OK"))) + { + case RX_TMOUT_ERR: + // Response was not received in specific time + break; + + case RX_FINISHED_STR_RECV: + // Response is OK = has been written + nRetVal = 1; + break; + + case RX_FINISHED_STR_NOT_RECV: + // Other response: e.g. ERROR + break; + } + SetCommLineStatus(CLS_FREE); + return (nRetVal); +} + + + + + +/********************************************************** +Function compares specified phone strNumber string +with phone strNumber stored at the specified SIM nPos + +nPos: SMS nPos <1..20> +strPhoneNumber: phone strNumber string which should be compare + +return: + ERROR ret. val: + --------------- + -1 - strComm. line to the CGSM module is not free + -2 - CGSM module didn't answer in time out + -3 - nPos must be > 0 + + OK ret val: + ----------- + 0 - phone numbers are different + 1 - phone numbers are the same + + +an example of usage: + if (1 == ComparePhoneNumber(1, "123456789")) { + // the phone num. "123456789" is stored on the SIM pos. #1 + // phone strNumber string is copied to the phone_num array + #ifdef DEBUG_PRINT + DebugPrint("DEBUG phone numbers are the same", 1); + #endif + } + else { + #ifdef DEBUG_PRINT + DebugPrint("DEBUG phone numbers are different", 1); + #endif + } +**********************************************************/ +int8_t CGSM::ComparePhoneNumber(const uint8_t nPos, char* strPhoneNumber) +{ + int8_t nRetVal = -1; + char strSIMPhoneNum[20]; + + + // Numbers are not the same so far + nRetVal = 0; + if (nPos == 0) + return (-3); + + if (1 == GetPhoneNumber(nPos, strSIMPhoneNum)) + { + Serial.print(F("CHIAMANTE ")); + Serial.println(strPhoneNumber); + Serial.print(F("SALVATO ")); + Serial.println(strSIMPhoneNum); + + // There is a valid strNumber at the spec. SIM nPos + if (0 == strcmp(strPhoneNumber, strSIMPhoneNum)) + { + // Phone numbers are the same + nRetVal = 1; + } + } + return (nRetVal); +} + +//----------------------------------------------------- + + + + + diff --git a/GSM.h b/GSM.h index f311026..544ced4 100644 --- a/GSM.h +++ b/GSM.h @@ -1,271 +1,251 @@ -#ifndef GSM_H -#define GSM_H - -#define UNO -//#define MEGA - -#include -#include -#include "WideTextFinder.h" - - -#define ctrlz 26 //Ascii character for ctr+z. End of a SMS. -#define cr 13 //Ascii character for carriage return. -#define lf 10 //Ascii character for line feed. -#define ctrlz 26 //Ascii character for ctr+z. End of a SMS. -#define cr 13 //Ascii character for carriage return. -#define lf 10 //Ascii character for line feed. -#define GSM_LIB_VERSION 308 // library version X.YY (e.g. 1.00) - -#define DEBUG_ON - - -#ifdef MEGA -#include "HWSerial.h" -#endif - -// if defined - debug print is enabled with possibility to print out -// debug texts to the terminal program -//#define DEBUG_PRINT - -// if defined - debug print is enabled with possibility to print out -// the data recived from gsm module -//#define DEBUG_GSMRX - -// if defined - debug LED is enabled, otherwise debug LED is disabled -//#define DEBUG_LED_ENABLED - -// if defined - SMSs are not send(are finished by the character 0x1b -// which causes that SMS are not send) -// by this way it is possible to develop program without paying for the SMSs -//#define DEBUG_SMS_ENABLED - - -// pins definition -#define GSM_ON 8 // connect GSM Module turn ON to pin 77 -#define GSM_RESET 9 // connect GSM Module RESET to pin 35 -//#define DTMF_OUTPUT_ENABLE 71 // connect DTMF Output Enable not used -#define DTMF_DATA_VALID 14 // connect DTMF Data Valid to pin 14 -#define DTMF_DATA0 72 // connect DTMF Data0 to pin 72 -#define DTMF_DATA1 73 // connect DTMF Data1 to pin 73 -#define DTMF_DATA2 74 // connect DTMF Data2 to pin 74 -#define DTMF_DATA3 75 // connect DTMF Data3 to pin 75 - -// length for the internal communication buffer -#define COMM_BUF_LEN 200 - -// some constants for the IsRxFinished() method -#define RX_NOT_STARTED 0 -#define RX_ALREADY_STARTED 1 - -// some constants for the InitParam() method -#define PARAM_SET_0 0 -#define PARAM_SET_1 1 - -// DTMF signal is NOT valid -//#define DTMF_NOT_VALID 0x10 - - -// status bits definition -#define STATUS_NONE 0 -#define STATUS_INITIALIZED 1 -#define STATUS_REGISTERED 2 -#define STATUS_USER_BUTTON_ENABLE 4 - -// GPRS status -#define CHECK_AND_OPEN 0 -#define CLOSE_AND_REOPEN 1 - -// Common string used -#define str_ok "OK" //string to reduce stack usage -#define str_at "AT" //string to reduce stack usage - -// SMS type -// use by method IsSMSPresent() -enum sms_type_enum { - SMS_UNREAD, - SMS_READ, - SMS_ALL, - - SMS_LAST_ITEM -}; - -enum comm_line_status_enum { - // CLS like CommunicationLineStatus - CLS_FREE, // line is free - not used by the communication and can be used - CLS_ATCMD, // line is used by AT commands, includes also time for response - CLS_DATA, // for the future - line is used in the CSD or GPRS communication - CLS_LAST_ITEM -}; - -enum rx_state_enum { - RX_NOT_FINISHED = 0, // not finished yet - RX_FINISHED, // finished, some character was received - RX_FINISHED_STR_RECV, // finished and expected string received - RX_FINISHED_STR_NOT_RECV, // finished, but expected string not received - RX_TMOUT_ERR, // finished, no character received - // initial communication tmout occurred - RX_LAST_ITEM -}; - - -enum at_resp_enum { - AT_RESP_ERR_NO_RESP = -1, // nothing received - AT_RESP_ERR_DIF_RESP = 0, // response_string is different from the response - AT_RESP_OK = 1, // response_string was included in the response - - AT_RESP_LAST_ITEM -}; - -enum registration_ret_val_enum { - REG_NOT_REGISTERED = 0, - REG_REGISTERED, - REG_NO_RESPONSE, - REG_COMM_LINE_BUSY, - - REG_LAST_ITEM -}; - -enum call_ret_val_enum { - CALL_NONE = 0, - CALL_INCOM_VOICE, - CALL_ACTIVE_VOICE, - CALL_INCOM_VOICE_AUTH, - CALL_INCOM_VOICE_NOT_AUTH, - CALL_INCOM_DATA_AUTH, - CALL_INCOM_DATA_NOT_AUTH, - CALL_ACTIVE_DATA, - CALL_OTHERS, - CALL_NO_RESPONSE, - CALL_COMM_LINE_BUSY, - - CALL_LAST_ITEM -}; - - -enum getsms_ret_val_enum { - GETSMS_NO_SMS = 0, - GETSMS_UNREAD_SMS, - GETSMS_READ_SMS, - GETSMS_OTHER_SMS, - - GETSMS_NOT_AUTH_SMS, - GETSMS_AUTH_SMS, - - GETSMS_LAST_ITEM -}; - - -class GSM { -public: - enum GSM_st_e { ERROR, IDLE, READY, ATTACHED, TCPSERVERWAIT, TCPCONNECTEDSERVER, TCPCONNECTEDCLIENT }; - byte comm_buf[COMM_BUF_LEN+1]; // communication buffer +1 for 0x00 termination - void InitParam (byte group); - -private: - int _status; - byte comm_line_status; - - // global status - bits are used for representation of states - byte module_status; - - // variables connected with communication buffer - - byte *p_comm_buf; // pointer to the communication buffer - byte comm_buf_len; // num. of characters in the buffer - byte rx_state; // internal state of rx state machine - uint16_t start_reception_tmout; // max tmout for starting reception - uint16_t interchar_tmout; // previous time in msec. - unsigned long prev_time; // previous time in msec. - - // last value of speaker volume - byte last_speaker_volume; - char InitSMSMemory(void); - -protected: -#ifdef MEGA - HWSerial _cell; -#endif -#ifdef UNO - SoftwareSerial _cell; -#endif - int isIP(const char* cadena); - -public: -#ifdef UNO - WideTextFinder _tf; -#endif - inline void setStatus(GSM_st_e status) { - _status = status; - } - GSM(); - inline int getStatus() { - return _status; - }; - virtual int begin(long baud_rate); - inline void SetCommLineStatus(byte new_status) { - comm_line_status = new_status; - }; - inline byte GetCommLineStatus(void) { - return comm_line_status; - }; - void RxInit(uint16_t start_comm_tmout, uint16_t max_interchar_tmout); - byte IsRxFinished(void); - byte IsStringReceived(char const *compare_string); - byte WaitResp(uint16_t start_comm_tmout, uint16_t max_interchar_tmout); - byte WaitResp(uint16_t start_comm_tmout, uint16_t max_interchar_tmout, - char const *expected_resp_string); - char SendATCmdWaitResp(char const *AT_cmd_string, - uint16_t start_comm_tmout, uint16_t max_interchar_tmout, - char const *response_string, - byte no_of_attempts); - char SendATCmdWaitResp(const __FlashStringHelper *AT_cmd_string, - uint16_t start_comm_tmout, uint16_t max_interchar_tmout, - char const *response_string, - byte no_of_attempts); - void Echo(byte state); - - - //----------------------- - // turns off/on the speaker - void SetSpeaker(byte off_on); - // checks if module is registered in the GSM network - // must be called regularly - byte CheckRegistration(void); - - // User button methods - inline byte IsUserButtonEnable(void) { - return (module_status & STATUS_USER_BUTTON_ENABLE); - }; - inline void DisableUserButton(void) { - module_status &= ~STATUS_USER_BUTTON_ENABLE; - }; - inline void EnableUserButton(void) { - module_status |= STATUS_USER_BUTTON_ENABLE; - }; - byte IsUserButtonPushed(void); - - // Phonebook's methods - char GetPhoneNumber(byte position, char *phone_number); - char WritePhoneNumber(byte position, char *phone_number); - char DelPhoneNumber(byte position); - char ComparePhoneNumber(byte position, char *phone_number); - - // returns registration state - byte IsRegistered(void); - // returns whether complete initialization was made - byte IsInitialized(void); - //----------------------- - - // debug methods -#ifdef DEBUG_LED_ENABLED - void BlinkDebugLED (byte num_of_blink); -#endif - -#ifdef DEBUG_PRINT - void DebugPrint(const char *string_to_print, byte last_debug_print); - void DebugPrint(int number_to_print, byte last_debug_print); -#endif -}; - -#endif +#ifndef GSM_H +#define GSM_H + + + + +#include +#include +#include "SWSerial.h" +#include "HWSerial.h" + + + + +#define ctrlz 26 //Ascii character for ctr+z. End of a SMS. +#define cr 13 //Ascii character for carriage return. +#define lf 10 //Ascii character for line feed. +#define ctrlz 26 //Ascii character for ctr+z. End of a SMS. +#define cr 13 //Ascii character for carriage return. +#define lf 10 //Ascii character for line feed. +#define GSM_LIB_VERSION 308 // library version X.YY (e.g. 1.00) + +#define DEBUG_ON + + + +// if defined - debug print is enabled with possibility to print out +// debug texts to the terminal program +//#define DEBUG_PRINT + +// if defined - debug print is enabled with possibility to print out +// the data recived from gsm module +//#define DEBUG_GSMRX + +// if defined - debug LED is enabled, otherwise debug LED is disabled +//#define DEBUG_LED_ENABLED + +// if defined - SMSs are not send(are finished by the character 0x1b +// which causes that SMS are not send) +// by this way it is possible to develop program without paying for the SMSs +//#define DEBUG_SMS_ENABLED + + +// pins definition +#define GSM_ON 12 // connect CGSM Module turn ON to pin 77 +#define GSM_RESET 9 // connect CGSM Module RESET to pin 35 +//#define DTMF_OUTPUT_ENABLE 71 // connect DTMF Output Enable not used +#define DTMF_DATA_VALID 14 // connect DTMF Data Valid to pin 14 +#define DTMF_DATA0 72 // connect DTMF Data0 to pin 72 +#define DTMF_DATA1 73 // connect DTMF Data1 to pin 73 +#define DTMF_DATA2 74 // connect DTMF Data2 to pin 74 +#define DTMF_DATA3 75 // connect DTMF Data3 to pin 75 + +// length for the internal communication buffer +#define COMM_BUF_LEN 200 + +// some constants for the IsRxFinished() method +#define RX_NOT_STARTED 0 +#define RX_ALREADY_STARTED 1 + +// some constants for the InitParam() method +#define PARAM_SET_0 0 +#define PARAM_SET_1 1 + +// DTMF signal is NOT valid +//#define DTMF_NOT_VALID 0x10 + + +// nStatus bits definition +#define STATUS_NONE 0 +#define STATUS_INITIALIZED 1 +#define STATUS_REGISTERED 2 +#define STATUS_USER_BUTTON_ENABLE 4 + +// GPRS nStatus +#define CHECK_AND_OPEN 0 +#define CLOSE_AND_REOPEN 1 + + + +// SMS type +// use by method IsSMSPresent() +enum sms_type_enum +{ + SMS_UNREAD, + SMS_READ, + SMS_ALL, + + SMS_LAST_ITEM +}; + +enum comm_line_status_enum +{ + // CLS like CommunicationLineStatus + CLS_FREE, // line is free - not used by the communication and can be used + CLS_ATCMD, // line is used by AT commands, includes also time for response + CLS_DATA, // for the future - line is used in the CSD or GPRS communication + CLS_LAST_ITEM +}; + +enum rx_state_enum +{ + RX_NOT_FINISHED = 0, // not finished yet + RX_FINISHED, // finished, some character was received + RX_FINISHED_STR_RECV, // finished and expected string received + RX_FINISHED_STR_NOT_RECV, // finished, but expected string not received + RX_TMOUT_ERR, // finished, no character received + // initial communication tmout occurred + RX_LAST_ITEM +}; + + +enum at_resp_enum +{ + AT_RESP_ERR_NO_RESP = -1, // nothing received + AT_RESP_ERR_DIF_RESP = 0, // strResp is different from the response + AT_RESP_OK = 1, // strResp was included in the response + + AT_RESP_LAST_ITEM +}; + +enum registration_ret_val_enum +{ + REG_NOT_REGISTERED = 0, + REG_REGISTERED, + REG_NO_RESPONSE, + REG_COMM_LINE_BUSY, + + REG_LAST_ITEM +}; + +enum call_ret_val_enum +{ + CALL_NONE = 0, + CALL_INCOM_VOICE, + CALL_ACTIVE_VOICE, + CALL_INCOM_VOICE_AUTH, + CALL_INCOM_VOICE_NOT_AUTH, + CALL_INCOM_DATA_AUTH, + CALL_INCOM_DATA_NOT_AUTH, + CALL_ACTIVE_DATA, + CALL_OTHERS, + CALL_NO_RESPONSE, + CALL_COMM_LINE_BUSY, + + CALL_LAST_ITEM +}; + + +enum getsms_ret_val_enum +{ + GETSMS_NO_SMS = 0, + GETSMS_UNREAD_SMS, + GETSMS_READ_SMS, + GETSMS_OTHER_SMS, + + GETSMS_NOT_AUTH_SMS, + GETSMS_AUTH_SMS, + + GETSMS_LAST_ITEM +}; + +typedef enum GSM_st_e { ERROR, IDLE, READY, ATTACHED, TCPSERVERWAIT, TCPCONNECTEDSERVER, TCPCONNECTEDCLIENT } EStatus; + + +class CGSM +{ + public: + + // Constructors + CGSM(const SoftwareSerial *pStream); + CGSM(const HardwareSerial *pStream); + + // Initialisation + virtual bool begin(const uint32_t nBaudRate); + + // Communication buffer + 1 for 0x00 termination + char m_arrayCommBuff[COMM_BUF_LEN + 1]; + + // Interface functions + void InitParam (uint8_t group); + inline void setStatus(EStatus nStatus) { m_nStatus = nStatus; }; + inline int16_t getStatus(){ return m_nStatus; }; + inline void SetCommLineStatus(uint8_t nNewStatus) {m_nCommLineStatus = nNewStatus;}; + inline uint8_t GetCommLineStatus(void) {return m_nCommLineStatus;}; + void RxInit(uint16_t nSartCommTimeout, uint16_t nInterCharTimeout); + uint8_t IsRxFinished(void); + uint8_t IsStringReceived(const __FlashStringHelper *fstrCompare); + uint8_t IsStringReceived(const char *strCompare); + uint8_t WaitResp(const uint16_t nSartCommTimeout, uint16_t nInterCharTimeout); + uint8_t WaitResp(uint16_t nSartCommTimeout, uint16_t nInterCharTimeout, const char *strExpectedResp); + uint8_t WaitResp(uint16_t nSartCommTimeout, uint16_t nInterCharTimeout, const __FlashStringHelper *fstrExpectedResp); + uint8_t SendATCmdWaitResp(const char *strATCommStr, uint16_t nSartCommTimeout, uint16_t nInterCharTimeout, const __FlashStringHelper *fstrResp, uint8_t nNumAttempts); + uint8_t SendATCmdWaitResp(const __FlashStringHelper *fstrATCommStr, uint16_t nSartCommTimeout, uint16_t nInterCharTimeout, const __FlashStringHelper *fstrResp, uint8_t nNumAttempts); + void SetSpeaker(const bool bOnOff); + + // User button methods + inline uint8_t IsUserButtonEnable(void) {return (m_nModuleStatus & STATUS_USER_BUTTON_ENABLE);}; + inline void DisableUserButton(void) {m_nModuleStatus &= ~STATUS_USER_BUTTON_ENABLE;}; + inline void EnableUserButton(void) {m_nModuleStatus |= STATUS_USER_BUTTON_ENABLE;}; + uint8_t IsUserButtonPushed(void); + + // Phonebook's methods + int8_t GetPhoneNumber(byte position, char *phone_number); + int8_t WritePhoneNumber(byte position, char *phone_number); + int8_t DelPhoneNumber(byte position); + int8_t ComparePhoneNumber(byte position, char *phone_number); + + uint8_t CheckRegistration(void); + bool IsRegistered(void); + bool IsInitialized(void); + + #ifdef DEBUG_LED_ENABLED + void BlinkDebugLED (uint8_t nNumOfBlink); + #endif + + #ifdef DEBUG_PRINT + void DebugPrint(const char *strToPrint, uint8_t nLastDebugPrint); + void DebugPrint(int16_t nToPrint, uint8_t nLastDebugPrint); + #endif + + protected: + // Constructors + CGSM(); // Don't want this constructor to be used + + // Status + EStatus m_nStatus; + uint8_t m_nModuleStatus, m_nCommLineStatus; + + // Serial source used to communicate with GSM + Stream* m_pStream; // Either a SoftwareSerial or a HardwareSerial object passed in through the constructor. + uint16_t m_nSizeofStream; // Size of the the SoftwareSerial or a HardwareSerial object so we can tell which type was used. + + // Variables connected with communication buffer + char *m_pCommBuff; // Pointer to the communication buffer + uint8_t m_nCommBuffLen; // Number of characters in the buffer + uint8_t m_nRxState; // Internal nState of rx nState machine + uint16_t m_nStartRecTimeout; // Max time out for starting reception + uint16_t m_nInterCharTimeout; // Previous time in milliseconds. + uint32_t m_nPrevTime; // Previous time in milliseconds. + + // Helper functions + char InitSMSMemory(void); + void beginSerial(const uint32_t nBaud); // Because class Stream does not have a begin(...) function. + bool isUsingSS(); // Using SoftwareSerial + bool isUsingHS(); // Using HardwareSerial + void turnOn(); // Attempt to turn the GSM on by grounding the power pin on the GSM chip. + bool isIP(const char* strCadena); +}; + +#endif diff --git a/GSMBase.cpp b/GSMBase.cpp new file mode 100644 index 0000000..06266e9 --- /dev/null +++ b/GSMBase.cpp @@ -0,0 +1 @@ +#include "GSMBase.h" diff --git a/GSMBase.h b/GSMBase.h new file mode 100644 index 0000000..8c0cc78 --- /dev/null +++ b/GSMBase.h @@ -0,0 +1,16 @@ +#ifndef __GSM_BASE_H_ +#define __GSM_BASE_H_ + +#include "SIM900.h" + +class CGSMBase +{ + public: + CGSMBase(CSIMCOM900& rSimComm900): m_rSimComm900(rSimComm900){}; + + protected: + CSIMCOM900& m_rSimComm900; +}; + +#endif + diff --git a/HWSerial.cpp b/HWSerial.cpp index 7522edc..cd5bbf1 100644 --- a/HWSerial.cpp +++ b/HWSerial.cpp @@ -1,346 +1,366 @@ -#include "HWSerial.h" -#ifdef MEGA -HWSerial::HWSerial() -{ - Serial1.begin(9600); - -} -/* -bool HWSerial::listen(){ - return Serial1.listen(); -} -*/ -void HWSerial::end() -{ - Serial1.end(); -} -/* -bool HWSerial::isListening(){ - return Serial1.isListening(); -} - -bool HWSerial::overflow(){ - return Serial1.overflow(); -} -*/ -void HWSerial::begin(long baud_rate) -{ - Serial1.begin(baud_rate); -} - -int HWSerial::peek() -{ - return Serial1.peek(); -} - -size_t HWSerial::write(uint8_t byte) -{ - return Serial1.write(byte); -} - -int HWSerial::read() -{ - return Serial1.read(); -} - -int HWSerial::available() -{ - return Serial1.available(); -} - -void HWSerial::flush() -{ - Serial1.flush(); -} - - -/**************************************/ - - - -size_t HWSerial::print(const __FlashStringHelper *ifsh) -{ - const char PROGMEM *p = (const char PROGMEM *)ifsh; - size_t n = 0; - while (1) { - unsigned char c = pgm_read_byte(p++); - if (c == 0) break; - n += write(c); - } - return n; -} - -size_t HWSerial::print(const String &s) -{ - size_t n = 0; - for (uint16_t i = 0; i < s.length(); i++) { - n += write(s[i]); - } - return n; -} - -size_t HWSerial::print(const char str[]) -{ - return write(str); -} - -size_t HWSerial::print(char c) -{ - return write(c); -} - -size_t HWSerial::print(unsigned char b, int base) -{ - return print((unsigned long) b, base); -} - -size_t HWSerial::print(int n, int base) -{ - return print((long) n, base); -} - -size_t HWSerial::print(unsigned int n, int base) -{ - return print((unsigned long) n, base); -} - -size_t HWSerial::print(long n, int base) -{ - if (base == 0) { - return write(n); - } else if (base == 10) { - if (n < 0) { - int t = print('-'); - n = -n; - return printNumber(n, 10) + t; - } - return printNumber(n, 10); - } else { - return printNumber(n, base); - } -} - -size_t HWSerial::print(unsigned long n, int base) -{ - if (base == 0) return write(n); - else return printNumber(n, base); -} - -size_t HWSerial::print(double n, int digits) -{ - return printFloat(n, digits); -} - -size_t HWSerial::println(const __FlashStringHelper *ifsh) -{ - size_t n = print(ifsh); - n += println(); - return n; -} - - -size_t HWSerial::println(void) -{ - size_t n = print('\r'); - n += print('\n'); - return n; -} - -size_t HWSerial::println(const String &s) -{ - size_t n = print(s); - n += println(); - return n; -} - - -size_t HWSerial::println(const char c[]) -{ - size_t n = print(c); - n += println(); - return n; -} - -size_t HWSerial::println(char c) -{ - size_t n = print(c); - n += println(); - return n; -} - -size_t HWSerial::println(unsigned char b, int base) -{ - size_t n = print(b, base); - n += println(); - return n; -} - -size_t HWSerial::println(int num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t HWSerial::println(unsigned int num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t HWSerial::println(long num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t HWSerial::println(unsigned long num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t HWSerial::println(double num, int digits) -{ - size_t n = print(num, digits); - n += println(); - return n; -} - - -/******************************/ -size_t HWSerial::write(const uint8_t *buffer, size_t size) -{ - size_t n = 0; - while (size--) { - n += write(*buffer++); - } - return n; -} - -size_t HWSerial::printNumber(unsigned long n, uint8_t base) -{ - char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. - char *str = &buf[sizeof(buf) - 1]; - - *str = '\0'; - - // prevent crash if called with base == 1 - if (base < 2) base = 10; - - do { - unsigned long m = n; - n /= base; - char c = m - base * n; - *--str = c < 10 ? c + '0' : c + 'A' - 10; - } while(n); - - return write(str); -} - -size_t HWSerial::printFloat(double number, uint8_t digits) -{ - size_t n = 0; - - // Handle negative numbers - if (number < 0.0) { - n += print('-'); - number = -number; - } - - // Round correctly so that print(1.999, 2) prints as "2.00" - double rounding = 0.5; - for (uint8_t i=0; i 0) { - n += print("."); - } - - // Extract digits from the remainder one at a time - while (digits-- > 0) { - remainder *= 10.0; - int toPrint = int(remainder); - n += print(toPrint); - remainder -= toPrint; - } - - return n; -} - - - -boolean HWSerial::find(char *target) -{ - return findUntil(target, NULL); -} - - -boolean HWSerial::findUntil(char *target, char *terminate) -{ - byte targetLen = strlen(target); - byte index = 0; // maximum target string length is 255 bytes - byte termIndex = 0; - byte termLen = (terminate == NULL ? 0 : strlen(terminate)); - char c; - - if( *target == 0) - return true; // return true if target is a null string - while( (c = read()) != 0) { - if( c == target[index]) { - if(++index >= targetLen) { // return true if all chars in the target match - return true; - } - } else { - index = 0; // reset index if any char does not match - } - if(termLen > 0 && c == terminate[termIndex]) { - if(++termIndex >= termLen) - return false; // return false if terminate string found before target string - } else - termIndex = 0; - } - return false; -} - - - -int HWSerial::getString( char *pre_string, char *post_string, char *buffer, int length) -{ - if( find(pre_string) ) { - int index = 0; - *buffer = 0; - while(index < length-1 ) { - char c = read(); - if( c == 0 ) { - return 0; // timeout returns 0 ! - } else if( c == *post_string ) { - - while (index < length) { - buffer[index] = '\0'; // terminate the string !!!!!!!!!!!IT DOESN'T WORK!!!!!!!!!!!!!!!!! - index++; - } - - //buffer[index]=0; - return index; // data got successfully - } else { - buffer[index++] = c; - } - } - buffer[index] = 0; - return index; // Note: buffer full before the closing post_string encountered - } - return 0; //failed to find the prestring -} -#endif +#include "HWSerial.h" + + +CHWSerial::CHWSerial(): _rSerial(Serial) +{ +} +CHWSerial::CHWSerial(HardwareSerial& rSerial): _rSerial(rSerial) +{ +} +void CHWSerial::end() +{ + _rSerial.end(); +} +void CHWSerial::begin(int32_t nBaudRate) +{ + _rSerial.begin(nBaudRate); +} + +int16_t CHWSerial::peek() +{ + return _rSerial.peek(); +} + +size_t CHWSerial::write(uint8_t uint8_t) +{ + return _rSerial.write(uint8_t); +} + +int16_t CHWSerial::read() +{ + return _rSerial.read(); +} + +int16_t CHWSerial::available() +{ + return _rSerial.available(); +} + +void CHWSerial::flush() +{ + _rSerial.flush(); +} + + + /**************************************/ + + + +size_t CHWSerial::print(const __FlashStringHelper *pstrIFSH) +{ + PGM_P pCh = (PGM_P)pstrIFSH; + size_t nSize = 0; + + while (true) + { + uint8_t cVal = pgm_read_byte(pCh++); + if (cVal == 0) + break; + nSize += write(cVal); + } + return nSize; +} + +size_t CHWSerial::print(const String &str) +{ + size_t nSize = 0; + for (uint16_t nI = 0; nI < str.length (); nI++) + { + nSize += write(str[nI]); + } + return nSize; +} + +size_t CHWSerial::print(const char str[]) +{ + return write(str); +} + +size_t CHWSerial::print(char cVal) +{ + return write(cVal); +} + +size_t CHWSerial::print(uint8_t nVal, int16_t nBase) +{ + return print((uint32_t) nVal, nBase); +} + +size_t CHWSerial::print(int16_t nVal, int16_t nBase) +{ + return print((int32_t) nVal, nBase); +} + +size_t CHWSerial::print(uint16_t nVal, int16_t nBase) +{ + return print((uint32_t) nVal, nBase); +} + +size_t CHWSerial::print(int32_t nVal, int16_t nBase) +{ + if (nBase == 0) + { + return write(nVal); + } + else if (nBase == 10) + { + if (nVal < 0) + { + int16_t nNum = print('-'); + nVal = -nVal; + return printNumber(nVal, 10) + nNum; + } + return printNumber(nVal, 10); + } + else + { + return printNumber(nVal, nBase); + } +} + +size_t CHWSerial::print(uint32_t nVal, int16_t nBase) +{ + if (nBase == 0) + return write(nVal); + else + return printNumber(nVal, nBase); +} + +size_t CHWSerial::print(double nVal, int16_t nDigits) +{ + return printFloat(nVal, nDigits); +} + +size_t CHWSerial::println(const __FlashStringHelper *pstrIFSH) +{ + size_t nSize = print(pstrIFSH); + nSize += println(); + return nSize; +} + + +size_t CHWSerial::println(void) +{ + size_t nSize = print('\r'); + nSize += print("\nSize"); + return nSize; +} + +size_t CHWSerial::println(const String &str) +{ + size_t nSize = print(str); + nSize += println(); + return nSize; +} + + +size_t CHWSerial::println(const char nVal[]) +{ + size_t nSize = print(nVal); + nSize += println(); + return nSize; +} + +size_t CHWSerial::println(char cVal) +{ + size_t nSize = print(cVal); + nSize += println(); + return nSize; +} + +size_t CHWSerial::println(uint8_t nVal, int16_t nBase) +{ + size_t nSize = print(nVal, nBase); + nSize += println(); + return nSize; +} + +size_t CHWSerial::println(int16_t nVal, int16_t nBase) +{ + size_t nSize = print(nVal, nBase); + nSize += println(); + return nSize; +} + +size_t CHWSerial::println(uint16_t nVal, int16_t nBase) +{ + size_t nSize = print(nVal, nBase); + nSize += println(); + return nSize; +} + +size_t CHWSerial::println(int32_t nVal, int16_t nBase) +{ + size_t nSize = print(nVal, nBase); + nSize += println(); + return nSize; +} + +size_t CHWSerial::println(uint32_t nVal, int16_t nBase) +{ + size_t nSize = print(nVal, nBase); + nSize += println(); + return nSize; +} + +size_t CHWSerial::println(double nVal, int16_t nDigits) +{ + size_t nSize = print(nVal, nDigits); + nSize += println(); + return nSize; +} + + +/******************************/ +size_t CHWSerial::write(const uint8_t *strBuff, size_t nSize) +{ + size_t nWritten = 0; + while (nSize--) + { + nWritten += write(*strBuff++); + } + return nWritten; +} + +size_t CHWSerial::printNumber(uint32_t nVal, uint8_t nBase) +{ + char strbuff[8 * sizeof(int32_t) + 1]; // Assumes 8-bit chars plus zero uint8_t. + char *str = &strbuff[sizeof(strbuff) - 1]; + + *str = '\0'; + + // prevent crash if called with nBase == 1 + if (nBase < 2) + nBase = 10; + + do + { + uint32_t nValTemp = nVal; + nVal /= nBase; + char cVal = nValTemp - nBase * nVal; + *--str = cVal < 10 ? cVal + '0' : cVal + 'A' - 10; + } + while (nVal); + + return write(str); +} + +size_t CHWSerial::printFloat(double dVal, uint8_t nDigits) +{ + size_t nSize = 0; + + // Handle negative numbers + if (dVal < 0.0) + { + nSize += print('-'); + dVal = -dVal; + } + + // Round correctly so that print(1.999, 2) prints as "2.00" + double dRounding = 0.5; + for (uint8_t nI=0; nI < nDigits; ++nI) + dRounding /= 10.0; + + dVal += dRounding; + + // Extract the integer part of the dVal and print it + uint32_t nIntPart = (uint32_t)dVal; + double dRemainder = dVal - (double)nIntPart; + nSize += print(nIntPart); + + // Print the decimal point, but only if there are nDigits beyond + if (nDigits > 0) + { + nSize += print("."); + } + // Extract nDigits from the dRemainder one at a time + while (nDigits-- > 0) + { + dRemainder *= 10.0; + int16_t nToPrint = int16_t(dRemainder); + nSize += print(nToPrint); + dRemainder -= nToPrint; + } + return nSize; +} + + +boolean CHWSerial::find(const char *strTarget) +{ + return findUntil(strTarget, NULL); +} + + +boolean CHWSerial::findUntil(const char *strTarget, const char *strTerminate) +{ + uint8_t nTargetLength = strlen(strTarget); + uint8_t nIndex = 0; // maximum strTarget string nLength is 255 bytes + uint8_t nTermIndex = 0; + uint8_t nTermLength = (strTerminate == NULL ? 0 : strlen(strTerminate)); + char cVal = 0; + + if (*strTarget == 0) + return true; // return true if strTarget is a null string + + while ((cVal = read()) != 0) + { + if (cVal == strTarget[nIndex]) + { + if (++nIndex >= nTargetLength) + { + // return true if all chars in the strTarget match + return true; + } + } + else + { + nIndex = 0; // reset nIndex if any char does not match + } + if ((nTermLength > 0) && (cVal == strTerminate[nTermIndex])) + { + if (++nTermIndex >= nTermLength) + return false; // return false if strTerminate string found before strTarget string + } + else + nTermIndex = 0; + } + return false; +} + + + +int16_t CHWSerial::getString(const char *strPre, const char *strPost, char *strBuff, int16_t nLength) + { + if (find(strPre)) + { + int16_t nIndex = 0; + *strBuff = 0; + + while (nIndex < nLength - 1) + { + char cVal = read(); + + if (cVal == 0) + { + return 0; // time out returns 0! + } + else if (cVal == *strPost) + { + while (nIndex < nLength ) + { + strBuff[nIndex] = '\0'; + nIndex++; + } + return nIndex; // data got successfully + } + else + { + strBuff[nIndex++] = cVal; + } + } + strBuff[nIndex] = 0; + return nIndex; // Note: strBuff full before the closing strPost encountered + } + return -1; //failed to find the prestring + } + \ No newline at end of file diff --git a/HWSerial.h b/HWSerial.h index 8e8fef2..38a7361 100644 --- a/HWSerial.h +++ b/HWSerial.h @@ -8,65 +8,58 @@ #include -class HWSerial { -#ifdef MEGA -private: - int write_error; - size_t printNumber(unsigned long, uint8_t); - size_t printFloat(double, uint8_t); +class CHWSerial +{ + private: + int16_t write_error; + size_t printNumber(uint32_t, uint8_t); + size_t printFloat(double, uint8_t); + HardwareSerial& _rSerial; -public: - HWSerial(); + CHWSerial(); - //bool listen(); - void end(); - /* - bool isListening(); - bool overflow(); - */ - int peek(); - virtual void begin(long baud_rate); + public: + CHWSerial(HardwareSerial& rSerial); - virtual size_t write(uint8_t byte); - size_t write(const char *str) { - return write((const uint8_t *)str, strlen(str)); - } - virtual size_t write(const uint8_t *buffer, size_t size); + void end(); + int16_t peek(); + virtual void begin(int32_t baud_rate); - virtual int read(); - virtual int available(); - virtual void flush(); + virtual size_t write(uint8_t byte); + size_t write(const char *str) { return write((const uint8_t *)str, strlen(str)); } + virtual size_t write(const uint8_t *strBuff, size_t size); - size_t print(const __FlashStringHelper *); - size_t print(const String &); - size_t print(const char[]); - size_t print(char); - size_t print(unsigned char, int = DEC); - size_t print(int, int = DEC); - size_t print(unsigned int, int = DEC); - size_t print(long, int = DEC); - size_t print(unsigned long, int = DEC); - size_t print(double, int = 2); + virtual int16_t read(); + virtual int16_t available(); + virtual void flush(); + size_t print(const __FlashStringHelper *); + size_t print(const String &); + size_t print(const char[]); + size_t print(char); + size_t print(uint8_t, int16_t = DEC); + size_t print(int16_t, int16_t = DEC); + size_t print(uint16_t, int16_t = DEC); + size_t print(int32_t, int16_t = DEC); + size_t print(uint32_t, int16_t = DEC); + size_t print(double, int16_t = 2); - size_t println(const __FlashStringHelper *); - size_t println(const String &s); - size_t println(const char[]); - size_t println(char); - size_t println(unsigned char, int = DEC); - size_t println(int, int = DEC); - size_t println(unsigned int, int = DEC); - size_t println(long, int = DEC); - size_t println(unsigned long, int = DEC); - size_t println(double, int = 2); - size_t println(void); + size_t println(const __FlashStringHelper *); + size_t println(const String &s); + size_t println(const char[]); + size_t println(char); + size_t println(uint8_t, int16_t = DEC); + size_t println(int16_t, int16_t = DEC); + size_t println(uint16_t, int16_t = DEC); + size_t println(int32_t, int16_t = DEC); + size_t println(uint32_t, int16_t = DEC); + size_t println(double, int16_t = 2); - int getString( char *pre_string, char *post_string, char *buffer, int length); - boolean find(char *target); - boolean findUntil(char *target, char *terminate); - -#endif + size_t println(void); + int16_t getString(const char *strPre, const char *strPost, char *strBuff, int16_t nLength); + boolean find(const char *strTarget); + boolean findUntil(const char *strTarget, const char *strTerminate); }; #endif \ No newline at end of file diff --git a/LOG.cpp b/LOG.cpp index 7180f0f..0656249 100644 --- a/LOG.cpp +++ b/LOG.cpp @@ -1,59 +1,65 @@ /* - LOG.cpp - Library for standard logging convention. + CLog.cpp - Library for standard logging convention. Created by Meir Michanie, June 9, 2010. Released into the public domain. Version 0.1 */ -#include "LOG.h" +#include "Log.h" -LOG::LOG(int level) +CLog::CLog(uint8_t nLevel) { - setLevel(level); + setLevel(nLevel); } -void LOG::DATA(const char* string) +void CLog::DATA(const char* strText) { - if (_level > 4) { - Serial.print(string); - } + if (m_nLevel > 4) + { + Serial.print(strText); + } } -void LOG::DATA(int number) +void CLog::DATA(uint8_t number) { - if (_level > 4) { - Serial.print(number); - } + if (m_nLevel > 4) + { + Serial.print(number); + } } -void LOG::DEBUG(const char* string) +void CLog::DEBUG(const char* strText) { - if (_level > 3) { - Serial.print("\n[DEBUG]: "); - Serial.println(string); - } + if (m_nLevel > 3) + { + Serial.print("\n[DEBUG]: "); + Serial.println(strText); + } } -void LOG::INFO(const char* string) +void CLog::INFO(const char* strText) { - if (_level > 2) { - Serial.print("\n[INFO]: "); - Serial.println(string); - } + if (m_nLevel > 2) + { + Serial.print("\n[INFO]: "); + Serial.println(strText); + } } -void LOG::WARNING(const char* string) +void CLog::WARNING(const char* strText) { - if (_level > 1) { - Serial.print("\n[WARNING]: "); - Serial.println(string); - } + if (m_nLevel > 1) + { + Serial.print("\n[WARNING]: "); + Serial.println(strText); + } } -void LOG::CRITICAL(const char* string) +void CLog::CRITICAL(const char* strText) { - if (_level > 0) { - Serial.print("\n[CRITICAL]: "); - Serial.println(string); - } -} + if (m_nLevel > 0) + { + Serial.print("\n[CRITICAL]: "); + Serial.println(strText); + } +} diff --git a/LOG.h b/LOG.h index ae23942..cd1e577 100644 --- a/LOG.h +++ b/LOG.h @@ -1,33 +1,24 @@ -/* - LOG.h - Library for standard logging convention. - Created by Meir Michanie, June 9, 2010. - Released into the public domain. - Version 0.1 -*/ +#ifndef __LOG_H +#define __LOG_H -#ifndef LOG_h -#define LOG_h #include "Arduino.h" -class LOG { -public: - LOG(int level); - void DEBUG(const char* string); - void INFO(const char* string); - void WARNING(const char* string); - void CRITICAL(const char* string); - void DATA(const char* string); - void DATA(int number); +class CLog +{ + public: + CLog(uint8_t nLevel); + void DEBUG(const char* strText); + void INFO(const char* strText); + void WARNING(const char* strText); + void CRITICAL(const char* strText); + void DATA(const char* strText); + void DATA(uint8_t number); - inline int getLevel(void) { - return _level; - } - inline void setLevel(int level) { - _level = level; - } - -private: - int _level; + inline uint8_t getLevel(void) { return m_nLevel; } + inline void setLevel(uint8_t nLevel) { m_nLevel = nLevel; } + + private: + uint8_t m_nLevel; }; -#endif +#endif diff --git a/README b/README index 108739f..338ee0a 100644 --- a/README +++ b/README @@ -1,8 +1,7 @@ GSM GPRS Shield for Arduino Uno For informations and support: -http://www.gsmlib.org -http://code.google.com/p/gsm-shield-arduino/ (no longer supported) +http://code.google.com/p/gsm-shield-arduino/ http://www.open-electronics.org/arduino-gsm-shield/ http://www.futurashop.it/ diff --git a/SIM900.cpp b/SIM900.cpp index fbd73cd..8fbc3d2 100644 --- a/SIM900.cpp +++ b/SIM900.cpp @@ -1,1011 +1,271 @@ -#include "SIM900.h" -#include "Streaming.h" - -#define _GSM_CONNECTION_TOUT_ 5 -#define _TCP_CONNECTION_TOUT_ 20 -#define _GSM_DATA_TOUT_ 10 - -//#define RESETPIN 7 - -SIMCOM900 gsm; -SIMCOM900::SIMCOM900() {}; -SIMCOM900::~SIMCOM900() {}; - -/********************************************************** -Function: This function premits to wake up the module - (only for SIM908) when it goes in energy saving - mode. - -Author: Marco Martines -Created: unknown -Modified: 18/02/2014 - -Output: none - -Comments: It would be nice to call this function - automatically when gsm.begin is called (of course - only if a SIM908 is used). -**********************************************************/ - -char SIMCOM900::forceON() -{ - char ret_val=0; - char *p_char; - char *p_char1; - - SimpleWriteln(F("AT+CREG?")); - WaitResp(5000, 100, str_ok); - if(IsStringReceived(str_ok)) { - ret_val=1; - } - - p_char = strchr((char *)(gsm.comm_buf),','); - p_char1 = p_char+1; - *(p_char1+2)=0; - p_char = strchr((char *)(p_char1), ','); - if (p_char != NULL) { - *p_char = 0; - } - - if((*p_char1)=='4') { - digitalWrite(GSM_ON, HIGH); - delay(1200); - digitalWrite(GSM_ON, LOW); - delay(10000); - ret_val=2; - } - - return ret_val; -} - -int SIMCOM900::configandwait(char* pin) -{ - int connCode; - //_tf.setTimeout(_GSM_CONNECTION_TOUT_); - - if(pin) setPIN(pin); //syv - - // Try 10 times to register in the network. Note this can take some time! - for(int i=0; i<10; i++) { - //Ask for register status to GPRS network. - SimpleWriteln(F("AT+CGREG?")); - - //Se espera la unsolicited response de registered to network. - while(gsm.WaitResp(5000, 50, "+CGREG: 0,")!=RX_FINISHED_STR_RECV) - //while (_tf.find("+CGREG: 0,")) // CHANGE!!!! - { - //connCode=_tf.getValue(); - connCode=_cell.read(); - if((connCode==1)||(connCode==5)) { - setStatus(READY); - - SimpleWriteln(F("AT+CMGF=1")); //SMS text mode. - delay(200); - // Buah, we should take this to readCall() - SimpleWriteln(F("AT+CLIP=1")); //SMS text mode. - delay(200); - //_cell << "AT+QIDEACT" << _DEC(cr) << endl; //To make sure not pending connection. - //delay(1000); - - return 1; - } - } - } - return 0; -} - -/** - * SIMCOM900::read(char* buffer, int buffersize) - * - * Waits for data to be readable from the gsm module, reads data until - * no more is available or the buffer has been filled - * - * returns number of bytes read - * - */ -int SIMCOM900::read(char* result, int resultlength) -{ - char temp; - int i=0; - -#ifdef DEBUG_ON - Serial.print(F("Starting read..\nWaiting for Data..")); -#endif - // Wait until we start receiving data - while(gsm.available()<1) { - delay(100); -#ifdef DEBUG_ON - Serial.print(F(".")); -#endif - } - - while(gsm.available()>0 && i<(resultlength-1)) { - temp=_cell.read(); - if(temp>0) { -#ifdef DEBUG_ON - Serial.print(temp); -#endif - result[i]=temp; - i++; - } - delay(1); - } - - // Terminate the string - result[resultlength-1]='\0'; - -#ifdef DEBUG_ON - Serial.println(F("\nDone..")); -#endif - return i; -} - -int SIMCOM900::readCellData(int &mcc, int &mnc, long &lac, long &cellid) -{ - if (getStatus()==IDLE) - return 0; - - //_tf.setTimeout(_GSM_DATA_TOUT_); - //_cell.flush(); - SimpleWriteln(F("AT+QENG=1,0")); - SimpleWriteln(F("AT+QENG?")); - if(gsm.WaitResp(5000, 50, "+QENG")!=RX_FINISHED_STR_NOT_RECV) - return 0; - - //mcc=_tf.getValue(); // The first one is 0 - mcc=_cell.read(); - //mcc=_tf.getValue(); - mcc=_cell.read(); - //mnc=_tf.getValue(); - mnc=_cell.read(); - //lac=_tf.getValue(); - lac=_cell.read(); - //cellid=_tf.getValue(); - cellid=_cell.read(); - - gsm.WaitResp(5000, 50, "+OK"); - SimpleWriteln(F("AT+QENG=1,0")); - gsm.WaitResp(5000, 50, "+OK"); - return 1; -} - -boolean SIMCOM900::readSMS(char* msg, int msglength, char* number, int nlength) -{ - Serial.println(F("This method is deprecated! Please use GetSMS in the SMS class.")); - long index; - char *p_char; - char *p_char1; - - /* - if (getStatus()==IDLE) - return false; - */ -#ifdef UNO - _tf.setTimeout(_GSM_DATA_TOUT_); -#endif - //_cell.flush(); - WaitResp(500, 500); - SimpleWriteln(F("AT+CMGL=\"REC UNREAD\",1")); - - WaitResp(5000, 500); - if(gsm.IsStringReceived("+CMGL")) { - - //index - p_char = strchr((char *)(gsm.comm_buf),'+CMGL'); - p_char1 = p_char+3; //we are on the first char of string - p_char = p_char1+1; - *p_char = 0; - index=atoi(p_char1); - - p_char1 = p_char+1; - p_char = strstr((char *)(p_char1), "\",\""); - p_char1 = p_char+3; - p_char = strstr((char *)(p_char1), "\",\""); - if (p_char != NULL) { - *p_char = 0; - } - strcpy(number, (char *)(p_char1)); - ////// - - p_char1 = p_char+3; - p_char = strstr((char *)(p_char1), "\",\""); - p_char1 = p_char+3; - - p_char = strstr((char *)(p_char1), "\n"); - p_char1 = p_char+1; - p_char = strstr((char *)(p_char1), "\n"); - if (p_char != NULL) { - *p_char = 0; - } - strcpy(msg, (char *)(p_char1)); - - // #ifdef UNO - // index=_tf.getValue(); - // #endif - // #ifdef MEGA - //index=_cell.read(); - // #endif - // Serial.println("DEBUG"); - // #ifdef UNO - // _tf.getString("\",\"", "\"", number, nlength); - // #endif - // Serial.println("PRIMA"); - // #ifdef MEGA - // _cell.getString("\",\"", "\"", number, nlength); - // #endif - // Serial.println("DEBUG"); - // #ifdef UNO - // _tf.getString("\n", "\nOK", msg, msglength); - // #endif - // #ifdef MEGA - // _cell.getString("\n", "\nOK", msg, msglength); - // #endif - - SimpleWrite(F("AT+CMGD=")); - SimpleWriteln(index); - // Serial.print("VAL= "); - // Serial.println(index); - gsm.WaitResp(5000, 50, str_ok); - return true; - }; - return false; -}; - -boolean SIMCOM900::readCall(char* number, int nlength) -{ - int index; - - if (getStatus()==IDLE) - return false; - - //_tf.setTimeout(_GSM_DATA_TOUT_); - if(gsm.WaitResp(5000, 50, "+CLIP: \"")!=RX_FINISHED_STR_RECV) - //if(_tf.find("+CLIP: \"")) - { -#ifdef UNO - _tf.getString("", "\"", number, nlength); -#endif -#ifdef MEGA - _cell.getString("", "\"", number, nlength); -#endif - SimpleWriteln(F("ATH")); - delay(1000); - //_cell.flush(); - return true; - }; - return false; -}; - -boolean SIMCOM900::call(char* number, unsigned int milliseconds) -{ - if (getStatus()==IDLE) - return false; - - //_tf.setTimeout(_GSM_DATA_TOUT_); - - SimpleWrite(F("ATD")); - SimpleWrite(number); - SimpleWriteln(F(";")); - delay(milliseconds); - SimpleWriteln(F("ATH")); - - return true; - -} - -int SIMCOM900::setPIN(char *pin) -{ - //Status = READY or ATTACHED. - if((getStatus() != IDLE)) - return 2; - - //_tf.setTimeout(_GSM_DATA_TOUT_); //Timeout for expecting modem responses. - - //_cell.flush(); - - //AT command to set PIN. - SimpleWrite(F("AT+CPIN=")); - SimpleWriteln(pin); - - //Expect str_ok. - - if(gsm.WaitResp(5000, 50, str_ok)!=RX_FINISHED_STR_NOT_RECV) - return 0; - else - return 1; -} - -int SIMCOM900::changeNSIPmode(char mode) -{ - //_tf.setTimeout(_TCP_CONNECTION_TOUT_); - - //if (getStatus()!=ATTACHED) - // return 0; - - //_cell.flush(); - - SimpleWrite(F("AT+QIDNSIP=")); - SimpleWriteln(mode); - if(gsm.WaitResp(5000, 50, str_ok)!=RX_FINISHED_STR_NOT_RECV) return 0; - //if(!_tf.find(str_ok)) return 0; - - return 1; -} - -int SIMCOM900::getCCI(char *cci) -{ - //Status must be READY - if((getStatus() != READY)) - return 2; - - //_tf.setTimeout(_GSM_DATA_TOUT_); //Timeout for expecting modem responses. - - //_cell.flush(); - - //AT command to get CCID. - SimpleWriteln(F("AT+QCCID")); - - //Read response from modem -#ifdef UNO - _tf.getString("AT+QCCID\r\r\r\n","\r\n",cci, 21); -#endif -#ifdef MEGA - _cell.getString("AT+QCCID\r\r\r\n","\r\n",cci, 21); -#endif - - //Expect str_ok. - if(gsm.WaitResp(5000, 50, str_ok)!=RX_FINISHED_STR_NOT_RECV) - return 0; - else - return 1; -} - -int SIMCOM900::getIMEI(char *imei) -{ - - //_tf.setTimeout(_GSM_DATA_TOUT_); //Timeout for expecting modem responses. - - //_cell.flush(); - - //AT command to get IMEI. - SimpleWriteln(F("AT+GSN")); - - //Read response from modem -//#ifdef UNO -// _tf.getString("\r\n","\r\n",imei, 16); -//#endif -//#ifdef MEGA -// _cell.getString("\r\n","\r\n",imei, 16); -//#endif - - //Expect str_ok. - if(gsm.WaitResp(5000, 50, str_ok)!=RX_FINISHED_STR_NOT_RECV){ - memcpy(imei,gsm.comm_buf+2,15); - imei[15]='\0'; - return 0; - }else - return 1; -} - -int SIMCOM900::available() -{ - return _cell.available(); -} - -uint8_t SIMCOM900::read() -{ - return _cell.read(); -} - -void SIMCOM900::SimpleRead() -{ - char datain; - if(_cell.available()>0) { - datain=_cell.read(); - if(datain>0) { - Serial.print(datain); - } - } -} - -void SIMCOM900::SimpleWrite(char *comm) -{ - _cell.print(comm); -} - -void SIMCOM900::SimpleWrite(const char *comm) -{ - _cell.print(comm); -} - -void SIMCOM900::SimpleWrite(int comm) -{ - _cell.print(comm); -} - -void SIMCOM900::SimpleWrite(const __FlashStringHelper *pgmstr) -{ - _cell.print(pgmstr); -} - -void SIMCOM900::SimpleWriteln(char *comm) -{ - _cell.println(comm); -} - -void SIMCOM900::SimpleWriteln(const __FlashStringHelper *pgmstr) -{ - _cell.println(pgmstr); -} - -void SIMCOM900::SimpleWriteln(char const *comm) -{ - _cell.println(comm); -} - -void SIMCOM900::SimpleWriteln(int comm) -{ - _cell.println(comm); -} - -void SIMCOM900::WhileSimpleRead() -{ - char datain; - while(_cell.available()>0) { - datain=_cell.read(); - if(datain>0) { - Serial.print(datain); - } - } -} - -//--------------------------------------------- -/********************************************************** -Turns on/off the speaker - -off_on: 0 - off - 1 - on -**********************************************************/ -void GSM::SetSpeaker(byte off_on) -{ - if (CLS_FREE != GetCommLineStatus()) return; - SetCommLineStatus(CLS_ATCMD); - if (off_on) { - //SendATCmdWaitResp("AT#GPIO=5,1,2", 500, 50, "#GPIO:", 1); - } else { - //SendATCmdWaitResp("AT#GPIO=5,0,2", 500, 50, "#GPIO:", 1); - } - SetCommLineStatus(CLS_FREE); -} - - -byte GSM::IsRegistered(void) -{ - return (module_status & STATUS_REGISTERED); -} - -byte GSM::IsInitialized(void) -{ - return (module_status & STATUS_INITIALIZED); -} - - -/********************************************************** -Method checks if the GSM module is registered in the GSM net -- this method communicates directly with the GSM module - in contrast to the method IsRegistered() which reads the - flag from the module_status (this flag is set inside this method) - -- must be called regularly - from 1sec. to cca. 10 sec. - -return values: - REG_NOT_REGISTERED - not registered - REG_REGISTERED - GSM module is registered - REG_NO_RESPONSE - GSM doesn't response - REG_COMM_LINE_BUSY - comm line between GSM module and Arduino is not free - for communication -**********************************************************/ -byte GSM::CheckRegistration(void) -{ - byte status; - byte ret_val = REG_NOT_REGISTERED; - - if (CLS_FREE != GetCommLineStatus()) return (REG_COMM_LINE_BUSY); - SetCommLineStatus(CLS_ATCMD); - _cell.println(F("AT+CREG?")); - // 5 sec. for initial comm tmout - // 50 msec. for inter character timeout - status = WaitResp(5000, 50); - - if (status == RX_FINISHED) { - // something was received but what was received? - // --------------------------------------------- - if(IsStringReceived("+CREG: 0,1") - || IsStringReceived("+CREG: 0,5")) { - // it means module is registered - // ---------------------------- - module_status |= STATUS_REGISTERED; - - - // in case GSM module is registered first time after reset - // sets flag STATUS_INITIALIZED - // it is used for sending some init commands which - // must be sent only after registration - // -------------------------------------------- - if (!IsInitialized()) { - module_status |= STATUS_INITIALIZED; - SetCommLineStatus(CLS_FREE); - InitParam(PARAM_SET_1); - } - ret_val = REG_REGISTERED; - } else { - // NOT registered - // -------------- - module_status &= ~STATUS_REGISTERED; - ret_val = REG_NOT_REGISTERED; - } - } else { - // nothing was received - // -------------------- - ret_val = REG_NO_RESPONSE; - } - SetCommLineStatus(CLS_FREE); - - - return (ret_val); -} - - -/********************************************************** -Method sets speaker volume - -speaker_volume: volume in range 0..14 - -return: - ERROR ret. val: - --------------- - -1 - comm. line to the GSM module is not free - -2 - GSM module did not answer in timeout - -3 - GSM module has answered "ERROR" string - - OK ret val: - ----------- - 0..14 current speaker volume -**********************************************************/ -/* -char GSM::SetSpeakerVolume(byte speaker_volume) -{ - - char ret_val = -1; - - if (CLS_FREE != GetCommLineStatus()) return (ret_val); - SetCommLineStatus(CLS_ATCMD); - // remember set value as last value - if (speaker_volume > 14) speaker_volume = 14; - // select speaker volume (0 to 14) - // AT+CLVL=X X<0..14> - _cell.print("AT+CLVL="); - _cell.print((int)speaker_volume); - _cell.print("\r"); // send - // 10 sec. for initial comm tmout - // 50 msec. for inter character timeout - if (RX_TMOUT_ERR == WaitResp(10000, 50)) { - ret_val = -2; // ERROR - } - else { - if(IsStringReceived(str_ok)) { - last_speaker_volume = speaker_volume; - ret_val = last_speaker_volume; // OK - } - else ret_val = -3; // ERROR - } - - SetCommLineStatus(CLS_FREE); - return (ret_val); -} -*/ -/********************************************************** -Method increases speaker volume - -return: - ERROR ret. val: - --------------- - -1 - comm. line to the GSM module is not free - -2 - GSM module did not answer in timeout - -3 - GSM module has answered "ERROR" string - - OK ret val: - ----------- - 0..14 current speaker volume -**********************************************************/ -/* -char GSM::IncSpeakerVolume(void) -{ - char ret_val; - byte current_speaker_value; - - current_speaker_value = last_speaker_volume; - if (current_speaker_value < 14) { - current_speaker_value++; - ret_val = SetSpeakerVolume(current_speaker_value); - } - else ret_val = 14; - - return (ret_val); -} -*/ -/********************************************************** -Method decreases speaker volume - -return: - ERROR ret. val: - --------------- - -1 - comm. line to the GSM module is not free - -2 - GSM module did not answer in timeout - -3 - GSM module has answered "ERROR" string - - OK ret val: - ----------- - 0..14 current speaker volume -**********************************************************/ -/* -char GSM::DecSpeakerVolume(void) -{ - char ret_val; - byte current_speaker_value; - - current_speaker_value = last_speaker_volume; - if (current_speaker_value > 0) { - current_speaker_value--; - ret_val = SetSpeakerVolume(current_speaker_value); - } - else ret_val = 0; - - return (ret_val); -} -*/ - -/********************************************************** -Method sends DTMF signal -This function only works when call is in progress - -dtmf_tone: tone to send 0..15 - -return: - ERROR ret. val: - --------------- - -1 - comm. line to the GSM module is not free - -2 - GSM module didn't answer in timeout - -3 - GSM module has answered "ERROR" string - - OK ret val: - ----------- - 0.. tone -**********************************************************/ -/* -char GSM::SendDTMFSignal(byte dtmf_tone) -{ - char ret_val = -1; - - if (CLS_FREE != GetCommLineStatus()) return (ret_val); - SetCommLineStatus(CLS_ATCMD); - // e.g. AT+VTS=5 - _cell.print("AT+VTS="); - _cell.print((int)dtmf_tone); - _cell.print("\r"); - // 1 sec. for initial comm tmout - // 50 msec. for inter character timeout - if (RX_TMOUT_ERR == WaitResp(1000, 50)) { - ret_val = -2; // ERROR - } - else { - if(IsStringReceived(str_ok)) { - ret_val = dtmf_tone; // OK - } - else ret_val = -3; // ERROR - } - - SetCommLineStatus(CLS_FREE); - return (ret_val); -} -*/ - -/********************************************************** -Method returns state of user button - - -return: 0 - not pushed = released - 1 - pushed -**********************************************************/ -byte GSM::IsUserButtonPushed(void) -{ - byte ret_val = 0; - if (CLS_FREE != GetCommLineStatus()) return(0); - SetCommLineStatus(CLS_ATCMD); - //if (AT_RESP_OK == SendATCmdWaitResp("AT#GPIO=9,2", 500, 50, "#GPIO: 0,0", 1)) { - // user button is pushed - // ret_val = 1; - //} - //else ret_val = 0; - //SetCommLineStatus(CLS_FREE); - //return (ret_val); -} - - - -/********************************************************** -Method reads phone number string from specified SIM position - -position: SMS position <1..20> - -return: - ERROR ret. val: - --------------- - -1 - comm. line to the GSM module is not free - -2 - GSM module didn't answer in timeout - -3 - position must be > 0 - phone_number is empty string - - OK ret val: - ----------- - 0 - there is no phone number on the position - 1 - phone number was found - phone_number is filled by the phone number string finished by 0x00 - so it is necessary to define string with at least - 15 bytes(including also 0x00 termination character) - -an example of usage: - GSM gsm; - char phone_num[20]; // array for the phone number string - - if (1 == gsm.GetPhoneNumber(1, phone_num)) { - // valid phone number on SIM pos. #1 - // phone number string is copied to the phone_num array - #ifdef DEBUG_PRINT - gsm.DebugPrint("DEBUG phone number: ", 0); - gsm.DebugPrint(phone_num, 1); - #endif - } - else { - // there is not valid phone number on the SIM pos.#1 - #ifdef DEBUG_PRINT - gsm.DebugPrint("DEBUG there is no phone number", 1); - #endif - } -**********************************************************/ - - -char GSM::GetPhoneNumber(byte position, char *phone_number) -{ - char ret_val = -1; - - char *p_char; - char *p_char1; - - if (position == 0) return (-3); - if (CLS_FREE != GetCommLineStatus()) return (ret_val); - SetCommLineStatus(CLS_ATCMD); - ret_val = 0; // not found yet - phone_number[0] = 0; // phone number not found yet => empty string - - //send "AT+CPBR=XY" - where XY = position - _cell.print(F("AT+CPBR=")); - _cell.print((int)position); - _cell.print("\r"); - - // 5000 msec. for initial comm tmout - // 50 msec. for inter character timeout - switch (WaitResp(5000, 50, "+CPBR")) { - case RX_TMOUT_ERR: - // response was not received in specific time - ret_val = -2; - break; - - case RX_FINISHED_STR_RECV: - // response in case valid phone number stored: - // +CPBR: ,,, - // OK - - // response in case there is not phone number: - // OK - p_char = strstr((char *)(comm_buf),",\""); - if (p_char != NULL) { - p_char++; - p_char++; // we are on the first phone number character - // find out '"' as finish character of phone number string - p_char1 = strchr((char *)(p_char),'"'); - if (p_char1 != NULL) { - *p_char1 = 0; // end of string - } - // extract phone number string - strcpy(phone_number, (char *)(p_char)); - // output value = we have found out phone number string - ret_val = 1; - } - break; - - case RX_FINISHED_STR_NOT_RECV: - // only OK or ERROR => no phone number - ret_val = 0; - break; - } - - SetCommLineStatus(CLS_FREE); - return (ret_val); -} - -/********************************************************** -Method writes phone number string to the specified SIM position - -position: SMS position <1..20> -phone_number: phone number string for the writing - -return: - ERROR ret. val: - --------------- - -1 - comm. line to the GSM module is not free - -2 - GSM module didn't answer in timeout - -3 - position must be > 0 - - OK ret val: - ----------- - 0 - phone number was not written - 1 - phone number was written -**********************************************************/ -char GSM::WritePhoneNumber(byte position, char *phone_number) -{ - char ret_val = -1; - - if (position == 0) return (-3); - if (CLS_FREE != GetCommLineStatus()) return (ret_val); - SetCommLineStatus(CLS_ATCMD); - ret_val = 0; // phone number was not written yet - - //send: AT+CPBW=XY,"00420123456789" - // where XY = position, - // "00420123456789" = phone number string - _cell.print(F("AT+CPBW=")); - _cell.print((int)position); - _cell.print(F(",\"")); - _cell.print(phone_number); - _cell.print(F("\"\r")); - - // 5000 msec. for initial comm tmout - // 50 msec. for inter character timeout - switch (WaitResp(5000, 50, str_ok)) { - case RX_TMOUT_ERR: - // response was not received in specific time - break; - - case RX_FINISHED_STR_RECV: - // response is OK = has been written - ret_val = 1; - break; - - case RX_FINISHED_STR_NOT_RECV: - // other response: e.g. ERROR - break; - } - - SetCommLineStatus(CLS_FREE); - return (ret_val); -} - - -/********************************************************** -Method del phone number from the specified SIM position - -position: SMS position <1..20> - -return: - ERROR ret. val: - --------------- - -1 - comm. line to the GSM module is not free - -2 - GSM module didn't answer in timeout - -3 - position must be > 0 - - OK ret val: - ----------- - 0 - phone number was not deleted - 1 - phone number was deleted -**********************************************************/ -char GSM::DelPhoneNumber(byte position) -{ - char ret_val = -1; - - if (position == 0) return (-3); - if (CLS_FREE != GetCommLineStatus()) return (ret_val); - SetCommLineStatus(CLS_ATCMD); - ret_val = 0; // phone number was not written yet - - //send: AT+CPBW=XY - // where XY = position - _cell.print(F("AT+CPBW=")); - _cell.print((int)position); - _cell.print(F("\r")); - - // 5000 msec. for initial comm tmout - // 50 msec. for inter character timeout - switch (WaitResp(5000, 50, str_ok)) { - case RX_TMOUT_ERR: - // response was not received in specific time - break; - - case RX_FINISHED_STR_RECV: - // response is OK = has been written - ret_val = 1; - break; - - case RX_FINISHED_STR_NOT_RECV: - // other response: e.g. ERROR - break; - } - - SetCommLineStatus(CLS_FREE); - return (ret_val); -} - - - - - -/********************************************************** -Function compares specified phone number string -with phone number stored at the specified SIM position - -position: SMS position <1..20> -phone_number: phone number string which should be compare - -return: - ERROR ret. val: - --------------- - -1 - comm. line to the GSM module is not free - -2 - GSM module didn't answer in timeout - -3 - position must be > 0 - - OK ret val: - ----------- - 0 - phone numbers are different - 1 - phone numbers are the same - - -an example of usage: - if (1 == gsm.ComparePhoneNumber(1, "123456789")) { - // the phone num. "123456789" is stored on the SIM pos. #1 - // phone number string is copied to the phone_num array - #ifdef DEBUG_PRINT - gsm.DebugPrint("DEBUG phone numbers are the same", 1); - #endif - } - else { - #ifdef DEBUG_PRINT - gsm.DebugPrint("DEBUG phone numbers are different", 1); - #endif - } -**********************************************************/ -char GSM::ComparePhoneNumber(byte position, char *phone_number) -{ - char ret_val = -1; - char sim_phone_number[20]; - - - ret_val = 0; // numbers are not the same so far - if (position == 0) return (-3); - if (1 == GetPhoneNumber(position, sim_phone_number)) { - //Serial.print("CHIAMANTE "); - //Serial.println(phone_number); - //Serial.print("SALVATO "); - //Serial.println(sim_phone_number); - - // there is a valid number at the spec. SIM position - // ------------------------------------------------- - if (0 == strcmp(phone_number, sim_phone_number)) { - // phone numbers are the same - // -------------------------- - ret_val = 1; - } - } - return (ret_val); -} - -//----------------------------------------------------- +#include "SIM900.h" +#include "Streaming.h" + +#define _GSM_CONNECTION_TOUT_ 5 +#define _TCP_CONNECTION_TOUT_ 20 +#define _GSM_DATA_TOUT_ 10 + +//#define RESETPIN 7 + +CSIMCOM900::CSIMCOM900(){}; + +CSIMCOM900::CSIMCOM900(const SoftwareSerial *pStream): CGSM(pStream) +{ +} + +CSIMCOM900::CSIMCOM900(const HardwareSerial *pStream): CGSM(pStream) +{ +} + +CSIMCOM900::~CSIMCOM900(){}; + +char CSIMCOM900::forceON() +{ + char cRetVal = 0; + char* str1 = NULL; + char* str2 = NULL; + + SimpleWriteln(F("AT+CREG?")); + WaitResp(5000, 100, F("OK")); + if (IsStringReceived(F("OK"))) + { + cRetVal=1; + } + //BCL + str1 = strchr((char *)(m_arrayCommBuff),','); + str2 = str1+1; //we are on the first char of BCS + *(str2+2)=0; + str1 = strchr((char *)(str2), ','); + if (str1 != NULL) { + *str1 = 0; + } + + if ((*str2)=='4'){ + digitalWrite(GSM_ON, HIGH); + delay(1200); + digitalWrite(GSM_ON, LOW); + delay(10000); + cRetVal=2; + } + + return cRetVal; +} + +int16_t CSIMCOM900::configandwait(char* pin) +{ + int16_t connCode; + //_tf.setTimeout(_GSM_CONNECTION_TOUT_); + + if (pin) setPIN(pin); //syv + + // Try 10 times to register in the network. Note this can take some time! + for(int16_t nI=0; nI<10; nI++) + { + //Ask for register nStatus to GPRS network. + SimpleWriteln(F("AT+CGREG?")); + + //Se espera la unsolicited response de registered to network. + while(WaitResp(5000, 50, "+CGREG: 0,")!=RX_FINISHED_STR_RECV) + //while (_tf.find("+CGREG: 0,")) // CHANGE!!!! + { + //connCode=_tf.getValue(); + connCode=m_pStream->read(); + if ((connCode==1)||(connCode==5)) + { + setStatus(READY); + + SimpleWriteln(F("AT+CMGF=1")); //SMS text mode. + delay(200); + // Buah, we should take this to readCall() + SimpleWriteln(F("AT+CLIP=1")); //SMS text mode. + delay(200); + //_cell << "AT+QIDEACT" << _DEC(cr) << endl; //To make sure not pending connection. + //delay(1000); + + return 1; + } + } + } + return 0; +} + +uint16_t CSIMCOM900::read(char* strResult, const uint16_t nLength) +{ + char cTemp = 0; + uint16_t nI = 0; + + for (nI = 0; nI < nLength; nI++) + { + cTemp = read(); + if (cTemp > 0) + { + Serial.print(cTemp); + strResult[nI] = cTemp; + } + } + return nI; +} + +uint16_t CSIMCOM900::readCellData(uint16_t& nMCC, uint16_t& nMNC, uint32_t &nLAC, uint32_t &nCellID) +{ + if (getStatus() == IDLE) + return 0; + + SimpleWriteln(F("AT+QENG=1,0")); + SimpleWriteln(F("AT+QENG?")); + + if (WaitResp(5000, 50, "+QENG")!=RX_FINISHED_STR_NOT_RECV) + return 0; + + nMCC = m_pStream->read(); + nMCC = m_pStream->read(); + nMNC = m_pStream->read(); + nLAC = m_pStream->read(); + nCellID = m_pStream->read(); + + WaitResp(5000, 50, "+OK"); + SimpleWriteln(F("AT+QENG=1,0")); + WaitResp(5000, 50, "+OK"); + + return 1; +} + +int16_t CSIMCOM900::setPIN(const char* strPIN) +{ + // Status = READY or ATTACHED. + if ( (getStatus() != IDLE)) + return 2; + + //AT command to set PIN. + SimpleWrite(F("AT+CPIN=")); + SimpleWriteln(strPIN); + + //Expect "OK". + if (WaitResp(5000, 50, F("OK")) != RX_FINISHED_STR_NOT_RECV) + return 0; + else + return 1; +} + +int16_t CSIMCOM900::changeNSIPmode(char mode) +{ + SimpleWrite(F("AT+QIDNSIP=")); + SimpleWriteln(mode); + + if (WaitResp(5000, 50, F("OK")) != RX_FINISHED_STR_NOT_RECV) + return 0; + + return 1; +} + +uint16_t CSIMCOM900::getCCI(char* strCCI) +{ + // Status must be READY + if ((getStatus() != READY)) + return 2; + + //AT command to get CCID. + SimpleWriteln(F("AT+QCCID")); + + if (isUsingSS()) + { + CSWSerial tf(*((SoftwareSerial*)m_pStream), 10); + tf.getString("AT+QCCID\r\r\r\n","\r\n",strCCI, 21); + } + else if (isUsingHS()) + { + CHWSerial hwserial(*((HardwareSerial*)m_pStream)); + hwserial.getString("AT+QCCID\r\r\r\n","\r\n",strCCI, 21); + } + //Expect "OK". + if (WaitResp(5000, 50, F("OK"))!=RX_FINISHED_STR_NOT_RECV) + return 0; + else + return 1; +} + +uint16_t CSIMCOM900::getIMEI(char* strIMEI) +{ + //AT command to get IMEI. + SimpleWriteln(F("AT+GSN")); + + if (isUsingSS()) + { + CSWSerial tf(*((SoftwareSerial*)m_pStream), 10); + tf.getString("\r\n","\r\n",strIMEI, 16); + } + else if (isUsingHS()) + { + CHWSerial hwserial(*((HardwareSerial*)m_pStream)); + hwserial.getString("\r\n","\r\n",strIMEI, 16); + } + //Expect "OK". + if (WaitResp(5000, 50, F("OK"))!=RX_FINISHED_STR_NOT_RECV) + return 0; + else + return 1; +} + + uint8_t CSIMCOM900::read() +{ + return m_pStream->read(); +} + +void CSIMCOM900::SimpleRead() +{ + char cDetain = 0; + + if (m_pStream->available() > 0) + { + cDetain = m_pStream->read(); + if (cDetain>0) + { + Serial.print(cDetain); + } + } +} + +void CSIMCOM900::SimpleWrite(const char* strComm) +{ + m_pStream->print(strComm); +} + +void CSIMCOM900::SimpleWrite(const uint16_t nComm) +{ + m_pStream->print(nComm); +} + +void CSIMCOM900::SimpleWrite(const __FlashStringHelper *pstr) +{ + m_pStream->print(pstr); +} + +void CSIMCOM900::SimpleWriteln(const char* strComm) +{ + m_pStream->println(strComm); +} + +void CSIMCOM900::SimpleWriteln(const __FlashStringHelper *pstr) +{ + m_pStream->println(pstr); +} + +void CSIMCOM900::SimpleWriteln(uint16_t nComm) +{ + m_pStream->println(nComm); +} + +void CSIMCOM900::WhileSimpleRead() +{ + char cDetain = 0; + + while(m_pStream->available()>0) + { + cDetain = m_pStream->read(); + if (cDetain>0) + { + Serial.print(cDetain); + } + } +} + diff --git a/SIM900.h b/SIM900.h index ecb4cea..3f4f2db 100644 --- a/SIM900.h +++ b/SIM900.h @@ -1,42 +1,41 @@ -#ifndef SIMCOM900_H -#define SIMCOM900_H -#include -#include "HWSerial.h" -#include "GSM.h" -class SIMCOM900 : public virtual GSM { - -private: - int configandwait(char* pin); - int setPIN(char *pin); - int changeNSIPmode(char); - -public: - SIMCOM900(); - ~SIMCOM900(); - int getCCI(char* cci); - int getIMEI(char* imei); - int sendSMS(const char* to, const char* msg); - boolean readSMS(char* msg, int msglength, char* number, int nlength); - boolean readCall(char* number, int nlength); - boolean call(char* number, unsigned int milliseconds); - char forceON(); - virtual int read(char* result, int resultlength); - virtual uint8_t read(); - virtual int available(); - int readCellData(int &mcc, int &mnc, long &lac, long &cellid); - void SimpleRead(); - void WhileSimpleRead(); - void SimpleWrite(char *comm); - void SimpleWrite(char const *comm); - void SimpleWrite(int comm); - void SimpleWrite(const __FlashStringHelper *pgmstr); - void SimpleWriteln(char *comm); - void SimpleWriteln(char const *comm); - void SimpleWriteln(const __FlashStringHelper *pgmstr); - void SimpleWriteln(int comm); -}; - -extern SIMCOM900 gsm; - -#endif - +#ifndef SIMCOM900_H +#define SIMCOM900_H +#include +#include "HWSerial.h" +#include "GSM.h" + +class CSIMCOM900 : public virtual CGSM +{ + + private: + int16_t configandwait(char* pin); + int16_t setPIN(const char* strpin); + int16_t changeNSIPmode(char); + + protected: + CSIMCOM900(); + + public: + CSIMCOM900(const SoftwareSerial *pStream); + CSIMCOM900(const HardwareSerial *pStream); + ~CSIMCOM900(); + uint16_t getCCI(char* cCCCI); + uint16_t getIMEI(char* cIEMI); + char forceON(); + virtual uint16_t read(char* strResult, const uint16_t nLen); + virtual uint8_t read(); + uint16_t readCellData(uint16_t &nMCC, uint16_t &nMNC, uint32_t &nLAC, uint32_t &nCellID); + void SimpleRead(); + void WhileSimpleRead(); + void SimpleWrite(const char* strComm); + void SimpleWrite(const uint16_t nComm); + void SimpleWrite(const __FlashStringHelper *pstr); + void SimpleWriteln(const char* strComm); + void SimpleWriteln(const uint16_t nComm); + void SimpleWriteln(const __FlashStringHelper *pstr); +}; + +//extern SIMCOM900 gsm; + +#endif + diff --git a/SWSerial.cpp b/SWSerial.cpp new file mode 100644 index 0000000..7d0ab5e --- /dev/null +++ b/SWSerial.cpp @@ -0,0 +1,236 @@ +#include "SWSerial.h" + +#define NO_SKIP_CHAR 1 // a magic char not found in a valid numeric field + +// private function to read characters from rStream +// the constructors allow one and only one of the streams to be initialized +char CSWSerial::read() +{ + char cCh; + + m_nStartMillis = millis(); + + while (millis() < (m_nStartMillis + m_nTimeout)) + { + if (m_rSoftwareSerial.available() > 0) + { + cCh = m_rSoftwareSerial.read(); + + //if (m_bDebug) + //Serial.print16_t(cCh); + + return cCh; + } + } + return 0; // 0 indicates nTimeout +} + +// Constructors +CSWSerial::CSWSerial(SoftwareSerial &rStream, int16_t nTimeout): m_rSoftwareSerial(rStream) +{ + m_nTimeout = nTimeout * 1000L; + m_bDebug = true; +} + +void CSWSerial::setDebug(boolean bDebug) +{ + m_bDebug = bDebug; +} + +// public methods +// +// find returns true if the strTarget string is found +boolean CSWSerial::find(const char *strTarget) +{ + return findUntil(strTarget, NULL); +} + +// as above but search ends if the strTerminate string is found +boolean CSWSerial::findUntil(const char *strTarget, const char *strTerminate) +{ + uint8_t nTargetLength = strlen(strTarget); + uint8_t nIndex = 0; // maximum strTarget string nLength is 255 bytes + uint8_t nTermIndex = 0; + uint8_t nTermLength = (strTerminate == NULL ? 0 : strlen(strTerminate)); + char cCh; + + if (*strTarget == 0) + return true; // return true if strTarget is a null string + + while ((cCh = read()) != 0) + { + if ( cCh == strTarget[nIndex]) + { + if (++nIndex >= nTargetLength) + { + return true; // return true if all chars in the strTarget match + } + } + else + { + nIndex = 0; // reset nIndex if any char does not match + } + if ((nTermLength > 0) && (cCh == strTerminate[nTermIndex])) + { + if (++nTermIndex >= nTermLength) + return false; // return false if strTerminate string found before strTarget string + } + else + nTermIndex = 0; + } + return false; +} + +// places the string between the prestring and poststring in the given strBuff +// strBuff must be one more than the longest string to get +// the string will be truncated to fit the strBuff nLength +// end of string determined by a single character match to the first char of poststring +// returns the number of characters placed in the strBuff (0 means no valid data found) +int16_t CSWSerial::getString(const char *strPre, const char *strPost, char *strBuff, const int16_t nLength) +{ + if (find(strPre)) + { + int16_t nIndex = 0; + *strBuff = 0; + + while (nIndex < (nLength - 1)) + { + char cCh = read(); + if (cCh == 0) + { + return 0; // nTimeout returns 0 ! + } + else if (cCh == *strPost) + { + while (nIndex < nLength) + { + strBuff[nIndex] = '\0'; // strTerminate the string !!!!!!!!!!!IT DOESN'T WORK!!!!!!!!!!!!!!!!! + nIndex++; + } + //strBuff[nIndex] = 0; + return nIndex; // data got successfully + } + else + { + strBuff[nIndex++] = cCh; + } + } + strBuff[nIndex] = 0; + return nIndex; // Note: strBuff full before the closing strPost encountered + } + return 0; // failed to find the prestring +} + +// getValue method: +// returns the first valid (int32_t) int16_teger nValue from the current position. +// initial characters that are not digits (or the minus sign) are skipped +// function is terminated by the first character that is not a digit. +int32_t CSWSerial::getValue() +{ + return getValue(NO_SKIP_CHAR); // strTerminate on first non-digit character +} + +// as above but a given cSkip is ignored +// this allows format characters (typically commas) in values to be ignored +int32_t CSWSerial::getValue(const char cSkip) +{ + boolean bIsNegative = false; + int32_t nValue = 0; + char cCh = 0; + + while (((cCh = read()) != '-') && ((cCh < '0') || (cCh > '9')) && (cCh != 0)) + { + // ignore non numeric leading characters + } + do + { + if (cCh == cSkip) + { + // ignore this charactor + } + else if (cCh == 0) + { + // Timeout + return 0; + } + else if (cCh == '-') + bIsNegative = true; + else if ((cCh >= '0') && (cCh <= '9')) + { + + // is cCh a digit? + nValue = nValue * 10 + cCh - '0'; + cCh = read(); + } + } + while (((cCh >= '0') && (cCh <= '9')) || (cCh == cSkip)); + + if (bIsNegative) + nValue = -nValue; + + return nValue; +} + +// float version of getValue method: +// as int16_teger version but returns a floating point16_t nValue +float CSWSerial::getFloat() +{ + getFloat(NO_SKIP_CHAR); +} + +// as above but the given cSkip is ignored +// this allows format characters (typically commas) in values to be ignored +float CSWSerial::getFloat(const char cSkip) +{ + boolean bIsNegative = false; + boolean isFraction = false; + int32_t nValue = 0; + float fValue = 0.0; + char cCh = 0; + float fFraction = 1.0; + + while (((cCh = read()) != '-') && ((cCh < '0') || (cCh > '9'))) + { + // ignore non numeric leading characters + } + do + { + if (cCh == cSkip) + { + // ignore + } + else if (cCh == '-') + bIsNegative = true; + else if (cCh == '.') + isFraction = true; + else if ((cCh >= '0') && (cCh <= '9')) + { + // is cCh a digit? + nValue = nValue * 10 + cCh - '0'; + if (isFraction) + fFraction *= 0.1; + } + cCh = read(); + } + while (((cCh >= '0') && (cCh <= '9')) || (cCh == '.') || (cCh == cSkip)); + + if (bIsNegative) + nValue = -nValue; + if (isFraction) + return nValue * fFraction; + else + return nValue; +} + + +// returns the number of seconds to wait for the next char before aborting read +uint32_t CSWSerial::getTimeout() +{ + return m_nTimeout; +} + +// set a new nValue for the wait nTimeout +void CSWSerial::setTimeout(const uint32_t nTimeout) +{ + m_nTimeout = nTimeout * 1000L; +} diff --git a/SWSerial.h b/SWSerial.h new file mode 100644 index 0000000..569ae63 --- /dev/null +++ b/SWSerial.h @@ -0,0 +1,61 @@ +#ifndef __SW_SERIAL_H +#define __SW_SERIAL_H + +//#include +#include +#include + + +class CSWSerial +{ + private: + SoftwareSerial& m_rSoftwareSerial; + + uint32_t m_nTimeout; // Number of seconds to wait for the next char before aborting read + uint32_t m_nStartMillis; // Used for nTimeout measurement + boolean m_bDebug; + + char read(); // private function to read from the rStream + + public: + // Constructor: + CSWSerial(SoftwareSerial &rStream, int16_t nTimeout = 5); // Ethernet constructor + + // Manage debug + void setDebug(boolean bDebug); + + // find methods - these seek through the data but do not return anything + // they are useful to skip past unwanted data + // + boolean find(const char *strTarget); // reads data from the rStream until the strTarget string is found + // returns true if strTarget string is found + + boolean findUntil(const char *strTarget, const char *strTerminate); // as above but search ends if the strTerminate string is found + + + // get methods - these get a numeric value or string from the data rStream + // + long getValue(); // returns the first valid (long) integer value from the current position. + // initial characters that are not digits (or the minus sign) are skipped + // integer is terminated by the first character that is not a digit. + + long getValue(const char cSkip); // as above but the given cSkip is ignored + // this allows format characters (typically commas) in values to be ignored + + float getFloat(); // float version of getValue + float getFloat(const char cSkip); // as above but the given cSkip is ignored + + int16_t getString(const char *strPre, const char *strPost, char *strBuff, int16_t nLength); //puts string found between given delimiters in strBuff + // string will be truncated to fit the strBuff length + // end of string determined by a match of a character to the first char of close delimiter + // returns the number of characters placed in the strBuff (0 means no valid data found) + + uint32_t getTimeout(); // returns the number of seconds to wait for the next char before aborting read + + // set methods + // + void setTimeout(const uint32_t nTimeout); // set a new value for the wait nTimeout + + }; + +#endif diff --git a/Streaming.h b/Streaming.h index 154a5f1..230c82b 100644 --- a/Streaming.h +++ b/Streaming.h @@ -24,39 +24,33 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "LOG.h" #define __ST_LOG_LEVEL 3 -static LOG _st_logme(__ST_LOG_LEVEL); +static CLog _st_logme(__ST_LOG_LEVEL); // Generic template -template -inline Print &operator <<(Print &stream, T arg) -{ - stream.print(arg); - _st_logme.DATA(arg); - return stream; -} - -struct _BASED { - long val; - int base; - _BASED(long v, int b): val(v), base(b) - {} +template +inline Print &operator <<(Print &stream, T arg) +{ stream.print(arg); _st_logme.DATA(arg); return stream; } + +struct CIntVal +{ + int32_t m_nVal; + uint8_t m_nBase; + CIntVal(int32_t nVal, uint8_t nBase): m_nVal(nVal), m_nBase(nBase) + {} }; -#define _HEX(a) _BASED(a, HEX) -#define _DEC(a) _BASED(a, DEC) -#define _OCT(a) _BASED(a, OCT) -#define _BIN(a) _BASED(a, BIN) +#define _HEX(a) CIntVal(a, HEX) +#define _DEC(a) CIntVal(a, DEC) +#define _OCT(a) CIntVal(a, OCT) +#define _BIN(a) CIntVal(a, BIN) -// Specialization for class _BASED -// Thanks to Arduino forum user Ben Combee who suggested this +// Specialization for class CIntVal +// Thanks to Arduino forum user Ben Combee who suggested this // clever technique to allow for expressions like // Serial << _HEX(a); -inline Print &operator <<(Print &obj, const _BASED &arg) -{ - obj.print(arg.val); - return obj; -} +inline Print &operator <<(Print &obj, const CIntVal &arg) +{ obj.print(arg.m_nVal); return obj; } #if ARDUINO >= 18 // Specialization for class _FLOAT @@ -65,18 +59,16 @@ inline Print &operator <<(Print &obj, const _BASED &arg) // feature like this: // Serial << _FLOAT(gps_latitude, 6); // 6 digits of precision -struct _FLOAT { - float val; - int digits; - _FLOAT(double v, int d): val(v), digits(d) - {} +struct _FLOAT +{ + float m_nVal; + uint8_t digits; + _FLOAT(double nVal, uint8_t d): m_nVal(nVal), digits(d) + {} }; inline Print &operator <<(Print &obj, const _FLOAT &arg) -{ - obj.print(arg.val, arg.digits); - return obj; -} +{ obj.print(arg.m_nVal, arg.digits); return obj; } #endif // Specialization for enum _EndLineCode @@ -86,10 +78,7 @@ inline Print &operator <<(Print &obj, const _FLOAT &arg) enum _EndLineCode { endl }; -inline Print &operator <<(Print &obj, _EndLineCode arg) -{ - obj.println(); - return obj; -} +inline Print &operator <<(Print &obj, _EndLineCode arg) +{ obj.println(); return obj; } #endif diff --git a/call.cpp b/call.cpp index d162d58..e7eed8a 100644 --- a/call.cpp +++ b/call.cpp @@ -1,334 +1,373 @@ #include "call.h" /********************************************************** -Method checks status of call +Method checks nStatus of call -return: +return: CALL_NONE - no call activity CALL_INCOM_VOICE - incoming voice CALL_ACTIVE_VOICE - active voice - CALL_NO_RESPONSE - no response to the AT command + CALL_NO_RESPONSE - no response to the AT command CALL_COMM_LINE_BUSY - comm line is not free **********************************************************/ -byte CallGSM::CallStatus(void) +uint8_t CCallGSM::CallStatus(void) { - byte ret_val = CALL_NONE; - - if (CLS_FREE != gsm.GetCommLineStatus()) return (CALL_COMM_LINE_BUSY); - gsm.SetCommLineStatus(CLS_ATCMD); - gsm.SimpleWriteln(F("AT+CPAS")); - - // 5 sec. for initial comm tmout - // 50 msec. for inter character timeout - if (RX_TMOUT_ERR == gsm.WaitResp(5000, 50)) { - // nothing was received (RX_TMOUT_ERR) - // ----------------------------------- - ret_val = CALL_NO_RESPONSE; - } else { - // something was received but what was received? - // --------------------------------------------- - // ready (device allows commands from TA/TE) - // +CPAS: 0 OK - // unavailable (device does not allow commands from TA/TE) - // +CPAS: 1 OK - // unknown (device is not guaranteed to respond to instructions) - // +CPAS: 2 OK - NO CALL - // ringing - // +CPAS: 3 OK - NO CALL - // call in progress - // +CPAS: 4 OK - NO CALL - if(gsm.IsStringReceived("+CPAS: 0")) { - // ready - there is no call - // ------------------------ - ret_val = CALL_NONE; - } else if(gsm.IsStringReceived("+CPAS: 3")) { - // incoming call - // -------------- - ret_val = CALL_INCOM_VOICE; - } else if(gsm.IsStringReceived("+CPAS: 4")) { - // active call - // ----------- - ret_val = CALL_ACTIVE_VOICE; - } - } - - gsm.SetCommLineStatus(CLS_FREE); - return (ret_val); - + uint8_t nRetVal = CALL_NONE; + + if (CLS_FREE != m_rSimComm900.GetCommLineStatus()) + return (CALL_COMM_LINE_BUSY); + + m_rSimComm900.SetCommLineStatus(CLS_ATCMD); + m_rSimComm900.SimpleWriteln(F("AT+CPAS")); + + // 5 sec. for initial comm tmout + // 50 msec. for inter character timeout + if (RX_TMOUT_ERR == m_rSimComm900.WaitResp(5000, 50)) + { + // nothing was received (RX_TMOUT_ERR) + // ----------------------------------- + nRetVal = CALL_NO_RESPONSE; + } + else + { + // something was received but what was received? + // --------------------------------------------- + // ready (device allows commands from TA/TE) + // +CPAS: 0 OK + // unavailable (device does not allow commands from TA/TE) + // +CPAS: 1 OK + // unknown (device is not guaranteed to respond to instructions) + // +CPAS: 2 OK - NO CALL + // ringing + // +CPAS: 3 OK - NO CALL + // call in progress + // +CPAS: 4 OK - NO CALL + if (m_rSimComm900.IsStringReceived(F("+CPAS: 0"))) + { + // ready - there is no call + // ------------------------ + nRetVal = CALL_NONE; + } + else if (m_rSimComm900.IsStringReceived(F("+CPAS: 3"))) + { + // incoming call + // -------------- + nRetVal = CALL_INCOM_VOICE; + } + else if (m_rSimComm900.IsStringReceived(F("+CPAS: 4"))) + { + // active call + // ----------- + nRetVal = CALL_ACTIVE_VOICE; + } + } + m_rSimComm900.SetCommLineStatus(CLS_FREE); + return (nRetVal); } /********************************************************** -Method checks status of call(incoming or active) +Method checks nStatus of call(incoming or active) and makes authorization with specified SIM positions range -phone_number: a pointer where the tel. number string of current call will be placed +strPhoneNumber: a pointer where the tel. number string of current call will be placed so the space for the phone number string must be reserved - see example -first_authorized_pos: initial SIM phonebook position where the authorization process +nFirstAuthorisedPos: initial SIM phonebook position where the authorization process starts -last_authorized_pos: last SIM phonebook position where the authorization process +nLastAuthorisedPos: last SIM phonebook position where the authorization process finishes Note(important): ================ - In case first_authorized_pos=0 and also last_authorized_pos=0 + In case nFirstAuthorisedPos=0 and also nLastAuthorisedPos=0 the received incoming phone number is NOT authorized at all, so every incoming is considered as authorized (CALL_INCOM_VOICE_NOT_AUTH is returned) -return: +return: CALL_NONE - no call activity CALL_INCOM_VOICE_AUTH - incoming voice - authorized CALL_INCOM_VOICE_NOT_AUTH - incoming voice - not authorized CALL_ACTIVE_VOICE - active voice CALL_INCOM_DATA_AUTH - incoming data call - authorized - CALL_INCOM_DATA_NOT_AUTH - incoming data call - not authorized + CALL_INCOM_DATA_NOT_AUTH - incoming data call - not authorized CALL_ACTIVE_DATA - active data call - CALL_NO_RESPONSE - no response to the AT command + CALL_NO_RESPONSE - no response to the AT command CALL_COMM_LINE_BUSY - comm line is not free **********************************************************/ -byte CallGSM::CallStatusWithAuth(char *phone_number, - byte first_authorized_pos, byte last_authorized_pos) +uint8_t CCallGSM::CallStatusWithAuth(char *strPhoneNumber, const uint8_t nFirstAuthorisedPos, const uint8_t nLastAuthorisedPos) { - byte ret_val = CALL_NONE; - byte search_phone_num = 0; - byte i; - byte status; - char *p_char; - char *p_char1; - - phone_number[0] = 0x00; // no phonr number so far - if (CLS_FREE != gsm.GetCommLineStatus()) return (CALL_COMM_LINE_BUSY); - gsm.SetCommLineStatus(CLS_ATCMD); - gsm.SimpleWriteln(F("AT+CLCC")); - - // 5 sec. for initial comm tmout - // and max. 1500 msec. for inter character timeout - gsm.RxInit(5000, 1500); - // wait response is finished - do { - if (gsm.IsStringReceived("OK\r\n")) { - // perfect - we have some response, but what: - - // there is either NO call: - // OK - - // or there is at least 1 call - // +CLCC: 1,1,4,0,0,"+420XXXXXXXXX",145 - // OK - status = RX_FINISHED; - break; // so finish receiving immediately and let's go to - // to check response - } - status = gsm.IsRxFinished(); - } while (status == RX_NOT_FINISHED); - - // generate tmout 30msec. before next AT command - delay(30); - - if (status == RX_FINISHED) { - // something was received but what was received? - // example: //+CLCC: 1,1,4,0,0,"+420XXXXXXXXX",145 - // --------------------------------------------- - if(gsm.IsStringReceived("+CLCC: 1,1,4,0,0")) { - // incoming VOICE call - not authorized so far - // ------------------------------------------- - search_phone_num = 1; - ret_val = CALL_INCOM_VOICE_NOT_AUTH; - } else if(gsm.IsStringReceived("+CLCC: 1,1,4,1,0")) { - // incoming DATA call - not authorized so far - // ------------------------------------------ - search_phone_num = 1; - ret_val = CALL_INCOM_DATA_NOT_AUTH; - } else if(gsm.IsStringReceived("+CLCC: 1,0,0,0,0")) { - // active VOICE call - GSM is caller - // ---------------------------------- - search_phone_num = 1; - ret_val = CALL_ACTIVE_VOICE; - } else if(gsm.IsStringReceived("+CLCC: 1,1,0,0,0")) { - // active VOICE call - GSM is listener - // ----------------------------------- - search_phone_num = 1; - ret_val = CALL_ACTIVE_VOICE; - } else if(gsm.IsStringReceived("+CLCC: 1,1,0,1,0")) { - // active DATA call - GSM is listener - // ---------------------------------- - search_phone_num = 1; - ret_val = CALL_ACTIVE_DATA; - } else if(gsm.IsStringReceived("+CLCC:")) { - // other string is not important for us - e.g. GSM module activate call - // etc. - // IMPORTANT - each +CLCC:xx response has also at the end - // string OK - ret_val = CALL_OTHERS; - } else if(gsm.IsStringReceived("OK")) { - // only "OK" => there is NO call activity - // -------------------------------------- - ret_val = CALL_NONE; - } - - - // now we will search phone num string - if (search_phone_num) { - // extract phone number string - // --------------------------- - p_char = strchr((char *)(gsm.comm_buf),'"'); - p_char1 = p_char+1; // we are on the first phone number character - p_char = strchr((char *)(p_char1),'"'); - if (p_char != NULL) { - *p_char = 0; // end of string - strcpy(phone_number, (char *)(p_char1)); - Serial.print("ATTESO: "); - Serial.println(phone_number); - } else - //Serial.println(gsm.comm_buf); - Serial.println("NULL"); - - if ( (ret_val == CALL_INCOM_VOICE_NOT_AUTH) - || (ret_val == CALL_INCOM_DATA_NOT_AUTH)) { - - if ((first_authorized_pos == 0) && (last_authorized_pos == 0)) { - // authorization is not required => it means authorization is OK - // ------------------------------------------------------------- - if (ret_val == CALL_INCOM_VOICE_NOT_AUTH) ret_val = CALL_INCOM_VOICE_AUTH; - else ret_val = CALL_INCOM_DATA_AUTH; - } else { - // make authorization - // ------------------ - gsm.SetCommLineStatus(CLS_FREE); - for (i = first_authorized_pos; i <= last_authorized_pos; i++) { - if (gsm.ComparePhoneNumber(i, phone_number)) { - // phone numbers are identical - // authorization is OK - // --------------------------- - if (ret_val == CALL_INCOM_VOICE_NOT_AUTH) ret_val = CALL_INCOM_VOICE_AUTH; - else ret_val = CALL_INCOM_DATA_AUTH; - break; // and finish authorization - } - } - } - } - } - - } else { - // nothing was received (RX_TMOUT_ERR) - // ----------------------------------- - ret_val = CALL_NO_RESPONSE; - } - - gsm.SetCommLineStatus(CLS_FREE); - return (ret_val); + uint8_t nRetVal = CALL_NONE; + uint8_t nSearchPhoneNum = 0; + uint8_t nI = 0; + uint8_t nStatus = 0; + char *str1 = NULL; + char *str2 = NULL; + + strPhoneNumber[0] = 0x00; // no phonr number so far + + if (CLS_FREE != m_rSimComm900.GetCommLineStatus()) + return (CALL_COMM_LINE_BUSY); + + m_rSimComm900.SetCommLineStatus(CLS_ATCMD); + m_rSimComm900.SimpleWriteln(F("AT+CLCC")); + + // 5 sec. for initial comm tmout + // and max. 1500 msec. for inter character timeout + m_rSimComm900.RxInit(5000, 1500); + + // wait response is finished + do + { + if (m_rSimComm900.IsStringReceived(F("OK\r\n"))) + { + // perfect - we have some response, but what: + + // there is either NO call: + // OK + + // or there is at least 1 call + // +CLCC: 1,1,4,0,0,"+420XXXXXXXXX",145 + // OK + nStatus = RX_FINISHED; + break; // so finish receiving immediately and let's go to check response + } + nStatus = m_rSimComm900.IsRxFinished(); + } + while (nStatus == RX_NOT_FINISHED); + + // generate tmout 30msec. before next AT command + delay(30); + + if (nStatus == RX_FINISHED) + { + // something was received but what was received? + // example: //+CLCC: 1,1,4,0,0,"+420XXXXXXXXX",145 + // --------------------------------------------- + if (m_rSimComm900.IsStringReceived(F("+CLCC: 1,1,4,0,0"))) + { + // incoming VOICE call - not authorized so far + // ------------------------------------------- + nSearchPhoneNum = 1; + nRetVal = CALL_INCOM_VOICE_NOT_AUTH; + } + else if (m_rSimComm900.IsStringReceived(F("+CLCC: 1,1,4,1,0"))) + { + // incoming DATA call - not authorized so far + // ------------------------------------------ + nSearchPhoneNum = 1; + nRetVal = CALL_INCOM_DATA_NOT_AUTH; + } + else if (m_rSimComm900.IsStringReceived(F("+CLCC: 1,0,0,0,0"))) + { + // active VOICE call - GSM is caller + // ---------------------------------- + nSearchPhoneNum = 1; + nRetVal = CALL_ACTIVE_VOICE; + } + else if (m_rSimComm900.IsStringReceived(F("+CLCC: 1,1,0,0,0"))) + { + // active VOICE call - GSM is listener + // ----------------------------------- + nSearchPhoneNum = 1; + nRetVal = CALL_ACTIVE_VOICE; + } + else if (m_rSimComm900.IsStringReceived(F("+CLCC: 1,1,0,1,0"))) + { + // active DATA call - GSM is listener + // ---------------------------------- + nSearchPhoneNum = 1; + nRetVal = CALL_ACTIVE_DATA; + } + else if (m_rSimComm900.IsStringReceived(F("+CLCC:"))) + { + // other string is not important for us - e.g. GSM module activate call etc. + // IMPORTANT - each +CLCC:xx response has also at the end string OK + nRetVal = CALL_OTHERS; + } + else if (m_rSimComm900.IsStringReceived(F("OK"))) + { + // only F("OK") => there is NO call activity + // -------------------------------------- + nRetVal = CALL_NONE; + } + // now we will search phone num string + if (nSearchPhoneNum) + { + // extract phone number string + // --------------------------- + str1 = strchr(m_rSimComm900.m_arrayCommBuff, '"'); + str2 = str1 + 1; // we are on the first phone number character + str1 = strchr((char *)(str2), '"'); + + if (str1 != NULL) + { + *str1 = 0; // end of string + strcpy(strPhoneNumber, (char *)(str2)); + Serial.print(F("ATTESO: ")); + Serial.println(strPhoneNumber); + } + else + Serial.println(F("NULL")); + + if ((nRetVal == CALL_INCOM_VOICE_NOT_AUTH) || (nRetVal == CALL_INCOM_DATA_NOT_AUTH)) + { + if ((nFirstAuthorisedPos == 0) && (nLastAuthorisedPos == 0)) + { + // authorization is not required => it means authorization is OK + // ------------------------------------------------------------- + if (nRetVal == CALL_INCOM_VOICE_NOT_AUTH) + nRetVal = CALL_INCOM_VOICE_AUTH; + else + nRetVal = CALL_INCOM_DATA_AUTH; + } + else + { + // make authorization + // ------------------ + m_rSimComm900.SetCommLineStatus(CLS_FREE); + + for (nI = nFirstAuthorisedPos; nI <= nLastAuthorisedPos; nI++) + { + if (m_rSimComm900.ComparePhoneNumber(nI, strPhoneNumber)) + { + // phone numbers are identical + // authorization is OK + // --------------------------- + if (nRetVal == CALL_INCOM_VOICE_NOT_AUTH) + nRetVal = CALL_INCOM_VOICE_AUTH; + else nRetVal = CALL_INCOM_DATA_AUTH; + break; // and finish authorization + } + } + } + } + } + } + else + { + // nothing was received (RX_TMOUT_ERR) + // ----------------------------------- + nRetVal = CALL_NO_RESPONSE; + } + m_rSimComm900.SetCommLineStatus(CLS_FREE); + return (nRetVal); } /********************************************************** Method picks up an incoming call -return: +return: **********************************************************/ -void CallGSM::PickUp(void) +void CCallGSM::PickUp(void) { - //if (CLS_FREE != gsm.GetCommLineStatus()) return; - //gsm.SetCommLineStatus(CLS_ATCMD); - gsm.SendATCmdWaitResp("ATA", 10, 10, "OK", 3); - gsm.SimpleWriteln("ATA"); - //gsm.SetCommLineStatus(CLS_FREE); + m_rSimComm900.SendATCmdWaitResp(F("ATA"), 10, 10, F("OK"), 3); + m_rSimComm900.SimpleWriteln(F("ATA")); } /********************************************************** Method hangs up incoming or active call -return: +return: **********************************************************/ -void CallGSM::HangUp(void) +void CCallGSM::HangUp(void) +{ + m_rSimComm900.SendATCmdWaitResp(F("ATH"), 500, 100, F("OK"), 5); +} + +void CCallGSM::SendDTMF(const __FlashStringHelper *fstrNumber, const int16_t nTime) { - //if (CLS_FREE != gsm.GetCommLineStatus()) return; - //gsm.SetCommLineStatus(CLS_ATCMD); - gsm.SendATCmdWaitResp("ATH", 500, 100, "OK", 5); - //gsm.SetCommLineStatus(CLS_FREE); + const uint16_t nLen = strlen_P((PGM_P)fstrNumber) + 1; + char *strNumber = new char[nLen]; + + memset(strNumber, 0, nLen); + strcpy_P(strNumber, (PGM_P)fstrNumber); + SendDTMF(strNumber, nTime); + delete strNumber; } + /********************************************************** Method calls the specific number -number_string: pointer to the phone number string - e.g. gsm.Call("+420123456789"); +strNumber: pointer to the phone number string + e.g. Call("+420123456789"); **********************************************************/ -void CallGSM::Call(char *number_string) +void CCallGSM::Call(const char *strNumber) { - if (CLS_FREE != gsm.GetCommLineStatus()) return; - gsm.SetCommLineStatus(CLS_ATCMD); - // ATDxxxxxx; - gsm.SimpleWrite(F("ATD")); - gsm.SimpleWrite(number_string); - gsm.SimpleWriteln(F(";")); - // 10 sec. for initial comm tmout - // 50 msec. for inter character timeout - gsm.WaitResp(10000, 50); - gsm.SetCommLineStatus(CLS_FREE); + if (CLS_FREE != m_rSimComm900.GetCommLineStatus()) + return; + + m_rSimComm900.SetCommLineStatus(CLS_ATCMD); + // ATDxxxxxx; + m_rSimComm900.SimpleWrite(F("ATD")); + m_rSimComm900.SimpleWrite(strNumber); + m_rSimComm900.SimpleWriteln(F(";")); + // 10 sec. for initial comm tmout + // 50 msec. for inter character timeout + m_rSimComm900.WaitResp(10000, 50); + m_rSimComm900.SetCommLineStatus(CLS_FREE); } /********************************************************** Method calls the number stored at the specified SIM position -sim_position: position in the SIM <1...> - e.g. gsm.Call(1); +nSIMPos: position in the SIM <1...> + e.g. Call(1); **********************************************************/ -void CallGSM::Call(int sim_position) +void CCallGSM::Call(const int16_t nSIMPos) { - if (CLS_FREE != gsm.GetCommLineStatus()) return; - gsm.SetCommLineStatus(CLS_ATCMD); - // ATD>"SM" 1; - gsm.SimpleWrite(F("ATD>\"SM\" ")); - gsm.SimpleWrite(sim_position); - gsm.SimpleWriteln(F(";")); - - // 10 sec. for initial comm tmout - // 50 msec. for inter character timeout - gsm.WaitResp(10000, 50); - - gsm.SetCommLineStatus(CLS_FREE); + if (CLS_FREE != m_rSimComm900.GetCommLineStatus()) + return; + + m_rSimComm900.SetCommLineStatus(CLS_ATCMD); + // ATD>"SM" 1; + m_rSimComm900.SimpleWrite(F("ATD>\"SM\" ")); + m_rSimComm900.SimpleWrite(nSIMPos); + m_rSimComm900.SimpleWriteln(F(";")); + + // 10 sec. for initial comm tmout + // 50 msec. for inter character timeout + m_rSimComm900.WaitResp(10000, 50); + m_rSimComm900.SetCommLineStatus(CLS_FREE); } -void CallGSM::SendDTMF(char *number_string, int time) +void CCallGSM::SendDTMF(const char *strNumber, int16_t nTime) { - if (CLS_FREE != gsm.GetCommLineStatus()) return; - gsm.SetCommLineStatus(CLS_ATCMD); - - gsm.SimpleWrite(F("AT+VTD=")); - gsm.SimpleWriteln(time); - gsm.WaitResp(1000, 100, "OK"); - - gsm.SimpleWrite(F("AT+VTS=\"")); - gsm.SimpleWrite(number_string); - gsm.SimpleWriteln(F("\"")); - - gsm.WaitResp(5000, 100, "OK"); - gsm.SetCommLineStatus(CLS_FREE); + if (CLS_FREE != m_rSimComm900.GetCommLineStatus()) + return; + + m_rSimComm900.SetCommLineStatus(CLS_ATCMD); + m_rSimComm900.SimpleWrite(F("AT+VTD=")); + m_rSimComm900.SimpleWriteln(nTime); + m_rSimComm900.WaitResp(1000, 100, F("OK")); + m_rSimComm900.SimpleWrite(F("AT+VTS=\"")); + m_rSimComm900.SimpleWrite(strNumber); + m_rSimComm900.SimpleWriteln(F("\"")); + m_rSimComm900.WaitResp(5000, 100, F("OK")); + m_rSimComm900.SetCommLineStatus(CLS_FREE); } -void CallGSM::SetDTMF(int DTMF_status) +void CCallGSM::SetDTMF(const int16_t nDTMFStatus) { - if(DTMF_status==1) - gsm.SendATCmdWaitResp("AT+DDET=1", 500, 50, "OK", 5); - else - gsm.SendATCmdWaitResp("AT+DDET=0", 500, 50, "OK", 5); + if (nDTMFStatus == 1) + m_rSimComm900.SendATCmdWaitResp(F("AT+DDET=1"), 500, 50, F("OK"), 5); + else + m_rSimComm900.SendATCmdWaitResp(F("AT+DDET=0"), 500, 50, F("OK"), 5); } -char CallGSM::DetDTMF() +char CCallGSM::DetDTMF() { - char *p_char; - char *p_char1; - char dtmf_char='-'; - gsm.WaitResp(1000, 500); - { - //Serial.print("BUF: "); - //Serial.println((char *)gsm.comm_buf); - //Serial.println("end"); - p_char = strstr((char *)(gsm.comm_buf),"+DTMF:"); - if (p_char != NULL) { - p_char1 = p_char+6; //we are on the first char of BCS - dtmf_char = *p_char1; - } - } - return dtmf_char; + char *str1; + char *str2; + char dtmf_char='-'; + m_rSimComm900.WaitResp(1000, 500); + { + str1 = strstr_P(m_rSimComm900.m_arrayCommBuff, (PGM_P)F("+DTMF:")); + if (str1 != NULL) { + str2 = str1+6; //we are on the first char of BCS + dtmf_char = *str2; + } + } + return dtmf_char; } \ No newline at end of file diff --git a/call.h b/call.h index 0a5ab1e..2f1ab8d 100644 --- a/call.h +++ b/call.h @@ -1,27 +1,29 @@ #ifndef _CALL_H_ #define _CALL_H_ -#include "SIM900.h" +#include "GSMBase.h" -class CallGSM { -public: - // finds out the status of call - byte CallStatus(void); - byte CallStatusWithAuth(char *phone_number, - byte first_authorized_pos, byte last_authorized_pos); - // picks up an incoming call - void PickUp(void); - // hangs up an incomming call - void HangUp(void); - // calls the specific number - void Call(char *number_string); - // makes a call to the number stored at the specified SIM position - void Call(int sim_position); - void SendDTMF(char *number_string, int time); - - void SetDTMF(int DTMF_status); - char DetDTMF(); +class CCallGSM: protected CGSMBase +{ + public: + CCallGSM(CSIMCOM900& rSimComm900): CGSMBase(rSimComm900){}; + + // finds out the status of call + uint8_t CallStatus(void); + uint8_t CallStatusWithAuth(char *strPhoneNumber, const uint8_t nFirstAuthorisedPos, const uint8_t nLastAuthorisedPos); + // picks up an incoming call + void PickUp(void); + // hangs up an incomming call + void HangUp(void); + // calls the specific number + void Call(const char *strNumber); + // makes a call to the number stored at the specified SIM position + void Call(const int16_t nSIMPos); + void SendDTMF(const char *strNumber, const int16_t nTime); + void SendDTMF(const __FlashStringHelper *fstrNumber, const int16_t nTime); + void SetDTMF(const int16_t nDTMFStatus); + char DetDTMF(); }; #endif diff --git a/examples/GSM_GPRSLibrary_AT/GSM_GPRSLibrary_AT.ino b/examples/GSM_GPRSLibrary_AT/GSM_GPRSLibrary_AT.ino index 1ce2d71..29325bd 100644 --- a/examples/GSM_GPRSLibrary_AT/GSM_GPRSLibrary_AT.ino +++ b/examples/GSM_GPRSLibrary_AT/GSM_GPRSLibrary_AT.ino @@ -16,62 +16,70 @@ //CallGSM call; //SMSGSM sms; -int numdata; -char inSerial[40]; -int i=0; +int nNumData; +char strInSerial[40]; +CSIMCOM900 gsm(&Serial1); - -void setup() +void setup() { - //Serial connection. - Serial.begin(9600); - Serial.println("GSM Shield testing."); - //Start configuration of shield with baudrate. - //For http uses is raccomanded to use 4800 or slower. - if (gsm.begin(9600)) - Serial.println("\nstatus=READY"); - else Serial.println("\nstatus=IDLE"); + //Serial connection. + Serial.begin(115200); + Serial.println("GSM Shield testing."); + //Start configuration of shield with baudrate. + //For http uses is raccomanded to use 4800 or slower. + Serial1.begin(115200); + if (gsm.begin(115200)) + Serial.println("\nstatus=READY"); + else + Serial.println("\nstatus=IDLE"); }; -void loop() +void loop() { - //Read for new byte on serial hardware, - //and write them on NewSoftSerial. - serialhwread(); - //Read for new byte on NewSoftSerial. - serialswread(); + //Read for new byte on serial hardware, + //and write them on NewSoftSerial. + serialhwread(); + //Read for new byte on NewSoftSerial. + serialswread(); }; void serialhwread() { - i=0; - if (Serial.available() > 0) { - while (Serial.available() > 0) { - inSerial[i]=(Serial.read()); - delay(10); - i++; - } - - inSerial[i]='\0'; - if(!strcmp(inSerial,"/END")) { - Serial.println("_"); - inSerial[0]=0x1a; - inSerial[1]='\0'; - gsm.SimpleWriteln(inSerial); - } - //Send a saved AT command using serial port. - if(!strcmp(inSerial,"TEST")) { - Serial.println("SIGNAL QUALITY"); - gsm.SimpleWriteln("AT+CSQ"); - } else { - Serial.println(inSerial); - gsm.SimpleWriteln(inSerial); - } - inSerial[0]='\0'; - } + uint16_t nI = 0; + + if (Serial.available() > 0) + { + while (Serial.available() > 0) + { + strInSerial[nI]=(Serial.read()); + delay(10); + nI++; + } + + strInSerial[nI]='\0'; + if (!strcmp(strInSerial,"/END")) + { + Serial.println("_"); + strInSerial[0]=0x1a; + strInSerial[1]='\0'; + gsm.SimpleWriteln(strInSerial); + } + //Send a saved AT command using serial port. + if (!strcmp(strInSerial,"TEST")) + { + Serial.println("SIGNAL QUALITY"); + gsm.SimpleWriteln("AT+CSQ"); + } + else + { + Serial.println(strInSerial); + gsm.SimpleWriteln(strInSerial); + } + strInSerial[0]='\0'; + } } void serialswread() { - gsm.SimpleRead(); + gsm.SimpleRead(); } diff --git a/examples/GSM_GPRSLibrary_Call/GSM_GPRSLibrary_Call.ino b/examples/GSM_GPRSLibrary_Call/GSM_GPRSLibrary_Call.ino index 20c6886..671c582 100644 --- a/examples/GSM_GPRSLibrary_Call/GSM_GPRSLibrary_Call.ino +++ b/examples/GSM_GPRSLibrary_Call/GSM_GPRSLibrary_Call.ino @@ -1,60 +1,61 @@ -#include "SIM900.h" -#include -//We don't need the http functions. So we can disable the next line. -//#include "inetGSM.h" -#include "sms.h" -#include "call.h" - -//To change pins for Software Serial, use the two lines in GSM.cpp. - -//GSM Shield for Arduino -//www.open-electronics.org -//this code is based on the example of Arduino Labs. - -//Simple sketch to check if an incoming call is from an authorized -//number and in this case, send to this number an SMS with the value -//of a digital input. - -//We have to create the classes for SMSs and calls. -CallGSM call; -SMSGSM sms; - -char number[20]; -byte stat=0; -int value=0; -int pin=1; -char value_str[5]; - -void setup() -{ - pinMode(pin,INPUT); - //Serial connection. - Serial.begin(9600); - Serial.println("GSM Shield testing."); - //Start configuration of shield with baudrate. - //For http uses is raccomanded to use 4800 or slower. - if (gsm.begin(2400)) - Serial.println("\nstatus=READY"); - else Serial.println("\nstatus=IDLE"); -}; - -void loop() -{ - //Chekcs status of call - stat=call.CallStatusWithAuth(number,1,3); - //If the incoming call is from an authorized number - //saved on SIM in the positions range from 1 to 3. - if(stat==CALL_INCOM_VOICE_AUTH) { - //Hang up the call. - call.HangUp(); - delay(2000); - //Check the value of the input. - value=digitalRead(1); - //Convert the int to a string. - itoa(value,value_str,10); - //Send an SMS to the previous number with - //the value read previously. - sms.SendSMS(number,value_str); - } - delay(1000); -}; +#include "SIM900.h" +#include +//We don't need the http functions. So we can disable the next line. +//#include "inetGSM.h" +#include "sms.h" +#include "call.h" + +//To change pins for Software Serial, use the two lines in GSM.cpp. + +//GSM Shield for Arduino +//www.open-electronics.org +//this code is based on the example of Arduino Labs. + +//Simple sketch to check if an incoming call is from an authorized +//number and in this case, send to this number an SMS with the value +//of a digital input. + +//We have to create the classes for SMSs and calls. +CSIMCOM900 gsm(&Serial1); +CCallGSM call(gsm); +CSMSGSM sms(gsm); + +char number[20]; +byte stat=0; +int value=0; +int pin=1; +char value_str[5]; + +void setup() +{ + pinMode(pin,INPUT); + //Serial connection. + Serial.begin(9600); + Serial.println("GSM Shield testing."); + //Start configuration of shield with baudrate. + //For http uses is raccomanded to use 4800 or slower. + if (gsm.begin(2400)) + Serial.println("\nstatus=READY"); + else Serial.println("\nstatus=IDLE"); +}; + +void loop() +{ + //Chekcs status of call + stat=call.CallStatusWithAuth(number,1,3); + //If the incoming call is from an authorized number + //saved on SIM in the positions range from 1 to 3. + if(stat==CALL_INCOM_VOICE_AUTH){ + //Hang up the call. + call.HangUp(); + delay(2000); + //Check the value of the input. + value=digitalRead(1); + //Convert the int to a string. + itoa(value,value_str,10); + //Send an SMS to the previous number with + //the value read previously. + sms.SendSMS(number,value_str); + } + delay(1000); +}; diff --git a/examples/GSM_GPRSLibrary_Client/GSM_GPRSLibrary_Client.ino b/examples/GSM_GPRSLibrary_Client/GSM_GPRSLibrary_Client.ino index 181f49b..db00b6f 100644 --- a/examples/GSM_GPRSLibrary_Client/GSM_GPRSLibrary_Client.ino +++ b/examples/GSM_GPRSLibrary_Client/GSM_GPRSLibrary_Client.ino @@ -12,9 +12,9 @@ //Simple sketch to start a connection as client. -InetGSM inet; -//CallGSM call; -//SMSGSM sms; +CSIMCOM900 gsm(&Serial1); +CInetGSM inet(gsm); + char msg[50]; int numdata; @@ -22,86 +22,86 @@ char inSerial[50]; int i=0; boolean started=false; -void setup() +void setup() { - //Serial connection. - Serial.begin(9600); - Serial.println("GSM Shield testing."); - //Start configuration of shield with baudrate. - //For http uses is raccomanded to use 4800 or slower. - if (gsm.begin(2400)) { - Serial.println("\nstatus=READY"); - started=true; - } else Serial.println("\nstatus=IDLE"); - - if(started) { - //GPRS attach, put in order APN, username and password. - //If no needed auth let them blank. - if (inet.attachGPRS("internet.wind", "", "")) - Serial.println("status=ATTACHED"); - else Serial.println("status=ERROR"); - delay(1000); - - //Read IP address. - gsm.SimpleWriteln("AT+CIFSR"); - delay(5000); - //Read until serial buffer is empty. - gsm.WhileSimpleRead(); - - //TCP Client GET, send a GET request to the server and - //save the reply. - numdata=inet.httpGET("www.google.com", 80, "/", msg, 50); - //Print the results. - Serial.println("\nNumber of data received:"); - Serial.println(numdata); - Serial.println("\nData received:"); - Serial.println(msg); - } + //Serial connection. + Serial.begin(9600); + Serial.println("GSM Shield testing."); + //Start configuration of shield with baudrate. + //For http uses is raccomanded to use 4800 or slower. + if (gsm.begin(2400)){ + Serial.println("\nstatus=READY"); + started=true; + } + else Serial.println("\nstatus=IDLE"); + + if(started){ + //GPRS attach, put in order APN, username and password. + //If no needed auth let them blank. + if (inet.attachGPRS("internet.wind", "", "")) + Serial.println("status=ATTACHED"); + else Serial.println("status=ERROR"); + delay(1000); + + //Read IP address. + gsm.SimpleWriteln("AT+CIFSR"); + delay(5000); + //Read until serial buffer is empty. + gsm.WhileSimpleRead(); + + //TCP Client GET, send a GET request to the server and + //save the reply. + numdata=inet.httpGET("www.google.com", 80, "/", msg, 50); + //Print the results. + Serial.println("\nNumber of data received:"); + Serial.println(numdata); + Serial.println("\nData received:"); + Serial.println(msg); + } }; -void loop() +void loop() { - //Read for new byte on serial hardware, - //and write them on NewSoftSerial. - serialhwread(); - //Read for new byte on NewSoftSerial. - serialswread(); + //Read for new byte on serial hardware, + //and write them on NewSoftSerial. + serialhwread(); + //Read for new byte on NewSoftSerial. + serialswread(); }; -void serialhwread() -{ - i=0; - if (Serial.available() > 0) { - while (Serial.available() > 0) { - inSerial[i]=(Serial.read()); - delay(10); - i++; - } - - inSerial[i]='\0'; - if(!strcmp(inSerial,"/END")) { - Serial.println("_"); - inSerial[0]=0x1a; - inSerial[1]='\0'; - gsm.SimpleWriteln(inSerial); - } - //Send a saved AT command using serial port. - if(!strcmp(inSerial,"TEST")) { - Serial.println("SIGNAL QUALITY"); - gsm.SimpleWriteln("AT+CSQ"); - } - //Read last message saved. - if(!strcmp(inSerial,"MSG")) { - Serial.println(msg); - } else { - Serial.println(inSerial); - gsm.SimpleWriteln(inSerial); - } - inSerial[0]='\0'; - } +void serialhwread(){ + i=0; + if (Serial.available() > 0){ + while (Serial.available() > 0) { + inSerial[i]=(Serial.read()); + delay(10); + i++; + } + + inSerial[i]='\0'; + if(!strcmp(inSerial,"/END")){ + Serial.println("_"); + inSerial[0]=0x1a; + inSerial[1]='\0'; + gsm.SimpleWriteln(inSerial); + } + //Send a saved AT command using serial port. + if(!strcmp(inSerial,"TEST")){ + Serial.println("SIGNAL QUALITY"); + gsm.SimpleWriteln("AT+CSQ"); + } + //Read last message saved. + if(!strcmp(inSerial,"MSG")){ + Serial.println(msg); + } + else{ + Serial.println(inSerial); + gsm.SimpleWriteln(inSerial); + } + inSerial[0]='\0'; + } } -void serialswread() -{ - gsm.SimpleRead(); +void serialswread(){ + gsm.SimpleRead(); } diff --git a/examples/GSM_GPRSLibrary_DTMF/GSM_GPRSLibrary_DTMF.ino b/examples/GSM_GPRSLibrary_DTMF/GSM_GPRSLibrary_DTMF.ino index a1a310f..9271a86 100644 --- a/examples/GSM_GPRSLibrary_DTMF/GSM_GPRSLibrary_DTMF.ino +++ b/examples/GSM_GPRSLibrary_DTMF/GSM_GPRSLibrary_DTMF.ino @@ -14,7 +14,8 @@ //Simple sketch to detect DTMF tones during a call //We have to create the classes for calls. -CallGSM call; +CSIMCOM900 gsm(&Serial1); +CCallGSM call(gsm); char number[20]; byte stat=0; @@ -24,40 +25,42 @@ char value_str[5]; char DTMF_char='_'; int count=0; -void setup() +void setup() { - pinMode(pin,INPUT); - //Serial connection. - Serial.begin(9600); - Serial.println("GSM Shield testing."); - //Start configuration of shield with baudrate. - //For http uses is raccomanded to use 4800 or slower. - if (gsm.begin(9600)) - Serial.println("\nstatus=READY"); - else Serial.println("\nstatus=IDLE"); - //Enable DTMF detection for SIM900 - call.SetDTMF(1); + pinMode(pin,INPUT); + //Serial connection. + Serial.begin(9600); + Serial.println("GSM Shield testing."); + //Start configuration of shield with baudrate. + //For http uses is raccomanded to use 4800 or slower. + if (gsm.begin(9600)) + Serial.println("\nstatus=READY"); + else Serial.println("\nstatus=IDLE"); + //Enable DTMF detection for SIM900 + call.SetDTMF(1); }; -void loop() +void loop() { - //Chekcs status of call - stat=call.CallStatus(); - //If the incoming call is from an authorized number - //saved on SIM in the positions range from 1 to 3. - if(stat==CALL_INCOM_VOICE) { - Serial.println("Pick Up"); - delay(50); - call.PickUp(); - } - while(stat==CALL_ACTIVE_VOICE) { - for (int k=0; k<100; k++) { - DTMF_char=call.DetDTMF(); - if(DTMF_char!='-') - Serial.println(DTMF_char); - } - stat=call.CallStatus(); - - } - delay(1000); -}; + //Chekcs status of call + stat=call.CallStatus(); + //If the incoming call is from an authorized number + //saved on SIM in the positions range from 1 to 3. + if(stat==CALL_INCOM_VOICE) + { + Serial.println("Pick Up"); + delay(50); + call.PickUp(); + } + while(stat==CALL_ACTIVE_VOICE){ + for (int k=0; k<100; k++) + { + DTMF_char=call.DetDTMF(); + if(DTMF_char!='-') + Serial.println(DTMF_char); + } + stat=call.CallStatus(); + + } + delay(1000); +}; diff --git a/examples/GSM_GPRSLibrary_GPS/GSM_GPRSLibrary_GPS.ino b/examples/GSM_GPRSLibrary_GPS/GSM_GPRSLibrary_GPS.ino index 90c0607..77cd04d 100644 --- a/examples/GSM_GPRSLibrary_GPS/GSM_GPRSLibrary_GPS.ino +++ b/examples/GSM_GPRSLibrary_GPS/GSM_GPRSLibrary_GPS.ino @@ -13,10 +13,8 @@ //Simple sketch to start a connection as client. -//InetGSM inet; -//CallGSM call; -//SMSGSM sms; -GPSGSM gps; +CSIMCOM900 gsm(&Serial1); +CGPSGSM gps(gsm); char lon[15]; char lat[15]; @@ -31,74 +29,74 @@ char inSerial[20]; int i=0; boolean started=false; -void setup() +void setup() { - //Serial connection. - Serial.begin(9600); - Serial.println("GSM Shield testing."); - //Start configuration of shield with baudrate. - //For http uses is raccomanded to use 4800 or slower. - if (gsm.begin(2400)) { - Serial.println("\nstatus=READY"); - gsm.forceON(); //To ensure that SIM908 is not only in charge mode - started=true; - } else Serial.println("\nstatus=IDLE"); - - if(started) { - //GPS attach - if (gps.attachGPS()) - Serial.println("status=GPSREADY"); - else Serial.println("status=ERROR"); - - delay(20000); //Time for fixing - stat=gps.getStat(); - if(stat==1) - Serial.println("NOT FIXED"); - else if(stat==0) - Serial.println("GPS OFF"); - else if(stat==2) - Serial.println("2D FIXED"); - else if(stat==3) - Serial.println("3D FIXED"); - delay(5000); - //Get data from GPS - gps.getPar(lon,lat,alt,time,vel); - Serial.println(lon); - Serial.println(lat); - Serial.println(alt); - Serial.println(time); - Serial.println(vel); - } + //Serial connection. + Serial.begin(9600); + Serial.println("GSM Shield testing."); + //Start configuration of shield with baudrate. + //For http uses is raccomanded to use 4800 or slower. + if (gsm.begin(2400)){ + Serial.println("\nstatus=READY"); + gsm.forceON(); //To ensure that SIM908 is not only in charge mode + started=true; + } + else Serial.println("\nstatus=IDLE"); + + if(started){ + //GPS attach + if (gps.attachGPS()) + Serial.println("status=GPSREADY"); + else Serial.println("status=ERROR"); + + delay(20000); //Time for fixing + stat=gps.getStat(); + if(stat==1) + Serial.println("NOT FIXED"); + else if(stat==0) + Serial.println("GPS OFF"); + else if(stat==2) + Serial.println("2D FIXED"); + else if(stat==3) + Serial.println("3D FIXED"); + delay(5000); + //Get data from GPS + gps.getPar(lon,lat,alt,time,vel); + Serial.println(lon); + Serial.println(lat); + Serial.println(alt); + Serial.println(time); + Serial.println(vel); + } }; -void loop() +void loop() { - //Read for new byte on serial hardware, - //and write them on NewSoftSerial. - serialhwread(); - //Read for new byte on NewSoftSerial. - serialswread(); + //Read for new byte on serial hardware, + //and write them on NewSoftSerial. + serialhwread(); + //Read for new byte on NewSoftSerial. + serialswread(); }; -void serialhwread() -{ - i=0; - if (Serial.available() > 0) { - while (Serial.available() > 0) { - inSerial[i]=(Serial.read()); - delay(10); - i++; - } - - inSerial[i]='\0'; - if(!strcmp(inSerial,"/END")) { - Serial.println("_"); - inSerial[0]=0x1a; - inSerial[1]='\0'; - gsm.SimpleWriteln(inSerial); - } - //Send a saved AT command using serial port. - if(!strcmp(inSerial,"TEST")) { +void serialhwread(){ + i=0; + if (Serial.available() > 0){ + while (Serial.available() > 0) { + inSerial[i]=(Serial.read()); + delay(10); + i++; + } + + inSerial[i]='\0'; + if(!strcmp(inSerial,"/END")){ + Serial.println("_"); + inSerial[0]=0x1a; + inSerial[1]='\0'; + gsm.SimpleWriteln(inSerial); + } + //Send a saved AT command using serial port. + if(!strcmp(inSerial,"TEST")){ // Serial.println("BATTERY TEST 1"); // gps.getBattInf(msg1,msg2); // Serial.println(msg1); @@ -106,28 +104,28 @@ void serialhwread() // Serial.println("BATTERY TEST 2"); // gps.getBattTVol(msg1); // Serial.println(msg1); - stat=gps.getStat(); - if(stat==1) - Serial.println("NOT FIXED"); - else if(stat==0) - Serial.println("GPS OFF"); - else if(stat==2) - Serial.println("2D FIXED"); - else if(stat==3) - Serial.println("3D FIXED"); - } - //Read last message saved. - if(!strcmp(inSerial,"MSG")) { - Serial.println(msg1); - } else { - Serial.println(inSerial); - gsm.SimpleWriteln(inSerial); - } - inSerial[0]='\0'; - } + stat=gps.getStat(); + if(stat==1) + Serial.println("NOT FIXED"); + else if(stat==0) + Serial.println("GPS OFF"); + else if(stat==2) + Serial.println("2D FIXED"); + else if(stat==3) + Serial.println("3D FIXED"); + } + //Read last message saved. + if(!strcmp(inSerial,"MSG")){ + Serial.println(msg1); + } + else{ + Serial.println(inSerial); + gsm.SimpleWriteln(inSerial); + } + inSerial[0]='\0'; + } } -void serialswread() -{ - gsm.SimpleRead(); -} +void serialswread(){ + gsm.SimpleRead(); +} diff --git a/examples/GSM_GPRSLibrary_SMS/GSM_GPRSLibrary_SMS.ino b/examples/GSM_GPRSLibrary_SMS/GSM_GPRSLibrary_SMS.ino index c9cca85..0f3aa0c 100644 --- a/examples/GSM_GPRSLibrary_SMS/GSM_GPRSLibrary_SMS.ino +++ b/examples/GSM_GPRSLibrary_SMS/GSM_GPRSLibrary_SMS.ino @@ -4,11 +4,13 @@ //for RAM saving. //If your sketch reboots itself proprably you have finished, //your memory available. -//#include "inetGSM.h" - -//If you want to use the Arduino functions to manage SMS, uncomment the lines below. +#include "SIM900.h" +#include #include "sms.h" -SMSGSM sms; + + +CSIMCOM900 gsm(&Serial1); +CSMSGSM sms(gsm); //To change pins for Software Serial, use the two lines in GSM.cpp. @@ -18,46 +20,43 @@ SMSGSM sms; //Simple sketch to send and receive SMS. -int numdata; -boolean started=false; -char smsbuffer[160]; -char n[20]; +boolean bStarted=false; +const uint8_t nLenSMSTextBuff = 160, nLenSMSNumberBuff = 20 +uint8_t arraySMSTextBuff[nLenSMSTextBuff]; +char arraySMSNumberBuff[nLenSMSNumberBuff]; -void setup() +void setup() { - //Serial connection. - Serial.begin(9600); - Serial.println("GSM Shield testing."); - //Start configuration of shield with baudrate. - //For http uses is raccomanded to use 4800 or slower. - if (gsm.begin(2400)) { - Serial.println("\nstatus=READY"); - started=true; - } else Serial.println("\nstatus=IDLE"); - - if(started) { - //Enable this two lines if you want to send an SMS. - //if (sms.SendSMS("3471234567", "Arduino SMS")) - //Serial.println("\nSMS sent OK"); - } + // Serial connection. + Serial.begin(115200); + Serial.println("GSM Shield testing."); + + // Start configuration of shield with baudrate. + if (gsm.begin(115200)) + { + Serial.println("\nstatus=READY"); + bStarted=true; + } + else Serial.println("\nstatus=IDLE"); + + if (bStarted) + { + if (sms.SendSMS("3471234567", "Arduino SMS")) + Serial.println("\nSMS sent OK"); + } }; -void loop() +void loop() { - if(started) { - //Read if there are messages on SIM card and print them. - /** deprecated method - if(gsm.readSMS(smsbuffer, 160, n, 20)) { - Serial.println(n); - Serial.println(smsbuffer); - } - **/ - //get 1st sms - sms.GetSMS(1,n,20,smsbuffer,160); - Serial.println(n); - Serial.println(smsbuffer); - - delay(1000); - } -}; + if (bStarted) + { + //Read if there are messages on SIM card and print them. + if (sms.GetSMS(arraySMSNumberBuff, arraySMSTextBuff, nLenSMSTextBuff)) + { + Serial.println((char*)arrayBuff); + Serial.println(arraySMSBuff); + } + delay(1000); + } +}; \ No newline at end of file diff --git a/examples/GSM_GPRSLibrary_Server/GSM_GPRSLibrary_Server.ino b/examples/GSM_GPRSLibrary_Server/GSM_GPRSLibrary_Server.ino index db6d08c..d975e0b 100644 --- a/examples/GSM_GPRSLibrary_Server/GSM_GPRSLibrary_Server.ino +++ b/examples/GSM_GPRSLibrary_Server/GSM_GPRSLibrary_Server.ino @@ -12,9 +12,9 @@ //Simple sketch to start a connection as server. -InetGSM inet; -//CallGSM call; -//SMSGSM sms; +CSIMCOM900 gsm(&Serial1); +CInetGSM inet(gsm); + char msg[50]; int numdata; @@ -23,96 +23,96 @@ int i=0; boolean started=false; long lasttime=millis(); -void setup() +void setup() { - //Serial connection. - Serial.begin(9600); - Serial.println("GSM Shield testing."); - //Start configuration of shield with baudrate. - //For http uses is raccomanded to use 4800 or slower. - if (gsm.begin(2400)) { - Serial.println("\nstatus=READY"); - started=true; - } else Serial.println("\nstatus=IDLE"); - - if(started) { - //GPRS attach, put in order APN, username and password. - //If no needed auth let them blank. - if (inet.attachGPRS("internet.wind", "", "")) - Serial.println("status=ATTACHED"); - else Serial.println("status=ERROR"); - delay(1000); + //Serial connection. + Serial.begin(9600); + Serial.println("GSM Shield testing."); + //Start configuration of shield with baudrate. + //For http uses is raccomanded to use 4800 or slower. + if (gsm.begin(2400)){ + Serial.println("\nstatus=READY"); + started=true; + } + else Serial.println("\nstatus=IDLE"); + + if(started){ + //GPRS attach, put in order APN, username and password. + //If no needed auth let them blank. + if (inet.attachGPRS("internet.wind", "", "")) + Serial.println("status=ATTACHED"); + else Serial.println("status=ERROR"); + delay(1000); + + //Read IP address. + gsm.SimpleWriteln("AT+CIFSR"); + delay(5000); + int i=0; + while(i<20){ + gsm.SimpleRead(); + i++; + } - //Read IP address. - gsm.SimpleWriteln("AT+CIFSR"); - delay(5000); - int i=0; - while(i<20) { - gsm.SimpleRead(); - i++; - } - - //TCP Server. Start the socket connection - //as server on the assigned port. - Serial.println(msg); - delay(5000); - if (inet.connectTCPServer(80)) - Serial.println("status=TCPSERVERWAIT"); - else Serial.println("ERROR in Server"); - lasttime=millis(); - } + //TCP Server. Start the socket connection + //as server on the assigned port. + Serial.println(msg); + delay(5000); + if (inet.connectTCPServer(80)) + Serial.println("status=TCPSERVERWAIT"); + else Serial.println("ERROR in Server"); + lasttime=millis(); + } }; -void loop() -{ - if(started) { - //Check if there is an active connection. - if (inet.connectedClient()) { - //Read and print the last message received. - gsm.read(msg, 50); - Serial.println(msg); - } - } else { - serialhwread(); - serialswread(); - } +void loop(){ + if(started){ + //Check if there is an active connection. + if (inet.connectedClient()){ + //Read and print the last message received. + gsm.read(msg, 50); + Serial.println(msg); + } + } + else{ + serialhwread(); + serialswread(); + } }; -void serialhwread() -{ - i=0; - if (Serial.available() > 0) { - while (Serial.available() > 0) { - inSerial[i]=(Serial.read()); - delay(10); - i++; - } - - inSerial[i]='\0'; - if(!strcmp(inSerial,"/END")) { - Serial.println("_"); - inSerial[0]=0x1a; - inSerial[1]='\0'; - gsm.SimpleWriteln(inSerial); - } - //Send a saved AT command using serial port. - if(!strcmp(inSerial,"TEST")) { - Serial.println("SIGNAL QUALITY"); - gsm.SimpleWriteln("AT+CSQ"); - } - //Read last message saved. - if(!strcmp(inSerial,"MSG")) { - Serial.println(msg); - } else { - Serial.println(inSerial); - gsm.SimpleWriteln(inSerial); - } - inSerial[0]='\0'; - } +void serialhwread(){ + i=0; + if (Serial.available() > 0){ + while (Serial.available() > 0) { + inSerial[i]=(Serial.read()); + delay(10); + i++; + } + + inSerial[i]='\0'; + if(!strcmp(inSerial,"/END")){ + Serial.println("_"); + inSerial[0]=0x1a; + inSerial[1]='\0'; + gsm.SimpleWriteln(inSerial); + } + //Send a saved AT command using serial port. + if(!strcmp(inSerial,"TEST")){ + Serial.println("SIGNAL QUALITY"); + gsm.SimpleWriteln("AT+CSQ"); + } + //Read last message saved. + if(!strcmp(inSerial,"MSG")){ + Serial.println(msg); + } + else{ + Serial.println(inSerial); + gsm.SimpleWriteln(inSerial); + } + inSerial[0]='\0'; + } } -void serialswread() -{ - gsm.SimpleRead(); +void serialswread(){ + gsm.SimpleRead(); } \ No newline at end of file diff --git a/gps.cpp b/gps.cpp index c7445ef..e7183dd 100644 --- a/gps.cpp +++ b/gps.cpp @@ -1,203 +1,210 @@ #include "gps.h" -char GPSGSM::getBattInf(char *str_perc, char *str_vol) + +bool CGPSGSM::getBattInf(char *strPerc, char *strVol) { - char ret_val=0; - char *p_char; - char *p_char1; - - gsm.SimpleWriteln("AT+CBC"); - gsm.WaitResp(5000, 100, "OK"); - if(gsm.IsStringReceived("+CBC")) - ret_val=1; - - //BCL - p_char = strchr((char *)(gsm.comm_buf),','); - p_char1 = p_char+1; //we are on the first char of BCS - p_char = strchr((char *)(p_char1), ','); - if (p_char != NULL) { - *p_char = 0; - } - strcpy(str_perc, (char *)(p_char1)); - - //Voltage - p_char++; - p_char1 = strchr((char *)(p_char), '\r'); - if (p_char1 != NULL) { - *p_char1 = 0; - } - strcpy(str_vol, (char *)(p_char)); - return ret_val; + bool bRetVal = false; + char *str1 = NULL; + char *str2 = NULL; + + m_rSimComm900.SimpleWriteln(F("AT+CBC")); + m_rSimComm900.WaitResp(5000, 100, F("OK")); + if (m_rSimComm900.IsStringReceived(F("+CBC"))) + bRetVal = true; + + //BCL + str1 = strchr(m_rSimComm900.m_arrayCommBuff,','); + str2 = str1+1; //we are on the first char of BCS + str1 = strchr(str2, ','); + + if (str1 != NULL) + *str1 = 0; + + strcpy(strPerc, str2); + + //Voltage + str1++; + str2 = strchr(str1, '\r'); + if (str2 != NULL) + *str2 = 0; + + strcpy(strVol, str1); + return bRetVal; } -char GPSGSM::getBattTVol(char *str_vol) +bool CGPSGSM::getBattTVol(char *strVol) { - char *p_char; - char *p_char1; - char ret_val=0; - - gsm.SimpleWriteln("AT+CBTE?"); - gsm.WaitResp(5000, 100, "OK"); - if(gsm.IsStringReceived("+CBTE")) - ret_val=1; - - //BCL - p_char = strchr((char *)(gsm.comm_buf),':'); - p_char1 = p_char+2; //we are on the first char of BCS - p_char = strchr((char *)(p_char1), '\r'); - if (p_char != NULL) { - *p_char = 0; - } - strcpy(str_vol, (char *)(p_char1)); - return ret_val; + char *str1 = NULL; + char *str2 = NULL; + bool bRetVal = false; + + m_rSimComm900.SimpleWriteln(F("AT+CBTE?")); + m_rSimComm900.WaitResp(5000, 100, F("OK")); + if (m_rSimComm900.IsStringReceived(F("+CBTE"))) + bRetVal = true; + + //BCL + str1 = strchr(m_rSimComm900.m_arrayCommBuff,':'); + str2 = str1+2; //we are on the first char of BCS + str1 = strchr(str2, '\r'); + if (str1 != NULL) + *str1 = 0; + + strcpy(strVol, str2); + return bRetVal; } -char GPSGSM::attachGPS() +bool CGPSGSM::attachGPS() { - if(AT_RESP_ERR_DIF_RESP == gsm.SendATCmdWaitResp("AT+CGPSPWR=1", 500, 100, "OK", 5)) - return 0; - if(AT_RESP_ERR_DIF_RESP == gsm.SendATCmdWaitResp("AT+CGPSRST=1", 500, 100, "OK", 5)) - return 0; - return 1; + if (AT_RESP_ERR_DIF_RESP == m_rSimComm900.SendATCmdWaitResp(F("AT+CGPSPWR=1"), 500, 100, F("OK"), 5)) + return false; + if (AT_RESP_ERR_DIF_RESP == m_rSimComm900.SendATCmdWaitResp(F("AT+CGPSRST=1"), 500, 100, F("OK"), 5)) + return false; + + return true; } -char GPSGSM::deattachGPS() +bool CGPSGSM::deattachGPS() { - if(AT_RESP_ERR_DIF_RESP == gsm.SendATCmdWaitResp("AT+CGPSPWR=0", 500, 100, "OK", 5)) - return 0; - return 1; + if (AT_RESP_ERR_DIF_RESP == m_rSimComm900.SendATCmdWaitResp(F("AT+CGPSPWR=0"), 500, 100, F("OK"), 5)) + return false; + + return true; } -char GPSGSM::getStat() +char CGPSGSM::getStat() { - char ret_val=-1; - gsm.SimpleWriteln("AT+CGPSSTATUS?"); - gsm.WaitResp(5000, 100, "OK"); - if(gsm.IsStringReceived("Unknown")||gsm.IsStringReceived("unknown")) - ret_val=0; - else if(gsm.IsStringReceived("Not")) - ret_val=1; - else if(gsm.IsStringReceived("2D")||gsm.IsStringReceived("2d")) - ret_val=2; - else if(gsm.IsStringReceived("3D")||gsm.IsStringReceived("3d")) - ret_val=3; - return ret_val; + char nRetVal =- 1; + + m_rSimComm900.SimpleWriteln(F("AT+CGPSSTATUS?")); + m_rSimComm900.WaitResp(5000, 100, F("OK")); + + if (m_rSimComm900.IsStringReceived("Unknown") || m_rSimComm900.IsStringReceived(F("unknown"))) + nRetVal = 0; + else if (m_rSimComm900.IsStringReceived(F("Not"))) + nRetVal = 1; + else if (m_rSimComm900.IsStringReceived(F("2D")) || m_rSimComm900.IsStringReceived(F("2d"))) + nRetVal = 2; + else if (m_rSimComm900.IsStringReceived(F("3D")) || m_rSimComm900.IsStringReceived(F("3d"))) + nRetVal = 3; + + return nRetVal; } -char GPSGSM::getPar(char *str_long, char *str_lat, char *str_alt, char *str_time, char *str_speed) +char CGPSGSM::getPar(char *strLongitude, char *strLatitude, char *strAltitude, char *strTime, char *str_speed) { - char ret_val=0; - char *p_char; - char *p_char1; - gsm.SimpleWriteln("AT+CGPSINF=0"); - gsm.WaitResp(5000, 100, "OK"); - if(gsm.IsStringReceived("OK")) - ret_val=1; - - //longitude - p_char = strchr((char *)(gsm.comm_buf),','); - p_char1 = p_char+1; //we are on the first char of longitude - p_char = strchr((char *)(p_char1), ','); - if (p_char != NULL) { - *p_char = 0; - } - strcpy(str_long, (char *)(p_char1)); - - // latitude - p_char++; - p_char1 = strchr((char *)(p_char), ','); - if (p_char1 != NULL) { - *p_char1 = 0; - } - strcpy(str_lat, (char *)(p_char)); - - // altitude - p_char1++; - p_char = strchr((char *)(p_char1), ','); - if (p_char != NULL) { - *p_char = 0; - } - strcpy(str_alt, (char *)(p_char1)); - - // UTC time - p_char++; - p_char1 = strchr((char *)(p_char), ','); - if (p_char1 != NULL) { - *p_char1 = 0; - } - strcpy(str_time, (char *)(p_char)); - - // TTFF - p_char1++; - p_char = strchr((char *)(p_char1), ','); - if (p_char != NULL) { - *p_char = 0; - } - - // num - p_char++; - p_char1 = strchr((char *)(p_char), ','); - if (p_char1 != NULL) { - *p_char1 = 0; - } - - // speed - p_char1++; - p_char = strchr((char *)(p_char1), ','); - if (p_char != NULL) { - *p_char = 0; - } - strcpy(str_speed, (char *)(p_char1)); - - return ret_val; + char nRetVal = 0; + char *str1 = NULL; + char *str2 = NULL; + + m_rSimComm900.SimpleWriteln(F("AT+CGPSINF=0")); + m_rSimComm900.WaitResp(5000, 100, F("OK")); + if (m_rSimComm900.IsStringReceived(F("OK"))) + nRetVal = 1; + + //dLongitude + str1 = strchr(m_rSimComm900.m_arrayCommBuff,','); + str2 = str1 + 1; //we are on the first char of dLongitude + str1 = strchr(str2, ','); + if (str1 != NULL) + *str1 = 0; + + strcpy(strLongitude, str2); + + // dLatitude + str1++; + str2 = strchr(str1, ','); + if (str2 != NULL) + *str2 = 0; + + strcpy(strLatitude, str1); + + // altitude + str2++; + str1 = strchr(str2, ','); + if (str1 != NULL) + *str1 = 0; + + strcpy(strAltitude, str2); + + // UTC nTime + str1++; + str2 = strchr(str1, ','); + if (str2 != NULL) + *str2 = 0; + + strcpy(strTime, str1); + + // TTFF + str2++; + str1 = strchr(str2, ','); + if (str1 != NULL) + *str1 = 0; + + // num + str1++; + str2 = strchr(str1, ','); + if (str2 != NULL) + *str2 = 0; + + // strSpeed + str2++; + str1 = strchr(str2, ','); + if (str1 != NULL) + *str1 = 0; + + strcpy(str_speed, str2); + + return nRetVal; } -void parseTime(char *field, int *time) +void parseTime(char *strField, int16_t *nTime) { - ////////////////Time//////////// - char tmp[4]; - tmp[2]=0; // Init tmp and null terminate - tmp[0] = field[8]; - tmp[1] = field[9]; - time[0] = atoi(tmp); // Hours - tmp[0] = field[10]; - tmp[1] = field[11]; - time[1] = atoi(tmp); // Minutes - tmp[0] = field[12]; - tmp[1] = field[13]; - time[2] = atoi(tmp); // Seconds - /////////////Date/////////////// - tmp[0] = field[0]; - tmp[1] = field[1]; - tmp[2] = field[2]; - tmp[3] = field[3]; - tmp[4]=0; // Init tmp and null terminate - time[3] = atoi(tmp); // year - tmp[0] = field[4]; - tmp[1] = field[5]; - tmp[2]=0; // Init tmp and null terminate - time[4] = atoi(tmp); // month - tmp[0] = field[6]; - tmp[1] = field[7]; - tmp[2]=0; // Init tmp and null terminate - time[5] = atoi(tmp); // day + ////////////////Time//////////// + char strTemp[4]; + + strTemp[2]=0; // Init strTemp and null terminate + strTemp[0] = strField[8]; + strTemp[1] = strField[9]; + nTime[0] = atoi(strTemp); // Hours + strTemp[0] = strField[10]; + strTemp[1] = strField[11]; + nTime[1] = atoi(strTemp); // Minutes + strTemp[0] = strField[12]; + strTemp[1] = strField[13]; + nTime[2] = atoi(strTemp); // Seconds + /////////////Date/////////////// + strTemp[0] = strField[0]; + strTemp[1] = strField[1]; + strTemp[2] = strField[2]; + strTemp[3] = strField[3]; + strTemp[4]=0; // Init strTemp and null terminate + nTime[3] = atoi(strTemp); // year + strTemp[0] = strField[4]; + strTemp[1] = strField[5]; + strTemp[2]=0; // Init strTemp and null terminate + nTime[4] = atoi(strTemp); // month + strTemp[0] = strField[6]; + strTemp[1] = strField[7]; + strTemp[2]=0; // Init strTemp and null terminate + nTime[5] = atoi(strTemp); // day } -// Read the latitude in decimal format from a GGA string -double convertLat(char* latString) +// Read the dLatitude in decimal format from a GGA string +double convertLat(char* strLatitude) { - double latitude = atof(latString); // convert to a double (precise) - int deg = (int) latitude / 100; // extract the number of degrees - double min = latitude - (100 * deg); // work out the number of minutes - latitude = deg + (double) min/60.0; // convert to decimal format - return latitude; + double dLatitude = atof(strLatitude); // convert to a double (precise) + int16_t nDegrees = (int16_t)dLatitude / 100; // extract the number of degrees + double dMinutes = dLatitude - (100 * nDegrees); // work out the number of minutes + dLatitude = nDegrees + (dMinutes / 60.0); // convert to decimal format + return dLatitude; } -// Read the longitude in decimal format from a GGA string -double convertLong(char* longString) +// Read the dLongitude in decimal format from a GGA string +double convertLong(char* longString) { - double longitude = atof(longString); // convert to a double - int deg = (int) longitude / 100; // extract the number of degrees - double min = longitude - (100 * deg); // work out the number of minutes - longitude = deg + (double) min/60.00; // convert to decimal format - return longitude; + double dLongitude = atof(longString); // convert to a double + int16_t nDegrees = (int16_t)dLongitude / 100; // extract the number of degrees + double dMinutes = dLongitude - (100 * nDegrees); // work out the number of minutes + dLongitude = nDegrees + (dMinutes / 60.00); // convert to decimal format + return dLongitude; } \ No newline at end of file diff --git a/gps.h b/gps.h index 1da04f4..572e311 100644 --- a/gps.h +++ b/gps.h @@ -1,19 +1,22 @@ #ifndef _GPS_H_ #define _GPS_H_ -#include "SIM900.h" +#include "GSMBase.h" -class GPSGSM { -public: - char getBattInf(char *str_perc, char *str_vol); - char getBattTVol(char *str_vol); - char attachGPS(); - char deattachGPS(); - char getStat(); - char getPar(char *str_long, char *str_lat, char *str_alt, char *str_time, char *speed); - void parseTime(char *field, int *time); - double convertLat(void); - double convertLong(void); +class CGPSGSM: protected CGSMBase +{ + public: + CGPSGSM(CSIMCOM900& rSimComm900): CGSMBase(rSimComm900){}; + + bool getBattInf(char *strPerc, char *strVol); + bool getBattTVol(char *strVol); + bool attachGPS(); + bool deattachGPS(); + char getStat(); + char getPar(char *strLongitude, char *strLatitude, char *strAltitude, char *strTime, char *strSpeed); + void parseTime(char *strField, int16_t *nTime); + double convertLat(void); + double convertLong(void); }; #endif diff --git a/inetGSM.cpp b/inetGSM.cpp index f3672ad..c813dc2 100644 --- a/inetGSM.cpp +++ b/inetGSM.cpp @@ -1,586 +1,518 @@ -#include "inetGSM.h" -#define _GSM_CONNECTION_TOUT_ 5 -#define _TCP_CONNECTION_TOUT_ 20 -#define _GSM_DATA_TOUT_ 10 - -int InetGSM::httpGET(const char* server, int port, const char* path, char* result, int resultlength) -{ - boolean connected=false; - int n_of_at=0; - int length_write; - char end_c[2]; - end_c[0]=0x1a; - end_c[1]='\0'; - - /* - Status = ATTACHED. - if(gsm.getStatus()!=GSM::ATTACHED) - return 0; - */ - while(n_of_at<3) { - if(!connectTCP(server, port)) { -#ifdef DEBUG_ON - Serial.println("DB:NOT CONN"); -#endif - n_of_at++; - } else { - connected=true; - n_of_at=3; - } - } - - if(!connected) return 0; - - gsm.SimpleWrite("GET "); - gsm.SimpleWrite(path); - gsm.SimpleWrite(" HTTP/1.0\r\nHost: "); - gsm.SimpleWrite(server); - gsm.SimpleWrite("\r\n"); - gsm.SimpleWrite("User-Agent: Arduino"); - gsm.SimpleWrite("\r\n\r\n"); - gsm.SimpleWrite(end_c); - - switch(gsm.WaitResp(10000, 10, "SEND OK")) { - case RX_TMOUT_ERR: - return 0; - break; - case RX_FINISHED_STR_NOT_RECV: - return 0; - break; - } - - - delay(50); -#ifdef DEBUG_ON - Serial.println("DB:SENT"); -#endif - int res = gsm.read(result, resultlength); - - //gsm.disconnectTCP(); - - //int res=1; - return res; -} - -int InetGSM::httpPOST(const char* server, int port, const char* path, const char* parameters, char* result, int resultlength) -{ - boolean connected=false; - int n_of_at=0; - char itoaBuffer[8]; - int num_char; - char end_c[2]; - end_c[0]=0x1a; - end_c[1]='\0'; - - while(n_of_at<3) { - if(!connectTCP(server, port)) { -#ifdef DEBUG_ON - Serial.println("DB:NOT CONN"); -#endif - n_of_at++; - } else { - connected=true; - n_of_at=3; - } - } - - if(!connected) return 0; - - gsm.SimpleWrite("POST "); - gsm.SimpleWrite(path); - gsm.SimpleWrite(" HTTP/1.1\r\nHost: "); - gsm.SimpleWrite(server); - gsm.SimpleWrite("\r\n"); - gsm.SimpleWrite("User-Agent: Arduino\r\n"); - gsm.SimpleWrite("Content-Type: application/x-www-form-urlencoded\r\n"); - gsm.SimpleWrite("Content-Length: "); - itoa(strlen(parameters),itoaBuffer,10); - gsm.SimpleWrite(itoaBuffer); - gsm.SimpleWrite("\r\n\r\n"); - gsm.SimpleWrite(parameters); - gsm.SimpleWrite("\r\n\r\n"); - gsm.SimpleWrite(end_c); - - switch(gsm.WaitResp(10000, 10, "SEND OK")) { - case RX_TMOUT_ERR: - return 0; - break; - case RX_FINISHED_STR_NOT_RECV: - return 0; - break; - } - - delay(50); -#ifdef DEBUG_ON - Serial.println("DB:SENT"); -#endif - - int res= gsm.read(result, resultlength); - //gsm.disconnectTCP(); - return res; -} - -int InetGSM::openmail(char* server, char* loginbase64, char* passbase64, char* from, char* to, char* subj) -{ - boolean connected=false; - int n_of_at=0; - char end_c[2]; - end_c[0]=0x1a; - end_c[1]='\0'; - - while(n_of_at<3) { - if(!connectTCP(server, 25)) { -#ifdef DEBUG_ON - Serial.println("DB:NOT CONN"); -#endif - n_of_at++; - } else { - connected=true; - n_of_at=3; - } - } - - if(!connected) return 0; - - delay(100); - gsm.SimpleWrite("HELO "); - gsm.SimpleWrite(server); - gsm.SimpleWrite("\n"); - gsm.SimpleWrite(end_c); - gsm.WaitResp(5000, 100, "OK"); - if(!gsm.IsStringReceived("SEND OK")) - return 0; - delay(500); - gsm.WaitResp(5000, 100); - - delay(100); - gsm.SimpleWriteln("AT+CIPSEND"); - switch(gsm.WaitResp(5000, 200, ">")) { - case RX_TMOUT_ERR: - return 0; - break; - case RX_FINISHED_STR_NOT_RECV: - return 0; - break; - } - gsm.SimpleWrite("AUTH LOGIN\n"); - gsm.SimpleWrite(end_c); - gsm.WaitResp(5000, 100, "OK"); - if(!gsm.IsStringReceived("OK")) - return 0; - delay(500); - gsm.WaitResp(5000, 100); - - delay(100); - gsm.SimpleWriteln("AT+CIPSEND"); - switch(gsm.WaitResp(5000, 200, ">")) { - case RX_TMOUT_ERR: - return 0; - break; - case RX_FINISHED_STR_NOT_RECV: - return 0; - break; - } - gsm.SimpleWrite(loginbase64); - gsm.SimpleWrite("\n"); - gsm.SimpleWrite(end_c); - gsm.WaitResp(5000, 100, "OK"); - if(!gsm.IsStringReceived("OK")) - return 0; - delay(500); - gsm.WaitResp(5000, 100); - - delay(100); - gsm.SimpleWriteln("AT+CIPSEND"); - switch(gsm.WaitResp(5000, 200, ">")) { - case RX_TMOUT_ERR: - return 0; - break; - case RX_FINISHED_STR_NOT_RECV: - return 0; - break; - } - gsm.SimpleWrite(passbase64); - gsm.SimpleWrite("\n"); - gsm.SimpleWrite(end_c); - gsm.WaitResp(5000, 100, "OK"); - if(!gsm.IsStringReceived("OK")) - return 0; - delay(500); - gsm.WaitResp(5000, 100); - - - delay(100); - gsm.SimpleWriteln("AT+CIPSEND"); - switch(gsm.WaitResp(5000, 200, ">")) { - case RX_TMOUT_ERR: - return 0; - break; - case RX_FINISHED_STR_NOT_RECV: - return 0; - break; - } - gsm.SimpleWrite("MAIL From: <"); - gsm.SimpleWrite(from); - gsm.SimpleWrite(">\n"); - gsm.SimpleWrite(end_c); - gsm.WaitResp(5000, 100, "OK"); - if(!gsm.IsStringReceived("OK")) - return 0; - delay(500); - gsm.WaitResp(5000, 100, ""); - - delay(100); - gsm.SimpleWriteln("AT+CIPSEND"); - switch(gsm.WaitResp(5000, 200, ">")) { - case RX_TMOUT_ERR: - return 0; - break; - case RX_FINISHED_STR_NOT_RECV: - return 0; - break; - } - gsm.SimpleWrite("RCPT TO: <"); - gsm.SimpleWrite(to); - gsm.SimpleWrite(">\n"); - gsm.SimpleWrite(end_c); - gsm.WaitResp(5000, 100, "OK"); - if(!gsm.IsStringReceived("OK")) - return 0; - delay(500); - gsm.WaitResp(5000, 100, ""); - - delay(100); - gsm.SimpleWriteln("AT+CIPSEND"); - switch(gsm.WaitResp(5000, 200, ">")) { - case RX_TMOUT_ERR: - return 0; - break; - case RX_FINISHED_STR_NOT_RECV: - return 0; - break; - } - gsm.SimpleWrite("Data\n"); - gsm.SimpleWrite(end_c); - gsm.WaitResp(5000, 100, "OK"); - if(!gsm.IsStringReceived("OK")) - return 0; - delay(500); - gsm.WaitResp(5000, 100, ""); - - delay(100); - gsm.SimpleWriteln("AT+CIPSEND"); - switch(gsm.WaitResp(5000, 200, ">")) { - case RX_TMOUT_ERR: - return 0; - break; - case RX_FINISHED_STR_NOT_RECV: - return 0; - break; - } - gsm.SimpleWrite("Subject: "); - gsm.SimpleWrite(subj); - gsm.SimpleWrite("\n\n"); - - return 1; -} -int InetGSM::closemail() -{ - char end_c[2]; - end_c[0]=0x1a; - end_c[1]='\0'; - - gsm.SimpleWrite("\n.\n"); - gsm.SimpleWrite(end_c); - disconnectTCP(); - return 1; -} - - -int InetGSM::attachGPRS(char* domain, char* dom1, char* dom2) -{ - int i=0; - delay(5000); - - //gsm._tf.setTimeout(_GSM_DATA_TOUT_); //Timeout for expecting modem responses. - gsm.WaitResp(50, 50); - gsm.SimpleWriteln("AT+CIFSR"); - if(gsm.WaitResp(5000, 50, "ERROR")!=RX_FINISHED_STR_RECV) { -#ifdef DEBUG_ON - Serial.println("DB:ALREADY HAVE AN IP"); -#endif - gsm.SimpleWriteln("AT+CIPCLOSE"); - gsm.WaitResp(5000, 50, "ERROR"); - delay(2000); - gsm.SimpleWriteln("AT+CIPSERVER=0"); - gsm.WaitResp(5000, 50, "ERROR"); - return 1; - } else { - -#ifdef DEBUG_ON - Serial.println("DB:STARTING NEW CONNECTION"); -#endif - - gsm.SimpleWriteln("AT+CIPSHUT"); - - switch(gsm.WaitResp(500, 50, "SHUT OK")) { - - case RX_TMOUT_ERR: - return 0; - break; - case RX_FINISHED_STR_NOT_RECV: - return 0; - break; - } -#ifdef DEBUG_ON - Serial.println("DB:SHUTTED OK"); -#endif - delay(1000); - - gsm.SimpleWrite("AT+CSTT=\""); - gsm.SimpleWrite(domain); - gsm.SimpleWrite("\",\""); - gsm.SimpleWrite(dom1); - gsm.SimpleWrite("\",\""); - gsm.SimpleWrite(dom2); - gsm.SimpleWrite("\"\r"); - - - switch(gsm.WaitResp(500, 50, "OK")) { - - case RX_TMOUT_ERR: - return 0; - break; - case RX_FINISHED_STR_NOT_RECV: - return 0; - break; - } -#ifdef DEBUG_ON - Serial.println("DB:APN OK"); -#endif - delay(5000); - - gsm.SimpleWriteln("AT+CIICR"); - - switch(gsm.WaitResp(10000, 50, "OK")) { - case RX_TMOUT_ERR: - return 0; - break; - case RX_FINISHED_STR_NOT_RECV: - return 0; - break; - } -#ifdef DEBUG_ON - Serial.println("DB:CONNECTION OK"); -#endif - - delay(1000); - - - gsm.SimpleWriteln("AT+CIFSR"); - if(gsm.WaitResp(5000, 50, "ERROR")!=RX_FINISHED_STR_RECV) { -#ifdef DEBUG_ON - Serial.println("DB:ASSIGNED AN IP"); -#endif - gsm.setStatus(gsm.ATTACHED); - return 1; - } -#ifdef DEBUG_ON - Serial.println("DB:NO IP AFTER CONNECTION"); -#endif - return 0; - } -} - -int InetGSM::dettachGPRS() -{ - if (gsm.getStatus()==gsm.IDLE) return 0; - - //gsm._tf.setTimeout(_GSM_CONNECTION_TOUT_); - - //_cell.flush(); - - //GPRS dettachment. - gsm.SimpleWriteln("AT+CGATT=0"); - if(gsm.WaitResp(5000, 50, "OK")!=RX_FINISHED_STR_NOT_RECV) { - gsm.setStatus(gsm.ERROR); - return 0; - } - delay(500); - - // Commented in initial trial code!! - //Stop IP stack. - //_cell << "AT+WIPCFG=0" << _DEC(cr) << endl; - // if(!gsm._tf.find("OK")) return 0; - //Close GPRS bearer. - //_cell << "AT+WIPBR=0,6" << _DEC(cr) << endl; - - gsm.setStatus(gsm.READY); - return 1; -} - -int InetGSM::connectTCP(const char* server, int port) -{ - //gsm._tf.setTimeout(_TCP_CONNECTION_TOUT_); - - //Status = ATTACHED. - //if (getStatus()!=ATTACHED) - //return 0; - - //_cell.flush(); - - //Visit the remote TCP server. - gsm.SimpleWrite("AT+CIPSTART=\"TCP\",\""); - gsm.SimpleWrite(server); - gsm.SimpleWrite("\","); - gsm.SimpleWriteln(port); - - switch(gsm.WaitResp(1000, 200, "OK")) { - case RX_TMOUT_ERR: - return 0; - break; - case RX_FINISHED_STR_NOT_RECV: - return 0; - break; - } -#ifdef DEBUG_ON - Serial.println("DB:RECVD CMD"); -#endif - if (!gsm.IsStringReceived("CONNECT OK")) { - switch(gsm.WaitResp(15000, 200, "OK")) { - case RX_TMOUT_ERR: - return 0; - break; - case RX_FINISHED_STR_NOT_RECV: - return 0; - break; - } - } - -#ifdef DEBUG_ON - Serial.println("DB:OK TCP"); -#endif - - delay(3000); - gsm.SimpleWriteln("AT+CIPSEND"); - switch(gsm.WaitResp(5000, 200, ">")) { - case RX_TMOUT_ERR: - return 0; - break; - case RX_FINISHED_STR_NOT_RECV: - return 0; - break; - } - -#ifdef DEBUG_ON - Serial.println("DB:>"); -#endif - delay(4000); - return 1; -} - -int InetGSM::disconnectTCP() -{ - //Status = TCPCONNECTEDCLIENT or TCPCONNECTEDSERVER. - /* - if ((getStatus()!=TCPCONNECTEDCLIENT)&&(getStatus()!=TCPCONNECTEDSERVER)) - return 0; - */ - //gsm._tf.setTimeout(_GSM_CONNECTION_TOUT_); - - - //_cell.flush(); - - //Switch to AT mode. - //_cell << "+++" << endl; - - //delay(200); - - //Close TCP client and deact. - gsm.SimpleWriteln("AT+CIPCLOSE"); - - //If remote server close connection AT+QICLOSE generate ERROR - /*if(gsm._tf.find("OK")) - { - if(getStatus()==TCPCONNECTEDCLIENT) - gsm.setStatus(ATTACHED); - else - gsm.setStatus(TCPSERVERWAIT); - return 1; - } - gsm.setStatus(ERROR); - - return 0; */ - if(gsm.getStatus()==gsm.TCPCONNECTEDCLIENT) - gsm.setStatus(gsm.ATTACHED); - else - gsm.setStatus(gsm.TCPSERVERWAIT); - return 1; -} - -int InetGSM::connectTCPServer(int port) -{ - /* - if (getStatus()!=ATTACHED) - return 0; - */ - //gsm._tf.setTimeout(_GSM_CONNECTION_TOUT_); - - //_cell.flush(); - - // Set port - - gsm.SimpleWrite("AT+CIPSERVER=1,"); - gsm.SimpleWriteln(port); - /* - switch(gsm.WaitResp(5000, 50, "OK")){ - case RX_TMOUT_ERR: - return 0; - break; - case RX_FINISHED_STR_NOT_RECV: - return 0; - break; - } - - switch(gsm.WaitResp(5000, 50, "SERVER")){ //Try SERVER OK - case RX_TMOUT_ERR: - return 0; - break; - case RX_FINISHED_STR_NOT_RECV: - return 0; - break; - } - */ - //delay(200); - - return 1; - -} - -boolean InetGSM::connectedClient() -{ - /* - if (getStatus()!=TCPSERVERWAIT) - return 0; - */ - - gsm.SimpleWriteln("AT+CIPSTATUS"); - // Alternative: AT+QISTAT, although it may be necessary to call an AT - // command every second,which is not wise - /* - switch(gsm.WaitResp(1000, 200, "OK")){ - case RX_TMOUT_ERR: - return 0; - break; - case RX_FINISHED_STR_NOT_RECV: - return 0; - break; - }*/ - //gsm._tf.setTimeout(1); - if(gsm.WaitResp(5000, 50, "CONNECT OK")!=RX_FINISHED_STR_RECV) { - gsm.setStatus(gsm.TCPCONNECTEDSERVER); - return true; - } else - return false; -} - +#include "inetGSM.h" +#define _GSM_CONNECTION_TOUT_ 5 +#define _TCP_CONNECTION_TOUT_ 20 +#define _GSM_DATA_TOUT_ 10 + +int16_t CInetGSM::httpGET(const char* strServer, int16_t nPort, const char* strPath, char* strResult, int16_t nResultLength) +{ + boolean bConnected = false; + int16_t nNumOfAt = 0; + int16_t nLengthWrite = 0; + char strEndC[2]; + + strEndC[0]=0x1a; + strEndC[1]='\0'; + + + while (nNumOfAt <3 ) + { + if (!connectTCP(strServer, nPort)) + { + #ifdef DEBUG_ON + Serial.println(F("DB:NOT CONN")); + #endif + nNumOfAt++; + } + else + { + bConnected = true; + nNumOfAt = 3; + } + } + + if (!bConnected) + return 0; + + m_rSimComm900.SimpleWrite(F("GET ")); + m_rSimComm900.SimpleWrite(strPath); + m_rSimComm900.SimpleWrite(F(" HTTP/1.0\nHost: ")); + m_rSimComm900.SimpleWrite(strServer); + m_rSimComm900.SimpleWrite(F("\n")); + m_rSimComm900.SimpleWrite(F("User-Agent: Arduino")); + m_rSimComm900.SimpleWrite(F("\n\n")); + m_rSimComm900.SimpleWrite(strEndC); + + switch (m_rSimComm900.WaitResp(10000, 10, F("SEND OK"))) + { + case RX_TMOUT_ERR: + return 0; + break; + case RX_FINISHED_STR_NOT_RECV: + return 0; + break; + } + + + delay(50); + #ifdef DEBUG_ON + Serial.println(F("DB:SENT")); + #endif + return m_rSimComm900.read(strResult, nResultLength); +} + +int16_t CInetGSM::httpPOST(const char* strServer, int16_t nPort, const char* strPath, const char* strParameters, char* strResult, int16_t nResultLength) +{ + boolean bConnected = false; + int16_t nNumOfAt = 0; + char strITOABuff[8]; + int16_t nNumChar = 0; + char strEndC[2]; + + strEndC[0] = 0x1a; + strEndC[1] = '\0'; + + while (nNumOfAt < 3) + { + if (!connectTCP(strServer, nPort)) + { + #ifdef DEBUG_ON + Serial.println(F("DB:NOT CONN")); + #endif + nNumOfAt++; + } + else + { + bConnected = true; + nNumOfAt = 3; + } + } + + if (!bConnected) + return 0; + + m_rSimComm900.SimpleWrite(F("POST ")); + m_rSimComm900.SimpleWrite(strPath); + m_rSimComm900.SimpleWrite(F(" HTTP/1.1\nHost: ")); + m_rSimComm900.SimpleWrite(strServer); + m_rSimComm900.SimpleWrite(F("\n")); + m_rSimComm900.SimpleWrite(F("User-Agent: Arduino\n")); + m_rSimComm900.SimpleWrite(F("Content-Type: application/x-www-form-urlencoded\n")); + m_rSimComm900.SimpleWrite(F("Content-Length: ")); + itoa(strlen(strParameters),strITOABuff,10); + m_rSimComm900.SimpleWrite(strITOABuff); + m_rSimComm900.SimpleWrite(F("\n\n")); + m_rSimComm900.SimpleWrite(strParameters); + m_rSimComm900.SimpleWrite(F("\n\n")); + m_rSimComm900.SimpleWrite(strEndC); + + switch(m_rSimComm900.WaitResp(10000, 10, F("SEND OK"))) + { + case RX_TMOUT_ERR: + return 0; + break; + case RX_FINISHED_STR_NOT_RECV: + return 0; + break; + } + + delay(50); + #ifdef DEBUG_ON + Serial.println(F("DB:SENT")); + #endif + + + return m_rSimComm900.read(strResult, nResultLength);; +} + +bool CInetGSM::openMail(char* strServer, char* strLoginBase64, char* strPasswordBase64, char* strFrom, char* strTo, char* strSubject) +{ + boolean bConnected = false; + int16_t nNumOfAt = 0; + char strEndC[2]; + + strEndC[0] = 0x1a; + strEndC[1] = '\0'; + + while (nNumOfAt < 3) + { + if (!connectTCP(strServer, 25)) + { + #ifdef DEBUG_ON + Serial.println(F("DB:NOT CONN")); + #endif + nNumOfAt++; + } + else + { + bConnected=true; + nNumOfAt=3; + } + } + + if (!bConnected) + return false; + + delay(100); + m_rSimComm900.SimpleWrite(F("HELO ")); + m_rSimComm900.SimpleWrite(strServer); + m_rSimComm900.SimpleWrite(F("\n")); + m_rSimComm900.SimpleWrite(strEndC); + m_rSimComm900.WaitResp(5000, 100, F("OK")); + if (!m_rSimComm900.IsStringReceived(F("SEND OK"))) + return false; + delay(500); + m_rSimComm900.WaitResp(5000, 100); + + delay(100); + m_rSimComm900.SimpleWriteln(F("AT+CIPSEND")); + switch(m_rSimComm900.WaitResp(5000, 200, F(">"))) + { + case RX_TMOUT_ERR: + return false; + break; + case RX_FINISHED_STR_NOT_RECV: + return false; + break; + } + m_rSimComm900.SimpleWrite(F("AUTH LOGIN\n")); + m_rSimComm900.SimpleWrite(strEndC); + m_rSimComm900.WaitResp(5000, 100, F("OK")); + if (!m_rSimComm900.IsStringReceived(F("OK"))) + return false; + delay(500); + m_rSimComm900.WaitResp(5000, 100); + + delay(100); + m_rSimComm900.SimpleWriteln(F("AT+CIPSEND")); + switch(m_rSimComm900.WaitResp(5000, 200, F(">"))) + { + case RX_TMOUT_ERR: + return false; + break; + case RX_FINISHED_STR_NOT_RECV: + return false; + break; + } + m_rSimComm900.SimpleWrite(strLoginBase64); + m_rSimComm900.SimpleWrite(F("\n")); + m_rSimComm900.SimpleWrite(strEndC); + m_rSimComm900.WaitResp(5000, 100, F("OK")); + if (!m_rSimComm900.IsStringReceived(F("OK"))) + return false; + delay(500); + m_rSimComm900.WaitResp(5000, 100); + + delay(100); + m_rSimComm900.SimpleWriteln(F("AT+CIPSEND")); + switch(m_rSimComm900.WaitResp(5000, 200, F(">"))) + { + case RX_TMOUT_ERR: + return false; + break; + case RX_FINISHED_STR_NOT_RECV: + return false; + break; + } + m_rSimComm900.SimpleWrite(strPasswordBase64); + m_rSimComm900.SimpleWrite(F("\n")); + m_rSimComm900.SimpleWrite(strEndC); + m_rSimComm900.WaitResp(5000, 100, F("OK")); + if (!m_rSimComm900.IsStringReceived(F("OK"))) + return false; + delay(500); + m_rSimComm900.WaitResp(5000, 100); + + delay(100); + m_rSimComm900.SimpleWriteln(F("AT+CIPSEND")); + switch(m_rSimComm900.WaitResp(5000, 200, F(">"))) + { + case RX_TMOUT_ERR: + return false; + break; + case RX_FINISHED_STR_NOT_RECV: + return false; + break; + } + m_rSimComm900.SimpleWrite(F("MAIL From: <")); + m_rSimComm900.SimpleWrite(strFrom); + m_rSimComm900.SimpleWrite(F(">\n")); + m_rSimComm900.SimpleWrite(strEndC); + m_rSimComm900.WaitResp(5000, 100, F("OK")); + if (!m_rSimComm900.IsStringReceived(F("OK"))) + return false; + delay(500); + m_rSimComm900.WaitResp(5000, 100, F("")); + + delay(100); + m_rSimComm900.SimpleWriteln(F("AT+CIPSEND")); + switch(m_rSimComm900.WaitResp(5000, 200, F(">"))) + { + case RX_TMOUT_ERR: + return false; + break; + case RX_FINISHED_STR_NOT_RECV: + return false; + break; + } + m_rSimComm900.SimpleWrite(F("RCPT TO: <")); + m_rSimComm900.SimpleWrite(strTo); + m_rSimComm900.SimpleWrite(F(">\n")); + m_rSimComm900.SimpleWrite(strEndC); + m_rSimComm900.WaitResp(5000, 100, F("OK")); + if (!m_rSimComm900.IsStringReceived(F("OK"))) + return false; + delay(500); + m_rSimComm900.WaitResp(5000, 100, F("")); + + delay(100); + m_rSimComm900.SimpleWriteln(F("AT+CIPSEND")); + switch(m_rSimComm900.WaitResp(5000, 200, F(">"))) + { + case RX_TMOUT_ERR: + return false; + break; + case RX_FINISHED_STR_NOT_RECV: + return false; + break; + } + m_rSimComm900.SimpleWrite(F("Data\n")); + m_rSimComm900.SimpleWrite(strEndC); + m_rSimComm900.WaitResp(5000, 100, F("OK")); + if (!m_rSimComm900.IsStringReceived(F("OK"))) + return false; + delay(500); + m_rSimComm900.WaitResp(5000, 100, F("")); + + delay(100); + m_rSimComm900.SimpleWriteln(F("AT+CIPSEND")); + switch(m_rSimComm900.WaitResp(5000, 200, F(">"))) + { + case RX_TMOUT_ERR: + return false; + break; + case RX_FINISHED_STR_NOT_RECV: + return false; + break; + } + m_rSimComm900.SimpleWrite(F("Subject: ")); + m_rSimComm900.SimpleWrite(strSubject); + m_rSimComm900.SimpleWrite(F("\n\n")); + + return 1; +} + +bool CInetGSM::closeMail() +{ + char strEndC[2]; + + strEndC[0]=0x1a; + strEndC[1]='\0'; + + m_rSimComm900.SimpleWrite(F("\n.\n")); + m_rSimComm900.SimpleWrite(strEndC); + disconnectTCP(); + + return true; +} + + +bool CInetGSM::attachGPRS(char* strDomain, char* strDom1, char* strDom2) +{ + int16_t nI = 0; + + delay(5000); + + m_rSimComm900.WaitResp(50, 50); + m_rSimComm900.SimpleWriteln(F("AT+CIFSR")); + if (m_rSimComm900.WaitResp(5000, 50, F("ERROR"))!=RX_FINISHED_STR_RECV) + { + #ifdef DEBUG_ON + Serial.println(F("DB:ALREADY HAVE AN IP")); + #endif + m_rSimComm900.SimpleWriteln(F("AT+CIPCLOSE")); + m_rSimComm900.WaitResp(5000, 50, F("ERROR")); + delay(2000); + m_rSimComm900.SimpleWriteln(F("AT+CIPSERVER=0")); + m_rSimComm900.WaitResp(5000, 50, F("ERROR")); + return true; + } + else + { + #ifdef DEBUG_ON + Serial.println(F("DB:STARTING NEW CONNECTION")); + #endif + m_rSimComm900.SimpleWriteln(F("AT+CIPSHUT")); + + switch(m_rSimComm900.WaitResp(500, 50, F("SHUT OK"))) + { + case RX_TMOUT_ERR: + return false; + break; + case RX_FINISHED_STR_NOT_RECV: + return false; + break; + } + #ifdef DEBUG_ON + Serial.println(F("DB:SHUTTED OK")); + #endif + delay(1000); + + m_rSimComm900.SimpleWrite(F("AT+CSTT=\"")); + m_rSimComm900.SimpleWrite(strDomain); + m_rSimComm900.SimpleWrite(F("\",\"")); + m_rSimComm900.SimpleWrite(strDom1); + m_rSimComm900.SimpleWrite(F("\",\"")); + m_rSimComm900.SimpleWrite(strDom2); + m_rSimComm900.SimpleWrite(F("\"\r")); + + + switch(m_rSimComm900.WaitResp(500, 50, F("OK"))) + { + case RX_TMOUT_ERR: + return false; + break; + case RX_FINISHED_STR_NOT_RECV: + return false; + break; + } + #ifdef DEBUG_ON + Serial.println(F("DB:APN OK")); + #endif + delay(5000); + m_rSimComm900.SimpleWriteln(F("AT+CIICR")); + + switch(m_rSimComm900.WaitResp(10000, 50, F("OK"))) + { + case RX_TMOUT_ERR: + return false; + break; + case RX_FINISHED_STR_NOT_RECV: + return false; + break; + } + #ifdef DEBUG_ON + Serial.println(F("DB:CONNECTION OK")); + #endif + delay(1000); + + m_rSimComm900.SimpleWriteln(F("AT+CIFSR")); + if (m_rSimComm900.WaitResp(5000, 50, F("ERROR"))!=RX_FINISHED_STR_RECV) + { + #ifdef DEBUG_ON + Serial.println(F("DB:ASSIGNED AN IP")); + #endif + m_rSimComm900.setStatus(ATTACHED); + return true; + } + #ifdef DEBUG_ON + Serial.println(F("DB:NO IP AFTER CONNECTION")); + #endif + return false; + } +} + +bool CInetGSM::dettachGPRS() +{ + if (m_rSimComm900.getStatus()==IDLE) + return false; + + m_rSimComm900.SimpleWriteln(F("AT+CGATT=0")); + if (m_rSimComm900.WaitResp(5000, 50, F("OK"))!=RX_FINISHED_STR_NOT_RECV) + { + m_rSimComm900.setStatus(ERROR); + return false; + } + delay(500); + + m_rSimComm900.setStatus(READY); + return true; +} + +bool CInetGSM::connectTCP(const char* strServer, int16_t nPort) +{ + //Visit the remote TCP strServer. + m_rSimComm900.SimpleWrite(F("AT+CIPSTART=\"TCP\",\"")); + m_rSimComm900.SimpleWrite(strServer); + m_rSimComm900.SimpleWrite(F("\",")); + m_rSimComm900.SimpleWriteln(nPort); + + switch(m_rSimComm900.WaitResp(1000, 200, F("OK"))) + { + case RX_TMOUT_ERR: + return false; + break; + case RX_FINISHED_STR_NOT_RECV: + return false; + break; + } + #ifdef DEBUG_ON + Serial.println(F("DB:RECVD CMD")); + #endif + if (!m_rSimComm900.IsStringReceived(F("CONNECT OK"))) + { + switch(m_rSimComm900.WaitResp(15000, 200, F("OK"))) + { + case RX_TMOUT_ERR: + return false; + break; + case RX_FINISHED_STR_NOT_RECV: + return false; + break; + } + } + #ifdef DEBUG_ON + Serial.println(F("DB:OK TCP")); + #endif + + delay(3000); + m_rSimComm900.SimpleWriteln(F("AT+CIPSEND")); + switch(m_rSimComm900.WaitResp(5000, 200, F(">"))) + { + case RX_TMOUT_ERR: + return false; + break; + case RX_FINISHED_STR_NOT_RECV: + return false; + break; + } + + #ifdef DEBUG_ON + Serial.println(F("DB:>")); + #endif + delay(4000); + return true; +} + +bool CInetGSM::disconnectTCP() +{ + + //Close TCP client and deact. + m_rSimComm900.SimpleWriteln(F("AT+CIPCLOSE")); + + if (m_rSimComm900.getStatus()==TCPCONNECTEDCLIENT) + m_rSimComm900.setStatus(ATTACHED); + else + m_rSimComm900.setStatus(TCPSERVERWAIT); + return true; +} + +bool CInetGSM::connectTCPServer(int16_t nPort) +{ + m_rSimComm900.SimpleWrite(F("AT+CIPSERVER=1,")); + m_rSimComm900.SimpleWriteln(nPort); + + return true; +} + +bool CInetGSM::connectedClient() +{ + m_rSimComm900.SimpleWriteln(F("AT+CIPSTATUS")); + if (m_rSimComm900.WaitResp(5000, 50, F("CONNECT OK")) != RX_FINISHED_STR_RECV) + { + m_rSimComm900.setStatus(TCPCONNECTEDSERVER); + return true; + } + else + return false; +} + diff --git a/inetGSM.h b/inetGSM.h index 41412c8..4f57412 100644 --- a/inetGSM.h +++ b/inetGSM.h @@ -3,29 +3,28 @@ #define BUFFERSIZE 1 -#include "SIM900.h" - -class InetGSM { -private: - char _buffer[BUFFERSIZE]; - -public: - int httpGET(const char* server, int port, const char* path, char* result, int resultlength); - int httpPOST(const char* server, int port, const char* path, const char* parameters, char* result, int resultlength); - - // Fast and dirty solution. Should make a "mail" object. And by the moment it does not run. - int openmail(char* server, char* loginbase64, char* passbase64, char* from, char* to, char* subj); - int closemail(); - int attachGPRS(char* domain, char* dom1, char* dom2); - int dettachGPRS(); - int connectTCP(const char* server, int port); - int disconnectTCP(); - int connectTCPServer(int port); - boolean connectedClient(); - - // This runs, yes - //int tweet(const char* token, const char* msg); - +#include "GSMBase.h" + +class CInetGSM: protected CGSMBase +{ + private: + char _buffer[BUFFERSIZE]; + + public: + CInetGSM(CSIMCOM900& rSimComm900): CGSMBase(rSimComm900){}; + + int16_t httpGET(const char* strServer, int16_t nPort, const char* strPath, char* strResult, int16_t nResultLength); + int16_t httpPOST(const char* strServer, int16_t nPort, const char* strPath, const char* strParameters, char* strResult, int16_t nResultLength); + + // Fast and dirty solution. Should make a "mail" object. And by the moment it does not run. + bool openMail(char* strServer, char* strLoginBase64, char* strPasswordBase64, char* strFrom, char* strTo, char* strSubject); + bool closeMail(); + bool attachGPRS(char* strDomain, char* strDom1, char* strDom2); + bool dettachGPRS(); + bool connectTCP(const char* strServer, int16_t nPort); + bool disconnectTCP(); + bool connectTCPServer(int16_t nPort); + bool connectedClient(); }; #endif diff --git a/sms.cpp b/sms.cpp index 9087ae6..735a8b8 100644 --- a/sms.cpp +++ b/sms.cpp @@ -1,94 +1,156 @@ #include "sms.h" +bool CSMSGSM::SendSMS(const __FlashStringHelper *fstrNumber, const __FlashStringHelper *fstrMessage) +{ + const uint16_t nLenNumber = strlen_P((PGM_P)fstrNumber), nLenMessage = strlen_P((PGM_P)fstrMessage); + char *strNumber = new char[nLenNumber + 1], *strMessage = new char [nLenMessage + 1]; + + memset(strNumber, 0, nLenNumber); + memset(strMessage, 0, nLenMessage); + strcpy_P(strNumber, (PGM_P)fstrNumber); + strcpy_P(strMessage, (PGM_P)fstrMessage); + bool bRetVal = SendSMS(strNumber, strMessage); + delete strNumber; + delete strMessage; + return bRetVal; +} + +bool CSMSGSM::SendSMS(const char *strNumber, const __FlashStringHelper *fstrMessage) +{ + const uint16_t nLenMessage = strlen_P((PGM_P)fstrMessage); + char* strMessage = new char [nLenMessage + 1]; + + memset(strMessage, 0, nLenMessage); + strcpy_P(strMessage, (PGM_P)fstrMessage); + bool bRetVal = SendSMS(strNumber, strMessage); + delete strMessage; + return bRetVal; +} + +bool CSMSGSM::SendSMS(const __FlashStringHelper *fstrNumber, const char *strMessage) +{ + const uint16_t nLenNumber = strlen_P((PGM_P)fstrNumber); + char* strNumber = new char[nLenNumber + 1]; + + memset(strNumber, 0, nLenNumber); + strcpy_P(strNumber, (PGM_P)fstrNumber); + bool bRetVal = SendSMS(strNumber, strMessage); + delete strNumber; + return bRetVal; +} + +bool CSMSGSM::SendSMS(uint8_t nSIMBookPos, const __FlashStringHelper *fstrMessage) +{ + const uint16_t nLenMessage = strlen_P((PGM_P)fstrMessage); + char* strMessage = new char[nLenMessage + 1]; + + memset(strMessage, 0, nLenMessage); + strcpy_P(strMessage, (PGM_P)fstrMessage); + bool bRetVal = SendSMS(nSIMBookPos, strMessage); + delete strMessage; + return bRetVal; +} + /********************************************************** Method sends SMS -number_str: pointer to the phone number string -message_str: pointer to the SMS text string +strNumber: pointer to the phone number string +strMessage: pointer to the SMS text string -return: +return: ERROR ret. val: --------------- -1 - comm. line to the GSM module is not free - -2 - GSM module didn't answer in timeout + -2 - GSM module didn't answer in time out -3 - GSM module has answered "ERROR" string - - OK ret val: - ----------- + 0 - SMS was not sent 1 - SMS was sent an example of usage: GSM gsm; - gsm.SendSMS("00XXXYYYYYYYYY", "SMS text"); + SendSMS("00XXXYYYYYYYYY", "SMS text"); **********************************************************/ -char SMSGSM::SendSMS(char *number_str, char *message_str) +bool CSMSGSM::SendSMS(const char *strNumber, const char *strMessage) { - if(strlen(message_str)>159) - Serial.println(F("Don't send message longer than 160 characters")); - char ret_val = -1; - byte i; - char end[2]; - end[0]=0x1a; - end[1]='\0'; - /* - if (CLS_FREE != gsm.GetCommLineStatus()) return (ret_val); - gsm.SetCommLineStatus(CLS_ATCMD); - ret_val = 0; // still not send - */ - // try to send SMS 3 times in case there is some problem - for (i = 0; i < 1; i++) { - // send AT+CMGS="number_str" - - gsm.SimpleWrite(F("AT+CMGS=\"")); - gsm.SimpleWrite(number_str); - gsm.SimpleWriteln("\""); - -#ifdef DEBUG_ON - Serial.println("DEBUG:SMS TEST"); -#endif - // 1000 msec. for initial comm tmout - // 50 msec. for inter character timeout - if (RX_FINISHED_STR_RECV == gsm.WaitResp(1000, 500, ">")) { -#ifdef DEBUG_ON - Serial.println("DEBUG:>"); -#endif - // send SMS text - gsm.SimpleWrite(message_str); - gsm.SimpleWriteln(end); - //_cell.flush(); // erase rx circular buffer - if (RX_FINISHED_STR_RECV == gsm.WaitResp(7000, 5000, "+CMGS")) { - // SMS was send correctly - ret_val = 1; - - break; - } else continue; - } else { - // try again - continue; - - } - } - - gsm.SetCommLineStatus(CLS_FREE); - return (ret_val); + bool bRetVal = false; + uint8_t nI = 0, nRes = 0; + char strEnd[2]; + + if ( strlen(strMessage)>159) + Serial.println(F("Don't send message longer than 160 characters")); + + strEnd[0]=0x1a; + strEnd[1]='\0'; + + // try to send SMS 3 times in case there is some problem + for (nI = 0; nI < 1; nI++) + { + // send AT+CMGS="strNumber" + m_rSimComm900.SimpleWrite(F("AT+CMGS=\"")); + m_rSimComm900.SimpleWrite(strNumber); + m_rSimComm900.SimpleWriteln(F("\"")); + + #ifdef DEBUG_ON + Serial.print(F("Sending \"")); + Serial.print(strMessage); + Serial.print(F("\" to ")); + Serial.print(strNumber); + Serial.print(F("...")); + #endif + // 1000 milliseconds. for initial comm time out 50 milliseconds. for inter character time out + if (RX_FINISHED_STR_RECV == m_rSimComm900.WaitResp(1000, 500, F(">"))) + { + // send SMS text + m_rSimComm900.SimpleWrite(strMessage); + m_rSimComm900.SimpleWriteln(strEnd); + + if (RX_FINISHED_STR_RECV == (nRes = m_rSimComm900.WaitResp(7000, 5000, F("+CMGS")))) + { + // SMS was send correctly + #ifdef DEBUG_ON + Serial.println(F("succeeded!")); + #endif + bRetVal = true; + break; + } + else + continue; + } + else + { + // try again + continue; + + } + } + if (!bRetVal) + { + #ifdef DEBUG_ON + Serial.print(F("failed (")); + Serial.print(nRes); + Serial.println(F(")!")); + #endif + } + m_rSimComm900.SetCommLineStatus(CLS_FREE); + return (bRetVal); } /********************************************************** -Method sends SMS to the specified SIM phonebook position +Method sends SMS to the specified SIM phonebook nPosition -sim_phonebook_position: SIM phonebook position <1..20> -message_str: pointer to the SMS text string +nSIMBookPos: SIM phonebook nPosition <1..20> +strMessage: pointer to the SMS text string -return: +return: ERROR ret. val: --------------- -1 - comm. line to the GSM module is not free - -2 - GSM module didn't answer in timeout - -3 - specified position must be > 0 + -2 - GSM module didn't answer in time out + -3 - specified nPosition must be > 0 OK ret val: ----------- @@ -98,470 +160,487 @@ message_str: pointer to the SMS text string an example of usage: GSM gsm; - gsm.SendSMS(1, "SMS text"); + SendSMS(1, "SMS text"); **********************************************************/ -char SMSGSM::SendSMS(byte sim_phonebook_position, char *message_str) +bool CSMSGSM::SendSMS(const uint8_t nSIMBookPos, const char *strMessage) { - char ret_val = -1; - char sim_phone_number[20]; - - ret_val = 0; // SMS is not send yet - if (sim_phonebook_position == 0) return (-3); - if (1 == gsm.GetPhoneNumber(sim_phonebook_position, sim_phone_number)) { - // there is a valid number at the spec. SIM position - // => send SMS - // ------------------------------------------------- - ret_val = SendSMS(sim_phone_number, message_str); - } - return (ret_val); - + bool bRetVal = -1; + char strSIMPhoneNum[20]; + + bRetVal = 0; // SMS is not send yet + if (nSIMBookPos == 0) + return (-3); + if (1 == m_rSimComm900.GetPhoneNumber(nSIMBookPos, strSIMPhoneNum)) + { + // there is a valid number at the spec. SIM nPosition + // => send SMS + // ------------------------------------------------- + bRetVal = SendSMS(strSIMPhoneNum, strMessage); + } + return bRetVal; } /********************************************************** Method finds out if there is present at least one SMS with -specified status +specified nStatus Note: if there is new SMS before IsSMSPresent() is executed -this SMS has a status UNREAD and then -after calling IsSMSPresent() method status of SMS +this SMS has a nStatus UNREAD and then +after calling IsSMSPresent() method nStatus of SMS is automatically changed to READ -required_status: SMS_UNREAD - new SMS - not read yet - SMS_READ - already read SMS +nRequiredStatus: SMS_UNREAD - new SMS - not read yet + SMS_READ - already read SMS SMS_ALL - all stored SMS -return: +return: ERROR ret. val: --------------- -1 - comm. line to the GSM module is not free - -2 - GSM module didn't answer in timeout + -2 - GSM module didn't answer in time out OK ret val: ----------- - 0 - there is no SMS with specified status - 1..20 - position where SMS is stored + 0 - there is no SMS with specified nStatus + 1..20 - nPosition where SMS is stored (suitable for the function GetSMS()) an example of use: GSM gsm; - char position; - char phone_number[20]; // array for the phone number string - char sms_text[100]; + int8_t nPosition; + int8_t strPhoneNumber[20]; // array for the phone number string + int8_t sms_text[100]; - position = gsm.IsSMSPresent(SMS_UNREAD); - if (position) { + nPosition = IsSMSPresent(SMS_UNREAD); + if (nPosition) { // read new SMS - gsm.GetSMS(position, phone_num, sms_text, 100); + GetSMS(nPosition, phone_num, sms_text, 100); // now we have phone number string in phone_num // and SMS text in sms_text } **********************************************************/ -char SMSGSM::IsSMSPresent(byte required_status) +int8_t CSMSGSM::IsSMSPresent(const uint8_t nRequiredStatus) { - char ret_val = -1; - char *p_char; - byte status; - - if (CLS_FREE != gsm.GetCommLineStatus()) return (ret_val); - gsm.SetCommLineStatus(CLS_ATCMD); - ret_val = 0; // still not present - - switch (required_status) { - case SMS_UNREAD: - gsm.SimpleWriteln(F("AT+CMGL=\"REC UNREAD\"")); - break; - case SMS_READ: - gsm.SimpleWriteln(F("AT+CMGL=\"REC READ\"")); - break; - case SMS_ALL: - gsm.SimpleWriteln(F("AT+CMGL=\"ALL\"")); - break; - } - - // 5 sec. for initial comm tmout - // and max. 1500 msec. for inter character timeout - gsm.RxInit(5000, 1500); - // wait response is finished - do { - if (gsm.IsStringReceived("OK")) { - // perfect - we have some response, but what: - - // there is either NO SMS: - // OK - - // or there is at least 1 SMS - // +CMGL: ,,,,[,,] - // OK - status = RX_FINISHED; - break; // so finish receiving immediately and let's go to - // to check response - } - status = gsm.IsRxFinished(); - } while (status == RX_NOT_FINISHED); - - - - - switch (status) { - case RX_TMOUT_ERR: - // response was not received in specific time - ret_val = -2; - break; - - case RX_FINISHED: - // something was received but what was received? - // --------------------------------------------- - if(gsm.IsStringReceived("+CMGL:")) { - // there is some SMS with status => get its position - // response is: - // +CMGL: ,,,,[,,] - // OK - p_char = strchr((char *)gsm.comm_buf,':'); - if (p_char != NULL) { - ret_val = atoi(p_char+1); - } - } else { - // other response like OK or ERROR - ret_val = 0; - } - - // here we have gsm.WaitResp() just for generation tmout 20msec. in case OK was detected - // not due to receiving - gsm.WaitResp(20, 20); - break; - } - - gsm.SetCommLineStatus(CLS_FREE); - return (ret_val); + bool bRetVal = -1; + char *strChar = NULL; + uint8_t nStatus = 0; + + if (CLS_FREE != m_rSimComm900.GetCommLineStatus()) + return (bRetVal); + + m_rSimComm900.SetCommLineStatus(CLS_ATCMD); + bRetVal = 0; // still not present + + switch (nRequiredStatus) + { + case SMS_UNREAD: + m_rSimComm900.SimpleWriteln(F("AT+CMGL=\"REC UNREAD\"")); + break; + case SMS_READ: + m_rSimComm900.SimpleWriteln(F("AT+CMGL=\"REC READ\"")); + break; + case SMS_ALL: + m_rSimComm900.SimpleWriteln(F("AT+CMGL=\"ALL\"")); + break; + } + // 5 sec. for initial comm time out + // and max. 1500 milliseconds. for inter character time out + m_rSimComm900.RxInit(5000, 1500); + // wait response is finished + do + { + if (m_rSimComm900.IsStringReceived(F("OK"))) + { + // perfect - we have some response, but what: + + // there is either NO SMS: + // OK + + // or there is at least 1 SMS + // +CMGL: ,,,,[,,] + // OK + nStatus = RX_FINISHED; + break; // so finish receiving immediately and let's go to check response + } + nStatus = m_rSimComm900.IsRxFinished(); + } + while (nStatus == RX_NOT_FINISHED); + + switch (nStatus) + { + case RX_TMOUT_ERR: + // response was not received in specific time + bRetVal = -2; + break; + + case RX_FINISHED: + // something was received but what was received? + // --------------------------------------------- + if (m_rSimComm900.IsStringReceived("+CMGL:")) + { + // there is some SMS with nStatus => get its nPosition + // response is: + // +CMGL: ,,,,[,,] + // OK + strChar = strchr(m_rSimComm900.m_arrayCommBuff, ':'); + if (strChar != NULL) + bRetVal = atoi(strChar+1); + } + else + { + // other response like OK or ERROR + bRetVal = 0; + } + // here we have m_rSimComm900.WaitResp() just for generation time out 20msec. in case OK was detected + // not due to receiving + m_rSimComm900.WaitResp(20, 20); + break; + } + m_rSimComm900.SetCommLineStatus(CLS_FREE); + return (bRetVal); } /********************************************************** -Method reads SMS from specified memory(SIM) position +Method reads SMS from specified memory(SIM) nPosition -position: SMS position <1..20> -phone_number: a pointer where the phone number string of received SMS will be placed +nPosition: SMS nPosition <1..20> +strPhoneNumber: a pointer where the phone number string of received SMS will be placed so the space for the phone number string must be reserved - see example -SMS_text : a pointer where SMS text will be placed -max_SMS_len: maximum length of SMS text excluding also string terminating 0x00 character - -return: +strSMSText : a pointer where SMS text will be placed +nMaxLength: maximum length of SMS text excluding also string terminating 0x00 character + +return: ERROR ret. val: --------------- -1 - comm. line to the GSM module is not free - -2 - GSM module didn't answer in timeout - -3 - specified position must be > 0 + -2 - GSM module didn't answer in time out + -3 - specified nPosition must be > 0 OK ret val: ----------- - GETSMS_NO_SMS - no SMS was not found at the specified position - GETSMS_UNREAD_SMS - new SMS was found at the specified position - GETSMS_READ_SMS - already read SMS was found at the specified position - GETSMS_OTHER_SMS - other type of SMS was found + GETSMS_NO_SMS - no SMS was not found at the specified nPosition + GETSMS_UNREAD_SMS - new SMS was found at the specified nPosition + GETSMS_READ_SMS - already read SMS was found at the specified nPosition + GETSMS_OTHER_SMS - other type of SMS was found an example of usage: GSM gsm; - char position; - char phone_num[20]; // array for the phone number string - char sms_text[100]; // array for the SMS text string + int8_t nPosition; + int8_t phone_num[20]; // array for the phone number string + int8_t sms_text[100]; // array for the SMS text string - position = gsm.IsSMSPresent(SMS_UNREAD); - if (position) { + nPosition = IsSMSPresent(SMS_UNREAD); + if (nPosition) { // there is new SMS => read it - gsm.GetSMS(position, phone_num, sms_text, 100); + GetSMS(nPosition, phone_num, sms_text, 100); #ifdef DEBUG_PRINT - gsm.DebugPrint("DEBUG SMS phone number: ", 0); - gsm.DebugPrint(phone_num, 0); - gsm.DebugPrint("\r\n SMS text: ", 0); - gsm.DebugPrint(sms_text, 1); + DebugPrint("DEBUG SMS phone number: ", 0); + DebugPrint(phone_num, 0); + DebugPrint("\r\n SMS text: ", 0); + DebugPrint(sms_text, 1); #endif - } + } **********************************************************/ -char SMSGSM::GetSMS(byte position, char *phone_number,byte max_phone_len, char *SMS_text, byte max_SMS_len) +int8_t CSMSGSM::GetSMS(char *strPhoneNumber, char *strSMSText, const uint8_t nMaxLength) { - char ret_val = -1; - char *p_char; - char *p_char1; - byte len; - - if (position == 0) return (-3); - if (CLS_FREE != gsm.GetCommLineStatus()) return (ret_val); - gsm.SetCommLineStatus(CLS_ATCMD); - phone_number[0] = 0; // end of string for now - ret_val = GETSMS_NO_SMS; // still no SMS - - //send "AT+CMGR=X" - where X = position - gsm.SimpleWrite(F("AT+CMGR=")); - gsm.SimpleWriteln((int)position); - - // 5000 msec. for initial comm tmout - // 100 msec. for inter character tmout - switch (gsm.WaitResp(5000, 100, "+CMGR")) { - case RX_TMOUT_ERR: - // response was not received in specific time - ret_val = -2; - break; - - case RX_FINISHED_STR_NOT_RECV: - // OK was received => there is NO SMS stored in this position - if(gsm.IsStringReceived("OK")) { - // there is only response OK - // => there is NO SMS - ret_val = GETSMS_NO_SMS; - } else if(gsm.IsStringReceived("ERROR")) { - // error should not be here but for sure - ret_val = GETSMS_NO_SMS; - } - break; - - case RX_FINISHED_STR_RECV: - // find out what was received exactly - - //response for new SMS: - //+CMGR: "REC UNREAD","+XXXXXXXXXXXX",,"02/03/18,09:54:28+40" - //There is SMS textOK - if(gsm.IsStringReceived("\"REC UNREAD\"")) { - // get phone number of received SMS: parse phone number string - // +XXXXXXXXXXXX - // ------------------------------------------------------- - ret_val = GETSMS_UNREAD_SMS; - } - //response for already read SMS = old SMS: - //+CMGR: "REC READ","+XXXXXXXXXXXX",,"02/03/18,09:54:28+40" - //There is SMS text - else if(gsm.IsStringReceived("\"REC READ\"")) { - // get phone number of received SMS - // -------------------------------- - ret_val = GETSMS_READ_SMS; - } else { - // other type like stored for sending.. - ret_val = GETSMS_OTHER_SMS; - } - - // extract phone number string - // --------------------------- - p_char = strchr((char *)(gsm.comm_buf),','); - p_char1 = p_char+2; // we are on the first phone number character - p_char = strchr((char *)(p_char1),'"'); - if (p_char != NULL) { - *p_char = 0; // end of string - len = strlen(p_char1); - if(len < max_phone_len){ - strcpy(phone_number, (char *)(p_char1)); - }else{ - memcpy(phone_number,(char *)p_char1,(max_phone_len-1)); - phone_number[max_phone_len]=0; - } - } - - - // get SMS text and copy this text to the SMS_text buffer - // ------------------------------------------------------ - p_char = strchr(p_char+1, 0x0a); // find - if (p_char != NULL) { - // next character after is the first SMS character - p_char++; // now we are on the first SMS character - - // find as the end of SMS string - p_char1 = strchr((char *)(p_char), 0x0d); - if (p_char1 != NULL) { - // finish the SMS text string - // because string must be finished for right behaviour - // of next strcpy() function - *p_char1 = 0; - } - // in case there is not finish sequence because the SMS is - // too long (more then 130 characters) sms text is finished by the 0x00 - // directly in the gsm.WaitResp() routine - - // find out length of the SMS (excluding 0x00 termination character) - len = strlen(p_char); - - if (len < max_SMS_len) { - // buffer SMS_text has enough place for copying all SMS text - // so copy whole SMS text - // from the beginning of the text(=p_char position) - // to the end of the string(= p_char1 position) - strcpy(SMS_text, (char *)(p_char)); - } else { - // buffer SMS_text doesn't have enough place for copying all SMS text - // so cut SMS text to the (max_SMS_len-1) - // (max_SMS_len-1) because we need 1 position for the 0x00 as finish - // string character - memcpy(SMS_text, (char *)(p_char), (max_SMS_len-1)); - SMS_text[max_SMS_len] = 0; // finish string - } - } - break; - } - - gsm.SetCommLineStatus(CLS_FREE); - return (ret_val); + return GetSMS(1, strPhoneNumber, strSMSText, nMaxLength); +} + +int8_t CSMSGSM::GetSMS(const uint8_t nPosition, char *strPhoneNumber, char *strSMSText, const uint8_t nMaxLength) +{ + bool bRetVal = -1; + char *strChar1 = NULL; + char *strChar2 = NULL; + uint8_t nLen = 0; + + if (nPosition == 0) + return (-3); + + if (CLS_FREE != m_rSimComm900.GetCommLineStatus()) + return (bRetVal); + + m_rSimComm900.SetCommLineStatus(CLS_ATCMD); + strPhoneNumber[0] = 0; // strEnd of string for now + bRetVal = GETSMS_NO_SMS; // still no SMS + + //send "AT+CMGR=X" - where X = nPosition + m_rSimComm900.SimpleWrite(F("AT+CMGR=")); + m_rSimComm900.SimpleWriteln((int)nPosition); + + // 5000 milliseconds. for initial comm time out 100 milliseconds. for inter character time out + switch (m_rSimComm900.WaitResp(5000, 100, F("+CMGR"))) + { + case RX_TMOUT_ERR: + // response was not received in specific time + bRetVal = -2; + break; + + case RX_FINISHED_STR_NOT_RECV: + // OK was received => there is NO SMS stored in this nPosition + if (m_rSimComm900.IsStringReceived(F("OK"))) + { + // there is only response OK => there is NO SMS + bRetVal = GETSMS_NO_SMS; + } + else if (m_rSimComm900.IsStringReceived(F("ERROR"))) + { + // error should not be here but for sure + bRetVal = GETSMS_NO_SMS; + } + break; + + case RX_FINISHED_STR_RECV: + // find out what was received exactly + //response for new SMS: + //+CMGR: "REC UNREAD","+XXXXXXXXXXXX",,"02/03/18,09:54:28+40" + //There is SMS textOK + if (m_rSimComm900.IsStringReceived(F("\"REC UNREAD\""))) + { + // get phone number of received SMS: parse phone number string + // +XXXXXXXXXXXX + // ------------------------------------------------------- + bRetVal = GETSMS_UNREAD_SMS; + } + //response for already read SMS = old SMS: + //+CMGR: "REC READ","+XXXXXXXXXXXX",,"02/03/18,09:54:28+40" + //There is SMS text + else if (m_rSimComm900.IsStringReceived(F("\"REC READ\""))) + { + // get phone number of received SMS + // -------------------------------- + bRetVal = GETSMS_READ_SMS; + } + else + { + // other type like stored for sending.. + bRetVal = GETSMS_OTHER_SMS; + } + + // extract phone number string + // --------------------------- + strChar1 = strchr((char*)(m_rSimComm900.m_arrayCommBuff), ','); + strChar2 = strChar1 + 2; // we are on the first phone number character + strChar1 = strchr(strChar2, '"'); + if (strChar1 != NULL) + { + *strChar1 = 0; // strEnd of string + strcpy(strPhoneNumber, strChar2); + } + // get SMS text and copy this text to the strSMSText buffer + // ------------------------------------------------------ + strChar1 = strchr(strChar1+1, 0x0a); // find + if (strChar1 != NULL) + { + // next character after is the first SMS character + strChar1++; // now we are on the first SMS character + + // find as the strEnd of SMS string + strChar2 = strchr(strChar1, 0x0d); + if (strChar2 != NULL) + { + // finish the SMS text string + // because string must be finished for right behaviour + // of next strcpy() function + *strChar2 = 0; + } + // in case there is not finish sequence because the SMS is too long (more then 130 characters) sms text is finished by the 0x00 + // directly in the m_rSimComm900.WaitResp() routine find out length of the SMS (excluding 0x00 termination character) + nLen = strlen(strChar1); + + if (nLen < nMaxLength) + { + // buffer strSMSText has enough place for copying all SMS text + // so copy whole SMS text + // from the beginning of the text(=strChar1 nPosition) + // to the strEnd of the string(= strChar2 nPosition) + strcpy(strSMSText, strChar1); + } + else + { + // buffer strSMSText doesn't have enough place for copying all SMS text so cut SMS text to the (nMaxLength-1) + // (nMaxLength-1) because we need 1 nPosition for the 0x00 as finish string character + memcpy(strSMSText, strChar1, (nMaxLength-1)); + strSMSText[nMaxLength] = 0; // finish string + } + } + break; + } + m_rSimComm900.SetCommLineStatus(CLS_FREE); + return (bRetVal); } /********************************************************** -Method reads SMS from specified memory(SIM) position and +Method reads SMS from specified memory(SIM) nPosition and makes authorization - it means SMS phone number is compared -with specified SIM phonebook position(s) and in case numbers +with specified SIM phonebook nPosition(s) and in case numbers match GETSMS_AUTH_SMS is returned, otherwise GETSMS_NOT_AUTH_SMS is returned -position: SMS position to be read <1..20> -phone_number: a pointer where the tel. number string of received SMS will be placed +nPosition: SMS nPosition to be read <1..20> +strPhoneNumber: 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 -SMS_text : a pointer where SMS text will be placed -max_SMS_len: maximum length of SMS text excluding terminating 0x00 character +strSMSText : a pointer where SMS text will be placed +nMaxLength: maximum length of SMS text excluding terminating 0x00 character -first_authorized_pos: initial SIM phonebook position where the authorization process +nFirstAuthPos: initial SIM phonebook nPosition where the authorization process starts -last_authorized_pos: last SIM phonebook position where the authorization process +nLastAuthPos: last SIM phonebook nPosition where the authorization process finishes Note(important): ================ - In case first_authorized_pos=0 and also last_authorized_pos=0 + In case nFirstAuthPos=0 and also nLastAuthPos=0 the received SMS phone number is NOT authorized at all, so every SMS is considered as authorized (GETSMS_AUTH_SMS is returned) - -return: + +return: ERROR ret. val: --------------- -1 - comm. line to the GSM module is not free - -2 - GSM module didn't answer in timeout - -3 - position must be > 0 + -2 - GSM module didn't answer in time out + -3 - nPosition must be > 0 OK ret val: ----------- - GETSMS_NO_SMS - no SMS was found at the specified position - GETSMS_NOT_AUTH_SMS - NOT authorized SMS found at the specified position - GETSMS_AUTH_SMS - authorized SMS found at the specified position + GETSMS_NO_SMS - no SMS was found at the specified nPosition + GETSMS_NOT_AUTH_SMS - NOT authorized SMS found at the specified nPosition + GETSMS_AUTH_SMS - authorized SMS found at the specified nPosition an example of usage: GSM gsm; - char phone_num[20]; // array for the phone number string - char sms_text[100]; // array for the SMS text string + int8_t phone_num[20]; // array for the phone number string + int8_t sms_text[100]; // array for the SMS text string // authorize SMS with SIM phonebook positions 1..3 - if (GETSMS_AUTH_SMS == gsm.GetAuthorizedSMS(1, phone_num, sms_text, 100, 1, 3)) { - // new authorized SMS was detected at the SMS position 1 + if (GETSMS_AUTH_SMS == GetAuthorizedSMS(1, phone_num, sms_text, 100, 1, 3)) { + // new authorized SMS was detected at the SMS nPosition 1 #ifdef DEBUG_PRINT - gsm.DebugPrint("DEBUG SMS phone number: ", 0); - gsm.DebugPrint(phone_num, 0); - gsm.DebugPrint("\r\n SMS text: ", 0); - gsm.DebugPrint(sms_text, 1); + DebugPrint("DEBUG SMS phone number: ", 0); + DebugPrint(phone_num, 0); + DebugPrint("\r\n SMS text: ", 0); + DebugPrint(sms_text, 1); #endif } // don't authorize SMS with SIM phonebook at all - if (GETSMS_AUTH_SMS == gsm.GetAuthorizedSMS(1, phone_num, sms_text, 100, 0, 0)) { - // new SMS was detected at the SMS position 1 + if (GETSMS_AUTH_SMS == GetAuthorizedSMS(1, phone_num, sms_text, 100, 0, 0)) { + // new SMS was detected at the SMS nPosition 1 // because authorization was not required // SMS is considered authorized #ifdef DEBUG_PRINT - gsm.DebugPrint("DEBUG SMS phone number: ", 0); - gsm.DebugPrint(phone_num, 0); - gsm.DebugPrint("\r\n SMS text: ", 0); - gsm.DebugPrint(sms_text, 1); + DebugPrint("DEBUG SMS phone number: ", 0); + DebugPrint(phone_num, 0); + DebugPrint("\r\n SMS text: ", 0); + DebugPrint(sms_text, 1); #endif } **********************************************************/ -char SMSGSM::GetAuthorizedSMS(byte position, char *phone_number,byte max_phone_len, char *SMS_text, byte max_SMS_len, - byte first_authorized_pos, byte last_authorized_pos) +int8_t CSMSGSM::GetAuthorizedSMS(const uint8_t nPosition, char *strPhoneNumber, char *strSMSText, const uint8_t nMaxLength, const uint8_t nFirstAuthPos, const uint8_t nLastAuthPos) { - char ret_val = -1; - byte i; - - ret_val = GetSMS(position, phone_number, max_phone_len, SMS_text, max_SMS_len); - if (ret_val < 0) { - // here is ERROR return code => finish - // ----------------------------------- - } else if (ret_val == GETSMS_NO_SMS) { - // no SMS detected => finish - // ------------------------- - } else if (ret_val == GETSMS_READ_SMS) { - // now SMS can has only READ attribute because we have already read - // this SMS at least once by the previous function GetSMS() - // - // new READ SMS was detected on the specified SMS position => - // make authorization now - // --------------------------------------------------------- - if ((first_authorized_pos == 0) && (last_authorized_pos == 0)) { - // authorization is not required => it means authorization is OK - // ------------------------------------------------------------- - ret_val = GETSMS_AUTH_SMS; - } else { - ret_val = GETSMS_NOT_AUTH_SMS; // authorization not valid yet - for (i = first_authorized_pos; i <= last_authorized_pos; i++) { - if (gsm.ComparePhoneNumber(i, phone_number)) { - // phone numbers are identical - // authorization is OK - // --------------------------- - ret_val = GETSMS_AUTH_SMS; - break; // and finish authorization - } - } - } - } - return (ret_val); + bool bRetVal = -1; + uint8_t nI = 0; + + bRetVal = GetSMS(nPosition, strPhoneNumber, strSMSText, nMaxLength); + + if (bRetVal < 0) + { + // here is ERROR return code => finish + // ----------------------------------- + } + else if (bRetVal == GETSMS_NO_SMS) + { + // no SMS detected => finish + // ------------------------- + } + else if (bRetVal == GETSMS_READ_SMS) + { + // now SMS can has only READ attribute because we have already read this SMS at least once by the previous function GetSMS() + // new READ SMS was detected on the specified SMS nPosition => make authorization now + // --------------------------------------------------------- + if ((nFirstAuthPos == 0) && (nLastAuthPos == 0)) + { + // authorization is not required => it means authorization is OK + // ------------------------------------------------------------- + bRetVal = GETSMS_AUTH_SMS; + } + else + { + bRetVal = GETSMS_NOT_AUTH_SMS; // authorization not valid yet + for (nI = nFirstAuthPos; nI <= nLastAuthPos; nI++) + { + if (m_rSimComm900.ComparePhoneNumber(nI, strPhoneNumber)) + { + // phone numbers are identical authorization is OK + // --------------------------- + bRetVal = GETSMS_AUTH_SMS; + break; // and finish authorization + } + } + } + } + return (bRetVal); } /********************************************************** -Method deletes SMS from the specified SMS position +Method deletes SMS from the specified SMS nPosition -position: SMS position <1..20> +nPosition: SMS nPosition <1..20> -return: +return: ERROR ret. val: --------------- -1 - comm. line to the GSM module is not free - -2 - GSM module didn't answer in timeout - -3 - position must be > 0 + -2 - GSM module didn't answer in time out + -3 - nPosition must be > 0 OK ret val: ----------- 0 - SMS was not deleted 1 - SMS was deleted **********************************************************/ -char SMSGSM::DeleteSMS(byte position) +int8_t CSMSGSM::DeleteSMS(const uint8_t nPosition) { - char ret_val = -1; - - if (position == 0) return (-3); - if (CLS_FREE != gsm.GetCommLineStatus()) return (ret_val); - gsm.SetCommLineStatus(CLS_ATCMD); - ret_val = 0; // not deleted yet - - //send "AT+CMGD=XY" - where XY = position - gsm.SimpleWrite(F("AT+CMGD=")); - gsm.SimpleWriteln((int)position); - - - // 5000 msec. for initial comm tmout - // 20 msec. for inter character timeout - switch (gsm.WaitResp(5000, 50, "OK")) { - case RX_TMOUT_ERR: - // response was not received in specific time - ret_val = -2; - break; - - case RX_FINISHED_STR_RECV: - // OK was received => SMS deleted - ret_val = 1; - break; - - case RX_FINISHED_STR_NOT_RECV: - // other response: e.g. ERROR => SMS was not deleted - ret_val = 0; - break; - } - - gsm.SetCommLineStatus(CLS_FREE); - return (ret_val); + bool bRetVal = -1; + + if (nPosition == 0) + return (-3); + + if (CLS_FREE != m_rSimComm900.GetCommLineStatus()) + return (bRetVal); + + m_rSimComm900.SetCommLineStatus(CLS_ATCMD); + bRetVal = 0; // not deleted yet + + //send "AT+CMGD=XY" - where XY = nPosition + m_rSimComm900.SimpleWrite(F("AT+CMGD=")); + m_rSimComm900.SimpleWriteln((int)nPosition); + + + // 5000 milliseconds. for initial comm time out + // 20 milliseconds. for inter character time out + switch (m_rSimComm900.WaitResp(5000, 50, F("OK"))) + { + case RX_TMOUT_ERR: + // response was not received in specific time + bRetVal = -2; + break; + case RX_FINISHED_STR_RECV: + // OK was received => SMS deleted + bRetVal = 1; + break; + case RX_FINISHED_STR_NOT_RECV: + // other response: e.g. ERROR => SMS was not deleted + bRetVal = 0; + break; + } + m_rSimComm900.SetCommLineStatus(CLS_FREE); + return bRetVal; } diff --git a/sms.h b/sms.h index 74a0e45..f6d4169 100644 --- a/sms.h +++ b/sms.h @@ -1,21 +1,29 @@ #ifndef _SMS_H_ #define _SMS_H_ +#include "GSMBase.h" #include "SIM900.h" -class SMSGSM { -public: - // SMS's methods - char SendSMS(char *number_str, char *message_str); - char SendSMS(byte sim_phonebook_position, char *message_str); - char IsSMSPresent(byte required_status); - char GetSMS(byte position, char *phone_number,byte max_phone_len, char *SMS_text, byte max_SMS_len); +class CSMSGSM: protected CGSMBase +{ + public: + CSMSGSM(CSIMCOM900& rSIMCom900): CGSMBase(rSIMCom900){}; + + // SMS's methods + bool SendSMS(const char *strNumber, const char *strMessage); + bool SendSMS(const __FlashStringHelper *fstrNumber, const __FlashStringHelper *fstrMessage); + bool SendSMS(const char *strNumber, const __FlashStringHelper *fstrMessage); + bool SendSMS(const __FlashStringHelper *fstrNumber, const char *strMessage); + bool SendSMS(const uint8_t nSIMBookPos, const char *strMessage); + bool SendSMS(const uint8_t nSIMBookPos, const __FlashStringHelper *fstrMessage); + int8_t IsSMSPresent(uint8_t nRequiredStatus); + int8_t GetSMS(char *strPhoneNumber, char *strSMSText, const uint8_t nMaxLength); + int8_t GetSMS(const uint8_t nPosition, char *strPhoneNumber, char *strSMSText, const uint8_t nMaxLength); + + int8_t GetAuthorizedSMS(const uint8_t nPosition, char *strPhoneNumber, char *strSMSText, const uint8_t nMaxLength, const uint8_t nFirstAuthPos, const uint8_t nLastAuthPos); + int8_t DeleteSMS(const uint8_t nPosition); - char GetAuthorizedSMS(byte position, char *phone_number, byte max_phone_len, char *SMS_text, byte max_SMS_len, - byte first_authorized_pos, byte last_authorized_pos); - char DeleteSMS(byte position); - -}; + }; #endif