Version using RawSerial instead of Serial (thread safe)
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