Library For the Adafruit FONA 808
Embed:
(wiki syntax)
Show/hide line numbers
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 // next line per http://postwarrior.com/arduino-ethershield-error-prog_char-does-not-name-a-type/ 00018 00019 #include "Adafruit_FONA.h" 00020 00021 00022 00023 00024 Adafruit_FONA::Adafruit_FONA(int8_t rst) 00025 { 00026 _rstpin = rst; 00027 00028 apn = F("FONAnet"); 00029 apnusername = 0; 00030 apnpassword = 0; 00031 mySerial = 0; 00032 httpsredirect = false; 00033 useragent = F("FONA"); 00034 ok_reply = F("OK"); 00035 } 00036 00037 uint8_t Adafruit_FONA::type(void) { 00038 return _type; 00039 } 00040 00041 boolean Adafruit_FONA::begin(Stream &port) { 00042 mySerial = &port; 00043 00044 pinMode(_rstpin, OUTPUT); 00045 digitalWrite(_rstpin, HIGH); 00046 delay(10); 00047 digitalWrite(_rstpin, LOW); 00048 delay(100); 00049 digitalWrite(_rstpin, HIGH); 00050 00051 DEBUG_PRINTLN(F("Attempting to open comm with ATs")); 00052 // give 7 seconds to reboot 00053 int16_t timeout = 7000; 00054 00055 while (timeout > 0) { 00056 while (mySerial->available()) mySerial->read(); 00057 if (sendCheckReply(F("AT"), ok_reply)) 00058 break; 00059 while (mySerial->available()) mySerial->read(); 00060 if (sendCheckReply(F("AT"), F("AT"))) 00061 break; 00062 delay(500); 00063 timeout-=500; 00064 } 00065 00066 if (timeout <= 0) { 00067 #ifdef ADAFRUIT_FONA_DEBUG 00068 DEBUG_PRINTLN(F("Timeout: No response to AT... last ditch attempt.")); 00069 #endif 00070 sendCheckReply(F("AT"), ok_reply); 00071 delay(100); 00072 sendCheckReply(F("AT"), ok_reply); 00073 delay(100); 00074 sendCheckReply(F("AT"), ok_reply); 00075 delay(100); 00076 } 00077 00078 // turn off Echo! 00079 sendCheckReply(F("ATE0"), ok_reply); 00080 delay(100); 00081 00082 if (! sendCheckReply(F("ATE0"), ok_reply)) { 00083 return false; 00084 } 00085 00086 // turn on hangupitude 00087 sendCheckReply(F("AT+CVHU=0"), ok_reply); 00088 00089 delay(100); 00090 flushInput(); 00091 00092 00093 DEBUG_PRINT(F("\t---> ")); DEBUG_PRINTLN("ATI"); 00094 00095 mySerial->println("ATI"); 00096 readline(500, true); 00097 00098 DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 00099 00100 00101 00102 if (prog_char_strstr(replybuffer, (prog_char *)F("SIM808 R14")) != 0) { 00103 _type = FONA808_V2; 00104 } else if (prog_char_strstr(replybuffer, (prog_char *)F("SIM808 R13")) != 0) { 00105 _type = FONA808_V1; 00106 } else if (prog_char_strstr(replybuffer, (prog_char *)F("SIM800 R13")) != 0) { 00107 _type = FONA800L; 00108 } else if (prog_char_strstr(replybuffer, (prog_char *)F("SIMCOM_SIM5320A")) != 0) { 00109 _type = FONA3G_A; 00110 } else if (prog_char_strstr(replybuffer, (prog_char *)F("SIMCOM_SIM5320E")) != 0) { 00111 _type = FONA3G_E; 00112 } 00113 00114 if (_type == FONA800L) { 00115 // determine if L or H 00116 00117 DEBUG_PRINT(F("\t---> ")); DEBUG_PRINTLN("AT+GMM"); 00118 00119 mySerial->println("AT+GMM"); 00120 readline(500, true); 00121 00122 DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 00123 00124 00125 if (prog_char_strstr(replybuffer, (prog_char *)F("SIM800H")) != 0) { 00126 _type = FONA800H; 00127 } 00128 } 00129 00130 #if defined(FONA_PREF_SMS_STORAGE) 00131 sendCheckReply(F("AT+CPMS=\"" FONA_PREF_SMS_STORAGE "\""), ok_reply); 00132 #endif 00133 00134 return true; 00135 } 00136 00137 00138 /********* Serial port ********************************************/ 00139 boolean Adafruit_FONA::setBaudrate(uint16_t baud) { 00140 return sendCheckReply(F("AT+IPREX="), baud, ok_reply); 00141 } 00142 00143 /********* Real Time Clock ********************************************/ 00144 00145 boolean Adafruit_FONA::readRTC(uint8_t *year, uint8_t *month, uint8_t *date, uint8_t *hr, uint8_t *min, uint8_t *sec) { 00146 uint16_t v; 00147 sendParseReply(F("AT+CCLK?"), F("+CCLK: "), &v, '/', 0); 00148 *year = v; 00149 00150 DEBUG_PRINTLN(*year); 00151 } 00152 00153 boolean Adafruit_FONA::enableRTC(uint8_t i) { 00154 if (! sendCheckReply(F("AT+CLTS="), i, ok_reply)) 00155 return false; 00156 return sendCheckReply(F("AT&W"), ok_reply); 00157 } 00158 00159 00160 /********* BATTERY & ADC ********************************************/ 00161 00162 /* returns value in mV (uint16_t) */ 00163 boolean Adafruit_FONA::getBattVoltage(uint16_t *v) { 00164 return sendParseReply(F("AT+CBC"), F("+CBC: "), v, ',', 2); 00165 } 00166 00167 /* returns value in mV (uint16_t) */ 00168 boolean Adafruit_FONA_3G::getBattVoltage(uint16_t *v) { 00169 float f; 00170 boolean b = sendParseReply(F("AT+CBC"), F("+CBC: "), &f, ',', 2); 00171 *v = f*1000; 00172 return b; 00173 } 00174 00175 00176 /* returns the percentage charge of battery as reported by sim800 */ 00177 boolean Adafruit_FONA::getBattPercent(uint16_t *p) { 00178 return sendParseReply(F("AT+CBC"), F("+CBC: "), p, ',', 1); 00179 } 00180 00181 boolean Adafruit_FONA::getADCVoltage(uint16_t *v) { 00182 return sendParseReply(F("AT+CADC?"), F("+CADC: 1,"), v); 00183 } 00184 00185 /********* SIM ***********************************************************/ 00186 00187 uint8_t Adafruit_FONA::unlockSIM(char *pin) 00188 { 00189 char sendbuff[14] = "AT+CPIN="; 00190 sendbuff[8] = pin[0]; 00191 sendbuff[9] = pin[1]; 00192 sendbuff[10] = pin[2]; 00193 sendbuff[11] = pin[3]; 00194 sendbuff[12] = '\0'; 00195 00196 return sendCheckReply(sendbuff, ok_reply); 00197 } 00198 00199 uint8_t Adafruit_FONA::getSIMCCID(char *ccid) { 00200 getReply(F("AT+CCID")); 00201 // up to 28 chars for reply, 20 char total ccid 00202 if (replybuffer[0] == '+') { 00203 // fona 3g? 00204 strncpy(ccid, replybuffer+8, 20); 00205 } else { 00206 // fona 800 or 800 00207 strncpy(ccid, replybuffer, 20); 00208 } 00209 ccid[20] = 0; 00210 00211 readline(); // eat 'OK' 00212 00213 return strlen(ccid); 00214 } 00215 00216 /********* IMEI **********************************************************/ 00217 00218 uint8_t Adafruit_FONA::getIMEI(char *imei) { 00219 getReply(F("AT+GSN")); 00220 00221 // up to 15 chars 00222 strncpy(imei, replybuffer, 15); 00223 imei[15] = 0; 00224 00225 readline(); // eat 'OK' 00226 00227 return strlen(imei); 00228 } 00229 00230 /********* NETWORK *******************************************************/ 00231 00232 uint8_t Adafruit_FONA::getNetworkStatus(void) { 00233 uint16_t status; 00234 00235 if (! sendParseReply(F("AT+CREG?"), F("+CREG: "), &status, ',', 1)) return 0; 00236 00237 return status; 00238 } 00239 00240 00241 uint8_t Adafruit_FONA::getRSSI(void) { 00242 uint16_t reply; 00243 00244 if (! sendParseReply(F("AT+CSQ"), F("+CSQ: "), &reply) ) return 0; 00245 00246 return reply; 00247 } 00248 00249 /********* AUDIO *******************************************************/ 00250 00251 boolean Adafruit_FONA::setAudio(uint8_t a) { 00252 // 0 is headset, 1 is external audio 00253 if (a > 1) return false; 00254 00255 return sendCheckReply(F("AT+CHFA="), a, ok_reply); 00256 } 00257 00258 uint8_t Adafruit_FONA::getVolume(void) { 00259 uint16_t reply; 00260 00261 if (! sendParseReply(F("AT+CLVL?"), F("+CLVL: "), &reply) ) return 0; 00262 00263 return reply; 00264 } 00265 00266 boolean Adafruit_FONA::setVolume(uint8_t i) { 00267 return sendCheckReply(F("AT+CLVL="), i, ok_reply); 00268 } 00269 00270 00271 boolean Adafruit_FONA::playDTMF(char dtmf) { 00272 char str[4]; 00273 str[0] = '\"'; 00274 str[1] = dtmf; 00275 str[2] = '\"'; 00276 str[3] = 0; 00277 return sendCheckReply(F("AT+CLDTMF=3,"), str, ok_reply); 00278 } 00279 00280 boolean Adafruit_FONA::playToolkitTone(uint8_t t, uint16_t len) { 00281 return sendCheckReply(F("AT+STTONE=1,"), t, len, ok_reply); 00282 } 00283 00284 boolean Adafruit_FONA_3G::playToolkitTone(uint8_t t, uint16_t len) { 00285 if (! sendCheckReply(F("AT+CPTONE="), t, ok_reply)) 00286 return false; 00287 delay(len); 00288 return sendCheckReply(F("AT+CPTONE=0"), ok_reply); 00289 } 00290 00291 boolean Adafruit_FONA::setMicVolume(uint8_t a, uint8_t level) { 00292 // 0 is headset, 1 is external audio 00293 if (a > 1) return false; 00294 00295 return sendCheckReply(F("AT+CMIC="), a, level, ok_reply); 00296 } 00297 00298 /********* FM RADIO *******************************************************/ 00299 00300 00301 boolean Adafruit_FONA::FMradio(boolean onoff, uint8_t a) { 00302 if (! onoff) { 00303 return sendCheckReply(F("AT+FMCLOSE"), ok_reply); 00304 } 00305 00306 // 0 is headset, 1 is external audio 00307 if (a > 1) return false; 00308 00309 return sendCheckReply(F("AT+FMOPEN="), a, ok_reply); 00310 } 00311 00312 boolean Adafruit_FONA::tuneFMradio(uint16_t station) { 00313 // Fail if FM station is outside allowed range. 00314 if ((station < 870) || (station > 1090)) 00315 return false; 00316 00317 return sendCheckReply(F("AT+FMFREQ="), station, ok_reply); 00318 } 00319 00320 boolean Adafruit_FONA::setFMVolume(uint8_t i) { 00321 // Fail if volume is outside allowed range (0-6). 00322 if (i > 6) { 00323 return false; 00324 } 00325 // Send FM volume command and verify response. 00326 return sendCheckReply(F("AT+FMVOLUME="), i, ok_reply); 00327 } 00328 00329 int8_t Adafruit_FONA::getFMVolume() { 00330 uint16_t level; 00331 00332 if (! sendParseReply(F("AT+FMVOLUME?"), F("+FMVOLUME: "), &level) ) return 0; 00333 00334 return level; 00335 } 00336 00337 int8_t Adafruit_FONA::getFMSignalLevel(uint16_t station) { 00338 // Fail if FM station is outside allowed range. 00339 if ((station < 875) || (station > 1080)) { 00340 return -1; 00341 } 00342 00343 // Send FM signal level query command. 00344 // Note, need to explicitly send timeout so right overload is chosen. 00345 getReply(F("AT+FMSIGNAL="), station, FONA_DEFAULT_TIMEOUT_MS); 00346 // Check response starts with expected value. 00347 char *p = prog_char_strstr(replybuffer, PSTR("+FMSIGNAL: ")); 00348 if (p == 0) return -1; 00349 p+=11; 00350 // Find second colon to get start of signal quality. 00351 p = strchr(p, ':'); 00352 if (p == 0) return -1; 00353 p+=1; 00354 // Parse signal quality. 00355 int8_t level = atoi(p); 00356 readline(); // eat the "OK" 00357 return level; 00358 } 00359 00360 /********* PWM/BUZZER **************************************************/ 00361 00362 boolean Adafruit_FONA::setPWM(uint16_t period, uint8_t duty) { 00363 if (period > 2000) return false; 00364 if (duty > 100) return false; 00365 00366 return sendCheckReply(F("AT+SPWM=0,"), period, duty, ok_reply); 00367 } 00368 00369 /********* CALL PHONES **************************************************/ 00370 boolean Adafruit_FONA::callPhone(char *number) { 00371 char sendbuff[35] = "ATD"; 00372 strncpy(sendbuff+3, number, min(30, strlen(number))); 00373 uint8_t x = strlen(sendbuff); 00374 sendbuff[x] = ';'; 00375 sendbuff[x+1] = 0; 00376 //DEBUG_PRINTLN(sendbuff); 00377 00378 return sendCheckReply(sendbuff, ok_reply); 00379 } 00380 00381 00382 uint8_t Adafruit_FONA::getCallStatus(void) { 00383 uint16_t phoneStatus; 00384 00385 if (! sendParseReply(F("AT+CPAS"), F("+CPAS: "), &phoneStatus)) 00386 return FONA_CALL_FAILED; // 1, since 0 is actually a known, good reply 00387 00388 return phoneStatus; // 0 ready, 2 unkown, 3 ringing, 4 call in progress 00389 } 00390 00391 boolean Adafruit_FONA::hangUp(void) { 00392 return sendCheckReply(F("ATH0"), ok_reply); 00393 } 00394 00395 boolean Adafruit_FONA_3G::hangUp(void) { 00396 getReply(F("ATH")); 00397 00398 return (prog_char_strstr(replybuffer, (prog_char *)F("VOICE CALL: END")) != 0); 00399 } 00400 00401 boolean Adafruit_FONA::pickUp(void) { 00402 return sendCheckReply(F("ATA"), ok_reply); 00403 } 00404 00405 boolean Adafruit_FONA_3G::pickUp(void) { 00406 return sendCheckReply(F("ATA"), F("VOICE CALL: BEGIN")); 00407 } 00408 00409 00410 void Adafruit_FONA::onIncomingCall() { 00411 00412 DEBUG_PRINT(F("> ")); DEBUG_PRINTLN(F("Incoming call...")); 00413 00414 Adafruit_FONA::_incomingCall = true; 00415 } 00416 00417 boolean Adafruit_FONA::_incomingCall = false; 00418 00419 boolean Adafruit_FONA::callerIdNotification(boolean enable, uint8_t interrupt) { 00420 if(enable){ 00421 attachInterrupt(interrupt, onIncomingCall, FALLING); 00422 return sendCheckReply(F("AT+CLIP=1"), ok_reply); 00423 } 00424 00425 detachInterrupt(interrupt); 00426 return sendCheckReply(F("AT+CLIP=0"), ok_reply); 00427 } 00428 00429 boolean Adafruit_FONA::incomingCallNumber(char* phonenum) { 00430 //+CLIP: "<incoming phone number>",145,"",0,"",0 00431 if(!Adafruit_FONA::_incomingCall) 00432 return false; 00433 00434 readline(); 00435 while(!prog_char_strcmp(replybuffer, (prog_char*)F("RING")) == 0) { 00436 flushInput(); 00437 readline(); 00438 } 00439 00440 readline(); //reads incoming phone number line 00441 00442 parseReply(F("+CLIP: \""), phonenum, '"'); 00443 00444 00445 DEBUG_PRINT(F("Phone Number: ")); 00446 DEBUG_PRINTLN(replybuffer); 00447 00448 00449 Adafruit_FONA::_incomingCall = false; 00450 return true; 00451 } 00452 00453 /********* SMS **********************************************************/ 00454 00455 uint8_t Adafruit_FONA::getSMSInterrupt(void) { 00456 uint16_t reply; 00457 00458 if (! sendParseReply(F("AT+CFGRI?"), F("+CFGRI: "), &reply) ) return 0; 00459 00460 return reply; 00461 } 00462 00463 boolean Adafruit_FONA::setSMSInterrupt(uint8_t i) { 00464 return sendCheckReply(F("AT+CFGRI="), i, ok_reply); 00465 } 00466 00467 int8_t Adafruit_FONA::getNumSMS(void) { 00468 uint16_t numsms; 00469 00470 // get into text mode 00471 if (! sendCheckReply(F("AT+CMGF=1"), ok_reply)) return -1; 00472 00473 // ask how many sms are stored 00474 if (sendParseReply(F("AT+CPMS?"), F("\"SM\","), &numsms)) 00475 return numsms; 00476 if (sendParseReply(F("AT+CPMS?"), F("\"SM_P\","), &numsms)) 00477 return numsms; 00478 return -1; 00479 } 00480 00481 // Reading SMS's is a bit involved so we don't use helpers that may cause delays or debug 00482 // printouts! 00483 boolean Adafruit_FONA::readSMS(uint8_t i, char *smsbuff, 00484 uint16_t maxlen, uint16_t *readlen) { 00485 // text mode 00486 if (! sendCheckReply(F("AT+CMGF=1"), ok_reply)) return false; 00487 00488 // show all text mode parameters 00489 if (! sendCheckReply(F("AT+CSDH=1"), ok_reply)) return false; 00490 00491 // parse out the SMS len 00492 uint16_t thesmslen = 0; 00493 00494 00495 DEBUG_PRINT(F("AT+CMGR=")); 00496 DEBUG_PRINTLN(i); 00497 00498 00499 //getReply(F("AT+CMGR="), i, 1000); // do not print debug! 00500 mySerial->print(F("AT+CMGR=")); 00501 mySerial->println(i); 00502 readline(1000); // timeout 00503 00504 //DEBUG_PRINT(F("Reply: ")); DEBUG_PRINTLN(replybuffer); 00505 // parse it out... 00506 00507 00508 DEBUG_PRINTLN(replybuffer); 00509 00510 00511 if (! parseReply(F("+CMGR:"), &thesmslen, ',', 11)) { 00512 *readlen = 0; 00513 return false; 00514 } 00515 00516 readRaw(thesmslen); 00517 00518 flushInput(); 00519 00520 uint16_t thelen = min(maxlen, strlen(replybuffer)); 00521 strncpy(smsbuff, replybuffer, thelen); 00522 smsbuff[thelen] = 0; // end the string 00523 00524 00525 DEBUG_PRINTLN(replybuffer); 00526 00527 *readlen = thelen; 00528 return true; 00529 } 00530 00531 // Retrieve the sender of the specified SMS message and copy it as a string to 00532 // the sender buffer. Up to senderlen characters of the sender will be copied 00533 // and a null terminator will be added if less than senderlen charactesr are 00534 // copied to the result. Returns true if a result was successfully retrieved, 00535 // otherwise false. 00536 boolean Adafruit_FONA::getSMSSender(uint8_t i, char *sender, int senderlen) { 00537 // Ensure text mode and all text mode parameters are sent. 00538 if (! sendCheckReply(F("AT+CMGF=1"), ok_reply)) return false; 00539 if (! sendCheckReply(F("AT+CSDH=1"), ok_reply)) return false; 00540 00541 00542 DEBUG_PRINT(F("AT+CMGR=")); 00543 DEBUG_PRINTLN(i); 00544 00545 00546 // Send command to retrieve SMS message and parse a line of response. 00547 mySerial->print(F("AT+CMGR=")); 00548 mySerial->println(i); 00549 readline(1000); 00550 00551 00552 DEBUG_PRINTLN(replybuffer); 00553 00554 00555 // Parse the second field in the response. 00556 boolean result = parseReplyQuoted(F("+CMGR:"), sender, senderlen, ',', 1); 00557 // Drop any remaining data from the response. 00558 flushInput(); 00559 return result; 00560 } 00561 00562 boolean Adafruit_FONA::sendSMS(char *smsaddr, char *smsmsg) { 00563 if (! sendCheckReply(F("AT+CMGF=1"), ok_reply)) return false; 00564 00565 char sendcmd[30] = "AT+CMGS=\""; 00566 strncpy(sendcmd+9, smsaddr, 30-9-2); // 9 bytes beginning, 2 bytes for close quote + null 00567 sendcmd[strlen(sendcmd)] = '\"'; 00568 00569 if (! sendCheckReply(sendcmd, F("> "))) return false; 00570 00571 DEBUG_PRINT(F("> ")); DEBUG_PRINTLN(smsmsg); 00572 00573 mySerial->println(smsmsg); 00574 mySerial->println(); 00575 mySerial->write(0x1A); 00576 00577 DEBUG_PRINTLN("^Z"); 00578 00579 if ( (_type == FONA3G_A) || (_type == FONA3G_E) ) { 00580 // Eat two sets of CRLF 00581 readline(200); 00582 //DEBUG_PRINT("Line 1: "); DEBUG_PRINTLN(strlen(replybuffer)); 00583 readline(200); 00584 //DEBUG_PRINT("Line 2: "); DEBUG_PRINTLN(strlen(replybuffer)); 00585 } 00586 readline(10000); // read the +CMGS reply, wait up to 10 seconds!!! 00587 //DEBUG_PRINT("Line 3: "); DEBUG_PRINTLN(strlen(replybuffer)); 00588 if (strstr(replybuffer, "+CMGS") == 0) { 00589 return false; 00590 } 00591 readline(1000); // read OK 00592 //DEBUG_PRINT("* "); DEBUG_PRINTLN(replybuffer); 00593 00594 if (strcmp(replybuffer, "OK") != 0) { 00595 return false; 00596 } 00597 00598 return true; 00599 } 00600 00601 00602 boolean Adafruit_FONA::deleteSMS(uint8_t i) { 00603 if (! sendCheckReply(F("AT+CMGF=1"), ok_reply)) return false; 00604 // read an sms 00605 char sendbuff[12] = "AT+CMGD=000"; 00606 sendbuff[8] = (i / 100) + '0'; 00607 i %= 100; 00608 sendbuff[9] = (i / 10) + '0'; 00609 i %= 10; 00610 sendbuff[10] = i + '0'; 00611 00612 return sendCheckReply(sendbuff, ok_reply, 2000); 00613 } 00614 00615 /********* USSD *********************************************************/ 00616 00617 boolean Adafruit_FONA::sendUSSD(char *ussdmsg, char *ussdbuff, uint16_t maxlen, uint16_t *readlen) { 00618 if (! sendCheckReply(F("AT+CUSD=1"), ok_reply)) return false; 00619 00620 char sendcmd[30] = "AT+CUSD=1,\""; 00621 strncpy(sendcmd+11, ussdmsg, 30-11-2); // 11 bytes beginning, 2 bytes for close quote + null 00622 sendcmd[strlen(sendcmd)] = '\"'; 00623 00624 if (! sendCheckReply(sendcmd, ok_reply)) { 00625 *readlen = 0; 00626 return false; 00627 } else { 00628 readline(10000); // read the +CUSD reply, wait up to 10 seconds!!! 00629 //DEBUG_PRINT("* "); DEBUG_PRINTLN(replybuffer); 00630 char *p = prog_char_strstr(replybuffer, PSTR("+CUSD: ")); 00631 if (p == 0) { 00632 *readlen = 0; 00633 return false; 00634 } 00635 p+=7; //+CUSD 00636 // Find " to get start of ussd message. 00637 p = strchr(p, '\"'); 00638 if (p == 0) { 00639 *readlen = 0; 00640 return false; 00641 } 00642 p+=1; //" 00643 // Find " to get end of ussd message. 00644 char *strend = strchr(p, '\"'); 00645 00646 uint16_t lentocopy = min(maxlen-1, strend - p); 00647 strncpy(ussdbuff, p, lentocopy+1); 00648 ussdbuff[lentocopy] = 0; 00649 *readlen = lentocopy; 00650 } 00651 return true; 00652 } 00653 00654 00655 /********* TIME **********************************************************/ 00656 00657 boolean Adafruit_FONA::enableNetworkTimeSync(boolean onoff) { 00658 if (onoff) { 00659 if (! sendCheckReply(F("AT+CLTS=1"), ok_reply)) 00660 return false; 00661 } else { 00662 if (! sendCheckReply(F("AT+CLTS=0"), ok_reply)) 00663 return false; 00664 } 00665 00666 flushInput(); // eat any 'Unsolicted Result Code' 00667 00668 return true; 00669 } 00670 00671 boolean Adafruit_FONA::enableNTPTimeSync(boolean onoff, FONAFlashStringPtr ntpserver) { 00672 if (onoff) { 00673 if (! sendCheckReply(F("AT+CNTPCID=1"), ok_reply)) 00674 return false; 00675 00676 mySerial->print(F("AT+CNTP=\"")); 00677 if (ntpserver != 0) { 00678 mySerial->print(ntpserver); 00679 } else { 00680 mySerial->print(F("pool.ntp.org")); 00681 } 00682 mySerial->println(F("\",0")); 00683 readline(FONA_DEFAULT_TIMEOUT_MS); 00684 if (strcmp(replybuffer, "OK") != 0) 00685 return false; 00686 00687 if (! sendCheckReply(F("AT+CNTP"), ok_reply, 10000)) 00688 return false; 00689 00690 uint16_t status; 00691 readline(10000); 00692 if (! parseReply(F("+CNTP:"), &status)) 00693 return false; 00694 } else { 00695 if (! sendCheckReply(F("AT+CNTPCID=0"), ok_reply)) 00696 return false; 00697 } 00698 00699 return true; 00700 } 00701 00702 boolean Adafruit_FONA::getTime(char *buff, uint16_t maxlen) { 00703 getReply(F("AT+CCLK?"), (uint16_t) 10000); 00704 if (strncmp(replybuffer, "+CCLK: ", 7) != 0) 00705 return false; 00706 00707 char *p = replybuffer+7; 00708 uint16_t lentocopy = min(maxlen-1, strlen(p)); 00709 strncpy(buff, p, lentocopy+1); 00710 buff[lentocopy] = 0; 00711 00712 readline(); // eat OK 00713 00714 return true; 00715 } 00716 00717 /********* GPS **********************************************************/ 00718 00719 00720 boolean Adafruit_FONA::enableGPS(boolean onoff) { 00721 uint16_t state; 00722 00723 // first check if its already on or off 00724 00725 if (_type == FONA808_V2) { 00726 if (! sendParseReply(F("AT+CGNSPWR?"), F("+CGNSPWR: "), &state) ) 00727 return false; 00728 } else { 00729 if (! sendParseReply(F("AT+CGPSPWR?"), F("+CGPSPWR: "), &state)) 00730 return false; 00731 } 00732 00733 if (onoff && !state) { 00734 if (_type == FONA808_V2) { 00735 if (! sendCheckReply(F("AT+CGNSPWR=1"), ok_reply)) // try GNS command 00736 return false; 00737 } else { 00738 if (! sendCheckReply(F("AT+CGPSPWR=1"), ok_reply)) 00739 return false; 00740 } 00741 } else if (!onoff && state) { 00742 if (_type == FONA808_V2) { 00743 if (! sendCheckReply(F("AT+CGNSPWR=0"), ok_reply)) // try GNS command 00744 return false; 00745 } else { 00746 if (! sendCheckReply(F("AT+CGPSPWR=0"), ok_reply)) 00747 return false; 00748 } 00749 } 00750 return true; 00751 } 00752 00753 00754 00755 boolean Adafruit_FONA_3G::enableGPS(boolean onoff) { 00756 uint16_t state; 00757 00758 // first check if its already on or off 00759 if (! Adafruit_FONA::sendParseReply(F("AT+CGPS?"), F("+CGPS: "), &state) ) 00760 return false; 00761 00762 if (onoff && !state) { 00763 if (! sendCheckReply(F("AT+CGPS=1"), ok_reply)) 00764 return false; 00765 } else if (!onoff && state) { 00766 if (! sendCheckReply(F("AT+CGPS=0"), ok_reply)) 00767 return false; 00768 // this takes a little time 00769 readline(2000); // eat '+CGPS: 0' 00770 } 00771 return true; 00772 } 00773 00774 int8_t Adafruit_FONA::GPSstatus(void) { 00775 if (_type == FONA808_V2) { 00776 // 808 V2 uses GNS commands and doesn't have an explicit 2D/3D fix status. 00777 // Instead just look for a fix and if found assume it's a 3D fix. 00778 getReply(F("AT+CGNSINF")); 00779 char *p = prog_char_strstr(replybuffer, (prog_char*)F("+CGNSINF: ")); 00780 if (p == 0) return -1; 00781 p+=10; 00782 readline(); // eat 'OK' 00783 if (p[0] == '0') return 0; // GPS is not even on! 00784 00785 p+=2; // Skip to second value, fix status. 00786 //DEBUG_PRINTLN(p); 00787 // Assume if the fix status is '1' then we have a 3D fix, otherwise no fix. 00788 if (p[0] == '1') return 3; 00789 else return 1; 00790 } 00791 if (_type == FONA3G_A || _type == FONA3G_E) { 00792 // FONA 3G doesn't have an explicit 2D/3D fix status. 00793 // Instead just look for a fix and if found assume it's a 3D fix. 00794 getReply(F("AT+CGPSINFO")); 00795 char *p = prog_char_strstr(replybuffer, (prog_char*)F("+CGPSINFO:")); 00796 if (p == 0) return -1; 00797 if (p[10] != ',') return 3; // if you get anything, its 3D fix 00798 return 0; 00799 } 00800 else { 00801 // 808 V1 looks for specific 2D or 3D fix state. 00802 getReply(F("AT+CGPSSTATUS?")); 00803 char *p = prog_char_strstr(replybuffer, (prog_char*)F("SSTATUS: Location ")); 00804 if (p == 0) return -1; 00805 p+=18; 00806 readline(); // eat 'OK' 00807 //DEBUG_PRINTLN(p); 00808 if (p[0] == 'U') return 0; 00809 if (p[0] == 'N') return 1; 00810 if (p[0] == '2') return 2; 00811 if (p[0] == '3') return 3; 00812 } 00813 // else 00814 return 0; 00815 } 00816 00817 uint8_t Adafruit_FONA::getGPS(uint8_t arg, char *buffer, uint8_t maxbuff) { 00818 int32_t x = arg; 00819 00820 if ( (_type == FONA3G_A) || (_type == FONA3G_E) ) { 00821 getReply(F("AT+CGPSINFO")); 00822 } else if (_type == FONA808_V1) { 00823 getReply(F("AT+CGPSINF="), x); 00824 } else { 00825 getReply(F("AT+CGNSINF")); 00826 } 00827 00828 char *p = prog_char_strstr(replybuffer, (prog_char*)F("SINF")); 00829 if (p == 0) { 00830 buffer[0] = 0; 00831 return 0; 00832 } 00833 00834 p+=6; 00835 00836 uint8_t len = max(maxbuff-1, strlen(p)); 00837 strncpy(buffer, p, len); 00838 buffer[len] = 0; 00839 00840 readline(); // eat 'OK' 00841 return len; 00842 } 00843 00844 boolean Adafruit_FONA::getGPS(float *lat, float *lon, float *speed_kph, float *heading, float *altitude) { 00845 00846 char gpsbuffer[120]; 00847 00848 // we need at least a 2D fix 00849 if (GPSstatus() < 2) 00850 return false; 00851 00852 // grab the mode 2^5 gps csv from the sim808 00853 uint8_t res_len = getGPS(32, gpsbuffer, 120); 00854 00855 // make sure we have a response 00856 if (res_len == 0) 00857 return false; 00858 00859 if (_type == FONA3G_A || _type == FONA3G_E) { 00860 // Parse 3G respose 00861 // +CGPSINFO:4043.000000,N,07400.000000,W,151015,203802.1,-12.0,0.0,0 00862 // skip beginning 00863 char *tok; 00864 00865 // grab the latitude 00866 char *latp = strtok(gpsbuffer, ","); 00867 if (! latp) return false; 00868 00869 // grab latitude direction 00870 char *latdir = strtok(NULL, ","); 00871 if (! latdir) return false; 00872 00873 // grab longitude 00874 char *longp = strtok(NULL, ","); 00875 if (! longp) return false; 00876 00877 // grab longitude direction 00878 char *longdir = strtok(NULL, ","); 00879 if (! longdir) return false; 00880 00881 // skip date & time 00882 tok = strtok(NULL, ","); 00883 tok = strtok(NULL, ","); 00884 00885 // only grab altitude if needed 00886 if (altitude != NULL) { 00887 // grab altitude 00888 char *altp = strtok(NULL, ","); 00889 if (! altp) return false; 00890 *altitude = atof(altp); 00891 } 00892 00893 // only grab speed if needed 00894 if (speed_kph != NULL) { 00895 // grab the speed in km/h 00896 char *speedp = strtok(NULL, ","); 00897 if (! speedp) return false; 00898 00899 *speed_kph = atof(speedp); 00900 } 00901 00902 // only grab heading if needed 00903 if (heading != NULL) { 00904 00905 // grab the speed in knots 00906 char *coursep = strtok(NULL, ","); 00907 if (! coursep) return false; 00908 00909 *heading = atof(coursep); 00910 } 00911 00912 double latitude = atof(latp); 00913 double longitude = atof(longp); 00914 00915 // convert latitude from minutes to decimal 00916 float degrees = floor(latitude / 100); 00917 double minutes = latitude - (100 * degrees); 00918 minutes /= 60; 00919 degrees += minutes; 00920 00921 // turn direction into + or - 00922 if (latdir[0] == 'S') degrees *= -1; 00923 00924 *lat = degrees; 00925 00926 // convert longitude from minutes to decimal 00927 degrees = floor(longitude / 100); 00928 minutes = longitude - (100 * degrees); 00929 minutes /= 60; 00930 degrees += minutes; 00931 00932 // turn direction into + or - 00933 if (longdir[0] == 'W') degrees *= -1; 00934 00935 *lon = degrees; 00936 00937 } else if (_type == FONA808_V2) { 00938 // Parse 808 V2 response. See table 2-3 from here for format: 00939 // http://www.adafruit.com/datasheets/SIM800%20Series_GNSS_Application%20Note%20V1.00.pdf 00940 00941 // skip GPS run status 00942 char *tok = strtok(gpsbuffer, ","); 00943 if (! tok) return false; 00944 00945 // skip fix status 00946 tok = strtok(NULL, ","); 00947 if (! tok) return false; 00948 00949 // skip date 00950 tok = strtok(NULL, ","); 00951 if (! tok) return false; 00952 00953 // grab the latitude 00954 char *latp = strtok(NULL, ","); 00955 if (! latp) return false; 00956 00957 // grab longitude 00958 char *longp = strtok(NULL, ","); 00959 if (! longp) return false; 00960 00961 *lat = atof(latp); 00962 *lon = atof(longp); 00963 00964 // only grab altitude if needed 00965 if (altitude != NULL) { 00966 // grab altitude 00967 char *altp = strtok(NULL, ","); 00968 if (! altp) return false; 00969 00970 *altitude = atof(altp); 00971 } 00972 00973 // only grab speed if needed 00974 if (speed_kph != NULL) { 00975 // grab the speed in km/h 00976 char *speedp = strtok(NULL, ","); 00977 if (! speedp) return false; 00978 00979 *speed_kph = atof(speedp); 00980 } 00981 00982 // only grab heading if needed 00983 if (heading != NULL) { 00984 00985 // grab the speed in knots 00986 char *coursep = strtok(NULL, ","); 00987 if (! coursep) return false; 00988 00989 *heading = atof(coursep); 00990 } 00991 } 00992 else { 00993 // Parse 808 V1 response. 00994 00995 // skip mode 00996 char *tok = strtok(gpsbuffer, ","); 00997 if (! tok) return false; 00998 00999 // skip date 01000 tok = strtok(NULL, ","); 01001 if (! tok) return false; 01002 01003 // skip fix 01004 tok = strtok(NULL, ","); 01005 if (! tok) return false; 01006 01007 // grab the latitude 01008 char *latp = strtok(NULL, ","); 01009 if (! latp) return false; 01010 01011 // grab latitude direction 01012 char *latdir = strtok(NULL, ","); 01013 if (! latdir) return false; 01014 01015 // grab longitude 01016 char *longp = strtok(NULL, ","); 01017 if (! longp) return false; 01018 01019 // grab longitude direction 01020 char *longdir = strtok(NULL, ","); 01021 if (! longdir) return false; 01022 01023 double latitude = atof(latp); 01024 double longitude = atof(longp); 01025 01026 // convert latitude from minutes to decimal 01027 float degrees = floor(latitude / 100); 01028 double minutes = latitude - (100 * degrees); 01029 minutes /= 60; 01030 degrees += minutes; 01031 01032 // turn direction into + or - 01033 if (latdir[0] == 'S') degrees *= -1; 01034 01035 *lat = degrees; 01036 01037 // convert longitude from minutes to decimal 01038 degrees = floor(longitude / 100); 01039 minutes = longitude - (100 * degrees); 01040 minutes /= 60; 01041 degrees += minutes; 01042 01043 // turn direction into + or - 01044 if (longdir[0] == 'W') degrees *= -1; 01045 01046 *lon = degrees; 01047 01048 // only grab speed if needed 01049 if (speed_kph != NULL) { 01050 01051 // grab the speed in knots 01052 char *speedp = strtok(NULL, ","); 01053 if (! speedp) return false; 01054 01055 // convert to kph 01056 *speed_kph = atof(speedp) * 1.852; 01057 01058 } 01059 01060 // only grab heading if needed 01061 if (heading != NULL) { 01062 01063 // grab the speed in knots 01064 char *coursep = strtok(NULL, ","); 01065 if (! coursep) return false; 01066 01067 *heading = atof(coursep); 01068 01069 } 01070 01071 // no need to continue 01072 if (altitude == NULL) 01073 return true; 01074 01075 // we need at least a 3D fix for altitude 01076 if (GPSstatus() < 3) 01077 return false; 01078 01079 // grab the mode 0 gps csv from the sim808 01080 res_len = getGPS(0, gpsbuffer, 120); 01081 01082 // make sure we have a response 01083 if (res_len == 0) 01084 return false; 01085 01086 // skip mode 01087 tok = strtok(gpsbuffer, ","); 01088 if (! tok) return false; 01089 01090 // skip lat 01091 tok = strtok(NULL, ","); 01092 if (! tok) return false; 01093 01094 // skip long 01095 tok = strtok(NULL, ","); 01096 if (! tok) return false; 01097 01098 // grab altitude 01099 char *altp = strtok(NULL, ","); 01100 if (! altp) return false; 01101 01102 *altitude = atof(altp); 01103 } 01104 01105 return true; 01106 01107 } 01108 01109 boolean Adafruit_FONA::enableGPSNMEA(uint8_t i) { 01110 01111 char sendbuff[15] = "AT+CGPSOUT=000"; 01112 sendbuff[11] = (i / 100) + '0'; 01113 i %= 100; 01114 sendbuff[12] = (i / 10) + '0'; 01115 i %= 10; 01116 sendbuff[13] = i + '0'; 01117 01118 if (_type == FONA808_V2) { 01119 if (i) 01120 return sendCheckReply(F("AT+CGNSTST=1"), ok_reply); 01121 else 01122 return sendCheckReply(F("AT+CGNSTST=0"), ok_reply); 01123 } else { 01124 return sendCheckReply(sendbuff, ok_reply, 2000); 01125 } 01126 } 01127 01128 01129 /********* GPRS **********************************************************/ 01130 01131 01132 boolean Adafruit_FONA::enableGPRS(boolean onoff) { 01133 01134 if (onoff) { 01135 // disconnect all sockets 01136 sendCheckReply(F("AT+CIPSHUT"), F("SHUT OK"), 20000); 01137 01138 if (! sendCheckReply(F("AT+CGATT=1"), ok_reply, 10000)) 01139 return false; 01140 01141 // set bearer profile! connection type GPRS 01142 if (! sendCheckReply(F("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\""), 01143 ok_reply, 10000)) 01144 return false; 01145 01146 // set bearer profile access point name 01147 if (apn) { 01148 // Send command AT+SAPBR=3,1,"APN","<apn value>" where <apn value> is the configured APN value. 01149 if (! sendCheckReplyQuoted(F("AT+SAPBR=3,1,\"APN\","), apn, ok_reply, 10000)) 01150 return false; 01151 01152 // send AT+CSTT,"apn","user","pass" 01153 flushInput(); 01154 01155 mySerial->print(F("AT+CSTT=\"")); 01156 mySerial->print(apn); 01157 if (apnusername) { 01158 mySerial->print("\",\""); 01159 mySerial->print(apnusername); 01160 } 01161 if (apnpassword) { 01162 mySerial->print("\",\""); 01163 mySerial->print(apnpassword); 01164 } 01165 mySerial->println("\""); 01166 01167 DEBUG_PRINT(F("\t---> ")); DEBUG_PRINT(F("AT+CSTT=\"")); 01168 DEBUG_PRINT(apn); 01169 01170 if (apnusername) { 01171 DEBUG_PRINT("\",\""); 01172 DEBUG_PRINT(apnusername); 01173 } 01174 if (apnpassword) { 01175 DEBUG_PRINT("\",\""); 01176 DEBUG_PRINT(apnpassword); 01177 } 01178 DEBUG_PRINTLN("\""); 01179 01180 if (! expectReply(ok_reply)) return false; 01181 01182 // set username/password 01183 if (apnusername) { 01184 // Send command AT+SAPBR=3,1,"USER","<user>" where <user> is the configured APN username. 01185 if (! sendCheckReplyQuoted(F("AT+SAPBR=3,1,\"USER\","), apnusername, ok_reply, 10000)) 01186 return false; 01187 } 01188 if (apnpassword) { 01189 // Send command AT+SAPBR=3,1,"PWD","<password>" where <password> is the configured APN password. 01190 if (! sendCheckReplyQuoted(F("AT+SAPBR=3,1,\"PWD\","), apnpassword, ok_reply, 10000)) 01191 return false; 01192 } 01193 } 01194 01195 // open GPRS context 01196 if (! sendCheckReply(F("AT+SAPBR=1,1"), ok_reply, 30000)) 01197 return false; 01198 01199 // bring up wireless connection 01200 if (! sendCheckReply(F("AT+CIICR"), ok_reply, 10000)) 01201 return false; 01202 01203 } else { 01204 // disconnect all sockets 01205 if (! sendCheckReply(F("AT+CIPSHUT"), F("SHUT OK"), 20000)) 01206 return false; 01207 01208 // close GPRS context 01209 if (! sendCheckReply(F("AT+SAPBR=0,1"), ok_reply, 10000)) 01210 return false; 01211 01212 if (! sendCheckReply(F("AT+CGATT=0"), ok_reply, 10000)) 01213 return false; 01214 01215 } 01216 return true; 01217 } 01218 01219 boolean Adafruit_FONA_3G::enableGPRS(boolean onoff) { 01220 01221 if (onoff) { 01222 // disconnect all sockets 01223 //sendCheckReply(F("AT+CIPSHUT"), F("SHUT OK"), 5000); 01224 01225 if (! sendCheckReply(F("AT+CGATT=1"), ok_reply, 10000)) 01226 return false; 01227 01228 01229 // set bearer profile access point name 01230 if (apn) { 01231 // Send command AT+CGSOCKCONT=1,"IP","<apn value>" where <apn value> is the configured APN name. 01232 if (! sendCheckReplyQuoted(F("AT+CGSOCKCONT=1,\"IP\","), apn, ok_reply, 10000)) 01233 return false; 01234 01235 // set username/password 01236 if (apnusername) { 01237 char authstring[100] = "AT+CGAUTH=1,1,\""; 01238 char *strp = authstring + strlen(authstring); 01239 prog_char_strcpy(strp, (prog_char *)apnusername); 01240 strp+=prog_char_strlen((prog_char *)apnusername); 01241 strp[0] = '\"'; 01242 strp++; 01243 strp[0] = 0; 01244 01245 if (apnpassword) { 01246 strp[0] = ','; strp++; 01247 strp[0] = '\"'; strp++; 01248 prog_char_strcpy(strp, (prog_char *)apnpassword); 01249 strp+=prog_char_strlen((prog_char *)apnpassword); 01250 strp[0] = '\"'; 01251 strp++; 01252 strp[0] = 0; 01253 } 01254 01255 if (! sendCheckReply(authstring, ok_reply, 10000)) 01256 return false; 01257 } 01258 } 01259 01260 // connect in transparent 01261 if (! sendCheckReply(F("AT+CIPMODE=1"), ok_reply, 10000)) 01262 return false; 01263 // open network (?) 01264 if (! sendCheckReply(F("AT+NETOPEN=,,1"), F("Network opened"), 10000)) 01265 return false; 01266 01267 readline(); // eat 'OK' 01268 } else { 01269 // close GPRS context 01270 if (! sendCheckReply(F("AT+NETCLOSE"), F("Network closed"), 10000)) 01271 return false; 01272 01273 readline(); // eat 'OK' 01274 } 01275 01276 return true; 01277 } 01278 01279 uint8_t Adafruit_FONA::GPRSstate(void) { 01280 uint16_t state; 01281 01282 if (! sendParseReply(F("AT+CGATT?"), F("+CGATT: "), &state) ) 01283 return -1; 01284 01285 return state; 01286 } 01287 01288 void Adafruit_FONA::setGPRSNetworkSettings(FONAFlashStringPtr apn, 01289 FONAFlashStringPtr username, FONAFlashStringPtr password) { 01290 this->apn = apn; 01291 this->apnusername = username; 01292 this->apnpassword = password; 01293 } 01294 01295 boolean Adafruit_FONA::getGSMLoc(uint16_t *errorcode, char *buff, uint16_t maxlen) { 01296 01297 getReply(F("AT+CIPGSMLOC=1,1"), (uint16_t)10000); 01298 01299 if (! parseReply(F("+CIPGSMLOC: "), errorcode)) 01300 return false; 01301 01302 char *p = replybuffer+14; 01303 uint16_t lentocopy = min(maxlen-1, strlen(p)); 01304 strncpy(buff, p, lentocopy+1); 01305 01306 readline(); // eat OK 01307 01308 return true; 01309 } 01310 01311 boolean Adafruit_FONA::getGSMLoc(float *lat, float *lon) { 01312 01313 uint16_t returncode; 01314 char gpsbuffer[120]; 01315 01316 // make sure we could get a response 01317 if (! getGSMLoc(&returncode, gpsbuffer, 120)) 01318 return false; 01319 01320 // make sure we have a valid return code 01321 if (returncode != 0) 01322 return false; 01323 01324 // +CIPGSMLOC: 0,-74.007729,40.730160,2015/10/15,19:24:55 01325 // tokenize the gps buffer to locate the lat & long 01326 char *longp = strtok(gpsbuffer, ","); 01327 if (! longp) return false; 01328 01329 char *latp = strtok(NULL, ","); 01330 if (! latp) return false; 01331 01332 *lat = atof(latp); 01333 *lon = atof(longp); 01334 01335 return true; 01336 01337 } 01338 /********* TCP FUNCTIONS ************************************/ 01339 01340 01341 boolean Adafruit_FONA::TCPconnect(char *server, uint16_t port) { 01342 flushInput(); 01343 01344 // close all old connections 01345 if (! sendCheckReply(F("AT+CIPSHUT"), F("SHUT OK"), 20000) ) return false; 01346 01347 // single connection at a time 01348 if (! sendCheckReply(F("AT+CIPMUX=0"), ok_reply) ) return false; 01349 01350 // manually read data 01351 if (! sendCheckReply(F("AT+CIPRXGET=1"), ok_reply) ) return false; 01352 01353 01354 DEBUG_PRINT(F("AT+CIPSTART=\"TCP\",\"")); 01355 DEBUG_PRINT(server); 01356 DEBUG_PRINT(F("\",\"")); 01357 DEBUG_PRINT(port); 01358 DEBUG_PRINTLN(F("\"")); 01359 01360 01361 mySerial->print(F("AT+CIPSTART=\"TCP\",\"")); 01362 mySerial->print(server); 01363 mySerial->print(F("\",\"")); 01364 mySerial->print(port); 01365 mySerial->println(F("\"")); 01366 01367 if (! expectReply(ok_reply)) return false; 01368 if (! expectReply(F("CONNECT OK"))) return false; 01369 01370 // looks like it was a success (?) 01371 return true; 01372 } 01373 01374 boolean Adafruit_FONA::TCPclose(void) { 01375 return sendCheckReply(F("AT+CIPCLOSE"), ok_reply); 01376 } 01377 01378 boolean Adafruit_FONA::TCPconnected(void) { 01379 if (! sendCheckReply(F("AT+CIPSTATUS"), ok_reply, 100) ) return false; 01380 readline(100); 01381 01382 DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 01383 01384 return (strcmp(replybuffer, "STATE: CONNECT OK") == 0); 01385 } 01386 01387 boolean Adafruit_FONA::TCPsend(char *packet, uint8_t len) { 01388 01389 DEBUG_PRINT(F("AT+CIPSEND=")); 01390 DEBUG_PRINTLN(len); 01391 #ifdef ADAFRUIT_FONA_DEBUG 01392 for (uint16_t i=0; i<len; i++) { 01393 DEBUG_PRINT(F(" 0x")); 01394 DEBUG_PRINT(packet[i], HEX); 01395 } 01396 #endif 01397 DEBUG_PRINTLN(); 01398 01399 01400 mySerial->print(F("AT+CIPSEND=")); 01401 mySerial->println(len); 01402 readline(); 01403 01404 DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 01405 01406 if (replybuffer[0] != '>') return false; 01407 01408 mySerial->write(packet, len); 01409 readline(3000); // wait up to 3 seconds to send the data 01410 01411 DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 01412 01413 01414 return (strcmp(replybuffer, "SEND OK") == 0); 01415 } 01416 01417 uint16_t Adafruit_FONA::TCPavailable(void) { 01418 uint16_t avail; 01419 01420 if (! sendParseReply(F("AT+CIPRXGET=4"), F("+CIPRXGET: 4,"), &avail, ',', 0) ) return false; 01421 01422 01423 DEBUG_PRINT (avail); DEBUG_PRINTLN(F(" bytes available")); 01424 01425 01426 return avail; 01427 } 01428 01429 01430 uint16_t Adafruit_FONA::TCPread(uint8_t *buff, uint8_t len) { 01431 uint16_t avail; 01432 01433 mySerial->print(F("AT+CIPRXGET=2,")); 01434 mySerial->println(len); 01435 readline(); 01436 if (! parseReply(F("+CIPRXGET: 2,"), &avail, ',', 0)) return false; 01437 01438 readRaw(avail); 01439 01440 #ifdef ADAFRUIT_FONA_DEBUG 01441 DEBUG_PRINT (avail); DEBUG_PRINTLN(F(" bytes read")); 01442 for (uint8_t i=0;i<avail;i++) { 01443 DEBUG_PRINT(F(" 0x")); DEBUG_PRINT(replybuffer[i], HEX); 01444 } 01445 DEBUG_PRINTLN(); 01446 #endif 01447 01448 memcpy(buff, replybuffer, avail); 01449 01450 return avail; 01451 } 01452 01453 01454 01455 /********* HTTP LOW LEVEL FUNCTIONS ************************************/ 01456 01457 boolean Adafruit_FONA::HTTP_init() { 01458 return sendCheckReply(F("AT+HTTPINIT"), ok_reply); 01459 } 01460 01461 boolean Adafruit_FONA::HTTP_term() { 01462 return sendCheckReply(F("AT+HTTPTERM"), ok_reply); 01463 } 01464 01465 void Adafruit_FONA::HTTP_para_start(FONAFlashStringPtr parameter, 01466 boolean quoted) { 01467 flushInput(); 01468 01469 01470 DEBUG_PRINT(F("\t---> ")); 01471 DEBUG_PRINT(F("AT+HTTPPARA=\"")); 01472 DEBUG_PRINT(parameter); 01473 DEBUG_PRINTLN('"'); 01474 01475 01476 mySerial->print(F("AT+HTTPPARA=\"")); 01477 mySerial->print(parameter); 01478 if (quoted) 01479 mySerial->print(F("\",\"")); 01480 else 01481 mySerial->print(F("\",")); 01482 } 01483 01484 boolean Adafruit_FONA::HTTP_para_end(boolean quoted) { 01485 if (quoted) 01486 mySerial->println('"'); 01487 else 01488 mySerial->println(); 01489 01490 return expectReply(ok_reply); 01491 } 01492 01493 boolean Adafruit_FONA::HTTP_para(FONAFlashStringPtr parameter, 01494 const char *value) { 01495 HTTP_para_start(parameter, true); 01496 mySerial->print(value); 01497 return HTTP_para_end(true); 01498 } 01499 01500 boolean Adafruit_FONA::HTTP_para(FONAFlashStringPtr parameter, 01501 FONAFlashStringPtr value) { 01502 HTTP_para_start(parameter, true); 01503 mySerial->print(value); 01504 return HTTP_para_end(true); 01505 } 01506 01507 boolean Adafruit_FONA::HTTP_para(FONAFlashStringPtr parameter, 01508 int32_t value) { 01509 HTTP_para_start(parameter, false); 01510 mySerial->print(value); 01511 return HTTP_para_end(false); 01512 } 01513 01514 boolean Adafruit_FONA::HTTP_data(uint32_t size, uint32_t maxTime) { 01515 flushInput(); 01516 01517 01518 DEBUG_PRINT(F("\t---> ")); 01519 DEBUG_PRINT(F("AT+HTTPDATA=")); 01520 DEBUG_PRINT(size); 01521 DEBUG_PRINT(','); 01522 DEBUG_PRINTLN(maxTime); 01523 01524 01525 mySerial->print(F("AT+HTTPDATA=")); 01526 mySerial->print(size); 01527 mySerial->print(","); 01528 mySerial->println(maxTime); 01529 01530 return expectReply(F("DOWNLOAD")); 01531 } 01532 01533 boolean Adafruit_FONA::HTTP_action(uint8_t method, uint16_t *status, 01534 uint16_t *datalen, int32_t timeout) { 01535 // Send request. 01536 if (! sendCheckReply(F("AT+HTTPACTION="), method, ok_reply)) 01537 return false; 01538 01539 // Parse response status and size. 01540 readline(timeout); 01541 if (! parseReply(F("+HTTPACTION:"), status, ',', 1)) 01542 return false; 01543 if (! parseReply(F("+HTTPACTION:"), datalen, ',', 2)) 01544 return false; 01545 01546 return true; 01547 } 01548 01549 boolean Adafruit_FONA::HTTP_readall(uint16_t *datalen) { 01550 getReply(F("AT+HTTPREAD")); 01551 if (! parseReply(F("+HTTPREAD:"), datalen, ',', 0)) 01552 return false; 01553 01554 return true; 01555 } 01556 01557 boolean Adafruit_FONA::HTTP_ssl(boolean onoff) { 01558 return sendCheckReply(F("AT+HTTPSSL="), onoff ? 1 : 0, ok_reply); 01559 } 01560 01561 /********* HTTP HIGH LEVEL FUNCTIONS ***************************/ 01562 01563 boolean Adafruit_FONA::HTTP_GET_start(char *url, 01564 uint16_t *status, uint16_t *datalen){ 01565 if (! HTTP_setup(url)) 01566 return false; 01567 01568 // HTTP GET 01569 if (! HTTP_action(FONA_HTTP_GET, status, datalen, 30000)) 01570 return false; 01571 01572 DEBUG_PRINT(F("Status: ")); DEBUG_PRINTLN(*status); 01573 DEBUG_PRINT(F("Len: ")); DEBUG_PRINTLN(*datalen); 01574 01575 // HTTP response data 01576 if (! HTTP_readall(datalen)) 01577 return false; 01578 01579 return true; 01580 } 01581 01582 /* 01583 boolean Adafruit_FONA_3G::HTTP_GET_start(char *ipaddr, char *path, uint16_t port 01584 uint16_t *status, uint16_t *datalen){ 01585 char send[100] = "AT+CHTTPACT=\""; 01586 char *sendp = send + strlen(send); 01587 memset(sendp, 0, 100 - strlen(send)); 01588 01589 strcpy(sendp, ipaddr); 01590 sendp+=strlen(ipaddr); 01591 sendp[0] = '\"'; 01592 sendp++; 01593 sendp[0] = ','; 01594 itoa(sendp, port); 01595 getReply(send, 500); 01596 01597 return; 01598 01599 if (! HTTP_setup(url)) 01600 01601 return false; 01602 01603 // HTTP GET 01604 if (! HTTP_action(FONA_HTTP_GET, status, datalen)) 01605 return false; 01606 01607 DEBUG_PRINT("Status: "); DEBUG_PRINTLN(*status); 01608 DEBUG_PRINT("Len: "); DEBUG_PRINTLN(*datalen); 01609 01610 // HTTP response data 01611 if (! HTTP_readall(datalen)) 01612 return false; 01613 01614 return true; 01615 } 01616 */ 01617 01618 void Adafruit_FONA::HTTP_GET_end(void) { 01619 HTTP_term(); 01620 } 01621 01622 boolean Adafruit_FONA::HTTP_POST_start(char *url, 01623 FONAFlashStringPtr contenttype, 01624 const uint8_t *postdata, uint16_t postdatalen, 01625 uint16_t *status, uint16_t *datalen){ 01626 if (! HTTP_setup(url)) 01627 return false; 01628 01629 if (! HTTP_para(F("CONTENT"), contenttype)) { 01630 return false; 01631 } 01632 01633 // HTTP POST data 01634 if (! HTTP_data(postdatalen, 10000)) 01635 return false; 01636 mySerial->write(postdata, postdatalen); 01637 if (! expectReply(ok_reply)) 01638 return false; 01639 01640 // HTTP POST 01641 if (! HTTP_action(FONA_HTTP_POST, status, datalen)) 01642 return false; 01643 01644 DEBUG_PRINT(F("Status: ")); DEBUG_PRINTLN(*status); 01645 DEBUG_PRINT(F("Len: ")); DEBUG_PRINTLN(*datalen); 01646 01647 // HTTP response data 01648 if (! HTTP_readall(datalen)) 01649 return false; 01650 01651 return true; 01652 } 01653 01654 void Adafruit_FONA::HTTP_POST_end(void) { 01655 HTTP_term(); 01656 } 01657 01658 void Adafruit_FONA::setUserAgent(FONAFlashStringPtr useragent) { 01659 this->useragent = useragent; 01660 } 01661 01662 void Adafruit_FONA::setHTTPSRedirect(boolean onoff) { 01663 httpsredirect = onoff; 01664 } 01665 01666 /********* HTTP HELPERS ****************************************/ 01667 01668 boolean Adafruit_FONA::HTTP_setup(char *url) { 01669 // Handle any pending 01670 HTTP_term(); 01671 01672 // Initialize and set parameters 01673 if (! HTTP_init()) 01674 return false; 01675 if (! HTTP_para(F("CID"), 1)) 01676 return false; 01677 if (! HTTP_para(F("UA"), useragent)) 01678 return false; 01679 if (! HTTP_para(F("URL"), url)) 01680 return false; 01681 01682 // HTTPS redirect 01683 if (httpsredirect) { 01684 if (! HTTP_para(F("REDIR"),1)) 01685 return false; 01686 01687 if (! HTTP_ssl(true)) 01688 return false; 01689 } 01690 01691 return true; 01692 } 01693 01694 /********* HELPERS *********************************************/ 01695 01696 boolean Adafruit_FONA::expectReply(FONAFlashStringPtr reply, 01697 uint16_t timeout) { 01698 readline(timeout); 01699 01700 DEBUG_PRINT(F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 01701 01702 return (prog_char_strcmp(replybuffer, (prog_char*)reply) == 0); 01703 } 01704 01705 /********* LOW LEVEL *******************************************/ 01706 01707 inline int Adafruit_FONA::available(void) { 01708 return mySerial->available(); 01709 } 01710 01711 inline size_t Adafruit_FONA::write(uint8_t x) { 01712 return mySerial->write(x); 01713 } 01714 01715 inline int Adafruit_FONA::read(void) { 01716 return mySerial->read(); 01717 } 01718 01719 inline int Adafruit_FONA::peek(void) { 01720 return mySerial->peek(); 01721 } 01722 01723 inline void Adafruit_FONA::flush() { 01724 mySerial->flush(); 01725 } 01726 01727 void Adafruit_FONA::flushInput() { 01728 // Read all available serial input to flush pending data. 01729 uint16_t timeoutloop = 0; 01730 while (timeoutloop++ < 40) { 01731 while(available()) { 01732 read(); 01733 timeoutloop = 0; // If char was received reset the timer 01734 } 01735 delay(1); 01736 } 01737 } 01738 01739 uint16_t Adafruit_FONA::readRaw(uint16_t b) { 01740 uint16_t idx = 0; 01741 01742 while (b && (idx < sizeof(replybuffer)-1)) { 01743 if (mySerial->available()) { 01744 replybuffer[idx] = mySerial->read(); 01745 idx++; 01746 b--; 01747 } 01748 } 01749 replybuffer[idx] = 0; 01750 01751 return idx; 01752 } 01753 01754 uint8_t Adafruit_FONA::readline(uint16_t timeout, boolean multiline) { 01755 uint16_t replyidx = 0; 01756 01757 while (timeout--) { 01758 if (replyidx >= 254) { 01759 //DEBUG_PRINTLN(F("SPACE")); 01760 break; 01761 } 01762 01763 while(mySerial->available()) { 01764 char c = mySerial->read(); 01765 if (c == '\r') continue; 01766 if (c == 0xA) { 01767 if (replyidx == 0) // the first 0x0A is ignored 01768 continue; 01769 01770 if (!multiline) { 01771 timeout = 0; // the second 0x0A is the end of the line 01772 break; 01773 } 01774 } 01775 replybuffer[replyidx] = c; 01776 //DEBUG_PRINT(c, HEX); DEBUG_PRINT("#"); DEBUG_PRINTLN(c); 01777 replyidx++; 01778 } 01779 01780 if (timeout == 0) { 01781 //DEBUG_PRINTLN(F("TIMEOUT")); 01782 break; 01783 } 01784 delay(1); 01785 } 01786 replybuffer[replyidx] = 0; // null term 01787 return replyidx; 01788 } 01789 01790 uint8_t Adafruit_FONA::getReply(char *send, uint16_t timeout) { 01791 flushInput(); 01792 01793 01794 DEBUG_PRINT(F("\t---> ")); DEBUG_PRINTLN(send); 01795 01796 01797 mySerial->println(send); 01798 01799 uint8_t l = readline(timeout); 01800 01801 DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 01802 01803 return l; 01804 } 01805 01806 uint8_t Adafruit_FONA::getReply(FONAFlashStringPtr send, uint16_t timeout) { 01807 flushInput(); 01808 01809 01810 DEBUG_PRINT(F("\t---> ")); DEBUG_PRINTLN(send); 01811 01812 01813 mySerial->println(send); 01814 01815 uint8_t l = readline(timeout); 01816 01817 DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 01818 01819 return l; 01820 } 01821 01822 // Send prefix, suffix, and newline. Return response (and also set replybuffer with response). 01823 uint8_t Adafruit_FONA::getReply(FONAFlashStringPtr prefix, char *suffix, uint16_t timeout) { 01824 flushInput(); 01825 01826 01827 DEBUG_PRINT(F("\t---> ")); DEBUG_PRINT(prefix); DEBUG_PRINTLN(suffix); 01828 01829 01830 mySerial->print(prefix); 01831 mySerial->println(suffix); 01832 01833 uint8_t l = readline(timeout); 01834 01835 DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 01836 01837 return l; 01838 } 01839 01840 // Send prefix, suffix, and newline. Return response (and also set replybuffer with response). 01841 uint8_t Adafruit_FONA::getReply(FONAFlashStringPtr prefix, int32_t suffix, uint16_t timeout) { 01842 flushInput(); 01843 01844 01845 DEBUG_PRINT(F("\t---> ")); DEBUG_PRINT(prefix); DEBUG_PRINTLN(suffix, DEC); 01846 01847 01848 mySerial->print(prefix); 01849 mySerial->println(suffix, DEC); 01850 01851 uint8_t l = readline(timeout); 01852 01853 DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 01854 01855 return l; 01856 } 01857 01858 // Send prefix, suffix, suffix2, and newline. Return response (and also set replybuffer with response). 01859 uint8_t Adafruit_FONA::getReply(FONAFlashStringPtr prefix, int32_t suffix1, int32_t suffix2, uint16_t timeout) { 01860 flushInput(); 01861 01862 01863 DEBUG_PRINT(F("\t---> ")); DEBUG_PRINT(prefix); 01864 DEBUG_PRINT(suffix1, DEC); DEBUG_PRINT(','); DEBUG_PRINTLN(suffix2, DEC); 01865 01866 01867 mySerial->print(prefix); 01868 mySerial->print(suffix1); 01869 mySerial->print(','); 01870 mySerial->println(suffix2, DEC); 01871 01872 uint8_t l = readline(timeout); 01873 01874 DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 01875 01876 return l; 01877 } 01878 01879 // Send prefix, ", suffix, ", and newline. Return response (and also set replybuffer with response). 01880 uint8_t Adafruit_FONA::getReplyQuoted(FONAFlashStringPtr prefix, FONAFlashStringPtr suffix, uint16_t timeout) { 01881 flushInput(); 01882 01883 01884 DEBUG_PRINT(F("\t---> ")); DEBUG_PRINT(prefix); 01885 DEBUG_PRINT('"'); DEBUG_PRINT(suffix); DEBUG_PRINTLN('"'); 01886 01887 01888 mySerial->print(prefix); 01889 mySerial->print('"'); 01890 mySerial->print(suffix); 01891 mySerial->println('"'); 01892 01893 uint8_t l = readline(timeout); 01894 01895 DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 01896 01897 return l; 01898 } 01899 01900 boolean Adafruit_FONA::sendCheckReply(char *send, char *reply, uint16_t timeout) { 01901 if (! getReply(send, timeout) ) 01902 return false; 01903 /* 01904 for (uint8_t i=0; i<strlen(replybuffer); i++) { 01905 DEBUG_PRINT(replybuffer[i], HEX); DEBUG_PRINT(" "); 01906 } 01907 DEBUG_PRINTLN(); 01908 for (uint8_t i=0; i<strlen(reply); i++) { 01909 DEBUG_PRINT(reply[i], HEX); DEBUG_PRINT(" "); 01910 } 01911 DEBUG_PRINTLN(); 01912 */ 01913 return (strcmp(replybuffer, reply) == 0); 01914 } 01915 01916 boolean Adafruit_FONA::sendCheckReply(FONAFlashStringPtr send, FONAFlashStringPtr reply, uint16_t timeout) { 01917 if (! getReply(send, timeout) ) 01918 return false; 01919 01920 return (prog_char_strcmp(replybuffer, (prog_char*)reply) == 0); 01921 } 01922 01923 boolean Adafruit_FONA::sendCheckReply(char* send, FONAFlashStringPtr reply, uint16_t timeout) { 01924 if (! getReply(send, timeout) ) 01925 return false; 01926 return (prog_char_strcmp(replybuffer, (prog_char*)reply) == 0); 01927 } 01928 01929 01930 // Send prefix, suffix, and newline. Verify FONA response matches reply parameter. 01931 boolean Adafruit_FONA::sendCheckReply(FONAFlashStringPtr prefix, char *suffix, FONAFlashStringPtr reply, uint16_t timeout) { 01932 getReply(prefix, suffix, timeout); 01933 return (prog_char_strcmp(replybuffer, (prog_char*)reply) == 0); 01934 } 01935 01936 // Send prefix, suffix, and newline. Verify FONA response matches reply parameter. 01937 boolean Adafruit_FONA::sendCheckReply(FONAFlashStringPtr prefix, int32_t suffix, FONAFlashStringPtr reply, uint16_t timeout) { 01938 getReply(prefix, suffix, timeout); 01939 return (prog_char_strcmp(replybuffer, (prog_char*)reply) == 0); 01940 } 01941 01942 // Send prefix, suffix, suffix2, and newline. Verify FONA response matches reply parameter. 01943 boolean Adafruit_FONA::sendCheckReply(FONAFlashStringPtr prefix, int32_t suffix1, int32_t suffix2, FONAFlashStringPtr reply, uint16_t timeout) { 01944 getReply(prefix, suffix1, suffix2, timeout); 01945 return (prog_char_strcmp(replybuffer, (prog_char*)reply) == 0); 01946 } 01947 01948 // Send prefix, ", suffix, ", and newline. Verify FONA response matches reply parameter. 01949 boolean Adafruit_FONA::sendCheckReplyQuoted(FONAFlashStringPtr prefix, FONAFlashStringPtr suffix, FONAFlashStringPtr reply, uint16_t timeout) { 01950 getReplyQuoted(prefix, suffix, timeout); 01951 return (prog_char_strcmp(replybuffer, (prog_char*)reply) == 0); 01952 } 01953 01954 01955 boolean Adafruit_FONA::parseReply(FONAFlashStringPtr toreply, 01956 uint16_t *v, char divider, uint8_t index) { 01957 char *p = prog_char_strstr(replybuffer, (prog_char*)toreply); // get the pointer to the voltage 01958 if (p == 0) return false; 01959 p+=prog_char_strlen((prog_char*)toreply); 01960 //DEBUG_PRINTLN(p); 01961 for (uint8_t i=0; i<index;i++) { 01962 // increment dividers 01963 p = strchr(p, divider); 01964 if (!p) return false; 01965 p++; 01966 //DEBUG_PRINTLN(p); 01967 01968 } 01969 *v = atoi(p); 01970 01971 return true; 01972 } 01973 01974 boolean Adafruit_FONA::parseReply(FONAFlashStringPtr toreply, 01975 char *v, char divider, uint8_t index) { 01976 uint8_t i=0; 01977 char *p = prog_char_strstr(replybuffer, (prog_char*)toreply); 01978 if (p == 0) return false; 01979 p+=prog_char_strlen((prog_char*)toreply); 01980 01981 for (i=0; i<index;i++) { 01982 // increment dividers 01983 p = strchr(p, divider); 01984 if (!p) return false; 01985 p++; 01986 } 01987 01988 for(i=0; i<strlen(p);i++) { 01989 if(p[i] == divider) 01990 break; 01991 v[i] = p[i]; 01992 } 01993 01994 v[i] = '\0'; 01995 01996 return true; 01997 } 01998 01999 // Parse a quoted string in the response fields and copy its value (without quotes) 02000 // to the specified character array (v). Only up to maxlen characters are copied 02001 // into the result buffer, so make sure to pass a large enough buffer to handle the 02002 // response. 02003 boolean Adafruit_FONA::parseReplyQuoted(FONAFlashStringPtr toreply, 02004 char *v, int maxlen, char divider, uint8_t index) { 02005 uint8_t i=0, j; 02006 // Verify response starts with toreply. 02007 char *p = prog_char_strstr(replybuffer, (prog_char*)toreply); 02008 if (p == 0) return false; 02009 p+=prog_char_strlen((prog_char*)toreply); 02010 02011 // Find location of desired response field. 02012 for (i=0; i<index;i++) { 02013 // increment dividers 02014 p = strchr(p, divider); 02015 if (!p) return false; 02016 p++; 02017 } 02018 02019 // Copy characters from response field into result string. 02020 for(i=0, j=0; j<maxlen && i<strlen(p); ++i) { 02021 // Stop if a divier is found. 02022 if(p[i] == divider) 02023 break; 02024 // Skip any quotation marks. 02025 else if(p[i] == '"') 02026 continue; 02027 v[j++] = p[i]; 02028 } 02029 02030 // Add a null terminator if result string buffer was not filled. 02031 if (j < maxlen) 02032 v[j] = '\0'; 02033 02034 return true; 02035 } 02036 02037 boolean Adafruit_FONA::sendParseReply(FONAFlashStringPtr tosend, 02038 FONAFlashStringPtr toreply, 02039 uint16_t *v, char divider, uint8_t index) { 02040 getReply(tosend); 02041 02042 if (! parseReply(toreply, v, divider, index)) return false; 02043 02044 readline(); // eat 'OK' 02045 02046 return true; 02047 } 02048 02049 02050 // needed for CBC and others 02051 02052 boolean Adafruit_FONA_3G::sendParseReply(FONAFlashStringPtr tosend, 02053 FONAFlashStringPtr toreply, 02054 float *f, char divider, uint8_t index) { 02055 getReply(tosend); 02056 02057 if (! parseReply(toreply, f, divider, index)) return false; 02058 02059 readline(); // eat 'OK' 02060 02061 return true; 02062 } 02063 02064 02065 boolean Adafruit_FONA_3G::parseReply(FONAFlashStringPtr toreply, 02066 float *f, char divider, uint8_t index) { 02067 char *p = prog_char_strstr(replybuffer, (prog_char*)toreply); // get the pointer to the voltage 02068 if (p == 0) return false; 02069 p+=prog_char_strlen((prog_char*)toreply); 02070 //DEBUG_PRINTLN(p); 02071 for (uint8_t i=0; i<index;i++) { 02072 // increment dividers 02073 p = strchr(p, divider); 02074 if (!p) return false; 02075 p++; 02076 //DEBUG_PRINTLN(p); 02077 02078 } 02079 *f = atof(p); 02080 02081 return true; 02082 }
Generated on Thu Jul 14 2022 09:19:29 by 1.7.2