Revision 0:8b6028668696, committed 2016-10-17
- Comitter:
- lewisdaw3
- Date:
- Mon Oct 17 10:51:58 2016 +0000
- Commit message:
- publish library
Changed in this revision
diff -r 000000000000 -r 8b6028668696 Adafruit_FONA.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Adafruit_FONA.cpp Mon Oct 17 10:51:58 2016 +0000
@@ -0,0 +1,2082 @@
+/***************************************************
+ This is a library for our Adafruit FONA Cellular Module
+
+ Designed specifically to work with the Adafruit FONA
+ ----> http://www.adafruit.com/products/1946
+ ----> http://www.adafruit.com/products/1963
+
+ These displays use TTL Serial to communicate, 2 pins are required to
+ interface
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ Written by Limor Fried/Ladyada for Adafruit Industries.
+ BSD license, all text above must be included in any redistribution
+ ****************************************************/
+ // next line per http://postwarrior.com/arduino-ethershield-error-prog_char-does-not-name-a-type/
+
+#include "Adafruit_FONA.h"
+
+
+
+
+Adafruit_FONA::Adafruit_FONA(int8_t rst)
+{
+ _rstpin = rst;
+
+ apn = F("FONAnet");
+ apnusername = 0;
+ apnpassword = 0;
+ mySerial = 0;
+ httpsredirect = false;
+ useragent = F("FONA");
+ ok_reply = F("OK");
+}
+
+uint8_t Adafruit_FONA::type(void) {
+ return _type;
+}
+
+boolean Adafruit_FONA::begin(Stream &port) {
+ mySerial = &port;
+
+ pinMode(_rstpin, OUTPUT);
+ digitalWrite(_rstpin, HIGH);
+ delay(10);
+ digitalWrite(_rstpin, LOW);
+ delay(100);
+ digitalWrite(_rstpin, HIGH);
+
+ DEBUG_PRINTLN(F("Attempting to open comm with ATs"));
+ // give 7 seconds to reboot
+ int16_t timeout = 7000;
+
+ while (timeout > 0) {
+ while (mySerial->available()) mySerial->read();
+ if (sendCheckReply(F("AT"), ok_reply))
+ break;
+ while (mySerial->available()) mySerial->read();
+ if (sendCheckReply(F("AT"), F("AT")))
+ break;
+ delay(500);
+ timeout-=500;
+ }
+
+ if (timeout <= 0) {
+#ifdef ADAFRUIT_FONA_DEBUG
+ DEBUG_PRINTLN(F("Timeout: No response to AT... last ditch attempt."));
+#endif
+ sendCheckReply(F("AT"), ok_reply);
+ delay(100);
+ sendCheckReply(F("AT"), ok_reply);
+ delay(100);
+ sendCheckReply(F("AT"), ok_reply);
+ delay(100);
+ }
+
+ // turn off Echo!
+ sendCheckReply(F("ATE0"), ok_reply);
+ delay(100);
+
+ if (! sendCheckReply(F("ATE0"), ok_reply)) {
+ return false;
+ }
+
+ // turn on hangupitude
+ sendCheckReply(F("AT+CVHU=0"), ok_reply);
+
+ delay(100);
+ flushInput();
+
+
+ DEBUG_PRINT(F("\t---> ")); DEBUG_PRINTLN("ATI");
+
+ mySerial->println("ATI");
+ readline(500, true);
+
+ DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer);
+
+
+
+ if (prog_char_strstr(replybuffer, (prog_char *)F("SIM808 R14")) != 0) {
+ _type = FONA808_V2;
+ } else if (prog_char_strstr(replybuffer, (prog_char *)F("SIM808 R13")) != 0) {
+ _type = FONA808_V1;
+ } else if (prog_char_strstr(replybuffer, (prog_char *)F("SIM800 R13")) != 0) {
+ _type = FONA800L;
+ } else if (prog_char_strstr(replybuffer, (prog_char *)F("SIMCOM_SIM5320A")) != 0) {
+ _type = FONA3G_A;
+ } else if (prog_char_strstr(replybuffer, (prog_char *)F("SIMCOM_SIM5320E")) != 0) {
+ _type = FONA3G_E;
+ }
+
+ if (_type == FONA800L) {
+ // determine if L or H
+
+ DEBUG_PRINT(F("\t---> ")); DEBUG_PRINTLN("AT+GMM");
+
+ mySerial->println("AT+GMM");
+ readline(500, true);
+
+ DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer);
+
+
+ if (prog_char_strstr(replybuffer, (prog_char *)F("SIM800H")) != 0) {
+ _type = FONA800H;
+ }
+ }
+
+#if defined(FONA_PREF_SMS_STORAGE)
+ sendCheckReply(F("AT+CPMS=\"" FONA_PREF_SMS_STORAGE "\""), ok_reply);
+#endif
+
+ return true;
+}
+
+
+/********* Serial port ********************************************/
+boolean Adafruit_FONA::setBaudrate(uint16_t baud) {
+ return sendCheckReply(F("AT+IPREX="), baud, ok_reply);
+}
+
+/********* Real Time Clock ********************************************/
+
+boolean Adafruit_FONA::readRTC(uint8_t *year, uint8_t *month, uint8_t *date, uint8_t *hr, uint8_t *min, uint8_t *sec) {
+ uint16_t v;
+ sendParseReply(F("AT+CCLK?"), F("+CCLK: "), &v, '/', 0);
+ *year = v;
+
+ DEBUG_PRINTLN(*year);
+}
+
+boolean Adafruit_FONA::enableRTC(uint8_t i) {
+ if (! sendCheckReply(F("AT+CLTS="), i, ok_reply))
+ return false;
+ return sendCheckReply(F("AT&W"), ok_reply);
+}
+
+
+/********* BATTERY & ADC ********************************************/
+
+/* returns value in mV (uint16_t) */
+boolean Adafruit_FONA::getBattVoltage(uint16_t *v) {
+ return sendParseReply(F("AT+CBC"), F("+CBC: "), v, ',', 2);
+}
+
+/* returns value in mV (uint16_t) */
+boolean Adafruit_FONA_3G::getBattVoltage(uint16_t *v) {
+ float f;
+ boolean b = sendParseReply(F("AT+CBC"), F("+CBC: "), &f, ',', 2);
+ *v = f*1000;
+ return b;
+}
+
+
+/* returns the percentage charge of battery as reported by sim800 */
+boolean Adafruit_FONA::getBattPercent(uint16_t *p) {
+ return sendParseReply(F("AT+CBC"), F("+CBC: "), p, ',', 1);
+}
+
+boolean Adafruit_FONA::getADCVoltage(uint16_t *v) {
+ return sendParseReply(F("AT+CADC?"), F("+CADC: 1,"), v);
+}
+
+/********* SIM ***********************************************************/
+
+uint8_t Adafruit_FONA::unlockSIM(char *pin)
+{
+ char sendbuff[14] = "AT+CPIN=";
+ sendbuff[8] = pin[0];
+ sendbuff[9] = pin[1];
+ sendbuff[10] = pin[2];
+ sendbuff[11] = pin[3];
+ sendbuff[12] = '\0';
+
+ return sendCheckReply(sendbuff, ok_reply);
+}
+
+uint8_t Adafruit_FONA::getSIMCCID(char *ccid) {
+ getReply(F("AT+CCID"));
+ // up to 28 chars for reply, 20 char total ccid
+ if (replybuffer[0] == '+') {
+ // fona 3g?
+ strncpy(ccid, replybuffer+8, 20);
+ } else {
+ // fona 800 or 800
+ strncpy(ccid, replybuffer, 20);
+ }
+ ccid[20] = 0;
+
+ readline(); // eat 'OK'
+
+ return strlen(ccid);
+}
+
+/********* IMEI **********************************************************/
+
+uint8_t Adafruit_FONA::getIMEI(char *imei) {
+ getReply(F("AT+GSN"));
+
+ // up to 15 chars
+ strncpy(imei, replybuffer, 15);
+ imei[15] = 0;
+
+ readline(); // eat 'OK'
+
+ return strlen(imei);
+}
+
+/********* NETWORK *******************************************************/
+
+uint8_t Adafruit_FONA::getNetworkStatus(void) {
+ uint16_t status;
+
+ if (! sendParseReply(F("AT+CREG?"), F("+CREG: "), &status, ',', 1)) return 0;
+
+ return status;
+}
+
+
+uint8_t Adafruit_FONA::getRSSI(void) {
+ uint16_t reply;
+
+ if (! sendParseReply(F("AT+CSQ"), F("+CSQ: "), &reply) ) return 0;
+
+ return reply;
+}
+
+/********* AUDIO *******************************************************/
+
+boolean Adafruit_FONA::setAudio(uint8_t a) {
+ // 0 is headset, 1 is external audio
+ if (a > 1) return false;
+
+ return sendCheckReply(F("AT+CHFA="), a, ok_reply);
+}
+
+uint8_t Adafruit_FONA::getVolume(void) {
+ uint16_t reply;
+
+ if (! sendParseReply(F("AT+CLVL?"), F("+CLVL: "), &reply) ) return 0;
+
+ return reply;
+}
+
+boolean Adafruit_FONA::setVolume(uint8_t i) {
+ return sendCheckReply(F("AT+CLVL="), i, ok_reply);
+}
+
+
+boolean Adafruit_FONA::playDTMF(char dtmf) {
+ char str[4];
+ str[0] = '\"';
+ str[1] = dtmf;
+ str[2] = '\"';
+ str[3] = 0;
+ return sendCheckReply(F("AT+CLDTMF=3,"), str, ok_reply);
+}
+
+boolean Adafruit_FONA::playToolkitTone(uint8_t t, uint16_t len) {
+ return sendCheckReply(F("AT+STTONE=1,"), t, len, ok_reply);
+}
+
+boolean Adafruit_FONA_3G::playToolkitTone(uint8_t t, uint16_t len) {
+ if (! sendCheckReply(F("AT+CPTONE="), t, ok_reply))
+ return false;
+ delay(len);
+ return sendCheckReply(F("AT+CPTONE=0"), ok_reply);
+}
+
+boolean Adafruit_FONA::setMicVolume(uint8_t a, uint8_t level) {
+ // 0 is headset, 1 is external audio
+ if (a > 1) return false;
+
+ return sendCheckReply(F("AT+CMIC="), a, level, ok_reply);
+}
+
+/********* FM RADIO *******************************************************/
+
+
+boolean Adafruit_FONA::FMradio(boolean onoff, uint8_t a) {
+ if (! onoff) {
+ return sendCheckReply(F("AT+FMCLOSE"), ok_reply);
+ }
+
+ // 0 is headset, 1 is external audio
+ if (a > 1) return false;
+
+ return sendCheckReply(F("AT+FMOPEN="), a, ok_reply);
+}
+
+boolean Adafruit_FONA::tuneFMradio(uint16_t station) {
+ // Fail if FM station is outside allowed range.
+ if ((station < 870) || (station > 1090))
+ return false;
+
+ return sendCheckReply(F("AT+FMFREQ="), station, ok_reply);
+}
+
+boolean Adafruit_FONA::setFMVolume(uint8_t i) {
+ // Fail if volume is outside allowed range (0-6).
+ if (i > 6) {
+ return false;
+ }
+ // Send FM volume command and verify response.
+ return sendCheckReply(F("AT+FMVOLUME="), i, ok_reply);
+}
+
+int8_t Adafruit_FONA::getFMVolume() {
+ uint16_t level;
+
+ if (! sendParseReply(F("AT+FMVOLUME?"), F("+FMVOLUME: "), &level) ) return 0;
+
+ return level;
+}
+
+int8_t Adafruit_FONA::getFMSignalLevel(uint16_t station) {
+ // Fail if FM station is outside allowed range.
+ if ((station < 875) || (station > 1080)) {
+ return -1;
+ }
+
+ // Send FM signal level query command.
+ // Note, need to explicitly send timeout so right overload is chosen.
+ getReply(F("AT+FMSIGNAL="), station, FONA_DEFAULT_TIMEOUT_MS);
+ // Check response starts with expected value.
+ char *p = prog_char_strstr(replybuffer, PSTR("+FMSIGNAL: "));
+ if (p == 0) return -1;
+ p+=11;
+ // Find second colon to get start of signal quality.
+ p = strchr(p, ':');
+ if (p == 0) return -1;
+ p+=1;
+ // Parse signal quality.
+ int8_t level = atoi(p);
+ readline(); // eat the "OK"
+ return level;
+}
+
+/********* PWM/BUZZER **************************************************/
+
+boolean Adafruit_FONA::setPWM(uint16_t period, uint8_t duty) {
+ if (period > 2000) return false;
+ if (duty > 100) return false;
+
+ return sendCheckReply(F("AT+SPWM=0,"), period, duty, ok_reply);
+}
+
+/********* CALL PHONES **************************************************/
+boolean Adafruit_FONA::callPhone(char *number) {
+ char sendbuff[35] = "ATD";
+ strncpy(sendbuff+3, number, min(30, strlen(number)));
+ uint8_t x = strlen(sendbuff);
+ sendbuff[x] = ';';
+ sendbuff[x+1] = 0;
+ //DEBUG_PRINTLN(sendbuff);
+
+ return sendCheckReply(sendbuff, ok_reply);
+}
+
+
+uint8_t Adafruit_FONA::getCallStatus(void) {
+ uint16_t phoneStatus;
+
+ if (! sendParseReply(F("AT+CPAS"), F("+CPAS: "), &phoneStatus))
+ return FONA_CALL_FAILED; // 1, since 0 is actually a known, good reply
+
+ return phoneStatus; // 0 ready, 2 unkown, 3 ringing, 4 call in progress
+}
+
+boolean Adafruit_FONA::hangUp(void) {
+ return sendCheckReply(F("ATH0"), ok_reply);
+}
+
+boolean Adafruit_FONA_3G::hangUp(void) {
+ getReply(F("ATH"));
+
+ return (prog_char_strstr(replybuffer, (prog_char *)F("VOICE CALL: END")) != 0);
+}
+
+boolean Adafruit_FONA::pickUp(void) {
+ return sendCheckReply(F("ATA"), ok_reply);
+}
+
+boolean Adafruit_FONA_3G::pickUp(void) {
+ return sendCheckReply(F("ATA"), F("VOICE CALL: BEGIN"));
+}
+
+
+void Adafruit_FONA::onIncomingCall() {
+
+ DEBUG_PRINT(F("> ")); DEBUG_PRINTLN(F("Incoming call..."));
+
+ Adafruit_FONA::_incomingCall = true;
+}
+
+boolean Adafruit_FONA::_incomingCall = false;
+
+boolean Adafruit_FONA::callerIdNotification(boolean enable, uint8_t interrupt) {
+ if(enable){
+ attachInterrupt(interrupt, onIncomingCall, FALLING);
+ return sendCheckReply(F("AT+CLIP=1"), ok_reply);
+ }
+
+ detachInterrupt(interrupt);
+ return sendCheckReply(F("AT+CLIP=0"), ok_reply);
+}
+
+boolean Adafruit_FONA::incomingCallNumber(char* phonenum) {
+ //+CLIP: "<incoming phone number>",145,"",0,"",0
+ if(!Adafruit_FONA::_incomingCall)
+ return false;
+
+ readline();
+ while(!prog_char_strcmp(replybuffer, (prog_char*)F("RING")) == 0) {
+ flushInput();
+ readline();
+ }
+
+ readline(); //reads incoming phone number line
+
+ parseReply(F("+CLIP: \""), phonenum, '"');
+
+
+ DEBUG_PRINT(F("Phone Number: "));
+ DEBUG_PRINTLN(replybuffer);
+
+
+ Adafruit_FONA::_incomingCall = false;
+ return true;
+}
+
+/********* SMS **********************************************************/
+
+uint8_t Adafruit_FONA::getSMSInterrupt(void) {
+ uint16_t reply;
+
+ if (! sendParseReply(F("AT+CFGRI?"), F("+CFGRI: "), &reply) ) return 0;
+
+ return reply;
+}
+
+boolean Adafruit_FONA::setSMSInterrupt(uint8_t i) {
+ return sendCheckReply(F("AT+CFGRI="), i, ok_reply);
+}
+
+int8_t Adafruit_FONA::getNumSMS(void) {
+ uint16_t numsms;
+
+ // get into text mode
+ if (! sendCheckReply(F("AT+CMGF=1"), ok_reply)) return -1;
+
+ // ask how many sms are stored
+ if (sendParseReply(F("AT+CPMS?"), F("\"SM\","), &numsms))
+ return numsms;
+ if (sendParseReply(F("AT+CPMS?"), F("\"SM_P\","), &numsms))
+ return numsms;
+ return -1;
+}
+
+// Reading SMS's is a bit involved so we don't use helpers that may cause delays or debug
+// printouts!
+boolean Adafruit_FONA::readSMS(uint8_t i, char *smsbuff,
+ uint16_t maxlen, uint16_t *readlen) {
+ // text mode
+ if (! sendCheckReply(F("AT+CMGF=1"), ok_reply)) return false;
+
+ // show all text mode parameters
+ if (! sendCheckReply(F("AT+CSDH=1"), ok_reply)) return false;
+
+ // parse out the SMS len
+ uint16_t thesmslen = 0;
+
+
+ DEBUG_PRINT(F("AT+CMGR="));
+ DEBUG_PRINTLN(i);
+
+
+ //getReply(F("AT+CMGR="), i, 1000); // do not print debug!
+ mySerial->print(F("AT+CMGR="));
+ mySerial->println(i);
+ readline(1000); // timeout
+
+ //DEBUG_PRINT(F("Reply: ")); DEBUG_PRINTLN(replybuffer);
+ // parse it out...
+
+
+ DEBUG_PRINTLN(replybuffer);
+
+
+ if (! parseReply(F("+CMGR:"), &thesmslen, ',', 11)) {
+ *readlen = 0;
+ return false;
+ }
+
+ readRaw(thesmslen);
+
+ flushInput();
+
+ uint16_t thelen = min(maxlen, strlen(replybuffer));
+ strncpy(smsbuff, replybuffer, thelen);
+ smsbuff[thelen] = 0; // end the string
+
+
+ DEBUG_PRINTLN(replybuffer);
+
+ *readlen = thelen;
+ return true;
+}
+
+// Retrieve the sender of the specified SMS message and copy it as a string to
+// the sender buffer. Up to senderlen characters of the sender will be copied
+// and a null terminator will be added if less than senderlen charactesr are
+// copied to the result. Returns true if a result was successfully retrieved,
+// otherwise false.
+boolean Adafruit_FONA::getSMSSender(uint8_t i, char *sender, int senderlen) {
+ // Ensure text mode and all text mode parameters are sent.
+ if (! sendCheckReply(F("AT+CMGF=1"), ok_reply)) return false;
+ if (! sendCheckReply(F("AT+CSDH=1"), ok_reply)) return false;
+
+
+ DEBUG_PRINT(F("AT+CMGR="));
+ DEBUG_PRINTLN(i);
+
+
+ // Send command to retrieve SMS message and parse a line of response.
+ mySerial->print(F("AT+CMGR="));
+ mySerial->println(i);
+ readline(1000);
+
+
+ DEBUG_PRINTLN(replybuffer);
+
+
+ // Parse the second field in the response.
+ boolean result = parseReplyQuoted(F("+CMGR:"), sender, senderlen, ',', 1);
+ // Drop any remaining data from the response.
+ flushInput();
+ return result;
+}
+
+boolean Adafruit_FONA::sendSMS(char *smsaddr, char *smsmsg) {
+ if (! sendCheckReply(F("AT+CMGF=1"), ok_reply)) return false;
+
+ char sendcmd[30] = "AT+CMGS=\"";
+ strncpy(sendcmd+9, smsaddr, 30-9-2); // 9 bytes beginning, 2 bytes for close quote + null
+ sendcmd[strlen(sendcmd)] = '\"';
+
+ if (! sendCheckReply(sendcmd, F("> "))) return false;
+
+ DEBUG_PRINT(F("> ")); DEBUG_PRINTLN(smsmsg);
+
+ mySerial->println(smsmsg);
+ mySerial->println();
+ mySerial->write(0x1A);
+
+ DEBUG_PRINTLN("^Z");
+
+ if ( (_type == FONA3G_A) || (_type == FONA3G_E) ) {
+ // Eat two sets of CRLF
+ readline(200);
+ //DEBUG_PRINT("Line 1: "); DEBUG_PRINTLN(strlen(replybuffer));
+ readline(200);
+ //DEBUG_PRINT("Line 2: "); DEBUG_PRINTLN(strlen(replybuffer));
+ }
+ readline(10000); // read the +CMGS reply, wait up to 10 seconds!!!
+ //DEBUG_PRINT("Line 3: "); DEBUG_PRINTLN(strlen(replybuffer));
+ if (strstr(replybuffer, "+CMGS") == 0) {
+ return false;
+ }
+ readline(1000); // read OK
+ //DEBUG_PRINT("* "); DEBUG_PRINTLN(replybuffer);
+
+ if (strcmp(replybuffer, "OK") != 0) {
+ return false;
+ }
+
+ return true;
+}
+
+
+boolean Adafruit_FONA::deleteSMS(uint8_t i) {
+ if (! sendCheckReply(F("AT+CMGF=1"), ok_reply)) return false;
+ // read an sms
+ char sendbuff[12] = "AT+CMGD=000";
+ sendbuff[8] = (i / 100) + '0';
+ i %= 100;
+ sendbuff[9] = (i / 10) + '0';
+ i %= 10;
+ sendbuff[10] = i + '0';
+
+ return sendCheckReply(sendbuff, ok_reply, 2000);
+}
+
+/********* USSD *********************************************************/
+
+boolean Adafruit_FONA::sendUSSD(char *ussdmsg, char *ussdbuff, uint16_t maxlen, uint16_t *readlen) {
+ if (! sendCheckReply(F("AT+CUSD=1"), ok_reply)) return false;
+
+ char sendcmd[30] = "AT+CUSD=1,\"";
+ strncpy(sendcmd+11, ussdmsg, 30-11-2); // 11 bytes beginning, 2 bytes for close quote + null
+ sendcmd[strlen(sendcmd)] = '\"';
+
+ if (! sendCheckReply(sendcmd, ok_reply)) {
+ *readlen = 0;
+ return false;
+ } else {
+ readline(10000); // read the +CUSD reply, wait up to 10 seconds!!!
+ //DEBUG_PRINT("* "); DEBUG_PRINTLN(replybuffer);
+ char *p = prog_char_strstr(replybuffer, PSTR("+CUSD: "));
+ if (p == 0) {
+ *readlen = 0;
+ return false;
+ }
+ p+=7; //+CUSD
+ // Find " to get start of ussd message.
+ p = strchr(p, '\"');
+ if (p == 0) {
+ *readlen = 0;
+ return false;
+ }
+ p+=1; //"
+ // Find " to get end of ussd message.
+ char *strend = strchr(p, '\"');
+
+ uint16_t lentocopy = min(maxlen-1, strend - p);
+ strncpy(ussdbuff, p, lentocopy+1);
+ ussdbuff[lentocopy] = 0;
+ *readlen = lentocopy;
+ }
+ return true;
+}
+
+
+/********* TIME **********************************************************/
+
+boolean Adafruit_FONA::enableNetworkTimeSync(boolean onoff) {
+ if (onoff) {
+ if (! sendCheckReply(F("AT+CLTS=1"), ok_reply))
+ return false;
+ } else {
+ if (! sendCheckReply(F("AT+CLTS=0"), ok_reply))
+ return false;
+ }
+
+ flushInput(); // eat any 'Unsolicted Result Code'
+
+ return true;
+}
+
+boolean Adafruit_FONA::enableNTPTimeSync(boolean onoff, FONAFlashStringPtr ntpserver) {
+ if (onoff) {
+ if (! sendCheckReply(F("AT+CNTPCID=1"), ok_reply))
+ return false;
+
+ mySerial->print(F("AT+CNTP=\""));
+ if (ntpserver != 0) {
+ mySerial->print(ntpserver);
+ } else {
+ mySerial->print(F("pool.ntp.org"));
+ }
+ mySerial->println(F("\",0"));
+ readline(FONA_DEFAULT_TIMEOUT_MS);
+ if (strcmp(replybuffer, "OK") != 0)
+ return false;
+
+ if (! sendCheckReply(F("AT+CNTP"), ok_reply, 10000))
+ return false;
+
+ uint16_t status;
+ readline(10000);
+ if (! parseReply(F("+CNTP:"), &status))
+ return false;
+ } else {
+ if (! sendCheckReply(F("AT+CNTPCID=0"), ok_reply))
+ return false;
+ }
+
+ return true;
+}
+
+boolean Adafruit_FONA::getTime(char *buff, uint16_t maxlen) {
+ getReply(F("AT+CCLK?"), (uint16_t) 10000);
+ if (strncmp(replybuffer, "+CCLK: ", 7) != 0)
+ return false;
+
+ char *p = replybuffer+7;
+ uint16_t lentocopy = min(maxlen-1, strlen(p));
+ strncpy(buff, p, lentocopy+1);
+ buff[lentocopy] = 0;
+
+ readline(); // eat OK
+
+ return true;
+}
+
+/********* GPS **********************************************************/
+
+
+boolean Adafruit_FONA::enableGPS(boolean onoff) {
+ uint16_t state;
+
+ // first check if its already on or off
+
+ if (_type == FONA808_V2) {
+ if (! sendParseReply(F("AT+CGNSPWR?"), F("+CGNSPWR: "), &state) )
+ return false;
+ } else {
+ if (! sendParseReply(F("AT+CGPSPWR?"), F("+CGPSPWR: "), &state))
+ return false;
+ }
+
+ if (onoff && !state) {
+ if (_type == FONA808_V2) {
+ if (! sendCheckReply(F("AT+CGNSPWR=1"), ok_reply)) // try GNS command
+ return false;
+ } else {
+ if (! sendCheckReply(F("AT+CGPSPWR=1"), ok_reply))
+ return false;
+ }
+ } else if (!onoff && state) {
+ if (_type == FONA808_V2) {
+ if (! sendCheckReply(F("AT+CGNSPWR=0"), ok_reply)) // try GNS command
+ return false;
+ } else {
+ if (! sendCheckReply(F("AT+CGPSPWR=0"), ok_reply))
+ return false;
+ }
+ }
+ return true;
+}
+
+
+
+boolean Adafruit_FONA_3G::enableGPS(boolean onoff) {
+ uint16_t state;
+
+ // first check if its already on or off
+ if (! Adafruit_FONA::sendParseReply(F("AT+CGPS?"), F("+CGPS: "), &state) )
+ return false;
+
+ if (onoff && !state) {
+ if (! sendCheckReply(F("AT+CGPS=1"), ok_reply))
+ return false;
+ } else if (!onoff && state) {
+ if (! sendCheckReply(F("AT+CGPS=0"), ok_reply))
+ return false;
+ // this takes a little time
+ readline(2000); // eat '+CGPS: 0'
+ }
+ return true;
+}
+
+int8_t Adafruit_FONA::GPSstatus(void) {
+ if (_type == FONA808_V2) {
+ // 808 V2 uses GNS commands and doesn't have an explicit 2D/3D fix status.
+ // Instead just look for a fix and if found assume it's a 3D fix.
+ getReply(F("AT+CGNSINF"));
+ char *p = prog_char_strstr(replybuffer, (prog_char*)F("+CGNSINF: "));
+ if (p == 0) return -1;
+ p+=10;
+ readline(); // eat 'OK'
+ if (p[0] == '0') return 0; // GPS is not even on!
+
+ p+=2; // Skip to second value, fix status.
+ //DEBUG_PRINTLN(p);
+ // Assume if the fix status is '1' then we have a 3D fix, otherwise no fix.
+ if (p[0] == '1') return 3;
+ else return 1;
+ }
+ if (_type == FONA3G_A || _type == FONA3G_E) {
+ // FONA 3G doesn't have an explicit 2D/3D fix status.
+ // Instead just look for a fix and if found assume it's a 3D fix.
+ getReply(F("AT+CGPSINFO"));
+ char *p = prog_char_strstr(replybuffer, (prog_char*)F("+CGPSINFO:"));
+ if (p == 0) return -1;
+ if (p[10] != ',') return 3; // if you get anything, its 3D fix
+ return 0;
+ }
+ else {
+ // 808 V1 looks for specific 2D or 3D fix state.
+ getReply(F("AT+CGPSSTATUS?"));
+ char *p = prog_char_strstr(replybuffer, (prog_char*)F("SSTATUS: Location "));
+ if (p == 0) return -1;
+ p+=18;
+ readline(); // eat 'OK'
+ //DEBUG_PRINTLN(p);
+ if (p[0] == 'U') return 0;
+ if (p[0] == 'N') return 1;
+ if (p[0] == '2') return 2;
+ if (p[0] == '3') return 3;
+ }
+ // else
+ return 0;
+}
+
+uint8_t Adafruit_FONA::getGPS(uint8_t arg, char *buffer, uint8_t maxbuff) {
+ int32_t x = arg;
+
+ if ( (_type == FONA3G_A) || (_type == FONA3G_E) ) {
+ getReply(F("AT+CGPSINFO"));
+ } else if (_type == FONA808_V1) {
+ getReply(F("AT+CGPSINF="), x);
+ } else {
+ getReply(F("AT+CGNSINF"));
+ }
+
+ char *p = prog_char_strstr(replybuffer, (prog_char*)F("SINF"));
+ if (p == 0) {
+ buffer[0] = 0;
+ return 0;
+ }
+
+ p+=6;
+
+ uint8_t len = max(maxbuff-1, strlen(p));
+ strncpy(buffer, p, len);
+ buffer[len] = 0;
+
+ readline(); // eat 'OK'
+ return len;
+}
+
+boolean Adafruit_FONA::getGPS(float *lat, float *lon, float *speed_kph, float *heading, float *altitude) {
+
+ char gpsbuffer[120];
+
+ // we need at least a 2D fix
+ if (GPSstatus() < 2)
+ return false;
+
+ // grab the mode 2^5 gps csv from the sim808
+ uint8_t res_len = getGPS(32, gpsbuffer, 120);
+
+ // make sure we have a response
+ if (res_len == 0)
+ return false;
+
+ if (_type == FONA3G_A || _type == FONA3G_E) {
+ // Parse 3G respose
+ // +CGPSINFO:4043.000000,N,07400.000000,W,151015,203802.1,-12.0,0.0,0
+ // skip beginning
+ char *tok;
+
+ // grab the latitude
+ char *latp = strtok(gpsbuffer, ",");
+ if (! latp) return false;
+
+ // grab latitude direction
+ char *latdir = strtok(NULL, ",");
+ if (! latdir) return false;
+
+ // grab longitude
+ char *longp = strtok(NULL, ",");
+ if (! longp) return false;
+
+ // grab longitude direction
+ char *longdir = strtok(NULL, ",");
+ if (! longdir) return false;
+
+ // skip date & time
+ tok = strtok(NULL, ",");
+ tok = strtok(NULL, ",");
+
+ // only grab altitude if needed
+ if (altitude != NULL) {
+ // grab altitude
+ char *altp = strtok(NULL, ",");
+ if (! altp) return false;
+ *altitude = atof(altp);
+ }
+
+ // only grab speed if needed
+ if (speed_kph != NULL) {
+ // grab the speed in km/h
+ char *speedp = strtok(NULL, ",");
+ if (! speedp) return false;
+
+ *speed_kph = atof(speedp);
+ }
+
+ // only grab heading if needed
+ if (heading != NULL) {
+
+ // grab the speed in knots
+ char *coursep = strtok(NULL, ",");
+ if (! coursep) return false;
+
+ *heading = atof(coursep);
+ }
+
+ double latitude = atof(latp);
+ double longitude = atof(longp);
+
+ // convert latitude from minutes to decimal
+ float degrees = floor(latitude / 100);
+ double minutes = latitude - (100 * degrees);
+ minutes /= 60;
+ degrees += minutes;
+
+ // turn direction into + or -
+ if (latdir[0] == 'S') degrees *= -1;
+
+ *lat = degrees;
+
+ // convert longitude from minutes to decimal
+ degrees = floor(longitude / 100);
+ minutes = longitude - (100 * degrees);
+ minutes /= 60;
+ degrees += minutes;
+
+ // turn direction into + or -
+ if (longdir[0] == 'W') degrees *= -1;
+
+ *lon = degrees;
+
+ } else if (_type == FONA808_V2) {
+ // Parse 808 V2 response. See table 2-3 from here for format:
+ // http://www.adafruit.com/datasheets/SIM800%20Series_GNSS_Application%20Note%20V1.00.pdf
+
+ // skip GPS run status
+ char *tok = strtok(gpsbuffer, ",");
+ if (! tok) return false;
+
+ // skip fix status
+ tok = strtok(NULL, ",");
+ if (! tok) return false;
+
+ // skip date
+ tok = strtok(NULL, ",");
+ if (! tok) return false;
+
+ // grab the latitude
+ char *latp = strtok(NULL, ",");
+ if (! latp) return false;
+
+ // grab longitude
+ char *longp = strtok(NULL, ",");
+ if (! longp) return false;
+
+ *lat = atof(latp);
+ *lon = atof(longp);
+
+ // only grab altitude if needed
+ if (altitude != NULL) {
+ // grab altitude
+ char *altp = strtok(NULL, ",");
+ if (! altp) return false;
+
+ *altitude = atof(altp);
+ }
+
+ // only grab speed if needed
+ if (speed_kph != NULL) {
+ // grab the speed in km/h
+ char *speedp = strtok(NULL, ",");
+ if (! speedp) return false;
+
+ *speed_kph = atof(speedp);
+ }
+
+ // only grab heading if needed
+ if (heading != NULL) {
+
+ // grab the speed in knots
+ char *coursep = strtok(NULL, ",");
+ if (! coursep) return false;
+
+ *heading = atof(coursep);
+ }
+ }
+ else {
+ // Parse 808 V1 response.
+
+ // skip mode
+ char *tok = strtok(gpsbuffer, ",");
+ if (! tok) return false;
+
+ // skip date
+ tok = strtok(NULL, ",");
+ if (! tok) return false;
+
+ // skip fix
+ tok = strtok(NULL, ",");
+ if (! tok) return false;
+
+ // grab the latitude
+ char *latp = strtok(NULL, ",");
+ if (! latp) return false;
+
+ // grab latitude direction
+ char *latdir = strtok(NULL, ",");
+ if (! latdir) return false;
+
+ // grab longitude
+ char *longp = strtok(NULL, ",");
+ if (! longp) return false;
+
+ // grab longitude direction
+ char *longdir = strtok(NULL, ",");
+ if (! longdir) return false;
+
+ double latitude = atof(latp);
+ double longitude = atof(longp);
+
+ // convert latitude from minutes to decimal
+ float degrees = floor(latitude / 100);
+ double minutes = latitude - (100 * degrees);
+ minutes /= 60;
+ degrees += minutes;
+
+ // turn direction into + or -
+ if (latdir[0] == 'S') degrees *= -1;
+
+ *lat = degrees;
+
+ // convert longitude from minutes to decimal
+ degrees = floor(longitude / 100);
+ minutes = longitude - (100 * degrees);
+ minutes /= 60;
+ degrees += minutes;
+
+ // turn direction into + or -
+ if (longdir[0] == 'W') degrees *= -1;
+
+ *lon = degrees;
+
+ // only grab speed if needed
+ if (speed_kph != NULL) {
+
+ // grab the speed in knots
+ char *speedp = strtok(NULL, ",");
+ if (! speedp) return false;
+
+ // convert to kph
+ *speed_kph = atof(speedp) * 1.852;
+
+ }
+
+ // only grab heading if needed
+ if (heading != NULL) {
+
+ // grab the speed in knots
+ char *coursep = strtok(NULL, ",");
+ if (! coursep) return false;
+
+ *heading = atof(coursep);
+
+ }
+
+ // no need to continue
+ if (altitude == NULL)
+ return true;
+
+ // we need at least a 3D fix for altitude
+ if (GPSstatus() < 3)
+ return false;
+
+ // grab the mode 0 gps csv from the sim808
+ res_len = getGPS(0, gpsbuffer, 120);
+
+ // make sure we have a response
+ if (res_len == 0)
+ return false;
+
+ // skip mode
+ tok = strtok(gpsbuffer, ",");
+ if (! tok) return false;
+
+ // skip lat
+ tok = strtok(NULL, ",");
+ if (! tok) return false;
+
+ // skip long
+ tok = strtok(NULL, ",");
+ if (! tok) return false;
+
+ // grab altitude
+ char *altp = strtok(NULL, ",");
+ if (! altp) return false;
+
+ *altitude = atof(altp);
+ }
+
+ return true;
+
+}
+
+boolean Adafruit_FONA::enableGPSNMEA(uint8_t i) {
+
+ char sendbuff[15] = "AT+CGPSOUT=000";
+ sendbuff[11] = (i / 100) + '0';
+ i %= 100;
+ sendbuff[12] = (i / 10) + '0';
+ i %= 10;
+ sendbuff[13] = i + '0';
+
+ if (_type == FONA808_V2) {
+ if (i)
+ return sendCheckReply(F("AT+CGNSTST=1"), ok_reply);
+ else
+ return sendCheckReply(F("AT+CGNSTST=0"), ok_reply);
+ } else {
+ return sendCheckReply(sendbuff, ok_reply, 2000);
+ }
+}
+
+
+/********* GPRS **********************************************************/
+
+
+boolean Adafruit_FONA::enableGPRS(boolean onoff) {
+
+ if (onoff) {
+ // disconnect all sockets
+ sendCheckReply(F("AT+CIPSHUT"), F("SHUT OK"), 20000);
+
+ if (! sendCheckReply(F("AT+CGATT=1"), ok_reply, 10000))
+ return false;
+
+ // set bearer profile! connection type GPRS
+ if (! sendCheckReply(F("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\""),
+ ok_reply, 10000))
+ return false;
+
+ // set bearer profile access point name
+ if (apn) {
+ // Send command AT+SAPBR=3,1,"APN","<apn value>" where <apn value> is the configured APN value.
+ if (! sendCheckReplyQuoted(F("AT+SAPBR=3,1,\"APN\","), apn, ok_reply, 10000))
+ return false;
+
+ // send AT+CSTT,"apn","user","pass"
+ flushInput();
+
+ mySerial->print(F("AT+CSTT=\""));
+ mySerial->print(apn);
+ if (apnusername) {
+ mySerial->print("\",\"");
+ mySerial->print(apnusername);
+ }
+ if (apnpassword) {
+ mySerial->print("\",\"");
+ mySerial->print(apnpassword);
+ }
+ mySerial->println("\"");
+
+ DEBUG_PRINT(F("\t---> ")); DEBUG_PRINT(F("AT+CSTT=\""));
+ DEBUG_PRINT(apn);
+
+ if (apnusername) {
+ DEBUG_PRINT("\",\"");
+ DEBUG_PRINT(apnusername);
+ }
+ if (apnpassword) {
+ DEBUG_PRINT("\",\"");
+ DEBUG_PRINT(apnpassword);
+ }
+ DEBUG_PRINTLN("\"");
+
+ if (! expectReply(ok_reply)) return false;
+
+ // set username/password
+ if (apnusername) {
+ // Send command AT+SAPBR=3,1,"USER","<user>" where <user> is the configured APN username.
+ if (! sendCheckReplyQuoted(F("AT+SAPBR=3,1,\"USER\","), apnusername, ok_reply, 10000))
+ return false;
+ }
+ if (apnpassword) {
+ // Send command AT+SAPBR=3,1,"PWD","<password>" where <password> is the configured APN password.
+ if (! sendCheckReplyQuoted(F("AT+SAPBR=3,1,\"PWD\","), apnpassword, ok_reply, 10000))
+ return false;
+ }
+ }
+
+ // open GPRS context
+ if (! sendCheckReply(F("AT+SAPBR=1,1"), ok_reply, 30000))
+ return false;
+
+ // bring up wireless connection
+ if (! sendCheckReply(F("AT+CIICR"), ok_reply, 10000))
+ return false;
+
+ } else {
+ // disconnect all sockets
+ if (! sendCheckReply(F("AT+CIPSHUT"), F("SHUT OK"), 20000))
+ return false;
+
+ // close GPRS context
+ if (! sendCheckReply(F("AT+SAPBR=0,1"), ok_reply, 10000))
+ return false;
+
+ if (! sendCheckReply(F("AT+CGATT=0"), ok_reply, 10000))
+ return false;
+
+ }
+ return true;
+}
+
+boolean Adafruit_FONA_3G::enableGPRS(boolean onoff) {
+
+ if (onoff) {
+ // disconnect all sockets
+ //sendCheckReply(F("AT+CIPSHUT"), F("SHUT OK"), 5000);
+
+ if (! sendCheckReply(F("AT+CGATT=1"), ok_reply, 10000))
+ return false;
+
+
+ // set bearer profile access point name
+ if (apn) {
+ // Send command AT+CGSOCKCONT=1,"IP","<apn value>" where <apn value> is the configured APN name.
+ if (! sendCheckReplyQuoted(F("AT+CGSOCKCONT=1,\"IP\","), apn, ok_reply, 10000))
+ return false;
+
+ // set username/password
+ if (apnusername) {
+ char authstring[100] = "AT+CGAUTH=1,1,\"";
+ char *strp = authstring + strlen(authstring);
+ prog_char_strcpy(strp, (prog_char *)apnusername);
+ strp+=prog_char_strlen((prog_char *)apnusername);
+ strp[0] = '\"';
+ strp++;
+ strp[0] = 0;
+
+ if (apnpassword) {
+ strp[0] = ','; strp++;
+ strp[0] = '\"'; strp++;
+ prog_char_strcpy(strp, (prog_char *)apnpassword);
+ strp+=prog_char_strlen((prog_char *)apnpassword);
+ strp[0] = '\"';
+ strp++;
+ strp[0] = 0;
+ }
+
+ if (! sendCheckReply(authstring, ok_reply, 10000))
+ return false;
+ }
+ }
+
+ // connect in transparent
+ if (! sendCheckReply(F("AT+CIPMODE=1"), ok_reply, 10000))
+ return false;
+ // open network (?)
+ if (! sendCheckReply(F("AT+NETOPEN=,,1"), F("Network opened"), 10000))
+ return false;
+
+ readline(); // eat 'OK'
+ } else {
+ // close GPRS context
+ if (! sendCheckReply(F("AT+NETCLOSE"), F("Network closed"), 10000))
+ return false;
+
+ readline(); // eat 'OK'
+ }
+
+ return true;
+}
+
+uint8_t Adafruit_FONA::GPRSstate(void) {
+ uint16_t state;
+
+ if (! sendParseReply(F("AT+CGATT?"), F("+CGATT: "), &state) )
+ return -1;
+
+ return state;
+}
+
+void Adafruit_FONA::setGPRSNetworkSettings(FONAFlashStringPtr apn,
+ FONAFlashStringPtr username, FONAFlashStringPtr password) {
+ this->apn = apn;
+ this->apnusername = username;
+ this->apnpassword = password;
+}
+
+boolean Adafruit_FONA::getGSMLoc(uint16_t *errorcode, char *buff, uint16_t maxlen) {
+
+ getReply(F("AT+CIPGSMLOC=1,1"), (uint16_t)10000);
+
+ if (! parseReply(F("+CIPGSMLOC: "), errorcode))
+ return false;
+
+ char *p = replybuffer+14;
+ uint16_t lentocopy = min(maxlen-1, strlen(p));
+ strncpy(buff, p, lentocopy+1);
+
+ readline(); // eat OK
+
+ return true;
+}
+
+boolean Adafruit_FONA::getGSMLoc(float *lat, float *lon) {
+
+ uint16_t returncode;
+ char gpsbuffer[120];
+
+ // make sure we could get a response
+ if (! getGSMLoc(&returncode, gpsbuffer, 120))
+ return false;
+
+ // make sure we have a valid return code
+ if (returncode != 0)
+ return false;
+
+ // +CIPGSMLOC: 0,-74.007729,40.730160,2015/10/15,19:24:55
+ // tokenize the gps buffer to locate the lat & long
+ char *longp = strtok(gpsbuffer, ",");
+ if (! longp) return false;
+
+ char *latp = strtok(NULL, ",");
+ if (! latp) return false;
+
+ *lat = atof(latp);
+ *lon = atof(longp);
+
+ return true;
+
+}
+/********* TCP FUNCTIONS ************************************/
+
+
+boolean Adafruit_FONA::TCPconnect(char *server, uint16_t port) {
+ flushInput();
+
+ // close all old connections
+ if (! sendCheckReply(F("AT+CIPSHUT"), F("SHUT OK"), 20000) ) return false;
+
+ // single connection at a time
+ if (! sendCheckReply(F("AT+CIPMUX=0"), ok_reply) ) return false;
+
+ // manually read data
+ if (! sendCheckReply(F("AT+CIPRXGET=1"), ok_reply) ) return false;
+
+
+ DEBUG_PRINT(F("AT+CIPSTART=\"TCP\",\""));
+ DEBUG_PRINT(server);
+ DEBUG_PRINT(F("\",\""));
+ DEBUG_PRINT(port);
+ DEBUG_PRINTLN(F("\""));
+
+
+ mySerial->print(F("AT+CIPSTART=\"TCP\",\""));
+ mySerial->print(server);
+ mySerial->print(F("\",\""));
+ mySerial->print(port);
+ mySerial->println(F("\""));
+
+ if (! expectReply(ok_reply)) return false;
+ if (! expectReply(F("CONNECT OK"))) return false;
+
+ // looks like it was a success (?)
+ return true;
+}
+
+boolean Adafruit_FONA::TCPclose(void) {
+ return sendCheckReply(F("AT+CIPCLOSE"), ok_reply);
+}
+
+boolean Adafruit_FONA::TCPconnected(void) {
+ if (! sendCheckReply(F("AT+CIPSTATUS"), ok_reply, 100) ) return false;
+ readline(100);
+
+ DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer);
+
+ return (strcmp(replybuffer, "STATE: CONNECT OK") == 0);
+}
+
+boolean Adafruit_FONA::TCPsend(char *packet, uint8_t len) {
+
+ DEBUG_PRINT(F("AT+CIPSEND="));
+ DEBUG_PRINTLN(len);
+#ifdef ADAFRUIT_FONA_DEBUG
+ for (uint16_t i=0; i<len; i++) {
+ DEBUG_PRINT(F(" 0x"));
+ DEBUG_PRINT(packet[i], HEX);
+ }
+#endif
+ DEBUG_PRINTLN();
+
+
+ mySerial->print(F("AT+CIPSEND="));
+ mySerial->println(len);
+ readline();
+
+ DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer);
+
+ if (replybuffer[0] != '>') return false;
+
+ mySerial->write(packet, len);
+ readline(3000); // wait up to 3 seconds to send the data
+
+ DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer);
+
+
+ return (strcmp(replybuffer, "SEND OK") == 0);
+}
+
+uint16_t Adafruit_FONA::TCPavailable(void) {
+ uint16_t avail;
+
+ if (! sendParseReply(F("AT+CIPRXGET=4"), F("+CIPRXGET: 4,"), &avail, ',', 0) ) return false;
+
+
+ DEBUG_PRINT (avail); DEBUG_PRINTLN(F(" bytes available"));
+
+
+ return avail;
+}
+
+
+uint16_t Adafruit_FONA::TCPread(uint8_t *buff, uint8_t len) {
+ uint16_t avail;
+
+ mySerial->print(F("AT+CIPRXGET=2,"));
+ mySerial->println(len);
+ readline();
+ if (! parseReply(F("+CIPRXGET: 2,"), &avail, ',', 0)) return false;
+
+ readRaw(avail);
+
+#ifdef ADAFRUIT_FONA_DEBUG
+ DEBUG_PRINT (avail); DEBUG_PRINTLN(F(" bytes read"));
+ for (uint8_t i=0;i<avail;i++) {
+ DEBUG_PRINT(F(" 0x")); DEBUG_PRINT(replybuffer[i], HEX);
+ }
+ DEBUG_PRINTLN();
+#endif
+
+ memcpy(buff, replybuffer, avail);
+
+ return avail;
+}
+
+
+
+/********* HTTP LOW LEVEL FUNCTIONS ************************************/
+
+boolean Adafruit_FONA::HTTP_init() {
+ return sendCheckReply(F("AT+HTTPINIT"), ok_reply);
+}
+
+boolean Adafruit_FONA::HTTP_term() {
+ return sendCheckReply(F("AT+HTTPTERM"), ok_reply);
+}
+
+void Adafruit_FONA::HTTP_para_start(FONAFlashStringPtr parameter,
+ boolean quoted) {
+ flushInput();
+
+
+ DEBUG_PRINT(F("\t---> "));
+ DEBUG_PRINT(F("AT+HTTPPARA=\""));
+ DEBUG_PRINT(parameter);
+ DEBUG_PRINTLN('"');
+
+
+ mySerial->print(F("AT+HTTPPARA=\""));
+ mySerial->print(parameter);
+ if (quoted)
+ mySerial->print(F("\",\""));
+ else
+ mySerial->print(F("\","));
+}
+
+boolean Adafruit_FONA::HTTP_para_end(boolean quoted) {
+ if (quoted)
+ mySerial->println('"');
+ else
+ mySerial->println();
+
+ return expectReply(ok_reply);
+}
+
+boolean Adafruit_FONA::HTTP_para(FONAFlashStringPtr parameter,
+ const char *value) {
+ HTTP_para_start(parameter, true);
+ mySerial->print(value);
+ return HTTP_para_end(true);
+}
+
+boolean Adafruit_FONA::HTTP_para(FONAFlashStringPtr parameter,
+ FONAFlashStringPtr value) {
+ HTTP_para_start(parameter, true);
+ mySerial->print(value);
+ return HTTP_para_end(true);
+}
+
+boolean Adafruit_FONA::HTTP_para(FONAFlashStringPtr parameter,
+ int32_t value) {
+ HTTP_para_start(parameter, false);
+ mySerial->print(value);
+ return HTTP_para_end(false);
+}
+
+boolean Adafruit_FONA::HTTP_data(uint32_t size, uint32_t maxTime) {
+ flushInput();
+
+
+ DEBUG_PRINT(F("\t---> "));
+ DEBUG_PRINT(F("AT+HTTPDATA="));
+ DEBUG_PRINT(size);
+ DEBUG_PRINT(',');
+ DEBUG_PRINTLN(maxTime);
+
+
+ mySerial->print(F("AT+HTTPDATA="));
+ mySerial->print(size);
+ mySerial->print(",");
+ mySerial->println(maxTime);
+
+ return expectReply(F("DOWNLOAD"));
+}
+
+boolean Adafruit_FONA::HTTP_action(uint8_t method, uint16_t *status,
+ uint16_t *datalen, int32_t timeout) {
+ // Send request.
+ if (! sendCheckReply(F("AT+HTTPACTION="), method, ok_reply))
+ return false;
+
+ // Parse response status and size.
+ readline(timeout);
+ if (! parseReply(F("+HTTPACTION:"), status, ',', 1))
+ return false;
+ if (! parseReply(F("+HTTPACTION:"), datalen, ',', 2))
+ return false;
+
+ return true;
+}
+
+boolean Adafruit_FONA::HTTP_readall(uint16_t *datalen) {
+ getReply(F("AT+HTTPREAD"));
+ if (! parseReply(F("+HTTPREAD:"), datalen, ',', 0))
+ return false;
+
+ return true;
+}
+
+boolean Adafruit_FONA::HTTP_ssl(boolean onoff) {
+ return sendCheckReply(F("AT+HTTPSSL="), onoff ? 1 : 0, ok_reply);
+}
+
+/********* HTTP HIGH LEVEL FUNCTIONS ***************************/
+
+boolean Adafruit_FONA::HTTP_GET_start(char *url,
+ uint16_t *status, uint16_t *datalen){
+ if (! HTTP_setup(url))
+ return false;
+
+ // HTTP GET
+ if (! HTTP_action(FONA_HTTP_GET, status, datalen, 30000))
+ return false;
+
+ DEBUG_PRINT(F("Status: ")); DEBUG_PRINTLN(*status);
+ DEBUG_PRINT(F("Len: ")); DEBUG_PRINTLN(*datalen);
+
+ // HTTP response data
+ if (! HTTP_readall(datalen))
+ return false;
+
+ return true;
+}
+
+/*
+boolean Adafruit_FONA_3G::HTTP_GET_start(char *ipaddr, char *path, uint16_t port
+ uint16_t *status, uint16_t *datalen){
+ char send[100] = "AT+CHTTPACT=\"";
+ char *sendp = send + strlen(send);
+ memset(sendp, 0, 100 - strlen(send));
+
+ strcpy(sendp, ipaddr);
+ sendp+=strlen(ipaddr);
+ sendp[0] = '\"';
+ sendp++;
+ sendp[0] = ',';
+ itoa(sendp, port);
+ getReply(send, 500);
+
+ return;
+
+ if (! HTTP_setup(url))
+
+ return false;
+
+ // HTTP GET
+ if (! HTTP_action(FONA_HTTP_GET, status, datalen))
+ return false;
+
+ DEBUG_PRINT("Status: "); DEBUG_PRINTLN(*status);
+ DEBUG_PRINT("Len: "); DEBUG_PRINTLN(*datalen);
+
+ // HTTP response data
+ if (! HTTP_readall(datalen))
+ return false;
+
+ return true;
+}
+*/
+
+void Adafruit_FONA::HTTP_GET_end(void) {
+ HTTP_term();
+}
+
+boolean Adafruit_FONA::HTTP_POST_start(char *url,
+ FONAFlashStringPtr contenttype,
+ const uint8_t *postdata, uint16_t postdatalen,
+ uint16_t *status, uint16_t *datalen){
+ if (! HTTP_setup(url))
+ return false;
+
+ if (! HTTP_para(F("CONTENT"), contenttype)) {
+ return false;
+ }
+
+ // HTTP POST data
+ if (! HTTP_data(postdatalen, 10000))
+ return false;
+ mySerial->write(postdata, postdatalen);
+ if (! expectReply(ok_reply))
+ return false;
+
+ // HTTP POST
+ if (! HTTP_action(FONA_HTTP_POST, status, datalen))
+ return false;
+
+ DEBUG_PRINT(F("Status: ")); DEBUG_PRINTLN(*status);
+ DEBUG_PRINT(F("Len: ")); DEBUG_PRINTLN(*datalen);
+
+ // HTTP response data
+ if (! HTTP_readall(datalen))
+ return false;
+
+ return true;
+}
+
+void Adafruit_FONA::HTTP_POST_end(void) {
+ HTTP_term();
+}
+
+void Adafruit_FONA::setUserAgent(FONAFlashStringPtr useragent) {
+ this->useragent = useragent;
+}
+
+void Adafruit_FONA::setHTTPSRedirect(boolean onoff) {
+ httpsredirect = onoff;
+}
+
+/********* HTTP HELPERS ****************************************/
+
+boolean Adafruit_FONA::HTTP_setup(char *url) {
+ // Handle any pending
+ HTTP_term();
+
+ // Initialize and set parameters
+ if (! HTTP_init())
+ return false;
+ if (! HTTP_para(F("CID"), 1))
+ return false;
+ if (! HTTP_para(F("UA"), useragent))
+ return false;
+ if (! HTTP_para(F("URL"), url))
+ return false;
+
+ // HTTPS redirect
+ if (httpsredirect) {
+ if (! HTTP_para(F("REDIR"),1))
+ return false;
+
+ if (! HTTP_ssl(true))
+ return false;
+ }
+
+ return true;
+}
+
+/********* HELPERS *********************************************/
+
+boolean Adafruit_FONA::expectReply(FONAFlashStringPtr reply,
+ uint16_t timeout) {
+ readline(timeout);
+
+ DEBUG_PRINT(F("\t<--- ")); DEBUG_PRINTLN(replybuffer);
+
+ return (prog_char_strcmp(replybuffer, (prog_char*)reply) == 0);
+}
+
+/********* LOW LEVEL *******************************************/
+
+inline int Adafruit_FONA::available(void) {
+ return mySerial->available();
+}
+
+inline size_t Adafruit_FONA::write(uint8_t x) {
+ return mySerial->write(x);
+}
+
+inline int Adafruit_FONA::read(void) {
+ return mySerial->read();
+}
+
+inline int Adafruit_FONA::peek(void) {
+ return mySerial->peek();
+}
+
+inline void Adafruit_FONA::flush() {
+ mySerial->flush();
+}
+
+void Adafruit_FONA::flushInput() {
+ // Read all available serial input to flush pending data.
+ uint16_t timeoutloop = 0;
+ while (timeoutloop++ < 40) {
+ while(available()) {
+ read();
+ timeoutloop = 0; // If char was received reset the timer
+ }
+ delay(1);
+ }
+}
+
+uint16_t Adafruit_FONA::readRaw(uint16_t b) {
+ uint16_t idx = 0;
+
+ while (b && (idx < sizeof(replybuffer)-1)) {
+ if (mySerial->available()) {
+ replybuffer[idx] = mySerial->read();
+ idx++;
+ b--;
+ }
+ }
+ replybuffer[idx] = 0;
+
+ return idx;
+}
+
+uint8_t Adafruit_FONA::readline(uint16_t timeout, boolean multiline) {
+ uint16_t replyidx = 0;
+
+ while (timeout--) {
+ if (replyidx >= 254) {
+ //DEBUG_PRINTLN(F("SPACE"));
+ break;
+ }
+
+ while(mySerial->available()) {
+ char c = mySerial->read();
+ if (c == '\r') continue;
+ if (c == 0xA) {
+ if (replyidx == 0) // the first 0x0A is ignored
+ continue;
+
+ if (!multiline) {
+ timeout = 0; // the second 0x0A is the end of the line
+ break;
+ }
+ }
+ replybuffer[replyidx] = c;
+ //DEBUG_PRINT(c, HEX); DEBUG_PRINT("#"); DEBUG_PRINTLN(c);
+ replyidx++;
+ }
+
+ if (timeout == 0) {
+ //DEBUG_PRINTLN(F("TIMEOUT"));
+ break;
+ }
+ delay(1);
+ }
+ replybuffer[replyidx] = 0; // null term
+ return replyidx;
+}
+
+uint8_t Adafruit_FONA::getReply(char *send, uint16_t timeout) {
+ flushInput();
+
+
+ DEBUG_PRINT(F("\t---> ")); DEBUG_PRINTLN(send);
+
+
+ mySerial->println(send);
+
+ uint8_t l = readline(timeout);
+
+ DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer);
+
+ return l;
+}
+
+uint8_t Adafruit_FONA::getReply(FONAFlashStringPtr send, uint16_t timeout) {
+ flushInput();
+
+
+ DEBUG_PRINT(F("\t---> ")); DEBUG_PRINTLN(send);
+
+
+ mySerial->println(send);
+
+ uint8_t l = readline(timeout);
+
+ DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer);
+
+ return l;
+}
+
+// Send prefix, suffix, and newline. Return response (and also set replybuffer with response).
+uint8_t Adafruit_FONA::getReply(FONAFlashStringPtr prefix, char *suffix, uint16_t timeout) {
+ flushInput();
+
+
+ DEBUG_PRINT(F("\t---> ")); DEBUG_PRINT(prefix); DEBUG_PRINTLN(suffix);
+
+
+ mySerial->print(prefix);
+ mySerial->println(suffix);
+
+ uint8_t l = readline(timeout);
+
+ DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer);
+
+ return l;
+}
+
+// Send prefix, suffix, and newline. Return response (and also set replybuffer with response).
+uint8_t Adafruit_FONA::getReply(FONAFlashStringPtr prefix, int32_t suffix, uint16_t timeout) {
+ flushInput();
+
+
+ DEBUG_PRINT(F("\t---> ")); DEBUG_PRINT(prefix); DEBUG_PRINTLN(suffix, DEC);
+
+
+ mySerial->print(prefix);
+ mySerial->println(suffix, DEC);
+
+ uint8_t l = readline(timeout);
+
+ DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer);
+
+ return l;
+}
+
+// Send prefix, suffix, suffix2, and newline. Return response (and also set replybuffer with response).
+uint8_t Adafruit_FONA::getReply(FONAFlashStringPtr prefix, int32_t suffix1, int32_t suffix2, uint16_t timeout) {
+ flushInput();
+
+
+ DEBUG_PRINT(F("\t---> ")); DEBUG_PRINT(prefix);
+ DEBUG_PRINT(suffix1, DEC); DEBUG_PRINT(','); DEBUG_PRINTLN(suffix2, DEC);
+
+
+ mySerial->print(prefix);
+ mySerial->print(suffix1);
+ mySerial->print(',');
+ mySerial->println(suffix2, DEC);
+
+ uint8_t l = readline(timeout);
+
+ DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer);
+
+ return l;
+}
+
+// Send prefix, ", suffix, ", and newline. Return response (and also set replybuffer with response).
+uint8_t Adafruit_FONA::getReplyQuoted(FONAFlashStringPtr prefix, FONAFlashStringPtr suffix, uint16_t timeout) {
+ flushInput();
+
+
+ DEBUG_PRINT(F("\t---> ")); DEBUG_PRINT(prefix);
+ DEBUG_PRINT('"'); DEBUG_PRINT(suffix); DEBUG_PRINTLN('"');
+
+
+ mySerial->print(prefix);
+ mySerial->print('"');
+ mySerial->print(suffix);
+ mySerial->println('"');
+
+ uint8_t l = readline(timeout);
+
+ DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer);
+
+ return l;
+}
+
+boolean Adafruit_FONA::sendCheckReply(char *send, char *reply, uint16_t timeout) {
+ if (! getReply(send, timeout) )
+ return false;
+/*
+ for (uint8_t i=0; i<strlen(replybuffer); i++) {
+ DEBUG_PRINT(replybuffer[i], HEX); DEBUG_PRINT(" ");
+ }
+ DEBUG_PRINTLN();
+ for (uint8_t i=0; i<strlen(reply); i++) {
+ DEBUG_PRINT(reply[i], HEX); DEBUG_PRINT(" ");
+ }
+ DEBUG_PRINTLN();
+ */
+ return (strcmp(replybuffer, reply) == 0);
+}
+
+boolean Adafruit_FONA::sendCheckReply(FONAFlashStringPtr send, FONAFlashStringPtr reply, uint16_t timeout) {
+ if (! getReply(send, timeout) )
+ return false;
+
+ return (prog_char_strcmp(replybuffer, (prog_char*)reply) == 0);
+}
+
+boolean Adafruit_FONA::sendCheckReply(char* send, FONAFlashStringPtr reply, uint16_t timeout) {
+ if (! getReply(send, timeout) )
+ return false;
+ return (prog_char_strcmp(replybuffer, (prog_char*)reply) == 0);
+}
+
+
+// Send prefix, suffix, and newline. Verify FONA response matches reply parameter.
+boolean Adafruit_FONA::sendCheckReply(FONAFlashStringPtr prefix, char *suffix, FONAFlashStringPtr reply, uint16_t timeout) {
+ getReply(prefix, suffix, timeout);
+ return (prog_char_strcmp(replybuffer, (prog_char*)reply) == 0);
+}
+
+// Send prefix, suffix, and newline. Verify FONA response matches reply parameter.
+boolean Adafruit_FONA::sendCheckReply(FONAFlashStringPtr prefix, int32_t suffix, FONAFlashStringPtr reply, uint16_t timeout) {
+ getReply(prefix, suffix, timeout);
+ return (prog_char_strcmp(replybuffer, (prog_char*)reply) == 0);
+}
+
+// Send prefix, suffix, suffix2, and newline. Verify FONA response matches reply parameter.
+boolean Adafruit_FONA::sendCheckReply(FONAFlashStringPtr prefix, int32_t suffix1, int32_t suffix2, FONAFlashStringPtr reply, uint16_t timeout) {
+ getReply(prefix, suffix1, suffix2, timeout);
+ return (prog_char_strcmp(replybuffer, (prog_char*)reply) == 0);
+}
+
+// Send prefix, ", suffix, ", and newline. Verify FONA response matches reply parameter.
+boolean Adafruit_FONA::sendCheckReplyQuoted(FONAFlashStringPtr prefix, FONAFlashStringPtr suffix, FONAFlashStringPtr reply, uint16_t timeout) {
+ getReplyQuoted(prefix, suffix, timeout);
+ return (prog_char_strcmp(replybuffer, (prog_char*)reply) == 0);
+}
+
+
+boolean Adafruit_FONA::parseReply(FONAFlashStringPtr toreply,
+ uint16_t *v, char divider, uint8_t index) {
+ char *p = prog_char_strstr(replybuffer, (prog_char*)toreply); // get the pointer to the voltage
+ if (p == 0) return false;
+ p+=prog_char_strlen((prog_char*)toreply);
+ //DEBUG_PRINTLN(p);
+ for (uint8_t i=0; i<index;i++) {
+ // increment dividers
+ p = strchr(p, divider);
+ if (!p) return false;
+ p++;
+ //DEBUG_PRINTLN(p);
+
+ }
+ *v = atoi(p);
+
+ return true;
+}
+
+boolean Adafruit_FONA::parseReply(FONAFlashStringPtr toreply,
+ char *v, char divider, uint8_t index) {
+ uint8_t i=0;
+ char *p = prog_char_strstr(replybuffer, (prog_char*)toreply);
+ if (p == 0) return false;
+ p+=prog_char_strlen((prog_char*)toreply);
+
+ for (i=0; i<index;i++) {
+ // increment dividers
+ p = strchr(p, divider);
+ if (!p) return false;
+ p++;
+ }
+
+ for(i=0; i<strlen(p);i++) {
+ if(p[i] == divider)
+ break;
+ v[i] = p[i];
+ }
+
+ v[i] = '\0';
+
+ return true;
+}
+
+// Parse a quoted string in the response fields and copy its value (without quotes)
+// to the specified character array (v). Only up to maxlen characters are copied
+// into the result buffer, so make sure to pass a large enough buffer to handle the
+// response.
+boolean Adafruit_FONA::parseReplyQuoted(FONAFlashStringPtr toreply,
+ char *v, int maxlen, char divider, uint8_t index) {
+ uint8_t i=0, j;
+ // Verify response starts with toreply.
+ char *p = prog_char_strstr(replybuffer, (prog_char*)toreply);
+ if (p == 0) return false;
+ p+=prog_char_strlen((prog_char*)toreply);
+
+ // Find location of desired response field.
+ for (i=0; i<index;i++) {
+ // increment dividers
+ p = strchr(p, divider);
+ if (!p) return false;
+ p++;
+ }
+
+ // Copy characters from response field into result string.
+ for(i=0, j=0; j<maxlen && i<strlen(p); ++i) {
+ // Stop if a divier is found.
+ if(p[i] == divider)
+ break;
+ // Skip any quotation marks.
+ else if(p[i] == '"')
+ continue;
+ v[j++] = p[i];
+ }
+
+ // Add a null terminator if result string buffer was not filled.
+ if (j < maxlen)
+ v[j] = '\0';
+
+ return true;
+}
+
+boolean Adafruit_FONA::sendParseReply(FONAFlashStringPtr tosend,
+ FONAFlashStringPtr toreply,
+ uint16_t *v, char divider, uint8_t index) {
+ getReply(tosend);
+
+ if (! parseReply(toreply, v, divider, index)) return false;
+
+ readline(); // eat 'OK'
+
+ return true;
+}
+
+
+// needed for CBC and others
+
+boolean Adafruit_FONA_3G::sendParseReply(FONAFlashStringPtr tosend,
+ FONAFlashStringPtr toreply,
+ float *f, char divider, uint8_t index) {
+ getReply(tosend);
+
+ if (! parseReply(toreply, f, divider, index)) return false;
+
+ readline(); // eat 'OK'
+
+ return true;
+}
+
+
+boolean Adafruit_FONA_3G::parseReply(FONAFlashStringPtr toreply,
+ float *f, char divider, uint8_t index) {
+ char *p = prog_char_strstr(replybuffer, (prog_char*)toreply); // get the pointer to the voltage
+ if (p == 0) return false;
+ p+=prog_char_strlen((prog_char*)toreply);
+ //DEBUG_PRINTLN(p);
+ for (uint8_t i=0; i<index;i++) {
+ // increment dividers
+ p = strchr(p, divider);
+ if (!p) return false;
+ p++;
+ //DEBUG_PRINTLN(p);
+
+ }
+ *f = atof(p);
+
+ return true;
+}
diff -r 000000000000 -r 8b6028668696 Adafruit_FONA.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Adafruit_FONA.h Mon Oct 17 10:51:58 2016 +0000
@@ -0,0 +1,263 @@
+/***************************************************
+ This is a library for our Adafruit FONA Cellular Module
+
+ Designed specifically to work with the Adafruit FONA
+ ----> http://www.adafruit.com/products/1946
+ ----> http://www.adafruit.com/products/1963
+
+ These displays use TTL Serial to communicate, 2 pins are required to
+ interface
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ Written by Limor Fried/Ladyada for Adafruit Industries.
+ BSD license, all text above must be included in any redistribution
+ ****************************************************/
+#ifndef ADAFRUIT_FONA_H
+#define ADAFRUIT_FONA_H
+
+#include "includes/FONAConfig.h"
+#include "includes/FONAExtIncludes.h"
+#include "includes/platform/FONAPlatform.h"
+
+
+
+#define FONA800L 1
+#define FONA800H 6
+
+#define FONA808_V1 2
+#define FONA808_V2 3
+
+#define FONA3G_A 4
+#define FONA3G_E 5
+
+// Uncomment to changed the preferred SMS storage
+//#define FONA_PREF_SMS_STORAGE "SM"
+
+#define FONA_HEADSETAUDIO 0
+#define FONA_EXTAUDIO 1
+
+#define FONA_STTONE_DIALTONE 1
+#define FONA_STTONE_BUSY 2
+#define FONA_STTONE_CONGESTION 3
+#define FONA_STTONE_PATHACK 4
+#define FONA_STTONE_DROPPED 5
+#define FONA_STTONE_ERROR 6
+#define FONA_STTONE_CALLWAIT 7
+#define FONA_STTONE_RINGING 8
+#define FONA_STTONE_BEEP 16
+#define FONA_STTONE_POSTONE 17
+#define FONA_STTONE_ERRTONE 18
+#define FONA_STTONE_INDIANDIALTONE 19
+#define FONA_STTONE_USADIALTONE 20
+
+#define FONA_DEFAULT_TIMEOUT_MS 500
+
+#define FONA_HTTP_GET 0
+#define FONA_HTTP_POST 1
+#define FONA_HTTP_HEAD 2
+
+#define FONA_CALL_READY 0
+#define FONA_CALL_FAILED 1
+#define FONA_CALL_UNKNOWN 2
+#define FONA_CALL_RINGING 3
+#define FONA_CALL_INPROGRESS 4
+
+class Adafruit_FONA : public FONAStreamType {
+ public:
+ Adafruit_FONA(int8_t r);
+ boolean begin(FONAStreamType &port);
+ uint8_t type();
+
+ // Stream
+ int available(void);
+ size_t write(uint8_t x);
+ int read(void);
+ int peek(void);
+ void flush();
+
+ // FONA 3G requirements
+ boolean setBaudrate(uint16_t baud);
+
+ // RTC
+ boolean enableRTC(uint8_t i);
+ boolean readRTC(uint8_t *year, uint8_t *month, uint8_t *date, uint8_t *hr, uint8_t *min, uint8_t *sec);
+
+ // Battery and ADC
+ boolean getADCVoltage(uint16_t *v);
+ boolean getBattPercent(uint16_t *p);
+ boolean getBattVoltage(uint16_t *v);
+
+ // SIM query
+ uint8_t unlockSIM(char *pin);
+ uint8_t getSIMCCID(char *ccid);
+ uint8_t getNetworkStatus(void);
+ uint8_t getRSSI(void);
+
+ // IMEI
+ uint8_t getIMEI(char *imei);
+
+ // set Audio output
+ boolean setAudio(uint8_t a);
+ boolean setVolume(uint8_t i);
+ uint8_t getVolume(void);
+ boolean playToolkitTone(uint8_t t, uint16_t len);
+ boolean setMicVolume(uint8_t a, uint8_t level);
+ boolean playDTMF(char tone);
+
+ // FM radio functions.
+ boolean tuneFMradio(uint16_t station);
+ boolean FMradio(boolean onoff, uint8_t a = FONA_HEADSETAUDIO);
+ boolean setFMVolume(uint8_t i);
+ int8_t getFMVolume();
+ int8_t getFMSignalLevel(uint16_t station);
+
+ // SMS handling
+ boolean setSMSInterrupt(uint8_t i);
+ uint8_t getSMSInterrupt(void);
+ int8_t getNumSMS(void);
+ boolean readSMS(uint8_t i, char *smsbuff, uint16_t max, uint16_t *readsize);
+ boolean sendSMS(char *smsaddr, char *smsmsg);
+ boolean deleteSMS(uint8_t i);
+ boolean getSMSSender(uint8_t i, char *sender, int senderlen);
+ boolean sendUSSD(char *ussdmsg, char *ussdbuff, uint16_t maxlen, uint16_t *readlen);
+
+ // Time
+ boolean enableNetworkTimeSync(boolean onoff);
+ boolean enableNTPTimeSync(boolean onoff, FONAFlashStringPtr ntpserver=0);
+ boolean getTime(char *buff, uint16_t maxlen);
+
+ // GPRS handling
+ boolean enableGPRS(boolean onoff);
+ uint8_t GPRSstate(void);
+ boolean getGSMLoc(uint16_t *replycode, char *buff, uint16_t maxlen);
+ boolean getGSMLoc(float *lat, float *lon);
+ void setGPRSNetworkSettings(FONAFlashStringPtr apn, FONAFlashStringPtr username=0, FONAFlashStringPtr password=0);
+
+ // GPS handling
+ boolean enableGPS(boolean onoff);
+ int8_t GPSstatus(void);
+ uint8_t getGPS(uint8_t arg, char *buffer, uint8_t maxbuff);
+ boolean getGPS(float *lat, float *lon, float *speed_kph=0, float *heading=0, float *altitude=0);
+ boolean enableGPSNMEA(uint8_t nmea);
+
+ // TCP raw connections
+ boolean TCPconnect(char *server, uint16_t port);
+ boolean TCPclose(void);
+ boolean TCPconnected(void);
+ boolean TCPsend(char *packet, uint8_t len);
+ uint16_t TCPavailable(void);
+ uint16_t TCPread(uint8_t *buff, uint8_t len);
+
+ // HTTP low level interface (maps directly to SIM800 commands).
+ boolean HTTP_init();
+ boolean HTTP_term();
+ void HTTP_para_start(FONAFlashStringPtr parameter, boolean quoted = true);
+ boolean HTTP_para_end(boolean quoted = true);
+ boolean HTTP_para(FONAFlashStringPtr parameter, const char *value);
+ boolean HTTP_para(FONAFlashStringPtr parameter, FONAFlashStringPtr value);
+ boolean HTTP_para(FONAFlashStringPtr parameter, int32_t value);
+ boolean HTTP_data(uint32_t size, uint32_t maxTime=10000);
+ boolean HTTP_action(uint8_t method, uint16_t *status, uint16_t *datalen, int32_t timeout = 10000);
+ boolean HTTP_readall(uint16_t *datalen);
+ boolean HTTP_ssl(boolean onoff);
+
+ // HTTP high level interface (easier to use, less flexible).
+ boolean HTTP_GET_start(char *url, uint16_t *status, uint16_t *datalen);
+ void HTTP_GET_end(void);
+ boolean HTTP_POST_start(char *url, FONAFlashStringPtr contenttype, const uint8_t *postdata, uint16_t postdatalen, uint16_t *status, uint16_t *datalen);
+ void HTTP_POST_end(void);
+ void setUserAgent(FONAFlashStringPtr useragent);
+
+ // HTTPS
+ void setHTTPSRedirect(boolean onoff);
+
+ // PWM (buzzer)
+ boolean setPWM(uint16_t period, uint8_t duty = 50);
+
+ // Phone calls
+ boolean callPhone(char *phonenum);
+ uint8_t getCallStatus(void);
+ boolean hangUp(void);
+ boolean pickUp(void);
+ boolean callerIdNotification(boolean enable, uint8_t interrupt = 0);
+ boolean incomingCallNumber(char* phonenum);
+
+ // Helper functions to verify responses.
+ boolean expectReply(FONAFlashStringPtr reply, uint16_t timeout = 10000);
+ boolean sendCheckReply(char *send, char *reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+ boolean sendCheckReply(FONAFlashStringPtr send, FONAFlashStringPtr reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+ boolean sendCheckReply(char* send, FONAFlashStringPtr reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+
+
+ protected:
+ int8_t _rstpin;
+ uint8_t _type;
+
+ char replybuffer[255];
+ FONAFlashStringPtr apn;
+ FONAFlashStringPtr apnusername;
+ FONAFlashStringPtr apnpassword;
+ boolean httpsredirect;
+ FONAFlashStringPtr useragent;
+ FONAFlashStringPtr ok_reply;
+
+ // HTTP helpers
+ boolean HTTP_setup(char *url);
+
+ void flushInput();
+ uint16_t readRaw(uint16_t b);
+ uint8_t readline(uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS, boolean multiline = false);
+ uint8_t getReply(char *send, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+ uint8_t getReply(FONAFlashStringPtr send, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+ uint8_t getReply(FONAFlashStringPtr prefix, char *suffix, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+ uint8_t getReply(FONAFlashStringPtr prefix, int32_t suffix, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+ uint8_t getReply(FONAFlashStringPtr prefix, int32_t suffix1, int32_t suffix2, uint16_t timeout); // Don't set default value or else function call is ambiguous.
+ uint8_t getReplyQuoted(FONAFlashStringPtr prefix, FONAFlashStringPtr suffix, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+
+ boolean sendCheckReply(FONAFlashStringPtr prefix, char *suffix, FONAFlashStringPtr reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+ boolean sendCheckReply(FONAFlashStringPtr prefix, int32_t suffix, FONAFlashStringPtr reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+ boolean sendCheckReply(FONAFlashStringPtr prefix, int32_t suffix, int32_t suffix2, FONAFlashStringPtr reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+ boolean sendCheckReplyQuoted(FONAFlashStringPtr prefix, FONAFlashStringPtr suffix, FONAFlashStringPtr reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+
+
+ boolean parseReply(FONAFlashStringPtr toreply,
+ uint16_t *v, char divider = ',', uint8_t index=0);
+ boolean parseReply(FONAFlashStringPtr toreply,
+ char *v, char divider = ',', uint8_t index=0);
+ boolean parseReplyQuoted(FONAFlashStringPtr toreply,
+ char *v, int maxlen, char divider, uint8_t index);
+
+ boolean sendParseReply(FONAFlashStringPtr tosend,
+ FONAFlashStringPtr toreply,
+ uint16_t *v, char divider = ',', uint8_t index=0);
+
+ static boolean _incomingCall;
+ static void onIncomingCall();
+
+ FONAStreamType *mySerial;
+};
+
+class Adafruit_FONA_3G : public Adafruit_FONA {
+
+ public:
+ Adafruit_FONA_3G (int8_t r) : Adafruit_FONA(r) { _type = FONA3G_A; }
+
+ boolean getBattVoltage(uint16_t *v);
+ boolean playToolkitTone(uint8_t t, uint16_t len);
+ boolean hangUp(void);
+ boolean pickUp(void);
+ boolean enableGPRS(boolean onoff);
+ boolean enableGPS(boolean onoff);
+
+ protected:
+ boolean parseReply(FONAFlashStringPtr toreply,
+ float *f, char divider, uint8_t index);
+
+ boolean sendParseReply(FONAFlashStringPtr tosend,
+ FONAFlashStringPtr toreply,
+ float *f, char divider = ',', uint8_t index=0);
+};
+
+#endif