Library to use SIMCOM's GSM/GPS/BT SIM808 module.

Dependents:   GPS_SIMCOM_SIM808

Fork of Adafruit_FONA_Library by Marc Plouhinec

Committer:
marcpl
Date:
Sat Jun 27 09:25:38 2015 +0000
Revision:
0:d567815b7a5f
Child:
1:89299f09929c
Port the Adafruit_FONA_Library for mbed.

Who changed what in which revision?

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