Version using RawSerial instead of Serial (thread safe)

Fork of FONA_Cellphone_Library by Dream Team

Committer:
zathorix
Date:
Tue Jul 11 20:16:43 2017 +0000
Revision:
4:243ae42bfd65
Parent:
3:7916fb0cc4b0
Added roaming set function

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jbaker66 0:52654f3080d9 1 /***************************************************
jbaker66 0:52654f3080d9 2 This is a library for our Adafruit FONA Cellular Module
jbaker66 0:52654f3080d9 3
jbaker66 0:52654f3080d9 4 Designed specifically to work with the Adafruit FONA
jbaker66 0:52654f3080d9 5 ----> http://www.adafruit.com/products/1946
jbaker66 0:52654f3080d9 6 ----> http://www.adafruit.com/products/1963
jbaker66 0:52654f3080d9 7
jbaker66 0:52654f3080d9 8 These displays use TTL Serial to communicate, 2 pins are required to
jbaker66 0:52654f3080d9 9 interface
jbaker66 0:52654f3080d9 10 Adafruit invests time and resources providing this open source code,
jbaker66 0:52654f3080d9 11 please support Adafruit and open-source hardware by purchasing
jbaker66 0:52654f3080d9 12 products from Adafruit!
jbaker66 0:52654f3080d9 13
jbaker66 0:52654f3080d9 14 Written by Limor Fried/Ladyada for Adafruit Industries.
jbaker66 0:52654f3080d9 15 BSD license, all text above must be included in any redistribution
jbaker66 0:52654f3080d9 16 ****************************************************/
jbaker66 0:52654f3080d9 17
jbaker66 0:52654f3080d9 18 /*
jbaker66 0:52654f3080d9 19 * Modified by George Tzintzarov & Jesse Baker 03/14/2016 for use in mbed LPC1768
jbaker66 0:52654f3080d9 20 */
jbaker66 0:52654f3080d9 21 #include <algorithm>
jbaker66 0:52654f3080d9 22 #include "Adafruit_FONA.h"
jbaker66 0:52654f3080d9 23
jbaker66 0:52654f3080d9 24 #define HIGH 1
jbaker66 0:52654f3080d9 25 #define LOW 0
jbaker66 0:52654f3080d9 26
jbaker66 0:52654f3080d9 27 /*
jbaker66 0:52654f3080d9 28 Notes George is taking:
jbaker66 0:52654f3080d9 29 sendCheckReply returns a boolean where its true when FONA responds with the string of its second input
jbaker66 0:52654f3080d9 30
jbaker66 0:52654f3080d9 31 */
jbaker66 0:52654f3080d9 32
jbaker66 0:52654f3080d9 33
jbaker66 0:52654f3080d9 34 bool Adafruit_FONA::begin(int baudrate) {
jbaker66 0:52654f3080d9 35 mySerial.baud(baudrate); //set the baud rate of the fona serial connection
zathorix 2:f292ec14f01e 36 mySerial.attach(this, &Adafruit_FONA::onSerialDataReceived, Serial::RxIrq); //attached onSerialDataReceived as Serial receive interrupt
jbaker66 0:52654f3080d9 37
jbaker66 0:52654f3080d9 38 // INIT Reboot process
jbaker66 0:52654f3080d9 39 _rstpin = HIGH;
zathorix 3:7916fb0cc4b0 40 Thread::wait(10);
jbaker66 0:52654f3080d9 41 _rstpin = LOW;
zathorix 3:7916fb0cc4b0 42 Thread::wait(100);
jbaker66 0:52654f3080d9 43 _rstpin = HIGH;
jbaker66 0:52654f3080d9 44
jbaker66 0:52654f3080d9 45 // give 3 seconds to reboot
zathorix 3:7916fb0cc4b0 46 Thread::wait(3000);
jbaker66 0:52654f3080d9 47
jbaker66 0:52654f3080d9 48 // flushes the serial port
jbaker66 0:52654f3080d9 49 while (readable()) getc();
jbaker66 0:52654f3080d9 50
jbaker66 0:52654f3080d9 51 // Make sure FONA is alive
jbaker66 0:52654f3080d9 52 sendCheckReply("AT", "OK");
zathorix 3:7916fb0cc4b0 53 Thread::wait(100);
jbaker66 0:52654f3080d9 54 sendCheckReply("AT", "OK");
zathorix 3:7916fb0cc4b0 55 Thread::wait(100);
jbaker66 0:52654f3080d9 56 sendCheckReply("AT", "OK");
zathorix 3:7916fb0cc4b0 57 Thread::wait(100);
jbaker66 0:52654f3080d9 58
jbaker66 0:52654f3080d9 59 // turn off Echo!
jbaker66 0:52654f3080d9 60 sendCheckReply("ATE0", "OK");
zathorix 3:7916fb0cc4b0 61 Thread::wait(100);
jbaker66 0:52654f3080d9 62
jbaker66 0:52654f3080d9 63 // Just checks if the FONA even responds, if it doesnt, then return false
jbaker66 0:52654f3080d9 64 if (! sendCheckReply("ATE0", "OK")) {
jbaker66 0:52654f3080d9 65 return false;
jbaker66 0:52654f3080d9 66 }
jbaker66 0:52654f3080d9 67
jbaker66 0:52654f3080d9 68 return true;
jbaker66 0:52654f3080d9 69 }
jbaker66 0:52654f3080d9 70
jbaker66 0:52654f3080d9 71 void Adafruit_FONA::setEventListener(EventListener *eventListener) {
jbaker66 0:52654f3080d9 72 this->eventListener = eventListener;
jbaker66 0:52654f3080d9 73 }
jbaker66 0:52654f3080d9 74
jbaker66 0:52654f3080d9 75 /********* Stream ********************************************/
jbaker66 0:52654f3080d9 76
jbaker66 0:52654f3080d9 77 int Adafruit_FONA::_putc(int value) {
jbaker66 0:52654f3080d9 78 return mySerial.putc(value);
jbaker66 0:52654f3080d9 79 }
jbaker66 0:52654f3080d9 80
jbaker66 0:52654f3080d9 81 int Adafruit_FONA::_getc() {
jbaker66 0:52654f3080d9 82 __disable_irq(); // Start Critical Section - don't interrupt while changing global buffer variables
jbaker66 0:52654f3080d9 83
jbaker66 0:52654f3080d9 84 // Wait for data if the buffer is empty
jbaker66 0:52654f3080d9 85 if (isRxBufferEmpty()) {
jbaker66 0:52654f3080d9 86 __enable_irq(); // End Critical Section - need to allow rx interrupt to get new characters for buffer
jbaker66 0:52654f3080d9 87
jbaker66 0:52654f3080d9 88 while(isRxBufferEmpty());
jbaker66 0:52654f3080d9 89
jbaker66 0:52654f3080d9 90 __disable_irq(); // Start Critical Section - don't interrupt while changing global buffer variables
jbaker66 0:52654f3080d9 91 }
jbaker66 0:52654f3080d9 92
jbaker66 0:52654f3080d9 93 int data = rxBuffer[rxBufferOutIndex];
jbaker66 0:52654f3080d9 94 incrementRxBufferOutIndex();
jbaker66 0:52654f3080d9 95
jbaker66 0:52654f3080d9 96 __enable_irq(); // End Critical Section
jbaker66 0:52654f3080d9 97
jbaker66 0:52654f3080d9 98 return data;
jbaker66 0:52654f3080d9 99 }
jbaker66 0:52654f3080d9 100
jbaker66 0:52654f3080d9 101 int Adafruit_FONA::readable() {
jbaker66 0:52654f3080d9 102 return !isRxBufferEmpty();
jbaker66 0:52654f3080d9 103 }
jbaker66 0:52654f3080d9 104
jbaker66 0:52654f3080d9 105 void Adafruit_FONA::onSerialDataReceived() {
jbaker66 0:52654f3080d9 106 while (mySerial.readable() && !isRxBufferFull()) {
jbaker66 0:52654f3080d9 107 int data = mySerial.getc();
jbaker66 0:52654f3080d9 108 rxBuffer[rxBufferInIndex] = data;
jbaker66 0:52654f3080d9 109
jbaker66 0:52654f3080d9 110 //
jbaker66 0:52654f3080d9 111 // Analyze the received data in order to detect events like RING or NO CARRIER
jbaker66 0:52654f3080d9 112 //
jbaker66 0:52654f3080d9 113
jbaker66 0:52654f3080d9 114 // Copy the data in the current line
jbaker66 0:52654f3080d9 115 if (currentReceivedLineSize < RX_BUFFER_SIZE && data != '\r' && data != '\n') {
jbaker66 0:52654f3080d9 116 currentReceivedLine[currentReceivedLineSize] = (char) data;
jbaker66 0:52654f3080d9 117 currentReceivedLineSize++;
jbaker66 0:52654f3080d9 118 }
jbaker66 0:52654f3080d9 119
jbaker66 0:52654f3080d9 120 // Check if the line is complete
jbaker66 0:52654f3080d9 121 if (data == '\n') {
jbaker66 0:52654f3080d9 122 currentReceivedLine[currentReceivedLineSize] = 0;
jbaker66 0:52654f3080d9 123
jbaker66 0:52654f3080d9 124 if (eventListener != NULL) {
jbaker66 0:52654f3080d9 125 // Check if we have a special event
jbaker66 0:52654f3080d9 126 if (strcmp(currentReceivedLine, "RING") == 0) {
jbaker66 0:52654f3080d9 127 eventListener->onRing();
jbaker66 0:52654f3080d9 128 } else if (strcmp(currentReceivedLine, "NO CARRIER") == 0) {
jbaker66 0:52654f3080d9 129 eventListener->onNoCarrier();
jbaker66 0:52654f3080d9 130 }
jbaker66 0:52654f3080d9 131 }
jbaker66 0:52654f3080d9 132
jbaker66 0:52654f3080d9 133 currentReceivedLineSize = 0;
jbaker66 0:52654f3080d9 134 }
jbaker66 0:52654f3080d9 135
jbaker66 0:52654f3080d9 136 incrementRxBufferInIndex();
jbaker66 0:52654f3080d9 137 }
jbaker66 0:52654f3080d9 138 }
jbaker66 0:52654f3080d9 139
jbaker66 0:52654f3080d9 140 /********* Real Time Clock ********************************************/
jbaker66 0:52654f3080d9 141
jbaker66 0:52654f3080d9 142 bool Adafruit_FONA::enableRTC(uint8_t i) {
jbaker66 0:52654f3080d9 143 if (! sendCheckReply("AT+CLTS=", i, "OK"))
jbaker66 0:52654f3080d9 144 return false;
jbaker66 0:52654f3080d9 145 return sendCheckReply("AT&W", "OK");
jbaker66 0:52654f3080d9 146 }
jbaker66 0:52654f3080d9 147
jbaker66 0:52654f3080d9 148 /********* BATTERY & ADC ********************************************/
jbaker66 0:52654f3080d9 149
jbaker66 0:52654f3080d9 150 /* returns value in mV (uint16_t) */
jbaker66 0:52654f3080d9 151 bool Adafruit_FONA::getBattVoltage(uint16_t *v) {
jbaker66 0:52654f3080d9 152 return sendParseReply("AT+CBC", "+CBC: ", v, ',', 2);
jbaker66 0:52654f3080d9 153 }
jbaker66 0:52654f3080d9 154
jbaker66 0:52654f3080d9 155 /* returns the percentage charge of battery as reported by sim800 */
jbaker66 0:52654f3080d9 156 bool Adafruit_FONA::getBattPercent(uint16_t *p) {
jbaker66 0:52654f3080d9 157 return sendParseReply("AT+CBC", "+CBC: ", p, ',', 1);
jbaker66 0:52654f3080d9 158 }
jbaker66 0:52654f3080d9 159
jbaker66 0:52654f3080d9 160 bool Adafruit_FONA::getADCVoltage(uint16_t *v) {
jbaker66 0:52654f3080d9 161 return sendParseReply("AT+CADC?", "+CADC: 1,", v);
jbaker66 0:52654f3080d9 162 }
jbaker66 0:52654f3080d9 163
jbaker66 0:52654f3080d9 164 /********* SIM ***********************************************************/
jbaker66 0:52654f3080d9 165
jbaker66 0:52654f3080d9 166 bool Adafruit_FONA::unlockSIM(char *pin)
jbaker66 0:52654f3080d9 167 {
jbaker66 0:52654f3080d9 168 char sendbuff[14] = "AT+CPIN=";
jbaker66 0:52654f3080d9 169 sendbuff[8] = pin[0];
jbaker66 0:52654f3080d9 170 sendbuff[9] = pin[1];
jbaker66 0:52654f3080d9 171 sendbuff[10] = pin[2];
jbaker66 0:52654f3080d9 172 sendbuff[11] = pin[3];
jbaker66 0:52654f3080d9 173 sendbuff[12] = NULL;
jbaker66 0:52654f3080d9 174
jbaker66 0:52654f3080d9 175 return sendCheckReply(sendbuff, "OK");
jbaker66 0:52654f3080d9 176 }
jbaker66 0:52654f3080d9 177
jbaker66 0:52654f3080d9 178 uint8_t Adafruit_FONA::getSIMCCID(char *ccid) {
jbaker66 0:52654f3080d9 179 getReply("AT+CCID");
jbaker66 0:52654f3080d9 180 // up to 20 chars
jbaker66 0:52654f3080d9 181 strncpy(ccid, replybuffer, 20);
jbaker66 0:52654f3080d9 182 ccid[20] = 0;
jbaker66 0:52654f3080d9 183
jbaker66 0:52654f3080d9 184 readline(); // eat 'OK'
jbaker66 0:52654f3080d9 185
jbaker66 0:52654f3080d9 186 return strlen(ccid);
jbaker66 0:52654f3080d9 187 }
jbaker66 0:52654f3080d9 188
jbaker66 0:52654f3080d9 189 /********* IMEI **********************************************************/
jbaker66 0:52654f3080d9 190
jbaker66 0:52654f3080d9 191 uint8_t Adafruit_FONA::getIMEI(char *imei) {
jbaker66 0:52654f3080d9 192 getReply("AT+GSN");
jbaker66 0:52654f3080d9 193
jbaker66 0:52654f3080d9 194 // up to 15 chars
jbaker66 0:52654f3080d9 195 strncpy(imei, replybuffer, 15);
jbaker66 0:52654f3080d9 196 imei[15] = 0;
jbaker66 0:52654f3080d9 197
jbaker66 0:52654f3080d9 198 readline(); // eat 'OK'
jbaker66 0:52654f3080d9 199
jbaker66 0:52654f3080d9 200 return strlen(imei);
jbaker66 0:52654f3080d9 201 }
jbaker66 0:52654f3080d9 202
jbaker66 0:52654f3080d9 203 /********* NETWORK *******************************************************/
jbaker66 0:52654f3080d9 204
jbaker66 0:52654f3080d9 205 uint8_t Adafruit_FONA::getNetworkStatus(void) {
jbaker66 0:52654f3080d9 206 uint16_t status;
jbaker66 0:52654f3080d9 207
jbaker66 0:52654f3080d9 208 if (! sendParseReply("AT+CREG?", "+CREG: ", &status, ',', 1)) return 0;
jbaker66 0:52654f3080d9 209
jbaker66 0:52654f3080d9 210 return status;
jbaker66 0:52654f3080d9 211 }
jbaker66 0:52654f3080d9 212
zathorix 4:243ae42bfd65 213 uint8_t Adafruit_FONA::setNetworkRoaming() {
zathorix 4:243ae42bfd65 214
zathorix 4:243ae42bfd65 215 if (!sendCheckReply("AT+CREG=5", "OK", 10000)) return -1;
zathorix 4:243ae42bfd65 216
zathorix 4:243ae42bfd65 217 return 1;
zathorix 4:243ae42bfd65 218
zathorix 4:243ae42bfd65 219 }
jbaker66 0:52654f3080d9 220
jbaker66 0:52654f3080d9 221 uint8_t Adafruit_FONA::getRSSI(void) {
jbaker66 0:52654f3080d9 222 uint16_t reply;
jbaker66 0:52654f3080d9 223
jbaker66 0:52654f3080d9 224 if (! sendParseReply("AT+CSQ", "+CSQ: ", &reply) ) return 0;
jbaker66 0:52654f3080d9 225
jbaker66 0:52654f3080d9 226 return reply;
jbaker66 0:52654f3080d9 227 }
jbaker66 0:52654f3080d9 228
jbaker66 0:52654f3080d9 229 /********* AUDIO *******************************************************/
jbaker66 0:52654f3080d9 230
jbaker66 0:52654f3080d9 231 bool Adafruit_FONA::setAudio(uint8_t a) {
jbaker66 0:52654f3080d9 232 // 0 is headset, 1 is external audio
jbaker66 0:52654f3080d9 233 if (a > 1) return false;
jbaker66 0:52654f3080d9 234
jbaker66 0:52654f3080d9 235 return sendCheckReply("AT+CHFA=", a, "OK");
jbaker66 0:52654f3080d9 236 }
jbaker66 0:52654f3080d9 237
jbaker66 0:52654f3080d9 238 uint8_t Adafruit_FONA::getVolume(void) {
jbaker66 0:52654f3080d9 239 uint16_t reply;
jbaker66 0:52654f3080d9 240
jbaker66 0:52654f3080d9 241 if (! sendParseReply("AT+CLVL?", "+CLVL: ", &reply) ) return 0;
jbaker66 0:52654f3080d9 242
jbaker66 0:52654f3080d9 243 return reply;
jbaker66 0:52654f3080d9 244 }
jbaker66 0:52654f3080d9 245
jbaker66 0:52654f3080d9 246 bool Adafruit_FONA::setVolume(uint8_t i) {
jbaker66 0:52654f3080d9 247 return sendCheckReply("AT+CLVL=", i, "OK");
jbaker66 0:52654f3080d9 248 }
jbaker66 0:52654f3080d9 249
jbaker66 0:52654f3080d9 250
jbaker66 0:52654f3080d9 251 bool Adafruit_FONA::playDTMF(char dtmf) {
jbaker66 0:52654f3080d9 252 char str[4];
jbaker66 0:52654f3080d9 253 str[0] = '\"';
jbaker66 0:52654f3080d9 254 str[1] = dtmf;
jbaker66 0:52654f3080d9 255 str[2] = '\"';
jbaker66 0:52654f3080d9 256 str[3] = 0;
jbaker66 0:52654f3080d9 257 return sendCheckReply("AT+CLDTMF=3,", str, "OK");
jbaker66 0:52654f3080d9 258 }
jbaker66 0:52654f3080d9 259
jbaker66 0:52654f3080d9 260 bool Adafruit_FONA::playToolkitTone(uint8_t t, uint16_t len) {
jbaker66 0:52654f3080d9 261 return sendCheckReply("AT+STTONE=1,", t, len, "OK");
jbaker66 0:52654f3080d9 262 }
jbaker66 0:52654f3080d9 263
jbaker66 0:52654f3080d9 264 bool Adafruit_FONA::setMicVolume(uint8_t a, uint8_t level) {
jbaker66 0:52654f3080d9 265 // 0 is headset, 1 is external audio
jbaker66 0:52654f3080d9 266 if (a > 1) return false;
jbaker66 0:52654f3080d9 267
jbaker66 0:52654f3080d9 268 return sendCheckReply("AT+CMIC=", a, level, "OK");
jbaker66 0:52654f3080d9 269 }
jbaker66 0:52654f3080d9 270
jbaker66 0:52654f3080d9 271 /********* FM RADIO *******************************************************/
jbaker66 0:52654f3080d9 272
jbaker66 0:52654f3080d9 273
jbaker66 0:52654f3080d9 274 bool Adafruit_FONA::FMradio(bool onoff, uint8_t a) {
jbaker66 0:52654f3080d9 275 if (! onoff) {
jbaker66 0:52654f3080d9 276 return sendCheckReply("AT+FMCLOSE", "OK");
jbaker66 0:52654f3080d9 277 }
jbaker66 0:52654f3080d9 278
jbaker66 0:52654f3080d9 279 // 0 is headset, 1 is external audio
jbaker66 0:52654f3080d9 280 if (a > 1) return false;
jbaker66 0:52654f3080d9 281
jbaker66 0:52654f3080d9 282 return sendCheckReply("AT+FMOPEN=", a, "OK");
jbaker66 0:52654f3080d9 283 }
jbaker66 0:52654f3080d9 284
jbaker66 0:52654f3080d9 285 bool Adafruit_FONA::tuneFMradio(uint16_t station) {
jbaker66 0:52654f3080d9 286 // Fail if FM station is outside allowed range.
jbaker66 0:52654f3080d9 287 if ((station < 870) || (station > 1090))
jbaker66 0:52654f3080d9 288 return false;
jbaker66 0:52654f3080d9 289
jbaker66 0:52654f3080d9 290 return sendCheckReply("AT+FMFREQ=", station, "OK");
jbaker66 0:52654f3080d9 291 }
jbaker66 0:52654f3080d9 292
jbaker66 0:52654f3080d9 293 bool Adafruit_FONA::setFMVolume(uint8_t i) {
jbaker66 0:52654f3080d9 294 // Fail if volume is outside allowed range (0-6).
jbaker66 0:52654f3080d9 295 if (i > 6) {
jbaker66 0:52654f3080d9 296 return false;
jbaker66 0:52654f3080d9 297 }
jbaker66 0:52654f3080d9 298 // Send FM volume command and verify response.
jbaker66 0:52654f3080d9 299 return sendCheckReply("AT+FMVOLUME=", i, "OK");
jbaker66 0:52654f3080d9 300 }
jbaker66 0:52654f3080d9 301
jbaker66 0:52654f3080d9 302 int8_t Adafruit_FONA::getFMVolume() {
jbaker66 0:52654f3080d9 303 uint16_t level;
jbaker66 0:52654f3080d9 304
jbaker66 0:52654f3080d9 305 if (! sendParseReply("AT+FMVOLUME?", "+FMVOLUME: ", &level) ) return 0;
jbaker66 0:52654f3080d9 306
jbaker66 0:52654f3080d9 307 return level;
jbaker66 0:52654f3080d9 308 }
jbaker66 0:52654f3080d9 309
jbaker66 0:52654f3080d9 310 int8_t Adafruit_FONA::getFMSignalLevel(uint16_t station) {
jbaker66 0:52654f3080d9 311 // Fail if FM station is outside allowed range.
jbaker66 0:52654f3080d9 312 if ((station < 875) || (station > 1080)) {
jbaker66 0:52654f3080d9 313 return -1;
jbaker66 0:52654f3080d9 314 }
jbaker66 0:52654f3080d9 315
jbaker66 0:52654f3080d9 316 // Send FM signal level query command.
jbaker66 0:52654f3080d9 317 // Note, need to explicitly send timeout so right overload is chosen.
jbaker66 0:52654f3080d9 318 getReply("AT+FMSIGNAL=", station, FONA_DEFAULT_TIMEOUT_MS);
jbaker66 0:52654f3080d9 319 // Check response starts with expected value.
jbaker66 0:52654f3080d9 320 char *p = strstr(replybuffer, "+FMSIGNAL: ");
jbaker66 0:52654f3080d9 321 if (p == 0) return -1;
jbaker66 0:52654f3080d9 322 p+=11;
jbaker66 0:52654f3080d9 323 // Find second colon to get start of signal quality.
jbaker66 0:52654f3080d9 324 p = strchr(p, ':');
jbaker66 0:52654f3080d9 325 if (p == 0) return -1;
jbaker66 0:52654f3080d9 326 p+=1;
jbaker66 0:52654f3080d9 327 // Parse signal quality.
jbaker66 0:52654f3080d9 328 int8_t level = atoi(p);
jbaker66 0:52654f3080d9 329 readline(); // eat the "OK"
jbaker66 0:52654f3080d9 330 return level;
jbaker66 0:52654f3080d9 331 }
jbaker66 0:52654f3080d9 332
jbaker66 0:52654f3080d9 333 /********* PWM/BUZZER **************************************************/
jbaker66 0:52654f3080d9 334
jbaker66 0:52654f3080d9 335 bool Adafruit_FONA::setPWM(uint16_t period, uint8_t duty) {
jbaker66 0:52654f3080d9 336 if (period > 2000) return false;
jbaker66 0:52654f3080d9 337 if (duty > 100) return false;
jbaker66 0:52654f3080d9 338
jbaker66 0:52654f3080d9 339 return sendCheckReply("AT+SPWM=0,", period, duty, "OK");
jbaker66 0:52654f3080d9 340 }
jbaker66 0:52654f3080d9 341
jbaker66 0:52654f3080d9 342 /********* CALL PHONES **************************************************/
jbaker66 0:52654f3080d9 343 bool Adafruit_FONA::callPhone(char *number) {
jbaker66 0:52654f3080d9 344 char sendbuff[35] = "ATD";
jbaker66 0:52654f3080d9 345 strncpy(sendbuff+3, number, min((int)30, (int)strlen(number)));
jbaker66 0:52654f3080d9 346 uint8_t x = strlen(sendbuff);
jbaker66 0:52654f3080d9 347 sendbuff[x] = ';';
jbaker66 0:52654f3080d9 348 sendbuff[x+1] = 0;
jbaker66 0:52654f3080d9 349
jbaker66 0:52654f3080d9 350 return sendCheckReply(sendbuff, "OK");
jbaker66 0:52654f3080d9 351 }
jbaker66 0:52654f3080d9 352
jbaker66 0:52654f3080d9 353 bool Adafruit_FONA::hangUp(void) {
jbaker66 0:52654f3080d9 354 return sendCheckReply("ATH0", "OK");
jbaker66 0:52654f3080d9 355 }
jbaker66 0:52654f3080d9 356
jbaker66 0:52654f3080d9 357 bool Adafruit_FONA::pickUp(void) {
jbaker66 0:52654f3080d9 358 return sendCheckReply("ATA", "OK");
jbaker66 0:52654f3080d9 359 }
jbaker66 0:52654f3080d9 360
jbaker66 0:52654f3080d9 361 void Adafruit_FONA::onIncomingCall() {
jbaker66 0:52654f3080d9 362 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 363 printf("> Incoming call...\r\n");
jbaker66 0:52654f3080d9 364 #endif
jbaker66 0:52654f3080d9 365 _incomingCall = true;
jbaker66 0:52654f3080d9 366 }
jbaker66 0:52654f3080d9 367
jbaker66 0:52654f3080d9 368 bool Adafruit_FONA::callerIdNotification(bool enable) {
jbaker66 0:52654f3080d9 369 if(enable){
jbaker66 0:52654f3080d9 370 _ringIndicatorInterruptIn.fall(this, &Adafruit_FONA::onIncomingCall);
jbaker66 0:52654f3080d9 371 return sendCheckReply("AT+CLIP=1", "OK");
jbaker66 0:52654f3080d9 372 }
jbaker66 0:52654f3080d9 373
jbaker66 0:52654f3080d9 374 _ringIndicatorInterruptIn.fall(NULL);
jbaker66 0:52654f3080d9 375 return sendCheckReply("AT+CLIP=0", "OK");
jbaker66 0:52654f3080d9 376 }
jbaker66 0:52654f3080d9 377
jbaker66 0:52654f3080d9 378 bool Adafruit_FONA::incomingCallNumber(char* phonenum) {
jbaker66 0:52654f3080d9 379 //+CLIP: "<incoming phone number>",145,"",0,"",0
jbaker66 0:52654f3080d9 380 if(!_incomingCall)
jbaker66 0:52654f3080d9 381 return false;
jbaker66 0:52654f3080d9 382
jbaker66 0:52654f3080d9 383 readline();
jbaker66 0:52654f3080d9 384 while(!strcmp(replybuffer, "RING") == 0) {
jbaker66 0:52654f3080d9 385 flushInput();
jbaker66 0:52654f3080d9 386 readline();
jbaker66 0:52654f3080d9 387 }
jbaker66 0:52654f3080d9 388
jbaker66 0:52654f3080d9 389 readline(); //reads incoming phone number line
jbaker66 0:52654f3080d9 390
jbaker66 0:52654f3080d9 391 parseReply("+CLIP: \"", phonenum, '"');
jbaker66 0:52654f3080d9 392
jbaker66 0:52654f3080d9 393 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 394 printf("Phone Number: %s\r\n", replybuffer);
jbaker66 0:52654f3080d9 395 #endif
jbaker66 0:52654f3080d9 396
jbaker66 0:52654f3080d9 397 _incomingCall = false;
jbaker66 0:52654f3080d9 398 return true;
jbaker66 0:52654f3080d9 399 }
jbaker66 0:52654f3080d9 400
jbaker66 0:52654f3080d9 401 /********* SMS **********************************************************/
jbaker66 0:52654f3080d9 402
jbaker66 0:52654f3080d9 403 uint8_t Adafruit_FONA::getSMSInterrupt(void) {
jbaker66 0:52654f3080d9 404 uint16_t reply;
jbaker66 0:52654f3080d9 405
jbaker66 0:52654f3080d9 406 if (! sendParseReply("AT+CFGRI?", "+CFGRI: ", &reply) ) return 0;
jbaker66 0:52654f3080d9 407
jbaker66 0:52654f3080d9 408 return reply;
jbaker66 0:52654f3080d9 409 }
jbaker66 0:52654f3080d9 410
jbaker66 0:52654f3080d9 411 bool Adafruit_FONA::setSMSInterrupt(uint8_t i) {
jbaker66 0:52654f3080d9 412 return sendCheckReply("AT+CFGRI=", i, "OK");
jbaker66 0:52654f3080d9 413 }
jbaker66 0:52654f3080d9 414
jbaker66 0:52654f3080d9 415 int8_t Adafruit_FONA::getNumSMS(void) {
jbaker66 0:52654f3080d9 416 uint16_t numsms;
jbaker66 0:52654f3080d9 417
jbaker66 0:52654f3080d9 418 if (! sendCheckReply("AT+CMGF=1", "OK")) return -1;
jbaker66 0:52654f3080d9 419 // ask how many sms are stored
jbaker66 0:52654f3080d9 420
jbaker66 0:52654f3080d9 421 if (! sendParseReply("AT+CPMS?", "+CPMS: \"SM_P\",", &numsms) ) return -1;
jbaker66 0:52654f3080d9 422
jbaker66 0:52654f3080d9 423 return numsms;
jbaker66 0:52654f3080d9 424 }
jbaker66 0:52654f3080d9 425
jbaker66 0:52654f3080d9 426 // Reading SMS's is a bit involved so we don't use helpers that may cause delays or debug
jbaker66 0:52654f3080d9 427 // printouts!
jbaker66 0:52654f3080d9 428 bool Adafruit_FONA::readSMS(uint8_t i, char *smsbuff, uint16_t maxlen, uint16_t *readlen) {
jbaker66 0:52654f3080d9 429 // text mode
jbaker66 0:52654f3080d9 430 if (! sendCheckReply("AT+CMGF=1", "OK")) return false;
jbaker66 0:52654f3080d9 431
jbaker66 0:52654f3080d9 432 // show all text mode parameters
jbaker66 0:52654f3080d9 433 if (! sendCheckReply("AT+CSDH=1", "OK")) return false;
jbaker66 0:52654f3080d9 434
jbaker66 0:52654f3080d9 435 // parse out the SMS len
jbaker66 0:52654f3080d9 436 uint16_t thesmslen = 0;
jbaker66 0:52654f3080d9 437
jbaker66 0:52654f3080d9 438 //getReply(F("AT+CMGR="), i, 1000); // do not print debug!
jbaker66 0:52654f3080d9 439 mySerial.printf("AT+CMGR=%d\r\n", i);
jbaker66 0:52654f3080d9 440 readline(1000); // timeout
jbaker66 0:52654f3080d9 441
jbaker66 0:52654f3080d9 442 // parse it out...
jbaker66 0:52654f3080d9 443 if (! parseReply("+CMGR:", &thesmslen, ',', 11)) {
jbaker66 0:52654f3080d9 444 *readlen = 0;
jbaker66 0:52654f3080d9 445 return false;
jbaker66 0:52654f3080d9 446 }
jbaker66 0:52654f3080d9 447
jbaker66 0:52654f3080d9 448 readRaw(thesmslen);
jbaker66 0:52654f3080d9 449
jbaker66 0:52654f3080d9 450 flushInput();
jbaker66 0:52654f3080d9 451
jbaker66 0:52654f3080d9 452 uint16_t thelen = min(maxlen, (uint16_t)strlen(replybuffer));
jbaker66 0:52654f3080d9 453 strncpy(smsbuff, replybuffer, thelen);
jbaker66 0:52654f3080d9 454 smsbuff[thelen] = 0; // end the string
jbaker66 0:52654f3080d9 455
jbaker66 0:52654f3080d9 456 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 457 printf("%s\r\n", replybuffer);
jbaker66 0:52654f3080d9 458 #endif
jbaker66 0:52654f3080d9 459 *readlen = thelen;
jbaker66 0:52654f3080d9 460 return true;
jbaker66 0:52654f3080d9 461 }
jbaker66 0:52654f3080d9 462
jbaker66 0:52654f3080d9 463 // Retrieve the sender of the specified SMS message and copy it as a string to
jbaker66 0:52654f3080d9 464 // the sender buffer. Up to senderlen characters of the sender will be copied
jbaker66 0:52654f3080d9 465 // and a null terminator will be added if less than senderlen charactesr are
jbaker66 0:52654f3080d9 466 // copied to the result. Returns true if a result was successfully retrieved,
jbaker66 0:52654f3080d9 467 // otherwise false.
jbaker66 0:52654f3080d9 468 bool Adafruit_FONA::getSMSSender(uint8_t i, char *sender, int senderlen) {
jbaker66 0:52654f3080d9 469 // Ensure text mode and all text mode parameters are sent.
jbaker66 0:52654f3080d9 470 if (! sendCheckReply("AT+CMGF=1", "OK")) return false;
jbaker66 0:52654f3080d9 471 if (! sendCheckReply("AT+CSDH=1", "OK")) return false;
jbaker66 0:52654f3080d9 472 // Send command to retrieve SMS message and parse a line of response.
jbaker66 0:52654f3080d9 473 mySerial.printf("AT+CMGR=%d\r\n", i);
jbaker66 0:52654f3080d9 474 readline(1000);
jbaker66 0:52654f3080d9 475 // Parse the second field in the response.
jbaker66 0:52654f3080d9 476 bool result = parseReplyQuoted("+CMGR:", sender, senderlen, ',', 1);
jbaker66 0:52654f3080d9 477 // Drop any remaining data from the response.
jbaker66 0:52654f3080d9 478 flushInput();
jbaker66 0:52654f3080d9 479 return result;
jbaker66 0:52654f3080d9 480 }
jbaker66 0:52654f3080d9 481
jbaker66 0:52654f3080d9 482 bool Adafruit_FONA::sendSMS(char *smsaddr, char *smsmsg) {
jbaker66 0:52654f3080d9 483 if (! sendCheckReply("AT+CMGF=1", "OK")) return -1;
jbaker66 0:52654f3080d9 484
jbaker66 0:52654f3080d9 485 char sendcmd[30] = "AT+CMGS=\"";
jbaker66 0:52654f3080d9 486 strncpy(sendcmd+9, smsaddr, 30-9-2); // 9 bytes beginning, 2 bytes for close quote + null
jbaker66 0:52654f3080d9 487 sendcmd[strlen(sendcmd)] = '\"';
jbaker66 0:52654f3080d9 488
jbaker66 0:52654f3080d9 489 if (! sendCheckReply(sendcmd, "> ")) return false;
jbaker66 0:52654f3080d9 490 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 491 printf("> %s\r\n", smsmsg);
jbaker66 0:52654f3080d9 492 #endif
jbaker66 0:52654f3080d9 493 mySerial.printf("%s\r\n\r\n", smsmsg);
jbaker66 0:52654f3080d9 494 mySerial.putc(0x1A);
jbaker66 0:52654f3080d9 495 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 496 printf("^Z\r\n");
jbaker66 0:52654f3080d9 497 #endif
jbaker66 0:52654f3080d9 498 readline(10000); // read the +CMGS reply, wait up to 10 seconds!!!
jbaker66 0:52654f3080d9 499 //Serial.print("* "); Serial.println(replybuffer);
jbaker66 0:52654f3080d9 500 if (strstr(replybuffer, "+CMGS") == 0) {
jbaker66 0:52654f3080d9 501 return false;
jbaker66 0:52654f3080d9 502 }
jbaker66 0:52654f3080d9 503 readline(1000); // read OK
jbaker66 0:52654f3080d9 504 //Serial.print("* "); Serial.println(replybuffer);
jbaker66 0:52654f3080d9 505
jbaker66 0:52654f3080d9 506 if (strcmp(replybuffer, "OK") != 0) {
jbaker66 0:52654f3080d9 507 return false;
jbaker66 0:52654f3080d9 508 }
jbaker66 0:52654f3080d9 509
jbaker66 0:52654f3080d9 510 return true;
jbaker66 0:52654f3080d9 511 }
jbaker66 0:52654f3080d9 512
jbaker66 0:52654f3080d9 513
jbaker66 0:52654f3080d9 514 bool Adafruit_FONA::deleteSMS(uint8_t i) {
jbaker66 0:52654f3080d9 515 if (! sendCheckReply("AT+CMGF=1", "OK")) return -1;
jbaker66 0:52654f3080d9 516 // read an sms
jbaker66 0:52654f3080d9 517 char sendbuff[12] = "AT+CMGD=000";
jbaker66 0:52654f3080d9 518 sendbuff[8] = (i / 100) + '0';
jbaker66 0:52654f3080d9 519 i %= 100;
jbaker66 0:52654f3080d9 520 sendbuff[9] = (i / 10) + '0';
jbaker66 0:52654f3080d9 521 i %= 10;
jbaker66 0:52654f3080d9 522 sendbuff[10] = i + '0';
jbaker66 0:52654f3080d9 523
jbaker66 0:52654f3080d9 524 return sendCheckReply(sendbuff, "OK", 2000);
jbaker66 0:52654f3080d9 525 }
jbaker66 0:52654f3080d9 526
jbaker66 0:52654f3080d9 527 /********* TIME **********************************************************/
jbaker66 0:52654f3080d9 528
jbaker66 0:52654f3080d9 529 bool Adafruit_FONA::enableNetworkTimeSync(bool onoff) {
jbaker66 0:52654f3080d9 530 if (onoff) {
jbaker66 0:52654f3080d9 531 if (! sendCheckReply("AT+CLTS=1", "OK"))
jbaker66 0:52654f3080d9 532 return false;
jbaker66 0:52654f3080d9 533 } else {
jbaker66 0:52654f3080d9 534 if (! sendCheckReply("AT+CLTS=0", "OK"))
jbaker66 0:52654f3080d9 535 return false;
jbaker66 0:52654f3080d9 536 }
jbaker66 0:52654f3080d9 537
jbaker66 0:52654f3080d9 538 flushInput(); // eat any 'Unsolicted Result Code'
jbaker66 0:52654f3080d9 539
jbaker66 0:52654f3080d9 540 return true;
jbaker66 0:52654f3080d9 541 }
jbaker66 0:52654f3080d9 542
jbaker66 0:52654f3080d9 543 bool Adafruit_FONA::enableNTPTimeSync(bool onoff, const char* ntpserver) {
jbaker66 0:52654f3080d9 544 if (onoff) {
jbaker66 0:52654f3080d9 545 if (! sendCheckReply("AT+CNTPCID=1", "OK"))
jbaker66 0:52654f3080d9 546 return false;
jbaker66 0:52654f3080d9 547
jbaker66 0:52654f3080d9 548 mySerial.printf("AT+CNTP=\"");
jbaker66 0:52654f3080d9 549 if (ntpserver != 0) {
jbaker66 0:52654f3080d9 550 mySerial.printf(ntpserver);
jbaker66 0:52654f3080d9 551 } else {
jbaker66 0:52654f3080d9 552 mySerial.printf("pool.ntp.org");
jbaker66 0:52654f3080d9 553 }
jbaker66 0:52654f3080d9 554 mySerial.printf("\",0\r\n");
jbaker66 0:52654f3080d9 555 readline(FONA_DEFAULT_TIMEOUT_MS);
jbaker66 0:52654f3080d9 556 if (strcmp(replybuffer, "OK") != 0)
jbaker66 0:52654f3080d9 557 return false;
jbaker66 0:52654f3080d9 558
jbaker66 0:52654f3080d9 559 if (! sendCheckReply("AT+CNTP", "OK", 10000))
jbaker66 0:52654f3080d9 560 return false;
jbaker66 0:52654f3080d9 561
jbaker66 0:52654f3080d9 562 uint16_t status;
jbaker66 0:52654f3080d9 563 readline(10000);
jbaker66 0:52654f3080d9 564 if (! parseReply("+CNTP:", &status))
jbaker66 0:52654f3080d9 565 return false;
jbaker66 0:52654f3080d9 566 } else {
jbaker66 0:52654f3080d9 567 if (! sendCheckReply("AT+CNTPCID=0", "OK"))
jbaker66 0:52654f3080d9 568 return false;
jbaker66 0:52654f3080d9 569 }
jbaker66 0:52654f3080d9 570
jbaker66 0:52654f3080d9 571 return true;
jbaker66 0:52654f3080d9 572 }
jbaker66 0:52654f3080d9 573
jbaker66 0:52654f3080d9 574 bool Adafruit_FONA::getTime(char* buff, uint16_t maxlen) {
jbaker66 0:52654f3080d9 575 getReply("AT+CCLK?", (uint16_t) 10000);
jbaker66 0:52654f3080d9 576 if (strncmp(replybuffer, "+CCLK: ", 7) != 0)
jbaker66 0:52654f3080d9 577 return false;
jbaker66 0:52654f3080d9 578
jbaker66 0:52654f3080d9 579 char *p = replybuffer+7;
jbaker66 0:52654f3080d9 580 uint16_t lentocopy = min((uint16_t)(maxlen-1), (uint16_t)strlen(p));
jbaker66 0:52654f3080d9 581 strncpy(buff, p, lentocopy+1);
jbaker66 0:52654f3080d9 582 buff[lentocopy] = 0;
jbaker66 0:52654f3080d9 583
jbaker66 0:52654f3080d9 584 readline(); // eat OK
jbaker66 0:52654f3080d9 585
jbaker66 0:52654f3080d9 586 return true;
jbaker66 0:52654f3080d9 587 }
jbaker66 0:52654f3080d9 588
jbaker66 0:52654f3080d9 589 /********* GPS **********************************************************/
jbaker66 0:52654f3080d9 590
jbaker66 0:52654f3080d9 591
jbaker66 0:52654f3080d9 592 bool Adafruit_FONA::enableGPS(bool onoff) {
jbaker66 0:52654f3080d9 593 uint16_t state;
jbaker66 0:52654f3080d9 594
jbaker66 0:52654f3080d9 595 // first check if its already on or off
jbaker66 0:52654f3080d9 596 if (! sendParseReply("AT+CGPSPWR?", "+CGPSPWR: ", &state) )
jbaker66 0:52654f3080d9 597 return false;
jbaker66 0:52654f3080d9 598
jbaker66 0:52654f3080d9 599 if (onoff && !state) {
jbaker66 0:52654f3080d9 600 if (! sendCheckReply("AT+CGPSPWR=1", "OK"))
jbaker66 0:52654f3080d9 601 return false;
jbaker66 0:52654f3080d9 602 } else if (!onoff && state) {
jbaker66 0:52654f3080d9 603 if (! sendCheckReply("AT+CGPSPWR=0", "OK"))
jbaker66 0:52654f3080d9 604 return false;
jbaker66 0:52654f3080d9 605 }
jbaker66 0:52654f3080d9 606 return true;
jbaker66 0:52654f3080d9 607 }
jbaker66 0:52654f3080d9 608
jbaker66 0:52654f3080d9 609 int8_t Adafruit_FONA::GPSstatus(void) {
jbaker66 0:52654f3080d9 610 getReply("AT+CGPSSTATUS?");
jbaker66 0:52654f3080d9 611
jbaker66 0:52654f3080d9 612 char *p = strstr(replybuffer, "+CGPSSTATUS: Location ");
jbaker66 0:52654f3080d9 613 if (p == 0) return -1;
jbaker66 0:52654f3080d9 614
jbaker66 0:52654f3080d9 615 p+=22;
jbaker66 0:52654f3080d9 616
jbaker66 0:52654f3080d9 617 readline(); // eat 'OK'
jbaker66 0:52654f3080d9 618
jbaker66 0:52654f3080d9 619
jbaker66 0:52654f3080d9 620 if (p[0] == 'U') return 0;
jbaker66 0:52654f3080d9 621 if (p[0] == 'N') return 1;
jbaker66 0:52654f3080d9 622 if (p[0] == '2') return 2;
jbaker66 0:52654f3080d9 623 if (p[0] == '3') return 3;
jbaker66 0:52654f3080d9 624
jbaker66 0:52654f3080d9 625 // else
jbaker66 0:52654f3080d9 626 return 0;
jbaker66 0:52654f3080d9 627 }
jbaker66 0:52654f3080d9 628
jbaker66 0:52654f3080d9 629 uint8_t Adafruit_FONA::getGPS(uint8_t arg, char *buffer, uint8_t maxbuff) {
jbaker66 0:52654f3080d9 630 int32_t x = arg;
jbaker66 0:52654f3080d9 631
jbaker66 0:52654f3080d9 632 getReply("AT+CGPSINF=", x);
jbaker66 0:52654f3080d9 633
jbaker66 0:52654f3080d9 634 char *p = strstr(replybuffer, "CGPSINF: ");
jbaker66 0:52654f3080d9 635 if (p == 0){
jbaker66 0:52654f3080d9 636 buffer[0] = 0;
jbaker66 0:52654f3080d9 637 return 0;
jbaker66 0:52654f3080d9 638 }
jbaker66 0:52654f3080d9 639 p+=9;
jbaker66 0:52654f3080d9 640 uint8_t len = max((uint8_t)(maxbuff-1), (uint8_t)strlen(p));
jbaker66 0:52654f3080d9 641 strncpy(buffer, p, len);
jbaker66 0:52654f3080d9 642 buffer[len] = 0;
jbaker66 0:52654f3080d9 643
jbaker66 0:52654f3080d9 644 readline(); // eat 'OK'
jbaker66 0:52654f3080d9 645 return len;
jbaker66 0:52654f3080d9 646 }
jbaker66 0:52654f3080d9 647
jbaker66 0:52654f3080d9 648 bool Adafruit_FONA::getGPS(float *lat, float *lon, float *speed_kph, float *heading, float *altitude) {
jbaker66 0:52654f3080d9 649 char gpsbuffer[120];
jbaker66 0:52654f3080d9 650
jbaker66 0:52654f3080d9 651 // we need at least a 2D fix
jbaker66 0:52654f3080d9 652 if (GPSstatus() < 2)
jbaker66 0:52654f3080d9 653 return false;
jbaker66 0:52654f3080d9 654
jbaker66 0:52654f3080d9 655 // grab the mode 2^5 gps csv from the sim808
jbaker66 0:52654f3080d9 656 uint8_t res_len = getGPS(32, gpsbuffer, 120);
jbaker66 0:52654f3080d9 657
jbaker66 0:52654f3080d9 658 // make sure we have a response
jbaker66 0:52654f3080d9 659 if (res_len == 0)
jbaker66 0:52654f3080d9 660 return false;
jbaker66 0:52654f3080d9 661
jbaker66 0:52654f3080d9 662 // skip mode
jbaker66 0:52654f3080d9 663 char *tok = strtok(gpsbuffer, ",");
jbaker66 0:52654f3080d9 664 if (! tok) return false;
jbaker66 0:52654f3080d9 665
jbaker66 0:52654f3080d9 666 // skip date
jbaker66 0:52654f3080d9 667 tok = strtok(NULL, ",");
jbaker66 0:52654f3080d9 668 if (! tok) return false;
jbaker66 0:52654f3080d9 669
jbaker66 0:52654f3080d9 670 // skip fix
jbaker66 0:52654f3080d9 671 tok = strtok(NULL, ",");
jbaker66 0:52654f3080d9 672 if (! tok) return false;
jbaker66 0:52654f3080d9 673
jbaker66 0:52654f3080d9 674 // grab the latitude
jbaker66 0:52654f3080d9 675 char *latp = strtok(NULL, ",");
jbaker66 0:52654f3080d9 676 if (! latp) return false;
jbaker66 0:52654f3080d9 677
jbaker66 0:52654f3080d9 678 // grab latitude direction
jbaker66 0:52654f3080d9 679 char *latdir = strtok(NULL, ",");
jbaker66 0:52654f3080d9 680 if (! latdir) return false;
jbaker66 0:52654f3080d9 681
jbaker66 0:52654f3080d9 682 // grab longitude
jbaker66 0:52654f3080d9 683 char *longp = strtok(NULL, ",");
jbaker66 0:52654f3080d9 684 if (! longp) return false;
jbaker66 0:52654f3080d9 685
jbaker66 0:52654f3080d9 686 // grab longitude direction
jbaker66 0:52654f3080d9 687 char *longdir = strtok(NULL, ",");
jbaker66 0:52654f3080d9 688 if (! longdir) return false;
jbaker66 0:52654f3080d9 689
jbaker66 0:52654f3080d9 690 double latitude = atof(latp);
jbaker66 0:52654f3080d9 691 double longitude = atof(longp);
jbaker66 0:52654f3080d9 692
jbaker66 0:52654f3080d9 693 // convert latitude from minutes to decimal
jbaker66 0:52654f3080d9 694 float degrees = floor(latitude / 100);
jbaker66 0:52654f3080d9 695 double minutes = latitude - (100 * degrees);
jbaker66 0:52654f3080d9 696 minutes /= 60;
jbaker66 0:52654f3080d9 697 degrees += minutes;
jbaker66 0:52654f3080d9 698
jbaker66 0:52654f3080d9 699 // turn direction into + or -
jbaker66 0:52654f3080d9 700 if (latdir[0] == 'S') degrees *= -1;
jbaker66 0:52654f3080d9 701
jbaker66 0:52654f3080d9 702 *lat = degrees;
jbaker66 0:52654f3080d9 703
jbaker66 0:52654f3080d9 704 // convert longitude from minutes to decimal
jbaker66 0:52654f3080d9 705 degrees = floor(longitude / 100);
jbaker66 0:52654f3080d9 706 minutes = longitude - (100 * degrees);
jbaker66 0:52654f3080d9 707 minutes /= 60;
jbaker66 0:52654f3080d9 708 degrees += minutes;
jbaker66 0:52654f3080d9 709
jbaker66 0:52654f3080d9 710 // turn direction into + or -
jbaker66 0:52654f3080d9 711 if (longdir[0] == 'W') degrees *= -1;
jbaker66 0:52654f3080d9 712
jbaker66 0:52654f3080d9 713 *lon = degrees;
jbaker66 0:52654f3080d9 714
jbaker66 0:52654f3080d9 715 // only grab speed if needed
jbaker66 0:52654f3080d9 716 if (speed_kph != NULL) {
jbaker66 0:52654f3080d9 717
jbaker66 0:52654f3080d9 718 // grab the speed in knots
jbaker66 0:52654f3080d9 719 char *speedp = strtok(NULL, ",");
jbaker66 0:52654f3080d9 720 if (! speedp) return false;
jbaker66 0:52654f3080d9 721
jbaker66 0:52654f3080d9 722 // convert to kph
jbaker66 0:52654f3080d9 723 *speed_kph = atof(speedp) * 1.852;
jbaker66 0:52654f3080d9 724
jbaker66 0:52654f3080d9 725 }
jbaker66 0:52654f3080d9 726
jbaker66 0:52654f3080d9 727 // only grab heading if needed
jbaker66 0:52654f3080d9 728 if (heading != NULL) {
jbaker66 0:52654f3080d9 729
jbaker66 0:52654f3080d9 730 // grab the speed in knots
jbaker66 0:52654f3080d9 731 char *coursep = strtok(NULL, ",");
jbaker66 0:52654f3080d9 732 if (! coursep) return false;
jbaker66 0:52654f3080d9 733
jbaker66 0:52654f3080d9 734 *heading = atof(coursep);
jbaker66 0:52654f3080d9 735
jbaker66 0:52654f3080d9 736 }
jbaker66 0:52654f3080d9 737
jbaker66 0:52654f3080d9 738 // no need to continue
jbaker66 0:52654f3080d9 739 if (altitude == NULL)
jbaker66 0:52654f3080d9 740 return true;
jbaker66 0:52654f3080d9 741
jbaker66 0:52654f3080d9 742 // we need at least a 3D fix for altitude
jbaker66 0:52654f3080d9 743 if (GPSstatus() < 3)
jbaker66 0:52654f3080d9 744 return false;
jbaker66 0:52654f3080d9 745
jbaker66 0:52654f3080d9 746 // grab the mode 0 gps csv from the sim808
jbaker66 0:52654f3080d9 747 res_len = getGPS(0, gpsbuffer, 120);
jbaker66 0:52654f3080d9 748
jbaker66 0:52654f3080d9 749 // make sure we have a response
jbaker66 0:52654f3080d9 750 if (res_len == 0)
jbaker66 0:52654f3080d9 751 return false;
jbaker66 0:52654f3080d9 752
jbaker66 0:52654f3080d9 753 // skip mode
jbaker66 0:52654f3080d9 754 tok = strtok(gpsbuffer, ",");
jbaker66 0:52654f3080d9 755 if (! tok) return false;
jbaker66 0:52654f3080d9 756
jbaker66 0:52654f3080d9 757 // skip lat
jbaker66 0:52654f3080d9 758 tok = strtok(NULL, ",");
jbaker66 0:52654f3080d9 759 if (! tok) return false;
jbaker66 0:52654f3080d9 760
jbaker66 0:52654f3080d9 761 // skip long
jbaker66 0:52654f3080d9 762 tok = strtok(NULL, ",");
jbaker66 0:52654f3080d9 763 if (! tok) return false;
jbaker66 0:52654f3080d9 764
jbaker66 0:52654f3080d9 765 // grab altitude
jbaker66 0:52654f3080d9 766 char *altp = strtok(NULL, ",");
jbaker66 0:52654f3080d9 767 if (! altp) return false;
jbaker66 0:52654f3080d9 768
jbaker66 0:52654f3080d9 769 *altitude = atof(altp);
jbaker66 0:52654f3080d9 770
jbaker66 0:52654f3080d9 771 return true;
jbaker66 0:52654f3080d9 772 }
jbaker66 0:52654f3080d9 773
jbaker66 0:52654f3080d9 774 bool Adafruit_FONA::enableGPSNMEA(uint8_t i) {
jbaker66 0:52654f3080d9 775 char sendbuff[15] = "AT+CGPSOUT=000";
jbaker66 0:52654f3080d9 776 sendbuff[11] = (i / 100) + '0';
jbaker66 0:52654f3080d9 777 i %= 100;
jbaker66 0:52654f3080d9 778 sendbuff[12] = (i / 10) + '0';
jbaker66 0:52654f3080d9 779 i %= 10;
jbaker66 0:52654f3080d9 780 sendbuff[13] = i + '0';
jbaker66 0:52654f3080d9 781
jbaker66 0:52654f3080d9 782 return sendCheckReply(sendbuff, "OK", 2000);
jbaker66 0:52654f3080d9 783 }
jbaker66 0:52654f3080d9 784
jbaker66 0:52654f3080d9 785
jbaker66 0:52654f3080d9 786 /********* GPRS **********************************************************/
jbaker66 0:52654f3080d9 787
jbaker66 0:52654f3080d9 788
jbaker66 0:52654f3080d9 789 bool Adafruit_FONA::enableGPRS(bool onoff) {
jbaker66 0:52654f3080d9 790 if (onoff) {
jbaker66 0:52654f3080d9 791 // disconnect all sockets
jbaker66 0:52654f3080d9 792 sendCheckReply("AT+CIPSHUT", "SHUT OK", 5000);
jbaker66 0:52654f3080d9 793
jbaker66 0:52654f3080d9 794 if (! sendCheckReply("AT+CGATT=1", "OK", 10000))
jbaker66 0:52654f3080d9 795 return false;
jbaker66 0:52654f3080d9 796
jbaker66 0:52654f3080d9 797 // set bearer profile! connection type GPRS
jbaker66 0:52654f3080d9 798 if (! sendCheckReply("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"", "OK", 10000))
jbaker66 0:52654f3080d9 799 return false;
jbaker66 0:52654f3080d9 800
jbaker66 0:52654f3080d9 801 // set bearer profile access point name
jbaker66 0:52654f3080d9 802 if (apn) {
jbaker66 0:52654f3080d9 803 // Send command AT+SAPBR=3,1,"APN","<apn value>" where <apn value> is the configured APN value.
jbaker66 0:52654f3080d9 804 if (! sendCheckReplyQuoted("AT+SAPBR=3,1,\"APN\",", apn, "OK", 10000))
jbaker66 0:52654f3080d9 805 return false;
jbaker66 0:52654f3080d9 806
jbaker66 0:52654f3080d9 807 // set username/password
jbaker66 0:52654f3080d9 808 if (apnusername) {
jbaker66 0:52654f3080d9 809 // Send command AT+SAPBR=3,1,"USER","<user>" where <user> is the configured APN username.
jbaker66 0:52654f3080d9 810 if (! sendCheckReplyQuoted("AT+SAPBR=3,1,\"USER\",", apnusername, "OK", 10000))
jbaker66 0:52654f3080d9 811 return false;
jbaker66 0:52654f3080d9 812 }
jbaker66 0:52654f3080d9 813 if (apnpassword) {
jbaker66 0:52654f3080d9 814 // Send command AT+SAPBR=3,1,"PWD","<password>" where <password> is the configured APN password.
jbaker66 0:52654f3080d9 815 if (! sendCheckReplyQuoted("AT+SAPBR=3,1,\"PWD\",", apnpassword, "OK", 10000))
jbaker66 0:52654f3080d9 816 return false;
jbaker66 0:52654f3080d9 817 }
jbaker66 0:52654f3080d9 818 }
jbaker66 0:52654f3080d9 819
jbaker66 0:52654f3080d9 820 // open GPRS context
jbaker66 0:52654f3080d9 821 if (! sendCheckReply("AT+SAPBR=1,1", "OK", 10000))
jbaker66 0:52654f3080d9 822 return false;
jbaker66 0:52654f3080d9 823 } else {
jbaker66 0:52654f3080d9 824 // disconnect all sockets
jbaker66 0:52654f3080d9 825 if (! sendCheckReply("AT+CIPSHUT", "SHUT OK", 5000))
jbaker66 0:52654f3080d9 826 return false;
jbaker66 0:52654f3080d9 827
jbaker66 0:52654f3080d9 828 // close GPRS context
jbaker66 0:52654f3080d9 829 if (! sendCheckReply("AT+SAPBR=0,1", "OK", 10000))
jbaker66 0:52654f3080d9 830 return false;
jbaker66 0:52654f3080d9 831
jbaker66 0:52654f3080d9 832 if (! sendCheckReply("AT+CGATT=0", "OK", 10000))
jbaker66 0:52654f3080d9 833 return false;
jbaker66 0:52654f3080d9 834 }
jbaker66 0:52654f3080d9 835 return true;
jbaker66 0:52654f3080d9 836 }
jbaker66 0:52654f3080d9 837
jbaker66 0:52654f3080d9 838 uint8_t Adafruit_FONA::GPRSstate(void) {
jbaker66 0:52654f3080d9 839 uint16_t state;
jbaker66 0:52654f3080d9 840
jbaker66 0:52654f3080d9 841 if (! sendParseReply("AT+CGATT?", "+CGATT: ", &state) )
jbaker66 0:52654f3080d9 842 return -1;
jbaker66 0:52654f3080d9 843
jbaker66 0:52654f3080d9 844 return state;
jbaker66 0:52654f3080d9 845 }
jbaker66 0:52654f3080d9 846
jbaker66 0:52654f3080d9 847 void Adafruit_FONA::setGPRSNetworkSettings(const char* apn, const char* ausername, const char* apassword) {
jbaker66 0:52654f3080d9 848 this->apn = (char*) apn;
jbaker66 0:52654f3080d9 849 this->apnusername = (char*) ausername;
jbaker66 0:52654f3080d9 850 this->apnpassword = (char*) apassword;
jbaker66 0:52654f3080d9 851 }
jbaker66 0:52654f3080d9 852
jbaker66 0:52654f3080d9 853 bool Adafruit_FONA::getGSMLoc(uint16_t *errorcode, char *buff, uint16_t maxlen) {
jbaker66 0:52654f3080d9 854 getReply("AT+CIPGSMLOC=1,1", (uint16_t)10000);
jbaker66 0:52654f3080d9 855
jbaker66 0:52654f3080d9 856 if (! parseReply("+CIPGSMLOC: ", errorcode))
jbaker66 0:52654f3080d9 857 return false;
jbaker66 0:52654f3080d9 858
jbaker66 0:52654f3080d9 859 char *p = replybuffer+14;
jbaker66 0:52654f3080d9 860 uint16_t lentocopy = min((uint16_t)(maxlen-1), (uint16_t)strlen(p));
jbaker66 0:52654f3080d9 861 strncpy(buff, p, lentocopy+1);
jbaker66 0:52654f3080d9 862
jbaker66 0:52654f3080d9 863 readline(); // eat OK
jbaker66 0:52654f3080d9 864
jbaker66 0:52654f3080d9 865 return true;
jbaker66 0:52654f3080d9 866 }
jbaker66 0:52654f3080d9 867
jbaker66 0:52654f3080d9 868 bool Adafruit_FONA::getGSMLoc(float *lat, float *lon) {
jbaker66 0:52654f3080d9 869 uint16_t returncode;
jbaker66 0:52654f3080d9 870 char gpsbuffer[120];
jbaker66 0:52654f3080d9 871
jbaker66 0:52654f3080d9 872 // make sure we could get a response
jbaker66 0:52654f3080d9 873 if (! getGSMLoc(&returncode, gpsbuffer, 120))
jbaker66 0:52654f3080d9 874 return false;
jbaker66 0:52654f3080d9 875
jbaker66 0:52654f3080d9 876 // make sure we have a valid return code
jbaker66 0:52654f3080d9 877 if (returncode != 0)
jbaker66 0:52654f3080d9 878 return false;
jbaker66 0:52654f3080d9 879
jbaker66 0:52654f3080d9 880 // tokenize the gps buffer to locate the lat & long
jbaker66 0:52654f3080d9 881 char *latp = strtok(gpsbuffer, ",");
jbaker66 0:52654f3080d9 882 if (! latp) return false;
jbaker66 0:52654f3080d9 883
jbaker66 0:52654f3080d9 884 char *longp = strtok(NULL, ",");
jbaker66 0:52654f3080d9 885 if (! longp) return false;
jbaker66 0:52654f3080d9 886
jbaker66 0:52654f3080d9 887 *lat = atof(latp);
jbaker66 0:52654f3080d9 888 *lon = atof(longp);
jbaker66 0:52654f3080d9 889
jbaker66 0:52654f3080d9 890 return true;
jbaker66 0:52654f3080d9 891 }
jbaker66 0:52654f3080d9 892
jbaker66 0:52654f3080d9 893 /********* TCP FUNCTIONS ************************************/
jbaker66 0:52654f3080d9 894
jbaker66 0:52654f3080d9 895
jbaker66 0:52654f3080d9 896 bool Adafruit_FONA::TCPconnect(char *server, uint16_t port) {
jbaker66 0:52654f3080d9 897 flushInput();
jbaker66 0:52654f3080d9 898
jbaker66 0:52654f3080d9 899 // close all old connections
jbaker66 0:52654f3080d9 900 if (! sendCheckReply("AT+CIPSHUT", "SHUT OK", 5000) ) return false;
jbaker66 0:52654f3080d9 901
jbaker66 0:52654f3080d9 902 // single connection at a time
jbaker66 0:52654f3080d9 903 if (! sendCheckReply("AT+CIPMUX=0", "OK") ) return false;
jbaker66 0:52654f3080d9 904
jbaker66 0:52654f3080d9 905 // manually read data
jbaker66 0:52654f3080d9 906 if (! sendCheckReply("AT+CIPRXGET=1", "OK") ) return false;
jbaker66 0:52654f3080d9 907
jbaker66 0:52654f3080d9 908 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 909 printf("AT+CIPSTART=\"TCP\",\"%s\",\"%d\"\r\n", server, port);
jbaker66 0:52654f3080d9 910 #endif
jbaker66 0:52654f3080d9 911
jbaker66 0:52654f3080d9 912 mySerial.printf("AT+CIPSTART=\"TCP\",\"%s\",\"%d\"\r\n", server, port);
jbaker66 0:52654f3080d9 913
jbaker66 0:52654f3080d9 914 if (! expectReply("OK")) return false;
jbaker66 0:52654f3080d9 915 if (! expectReply("CONNECT OK")) return false;
jbaker66 0:52654f3080d9 916 return true;
jbaker66 0:52654f3080d9 917 }
jbaker66 0:52654f3080d9 918
jbaker66 0:52654f3080d9 919 bool Adafruit_FONA::TCPclose(void) {
jbaker66 0:52654f3080d9 920 return sendCheckReply("AT+CIPCLOSE", "OK");
jbaker66 0:52654f3080d9 921 }
jbaker66 0:52654f3080d9 922
jbaker66 0:52654f3080d9 923 bool Adafruit_FONA::TCPconnected(void) {
jbaker66 0:52654f3080d9 924 if (! sendCheckReply("AT+CIPSTATUS", "OK", 100) ) return false;
jbaker66 0:52654f3080d9 925 readline(100);
jbaker66 0:52654f3080d9 926 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 927 printf("\t<--- %s\r\n", replybuffer);
jbaker66 0:52654f3080d9 928 #endif
jbaker66 0:52654f3080d9 929 return (strcmp(replybuffer, "STATE: CONNECT OK") == 0);
jbaker66 0:52654f3080d9 930 }
jbaker66 0:52654f3080d9 931
jbaker66 0:52654f3080d9 932 bool Adafruit_FONA::TCPsend(char *packet, uint8_t len) {
jbaker66 0:52654f3080d9 933 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 934 printf("AT+CIPSEND=%d\r\n", len);
jbaker66 0:52654f3080d9 935
jbaker66 0:52654f3080d9 936 for (uint16_t i=0; i<len; i++) {
jbaker66 0:52654f3080d9 937 printf(" 0x%#02x", packet[i]);
jbaker66 0:52654f3080d9 938 }
jbaker66 0:52654f3080d9 939 printf("\r\n");
jbaker66 0:52654f3080d9 940 #endif
jbaker66 0:52654f3080d9 941
jbaker66 0:52654f3080d9 942
jbaker66 0:52654f3080d9 943 mySerial.printf("AT+CIPSEND=%d\r\n", len);
jbaker66 0:52654f3080d9 944 readline();
jbaker66 0:52654f3080d9 945 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 946 printf("\t<--- %s\r\n", replybuffer);
jbaker66 0:52654f3080d9 947 #endif
jbaker66 0:52654f3080d9 948 if (replybuffer[0] != '>') return false;
jbaker66 0:52654f3080d9 949
jbaker66 0:52654f3080d9 950 for (uint16_t i=0; i<len; i++) {
jbaker66 0:52654f3080d9 951 mySerial.putc(packet[i]);
jbaker66 0:52654f3080d9 952 }
jbaker66 0:52654f3080d9 953 readline(3000); // wait up to 3 seconds to send the data
jbaker66 0:52654f3080d9 954 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 955 printf("\t<--- %s\r\n", replybuffer);
jbaker66 0:52654f3080d9 956 #endif
jbaker66 0:52654f3080d9 957
jbaker66 0:52654f3080d9 958 return (strcmp(replybuffer, "SEND OK") == 0);
jbaker66 0:52654f3080d9 959 }
jbaker66 0:52654f3080d9 960
jbaker66 0:52654f3080d9 961 uint16_t Adafruit_FONA::TCPavailable(void) {
jbaker66 0:52654f3080d9 962 uint16_t avail;
jbaker66 0:52654f3080d9 963
jbaker66 0:52654f3080d9 964 if (! sendParseReply("AT+CIPRXGET=4", "+CIPRXGET: 4,", &avail, ',', 0) ) return false;
jbaker66 0:52654f3080d9 965
jbaker66 0:52654f3080d9 966 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 967 printf("%d bytes available\r\n", avail);
jbaker66 0:52654f3080d9 968 #endif
jbaker66 0:52654f3080d9 969
jbaker66 0:52654f3080d9 970 return avail;
jbaker66 0:52654f3080d9 971 }
jbaker66 0:52654f3080d9 972
jbaker66 0:52654f3080d9 973
jbaker66 0:52654f3080d9 974 uint16_t Adafruit_FONA::TCPread(uint8_t *buff, uint8_t len) {
jbaker66 0:52654f3080d9 975 uint16_t avail;
jbaker66 0:52654f3080d9 976
jbaker66 0:52654f3080d9 977 mySerial.printf("AT+CIPRXGET=2,%d\r\n", len);
jbaker66 0:52654f3080d9 978 readline();
jbaker66 0:52654f3080d9 979 if (! parseReply("+CIPRXGET: 2,", &avail, ',', 0)) return false;
jbaker66 0:52654f3080d9 980
jbaker66 0:52654f3080d9 981 readRaw(avail);
jbaker66 0:52654f3080d9 982
jbaker66 0:52654f3080d9 983 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 984 printf("%d bytes read\r\n", avail);
jbaker66 0:52654f3080d9 985 for (uint8_t i=0;i<avail;i++) {
jbaker66 0:52654f3080d9 986 printf(" 0x%#02x", replybuffer[i]);
jbaker66 0:52654f3080d9 987 }
jbaker66 0:52654f3080d9 988 printf("\r\n");
jbaker66 0:52654f3080d9 989 #endif
jbaker66 0:52654f3080d9 990
jbaker66 0:52654f3080d9 991 memcpy(buff, replybuffer, avail);
jbaker66 0:52654f3080d9 992
jbaker66 0:52654f3080d9 993 return avail;
jbaker66 0:52654f3080d9 994 }
jbaker66 0:52654f3080d9 995
jbaker66 0:52654f3080d9 996 /********* HTTP LOW LEVEL FUNCTIONS ************************************/
jbaker66 0:52654f3080d9 997
jbaker66 0:52654f3080d9 998 bool Adafruit_FONA::HTTP_init() {
jbaker66 0:52654f3080d9 999 return sendCheckReply("AT+HTTPINIT", "OK");
jbaker66 0:52654f3080d9 1000 }
jbaker66 0:52654f3080d9 1001
jbaker66 0:52654f3080d9 1002 bool Adafruit_FONA::HTTP_term() {
jbaker66 0:52654f3080d9 1003 return sendCheckReply("AT+HTTPTERM", "OK");
jbaker66 0:52654f3080d9 1004 }
jbaker66 0:52654f3080d9 1005
jbaker66 0:52654f3080d9 1006 void Adafruit_FONA::HTTP_para_start(const char* parameter, bool quoted) {
jbaker66 0:52654f3080d9 1007 flushInput();
jbaker66 0:52654f3080d9 1008
jbaker66 0:52654f3080d9 1009 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 1010 printf("\t---> AT+HTTPPARA=\"%s\"\r\n", parameter);
jbaker66 0:52654f3080d9 1011 #endif
jbaker66 0:52654f3080d9 1012
jbaker66 0:52654f3080d9 1013 mySerial.printf("AT+HTTPPARA=\"%s", parameter);
jbaker66 0:52654f3080d9 1014 if (quoted)
jbaker66 0:52654f3080d9 1015 mySerial.printf("\",\"");
jbaker66 0:52654f3080d9 1016 else
jbaker66 0:52654f3080d9 1017 mySerial.printf("\",");
jbaker66 0:52654f3080d9 1018 }
jbaker66 0:52654f3080d9 1019
jbaker66 0:52654f3080d9 1020 bool Adafruit_FONA::HTTP_para_end(bool quoted) {
jbaker66 0:52654f3080d9 1021 if (quoted)
jbaker66 0:52654f3080d9 1022 mySerial.printf("\"\r\n");
jbaker66 0:52654f3080d9 1023 else
jbaker66 0:52654f3080d9 1024 mySerial.printf("\r\n");
jbaker66 0:52654f3080d9 1025
jbaker66 0:52654f3080d9 1026 return expectReply("OK");
jbaker66 0:52654f3080d9 1027 }
jbaker66 0:52654f3080d9 1028
jbaker66 0:52654f3080d9 1029 bool Adafruit_FONA::HTTP_para(const char* parameter, const char* value) {
jbaker66 0:52654f3080d9 1030 HTTP_para_start(parameter, true);
jbaker66 0:52654f3080d9 1031 mySerial.printf(value);
jbaker66 0:52654f3080d9 1032 return HTTP_para_end(true);
jbaker66 0:52654f3080d9 1033 }
jbaker66 0:52654f3080d9 1034
jbaker66 0:52654f3080d9 1035 bool Adafruit_FONA::HTTP_para(const char* parameter, int32_t value) {
jbaker66 0:52654f3080d9 1036 HTTP_para_start(parameter, false);
jbaker66 0:52654f3080d9 1037 mySerial.printf("%d", value);
jbaker66 0:52654f3080d9 1038 return HTTP_para_end(false);
jbaker66 0:52654f3080d9 1039 }
jbaker66 0:52654f3080d9 1040
jbaker66 0:52654f3080d9 1041 bool Adafruit_FONA::HTTP_data(uint32_t size, uint32_t maxTime) {
jbaker66 0:52654f3080d9 1042 flushInput();
jbaker66 0:52654f3080d9 1043
jbaker66 0:52654f3080d9 1044 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 1045 printf("\t---> AT+HTTPDATA=%d,%d\r\n", size, maxTime);
jbaker66 0:52654f3080d9 1046 #endif
jbaker66 0:52654f3080d9 1047
jbaker66 0:52654f3080d9 1048 mySerial.printf("AT+HTTPDATA=%d,%d\r\n", size, maxTime);
jbaker66 0:52654f3080d9 1049
jbaker66 0:52654f3080d9 1050 return expectReply("DOWNLOAD");
jbaker66 0:52654f3080d9 1051 }
jbaker66 0:52654f3080d9 1052
jbaker66 0:52654f3080d9 1053 bool Adafruit_FONA::HTTP_action(uint8_t method, uint16_t *status, uint16_t *datalen, int32_t timeout) {
jbaker66 0:52654f3080d9 1054 // Send request.
jbaker66 0:52654f3080d9 1055 if (! sendCheckReply("AT+HTTPACTION=", method, "OK"))
jbaker66 0:52654f3080d9 1056 return false;
jbaker66 0:52654f3080d9 1057
jbaker66 0:52654f3080d9 1058 // Parse response status and size.
jbaker66 0:52654f3080d9 1059 readline(timeout);
jbaker66 0:52654f3080d9 1060 if (! parseReply("+HTTPACTION:", status, ',', 1))
jbaker66 0:52654f3080d9 1061 return false;
jbaker66 0:52654f3080d9 1062 if (! parseReply("+HTTPACTION:", datalen, ',', 2))
jbaker66 0:52654f3080d9 1063 return false;
jbaker66 0:52654f3080d9 1064
jbaker66 0:52654f3080d9 1065 return true;
jbaker66 0:52654f3080d9 1066 }
jbaker66 0:52654f3080d9 1067
jbaker66 0:52654f3080d9 1068 bool Adafruit_FONA::HTTP_readall(uint16_t *datalen) {
jbaker66 0:52654f3080d9 1069 getReply("AT+HTTPREAD");
jbaker66 0:52654f3080d9 1070 if (! parseReply("+HTTPREAD:", datalen, ',', 0))
jbaker66 0:52654f3080d9 1071 return false;
jbaker66 0:52654f3080d9 1072
jbaker66 0:52654f3080d9 1073 return true;
jbaker66 0:52654f3080d9 1074 }
jbaker66 0:52654f3080d9 1075
jbaker66 0:52654f3080d9 1076 bool Adafruit_FONA::HTTP_ssl(bool onoff) {
jbaker66 0:52654f3080d9 1077 return sendCheckReply("AT+HTTPSSL=", onoff ? 1 : 0, "OK");
jbaker66 0:52654f3080d9 1078 }
jbaker66 0:52654f3080d9 1079
jbaker66 0:52654f3080d9 1080 /********* HTTP HIGH LEVEL FUNCTIONS ***************************/
jbaker66 0:52654f3080d9 1081
jbaker66 0:52654f3080d9 1082 bool Adafruit_FONA::HTTP_GET_start(char *url, uint16_t *status, uint16_t *datalen){
jbaker66 0:52654f3080d9 1083 if (! HTTP_setup(url))
jbaker66 0:52654f3080d9 1084 return false;
jbaker66 0:52654f3080d9 1085
jbaker66 0:52654f3080d9 1086 // HTTP GET
jbaker66 0:52654f3080d9 1087 if (! HTTP_action(FONA_HTTP_GET, status, datalen))
jbaker66 0:52654f3080d9 1088 return false;
jbaker66 0:52654f3080d9 1089
jbaker66 0:52654f3080d9 1090 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 1091 printf("Status: %d\r\n", *status);
jbaker66 0:52654f3080d9 1092 printf("Len: %d\r\n", *datalen);
jbaker66 0:52654f3080d9 1093 #endif
jbaker66 0:52654f3080d9 1094
jbaker66 0:52654f3080d9 1095 // HTTP response data
jbaker66 0:52654f3080d9 1096 if (! HTTP_readall(datalen))
jbaker66 0:52654f3080d9 1097 return false;
jbaker66 0:52654f3080d9 1098
jbaker66 0:52654f3080d9 1099 return true;
jbaker66 0:52654f3080d9 1100 }
jbaker66 0:52654f3080d9 1101
jbaker66 0:52654f3080d9 1102 void Adafruit_FONA::HTTP_GET_end(void) {
jbaker66 0:52654f3080d9 1103 HTTP_term();
jbaker66 0:52654f3080d9 1104 }
jbaker66 0:52654f3080d9 1105
jbaker66 0:52654f3080d9 1106 bool Adafruit_FONA::HTTP_POST_start(char *url, const char* contenttype, const uint8_t *postdata, uint16_t postdatalen, uint16_t *status, uint16_t *datalen) {
jbaker66 0:52654f3080d9 1107 if (! HTTP_setup(url))
jbaker66 0:52654f3080d9 1108 return false;
jbaker66 0:52654f3080d9 1109
jbaker66 0:52654f3080d9 1110 if (! HTTP_para("CONTENT", contenttype)) {
jbaker66 0:52654f3080d9 1111 return false;
jbaker66 0:52654f3080d9 1112 }
jbaker66 0:52654f3080d9 1113
jbaker66 0:52654f3080d9 1114 // HTTP POST data
jbaker66 0:52654f3080d9 1115 if (! HTTP_data(postdatalen, 10000))
jbaker66 0:52654f3080d9 1116 return false;
jbaker66 0:52654f3080d9 1117 for (uint16_t i = 0; i < postdatalen; i++) {
jbaker66 0:52654f3080d9 1118 mySerial.putc(postdata[i]);
jbaker66 0:52654f3080d9 1119 }
jbaker66 0:52654f3080d9 1120 if (! expectReply("OK"))
jbaker66 0:52654f3080d9 1121 return false;
jbaker66 0:52654f3080d9 1122
jbaker66 0:52654f3080d9 1123 // HTTP POST
jbaker66 0:52654f3080d9 1124 if (! HTTP_action(FONA_HTTP_POST, status, datalen))
jbaker66 0:52654f3080d9 1125 return false;
jbaker66 0:52654f3080d9 1126
jbaker66 0:52654f3080d9 1127 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 1128 printf("Status: %d\r\n", *status);
jbaker66 0:52654f3080d9 1129 printf("Len: %d\r\n", *datalen);
jbaker66 0:52654f3080d9 1130 #endif
jbaker66 0:52654f3080d9 1131
jbaker66 0:52654f3080d9 1132 // HTTP response data
jbaker66 0:52654f3080d9 1133 if (! HTTP_readall(datalen))
jbaker66 0:52654f3080d9 1134 return false;
jbaker66 0:52654f3080d9 1135
jbaker66 0:52654f3080d9 1136 return true;
jbaker66 0:52654f3080d9 1137 }
jbaker66 0:52654f3080d9 1138
jbaker66 0:52654f3080d9 1139 void Adafruit_FONA::HTTP_POST_end(void) {
jbaker66 0:52654f3080d9 1140 HTTP_term();
jbaker66 0:52654f3080d9 1141 }
jbaker66 0:52654f3080d9 1142
jbaker66 0:52654f3080d9 1143 void Adafruit_FONA::setUserAgent(const char* useragent) {
jbaker66 0:52654f3080d9 1144 this->useragent = (char*) useragent;
jbaker66 0:52654f3080d9 1145 }
jbaker66 0:52654f3080d9 1146
jbaker66 0:52654f3080d9 1147 void Adafruit_FONA::setHTTPSRedirect(bool onoff) {
jbaker66 0:52654f3080d9 1148 httpsredirect = onoff;
jbaker66 0:52654f3080d9 1149 }
jbaker66 0:52654f3080d9 1150
jbaker66 0:52654f3080d9 1151 /********* HTTP HELPERS ****************************************/
jbaker66 0:52654f3080d9 1152
jbaker66 0:52654f3080d9 1153 bool Adafruit_FONA::HTTP_setup(char *url) {
jbaker66 0:52654f3080d9 1154 // Handle any pending
jbaker66 0:52654f3080d9 1155 HTTP_term();
jbaker66 0:52654f3080d9 1156
jbaker66 0:52654f3080d9 1157 // Initialize and set parameters
jbaker66 0:52654f3080d9 1158 if (! HTTP_init())
jbaker66 0:52654f3080d9 1159 return false;
jbaker66 0:52654f3080d9 1160 if (! HTTP_para("CID", 1))
jbaker66 0:52654f3080d9 1161 return false;
jbaker66 0:52654f3080d9 1162 if (! HTTP_para("UA", useragent))
jbaker66 0:52654f3080d9 1163 return false;
jbaker66 0:52654f3080d9 1164 if (! HTTP_para("URL", url))
jbaker66 0:52654f3080d9 1165 return false;
jbaker66 0:52654f3080d9 1166
jbaker66 0:52654f3080d9 1167 // HTTPS redirect
jbaker66 0:52654f3080d9 1168 if (httpsredirect) {
jbaker66 0:52654f3080d9 1169 if (! HTTP_para("REDIR",1))
jbaker66 0:52654f3080d9 1170 return false;
jbaker66 0:52654f3080d9 1171
jbaker66 0:52654f3080d9 1172 if (! HTTP_ssl(true))
jbaker66 0:52654f3080d9 1173 return false;
jbaker66 0:52654f3080d9 1174 }
jbaker66 0:52654f3080d9 1175
jbaker66 0:52654f3080d9 1176 return true;
jbaker66 0:52654f3080d9 1177 }
jbaker66 0:52654f3080d9 1178
jbaker66 0:52654f3080d9 1179
jbaker66 0:52654f3080d9 1180 /********* HELPERS *********************************************/
jbaker66 0:52654f3080d9 1181
jbaker66 0:52654f3080d9 1182 bool Adafruit_FONA::expectReply(const char* reply, uint16_t timeout) {
jbaker66 0:52654f3080d9 1183 readline(timeout);
jbaker66 0:52654f3080d9 1184 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 1185 printf("\t<--- %s\r\n", replybuffer);
jbaker66 0:52654f3080d9 1186 #endif
jbaker66 0:52654f3080d9 1187 return (strcmp(replybuffer, reply) == 0);
jbaker66 0:52654f3080d9 1188 }
jbaker66 0:52654f3080d9 1189
jbaker66 0:52654f3080d9 1190 /********* LOW LEVEL *******************************************/
jbaker66 0:52654f3080d9 1191
jbaker66 0:52654f3080d9 1192 void Adafruit_FONA::flushInput() {
jbaker66 0:52654f3080d9 1193 // Read all available serial input to flush pending data.
jbaker66 0:52654f3080d9 1194 uint16_t timeoutloop = 0;
jbaker66 0:52654f3080d9 1195 while (timeoutloop++ < 40) {
jbaker66 0:52654f3080d9 1196 while(readable()) {
jbaker66 0:52654f3080d9 1197 getc();
jbaker66 0:52654f3080d9 1198 timeoutloop = 0; // If char was received reset the timer
jbaker66 0:52654f3080d9 1199 }
zathorix 3:7916fb0cc4b0 1200 Thread::wait(1);
jbaker66 0:52654f3080d9 1201 }
jbaker66 0:52654f3080d9 1202 }
jbaker66 0:52654f3080d9 1203
jbaker66 0:52654f3080d9 1204 uint16_t Adafruit_FONA::readRaw(uint16_t b) {
jbaker66 0:52654f3080d9 1205 uint16_t idx = 0;
jbaker66 0:52654f3080d9 1206
jbaker66 0:52654f3080d9 1207 while (b && (idx < sizeof(replybuffer)-1)) {
jbaker66 0:52654f3080d9 1208 if (readable()) {
jbaker66 0:52654f3080d9 1209 replybuffer[idx] = getc();
jbaker66 0:52654f3080d9 1210 idx++;
jbaker66 0:52654f3080d9 1211 b--;
jbaker66 0:52654f3080d9 1212 }
jbaker66 0:52654f3080d9 1213 }
jbaker66 0:52654f3080d9 1214 replybuffer[idx] = 0;
jbaker66 0:52654f3080d9 1215
jbaker66 0:52654f3080d9 1216 return idx;
jbaker66 0:52654f3080d9 1217 }
jbaker66 0:52654f3080d9 1218
jbaker66 0:52654f3080d9 1219 // This function just reads the output from FONA after an AT command is sent to it
jbaker66 0:52654f3080d9 1220 uint8_t Adafruit_FONA::readline(uint16_t timeout, bool multiline) {
jbaker66 0:52654f3080d9 1221 uint16_t replyidx = 0;
jbaker66 0:52654f3080d9 1222
jbaker66 0:52654f3080d9 1223 while (timeout--) {
jbaker66 0:52654f3080d9 1224 if (replyidx >= 254) {
jbaker66 0:52654f3080d9 1225 break;
jbaker66 0:52654f3080d9 1226 }
jbaker66 0:52654f3080d9 1227
jbaker66 0:52654f3080d9 1228 while(readable()) {
jbaker66 0:52654f3080d9 1229 char c = getc();
jbaker66 0:52654f3080d9 1230 if (c == '\r') continue;
jbaker66 0:52654f3080d9 1231 if (c == 0xA) {
jbaker66 0:52654f3080d9 1232 if (replyidx == 0) // the first 0x0A is ignored
jbaker66 0:52654f3080d9 1233 continue;
jbaker66 0:52654f3080d9 1234
jbaker66 0:52654f3080d9 1235 if (!multiline) {
jbaker66 0:52654f3080d9 1236 timeout = 0; // the second 0x0A is the end of the line
jbaker66 0:52654f3080d9 1237 break;
jbaker66 0:52654f3080d9 1238 }
jbaker66 0:52654f3080d9 1239 }
jbaker66 0:52654f3080d9 1240 replybuffer[replyidx] = c;
jbaker66 0:52654f3080d9 1241 replyidx++;
jbaker66 0:52654f3080d9 1242 }
jbaker66 0:52654f3080d9 1243
jbaker66 0:52654f3080d9 1244 if (timeout == 0) {
jbaker66 0:52654f3080d9 1245 break;
jbaker66 0:52654f3080d9 1246 }
zathorix 3:7916fb0cc4b0 1247 Thread::wait(1);
jbaker66 0:52654f3080d9 1248 }
jbaker66 0:52654f3080d9 1249 replybuffer[replyidx] = 0; // null term
jbaker66 0:52654f3080d9 1250 return replyidx;
jbaker66 0:52654f3080d9 1251 }
jbaker66 0:52654f3080d9 1252
jbaker66 0:52654f3080d9 1253 uint8_t Adafruit_FONA::getReply(const char* send, uint16_t timeout) {
jbaker66 0:52654f3080d9 1254 flushInput();
jbaker66 0:52654f3080d9 1255
jbaker66 0:52654f3080d9 1256 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 1257 printf("\t---> %s\r\n", send);
jbaker66 0:52654f3080d9 1258 #endif
jbaker66 0:52654f3080d9 1259
jbaker66 0:52654f3080d9 1260 mySerial.printf("%s\r\n",send);
jbaker66 0:52654f3080d9 1261
jbaker66 0:52654f3080d9 1262 uint8_t l = readline(timeout);
jbaker66 0:52654f3080d9 1263 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 1264 printf("\t<--- %s\r\n", replybuffer);
jbaker66 0:52654f3080d9 1265 #endif
jbaker66 0:52654f3080d9 1266 return l;
jbaker66 0:52654f3080d9 1267 }
jbaker66 0:52654f3080d9 1268
jbaker66 0:52654f3080d9 1269 // Send prefix, suffix, and newline. Return response (and also set replybuffer with response).
jbaker66 0:52654f3080d9 1270 uint8_t Adafruit_FONA::getReply(const char* prefix, char* suffix, uint16_t timeout) {
jbaker66 0:52654f3080d9 1271 flushInput();
jbaker66 0:52654f3080d9 1272
jbaker66 0:52654f3080d9 1273 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 1274 printf("\t---> %s%s\r\n", prefix, suffix);
jbaker66 0:52654f3080d9 1275 #endif
jbaker66 0:52654f3080d9 1276
jbaker66 0:52654f3080d9 1277 mySerial.printf("%s%s\r\n", prefix, suffix);
jbaker66 0:52654f3080d9 1278
jbaker66 0:52654f3080d9 1279 uint8_t l = readline(timeout);
jbaker66 0:52654f3080d9 1280 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 1281 printf("\t<--- %s\r\n", replybuffer);
jbaker66 0:52654f3080d9 1282 #endif
jbaker66 0:52654f3080d9 1283 return l;
jbaker66 0:52654f3080d9 1284 }
jbaker66 0:52654f3080d9 1285
jbaker66 0:52654f3080d9 1286 // Send prefix, suffix, and newline. Return response (and also set replybuffer with response).
jbaker66 0:52654f3080d9 1287 uint8_t Adafruit_FONA::getReply(const char* prefix, int32_t suffix, uint16_t timeout) {
jbaker66 0:52654f3080d9 1288 flushInput();
jbaker66 0:52654f3080d9 1289
jbaker66 0:52654f3080d9 1290 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 1291 printf("\t---> %s%d\r\n", prefix, suffix);
jbaker66 0:52654f3080d9 1292 #endif
jbaker66 0:52654f3080d9 1293
jbaker66 0:52654f3080d9 1294 mySerial.printf("%s%d\r\n", prefix, suffix);
jbaker66 0:52654f3080d9 1295
jbaker66 0:52654f3080d9 1296 uint8_t l = readline(timeout);
jbaker66 0:52654f3080d9 1297 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 1298 printf("\t<--- %s\r\n", replybuffer);
jbaker66 0:52654f3080d9 1299 #endif
jbaker66 0:52654f3080d9 1300 return l;
jbaker66 0:52654f3080d9 1301 }
jbaker66 0:52654f3080d9 1302
jbaker66 0:52654f3080d9 1303 // Send prefix, suffix, suffix2, and newline. Return response (and also set replybuffer with response).
jbaker66 0:52654f3080d9 1304 uint8_t Adafruit_FONA::getReply(const char* prefix, int32_t suffix1, int32_t suffix2, uint16_t timeout) {
jbaker66 0:52654f3080d9 1305 flushInput();
jbaker66 0:52654f3080d9 1306
jbaker66 0:52654f3080d9 1307 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 1308 printf("\t---> %s%d,%d\r\n", prefix, suffix1, suffix2);
jbaker66 0:52654f3080d9 1309 #endif
jbaker66 0:52654f3080d9 1310
jbaker66 0:52654f3080d9 1311 mySerial.printf("%s%d,%d\r\n", prefix, suffix1, suffix2);
jbaker66 0:52654f3080d9 1312
jbaker66 0:52654f3080d9 1313 uint8_t l = readline(timeout);
jbaker66 0:52654f3080d9 1314 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 1315 printf("\t<--- %s\r\n", replybuffer);
jbaker66 0:52654f3080d9 1316 #endif
jbaker66 0:52654f3080d9 1317 return l;
jbaker66 0:52654f3080d9 1318 }
jbaker66 0:52654f3080d9 1319
jbaker66 0:52654f3080d9 1320 // Send prefix, ", suffix, ", and newline. Return response (and also set replybuffer with response).
jbaker66 0:52654f3080d9 1321 uint8_t Adafruit_FONA::getReplyQuoted(const char* prefix, const char* suffix, uint16_t timeout) {
jbaker66 0:52654f3080d9 1322 flushInput();
jbaker66 0:52654f3080d9 1323
jbaker66 0:52654f3080d9 1324 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 1325 printf("\t---> %s\"%s\"\r\n", prefix, suffix);
jbaker66 0:52654f3080d9 1326 #endif
jbaker66 0:52654f3080d9 1327
jbaker66 0:52654f3080d9 1328 mySerial.printf("%s\"%s\"\r\n", prefix, suffix);
jbaker66 0:52654f3080d9 1329
jbaker66 0:52654f3080d9 1330 uint8_t l = readline(timeout);
jbaker66 0:52654f3080d9 1331 #ifdef ADAFRUIT_FONA_DEBUG
jbaker66 0:52654f3080d9 1332 printf("\t<--- %s\r\n", replybuffer);
jbaker66 0:52654f3080d9 1333 #endif
jbaker66 0:52654f3080d9 1334 return l;
jbaker66 0:52654f3080d9 1335 }
jbaker66 0:52654f3080d9 1336
jbaker66 0:52654f3080d9 1337
jbaker66 0:52654f3080d9 1338 bool Adafruit_FONA::sendCheckReply(const char *send, const char *reply, uint16_t timeout) {
jbaker66 0:52654f3080d9 1339 getReply(send, timeout);
jbaker66 0:52654f3080d9 1340
jbaker66 0:52654f3080d9 1341 return (strcmp(replybuffer, reply) == 0);
jbaker66 0:52654f3080d9 1342 }
jbaker66 0:52654f3080d9 1343
jbaker66 0:52654f3080d9 1344 // Send prefix, suffix, and newline. Verify FONA response matches reply parameter.
jbaker66 0:52654f3080d9 1345 bool Adafruit_FONA::sendCheckReply(const char* prefix, char *suffix, const char* reply, uint16_t timeout) {
jbaker66 0:52654f3080d9 1346 getReply(prefix, suffix, timeout);
jbaker66 0:52654f3080d9 1347 return (strcmp(replybuffer, reply) == 0);
jbaker66 0:52654f3080d9 1348 }
jbaker66 0:52654f3080d9 1349
jbaker66 0:52654f3080d9 1350 // Send prefix, suffix, and newline. Verify FONA response matches reply parameter.
jbaker66 0:52654f3080d9 1351 bool Adafruit_FONA::sendCheckReply(const char* prefix, int32_t suffix, const char* reply, uint16_t timeout) {
jbaker66 0:52654f3080d9 1352 getReply(prefix, suffix, timeout);
jbaker66 0:52654f3080d9 1353 return (strcmp(replybuffer, reply) == 0);
jbaker66 0:52654f3080d9 1354 }
jbaker66 0:52654f3080d9 1355
jbaker66 0:52654f3080d9 1356 // Send prefix, suffix, suffix2, and newline. Verify FONA response matches reply parameter.
jbaker66 0:52654f3080d9 1357 bool Adafruit_FONA::sendCheckReply(const char* prefix, int32_t suffix1, int32_t suffix2, const char* reply, uint16_t timeout) {
jbaker66 0:52654f3080d9 1358 getReply(prefix, suffix1, suffix2, timeout);
jbaker66 0:52654f3080d9 1359 return (strcmp(replybuffer, reply) == 0);
jbaker66 0:52654f3080d9 1360 }
jbaker66 0:52654f3080d9 1361
jbaker66 0:52654f3080d9 1362 // Send prefix, ", suffix, ", and newline. Verify FONA response matches reply parameter.
jbaker66 0:52654f3080d9 1363 bool Adafruit_FONA::sendCheckReplyQuoted(const char* prefix, const char* suffix, const char* reply, uint16_t timeout) {
jbaker66 0:52654f3080d9 1364 getReplyQuoted(prefix, suffix, timeout);
jbaker66 0:52654f3080d9 1365 return (strcmp(replybuffer, reply) == 0);
jbaker66 0:52654f3080d9 1366 }
jbaker66 0:52654f3080d9 1367
jbaker66 0:52654f3080d9 1368 bool Adafruit_FONA::parseReply(const char* toreply, uint16_t *v, char divider, uint8_t index) {
jbaker66 0:52654f3080d9 1369 char *p = strstr(replybuffer, toreply); // get the pointer to the voltage
jbaker66 0:52654f3080d9 1370 if (p == 0) return false;
jbaker66 0:52654f3080d9 1371 p += strlen(toreply);
jbaker66 0:52654f3080d9 1372
jbaker66 0:52654f3080d9 1373 for (uint8_t i=0; i<index;i++) {
jbaker66 0:52654f3080d9 1374 // increment dividers
jbaker66 0:52654f3080d9 1375 p = strchr(p, divider);
jbaker66 0:52654f3080d9 1376 if (!p) return false;
jbaker66 0:52654f3080d9 1377 p++;
jbaker66 0:52654f3080d9 1378 }
jbaker66 0:52654f3080d9 1379
jbaker66 0:52654f3080d9 1380 *v = atoi(p);
jbaker66 0:52654f3080d9 1381
jbaker66 0:52654f3080d9 1382 return true;
jbaker66 0:52654f3080d9 1383 }
jbaker66 0:52654f3080d9 1384
jbaker66 0:52654f3080d9 1385 bool Adafruit_FONA::parseReply(const char* toreply, char *v, char divider, uint8_t index) {
jbaker66 0:52654f3080d9 1386 uint8_t i=0;
jbaker66 0:52654f3080d9 1387 char *p = strstr(replybuffer, toreply);
jbaker66 0:52654f3080d9 1388 if (p == 0) return false;
jbaker66 0:52654f3080d9 1389 p+=strlen(toreply);
jbaker66 0:52654f3080d9 1390
jbaker66 0:52654f3080d9 1391 for (i=0; i<index;i++) {
jbaker66 0:52654f3080d9 1392 // increment dividers
jbaker66 0:52654f3080d9 1393 p = strchr(p, divider);
jbaker66 0:52654f3080d9 1394 if (!p) return false;
jbaker66 0:52654f3080d9 1395 p++;
jbaker66 0:52654f3080d9 1396 }
jbaker66 0:52654f3080d9 1397
jbaker66 0:52654f3080d9 1398 for(i=0; i<strlen(p);i++) {
jbaker66 0:52654f3080d9 1399 if(p[i] == divider)
jbaker66 0:52654f3080d9 1400 break;
jbaker66 0:52654f3080d9 1401 v[i] = p[i];
jbaker66 0:52654f3080d9 1402 }
jbaker66 0:52654f3080d9 1403
jbaker66 0:52654f3080d9 1404 v[i] = '\0';
jbaker66 0:52654f3080d9 1405
jbaker66 0:52654f3080d9 1406 return true;
jbaker66 0:52654f3080d9 1407 }
jbaker66 0:52654f3080d9 1408
jbaker66 0:52654f3080d9 1409 // Parse a quoted string in the response fields and copy its value (without quotes)
jbaker66 0:52654f3080d9 1410 // to the specified character array (v). Only up to maxlen characters are copied
jbaker66 0:52654f3080d9 1411 // into the result buffer, so make sure to pass a large enough buffer to handle the
jbaker66 0:52654f3080d9 1412 // response.
jbaker66 0:52654f3080d9 1413 bool Adafruit_FONA::parseReplyQuoted(const char* toreply, char* v, int maxlen, char divider, uint8_t index) {
jbaker66 0:52654f3080d9 1414 uint8_t i=0, j;
jbaker66 0:52654f3080d9 1415 // Verify response starts with toreply.
jbaker66 0:52654f3080d9 1416 char *p = strstr(replybuffer, toreply);
jbaker66 0:52654f3080d9 1417 if (p == 0) return false;
jbaker66 0:52654f3080d9 1418 p+=strlen(toreply);
jbaker66 0:52654f3080d9 1419
jbaker66 0:52654f3080d9 1420 // Find location of desired response field.
jbaker66 0:52654f3080d9 1421 for (i=0; i<index;i++) {
jbaker66 0:52654f3080d9 1422 // increment dividers
jbaker66 0:52654f3080d9 1423 p = strchr(p, divider);
jbaker66 0:52654f3080d9 1424 if (!p) return false;
jbaker66 0:52654f3080d9 1425 p++;
jbaker66 0:52654f3080d9 1426 }
jbaker66 0:52654f3080d9 1427
jbaker66 0:52654f3080d9 1428 // Copy characters from response field into result string.
jbaker66 0:52654f3080d9 1429 for(i=0, j=0; j<maxlen && i<strlen(p); ++i) {
jbaker66 0:52654f3080d9 1430 // Stop if a divier is found.
jbaker66 0:52654f3080d9 1431 if(p[i] == divider)
jbaker66 0:52654f3080d9 1432 break;
jbaker66 0:52654f3080d9 1433 // Skip any quotation marks.
jbaker66 0:52654f3080d9 1434 else if(p[i] == '"')
jbaker66 0:52654f3080d9 1435 continue;
jbaker66 0:52654f3080d9 1436 v[j++] = p[i];
jbaker66 0:52654f3080d9 1437 }
jbaker66 0:52654f3080d9 1438
jbaker66 0:52654f3080d9 1439 // Add a null terminator if result string buffer was not filled.
jbaker66 0:52654f3080d9 1440 if (j < maxlen)
jbaker66 0:52654f3080d9 1441 v[j] = '\0';
jbaker66 0:52654f3080d9 1442
jbaker66 0:52654f3080d9 1443 return true;
jbaker66 0:52654f3080d9 1444 }
jbaker66 0:52654f3080d9 1445
jbaker66 0:52654f3080d9 1446 bool Adafruit_FONA::sendParseReply(const char* tosend, const char* toreply, uint16_t *v, char divider, uint8_t index) {
jbaker66 0:52654f3080d9 1447 getReply(tosend);
jbaker66 0:52654f3080d9 1448
jbaker66 0:52654f3080d9 1449 if (! parseReply(toreply, v, divider, index)) return false;
jbaker66 0:52654f3080d9 1450
jbaker66 0:52654f3080d9 1451 readline(); // eat 'OK'
jbaker66 0:52654f3080d9 1452
jbaker66 0:52654f3080d9 1453 return true;
jbaker66 0:52654f3080d9 1454 }