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