screen display for roommate tracker

Dependencies:   mbed-rtos mbed uLCD_4D_Picaso

Dependents:   RoommateTracker

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Adafruit_FONA.cpp Source File

Adafruit_FONA.cpp

00001 /***************************************************
00002   This is a library for our Adafruit FONA Cellular Module
00003 
00004   Designed specifically to work with the Adafruit FONA
00005   ----> http://www.adafruit.com/products/1946
00006   ----> http://www.adafruit.com/products/1963
00007 
00008   These displays use TTL Serial to communicate, 2 pins are required to
00009   interface
00010   Adafruit invests time and resources providing this open source code,
00011   please support Adafruit and open-source hardware by purchasing
00012   products from Adafruit!
00013 
00014   Written by Limor Fried/Ladyada for Adafruit Industries.
00015   BSD license, all text above must be included in any redistribution
00016  ****************************************************/
00017  
00018  /*
00019   *  Modified by George Tzintzarov & Jesse Baker 03/14/2016 for use in mbed LPC1768
00020   */
00021 #include <algorithm>
00022 #include "Adafruit_FONA.h"
00023 
00024 #define HIGH 1
00025 #define LOW 0
00026 
00027 /*
00028 Notes George is taking:
00029 sendCheckReply returns a boolean where its true when FONA responds with the string of its second input
00030 
00031 */
00032 
00033 
00034 bool Adafruit_FONA::begin(int baudrate) {
00035     mySerial.baud(baudrate); //set the baud rate of the fona serial connection
00036     mySerial.attach(this, &Adafruit_FONA::onSerialDataReceived, Serial::RxIrq); //attached onSerialDataReceived as Serial receive interrupt
00037     
00038     // INIT Reboot process
00039     _rstpin = HIGH;
00040     wait_ms(10);
00041     _rstpin = LOW;
00042     wait_ms(100);
00043     _rstpin = HIGH;
00044     
00045     // give 3 seconds to reboot
00046     wait_ms(3000);
00047     
00048     // flushes the serial port
00049     while (readable()) getc();
00050     
00051     // Make sure FONA is alive
00052     sendCheckReply("AT", "OK");
00053     wait_ms(100);
00054     sendCheckReply("AT", "OK");
00055     wait_ms(100);
00056     sendCheckReply("AT", "OK");
00057     wait_ms(100);
00058     
00059     // turn off Echo!
00060     sendCheckReply("ATE0", "OK");
00061     wait_ms(100);
00062     
00063     // Just checks if the FONA even responds, if it doesnt, then return false
00064     if (! sendCheckReply("ATE0", "OK")) {
00065         return false;
00066     }
00067     
00068     return true;
00069 }
00070 
00071 void Adafruit_FONA::setEventListener(EventListener *eventListener) {
00072     this->eventListener = eventListener;
00073 }
00074 
00075 /********* Stream ********************************************/
00076 
00077 int Adafruit_FONA::_putc(int value) {
00078     return mySerial.putc(value);
00079 }
00080 
00081 int Adafruit_FONA::_getc() {
00082     __disable_irq(); // Start Critical Section - don't interrupt while changing global buffer variables
00083     
00084     // Wait for data if the buffer is empty
00085     if (isRxBufferEmpty()) {
00086         __enable_irq(); // End Critical Section - need to allow rx interrupt to get new characters for buffer
00087         
00088         while(isRxBufferEmpty());
00089         
00090         __disable_irq(); // Start Critical Section - don't interrupt while changing global buffer variables
00091     }
00092     
00093     int data = rxBuffer[rxBufferOutIndex];
00094     incrementRxBufferOutIndex();
00095     
00096     __enable_irq(); // End Critical Section
00097     
00098     return data;
00099 }
00100 
00101 int Adafruit_FONA::readable() {
00102     return !isRxBufferEmpty();
00103 }
00104 
00105 void Adafruit_FONA::onSerialDataReceived() {
00106     while (mySerial.readable() && !isRxBufferFull()) {
00107         int data = mySerial.getc();
00108         rxBuffer[rxBufferInIndex] = data;
00109         
00110         //
00111         // Analyze the received data in order to detect events like RING or NO CARRIER
00112         //
00113         
00114         // Copy the data in the current line
00115         if (currentReceivedLineSize < RX_BUFFER_SIZE && data != '\r' && data != '\n') {
00116             currentReceivedLine[currentReceivedLineSize] = (char) data;
00117             currentReceivedLineSize++;
00118         }
00119         
00120         // Check if the line is complete
00121         if (data == '\n') {
00122             currentReceivedLine[currentReceivedLineSize] = 0;
00123             
00124             if (eventListener != NULL) {
00125                 // Check if we have a special event
00126                 if (strcmp(currentReceivedLine, "RING") == 0) {
00127                     eventListener->onRing();
00128                 } else if (strcmp(currentReceivedLine, "NO CARRIER") == 0) {
00129                     eventListener->onNoCarrier();
00130                 }
00131             }
00132             
00133             currentReceivedLineSize = 0;
00134         }
00135         
00136         incrementRxBufferInIndex();
00137     }
00138 }
00139 
00140 /********* Real Time Clock ********************************************/
00141 
00142 bool Adafruit_FONA::enableRTC(uint8_t i) {
00143     if (! sendCheckReply("AT+CLTS=", i, "OK")) 
00144         return false;
00145     return sendCheckReply("AT&W", "OK");
00146 }
00147 
00148 /********* BATTERY & ADC ********************************************/
00149 
00150 /* returns value in mV (uint16_t) */
00151 bool Adafruit_FONA::getBattVoltage(uint16_t *v) {
00152     return sendParseReply("AT+CBC", "+CBC: ", v, ',', 2);
00153 }
00154 
00155 /* returns the percentage charge of battery as reported by sim800 */
00156 bool Adafruit_FONA::getBattPercent(uint16_t *p) {
00157     return sendParseReply("AT+CBC", "+CBC: ", p, ',', 1);
00158 }
00159 
00160 bool Adafruit_FONA::getADCVoltage(uint16_t *v) {
00161     return sendParseReply("AT+CADC?", "+CADC: 1,", v);
00162 }
00163 
00164 /********* SIM ***********************************************************/
00165 
00166 bool Adafruit_FONA::unlockSIM(char *pin)
00167 {
00168     char sendbuff[14] = "AT+CPIN=";
00169     sendbuff[8] = pin[0];
00170     sendbuff[9] = pin[1];
00171     sendbuff[10] = pin[2];
00172     sendbuff[11] = pin[3];
00173     sendbuff[12] = NULL;
00174     
00175     return sendCheckReply(sendbuff, "OK");
00176 }
00177 
00178 uint8_t Adafruit_FONA::getSIMCCID(char *ccid) {
00179     getReply("AT+CCID");
00180     // up to 20 chars
00181     strncpy(ccid, replybuffer, 20);
00182     ccid[20] = 0;
00183     
00184     readline(); // eat 'OK'
00185     
00186     return strlen(ccid);
00187 }
00188 
00189 /********* IMEI **********************************************************/
00190 
00191 uint8_t Adafruit_FONA::getIMEI(char *imei) {
00192     getReply("AT+GSN");
00193     
00194     // up to 15 chars
00195     strncpy(imei, replybuffer, 15);
00196     imei[15] = 0;
00197     
00198     readline(); // eat 'OK'
00199     
00200     return strlen(imei);
00201 }
00202 
00203 /********* NETWORK *******************************************************/
00204 
00205 uint8_t Adafruit_FONA::getNetworkStatus(void) {
00206     uint16_t status;
00207     
00208     if (! sendParseReply("AT+CREG?", "+CREG: ", &status, ',', 1)) return 0;
00209     
00210     return status;
00211 }
00212 
00213 
00214 uint8_t Adafruit_FONA::getRSSI(void) {
00215     uint16_t reply;
00216     
00217     if (! sendParseReply("AT+CSQ", "+CSQ: ", &reply) ) return 0;
00218     
00219     return reply;
00220 }
00221 
00222 /********* AUDIO *******************************************************/
00223 
00224 bool Adafruit_FONA::setAudio(uint8_t a) {
00225     // 0 is headset, 1 is external audio
00226     if (a > 1) return false;
00227     
00228     return sendCheckReply("AT+CHFA=", a, "OK");
00229 }
00230 
00231 uint8_t Adafruit_FONA::getVolume(void) {
00232     uint16_t reply;
00233     
00234     if (! sendParseReply("AT+CLVL?", "+CLVL: ", &reply) ) return 0;
00235     
00236     return reply;
00237 }
00238 
00239 bool Adafruit_FONA::setVolume(uint8_t i) {
00240     return sendCheckReply("AT+CLVL=", i, "OK");
00241 }
00242 
00243 
00244 bool Adafruit_FONA::playDTMF(char dtmf) {
00245     char str[4];
00246     str[0] = '\"';
00247     str[1] = dtmf;
00248     str[2] = '\"';
00249     str[3] = 0;
00250     return sendCheckReply("AT+CLDTMF=3,", str, "OK");
00251 }
00252 
00253 bool Adafruit_FONA::playToolkitTone(uint8_t t, uint16_t len) {
00254     return sendCheckReply("AT+STTONE=1,", t, len, "OK");
00255 }
00256 
00257 bool Adafruit_FONA::setMicVolume(uint8_t a, uint8_t level) {
00258     // 0 is headset, 1 is external audio
00259     if (a > 1) return false;
00260     
00261     return sendCheckReply("AT+CMIC=", a, level, "OK");
00262 }
00263 
00264 /********* FM RADIO *******************************************************/
00265 
00266 
00267 bool Adafruit_FONA::FMradio(bool onoff, uint8_t a) {
00268     if (! onoff) {
00269         return sendCheckReply("AT+FMCLOSE", "OK");
00270     }
00271     
00272     // 0 is headset, 1 is external audio
00273     if (a > 1) return false;
00274     
00275     return sendCheckReply("AT+FMOPEN=", a, "OK");
00276 }
00277 
00278 bool Adafruit_FONA::tuneFMradio(uint16_t station) {
00279     // Fail if FM station is outside allowed range.
00280     if ((station < 870) || (station > 1090))
00281         return false;
00282     
00283     return sendCheckReply("AT+FMFREQ=", station, "OK");
00284 }
00285 
00286 bool Adafruit_FONA::setFMVolume(uint8_t i) {
00287     // Fail if volume is outside allowed range (0-6).
00288     if (i > 6) {
00289     return false;
00290     }
00291     // Send FM volume command and verify response.
00292     return sendCheckReply("AT+FMVOLUME=", i, "OK");
00293 }
00294 
00295 int8_t Adafruit_FONA::getFMVolume() {
00296     uint16_t level;
00297     
00298     if (! sendParseReply("AT+FMVOLUME?", "+FMVOLUME: ", &level) ) return 0;
00299     
00300     return level;
00301 }
00302 
00303 int8_t Adafruit_FONA::getFMSignalLevel(uint16_t station) {
00304     // Fail if FM station is outside allowed range.
00305     if ((station < 875) || (station > 1080)) {
00306         return -1;
00307     }   
00308     
00309     // Send FM signal level query command.
00310     // Note, need to explicitly send timeout so right overload is chosen.
00311     getReply("AT+FMSIGNAL=", station, FONA_DEFAULT_TIMEOUT_MS);
00312     // Check response starts with expected value.
00313     char *p = strstr(replybuffer, "+FMSIGNAL: ");
00314     if (p == 0) return -1;
00315     p+=11;
00316     // Find second colon to get start of signal quality.
00317     p = strchr(p, ':');
00318     if (p == 0) return -1;
00319     p+=1;
00320     // Parse signal quality.
00321     int8_t level = atoi(p);
00322     readline();  // eat the "OK"
00323     return level;
00324 }
00325 
00326 /********* PWM/BUZZER **************************************************/
00327 
00328 bool Adafruit_FONA::setPWM(uint16_t period, uint8_t duty) {
00329     if (period > 2000) return false;
00330     if (duty > 100) return false;
00331     
00332     return sendCheckReply("AT+SPWM=0,", period, duty, "OK");
00333 }
00334 
00335 /********* CALL PHONES **************************************************/
00336 bool Adafruit_FONA::callPhone(char *number) {
00337     char sendbuff[35] = "ATD";
00338     strncpy(sendbuff+3, number, min((int)30, (int)strlen(number)));
00339     uint8_t x = strlen(sendbuff);
00340     sendbuff[x] = ';';
00341     sendbuff[x+1] = 0;
00342     
00343     return sendCheckReply(sendbuff, "OK");
00344 }
00345 
00346 bool Adafruit_FONA::hangUp(void) {
00347     return sendCheckReply("ATH0", "OK");
00348 }
00349 
00350 bool Adafruit_FONA::pickUp(void) {
00351     return sendCheckReply("ATA", "OK");
00352 }
00353 
00354 void Adafruit_FONA::onIncomingCall() {
00355 #ifdef ADAFRUIT_FONA_DEBUG
00356     printf("> Incoming call...\r\n");
00357 #endif
00358     _incomingCall = true;
00359 }
00360 
00361 bool Adafruit_FONA::callerIdNotification(bool enable) {
00362     if(enable){
00363         _ringIndicatorInterruptIn.fall(this, &Adafruit_FONA::onIncomingCall);
00364         return sendCheckReply("AT+CLIP=1", "OK");
00365     }
00366     
00367     _ringIndicatorInterruptIn.fall(NULL);
00368     return sendCheckReply("AT+CLIP=0", "OK");
00369 }
00370 
00371 bool Adafruit_FONA::incomingCallNumber(char* phonenum) {
00372     //+CLIP: "<incoming phone number>",145,"",0,"",0
00373     if(!_incomingCall)
00374         return false;
00375     
00376     readline();
00377     while(!strcmp(replybuffer, "RING") == 0) {
00378         flushInput();
00379         readline();
00380     }
00381     
00382     readline(); //reads incoming phone number line
00383     
00384     parseReply("+CLIP: \"", phonenum, '"');
00385     
00386 #ifdef ADAFRUIT_FONA_DEBUG
00387     printf("Phone Number: %s\r\n", replybuffer);
00388 #endif
00389     
00390     _incomingCall = false;
00391     return true;
00392 }
00393 
00394 /********* SMS **********************************************************/
00395 
00396 uint8_t Adafruit_FONA::getSMSInterrupt(void) {
00397     uint16_t reply;
00398     
00399     if (! sendParseReply("AT+CFGRI?", "+CFGRI: ", &reply) ) return 0;
00400     
00401     return reply;
00402 }
00403 
00404 bool Adafruit_FONA::setSMSInterrupt(uint8_t i) {
00405     return sendCheckReply("AT+CFGRI=", i, "OK");
00406 }
00407 
00408 int8_t Adafruit_FONA::getNumSMS(void) {
00409     uint16_t numsms;
00410     
00411     if (! sendCheckReply("AT+CMGF=1", "OK")) return -1;
00412     // ask how many sms are stored
00413     
00414     if (! sendParseReply("AT+CPMS?", "+CPMS: \"SM_P\",", &numsms) ) return -1;
00415     
00416     return numsms;
00417 }
00418 
00419 // Reading SMS's is a bit involved so we don't use helpers that may cause delays or debug
00420 // printouts!
00421 bool Adafruit_FONA::readSMS(uint8_t i, char *smsbuff, uint16_t maxlen, uint16_t *readlen) {
00422     // text mode
00423     if (! sendCheckReply("AT+CMGF=1", "OK")) return false;
00424     
00425     // show all text mode parameters
00426     if (! sendCheckReply("AT+CSDH=1", "OK")) return false;
00427     
00428     // parse out the SMS len
00429     uint16_t thesmslen = 0;
00430     
00431     //getReply(F("AT+CMGR="), i, 1000);  //  do not print debug!
00432     mySerial.printf("AT+CMGR=%d\r\n", i);
00433     readline(1000); // timeout
00434     
00435     // parse it out...
00436     if (! parseReply("+CMGR:", &thesmslen, ',', 11)) {
00437         *readlen = 0;
00438         return false;
00439     }
00440     
00441     readRaw(thesmslen);
00442     
00443     flushInput();
00444     
00445     uint16_t thelen = min(maxlen, (uint16_t)strlen(replybuffer));
00446     strncpy(smsbuff, replybuffer, thelen);
00447     smsbuff[thelen] = 0; // end the string
00448     
00449 #ifdef ADAFRUIT_FONA_DEBUG
00450     printf("%s\r\n", replybuffer);
00451 #endif
00452     *readlen = thelen;
00453     return true;
00454 }
00455 
00456 // Retrieve the sender of the specified SMS message and copy it as a string to
00457 // the sender buffer.  Up to senderlen characters of the sender will be copied
00458 // and a null terminator will be added if less than senderlen charactesr are
00459 // copied to the result.  Returns true if a result was successfully retrieved,
00460 // otherwise false.
00461 bool Adafruit_FONA::getSMSSender(uint8_t i, char *sender, int senderlen) {
00462     // Ensure text mode and all text mode parameters are sent.
00463     if (! sendCheckReply("AT+CMGF=1", "OK")) return false;
00464     if (! sendCheckReply("AT+CSDH=1", "OK")) return false;
00465     // Send command to retrieve SMS message and parse a line of response.
00466     mySerial.printf("AT+CMGR=%d\r\n", i);
00467     readline(1000);
00468     // Parse the second field in the response.
00469     bool result = parseReplyQuoted("+CMGR:", sender, senderlen, ',', 1);
00470     // Drop any remaining data from the response.
00471     flushInput();
00472     return result;
00473 }
00474 
00475 bool Adafruit_FONA::sendSMS(char *smsaddr, char *smsmsg) {
00476     if (! sendCheckReply("AT+CMGF=1", "OK")) return -1;
00477     
00478     char sendcmd[30] = "AT+CMGS=\"";
00479     strncpy(sendcmd+9, smsaddr, 30-9-2);  // 9 bytes beginning, 2 bytes for close quote + null
00480     sendcmd[strlen(sendcmd)] = '\"';
00481     
00482     if (! sendCheckReply(sendcmd, "> ")) return false;
00483 #ifdef ADAFRUIT_FONA_DEBUG
00484     printf("> %s\r\n", smsmsg);
00485 #endif
00486     mySerial.printf("%s\r\n\r\n", smsmsg);
00487     mySerial.putc(0x1A);
00488 #ifdef ADAFRUIT_FONA_DEBUG
00489     printf("^Z\r\n");
00490 #endif
00491     readline(10000); // read the +CMGS reply, wait up to 10 seconds!!!
00492     //Serial.print("* "); Serial.println(replybuffer);
00493     if (strstr(replybuffer, "+CMGS") == 0) {
00494         return false;
00495     }
00496     readline(1000); // read OK
00497     //Serial.print("* "); Serial.println(replybuffer);
00498     
00499     if (strcmp(replybuffer, "OK") != 0) {
00500         return false;
00501     }
00502     
00503     return true;
00504 }
00505 
00506 
00507 bool Adafruit_FONA::deleteSMS(uint8_t i) {
00508     if (! sendCheckReply("AT+CMGF=1", "OK")) return -1;
00509     // read an sms
00510     char sendbuff[12] = "AT+CMGD=000";
00511     sendbuff[8] = (i / 100) + '0';
00512     i %= 100;
00513     sendbuff[9] = (i / 10) + '0';
00514     i %= 10;
00515     sendbuff[10] = i + '0';
00516     
00517     return sendCheckReply(sendbuff, "OK", 2000);
00518 }
00519 
00520 /********* TIME **********************************************************/
00521 
00522 bool Adafruit_FONA::enableNetworkTimeSync(bool onoff) {
00523     if (onoff) {
00524         if (! sendCheckReply("AT+CLTS=1", "OK"))
00525             return false;
00526     } else {
00527         if (! sendCheckReply("AT+CLTS=0", "OK"))
00528             return false;
00529     }
00530     
00531     flushInput(); // eat any 'Unsolicted Result Code'
00532     
00533     return true;
00534 }
00535 
00536 bool Adafruit_FONA::enableNTPTimeSync(bool onoff, const char* ntpserver) {
00537     if (onoff) {
00538         if (! sendCheckReply("AT+CNTPCID=1", "OK"))
00539             return false;
00540         
00541         mySerial.printf("AT+CNTP=\"");
00542         if (ntpserver != 0) {
00543             mySerial.printf(ntpserver);
00544         } else {
00545             mySerial.printf("pool.ntp.org");
00546         }
00547         mySerial.printf("\",0\r\n");
00548         readline(FONA_DEFAULT_TIMEOUT_MS);
00549         if (strcmp(replybuffer, "OK") != 0)
00550             return false;
00551         
00552         if (! sendCheckReply("AT+CNTP", "OK", 10000))
00553             return false;
00554         
00555         uint16_t status;
00556         readline(10000);
00557         if (! parseReply("+CNTP:", &status))
00558             return false;
00559     } else {
00560         if (! sendCheckReply("AT+CNTPCID=0", "OK"))
00561             return false;
00562     }
00563     
00564     return true;
00565 }
00566 
00567 bool Adafruit_FONA::getTime(char* buff, uint16_t maxlen) {
00568     getReply("AT+CCLK?", (uint16_t) 10000);
00569     if (strncmp(replybuffer, "+CCLK: ", 7) != 0)
00570         return false;
00571     
00572     char *p = replybuffer+7;
00573     uint16_t lentocopy = min((uint16_t)(maxlen-1), (uint16_t)strlen(p));
00574     strncpy(buff, p, lentocopy+1);
00575     buff[lentocopy] = 0;
00576     
00577     readline(); // eat OK
00578     
00579     return true;
00580 }
00581 
00582 /********* GPS **********************************************************/
00583 
00584 
00585 bool Adafruit_FONA::enableGPS(bool onoff) {
00586     uint16_t state;
00587     
00588     // first check if its already on or off
00589     if (! sendParseReply("AT+CGPSPWR?", "+CGPSPWR: ", &state) )
00590         return false;
00591     
00592     if (onoff && !state) {
00593         if (! sendCheckReply("AT+CGPSPWR=1", "OK"))
00594             return false;
00595     } else if (!onoff && state) {
00596         if (! sendCheckReply("AT+CGPSPWR=0", "OK"))
00597             return false;
00598     }
00599     return true;
00600 }
00601 
00602 int8_t Adafruit_FONA::GPSstatus(void) {
00603     getReply("AT+CGPSSTATUS?");
00604     
00605     char *p = strstr(replybuffer, "+CGPSSTATUS: Location ");
00606     if (p == 0) return -1;
00607     
00608     p+=22;
00609     
00610     readline(); // eat 'OK'
00611     
00612     
00613     if (p[0] == 'U') return 0;
00614     if (p[0] == 'N') return 1;
00615     if (p[0] == '2') return 2;
00616     if (p[0] == '3') return 3;
00617     
00618     // else
00619     return 0;
00620 }
00621 
00622 uint8_t Adafruit_FONA::getGPS(uint8_t arg, char *buffer, uint8_t maxbuff) {
00623     int32_t x = arg;
00624     
00625     getReply("AT+CGPSINF=", x);
00626     
00627     char *p = strstr(replybuffer, "CGPSINF: ");
00628     if (p == 0){
00629         buffer[0] = 0;
00630         return 0;
00631     }
00632     p+=9;
00633     uint8_t len = max((uint8_t)(maxbuff-1), (uint8_t)strlen(p));
00634     strncpy(buffer, p, len);
00635     buffer[len] = 0;
00636     
00637     readline(); // eat 'OK'
00638     return len;
00639 }
00640 
00641 bool Adafruit_FONA::getGPS(float *lat, float *lon, float *speed_kph, float *heading, float *altitude) {
00642     char gpsbuffer[120];
00643     
00644     // we need at least a 2D fix
00645     if (GPSstatus() < 2)
00646         return false;
00647     
00648     // grab the mode 2^5 gps csv from the sim808
00649     uint8_t res_len = getGPS(32, gpsbuffer, 120);
00650     
00651     // make sure we have a response
00652     if (res_len == 0)
00653         return false;
00654     
00655     // skip mode
00656     char *tok = strtok(gpsbuffer, ",");
00657     if (! tok) return false;
00658     
00659     // skip date
00660     tok = strtok(NULL, ",");
00661     if (! tok) return false;
00662     
00663     // skip fix
00664     tok = strtok(NULL, ",");
00665     if (! tok) return false;
00666     
00667     // grab the latitude
00668     char *latp = strtok(NULL, ",");
00669     if (! latp) return false;
00670     
00671     // grab latitude direction
00672     char *latdir = strtok(NULL, ",");
00673     if (! latdir) return false;
00674     
00675     // grab longitude
00676     char *longp = strtok(NULL, ",");
00677     if (! longp) return false;
00678     
00679     // grab longitude direction
00680     char *longdir = strtok(NULL, ",");
00681     if (! longdir) return false;
00682     
00683     double latitude = atof(latp);
00684     double longitude = atof(longp);
00685     
00686     // convert latitude from minutes to decimal
00687     float degrees = floor(latitude / 100);
00688     double minutes = latitude - (100 * degrees);
00689     minutes /= 60;
00690     degrees += minutes;
00691     
00692     // turn direction into + or -
00693     if (latdir[0] == 'S') degrees *= -1;
00694     
00695     *lat = degrees;
00696     
00697     // convert longitude from minutes to decimal
00698     degrees = floor(longitude / 100);
00699     minutes = longitude - (100 * degrees);
00700     minutes /= 60;
00701     degrees += minutes;
00702     
00703     // turn direction into + or -
00704     if (longdir[0] == 'W') degrees *= -1;
00705     
00706     *lon = degrees;
00707     
00708     // only grab speed if needed
00709     if (speed_kph != NULL) {
00710         
00711         // grab the speed in knots
00712         char *speedp = strtok(NULL, ",");
00713         if (! speedp) return false;
00714         
00715         // convert to kph
00716         *speed_kph = atof(speedp) * 1.852;
00717         
00718     }
00719     
00720     // only grab heading if needed
00721     if (heading != NULL) {
00722         
00723         // grab the speed in knots
00724         char *coursep = strtok(NULL, ",");
00725         if (! coursep) return false;
00726         
00727         *heading = atof(coursep);
00728     
00729     }
00730     
00731     // no need to continue
00732     if (altitude == NULL)
00733         return true;
00734     
00735     // we need at least a 3D fix for altitude
00736     if (GPSstatus() < 3)
00737         return false;
00738     
00739     // grab the mode 0 gps csv from the sim808
00740     res_len = getGPS(0, gpsbuffer, 120);
00741     
00742     // make sure we have a response
00743     if (res_len == 0)
00744         return false;
00745     
00746     // skip mode
00747     tok = strtok(gpsbuffer, ",");
00748     if (! tok) return false;
00749     
00750     // skip lat
00751     tok = strtok(NULL, ",");
00752     if (! tok) return false;
00753     
00754     // skip long
00755     tok = strtok(NULL, ",");
00756     if (! tok) return false;
00757     
00758     // grab altitude
00759     char *altp = strtok(NULL, ",");
00760     if (! altp) return false;
00761     
00762     *altitude = atof(altp);
00763     
00764     return true;
00765 }
00766 
00767 bool Adafruit_FONA::enableGPSNMEA(uint8_t i) {
00768     char sendbuff[15] = "AT+CGPSOUT=000";
00769     sendbuff[11] = (i / 100) + '0';
00770     i %= 100;
00771     sendbuff[12] = (i / 10) + '0';
00772     i %= 10;
00773     sendbuff[13] = i + '0';
00774     
00775     return sendCheckReply(sendbuff, "OK", 2000);
00776 }
00777 
00778 
00779 /********* GPRS **********************************************************/
00780 
00781 
00782 bool Adafruit_FONA::enableGPRS(bool onoff) {
00783     if (onoff) {
00784         // disconnect all sockets
00785         sendCheckReply("AT+CIPSHUT", "SHUT OK", 5000);
00786         
00787         if (! sendCheckReply("AT+CGATT=1", "OK", 10000))
00788             return false;
00789         
00790         // set bearer profile! connection type GPRS
00791         if (! sendCheckReply("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"", "OK", 10000))
00792             return false;
00793         
00794         // set bearer profile access point name
00795         if (apn) {
00796             // Send command AT+SAPBR=3,1,"APN","<apn value>" where <apn value> is the configured APN value.
00797             if (! sendCheckReplyQuoted("AT+SAPBR=3,1,\"APN\",", apn, "OK", 10000))
00798                 return false;
00799             
00800             // set username/password
00801             if (apnusername) {
00802                 // Send command AT+SAPBR=3,1,"USER","<user>" where <user> is the configured APN username.
00803                 if (! sendCheckReplyQuoted("AT+SAPBR=3,1,\"USER\",", apnusername, "OK", 10000))
00804                     return false;
00805             }
00806             if (apnpassword) {
00807                 // Send command AT+SAPBR=3,1,"PWD","<password>" where <password> is the configured APN password.
00808                 if (! sendCheckReplyQuoted("AT+SAPBR=3,1,\"PWD\",", apnpassword, "OK", 10000))
00809                     return false;
00810             }
00811         }
00812         
00813         // open GPRS context
00814         if (! sendCheckReply("AT+SAPBR=1,1", "OK", 10000))
00815             return false;
00816     } else {
00817         // disconnect all sockets
00818         if (! sendCheckReply("AT+CIPSHUT", "SHUT OK", 5000))
00819             return false;
00820         
00821         // close GPRS context
00822         if (! sendCheckReply("AT+SAPBR=0,1", "OK", 10000))
00823             return false;
00824         
00825         if (! sendCheckReply("AT+CGATT=0", "OK", 10000))
00826             return false;
00827     }
00828     return true;
00829 }
00830 
00831 uint8_t Adafruit_FONA::GPRSstate(void) {
00832     uint16_t state;
00833     
00834     if (! sendParseReply("AT+CGATT?", "+CGATT: ", &state) )
00835         return -1;
00836     
00837     return state;
00838 }
00839 
00840 void Adafruit_FONA::setGPRSNetworkSettings(const char* apn, const char* ausername, const char* apassword) {
00841     this->apn = (char*) apn;
00842     this->apnusername = (char*) ausername;
00843     this->apnpassword = (char*) apassword;
00844 }
00845 
00846 bool Adafruit_FONA::getGSMLoc(uint16_t *errorcode, char *buff, uint16_t maxlen) {
00847     getReply("AT+CIPGSMLOC=1,1", (uint16_t)10000);
00848     
00849     if (! parseReply("+CIPGSMLOC: ", errorcode))
00850         return false;
00851     
00852     char *p = replybuffer+14;
00853     uint16_t lentocopy = min((uint16_t)(maxlen-1), (uint16_t)strlen(p));
00854     strncpy(buff, p, lentocopy+1);
00855     
00856     readline(); // eat OK
00857     
00858     return true;
00859 }
00860 
00861 bool Adafruit_FONA::getGSMLoc(float *lat, float *lon) {
00862     uint16_t returncode;
00863     char gpsbuffer[120];
00864     
00865     // make sure we could get a response
00866     if (! getGSMLoc(&returncode, gpsbuffer, 120))
00867         return false;
00868     
00869     // make sure we have a valid return code
00870     if (returncode != 0)
00871         return false;
00872     
00873     // tokenize the gps buffer to locate the lat & long
00874     char *latp = strtok(gpsbuffer, ",");
00875     if (! latp) return false;
00876     
00877     char *longp = strtok(NULL, ",");
00878     if (! longp) return false;
00879     
00880     *lat = atof(latp);
00881     *lon = atof(longp);
00882     
00883     return true;
00884 }
00885 
00886 /********* TCP FUNCTIONS  ************************************/
00887 
00888 
00889 bool Adafruit_FONA::TCPconnect(char *server, uint16_t port) {
00890     flushInput();
00891     
00892     // close all old connections
00893     if (! sendCheckReply("AT+CIPSHUT", "SHUT OK", 5000) ) return false;
00894     
00895     // single connection at a time
00896     if (! sendCheckReply("AT+CIPMUX=0", "OK") ) return false;
00897     
00898     // manually read data
00899     if (! sendCheckReply("AT+CIPRXGET=1", "OK") ) return false;
00900     
00901 #ifdef ADAFRUIT_FONA_DEBUG
00902     printf("AT+CIPSTART=\"TCP\",\"%s\",\"%d\"\r\n", server, port);
00903 #endif
00904     
00905     mySerial.printf("AT+CIPSTART=\"TCP\",\"%s\",\"%d\"\r\n", server, port);
00906     
00907     if (! expectReply("OK")) return false;
00908     if (! expectReply("CONNECT OK")) return false;
00909     return true;
00910 }
00911 
00912 bool Adafruit_FONA::TCPclose(void) {
00913     return sendCheckReply("AT+CIPCLOSE", "OK");
00914 }
00915 
00916 bool Adafruit_FONA::TCPconnected(void) {
00917     if (! sendCheckReply("AT+CIPSTATUS", "OK", 100) ) return false;
00918     readline(100);
00919 #ifdef ADAFRUIT_FONA_DEBUG
00920     printf("\t<--- %s\r\n", replybuffer);
00921 #endif
00922     return (strcmp(replybuffer, "STATE: CONNECT OK") == 0);
00923 }
00924 
00925 bool Adafruit_FONA::TCPsend(char *packet, uint8_t len) {
00926 #ifdef ADAFRUIT_FONA_DEBUG
00927     printf("AT+CIPSEND=%d\r\n", len);
00928     
00929     for (uint16_t i=0; i<len; i++) {
00930         printf(" 0x%#02x", packet[i]);
00931     }
00932     printf("\r\n");
00933 #endif
00934     
00935     
00936     mySerial.printf("AT+CIPSEND=%d\r\n", len);
00937     readline();
00938 #ifdef ADAFRUIT_FONA_DEBUG
00939     printf("\t<--- %s\r\n", replybuffer);
00940 #endif
00941     if (replybuffer[0] != '>') return false;
00942     
00943     for (uint16_t i=0; i<len; i++) {
00944         mySerial.putc(packet[i]);
00945     }
00946     readline(3000); // wait up to 3 seconds to send the data
00947 #ifdef ADAFRUIT_FONA_DEBUG
00948     printf("\t<--- %s\r\n", replybuffer);
00949 #endif
00950     
00951     return (strcmp(replybuffer, "SEND OK") == 0);
00952 }
00953 
00954 uint16_t Adafruit_FONA::TCPavailable(void) {
00955     uint16_t avail;
00956     
00957     if (! sendParseReply("AT+CIPRXGET=4", "+CIPRXGET: 4,", &avail, ',', 0) ) return false;
00958     
00959 #ifdef ADAFRUIT_FONA_DEBUG
00960     printf("%d bytes available\r\n", avail);
00961 #endif
00962     
00963     return avail;
00964 }
00965 
00966 
00967 uint16_t Adafruit_FONA::TCPread(uint8_t *buff, uint8_t len) {
00968     uint16_t avail;
00969     
00970     mySerial.printf("AT+CIPRXGET=2,%d\r\n", len);
00971     readline();
00972     if (! parseReply("+CIPRXGET: 2,", &avail, ',', 0)) return false;
00973     
00974     readRaw(avail);
00975     
00976 #ifdef ADAFRUIT_FONA_DEBUG
00977     printf("%d bytes read\r\n", avail);
00978     for (uint8_t i=0;i<avail;i++) {
00979         printf(" 0x%#02x", replybuffer[i]);
00980     }
00981     printf("\r\n");
00982 #endif
00983     
00984     memcpy(buff, replybuffer, avail);
00985     
00986     return avail;
00987 }
00988 
00989 /********* HTTP LOW LEVEL FUNCTIONS  ************************************/
00990 
00991 bool Adafruit_FONA::HTTP_init() {
00992     return sendCheckReply("AT+HTTPINIT", "OK");
00993 }
00994 
00995 bool Adafruit_FONA::HTTP_term() {
00996     return sendCheckReply("AT+HTTPTERM", "OK");
00997 }
00998 
00999 void Adafruit_FONA::HTTP_para_start(const char* parameter, bool quoted) {
01000     flushInput();
01001     
01002 #ifdef ADAFRUIT_FONA_DEBUG
01003     printf("\t---> AT+HTTPPARA=\"%s\"\r\n", parameter);
01004 #endif
01005     
01006     mySerial.printf("AT+HTTPPARA=\"%s", parameter);
01007     if (quoted)
01008         mySerial.printf("\",\"");
01009     else
01010         mySerial.printf("\",");
01011 }
01012 
01013 bool Adafruit_FONA::HTTP_para_end(bool quoted) {
01014     if (quoted)
01015         mySerial.printf("\"\r\n");
01016     else
01017         mySerial.printf("\r\n");
01018     
01019     return expectReply("OK");
01020 }
01021 
01022 bool Adafruit_FONA::HTTP_para(const char* parameter, const char* value) {
01023     HTTP_para_start(parameter, true);
01024     mySerial.printf(value);
01025     return HTTP_para_end(true);
01026 }
01027 
01028 bool Adafruit_FONA::HTTP_para(const char* parameter, int32_t value) {
01029     HTTP_para_start(parameter, false);
01030     mySerial.printf("%d", value);
01031     return HTTP_para_end(false);
01032 }
01033 
01034 bool Adafruit_FONA::HTTP_data(uint32_t size, uint32_t maxTime) {
01035     flushInput();
01036     
01037 #ifdef ADAFRUIT_FONA_DEBUG
01038     printf("\t---> AT+HTTPDATA=%d,%d\r\n", size, maxTime);
01039 #endif
01040     
01041     mySerial.printf("AT+HTTPDATA=%d,%d\r\n", size, maxTime);
01042     
01043     return expectReply("DOWNLOAD");
01044 }
01045 
01046 bool Adafruit_FONA::HTTP_action(uint8_t method, uint16_t *status, uint16_t *datalen, int32_t timeout) {
01047     // Send request.
01048     if (! sendCheckReply("AT+HTTPACTION=", method, "OK"))
01049         return false;
01050     
01051     // Parse response status and size.
01052     readline(timeout);
01053     if (! parseReply("+HTTPACTION:", status, ',', 1))
01054         return false;
01055     if (! parseReply("+HTTPACTION:", datalen, ',', 2))
01056         return false;
01057     
01058     return true;
01059 }
01060 
01061 bool Adafruit_FONA::HTTP_readall(uint16_t *datalen) {
01062     getReply("AT+HTTPREAD");
01063     if (! parseReply("+HTTPREAD:", datalen, ',', 0))
01064         return false;
01065     
01066     return true;
01067 }
01068 
01069 bool Adafruit_FONA::HTTP_ssl(bool onoff) {
01070     return sendCheckReply("AT+HTTPSSL=", onoff ? 1 : 0, "OK");
01071 }
01072 
01073 /********* HTTP HIGH LEVEL FUNCTIONS ***************************/
01074 
01075 bool Adafruit_FONA::HTTP_GET_start(char *url, uint16_t *status, uint16_t *datalen){
01076     if (! HTTP_setup(url))
01077         return false;
01078     
01079     // HTTP GET
01080     if (! HTTP_action(FONA_HTTP_GET, status, datalen))
01081         return false;
01082     
01083 #ifdef ADAFRUIT_FONA_DEBUG
01084     printf("Status: %d\r\n", *status);
01085     printf("Len: %d\r\n", *datalen);
01086 #endif
01087     
01088     // HTTP response data
01089     if (! HTTP_readall(datalen))
01090         return false;
01091     
01092     return true;
01093 }
01094 
01095 void Adafruit_FONA::HTTP_GET_end(void) {
01096     HTTP_term();
01097 }
01098 
01099 bool Adafruit_FONA::HTTP_POST_start(char *url, const char* contenttype, const uint8_t *postdata, uint16_t postdatalen, uint16_t *status, uint16_t *datalen) {
01100     if (! HTTP_setup(url))
01101         return false;
01102     
01103     if (! HTTP_para("CONTENT", contenttype)) {
01104         return false;
01105     }
01106     
01107     // HTTP POST data
01108     if (! HTTP_data(postdatalen, 10000))
01109         return false;
01110     for (uint16_t i = 0; i < postdatalen; i++) {
01111         mySerial.putc(postdata[i]);
01112     }
01113     if (! expectReply("OK"))
01114         return false;
01115     
01116     // HTTP POST
01117     if (! HTTP_action(FONA_HTTP_POST, status, datalen))
01118         return false;
01119     
01120 #ifdef ADAFRUIT_FONA_DEBUG
01121     printf("Status: %d\r\n", *status);
01122     printf("Len: %d\r\n", *datalen);
01123 #endif
01124     
01125     // HTTP response data
01126     if (! HTTP_readall(datalen))
01127         return false;
01128     
01129     return true;
01130 }
01131 
01132 void Adafruit_FONA::HTTP_POST_end(void) {
01133     HTTP_term();
01134 }
01135 
01136 void Adafruit_FONA::setUserAgent(const char* useragent) {
01137     this->useragent = (char*) useragent;
01138 }
01139 
01140 void Adafruit_FONA::setHTTPSRedirect(bool onoff) {
01141     httpsredirect = onoff;
01142 }
01143 
01144 /********* HTTP HELPERS ****************************************/
01145 
01146 bool Adafruit_FONA::HTTP_setup(char *url) {
01147     // Handle any pending
01148     HTTP_term();
01149     
01150     // Initialize and set parameters
01151     if (! HTTP_init())
01152         return false;
01153     if (! HTTP_para("CID", 1))
01154         return false;
01155     if (! HTTP_para("UA", useragent))
01156         return false;
01157     if (! HTTP_para("URL", url))
01158         return false;
01159     
01160     // HTTPS redirect
01161     if (httpsredirect) {
01162         if (! HTTP_para("REDIR",1))
01163             return false;
01164         
01165         if (! HTTP_ssl(true))
01166             return false;
01167     }
01168     
01169     return true;
01170 }
01171 
01172 
01173 /********* HELPERS *********************************************/
01174 
01175 bool Adafruit_FONA::expectReply(const char* reply, uint16_t timeout) {
01176     readline(timeout);
01177 #ifdef ADAFRUIT_FONA_DEBUG
01178     printf("\t<--- %s\r\n", replybuffer);
01179 #endif
01180     return (strcmp(replybuffer, reply) == 0);
01181 }
01182 
01183 /********* LOW LEVEL *******************************************/
01184 
01185 void Adafruit_FONA::flushInput() {
01186     // Read all available serial input to flush pending data.
01187     uint16_t timeoutloop = 0;
01188     while (timeoutloop++ < 40) {
01189         while(readable()) {
01190             getc();
01191             timeoutloop = 0;  // If char was received reset the timer
01192         }
01193         wait_ms(1);
01194     }
01195 }
01196 
01197 uint16_t Adafruit_FONA::readRaw(uint16_t b) {
01198     uint16_t idx = 0;
01199     
01200     while (b && (idx < sizeof(replybuffer)-1)) {
01201         if (readable()) {
01202             replybuffer[idx] = getc();
01203             idx++;
01204             b--;
01205         }
01206     }
01207     replybuffer[idx] = 0;
01208     
01209     return idx;
01210 }
01211 
01212 // This function just reads the output from FONA after an AT command is sent to it
01213 uint8_t Adafruit_FONA::readline(uint16_t timeout, bool multiline) {
01214     uint16_t replyidx = 0;
01215     
01216     while (timeout--) {
01217         if (replyidx >= 254) {
01218             break;
01219         }
01220     
01221         while(readable()) {
01222             char c =  getc();
01223             if (c == '\r') continue;
01224             if (c == 0xA) {
01225                 if (replyidx == 0)   // the first 0x0A is ignored
01226                     continue;
01227                 
01228                 if (!multiline) {
01229                     timeout = 0;         // the second 0x0A is the end of the line
01230                     break;
01231                 }
01232             }
01233             replybuffer[replyidx] = c;
01234             replyidx++;
01235         }
01236     
01237         if (timeout == 0) {
01238             break;
01239         }
01240         wait_ms(1);
01241     }
01242     replybuffer[replyidx] = 0;  // null term
01243     return replyidx;
01244 }
01245 
01246 uint8_t Adafruit_FONA::getReply(const char* send, uint16_t timeout) {
01247     flushInput();
01248 
01249 #ifdef ADAFRUIT_FONA_DEBUG
01250     printf("\t---> %s\r\n", send);
01251 #endif
01252 
01253     mySerial.printf("%s\r\n",send);
01254 
01255     uint8_t l = readline(timeout);
01256 #ifdef ADAFRUIT_FONA_DEBUG
01257     printf("\t<--- %s\r\n", replybuffer);
01258 #endif
01259     return l;
01260 }
01261 
01262 // Send prefix, suffix, and newline. Return response (and also set replybuffer with response).
01263 uint8_t Adafruit_FONA::getReply(const char* prefix, char* suffix, uint16_t timeout) {
01264     flushInput();
01265     
01266 #ifdef ADAFRUIT_FONA_DEBUG
01267     printf("\t---> %s%s\r\n", prefix, suffix);
01268 #endif
01269     
01270     mySerial.printf("%s%s\r\n", prefix, suffix);
01271     
01272     uint8_t l = readline(timeout);
01273 #ifdef ADAFRUIT_FONA_DEBUG
01274     printf("\t<--- %s\r\n", replybuffer);
01275 #endif
01276     return l;
01277 }
01278 
01279 // Send prefix, suffix, and newline. Return response (and also set replybuffer with response).
01280 uint8_t Adafruit_FONA::getReply(const char* prefix, int32_t suffix, uint16_t timeout) {
01281     flushInput();
01282     
01283 #ifdef ADAFRUIT_FONA_DEBUG
01284     printf("\t---> %s%d\r\n", prefix, suffix);
01285 #endif
01286     
01287     mySerial.printf("%s%d\r\n", prefix, suffix);
01288     
01289     uint8_t l = readline(timeout);
01290 #ifdef ADAFRUIT_FONA_DEBUG
01291     printf("\t<--- %s\r\n", replybuffer);
01292 #endif
01293     return l;
01294 }
01295 
01296 // Send prefix, suffix, suffix2, and newline. Return response (and also set replybuffer with response).
01297 uint8_t Adafruit_FONA::getReply(const char* prefix, int32_t suffix1, int32_t suffix2, uint16_t timeout) {
01298     flushInput();
01299     
01300 #ifdef ADAFRUIT_FONA_DEBUG
01301     printf("\t---> %s%d,%d\r\n", prefix, suffix1, suffix2);
01302 #endif
01303     
01304     mySerial.printf("%s%d,%d\r\n", prefix, suffix1, suffix2);
01305     
01306     uint8_t l = readline(timeout);
01307 #ifdef ADAFRUIT_FONA_DEBUG
01308     printf("\t<--- %s\r\n", replybuffer);
01309 #endif
01310     return l;
01311 }
01312 
01313 // Send prefix, ", suffix, ", and newline. Return response (and also set replybuffer with response).
01314 uint8_t Adafruit_FONA::getReplyQuoted(const char* prefix, const char* suffix, uint16_t timeout) {
01315     flushInput();
01316     
01317 #ifdef ADAFRUIT_FONA_DEBUG
01318     printf("\t---> %s\"%s\"\r\n", prefix, suffix);
01319 #endif
01320     
01321     mySerial.printf("%s\"%s\"\r\n", prefix, suffix);
01322     
01323     uint8_t l = readline(timeout);
01324 #ifdef ADAFRUIT_FONA_DEBUG
01325     printf("\t<--- %s\r\n", replybuffer);
01326 #endif
01327     return l;
01328 }
01329 
01330 
01331 bool Adafruit_FONA::sendCheckReply(const char *send, const char *reply, uint16_t timeout) {
01332     getReply(send, timeout);
01333     
01334     return (strcmp(replybuffer, reply) == 0);
01335 }
01336 
01337 // Send prefix, suffix, and newline.  Verify FONA response matches reply parameter.
01338 bool Adafruit_FONA::sendCheckReply(const char* prefix, char *suffix, const char* reply, uint16_t timeout) {
01339     getReply(prefix, suffix, timeout);
01340     return (strcmp(replybuffer, reply) == 0);
01341 }
01342 
01343 // Send prefix, suffix, and newline.  Verify FONA response matches reply parameter.
01344 bool Adafruit_FONA::sendCheckReply(const char* prefix, int32_t suffix, const char* reply, uint16_t timeout) {
01345     getReply(prefix, suffix, timeout);
01346     return (strcmp(replybuffer, reply) == 0);
01347 }
01348 
01349 // Send prefix, suffix, suffix2, and newline.  Verify FONA response matches reply parameter.
01350 bool Adafruit_FONA::sendCheckReply(const char* prefix, int32_t suffix1, int32_t suffix2, const char* reply, uint16_t timeout) {
01351     getReply(prefix, suffix1, suffix2, timeout);
01352     return (strcmp(replybuffer, reply) == 0);
01353 }
01354 
01355 // Send prefix, ", suffix, ", and newline.  Verify FONA response matches reply parameter.
01356 bool Adafruit_FONA::sendCheckReplyQuoted(const char* prefix, const char* suffix, const char* reply, uint16_t timeout) {
01357   getReplyQuoted(prefix, suffix, timeout);
01358   return (strcmp(replybuffer, reply) == 0);
01359 }
01360 
01361 bool Adafruit_FONA::parseReply(const char* toreply, uint16_t *v, char divider, uint8_t index) {
01362     char *p = strstr(replybuffer, toreply);  // get the pointer to the voltage
01363     if (p == 0) return false;
01364     p += strlen(toreply);
01365     
01366     for (uint8_t i=0; i<index;i++) {
01367         // increment dividers
01368         p = strchr(p, divider);
01369         if (!p) return false;
01370         p++;
01371     }
01372     
01373     *v = atoi(p);
01374     
01375     return true;
01376 }
01377 
01378 bool Adafruit_FONA::parseReply(const char* toreply, char *v, char divider, uint8_t index) {
01379     uint8_t i=0;
01380     char *p = strstr(replybuffer, toreply);
01381     if (p == 0) return false;
01382     p+=strlen(toreply);
01383     
01384     for (i=0; i<index;i++) {
01385         // increment dividers
01386         p = strchr(p, divider);
01387         if (!p) return false;
01388         p++;
01389     }
01390     
01391     for(i=0; i<strlen(p);i++) {
01392         if(p[i] == divider)
01393             break;
01394         v[i] = p[i];
01395     }
01396     
01397     v[i] = '\0';
01398     
01399     return true;
01400 }
01401 
01402 // Parse a quoted string in the response fields and copy its value (without quotes)
01403 // to the specified character array (v).  Only up to maxlen characters are copied
01404 // into the result buffer, so make sure to pass a large enough buffer to handle the
01405 // response.
01406 bool Adafruit_FONA::parseReplyQuoted(const char* toreply, char* v, int maxlen, char divider, uint8_t index) {
01407     uint8_t i=0, j;
01408     // Verify response starts with toreply.
01409     char *p = strstr(replybuffer, toreply);
01410     if (p == 0) return false;
01411     p+=strlen(toreply);
01412     
01413     // Find location of desired response field.
01414     for (i=0; i<index;i++) {
01415         // increment dividers
01416         p = strchr(p, divider);
01417         if (!p) return false;
01418             p++;
01419     }
01420     
01421     // Copy characters from response field into result string.
01422     for(i=0, j=0; j<maxlen && i<strlen(p); ++i) {
01423         // Stop if a divier is found.
01424         if(p[i] == divider)
01425             break;
01426         // Skip any quotation marks.
01427         else if(p[i] == '"')
01428             continue;
01429         v[j++] = p[i];
01430     }
01431     
01432     // Add a null terminator if result string buffer was not filled.
01433     if (j < maxlen)
01434         v[j] = '\0';
01435     
01436     return true;
01437 }
01438 
01439 bool Adafruit_FONA::sendParseReply(const char* tosend, const char* toreply, uint16_t *v, char divider, uint8_t index) {
01440     getReply(tosend);
01441     
01442     if (! parseReply(toreply, v, divider, index)) return false;
01443     
01444     readline(); // eat 'OK'
01445     
01446     return true;
01447 }