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