Allows SMS to be sent to query Alexa. Also allows HTTP requests to be sent to Alexa via an ESP8266-hosted web server.
Revision 0:1271d15b4d4b, committed 2017-05-02
- Comitter:
- itatchi42
- Date:
- Tue May 02 03:13:27 2017 +0000
- Commit message:
- Allows SMS communication with Amazon Dot's Alexa.; Also allows URL queries to be sent to ESP8266-hosted HTTP server to communicate with Alexa.
Changed in this revision
diff -r 000000000000 -r 1271d15b4d4b Adafruit_FONA.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Adafruit_FONA.cpp Tue May 02 03:13:27 2017 +0000 @@ -0,0 +1,1447 @@ +/*************************************************** + This is a library for our Adafruit FONA Cellular Module + + Designed specifically to work with the Adafruit FONA + ----> http://www.adafruit.com/products/1946 + ----> http://www.adafruit.com/products/1963 + + These displays use TTL Serial to communicate, 2 pins are required to + interface + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + Written by Limor Fried/Ladyada for Adafruit Industries. + BSD license, all text above must be included in any redistribution + ****************************************************/ + + /* + * Modified by George Tzintzarov & Jesse Baker 03/14/2016 for use in mbed LPC1768 + */ +#include <algorithm> +#include "Adafruit_FONA.h" + +#define HIGH 1 +#define LOW 0 + +/* +Notes George is taking: +sendCheckReply returns a boolean where its true when FONA responds with the string of its second input + +*/ + + +bool Adafruit_FONA::begin(int baudrate) { + mySerial.baud(baudrate); //set the baud rate of the fona serial connection + mySerial.attach(this, &Adafruit_FONA::onSerialDataReceived, Serial::RxIrq); //attached onSerialDataReceived as Serial receive interrupt + + // INIT Reboot process + _rstpin = HIGH; + wait_ms(10); + _rstpin = LOW; + wait_ms(100); + _rstpin = HIGH; + + // give 3 seconds to reboot + wait_ms(3000); + + // flushes the serial port + while (readable()) getc(); + + // Make sure FONA is alive + sendCheckReply("AT", "OK"); + wait_ms(100); + sendCheckReply("AT", "OK"); + wait_ms(100); + sendCheckReply("AT", "OK"); + wait_ms(100); + + // turn off Echo! + sendCheckReply("ATE0", "OK"); + wait_ms(100); + + // Just checks if the FONA even responds, if it doesnt, then return false + if (! sendCheckReply("ATE0", "OK")) { + return false; + } + + return true; +} + +void Adafruit_FONA::setEventListener(EventListener *eventListener) { + this->eventListener = eventListener; +} + +/********* Stream ********************************************/ + +int Adafruit_FONA::_putc(int value) { + return mySerial.putc(value); +} + +int Adafruit_FONA::_getc() { + __disable_irq(); // Start Critical Section - don't interrupt while changing global buffer variables + + // Wait for data if the buffer is empty + if (isRxBufferEmpty()) { + __enable_irq(); // End Critical Section - need to allow rx interrupt to get new characters for buffer + + while(isRxBufferEmpty()); + + __disable_irq(); // Start Critical Section - don't interrupt while changing global buffer variables + } + + int data = rxBuffer[rxBufferOutIndex]; + incrementRxBufferOutIndex(); + + __enable_irq(); // End Critical Section + + return data; +} + +int Adafruit_FONA::readable() { + return !isRxBufferEmpty(); +} + +void Adafruit_FONA::onSerialDataReceived() { + while (mySerial.readable() && !isRxBufferFull()) { + int data = mySerial.getc(); + rxBuffer[rxBufferInIndex] = data; + + // + // Analyze the received data in order to detect events like RING or NO CARRIER + // + + // Copy the data in the current line + if (currentReceivedLineSize < RX_BUFFER_SIZE && data != '\r' && data != '\n') { + currentReceivedLine[currentReceivedLineSize] = (char) data; + currentReceivedLineSize++; + } + + // Check if the line is complete + if (data == '\n') { + currentReceivedLine[currentReceivedLineSize] = 0; + + if (eventListener != NULL) { + // Check if we have a special event + if (strcmp(currentReceivedLine, "RING") == 0) { + eventListener->onRing(); + } else if (strcmp(currentReceivedLine, "NO CARRIER") == 0) { + eventListener->onNoCarrier(); + } + } + + currentReceivedLineSize = 0; + } + + incrementRxBufferInIndex(); + } +} + +/********* Real Time Clock ********************************************/ + +bool Adafruit_FONA::enableRTC(uint8_t i) { + if (! sendCheckReply("AT+CLTS=", i, "OK")) + return false; + return sendCheckReply("AT&W", "OK"); +} + +/********* BATTERY & ADC ********************************************/ + +/* returns value in mV (uint16_t) */ +bool Adafruit_FONA::getBattVoltage(uint16_t *v) { + return sendParseReply("AT+CBC", "+CBC: ", v, ',', 2); +} + +/* returns the percentage charge of battery as reported by sim800 */ +bool Adafruit_FONA::getBattPercent(uint16_t *p) { + return sendParseReply("AT+CBC", "+CBC: ", p, ',', 1); +} + +bool Adafruit_FONA::getADCVoltage(uint16_t *v) { + return sendParseReply("AT+CADC?", "+CADC: 1,", v); +} + +/********* SIM ***********************************************************/ + +bool Adafruit_FONA::unlockSIM(char *pin) +{ + char sendbuff[14] = "AT+CPIN="; + sendbuff[8] = pin[0]; + sendbuff[9] = pin[1]; + sendbuff[10] = pin[2]; + sendbuff[11] = pin[3]; + sendbuff[12] = NULL; + + return sendCheckReply(sendbuff, "OK"); +} + +uint8_t Adafruit_FONA::getSIMCCID(char *ccid) { + getReply("AT+CCID"); + // up to 20 chars + strncpy(ccid, replybuffer, 20); + ccid[20] = 0; + + readline(); // eat 'OK' + + return strlen(ccid); +} + +/********* IMEI **********************************************************/ + +uint8_t Adafruit_FONA::getIMEI(char *imei) { + getReply("AT+GSN"); + + // up to 15 chars + strncpy(imei, replybuffer, 15); + imei[15] = 0; + + readline(); // eat 'OK' + + return strlen(imei); +} + +/********* NETWORK *******************************************************/ + +uint8_t Adafruit_FONA::getNetworkStatus(void) { + uint16_t status; + + if (! sendParseReply("AT+CREG?", "+CREG: ", &status, ',', 1)) return 0; + + return status; +} + + +uint8_t Adafruit_FONA::getRSSI(void) { + uint16_t reply; + + if (! sendParseReply("AT+CSQ", "+CSQ: ", &reply) ) return 0; + + return reply; +} + +/********* AUDIO *******************************************************/ + +bool Adafruit_FONA::setAudio(uint8_t a) { + // 0 is headset, 1 is external audio + if (a > 1) return false; + + return sendCheckReply("AT+CHFA=", a, "OK"); +} + +uint8_t Adafruit_FONA::getVolume(void) { + uint16_t reply; + + if (! sendParseReply("AT+CLVL?", "+CLVL: ", &reply) ) return 0; + + return reply; +} + +bool Adafruit_FONA::setVolume(uint8_t i) { + return sendCheckReply("AT+CLVL=", i, "OK"); +} + + +bool Adafruit_FONA::playDTMF(char dtmf) { + char str[4]; + str[0] = '\"'; + str[1] = dtmf; + str[2] = '\"'; + str[3] = 0; + return sendCheckReply("AT+CLDTMF=3,", str, "OK"); +} + +bool Adafruit_FONA::playToolkitTone(uint8_t t, uint16_t len) { + return sendCheckReply("AT+STTONE=1,", t, len, "OK"); +} + +bool Adafruit_FONA::setMicVolume(uint8_t a, uint8_t level) { + // 0 is headset, 1 is external audio + if (a > 1) return false; + + return sendCheckReply("AT+CMIC=", a, level, "OK"); +} + +/********* FM RADIO *******************************************************/ + + +bool Adafruit_FONA::FMradio(bool onoff, uint8_t a) { + if (! onoff) { + return sendCheckReply("AT+FMCLOSE", "OK"); + } + + // 0 is headset, 1 is external audio + if (a > 1) return false; + + return sendCheckReply("AT+FMOPEN=", a, "OK"); +} + +bool Adafruit_FONA::tuneFMradio(uint16_t station) { + // Fail if FM station is outside allowed range. + if ((station < 870) || (station > 1090)) + return false; + + return sendCheckReply("AT+FMFREQ=", station, "OK"); +} + +bool Adafruit_FONA::setFMVolume(uint8_t i) { + // Fail if volume is outside allowed range (0-6). + if (i > 6) { + return false; + } + // Send FM volume command and verify response. + return sendCheckReply("AT+FMVOLUME=", i, "OK"); +} + +int8_t Adafruit_FONA::getFMVolume() { + uint16_t level; + + if (! sendParseReply("AT+FMVOLUME?", "+FMVOLUME: ", &level) ) return 0; + + return level; +} + +int8_t Adafruit_FONA::getFMSignalLevel(uint16_t station) { + // Fail if FM station is outside allowed range. + if ((station < 875) || (station > 1080)) { + return -1; + } + + // Send FM signal level query command. + // Note, need to explicitly send timeout so right overload is chosen. + getReply("AT+FMSIGNAL=", station, FONA_DEFAULT_TIMEOUT_MS); + // Check response starts with expected value. + char *p = strstr(replybuffer, "+FMSIGNAL: "); + if (p == 0) return -1; + p+=11; + // Find second colon to get start of signal quality. + p = strchr(p, ':'); + if (p == 0) return -1; + p+=1; + // Parse signal quality. + int8_t level = atoi(p); + readline(); // eat the "OK" + return level; +} + +/********* PWM/BUZZER **************************************************/ + +bool Adafruit_FONA::setPWM(uint16_t period, uint8_t duty) { + if (period > 2000) return false; + if (duty > 100) return false; + + return sendCheckReply("AT+SPWM=0,", period, duty, "OK"); +} + +/********* CALL PHONES **************************************************/ +bool Adafruit_FONA::callPhone(char *number) { + char sendbuff[35] = "ATD"; + strncpy(sendbuff+3, number, min((int)30, (int)strlen(number))); + uint8_t x = strlen(sendbuff); + sendbuff[x] = ';'; + sendbuff[x+1] = 0; + + return sendCheckReply(sendbuff, "OK"); +} + +bool Adafruit_FONA::hangUp(void) { + return sendCheckReply("ATH0", "OK"); +} + +bool Adafruit_FONA::pickUp(void) { + return sendCheckReply("ATA", "OK"); +} + +void Adafruit_FONA::onIncomingCall() { +#ifdef ADAFRUIT_FONA_DEBUG + printf("> Incoming call...\r\n"); +#endif + _incomingCall = true; +} + +bool Adafruit_FONA::callerIdNotification(bool enable) { + if(enable){ + _ringIndicatorInterruptIn.fall(this, &Adafruit_FONA::onIncomingCall); + return sendCheckReply("AT+CLIP=1", "OK"); + } + + _ringIndicatorInterruptIn.fall(NULL); + return sendCheckReply("AT+CLIP=0", "OK"); +} + +bool Adafruit_FONA::incomingCallNumber(char* phonenum) { + //+CLIP: "<incoming phone number>",145,"",0,"",0 + if(!_incomingCall) + return false; + + readline(); + while(!strcmp(replybuffer, "RING") == 0) { + flushInput(); + readline(); + } + + readline(); //reads incoming phone number line + + parseReply("+CLIP: \"", phonenum, '"'); + +#ifdef ADAFRUIT_FONA_DEBUG + printf("Phone Number: %s\r\n", replybuffer); +#endif + + _incomingCall = false; + return true; +} + +/********* SMS **********************************************************/ + +uint8_t Adafruit_FONA::getSMSInterrupt(void) { + uint16_t reply; + + if (! sendParseReply("AT+CFGRI?", "+CFGRI: ", &reply) ) return 0; + + return reply; +} + +bool Adafruit_FONA::setSMSInterrupt(uint8_t i) { + return sendCheckReply("AT+CFGRI=", i, "OK"); +} + +int8_t Adafruit_FONA::getNumSMS(void) { + uint16_t numsms; + + if (! sendCheckReply("AT+CMGF=1", "OK")) return -1; + // ask how many sms are stored + + if (! sendParseReply("AT+CPMS?", "+CPMS: \"SM_P\",", &numsms) ) return -1; + + return numsms; +} + +// Reading SMS's is a bit involved so we don't use helpers that may cause delays or debug +// printouts! +bool Adafruit_FONA::readSMS(uint8_t i, char *smsbuff, uint16_t maxlen, uint16_t *readlen) { + // text mode + if (! sendCheckReply("AT+CMGF=1", "OK")) return false; + + // show all text mode parameters + if (! sendCheckReply("AT+CSDH=1", "OK")) return false; + + // parse out the SMS len + uint16_t thesmslen = 0; + + //getReply(F("AT+CMGR="), i, 1000); // do not print debug! + mySerial.printf("AT+CMGR=%d\r\n", i); + readline(1000); // timeout + + // parse it out... + if (! parseReply("+CMGR:", &thesmslen, ',', 11)) { + *readlen = 0; + return false; + } + + readRaw(thesmslen); + + flushInput(); + + uint16_t thelen = min(maxlen, (uint16_t)strlen(replybuffer)); + strncpy(smsbuff, replybuffer, thelen); + smsbuff[thelen] = 0; // end the string + +#ifdef ADAFRUIT_FONA_DEBUG + printf("%s\r\n", replybuffer); +#endif + *readlen = thelen; + return true; +} + +// Retrieve the sender of the specified SMS message and copy it as a string to +// the sender buffer. Up to senderlen characters of the sender will be copied +// and a null terminator will be added if less than senderlen charactesr are +// copied to the result. Returns true if a result was successfully retrieved, +// otherwise false. +bool Adafruit_FONA::getSMSSender(uint8_t i, char *sender, int senderlen) { + // Ensure text mode and all text mode parameters are sent. + if (! sendCheckReply("AT+CMGF=1", "OK")) return false; + if (! sendCheckReply("AT+CSDH=1", "OK")) return false; + // Send command to retrieve SMS message and parse a line of response. + mySerial.printf("AT+CMGR=%d\r\n", i); + readline(1000); + // Parse the second field in the response. + bool result = parseReplyQuoted("+CMGR:", sender, senderlen, ',', 1); + // Drop any remaining data from the response. + flushInput(); + return result; +} + +bool Adafruit_FONA::sendSMS(char *smsaddr, char *smsmsg) { + if (! sendCheckReply("AT+CMGF=1", "OK")) return -1; + + char sendcmd[30] = "AT+CMGS=\""; + strncpy(sendcmd+9, smsaddr, 30-9-2); // 9 bytes beginning, 2 bytes for close quote + null + sendcmd[strlen(sendcmd)] = '\"'; + + if (! sendCheckReply(sendcmd, "> ")) return false; +#ifdef ADAFRUIT_FONA_DEBUG + printf("> %s\r\n", smsmsg); +#endif + mySerial.printf("%s\r\n\r\n", smsmsg); + mySerial.putc(0x1A); +#ifdef ADAFRUIT_FONA_DEBUG + printf("^Z\r\n"); +#endif + readline(10000); // read the +CMGS reply, wait up to 10 seconds!!! + //Serial.print("* "); Serial.println(replybuffer); + if (strstr(replybuffer, "+CMGS") == 0) { + return false; + } + readline(1000); // read OK + //Serial.print("* "); Serial.println(replybuffer); + + if (strcmp(replybuffer, "OK") != 0) { + return false; + } + + return true; +} + + +bool Adafruit_FONA::deleteSMS(uint8_t i) { + if (! sendCheckReply("AT+CMGF=1", "OK")) return -1; + // read an sms + char sendbuff[12] = "AT+CMGD=000"; + sendbuff[8] = (i / 100) + '0'; + i %= 100; + sendbuff[9] = (i / 10) + '0'; + i %= 10; + sendbuff[10] = i + '0'; + + return sendCheckReply(sendbuff, "OK", 2000); +} + +/********* TIME **********************************************************/ + +bool Adafruit_FONA::enableNetworkTimeSync(bool onoff) { + if (onoff) { + if (! sendCheckReply("AT+CLTS=1", "OK")) + return false; + } else { + if (! sendCheckReply("AT+CLTS=0", "OK")) + return false; + } + + flushInput(); // eat any 'Unsolicted Result Code' + + return true; +} + +bool Adafruit_FONA::enableNTPTimeSync(bool onoff, const char* ntpserver) { + if (onoff) { + if (! sendCheckReply("AT+CNTPCID=1", "OK")) + return false; + + mySerial.printf("AT+CNTP=\""); + if (ntpserver != 0) { + mySerial.printf(ntpserver); + } else { + mySerial.printf("pool.ntp.org"); + } + mySerial.printf("\",0\r\n"); + readline(FONA_DEFAULT_TIMEOUT_MS); + if (strcmp(replybuffer, "OK") != 0) + return false; + + if (! sendCheckReply("AT+CNTP", "OK", 10000)) + return false; + + uint16_t status; + readline(10000); + if (! parseReply("+CNTP:", &status)) + return false; + } else { + if (! sendCheckReply("AT+CNTPCID=0", "OK")) + return false; + } + + return true; +} + +bool Adafruit_FONA::getTime(char* buff, uint16_t maxlen) { + getReply("AT+CCLK?", (uint16_t) 10000); + if (strncmp(replybuffer, "+CCLK: ", 7) != 0) + return false; + + char *p = replybuffer+7; + uint16_t lentocopy = min((uint16_t)(maxlen-1), (uint16_t)strlen(p)); + strncpy(buff, p, lentocopy+1); + buff[lentocopy] = 0; + + readline(); // eat OK + + return true; +} + +/********* GPS **********************************************************/ + + +bool Adafruit_FONA::enableGPS(bool onoff) { + uint16_t state; + + // first check if its already on or off + if (! sendParseReply("AT+CGPSPWR?", "+CGPSPWR: ", &state) ) + return false; + + if (onoff && !state) { + if (! sendCheckReply("AT+CGPSPWR=1", "OK")) + return false; + } else if (!onoff && state) { + if (! sendCheckReply("AT+CGPSPWR=0", "OK")) + return false; + } + return true; +} + +int8_t Adafruit_FONA::GPSstatus(void) { + getReply("AT+CGPSSTATUS?"); + + char *p = strstr(replybuffer, "+CGPSSTATUS: Location "); + if (p == 0) return -1; + + p+=22; + + readline(); // eat 'OK' + + + if (p[0] == 'U') return 0; + if (p[0] == 'N') return 1; + if (p[0] == '2') return 2; + if (p[0] == '3') return 3; + + // else + return 0; +} + +uint8_t Adafruit_FONA::getGPS(uint8_t arg, char *buffer, uint8_t maxbuff) { + int32_t x = arg; + + getReply("AT+CGPSINF=", x); + + char *p = strstr(replybuffer, "CGPSINF: "); + if (p == 0){ + buffer[0] = 0; + return 0; + } + p+=9; + uint8_t len = max((uint8_t)(maxbuff-1), (uint8_t)strlen(p)); + strncpy(buffer, p, len); + buffer[len] = 0; + + readline(); // eat 'OK' + return len; +} + +bool Adafruit_FONA::getGPS(float *lat, float *lon, float *speed_kph, float *heading, float *altitude) { + char gpsbuffer[120]; + + // we need at least a 2D fix + if (GPSstatus() < 2) + return false; + + // grab the mode 2^5 gps csv from the sim808 + uint8_t res_len = getGPS(32, gpsbuffer, 120); + + // make sure we have a response + if (res_len == 0) + return false; + + // skip mode + char *tok = strtok(gpsbuffer, ","); + if (! tok) return false; + + // skip date + tok = strtok(NULL, ","); + if (! tok) return false; + + // skip fix + tok = strtok(NULL, ","); + if (! tok) return false; + + // grab the latitude + char *latp = strtok(NULL, ","); + if (! latp) return false; + + // grab latitude direction + char *latdir = strtok(NULL, ","); + if (! latdir) return false; + + // grab longitude + char *longp = strtok(NULL, ","); + if (! longp) return false; + + // grab longitude direction + char *longdir = strtok(NULL, ","); + if (! longdir) return false; + + double latitude = atof(latp); + double longitude = atof(longp); + + // convert latitude from minutes to decimal + float degrees = floor(latitude / 100); + double minutes = latitude - (100 * degrees); + minutes /= 60; + degrees += minutes; + + // turn direction into + or - + if (latdir[0] == 'S') degrees *= -1; + + *lat = degrees; + + // convert longitude from minutes to decimal + degrees = floor(longitude / 100); + minutes = longitude - (100 * degrees); + minutes /= 60; + degrees += minutes; + + // turn direction into + or - + if (longdir[0] == 'W') degrees *= -1; + + *lon = degrees; + + // only grab speed if needed + if (speed_kph != NULL) { + + // grab the speed in knots + char *speedp = strtok(NULL, ","); + if (! speedp) return false; + + // convert to kph + *speed_kph = atof(speedp) * 1.852; + + } + + // only grab heading if needed + if (heading != NULL) { + + // grab the speed in knots + char *coursep = strtok(NULL, ","); + if (! coursep) return false; + + *heading = atof(coursep); + + } + + // no need to continue + if (altitude == NULL) + return true; + + // we need at least a 3D fix for altitude + if (GPSstatus() < 3) + return false; + + // grab the mode 0 gps csv from the sim808 + res_len = getGPS(0, gpsbuffer, 120); + + // make sure we have a response + if (res_len == 0) + return false; + + // skip mode + tok = strtok(gpsbuffer, ","); + if (! tok) return false; + + // skip lat + tok = strtok(NULL, ","); + if (! tok) return false; + + // skip long + tok = strtok(NULL, ","); + if (! tok) return false; + + // grab altitude + char *altp = strtok(NULL, ","); + if (! altp) return false; + + *altitude = atof(altp); + + return true; +} + +bool Adafruit_FONA::enableGPSNMEA(uint8_t i) { + char sendbuff[15] = "AT+CGPSOUT=000"; + sendbuff[11] = (i / 100) + '0'; + i %= 100; + sendbuff[12] = (i / 10) + '0'; + i %= 10; + sendbuff[13] = i + '0'; + + return sendCheckReply(sendbuff, "OK", 2000); +} + + +/********* GPRS **********************************************************/ + + +bool Adafruit_FONA::enableGPRS(bool onoff) { + if (onoff) { + // disconnect all sockets + sendCheckReply("AT+CIPSHUT", "SHUT OK", 5000); + + if (! sendCheckReply("AT+CGATT=1", "OK", 10000)) + return false; + + // set bearer profile! connection type GPRS + if (! sendCheckReply("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"", "OK", 10000)) + return false; + + // set bearer profile access point name + if (apn) { + // Send command AT+SAPBR=3,1,"APN","<apn value>" where <apn value> is the configured APN value. + if (! sendCheckReplyQuoted("AT+SAPBR=3,1,\"APN\",", apn, "OK", 10000)) + return false; + + // set username/password + if (apnusername) { + // Send command AT+SAPBR=3,1,"USER","<user>" where <user> is the configured APN username. + if (! sendCheckReplyQuoted("AT+SAPBR=3,1,\"USER\",", apnusername, "OK", 10000)) + return false; + } + if (apnpassword) { + // Send command AT+SAPBR=3,1,"PWD","<password>" where <password> is the configured APN password. + if (! sendCheckReplyQuoted("AT+SAPBR=3,1,\"PWD\",", apnpassword, "OK", 10000)) + return false; + } + } + + // open GPRS context + if (! sendCheckReply("AT+SAPBR=1,1", "OK", 10000)) + return false; + } else { + // disconnect all sockets + if (! sendCheckReply("AT+CIPSHUT", "SHUT OK", 5000)) + return false; + + // close GPRS context + if (! sendCheckReply("AT+SAPBR=0,1", "OK", 10000)) + return false; + + if (! sendCheckReply("AT+CGATT=0", "OK", 10000)) + return false; + } + return true; +} + +uint8_t Adafruit_FONA::GPRSstate(void) { + uint16_t state; + + if (! sendParseReply("AT+CGATT?", "+CGATT: ", &state) ) + return -1; + + return state; +} + +void Adafruit_FONA::setGPRSNetworkSettings(const char* apn, const char* ausername, const char* apassword) { + this->apn = (char*) apn; + this->apnusername = (char*) ausername; + this->apnpassword = (char*) apassword; +} + +bool Adafruit_FONA::getGSMLoc(uint16_t *errorcode, char *buff, uint16_t maxlen) { + getReply("AT+CIPGSMLOC=1,1", (uint16_t)10000); + + if (! parseReply("+CIPGSMLOC: ", errorcode)) + return false; + + char *p = replybuffer+14; + uint16_t lentocopy = min((uint16_t)(maxlen-1), (uint16_t)strlen(p)); + strncpy(buff, p, lentocopy+1); + + readline(); // eat OK + + return true; +} + +bool Adafruit_FONA::getGSMLoc(float *lat, float *lon) { + uint16_t returncode; + char gpsbuffer[120]; + + // make sure we could get a response + if (! getGSMLoc(&returncode, gpsbuffer, 120)) + return false; + + // make sure we have a valid return code + if (returncode != 0) + return false; + + // tokenize the gps buffer to locate the lat & long + char *latp = strtok(gpsbuffer, ","); + if (! latp) return false; + + char *longp = strtok(NULL, ","); + if (! longp) return false; + + *lat = atof(latp); + *lon = atof(longp); + + return true; +} + +/********* TCP FUNCTIONS ************************************/ + + +bool Adafruit_FONA::TCPconnect(char *server, uint16_t port) { + flushInput(); + + // close all old connections + if (! sendCheckReply("AT+CIPSHUT", "SHUT OK", 5000) ) return false; + + // single connection at a time + if (! sendCheckReply("AT+CIPMUX=0", "OK") ) return false; + + // manually read data + if (! sendCheckReply("AT+CIPRXGET=1", "OK") ) return false; + +#ifdef ADAFRUIT_FONA_DEBUG + printf("AT+CIPSTART=\"TCP\",\"%s\",\"%d\"\r\n", server, port); +#endif + + mySerial.printf("AT+CIPSTART=\"TCP\",\"%s\",\"%d\"\r\n", server, port); + + if (! expectReply("OK")) return false; + if (! expectReply("CONNECT OK")) return false; + return true; +} + +bool Adafruit_FONA::TCPclose(void) { + return sendCheckReply("AT+CIPCLOSE", "OK"); +} + +bool Adafruit_FONA::TCPconnected(void) { + if (! sendCheckReply("AT+CIPSTATUS", "OK", 100) ) return false; + readline(100); +#ifdef ADAFRUIT_FONA_DEBUG + printf("\t<--- %s\r\n", replybuffer); +#endif + return (strcmp(replybuffer, "STATE: CONNECT OK") == 0); +} + +bool Adafruit_FONA::TCPsend(char *packet, uint8_t len) { +#ifdef ADAFRUIT_FONA_DEBUG + printf("AT+CIPSEND=%d\r\n", len); + + for (uint16_t i=0; i<len; i++) { + printf(" 0x%#02x", packet[i]); + } + printf("\r\n"); +#endif + + + mySerial.printf("AT+CIPSEND=%d\r\n", len); + readline(); +#ifdef ADAFRUIT_FONA_DEBUG + printf("\t<--- %s\r\n", replybuffer); +#endif + if (replybuffer[0] != '>') return false; + + for (uint16_t i=0; i<len; i++) { + mySerial.putc(packet[i]); + } + readline(3000); // wait up to 3 seconds to send the data +#ifdef ADAFRUIT_FONA_DEBUG + printf("\t<--- %s\r\n", replybuffer); +#endif + + return (strcmp(replybuffer, "SEND OK") == 0); +} + +uint16_t Adafruit_FONA::TCPavailable(void) { + uint16_t avail; + + if (! sendParseReply("AT+CIPRXGET=4", "+CIPRXGET: 4,", &avail, ',', 0) ) return false; + +#ifdef ADAFRUIT_FONA_DEBUG + printf("%d bytes available\r\n", avail); +#endif + + return avail; +} + + +uint16_t Adafruit_FONA::TCPread(uint8_t *buff, uint8_t len) { + uint16_t avail; + + mySerial.printf("AT+CIPRXGET=2,%d\r\n", len); + readline(); + if (! parseReply("+CIPRXGET: 2,", &avail, ',', 0)) return false; + + readRaw(avail); + +#ifdef ADAFRUIT_FONA_DEBUG + printf("%d bytes read\r\n", avail); + for (uint8_t i=0;i<avail;i++) { + printf(" 0x%#02x", replybuffer[i]); + } + printf("\r\n"); +#endif + + memcpy(buff, replybuffer, avail); + + return avail; +} + +/********* HTTP LOW LEVEL FUNCTIONS ************************************/ + +bool Adafruit_FONA::HTTP_init() { + return sendCheckReply("AT+HTTPINIT", "OK"); +} + +bool Adafruit_FONA::HTTP_term() { + return sendCheckReply("AT+HTTPTERM", "OK"); +} + +void Adafruit_FONA::HTTP_para_start(const char* parameter, bool quoted) { + flushInput(); + +#ifdef ADAFRUIT_FONA_DEBUG + printf("\t---> AT+HTTPPARA=\"%s\"\r\n", parameter); +#endif + + mySerial.printf("AT+HTTPPARA=\"%s", parameter); + if (quoted) + mySerial.printf("\",\""); + else + mySerial.printf("\","); +} + +bool Adafruit_FONA::HTTP_para_end(bool quoted) { + if (quoted) + mySerial.printf("\"\r\n"); + else + mySerial.printf("\r\n"); + + return expectReply("OK"); +} + +bool Adafruit_FONA::HTTP_para(const char* parameter, const char* value) { + HTTP_para_start(parameter, true); + mySerial.printf(value); + return HTTP_para_end(true); +} + +bool Adafruit_FONA::HTTP_para(const char* parameter, int32_t value) { + HTTP_para_start(parameter, false); + mySerial.printf("%d", value); + return HTTP_para_end(false); +} + +bool Adafruit_FONA::HTTP_data(uint32_t size, uint32_t maxTime) { + flushInput(); + +#ifdef ADAFRUIT_FONA_DEBUG + printf("\t---> AT+HTTPDATA=%d,%d\r\n", size, maxTime); +#endif + + mySerial.printf("AT+HTTPDATA=%d,%d\r\n", size, maxTime); + + return expectReply("DOWNLOAD"); +} + +bool Adafruit_FONA::HTTP_action(uint8_t method, uint16_t *status, uint16_t *datalen, int32_t timeout) { + // Send request. + if (! sendCheckReply("AT+HTTPACTION=", method, "OK")) + return false; + + // Parse response status and size. + readline(timeout); + if (! parseReply("+HTTPACTION:", status, ',', 1)) + return false; + if (! parseReply("+HTTPACTION:", datalen, ',', 2)) + return false; + + return true; +} + +bool Adafruit_FONA::HTTP_readall(uint16_t *datalen) { + getReply("AT+HTTPREAD"); + if (! parseReply("+HTTPREAD:", datalen, ',', 0)) + return false; + + return true; +} + +bool Adafruit_FONA::HTTP_ssl(bool onoff) { + return sendCheckReply("AT+HTTPSSL=", onoff ? 1 : 0, "OK"); +} + +/********* HTTP HIGH LEVEL FUNCTIONS ***************************/ + +bool Adafruit_FONA::HTTP_GET_start(char *url, uint16_t *status, uint16_t *datalen){ + if (! HTTP_setup(url)) + return false; + + // HTTP GET + if (! HTTP_action(FONA_HTTP_GET, status, datalen)) + return false; + +#ifdef ADAFRUIT_FONA_DEBUG + printf("Status: %d\r\n", *status); + printf("Len: %d\r\n", *datalen); +#endif + + // HTTP response data + if (! HTTP_readall(datalen)) + return false; + + return true; +} + +void Adafruit_FONA::HTTP_GET_end(void) { + HTTP_term(); +} + +bool Adafruit_FONA::HTTP_POST_start(char *url, const char* contenttype, const uint8_t *postdata, uint16_t postdatalen, uint16_t *status, uint16_t *datalen) { + if (! HTTP_setup(url)) + return false; + + if (! HTTP_para("CONTENT", contenttype)) { + return false; + } + + // HTTP POST data + if (! HTTP_data(postdatalen, 10000)) + return false; + for (uint16_t i = 0; i < postdatalen; i++) { + mySerial.putc(postdata[i]); + } + if (! expectReply("OK")) + return false; + + // HTTP POST + if (! HTTP_action(FONA_HTTP_POST, status, datalen)) + return false; + +#ifdef ADAFRUIT_FONA_DEBUG + printf("Status: %d\r\n", *status); + printf("Len: %d\r\n", *datalen); +#endif + + // HTTP response data + if (! HTTP_readall(datalen)) + return false; + + return true; +} + +void Adafruit_FONA::HTTP_POST_end(void) { + HTTP_term(); +} + +void Adafruit_FONA::setUserAgent(const char* useragent) { + this->useragent = (char*) useragent; +} + +void Adafruit_FONA::setHTTPSRedirect(bool onoff) { + httpsredirect = onoff; +} + +/********* HTTP HELPERS ****************************************/ + +bool Adafruit_FONA::HTTP_setup(char *url) { + // Handle any pending + HTTP_term(); + + // Initialize and set parameters + if (! HTTP_init()) + return false; + if (! HTTP_para("CID", 1)) + return false; + if (! HTTP_para("UA", useragent)) + return false; + if (! HTTP_para("URL", url)) + return false; + + // HTTPS redirect + if (httpsredirect) { + if (! HTTP_para("REDIR",1)) + return false; + + if (! HTTP_ssl(true)) + return false; + } + + return true; +} + + +/********* HELPERS *********************************************/ + +bool Adafruit_FONA::expectReply(const char* reply, uint16_t timeout) { + readline(timeout); +#ifdef ADAFRUIT_FONA_DEBUG + printf("\t<--- %s\r\n", replybuffer); +#endif + return (strcmp(replybuffer, reply) == 0); +} + +/********* LOW LEVEL *******************************************/ + +void Adafruit_FONA::flushInput() { + // Read all available serial input to flush pending data. + uint16_t timeoutloop = 0; + while (timeoutloop++ < 40) { + while(readable()) { + getc(); + timeoutloop = 0; // If char was received reset the timer + } + wait_ms(1); + } +} + +uint16_t Adafruit_FONA::readRaw(uint16_t b) { + uint16_t idx = 0; + + while (b && (idx < sizeof(replybuffer)-1)) { + if (readable()) { + replybuffer[idx] = getc(); + idx++; + b--; + } + } + replybuffer[idx] = 0; + + return idx; +} + +// This function just reads the output from FONA after an AT command is sent to it +uint8_t Adafruit_FONA::readline(uint16_t timeout, bool multiline) { + uint16_t replyidx = 0; + + while (timeout--) { + if (replyidx >= 254) { + break; + } + + while(readable()) { + char c = getc(); + if (c == '\r') continue; + if (c == 0xA) { + if (replyidx == 0) // the first 0x0A is ignored + continue; + + if (!multiline) { + timeout = 0; // the second 0x0A is the end of the line + break; + } + } + replybuffer[replyidx] = c; + replyidx++; + } + + if (timeout == 0) { + break; + } + wait_ms(1); + } + replybuffer[replyidx] = 0; // null term + return replyidx; +} + +uint8_t Adafruit_FONA::getReply(const char* send, uint16_t timeout) { + flushInput(); + +#ifdef ADAFRUIT_FONA_DEBUG + printf("\t---> %s\r\n", send); +#endif + + mySerial.printf("%s\r\n",send); + + uint8_t l = readline(timeout); +#ifdef ADAFRUIT_FONA_DEBUG + printf("\t<--- %s\r\n", replybuffer); +#endif + return l; +} + +// Send prefix, suffix, and newline. Return response (and also set replybuffer with response). +uint8_t Adafruit_FONA::getReply(const char* prefix, char* suffix, uint16_t timeout) { + flushInput(); + +#ifdef ADAFRUIT_FONA_DEBUG + printf("\t---> %s%s\r\n", prefix, suffix); +#endif + + mySerial.printf("%s%s\r\n", prefix, suffix); + + uint8_t l = readline(timeout); +#ifdef ADAFRUIT_FONA_DEBUG + printf("\t<--- %s\r\n", replybuffer); +#endif + return l; +} + +// Send prefix, suffix, and newline. Return response (and also set replybuffer with response). +uint8_t Adafruit_FONA::getReply(const char* prefix, int32_t suffix, uint16_t timeout) { + flushInput(); + +#ifdef ADAFRUIT_FONA_DEBUG + printf("\t---> %s%d\r\n", prefix, suffix); +#endif + + mySerial.printf("%s%d\r\n", prefix, suffix); + + uint8_t l = readline(timeout); +#ifdef ADAFRUIT_FONA_DEBUG + printf("\t<--- %s\r\n", replybuffer); +#endif + return l; +} + +// Send prefix, suffix, suffix2, and newline. Return response (and also set replybuffer with response). +uint8_t Adafruit_FONA::getReply(const char* prefix, int32_t suffix1, int32_t suffix2, uint16_t timeout) { + flushInput(); + +#ifdef ADAFRUIT_FONA_DEBUG + printf("\t---> %s%d,%d\r\n", prefix, suffix1, suffix2); +#endif + + mySerial.printf("%s%d,%d\r\n", prefix, suffix1, suffix2); + + uint8_t l = readline(timeout); +#ifdef ADAFRUIT_FONA_DEBUG + printf("\t<--- %s\r\n", replybuffer); +#endif + return l; +} + +// Send prefix, ", suffix, ", and newline. Return response (and also set replybuffer with response). +uint8_t Adafruit_FONA::getReplyQuoted(const char* prefix, const char* suffix, uint16_t timeout) { + flushInput(); + +#ifdef ADAFRUIT_FONA_DEBUG + printf("\t---> %s\"%s\"\r\n", prefix, suffix); +#endif + + mySerial.printf("%s\"%s\"\r\n", prefix, suffix); + + uint8_t l = readline(timeout); +#ifdef ADAFRUIT_FONA_DEBUG + printf("\t<--- %s\r\n", replybuffer); +#endif + return l; +} + + +bool Adafruit_FONA::sendCheckReply(const char *send, const char *reply, uint16_t timeout) { + getReply(send, timeout); + + return (strcmp(replybuffer, reply) == 0); +} + +// Send prefix, suffix, and newline. Verify FONA response matches reply parameter. +bool Adafruit_FONA::sendCheckReply(const char* prefix, char *suffix, const char* reply, uint16_t timeout) { + getReply(prefix, suffix, timeout); + return (strcmp(replybuffer, reply) == 0); +} + +// Send prefix, suffix, and newline. Verify FONA response matches reply parameter. +bool Adafruit_FONA::sendCheckReply(const char* prefix, int32_t suffix, const char* reply, uint16_t timeout) { + getReply(prefix, suffix, timeout); + return (strcmp(replybuffer, reply) == 0); +} + +// Send prefix, suffix, suffix2, and newline. Verify FONA response matches reply parameter. +bool Adafruit_FONA::sendCheckReply(const char* prefix, int32_t suffix1, int32_t suffix2, const char* reply, uint16_t timeout) { + getReply(prefix, suffix1, suffix2, timeout); + return (strcmp(replybuffer, reply) == 0); +} + +// Send prefix, ", suffix, ", and newline. Verify FONA response matches reply parameter. +bool Adafruit_FONA::sendCheckReplyQuoted(const char* prefix, const char* suffix, const char* reply, uint16_t timeout) { + getReplyQuoted(prefix, suffix, timeout); + return (strcmp(replybuffer, reply) == 0); +} + +bool Adafruit_FONA::parseReply(const char* toreply, uint16_t *v, char divider, uint8_t index) { + char *p = strstr(replybuffer, toreply); // get the pointer to the voltage + if (p == 0) return false; + p += strlen(toreply); + + for (uint8_t i=0; i<index;i++) { + // increment dividers + p = strchr(p, divider); + if (!p) return false; + p++; + } + + *v = atoi(p); + + return true; +} + +bool Adafruit_FONA::parseReply(const char* toreply, char *v, char divider, uint8_t index) { + uint8_t i=0; + char *p = strstr(replybuffer, toreply); + if (p == 0) return false; + p+=strlen(toreply); + + for (i=0; i<index;i++) { + // increment dividers + p = strchr(p, divider); + if (!p) return false; + p++; + } + + for(i=0; i<strlen(p);i++) { + if(p[i] == divider) + break; + v[i] = p[i]; + } + + v[i] = '\0'; + + return true; +} + +// Parse a quoted string in the response fields and copy its value (without quotes) +// to the specified character array (v). Only up to maxlen characters are copied +// into the result buffer, so make sure to pass a large enough buffer to handle the +// response. +bool Adafruit_FONA::parseReplyQuoted(const char* toreply, char* v, int maxlen, char divider, uint8_t index) { + uint8_t i=0, j; + // Verify response starts with toreply. + char *p = strstr(replybuffer, toreply); + if (p == 0) return false; + p+=strlen(toreply); + + // Find location of desired response field. + for (i=0; i<index;i++) { + // increment dividers + p = strchr(p, divider); + if (!p) return false; + p++; + } + + // Copy characters from response field into result string. + for(i=0, j=0; j<maxlen && i<strlen(p); ++i) { + // Stop if a divier is found. + if(p[i] == divider) + break; + // Skip any quotation marks. + else if(p[i] == '"') + continue; + v[j++] = p[i]; + } + + // Add a null terminator if result string buffer was not filled. + if (j < maxlen) + v[j] = '\0'; + + return true; +} + +bool Adafruit_FONA::sendParseReply(const char* tosend, const char* toreply, uint16_t *v, char divider, uint8_t index) { + getReply(tosend); + + if (! parseReply(toreply, v, divider, index)) return false; + + readline(); // eat 'OK' + + return true; +} \ No newline at end of file
diff -r 000000000000 -r 1271d15b4d4b Adafruit_FONA.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Adafruit_FONA.h Tue May 02 03:13:27 2017 +0000 @@ -0,0 +1,542 @@ +/*************************************************** + This is a library for our Adafruit FONA Cellular Module + + Designed specifically to work with the Adafruit FONA + ----> http://www.adafruit.com/products/1946 + ----> http://www.adafruit.com/products/1963 + + These displays use TTL Serial to communicate, 2 pins are required to + interface + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + Written by Limor Fried/Ladyada for Adafruit Industries. + BSD license, all text above must be included in any redistribution + ****************************************************/ + + /* + * Modified by George Tzintzarov & Jesse Baker 03/14/2016 for use in mbed LPC1768 + */ + +#ifndef ADAFRUIT_FONA_H +#define ADAFRUIT_FONA_H + +#include "mbed.h" + +//#define ADAFRUIT_FONA_DEBUG + +#define FONA_HEADSETAUDIO 0 +#define FONA_EXTAUDIO 1 + +#define FONA_STTONE_DIALTONE 1 +#define FONA_STTONE_BUSY 2 +#define FONA_STTONE_CONGESTION 3 +#define FONA_STTONE_PATHACK 4 +#define FONA_STTONE_DROPPED 5 +#define FONA_STTONE_ERROR 6 +#define FONA_STTONE_CALLWAIT 7 +#define FONA_STTONE_RINGING 8 +#define FONA_STTONE_BEEP 16 +#define FONA_STTONE_POSTONE 17 +#define FONA_STTONE_ERRTONE 18 +#define FONA_STTONE_INDIANDIALTONE 19 +#define FONA_STTONE_USADIALTONE 20 + +#define FONA_DEFAULT_TIMEOUT_MS 500 //timeout between send AT and reply from FONA + +#define FONA_HTTP_GET 0 +#define FONA_HTTP_POST 1 +#define FONA_HTTP_HEAD 2 + +#define RX_BUFFER_SIZE 255 + +/** Adafruit FONA 800H Class +* Modified by George Tzintzarov & Jesse Baker 03/14/2016 for use in mbed LPC1768 +*/ + +class Adafruit_FONA : public Stream { + public: +/** +Listener for FONA events. Inherit this class to customize. +@code +#define FONA_RST p12 +#define FONA_TX p13 +#define FONA_RX p14 +#define FONA_RI p11 + +Adafruit_FONA my_fona(FONA_TX, FONA_RX, FONA_RST, FONA_RI); +DigitalOut led1(LED1); +class FonaEventListener : public Adafruit_FONA::EventListener { + virtual void onRing() { + led1 = 1; +} + + virtual void onNoCarrier() { + led1 = 0; + } +}; +FonaEventListener fonaEventListener; +my_fona.setEventListener(&fonaEventListener); +@endcode +*/ + + class EventListener { + public: + /** + * Method called when somebody call the FONA. + */ + virtual void onRing() = 0; + + /** + * Method called when the calling person stop his call. + */ + virtual void onNoCarrier() = 0; + }; + + public: + /** Create instance of the Adafruit_FONA + @param tx Set mbed TX + @param rx Set mbed RX + @param rst Set reset pin + @param ringIndicator Set ring indicator pin. This is to let mbed know if there is an incoming call + */ + + Adafruit_FONA(PinName tx, PinName rx, PinName rst, PinName ringIndicator) : + _rstpin(rst, false), _ringIndicatorInterruptIn(ringIndicator), + apn("FONAnet"), apnusername(NULL), apnpassword(NULL), httpsredirect(false), useragent("FONA"), + _incomingCall(false), eventListener(NULL), mySerial(tx, rx), rxBufferInIndex(0), rxBufferOutIndex(0), + currentReceivedLineSize(0) {} + + /** Built-in Test to see if FONA is connected + @param baudrate test and set at baudrate + @return true upon success + @return false upon failure. Most likely something is not hooked up. + +EXAMPLE CODE: + @code +// See if the FONA is responding +// fona is an instance of Adafruit_FONA +if (! fona.begin(9600)) { + printf("Couldn't find FONA\r\n"); + while (1); +} + @endcode + */ + bool begin(int baudrate); + + /** Set the event listener for incoming calls + @param eventListener A pointer to the event listener + @see Adafruit_FONA::EventListener for specific example + */ + + void setEventListener(EventListener *eventListener); + + // Stream---------------------------------------------------------------------- + virtual int _putc(int value); + virtual int _getc(); + + /** Check if FONA has anything in its output buffer + @return 0 if nothing + */ + int readable(void); + + // RTC---------------------------------------------------------------------- + bool enableRTC(uint8_t i); // i = 0 <=> disable, i = 1 <=> enable + + // Battery and ADC---------------------------------------------------------------------- + /** Get ADC voltage from external pin + @param v uint16_t pointer to insert ADC voltage data + @return TRUE if successful + +EXAMPLE CODE: + @code +// read the ADC +// fona is an instance of Adafruit_FONA +uint16_t adc; +if (! fona.getADCVoltage(&adc)) { + printf("Failed to read ADC\r\n"); +} +else { + printf("ADC = %d mV\r\n", adc); +} + @endcode + */ + bool getADCVoltage(uint16_t *v); + + /** Get battery percentage level + @param p uint16_t pointer to insert battery percent data + @return TRUE if successful + +EXAMPLE CODE: + @code +// read the battery percent level +// fona is an instance of Adafruit_FONA +uint16_t vbatPer; +if (! fona.getBattPercent(&vbatPer)) { + printf("Failed to read Batt\r\n"); +} +else { + printf("VPct = %d%%\r\n", vbatPer); +} + @endcode + */ + + bool getBattPercent(uint16_t *p); + + /** Get battery voltage level + @param v uint16_t pointer to insert battery voltage data + @return TRUE if successful + +EXAMPLE CODE: + @code +// read the battery voltage +// fona is an instance of Adafruit_FONA +uint16_t vbat; +if (! fona.getBattPercent(&vbat)) { + printf("Failed to read Batt\r\n"); +} +else { + printf("Vbat = %d%%\r\n", vbat); +} + @endcode + */ + bool getBattVoltage(uint16_t *v); + + // SIM query---------------------------------------------------------------------- + /** Unlock SIM if needed + @param pin 4 digit char arrary + @return TRUE if successful + */ + bool unlockSIM(char *pin); + /** Get the SIM chip card interface device (CCID) + @param ccid make sure it is at least 21 bytes long + @return length of CCID + */ + + uint8_t getSIMCCID(char *ccid); + /** Get the Network Status of FONA + @return Code 0-5 + @see https://www.adafruit.com/datasheets/sim800_series_at_command_manual_v1.01.pdf page 80 + */ + uint8_t getNetworkStatus(void); + + /** Get the RSSI of the network signal + @return RSSI value in dBm per below reference + + EXAMPLE + @code +// read the RSSI +uint8_t n = fona.getRSSI(); +int8_t r = 0; + +pcSerial.printf("RSSI = %d: ", n); +if (n == 0) r = -115; +if (n == 1) r = -111; +if (n == 31) r = -52; +if ((n >= 2) && (n <= 30)) { + r = map(n, 2, 30, -110, -54); +} +printf("%d dBm\r\n", r); + +// helper function MAP to do calculations +long MAP(long x, long in_min, long in_max, long out_min, long out_max) +{ + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + @endcode + @see https://www.adafruit.com/datasheets/sim800_series_at_command_manual_v1.01.pdf page 82 + */ + uint8_t getRSSI(void); + + // IMEI---------------------------------------------------------------------- + /** Get the International Mobile Station Equipment Identity (IMEI) + @param imei A char array with minimum length 16 + @return The IMEI of the device + +EXAMPLE CODE: + @code +// Print SIM card IMEI number. +char imei[15] = {0}; // MUST use a 16 character buffer for IMEI! +uint8_t imeiLen = fona.getIMEI(imei); //fona is an instance of Adafruit_FONA +if (imeiLen > 0) { + pcSerial.printf("SIM card IMEI: %s\r\n", imei); +} + @endcode + */ + uint8_t getIMEI(char *imei); + + // set Audio output---------------------------------------------------------------------- + /** Set the Audio Output interface + @param a 0 is headset, 1 is external audio + @return TRUE if successful + */ + bool setAudio(uint8_t a); + + /** Set the Audio Volume + @param i a unit8_t volume number + @return TRUE if successful + */ + bool setVolume(uint8_t i); + + /** Get the Audio Volume + @return the current volume + */ + uint8_t getVolume(void); + bool playToolkitTone(uint8_t t, uint16_t len); + bool setMicVolume(uint8_t a, uint8_t level); + bool playDTMF(char tone); + + // FM radio functions---------------------------------------------------------------------- + /** Tune the FM radio + @param station frequency, for example 107.9 MHz -> 1079 + @return TRUE if successful + */ + bool tuneFMradio(uint16_t station); + + /** FM radio set output + @param onoff bool to turn on if TRUE + @param a 0 (default) is headset, 1 is external audio + @return TRUE if successful + */ + bool FMradio(bool onoff, uint8_t a = FONA_HEADSETAUDIO); + + /** Set the FM Radio Volume + @param i a unit8_t volume number + @return TRUE if successful + */ + bool setFMVolume(uint8_t i); + + /** Get the FM Volume + @return the current FM volume + */ + int8_t getFMVolume(); + + /** Get the FM signal strength + @param station a unit8_t volume number + @return TRUE if successful + */ + int8_t getFMSignalLevel(uint16_t station); + + // SMS handling---------------------------------------------------------------------- + /** Set the SMS Interrupt + @param i 0 = OFF, 1 = ON with TCPIP, FTP, and URC control Ring Indicator Pin, 2 = ON with only TCPIP control + @return TRUE if successful + @see https://www.adafruit.com/datasheets/sim800_series_at_command_manual_v1.01.pdf page 152 + */ + bool setSMSInterrupt(uint8_t i); + + /** Get SMS Interrupt Setting + @return setting + @see https://www.adafruit.com/datasheets/sim800_series_at_command_manual_v1.01.pdf page 152 + */ + uint8_t getSMSInterrupt(void); + + /** Set the SMS Interrupt + @return number of SMS messages in inbox + */ + int8_t getNumSMS(void); + + /** Read SMS + @param i sms number in memory + @param smsbuff char pointer to char array + @param max Maximum length of smsbuff + @param readsize the size in bytes of the SMS + @return TRUE if successful + */ + bool readSMS(uint8_t i, char *smsbuff, uint16_t max, uint16_t *readsize); + + /** Send SMS + @param smsaddr Phone number to send out + @param smsmsg Char array containing message + @return TRUE if successful + */ + bool sendSMS(char *smsaddr, char *smsmsg); + + /** Delete SMS + @param i number of SMS in memory + @return TRUE if successful + */ + bool deleteSMS(uint8_t i); + + /** Send SMS + @param i Number of SMS in memory + @param sender Char array to store the sender number + @param senderlen length of sender + @return TRUE if successful + */ + bool getSMSSender(uint8_t i, char *sender, int senderlen); + + // Time---------------------------------------------------------------------- + /** Enable FONA to sync time with the cellular network + @param onoff on = true, off = false + @return TRUE if successful + */ + bool enableNetworkTimeSync(bool onoff); + + /** Enable FONA to sync time with the time server + @param onoff true = on, false = off + @return TRUE if successful + */ + bool enableNTPTimeSync(bool onoff, const char* ntpserver=0); + + /** Retrieve the current time from the enabled server + @param buff char array to store time value. Given as "yy/MM/dd,hh:mm:ss+zz" + @param maxlen Maximum length of the char array + @return TRUE if successful + */ + bool getTime(char* buff, uint16_t maxlen); + + // GPRS handling---------------------------------------------------------------------- + bool enableGPRS(bool onoff); + uint8_t GPRSstate(void); + bool getGSMLoc(uint16_t *replycode, char *buff, uint16_t maxlen); + bool getGSMLoc(float *lat, float *lon); + void setGPRSNetworkSettings(const char* apn, const char* username=0, const char* password=0); + + // GPS handling---------------------------------------------------------------------- + bool enableGPS(bool onoff); + int8_t GPSstatus(void); + uint8_t getGPS(uint8_t arg, char *buffer, uint8_t maxbuff); + bool getGPS(float *lat, float *lon, float *speed_kph=0, float *heading=0, float *altitude=0); + bool enableGPSNMEA(uint8_t nmea); + + // TCP raw connections---------------------------------------------------------------------- + bool TCPconnect(char *server, uint16_t port); + bool TCPclose(void); + bool TCPconnected(void); + bool TCPsend(char *packet, uint8_t len); + uint16_t TCPavailable(void); + uint16_t TCPread(uint8_t *buff, uint8_t len); + + // HTTP low level interface (maps directly to SIM800 commands).---------------------------------------------------------------------- + bool HTTP_init(); + bool HTTP_term(); + void HTTP_para_start(const char* parameter, bool quoted = true); + bool HTTP_para_end(bool quoted = true); + bool HTTP_para(const char* parameter, const char *value); + bool HTTP_para(const char* parameter, int32_t value); + bool HTTP_data(uint32_t size, uint32_t maxTime=10000); + bool HTTP_action(uint8_t method, uint16_t *status, uint16_t *datalen, int32_t timeout = 10000); + bool HTTP_readall(uint16_t *datalen); + bool HTTP_ssl(bool onoff); + + // HTTP high level interface (easier to use, less flexible).---------------------------------------------------------------------- + bool HTTP_GET_start(char *url, uint16_t *status, uint16_t *datalen); + void HTTP_GET_end(void); + bool HTTP_POST_start(char *url, const char* contenttype, const uint8_t *postdata, uint16_t postdatalen, uint16_t *status, uint16_t *datalen); + void HTTP_POST_end(void); + void setUserAgent(const char* useragent); + + // HTTPS---------------------------------------------------------------------- + void setHTTPSRedirect(bool onoff); + + // PWM (buzzer)---------------------------------------------------------------------- + /** Control the buzzer capability of the PWM out on the FONA + @param period of the buzzing cycle (max 2000) + @param duty the duty cycle of the buzzer (0 to 100) + @return TRUE if successful + */ + bool setPWM(uint16_t period, uint8_t duty = 50); + + // Phone calls---------------------------------------------------------------------- + /** Call a phone + @param phonenum a character array of the phone number + @return TRUE if successful + */ + bool callPhone(char *phonenum); + + /** Hang up a phone call + */ + bool hangUp(void); + + /** Answer a phone call + */ + bool pickUp(void); + + /** Enable/disable caller ID + @param enable true to enable, false to disable + @return TRUE if successful + */ + bool callerIdNotification(bool enable); + + /** Retrieve the incoming call number + @param phonenum a character array of the phone number calling + @return TRUE if successful + */ + bool incomingCallNumber(char* phonenum); + + // Helper functions to verify responses. + bool expectReply(const char* reply, uint16_t timeout = 10000); + + private: + DigitalOut _rstpin; + InterruptIn _ringIndicatorInterruptIn; + + char replybuffer[255]; // the output of getreply(), readline() is the function that changes the replybuffer + char* apn; + char* apnusername; + char* apnpassword; + bool httpsredirect; + char* useragent; + + volatile bool _incomingCall; + EventListener *eventListener; + Serial mySerial; + + // Circular buffer used to receive serial data from an interruption + int rxBuffer[RX_BUFFER_SIZE + 1]; + volatile int rxBufferInIndex; // Index where new data is added to the buffer + volatile int rxBufferOutIndex; // Index where data is removed from the buffer + char currentReceivedLine[RX_BUFFER_SIZE]; // Array containing the current received line + int currentReceivedLineSize; + + inline bool isRxBufferFull() { + return ((rxBufferInIndex + 1) % RX_BUFFER_SIZE) == rxBufferOutIndex; + } + + inline bool isRxBufferEmpty() { + return rxBufferInIndex == rxBufferOutIndex; + } + + inline void incrementRxBufferInIndex() { + rxBufferInIndex = (rxBufferInIndex + 1) % RX_BUFFER_SIZE; + } + + inline void incrementRxBufferOutIndex() { + rxBufferOutIndex = (rxBufferOutIndex + 1) % RX_BUFFER_SIZE; + } + + /** + * Method called when Serial data is received (interrupt routine). + */ + void onSerialDataReceived(); + + // HTTP helpers + bool HTTP_setup(char *url); + + void flushInput(); + uint16_t readRaw(uint16_t b); + uint8_t readline(uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS, bool multiline = false); + uint8_t getReply(const char* send, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); + uint8_t getReply(const char* prefix, char *suffix, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); + uint8_t getReply(const char* prefix, int32_t suffix, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); + uint8_t getReply(const char* prefix, int32_t suffix1, int32_t suffix2, uint16_t timeout); // Don't set default value or else function call is ambiguous. + uint8_t getReplyQuoted(const char* prefix, const char* suffix, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); + + bool sendCheckReply(const char* send, const char* reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); + bool sendCheckReply(const char* prefix, char *suffix, const char* reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); + bool sendCheckReply(const char* prefix, int32_t suffix, const char* reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); + bool sendCheckReply(const char* prefix, int32_t suffix, int32_t suffix2, const char* reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); + bool sendCheckReplyQuoted(const char* prefix, const char* suffix, const char* reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); + + bool parseReply(const char* toreply, uint16_t *v, char divider = ',', uint8_t index=0); + bool parseReply(const char* toreply, char *v, char divider = ',', uint8_t index=0); + bool parseReplyQuoted(const char* toreply, char* v, int maxlen, char divider, uint8_t index); + + bool sendParseReply(const char* tosend, const char* toreply, uint16_t *v, char divider = ',', uint8_t index = 0); + + void onIncomingCall(); +}; + +#endif \ No newline at end of file
diff -r 000000000000 -r 1271d15b4d4b BACKUP_main.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BACKUP_main.txt Tue May 02 03:13:27 2017 +0000 @@ -0,0 +1,954 @@ +/*************************************************** + This is an example for our Adafruit FONA Cellular Module + + Designed specifically to work with the Adafruit FONA + ----> http://www.adafruit.com/products/1946 + ----> http://www.adafruit.com/products/1963 + ----> http://www.adafruit.com/products/2468 + ----> http://www.adafruit.com/products/2542 + + These cellular modules use TTL Serial to communicate, 2 pins are + required to interface + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + Written by Limor Fried/Ladyada for Adafruit Industries. + BSD license, all text above must be included in any redistribution + ****************************************************/ + + /* + * Modified by Jesse Baker & George Tzintzarov 03/30/2016 for use in mbed LPC1768 + */ + +/* +THIS CODE IS STILL IN PROGRESS! + +Open up the serial console on the Arduino at 4800 baud to interact with FONA + +Note that if you need to set a GPRS APN, username, and password scroll down to +the commented section below just before the main "while (true)" loop. +*/ + +#include <string.h> //// BY JONATHAN: For strcpy() +#include <ctype.h> +//#include "SoftSerial.h" I dont think we need this +#include "Adafruit_FONA.h" +#include "emic2.h" + +#define FONA_RST p12 +#define FONA_TX p13 +#define FONA_RX p14 +#define FONA_RI p11 + +// this is a large buffer for replies +char replybuffer[255]; +char smsText[255], smsPhoneNo[11]; ///// By Jonathan: Text to send to Text -> Speech chip & phone # to send to + +int count; // by Jonathan + + +Serial pcSerial(USBTX, USBRX); +Adafruit_FONA fona(FONA_TX, FONA_RX, FONA_RST, FONA_RI); +//uLCD_4DGL uLCD(p28,p27,p30); + +// Turn on a LED when somebody call the FONA +DigitalOut led1(LED1); +emic2 myTTS(p9, p10); + +class FonaEventListener : public Adafruit_FONA::EventListener { + virtual void onRing() { + led1 = 1; + } + + virtual void onNoCarrier() { + led1 = 0; + } +}; +FonaEventListener fonaEventListener; + +// Functions defined after main() +uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout = 0); +void printMenu(void); +void flushSerial(); +char readBlocking(); +uint16_t readnumber(); +long map(long x, long in_min, long in_max, long out_min, long out_max); + +int main() { + myTTS.volume(5); + myTTS.voice(0); + pcSerial.baud(9600); + wait(1); + pcSerial.printf("\r\n"); + + pcSerial.printf("FONA basic test\r\n"); + pcSerial.printf("Initializing....(May take 3 seconds)\r\n"); + + // See if the FONA is responding + if (! fona.begin(9600)) { + pcSerial.printf("Couldn't find FONA\r\n"); + while (1); + } + fona.setEventListener(&fonaEventListener); + pcSerial.printf("FONA is OK\r\n"); + + // Print SIM card IMEI number. + char imei[15] = {0}; // MUST use a 16 character buffer for IMEI! + uint8_t imeiLen = fona.getIMEI(imei); + if (imeiLen > 0) { + pcSerial.printf("SIM card IMEI: %s\r\n", imei); + } + + // Optionally configure a GPRS APN, username, and password. + // You might need to do this to access your network's GPRS/data + // network. Contact your provider for the exact APN, username, + // and password values. Username and password are optional and + // can be removed, but APN is required. + //fona.setGPRSNetworkSettings("your APN", "your username", "your password"); + //fona.setGPRSNetworkSettings("web.pt.lu", "", ""); + + // Optionally configure HTTP gets to follow redirects over SSL. + // Default is not to follow SSL redirects, however if you uncomment + // the following line then redirects over SSL will be followed. + //fona.setHTTPSRedirect(true); + + printMenu(); + + + while (true) { + + pcSerial.printf("FONA> "); + // if nothing is available on the pcSearial port but there is something on the fona serial, then print it (flush it) to the pc Serial + + /* + while (! pcSerial.readable() ) { + if (fona.readable()) { + pcSerial.putc(fona.getc()); /////// RESPONSIBLE FOR DETECTING RECV'D TXT/////// + } + } */ + + //////////////////// By Jonathan: Edited version of while() above + while (! pcSerial.readable()) { + if (fona.readable()) { + + //// Printf that incoming SMS detected + pcSerial.putc(fona.getc()); + + + // ----------------------------------------------------------------// + + // read an SMS + send -> TTS chip + flushSerial(); + pcSerial.printf("\r\nReading SMS #1\r\n"); + + // Retrieve SMS sender address/phone number. + if (! fona.getSMSSender(1, replybuffer, 250)) { + pcSerial.printf("Failed!\r\n"); + break; + } + pcSerial.printf("FROM: %s\r\n", replybuffer); + for (int i = 0; i < 10; i++) { /////// BY JONATHAN to store phone # to respond to + smsPhoneNo[i] = replybuffer[i + 2]; // chop off the "+1" from phone # returned by replybuffer + } + smsPhoneNo[10] = '\0'; // null terminate.... NECESSARY?? + pcSerial.printf("FROM: %s\r\n", smsPhoneNo); + + // Retrieve SMS value. + uint16_t smslen; + if (! fona.readSMS(1, replybuffer, 250, &smslen)) { // pass in buffer and max len! + pcSerial.printf("Failed!\r\n"); + break; + } + pcSerial.printf("***** SMS #1 (%d) bytes *****\r\n", smslen); + pcSerial.printf("%s\r\n", replybuffer); + pcSerial.printf("*****\r\n"); + + + + //char message[255]; // CHANGED BY JONATHAN. 141 -> 255 + char myString[255]; + + for (int i = 0; i < 255; i++) { + myString[i] = replybuffer[i + 5]; // chop of the "Alexa string" + } + + strcpy(smsText, "Uh lex uh "); //Pronunciation Correction. + strcat(smsText, myString); + myTTS.speakf("S%s\r", smsText); // Send text message to the text to speech module. + + + // ----------------------------------------------------------------// + + // send an SMS back! + char message[255]; + + strcpy(message, ""); + + flushSerial(); + + pcSerial.printf("Replying to %s\r\n", smsPhoneNo); + + + if(strstr(replybuffer, "how old are you")) { // if reply buffer contains that string + strcpy(message, "I'm 2 in human years, 14 in dog years, and 25 in cat years. I think AI years are marked in nanoseconds, so that makes me, like, a scrillion!"); + } + else if(strstr(replybuffer, "what is the world population")) { + strcpy(message, "The population of the world is about 7 Billion 400 Million."); + } + else if(strstr(replybuffer, "integral of x squared")) { + strcpy(message, "The integral of x squared is one third x cubed plus a constant."); + } + else if(strstr(replybuffer, "discrete co sine transform")) { + strcpy(message, "The discrete cosine transform expresses a finite sequence of data points in terms of a sum of cosine function oscillating at different frequencies."); + } + else { + strcpy(message, "Sorry, command not recognized."); + } + + + + // message[255] = '\0'; + + pcSerial.printf("%s\r\n", message); + if (!fona.sendSMS(smsPhoneNo, message)) + pcSerial.printf("Failed\r\n"); + else + pcSerial.printf("Sent!\r\n"); + + // ----------------------------------------------------------------// + + // delete an SMS after response sent back + flushSerial(); + pcSerial.printf("\r\nDeleting SMS #1\r\n"); + if (fona.deleteSMS(1)) // delete SMS #1 + pcSerial.printf("OK!\r\n"); + else + pcSerial.printf("Couldn't delete\r\n"); + + } // end if + } // end while + + + + // Above while() by Jonathan // + + + + // get the input command from the terminal + char command = pcSerial.getc(); + pcSerial.printf("%c\r\n", command); //loops back to COM port + + + switch (command) { + case '?': { + printMenu(); + break; + } + + case 'a': { + // read the ADC + uint16_t adc; + if (! fona.getADCVoltage(&adc)) { + pcSerial.printf("Failed to read ADC\r\n"); + } else { + pcSerial.printf("ADC = %d mV\r\n", adc); + } + break; + } + + case 'b': { + // read the battery voltage and percentage + uint16_t vbat; + if (! fona.getBattVoltage(&vbat)) { + pcSerial.printf("Failed to read Batt\r\n"); + } else { + pcSerial.printf("VBat = %d mV\r\n", vbat); + } + + if (! fona.getBattPercent(&vbat)) { + pcSerial.printf("Failed to read Batt\r\n"); + } else { + pcSerial.printf("VPct = %d%%\r\n", vbat); + } + + break; + } + + case 'U': { + // Unlock the SIM with a PIN code + char PIN[5]; + flushSerial(); + pcSerial.printf("Enter 4-digit PIN\r\n"); + readline(PIN, 3); + pcSerial.printf("%s\r\n", PIN); + pcSerial.printf("Unlocking SIM card: "); + if (! fona.unlockSIM(PIN)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + break; + } + + case 'C': { + // read the CCID + fona.getSIMCCID(replybuffer); // make sure replybuffer is at least 21 bytes! + pcSerial.printf("SIM CCID = %s\r\n", replybuffer); + break; + } + + case 'i': { + // read the RSSI + uint8_t n = fona.getRSSI(); + int8_t r = 0; + + pcSerial.printf("RSSI = %d: ", n); + if (n == 0) r = -115; + if (n == 1) r = -111; + if (n == 31) r = -52; + if ((n >= 2) && (n <= 30)) { + r = map(n, 2, 30, -110, -54); + } + pcSerial.printf("%d dBm\r\n", r); + + break; + } + + case 'n': { + // read the network/cellular status + uint8_t n = fona.getNetworkStatus(); + pcSerial.printf("Network status %d: ", n); + if (n == 0) pcSerial.printf("Not registered\r\n"); + if (n == 1) pcSerial.printf("Registered (home)\r\n"); + if (n == 2) pcSerial.printf("Not registered (searching)\r\n"); + if (n == 3) pcSerial.printf("Denied\r\n"); + if (n == 4) pcSerial.printf("Unknown\r\n"); + if (n == 5) pcSerial.printf("Registered roaming\r\n"); + break; + } + + /*** Audio ***/ + case 'v': { + // set volume + flushSerial(); + pcSerial.printf("Set Vol %%"); + uint8_t vol = readnumber(); + pcSerial.printf("\r\n"); + if (! fona.setVolume(vol)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + break; + } + + case 'V': { + uint8_t v = fona.getVolume(); + pcSerial.printf("%d%%\r\n", v); + + break; + } + + case 'H': { + // Set Headphone output + if (! fona.setAudio(FONA_HEADSETAUDIO)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + fona.setMicVolume(FONA_HEADSETAUDIO, 15); + break; + } + case 'e': { + // Set External output + if (! fona.setAudio(FONA_EXTAUDIO)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + + fona.setMicVolume(FONA_EXTAUDIO, 10); + break; + } + + case 'T': { + // play tone + flushSerial(); + pcSerial.printf("Play tone #"); + uint8_t kittone = readnumber(); + pcSerial.printf("\r\n"); + // play for 1 second (1000 ms) + if (! fona.playToolkitTone(kittone, 1000)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + break; + } + + /*** FM Radio ***/ + + case 'f': { + // get freq + flushSerial(); + pcSerial.printf("FM Freq (eg 1011 == 101.1 MHz): "); + uint16_t station = readnumber(); + pcSerial.printf("\r\n"); + // FM radio ON using headset + if (fona.FMradio(true, FONA_HEADSETAUDIO)) { + pcSerial.printf("Opened\r\n"); + } + if (! fona.tuneFMradio(station)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("Tuned\r\n"); + } + break; + } + case 'F': { + // FM radio off + if (! fona.FMradio(false)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + break; + } + case 'm': { + // Set FM volume. + flushSerial(); + pcSerial.printf("Set FM Vol [0-6]:"); + uint8_t vol = readnumber(); + pcSerial.printf("\r\n"); + if (!fona.setFMVolume(vol)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + break; + } + case 'M': { + // Get FM volume. + int8_t fmvol = fona.getFMVolume(); + if (fmvol < 0) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("FM volume: %d\r\n", fmvol); + } + break; + } + case 'q': { + // Get FM station signal level (in decibels). + flushSerial(); + pcSerial.printf("FM Freq (eg 1011 == 101.1 MHz): "); + uint16_t station = readnumber(); + pcSerial.printf("\r\n"); + int8_t level = fona.getFMSignalLevel(station); + if (level < 0) { + pcSerial.printf("Failed! Make sure FM radio is on (tuned to station).\r\n"); + } else { + pcSerial.printf("Signal level (dB): %d\r\n", level); + } + break; + } + + /*** PWM ***/ + + case 'P': { + // PWM Buzzer output @ 2KHz max + flushSerial(); + pcSerial.printf("PWM Freq, 0 = Off, (1-2000): "); + uint16_t freq = readnumber(); + pcSerial.printf("\r\n"); + if (! fona.setPWM(freq)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + break; + } + + /*** Call ***/ + case 'c': { + // call a phone! + char number[10]; + flushSerial(); + pcSerial.printf("Call #"); + readline(number, 9); + pcSerial.printf("\r\n"); + pcSerial.printf("Calling %s\r\n", number); + if (!fona.callPhone(number)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("Sent!\r\n"); + } + + break; + } + case 'h': { + // hang up! + if (! fona.hangUp()) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + break; + } + + case 'p': { + // pick up! + if (! fona.pickUp()) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + break; + } + + /*** SMS ***/ + + case 'N': { + // read the number of SMS's! + int8_t smsnum = fona.getNumSMS(); + if (smsnum < 0) { + pcSerial.printf("Could not read # SMS\r\n"); + } else { + pcSerial.printf("%d SMS's on SIM card!\r\n", smsnum); + } + break; + } + case 'r': { + // read an SMS + flushSerial(); + pcSerial.printf("Read #"); + uint8_t smsn = readnumber(); + pcSerial.printf("\r\nReading SMS #%d\r\n", smsn); + + // Retrieve SMS sender address/phone number. + if (! fona.getSMSSender(smsn, replybuffer, 250)) { + pcSerial.printf("Failed!\r\n"); + break; + } + pcSerial.printf("FROM: %s\r\n", replybuffer); + + // Retrieve SMS value. + uint16_t smslen; + if (! fona.readSMS(smsn, replybuffer, 250, &smslen)) { // pass in buffer and max len! + pcSerial.printf("Failed!\r\n"); + break; + } + pcSerial.printf("***** SMS #%d (%d) bytes *****\r\n", smsn, smslen); + pcSerial.printf("%s\r\n", replybuffer); + pcSerial.printf("*****\r\n"); + + break; + } + case 'R': { + // read all SMS + int8_t smsnum = fona.getNumSMS(); + uint16_t smslen; + for (int8_t smsn=1; smsn<=smsnum; smsn++) { + pcSerial.printf("\r\nReading SMS #%d\r\n", smsn); + if (!fona.readSMS(smsn, replybuffer, 250, &smslen)) { // pass in buffer and max len! + pcSerial.printf("Failed!\r\n"); + break; + } + // if the length is zero, its a special case where the index number is higher + // so increase the max we'll look at! + if (smslen == 0) { + pcSerial.printf("[empty slot]\r\n"); + smsnum++; + continue; + } + + pcSerial.printf("***** SMS #%d (%d) bytes *****\r\n", smsn, smslen); + pcSerial.printf("%s\r\n", replybuffer); + pcSerial.printf("*****\r\n"); + } + break; + } + + case 'd': { + // delete an SMS + flushSerial(); + pcSerial.printf("Delete #"); + uint8_t smsn = readnumber(); + + pcSerial.printf("\r\nDeleting SMS #%d\r\n", smsn); + if (fona.deleteSMS(smsn)) { + pcSerial.printf("OK!\r\n"); + } else { + pcSerial.printf("Couldn't delete\r\n"); + } + break; + } + + case 's': { + // send an SMS! + char sendto[10], message[141],currChar; // 'currChar' by Jonathan + count = 0; // reset + + flushSerial(); + pcSerial.printf("Send to #"); + //currChar = pcSerial.getc(); + readline(sendto, 9); + pcSerial.printf("%s\r\n", sendto); + pcSerial.printf("Type out one-line message (140 char): "); + + count = 0; + while (1) // whole while loop added by jonathan... WORKS PERFECTLY for sending texts to phone + { + + pcSerial.putc(currChar = pcSerial.getc()); // local echo + if (currChar == '\r') + { + pcSerial.printf("breaking\r\n"); + message[count] = '\0'; // null terminate... NECESSARY?? + break; + } + message[count] = currChar; // fill in char array + count++; // global var update + //pcSerial.printf("\n%d\n", count); + } + + //readline(message, count); // edited by JONATHAN (140 -> 'count'). THEN COMPLETELY COMMENTED OUT, b/c I write directly to message[] above + //pcSerial.printf("\n%d\n", count); // added by jonathan + + + pcSerial.printf("%s\r\n", message); + if (!fona.sendSMS(sendto, message)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("Sent!\r\n"); + } + + break; + } + + /*** Time ***/ + + case 'y': { + // enable network time sync + if (!fona.enableNetworkTimeSync(true)) + pcSerial.printf("Failed to enable\r\n"); + break; + } + + case 'Y': { + // enable NTP time sync + if (!fona.enableNTPTimeSync(true, "pool.ntp.org")) + pcSerial.printf("Failed to enable\r\n"); + break; + } + + case 't': { + // read the time + char buffer[23]; + + fona.getTime(buffer, 23); // make sure replybuffer is at least 23 bytes! + pcSerial.printf("Time = %s\r\n", buffer); + break; + } + + /*********************************** GPS (SIM808 only) */ + + case 'o': { + // turn GPS off + if (!fona.enableGPS(false)) + pcSerial.printf("Failed to turn off\r\n"); + break; + } + case 'O': { + // turn GPS on + if (!fona.enableGPS(true)) + pcSerial.printf("Failed to turn on\r\n"); + break; + } + case 'x': { + int8_t stat; + // check GPS fix + stat = fona.GPSstatus(); + if (stat < 0) + pcSerial.printf("Failed to query\r\n"); + if (stat == 0) pcSerial.printf("GPS off\r\n"); + if (stat == 1) pcSerial.printf("No fix\r\n"); + if (stat == 2) pcSerial.printf("2D fix\r\n"); + if (stat == 3) pcSerial.printf("3D fix\r\n"); + break; + } + + case 'L': { + // check for GPS location + char gpsdata[80]; + fona.getGPS(0, gpsdata, 80); + pcSerial.printf("Reply in format: mode,longitude,latitude,altitude,utctime(yyyymmddHHMMSS),ttff,satellites,speed,course\r\n"); + pcSerial.printf("%s\r\n", gpsdata); + + break; + } + + case 'E': { + flushSerial(); + pcSerial.printf("GPS NMEA output sentences (0 = off, 34 = RMC+GGA, 255 = all)\r\n"); + uint8_t nmeaout = readnumber(); + + // turn on NMEA output + fona.enableGPSNMEA(nmeaout); + + break; + } + + /*********************************** GPRS */ + + case 'g': { + // turn GPRS off + if (!fona.enableGPRS(false)) + pcSerial.printf("Failed to turn off\r\n"); + break; + } + case 'G': { + // turn GPRS on + if (!fona.enableGPRS(true)) + pcSerial.printf("Failed to turn on\r\n"); + break; + } + case 'l': { + // check for GSMLOC (requires GPRS) + uint16_t returncode; + + if (!fona.getGSMLoc(&returncode, replybuffer, 250)) + pcSerial.printf("Failed!\r\n"); + if (returncode == 0) { + pcSerial.printf("%s\r\n", replybuffer); + } else { + pcSerial.printf("Fail code #%d\r\n", returncode); + } + + break; + } + case 'w': { + // read website URL + uint16_t statuscode; + int16_t length; + char url[80]; + + flushSerial(); + pcSerial.printf("NOTE: in beta! Use small webpages to read!\r\n"); + pcSerial.printf("URL to read (e.g. www.adafruit.com/testwifi/index.html):\r\n"); + pcSerial.printf("http://"); readline(url, 79); + pcSerial.printf("%s\r\n", url); + + pcSerial.printf("****\r\n"); + if (!fona.HTTP_GET_start(url, &statuscode, (uint16_t *)&length)) { + pcSerial.printf("Failed!\r\n"); + break; + } + while (length > 0) { + while (fona.readable()) { + char c = fona.getc(); + pcSerial.putc(c); + length--; + if (! length) break; + } + } + pcSerial.printf("\r\n****\r\n"); + fona.HTTP_GET_end(); + break; + } + + case 'W': { + // Post data to website + uint16_t statuscode; + int16_t length; + char url[80]; + char data[80]; + + flushSerial(); + pcSerial.printf("NOTE: in beta! Use simple websites to post!\r\n"); + pcSerial.printf("URL to post (e.g. httpbin.org/post):\r\n"); + pcSerial.printf("http://"); readline(url, 79); + pcSerial.printf("%s\r\n", url); + pcSerial.printf("Data to post (e.g. \"foo\" or \"{\"simple\":\"json\"}\"):\r\n"); + readline(data, 79); + pcSerial.printf("%s\r\n", data); + + pcSerial.printf("****\r\n"); + if (!fona.HTTP_POST_start(url, "text/plain", (uint8_t *) data, strlen(data), &statuscode, (uint16_t *)&length)) { + pcSerial.printf("Failed!\r\n"); + break; + } + while (length > 0) { + while (fona.readable()) { + char c = fona.getc(); + pcSerial.putc(c); + length--; + if (! length) break; + } + } + pcSerial.printf("\r\n****\r\n"); + fona.HTTP_POST_end(); + break; + } + /*****************************************/ + + case 'S': { + pcSerial.printf("Creating SERIAL TUBE\r\n"); + while (1) { + while (pcSerial.readable()) { + wait_ms(1); + fona.putc(pcSerial.getc()); + } + if (fona.readable()) { + pcSerial.putc(fona.getc()); + } + } + } + + default: { + pcSerial.printf("Unknown command\r\n"); + printMenu(); + break; + } + } // end switch + // flush input + flushSerial(); + while (fona.readable()) { + pcSerial.putc(fona.getc()); + } + } // end while() +} + +void printMenu(void) { + pcSerial.printf("-------------------------------------\r\n"); + pcSerial.printf("[?] Print this menu\r\n"); + pcSerial.printf("[a] read the ADC (2.8V max)\r\n"); + pcSerial.printf("[b] read the Battery V and %% charged\r\n"); + pcSerial.printf("[C] read the SIM CCID\r\n"); + pcSerial.printf("[U] Unlock SIM with PIN code\r\n"); + pcSerial.printf("[i] read RSSI\r\n"); + pcSerial.printf("[n] get Network status\r\n"); + pcSerial.printf("[v] set audio Volume\r\n"); + pcSerial.printf("[V] get Volume\r\n"); + pcSerial.printf("[H] set Headphone audio\r\n"); + pcSerial.printf("[e] set External audio\r\n"); + pcSerial.printf("[T] play audio Tone\r\n"); + pcSerial.printf("[P] PWM/Buzzer out\r\n"); + + // FM (SIM800 only) + pcSerial.printf("[f] tune FM radio\r\n"); + pcSerial.printf("[F] turn off FM\r\n"); + pcSerial.printf("[m] set FM volume\r\n"); + pcSerial.printf("[M] get FM volume\r\n"); + pcSerial.printf("[q] get FM station signal level\r\n"); + + // Phone + pcSerial.printf("[c] make phone Call\r\n"); + pcSerial.printf("[h] Hang up phone\r\n"); + pcSerial.printf("[p] Pick up phone\r\n"); + + // SMS + pcSerial.printf("[N] Number of SMSs\r\n"); + pcSerial.printf("[r] Read SMS #\r\n"); + pcSerial.printf("[R] Read All SMS\r\n"); + pcSerial.printf("[d] Delete SMS #\r\n"); + pcSerial.printf("[s] Send SMS\r\n"); + + // Time + pcSerial.printf("[y] Enable network time sync\r\n"); + pcSerial.printf("[Y] Enable NTP time sync (GPRS)\r\n"); + pcSerial.printf("[t] Get network time\r\n"); + + // GPRS + pcSerial.printf("[G] Enable GPRS\r\n"); + pcSerial.printf("[g] Disable GPRS\r\n"); + pcSerial.printf("[l] Query GSMLOC (GPRS)\r\n"); + pcSerial.printf("[w] Read webpage (GPRS)\r\n"); + pcSerial.printf("[W] Post to website (GPRS)\r\n"); + + // GPS + pcSerial.printf("[O] Turn GPS on (SIM808)\r\n"); + pcSerial.printf("[o] Turn GPS off (SIM808)\r\n"); + pcSerial.printf("[x] GPS fix status (SIM808)\r\n"); + pcSerial.printf("[L] Query GPS location (SIM808)\r\n"); + pcSerial.printf("[E] Raw NMEA out (SIM808)\r\n"); + + pcSerial.printf("[S] create Serial passthru tunnel\r\n"); + pcSerial.printf("-------------------------------------\r\n"); + pcSerial.printf("\r\n"); +} + +void flushSerial() { + while (pcSerial.readable()) + pcSerial.getc(); +} + +char readBlocking() { + while (!pcSerial.readable()); + return pcSerial.getc(); +} + +uint16_t readnumber() { + uint16_t x = 0; + char c; + while (! isdigit(c = readBlocking())) { + //pcSerial.putc(c); + } + pcSerial.putc(c); + x = c - '0'; + while (isdigit(c = readBlocking())) { + pcSerial.putc(c); + x *= 10; + x += c - '0'; + } + return x; +} + +uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout) { + uint16_t buffidx = 0; + bool timeoutvalid = true; + if (timeout == 0) timeoutvalid = false; + + while (true) { + if (buffidx > maxbuff) { + //pcSerial.printf("SPACE\r\n"); + break; + } + + while(pcSerial.readable()) { + char c = pcSerial.getc(); + + //pcSerial.printf("%02x#%c\r\n", c, c); + + if (c == '\r') + continue; + + + if (c == '\r') { /////////////////////////////////////////// CHANGED BY JONATHAN: (0XA -> '\r') + if (buffidx == 0) // the first 0x0A is ignored + continue; + + timeout = 0; // the second 0x0A is the end of the line + timeoutvalid = true; + break; + } + buff[buffidx] = c; + buffidx++; + + count++; ///////////////////////// ADED BY JONATHAN + } + + if (timeoutvalid && timeout == 0) { + //pcSerial.printf("TIMEOUT\r\n"); + break; + } + wait_ms(1); + } + buff[buffidx] = 0; // null term + return buffidx; +} + +long map(long x, long in_min, long in_max, long out_min, long out_max) +{ + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +}
diff -r 000000000000 -r 1271d15b4d4b UPDATED_BACKUP_main.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UPDATED_BACKUP_main.txt Tue May 02 03:13:27 2017 +0000 @@ -0,0 +1,1234 @@ +// Author: Alexander Mussa, Jonathan Osei-Owusu +// Purpose: Integrate ESP8266 WiFi Chip with Adafruit FONA Cellular Module to send text commands to Amazon Echo Dot +// 4180 Final Project + +/*************************************************** + This is an example for our Adafruit FONA Cellular Module + ESP8266 WiFi Chip + + Designed specifically to work with the Adafruit FONA + ----> http://www.adafruit.com/products/1946 + ----> http://www.adafruit.com/products/1963 + ----> http://www.adafruit.com/products/2468 + ----> http://www.adafruit.com/products/2542 + + These cellular modules use TTL Serial to communicate, 2 pins are + required to interface + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + Written by Limor Fried/Ladyada for Adafruit Industries. + BSD license, all text above must be included in any redistribution + ****************************************************/ + + /* + * Modified by Jesse Baker & George Tzintzarov 03/30/2016 for use in mbed LPC1768 + */ + +/* +THIS CODE IS STILL IN PROGRESS! + +Open up the serial console on the Arduino at 4800 baud to interact with FONA + +Note that if you need to set a GPRS APN, username, and password scroll down to +the commented section below just before the main "while (true)" loop. +*/ + +#include <string.h> //// BY JONATHAN: For strcpy() +#include <ctype.h> +//#include "SoftSerial.h" I dont think we need this +#include "Adafruit_FONA.h" +#include "emic2.h" + +#define FONA_RST p12 +#define FONA_TX p13 +#define FONA_RX p14 +#define FONA_RI p11 + +// this is a large buffer for replies +char replybuffer[255]; +char smsText[255], smsPhoneNo[11]; ///// By Jonathan: Text to send to Text -> Speech chip & phone # to send to + +int myCount; // by Jonathan + + +Serial pcSerial(USBTX, USBRX); +Adafruit_FONA fona(FONA_TX, FONA_RX, FONA_RST, FONA_RI); +//uLCD_4DGL uLCD(p28,p27,p30); + +// Turn on a LED when somebody call the FONA +DigitalOut led1(LED1); +emic2 myTTS(p9, p10); + +///// ---------------- Below are global vars and functions for ESP2886 chip -------------////////// + +Serial esp(p28, p27); // tx, rx +DigitalOut reset(p26); +DigitalOut led4(LED4); +Timer t; + +int count,ended,timeout; +char buf[2024]; +char snd[1024]; + +char myText[1024]; //////////////// by Jonathan (string to post to web server) + +char ssid[32] = "Brocano"; // enter WiFi router ssid inside the quotes +char pwd [32] = "habitacion"; // enter WiFi router password inside the quotes + +void SendCMD(),getreply(),ESPconfig(),ESPsetbaudrate(); + void dev_recv() +{ + led1 = !led1; + while(esp.readable()) { + pcSerial.putc(esp.getc()); + } +} + + //////// JONATHAN: CODE TO EDIIIIT //////////////// +void pc_recv() //////// CODE TO EDIT TO INPUT TEXT FROM TERMINAL -> WEBSITE ////// +{ + led4 = !led4; + char currChar; + myText[0] = '\0'; // clear text from char array + int i = 0; + while(pcSerial.readable()) { + currChar = pcSerial.getc(); + pcSerial.putc(currChar); // Added by Jonathan. local echo + myText[i++] = currChar; + } +} + + + + + + +//// ---------------------End ESP8226 Global region ------------------------------//// + + + +class FonaEventListener : public Adafruit_FONA::EventListener { + virtual void onRing() { + led1 = 1; + } + + virtual void onNoCarrier() { + led1 = 0; + } +}; +FonaEventListener fonaEventListener; + +// Functions defined after main() +uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout = 0); +void printMenu(void); +void flushSerial(); +char readBlocking(); +uint16_t readnumber(); +long map(long x, long in_min, long in_max, long out_min, long out_max); + +int main() { + myTTS.volume(5); + myTTS.voice(0); + pcSerial.baud(9600); + wait(1); + pcSerial.printf("\r\n"); + + //// ------------------- Setting up ESP8266 WiFi Below --------------- /// + + reset=0; //hardware reset for 8266 + pcSerial.printf("\f\n\r-------------ESP8266 Hardware Reset-------------\n\r"); + wait(0.5); + reset=1; + timeout=2; + getreply(); + + esp.baud(9600); // change this to the new ESP8266 baudrate if it is changed at any time. + + //ESPsetbaudrate(); //****************** include this routine to set a different ESP8266 baudrate ****************** + + ESPconfig(); //****************** include Config to set the ESP8266 configuration *********************** + + + + pcSerial.attach(&pc_recv, Serial::RxIrq); + esp.attach(&dev_recv, Serial::RxIrq); + + + + + //// ---------------------Setting up FONA GSM Chip Below ------------------- //// + + + pcSerial.printf("FONA basic test\r\n"); + pcSerial.printf("Initializing....(May take 3 seconds)\r\n"); + + // See if the FONA is responding + if (! fona.begin(9600)) { + pcSerial.printf("Couldn't find FONA\r\n"); + while (1); + } + fona.setEventListener(&fonaEventListener); + pcSerial.printf("FONA is OK\r\n"); + + // Print SIM card IMEI number. + char imei[15] = {0}; // MUST use a 16 character buffer for IMEI! + uint8_t imeiLen = fona.getIMEI(imei); + if (imeiLen > 0) { + pcSerial.printf("SIM card IMEI: %s\r\n", imei); + } + + // Optionally configure a GPRS APN, username, and password. + // You might need to do this to access your network's GPRS/data + // network. Contact your provider for the exact APN, username, + // and password values. Username and password are optional and + // can be removed, but APN is required. + //fona.setGPRSNetworkSettings("your APN", "your username", "your password"); + //fona.setGPRSNetworkSettings("web.pt.lu", "", ""); + + // Optionally configure HTTP gets to follow redirects over SSL. + // Default is not to follow SSL redirects, however if you uncomment + // the following line then redirects over SSL will be followed. + //fona.setHTTPSRedirect(true); + + printMenu(); + + + while (true) { + + pcSerial.printf("FONA> "); + // if nothing is available on the pcSearial port but there is something on the fona serial, then print it (flush it) to the pc Serial + + /* + while (! pcSerial.readable() ) { + if (fona.readable()) { + pcSerial.putc(fona.getc()); /////// RESPONSIBLE FOR DETECTING RECV'D TXT/////// + } + } */ + + //////////////////// By Jonathan: Edited version of while() above + while (! pcSerial.readable()) { + if (fona.readable()) { + + //// Printf that incoming SMS detected + pcSerial.putc(fona.getc()); + + + // ----------------------------------------------------------------// + + // read an SMS + send -> TTS chip + flushSerial(); + pcSerial.printf("\r\nReading SMS #1\r\n"); + + // Retrieve SMS sender address/phone number. + if (! fona.getSMSSender(1, replybuffer, 250)) { + pcSerial.printf("Failed!\r\n"); + break; + } + pcSerial.printf("FROM: %s\r\n", replybuffer); + for (int i = 0; i < 10; i++) { /////// BY JONATHAN to store phone # to respond to + smsPhoneNo[i] = replybuffer[i + 2]; // chop off the "+1" from phone # returned by replybuffer + } + smsPhoneNo[10] = '\0'; // null terminate.... NECESSARY?? + pcSerial.printf("FROM: %s\r\n", smsPhoneNo); + + // Retrieve SMS value. + uint16_t smslen; + if (! fona.readSMS(1, replybuffer, 250, &smslen)) { // pass in buffer and max len! + pcSerial.printf("Failed!\r\n"); + break; + } + pcSerial.printf("***** SMS #1 (%d) bytes *****\r\n", smslen); + pcSerial.printf("%s\r\n", replybuffer); + pcSerial.printf("*****\r\n"); + + + + //char message[255]; // CHANGED BY JONATHAN. 141 -> 255 + char myString[255]; + + for (int i = 0; i < 255; i++) { + myString[i] = replybuffer[i + 5]; // chop of the "Alexa string" + } + + strcpy(smsText, "Uh lex uh "); //Pronunciation Correction. + strcat(smsText, myString); + myTTS.speakf("S%s\r", smsText); // Send text message to the text to speech module. + + + // ----------------------------------------------------------------// + + // send an SMS back! + char message[255]; + + strcpy(message, ""); + + flushSerial(); + + pcSerial.printf("Replying to %s\r\n", smsPhoneNo); + + + if(strstr(replybuffer, "how old are you")) { // if reply buffer contains that string + strcpy(message, "I'm 2 in human years, 14 in dog years, and 25 in cat years. I think AI years are marked in nanoseconds, so that makes me, like, a scrillion!"); + } + else if(strstr(replybuffer, "what is the world population")) { + strcpy(message, "The population of the world is about 7 Billion 400 Million."); + } + else if(strstr(replybuffer, "integral of x squared")) { + strcpy(message, "The integral of x squared is one third x cubed plus a constant."); + } + else if(strstr(replybuffer, "discrete co sine transform")) { + strcpy(message, "The discrete cosine transform expresses a finite sequence of data points in terms of a sum of cosine function oscillating at different frequencies."); + } + else { + strcpy(message, "Sorry, command not recognized."); + } + + + + // message[255] = '\0'; + + pcSerial.printf("%s\r\n", message); + if (!fona.sendSMS(smsPhoneNo, message)) + pcSerial.printf("Failed\r\n"); + else + pcSerial.printf("Sent!\r\n"); + + // ----------------------------------------------------------------// + + // delete an SMS after response sent back + flushSerial(); + pcSerial.printf("\r\nDeleting SMS #1\r\n"); + if (fona.deleteSMS(1)) // delete SMS #1 + pcSerial.printf("OK!\r\n"); + else + pcSerial.printf("Couldn't delete\r\n"); + + } // end if + } // end while + + + + // Above while() by Jonathan // + + + + // get the input command from the terminal + char command = pcSerial.getc(); + pcSerial.printf("%c\r\n", command); //loops back to COM port + + + switch (command) { + case '?': { + printMenu(); + break; + } + + case 'a': { + // read the ADC + uint16_t adc; + if (! fona.getADCVoltage(&adc)) { + pcSerial.printf("Failed to read ADC\r\n"); + } else { + pcSerial.printf("ADC = %d mV\r\n", adc); + } + break; + } + + case 'b': { + // read the battery voltage and percentage + uint16_t vbat; + if (! fona.getBattVoltage(&vbat)) { + pcSerial.printf("Failed to read Batt\r\n"); + } else { + pcSerial.printf("VBat = %d mV\r\n", vbat); + } + + if (! fona.getBattPercent(&vbat)) { + pcSerial.printf("Failed to read Batt\r\n"); + } else { + pcSerial.printf("VPct = %d%%\r\n", vbat); + } + + break; + } + + case 'U': { + // Unlock the SIM with a PIN code + char PIN[5]; + flushSerial(); + pcSerial.printf("Enter 4-digit PIN\r\n"); + readline(PIN, 3); + pcSerial.printf("%s\r\n", PIN); + pcSerial.printf("Unlocking SIM card: "); + if (! fona.unlockSIM(PIN)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + break; + } + + case 'C': { + // read the CCID + fona.getSIMCCID(replybuffer); // make sure replybuffer is at least 21 bytes! + pcSerial.printf("SIM CCID = %s\r\n", replybuffer); + break; + } + + case 'i': { + // read the RSSI + uint8_t n = fona.getRSSI(); + int8_t r = 0; + + pcSerial.printf("RSSI = %d: ", n); + if (n == 0) r = -115; + if (n == 1) r = -111; + if (n == 31) r = -52; + if ((n >= 2) && (n <= 30)) { + r = map(n, 2, 30, -110, -54); + } + pcSerial.printf("%d dBm\r\n", r); + + break; + } + + case 'n': { + // read the network/cellular status + uint8_t n = fona.getNetworkStatus(); + pcSerial.printf("Network status %d: ", n); + if (n == 0) pcSerial.printf("Not registered\r\n"); + if (n == 1) pcSerial.printf("Registered (home)\r\n"); + if (n == 2) pcSerial.printf("Not registered (searching)\r\n"); + if (n == 3) pcSerial.printf("Denied\r\n"); + if (n == 4) pcSerial.printf("Unknown\r\n"); + if (n == 5) pcSerial.printf("Registered roaming\r\n"); + break; + } + + /*** Audio ***/ + case 'v': { + // set volume + flushSerial(); + pcSerial.printf("Set Vol %%"); + uint8_t vol = readnumber(); + pcSerial.printf("\r\n"); + if (! fona.setVolume(vol)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + break; + } + + case 'V': { + uint8_t v = fona.getVolume(); + pcSerial.printf("%d%%\r\n", v); + + break; + } + + case 'H': { + // Set Headphone output + if (! fona.setAudio(FONA_HEADSETAUDIO)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + fona.setMicVolume(FONA_HEADSETAUDIO, 15); + break; + } + case 'e': { + // Set External output + if (! fona.setAudio(FONA_EXTAUDIO)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + + fona.setMicVolume(FONA_EXTAUDIO, 10); + break; + } + + case 'T': { + // play tone + flushSerial(); + pcSerial.printf("Play tone #"); + uint8_t kittone = readnumber(); + pcSerial.printf("\r\n"); + // play for 1 second (1000 ms) + if (! fona.playToolkitTone(kittone, 1000)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + break; + } + + /*** FM Radio ***/ + + case 'f': { + // get freq + flushSerial(); + pcSerial.printf("FM Freq (eg 1011 == 101.1 MHz): "); + uint16_t station = readnumber(); + pcSerial.printf("\r\n"); + // FM radio ON using headset + if (fona.FMradio(true, FONA_HEADSETAUDIO)) { + pcSerial.printf("Opened\r\n"); + } + if (! fona.tuneFMradio(station)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("Tuned\r\n"); + } + break; + } + case 'F': { + // FM radio off + if (! fona.FMradio(false)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + break; + } + case 'm': { + // Set FM volume. + flushSerial(); + pcSerial.printf("Set FM Vol [0-6]:"); + uint8_t vol = readnumber(); + pcSerial.printf("\r\n"); + if (!fona.setFMVolume(vol)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + break; + } + case 'M': { + // Get FM volume. + int8_t fmvol = fona.getFMVolume(); + if (fmvol < 0) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("FM volume: %d\r\n", fmvol); + } + break; + } + case 'q': { + // Get FM station signal level (in decibels). + flushSerial(); + pcSerial.printf("FM Freq (eg 1011 == 101.1 MHz): "); + uint16_t station = readnumber(); + pcSerial.printf("\r\n"); + int8_t level = fona.getFMSignalLevel(station); + if (level < 0) { + pcSerial.printf("Failed! Make sure FM radio is on (tuned to station).\r\n"); + } else { + pcSerial.printf("Signal level (dB): %d\r\n", level); + } + break; + } + + /*** PWM ***/ + + case 'P': { + // PWM Buzzer output @ 2KHz max + flushSerial(); + pcSerial.printf("PWM Freq, 0 = Off, (1-2000): "); + uint16_t freq = readnumber(); + pcSerial.printf("\r\n"); + if (! fona.setPWM(freq)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + break; + } + + /*** Call ***/ + case 'c': { + // call a phone! + char number[10]; + flushSerial(); + pcSerial.printf("Call #"); + readline(number, 9); + pcSerial.printf("\r\n"); + pcSerial.printf("Calling %s\r\n", number); + if (!fona.callPhone(number)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("Sent!\r\n"); + } + + break; + } + case 'h': { + // hang up! + if (! fona.hangUp()) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + break; + } + + case 'p': { + // pick up! + if (! fona.pickUp()) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("OK!\r\n"); + } + break; + } + + /*** SMS ***/ + + case 'N': { + // read the number of SMS's! + int8_t smsnum = fona.getNumSMS(); + if (smsnum < 0) { + pcSerial.printf("Could not read # SMS\r\n"); + } else { + pcSerial.printf("%d SMS's on SIM card!\r\n", smsnum); + } + break; + } + case 'r': { + // read an SMS + flushSerial(); + pcSerial.printf("Read #"); + uint8_t smsn = readnumber(); + pcSerial.printf("\r\nReading SMS #%d\r\n", smsn); + + // Retrieve SMS sender address/phone number. + if (! fona.getSMSSender(smsn, replybuffer, 250)) { + pcSerial.printf("Failed!\r\n"); + break; + } + pcSerial.printf("FROM: %s\r\n", replybuffer); + + // Retrieve SMS value. + uint16_t smslen; + if (! fona.readSMS(smsn, replybuffer, 250, &smslen)) { // pass in buffer and max len! + pcSerial.printf("Failed!\r\n"); + break; + } + pcSerial.printf("***** SMS #%d (%d) bytes *****\r\n", smsn, smslen); + pcSerial.printf("%s\r\n", replybuffer); + pcSerial.printf("*****\r\n"); + + break; + } + case 'R': { + // read all SMS + int8_t smsnum = fona.getNumSMS(); + uint16_t smslen; + for (int8_t smsn=1; smsn<=smsnum; smsn++) { + pcSerial.printf("\r\nReading SMS #%d\r\n", smsn); + if (!fona.readSMS(smsn, replybuffer, 250, &smslen)) { // pass in buffer and max len! + pcSerial.printf("Failed!\r\n"); + break; + } + // if the length is zero, its a special case where the index number is higher + // so increase the max we'll look at! + if (smslen == 0) { + pcSerial.printf("[empty slot]\r\n"); + smsnum++; + continue; + } + + pcSerial.printf("***** SMS #%d (%d) bytes *****\r\n", smsn, smslen); + pcSerial.printf("%s\r\n", replybuffer); + pcSerial.printf("*****\r\n"); + } + break; + } + + case 'd': { + // delete an SMS + flushSerial(); + pcSerial.printf("Delete #"); + uint8_t smsn = readnumber(); + + pcSerial.printf("\r\nDeleting SMS #%d\r\n", smsn); + if (fona.deleteSMS(smsn)) { + pcSerial.printf("OK!\r\n"); + } else { + pcSerial.printf("Couldn't delete\r\n"); + } + break; + } + + case 's': { + // send an SMS! + char sendto[10], message[141],currChar; // 'currChar' by Jonathan + myCount = 0; // reset + + flushSerial(); + pcSerial.printf("Send to #"); + //currChar = pcSerial.getc(); + readline(sendto, 9); + pcSerial.printf("%s\r\n", sendto); + pcSerial.printf("Type out one-line message (140 char): "); + + myCount = 0; + while (1) // whole while loop added by jonathan... WORKS PERFECTLY for sending texts to phone + { + + pcSerial.putc(currChar = pcSerial.getc()); // local echo + if (currChar == '\r') + { + pcSerial.printf("breaking\r\n"); + message[myCount] = '\0'; // null terminate... NECESSARY?? + break; + } + message[myCount] = currChar; // fill in char array + myCount++; // global var update + //pcSerial.printf("\n%d\n", myCount); + } + + //readline(message, myCount); // edited by JONATHAN (140 -> 'myCount'). THEN COMPLETELY COMMENTED OUT, b/c I write directly to message[] above + //pcSerial.printf("\n%d\n", myCount); // added by jonathan + + + pcSerial.printf("%s\r\n", message); + if (!fona.sendSMS(sendto, message)) { + pcSerial.printf("Failed\r\n"); + } else { + pcSerial.printf("Sent!\r\n"); + } + + break; + } + + /*** Time ***/ + + case 'y': { + // enable network time sync + if (!fona.enableNetworkTimeSync(true)) + pcSerial.printf("Failed to enable\r\n"); + break; + } + + case 'Y': { + // enable NTP time sync + if (!fona.enableNTPTimeSync(true, "pool.ntp.org")) + pcSerial.printf("Failed to enable\r\n"); + break; + } + + case 't': { + // read the time + char buffer[23]; + + fona.getTime(buffer, 23); // make sure replybuffer is at least 23 bytes! + pcSerial.printf("Time = %s\r\n", buffer); + break; + } + + /*********************************** GPS (SIM808 only) */ + + case 'o': { + // turn GPS off + if (!fona.enableGPS(false)) + pcSerial.printf("Failed to turn off\r\n"); + break; + } + case 'O': { + // turn GPS on + if (!fona.enableGPS(true)) + pcSerial.printf("Failed to turn on\r\n"); + break; + } + case 'x': { + int8_t stat; + // check GPS fix + stat = fona.GPSstatus(); + if (stat < 0) + pcSerial.printf("Failed to query\r\n"); + if (stat == 0) pcSerial.printf("GPS off\r\n"); + if (stat == 1) pcSerial.printf("No fix\r\n"); + if (stat == 2) pcSerial.printf("2D fix\r\n"); + if (stat == 3) pcSerial.printf("3D fix\r\n"); + break; + } + + case 'L': { + // check for GPS location + char gpsdata[80]; + fona.getGPS(0, gpsdata, 80); + pcSerial.printf("Reply in format: mode,longitude,latitude,altitude,utctime(yyyymmddHHMMSS),ttff,satellites,speed,course\r\n"); + pcSerial.printf("%s\r\n", gpsdata); + + break; + } + + case 'E': { + flushSerial(); + pcSerial.printf("GPS NMEA output sentences (0 = off, 34 = RMC+GGA, 255 = all)\r\n"); + uint8_t nmeaout = readnumber(); + + // turn on NMEA output + fona.enableGPSNMEA(nmeaout); + + break; + } + + /*********************************** GPRS */ + + case 'g': { + // turn GPRS off + if (!fona.enableGPRS(false)) + pcSerial.printf("Failed to turn off\r\n"); + break; + } + case 'G': { + // turn GPRS on + if (!fona.enableGPRS(true)) + pcSerial.printf("Failed to turn on\r\n"); + break; + } + case 'l': { + // check for GSMLOC (requires GPRS) + uint16_t returncode; + + if (!fona.getGSMLoc(&returncode, replybuffer, 250)) + pcSerial.printf("Failed!\r\n"); + if (returncode == 0) { + pcSerial.printf("%s\r\n", replybuffer); + } else { + pcSerial.printf("Fail code #%d\r\n", returncode); + } + + break; + } + case 'w': { + // read website URL + uint16_t statuscode; + int16_t length; + char url[80]; + + flushSerial(); + pcSerial.printf("NOTE: in beta! Use small webpages to read!\r\n"); + pcSerial.printf("URL to read (e.g. www.adafruit.com/testwifi/index.html):\r\n"); + pcSerial.printf("http://"); readline(url, 79); + pcSerial.printf("%s\r\n", url); + + pcSerial.printf("****\r\n"); + if (!fona.HTTP_GET_start(url, &statuscode, (uint16_t *)&length)) { + pcSerial.printf("Failed!\r\n"); + break; + } + while (length > 0) { + while (fona.readable()) { + char c = fona.getc(); + pcSerial.putc(c); + length--; + if (! length) break; + } + } + pcSerial.printf("\r\n****\r\n"); + fona.HTTP_GET_end(); + break; + } + + case 'W': { + // Post data to website + uint16_t statuscode; + int16_t length; + char url[80]; + char data[80]; + + flushSerial(); + pcSerial.printf("NOTE: in beta! Use simple websites to post!\r\n"); + pcSerial.printf("URL to post (e.g. httpbin.org/post):\r\n"); + pcSerial.printf("http://"); readline(url, 79); + pcSerial.printf("%s\r\n", url); + pcSerial.printf("Data to post (e.g. \"foo\" or \"{\"simple\":\"json\"}\"):\r\n"); + readline(data, 79); + pcSerial.printf("%s\r\n", data); + + pcSerial.printf("****\r\n"); + if (!fona.HTTP_POST_start(url, "text/plain", (uint8_t *) data, strlen(data), &statuscode, (uint16_t *)&length)) { + pcSerial.printf("Failed!\r\n"); + break; + } + while (length > 0) { + while (fona.readable()) { + char c = fona.getc(); + pcSerial.putc(c); + length--; + if (! length) break; + } + } + pcSerial.printf("\r\n****\r\n"); + fona.HTTP_POST_end(); + break; + } + /*****************************************/ + + case 'S': { + pcSerial.printf("Creating SERIAL TUBE\r\n"); + while (1) { + while (pcSerial.readable()) { + wait_ms(1); + fona.putc(pcSerial.getc()); + } + if (fona.readable()) { + pcSerial.putc(fona.getc()); + } + } + } + + default: { + pcSerial.printf("Unknown command\r\n"); + printMenu(); + break; + } + } // end switch + // flush input + flushSerial(); + while (fona.readable()) { + pcSerial.putc(fona.getc()); + } + } // end while() +} // end main + +void printMenu(void) { + pcSerial.printf("-------------------------------------\r\n"); + pcSerial.printf("[?] Print this menu\r\n"); + pcSerial.printf("[a] read the ADC (2.8V max)\r\n"); + pcSerial.printf("[b] read the Battery V and %% charged\r\n"); + pcSerial.printf("[C] read the SIM CCID\r\n"); + pcSerial.printf("[U] Unlock SIM with PIN code\r\n"); + pcSerial.printf("[i] read RSSI\r\n"); + pcSerial.printf("[n] get Network status\r\n"); + pcSerial.printf("[v] set audio Volume\r\n"); + pcSerial.printf("[V] get Volume\r\n"); + pcSerial.printf("[H] set Headphone audio\r\n"); + pcSerial.printf("[e] set External audio\r\n"); + pcSerial.printf("[T] play audio Tone\r\n"); + pcSerial.printf("[P] PWM/Buzzer out\r\n"); + + // FM (SIM800 only) + pcSerial.printf("[f] tune FM radio\r\n"); + pcSerial.printf("[F] turn off FM\r\n"); + pcSerial.printf("[m] set FM volume\r\n"); + pcSerial.printf("[M] get FM volume\r\n"); + pcSerial.printf("[q] get FM station signal level\r\n"); + + // Phone + pcSerial.printf("[c] make phone Call\r\n"); + pcSerial.printf("[h] Hang up phone\r\n"); + pcSerial.printf("[p] Pick up phone\r\n"); + + // SMS + pcSerial.printf("[N] Number of SMSs\r\n"); + pcSerial.printf("[r] Read SMS #\r\n"); + pcSerial.printf("[R] Read All SMS\r\n"); + pcSerial.printf("[d] Delete SMS #\r\n"); + pcSerial.printf("[s] Send SMS\r\n"); + + // Time + pcSerial.printf("[y] Enable network time sync\r\n"); + pcSerial.printf("[Y] Enable NTP time sync (GPRS)\r\n"); + pcSerial.printf("[t] Get network time\r\n"); + + // GPRS + pcSerial.printf("[G] Enable GPRS\r\n"); + pcSerial.printf("[g] Disable GPRS\r\n"); + pcSerial.printf("[l] Query GSMLOC (GPRS)\r\n"); + pcSerial.printf("[w] Read webpage (GPRS)\r\n"); + pcSerial.printf("[W] Post to website (GPRS)\r\n"); + + // GPS + pcSerial.printf("[O] Turn GPS on (SIM808)\r\n"); + pcSerial.printf("[o] Turn GPS off (SIM808)\r\n"); + pcSerial.printf("[x] GPS fix status (SIM808)\r\n"); + pcSerial.printf("[L] Query GPS location (SIM808)\r\n"); + pcSerial.printf("[E] Raw NMEA out (SIM808)\r\n"); + + pcSerial.printf("[S] create Serial passthru tunnel\r\n"); + pcSerial.printf("-------------------------------------\r\n"); + pcSerial.printf("\r\n"); +} + +void flushSerial() { + while (pcSerial.readable()) + pcSerial.getc(); +} + +char readBlocking() { + while (!pcSerial.readable()); + return pcSerial.getc(); +} + +uint16_t readnumber() { + uint16_t x = 0; + char c; + while (! isdigit(c = readBlocking())) { + //pcSerial.putc(c); + } + pcSerial.putc(c); + x = c - '0'; + while (isdigit(c = readBlocking())) { + pcSerial.putc(c); + x *= 10; + x += c - '0'; + } + return x; +} + +uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout) { + uint16_t buffidx = 0; + bool timeoutvalid = true; + if (timeout == 0) timeoutvalid = false; + + while (true) { + if (buffidx > maxbuff) { + //pcSerial.printf("SPACE\r\n"); + break; + } + + while(pcSerial.readable()) { + char c = pcSerial.getc(); + + //pcSerial.printf("%02x#%c\r\n", c, c); + + if (c == '\r') + continue; + + + if (c == '\r') { /////////////////////////////////////////// CHANGED BY JONATHAN: (0XA -> '\r') + if (buffidx == 0) // the first 0x0A is ignored + continue; + + timeout = 0; // the second 0x0A is the end of the line + timeoutvalid = true; + break; + } + buff[buffidx] = c; + buffidx++; + + myCount++; ///////////////////////// ADED BY JONATHAN + } + + if (timeoutvalid && timeout == 0) { + //pcSerial.printf("TIMEOUT\r\n"); + break; + } + wait_ms(1); + } + buff[buffidx] = 0; // null term + return buffidx; +} + +long map(long x, long in_min, long in_max, long out_min, long out_max) +{ + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + + +///// ------------------- Below is ESP8266 WiFi Chip Config + Setup COde -------------------- //// +// Sets new ESP8266 baurate, change the esp.baud(xxxxx) to match your new setting once this has been executed +void ESPsetbaudrate() +{ + strcpy(snd, "AT+CIOBAUD=115200\r\n"); // change the numeric value to the required baudrate + SendCMD(); +} + + void ESPstart() { + wait(3); + pcSerial.printf("\f---------- Starting ESP Config ----------\r\n\n"); + strcpy(snd,".\r\n.\r\n"); + SendCMD(); +} + +void ESPreset() { + wait(1); + pcSerial.printf("---------- Reset & get Firmware ----------\r\n"); + strcpy(snd,"node.restart()\r\n"); + SendCMD(); + timeout=5; + getreply(); + pcSerial.printf(buf); +} + +void ESPversion() { + wait(1); + pcSerial.printf("\n---------- Get Version ----------\r\n"); + strcpy(snd,"print(node.info())\r\n"); + SendCMD(); + timeout=4; + getreply(); + pcSerial.printf(buf); +} + +void ESPmode() { + wait(2); + + // set CWMODE to 1=Station,2=AP,3=BOTH, default mode 1 (Station) + pcSerial.printf("\n---------- Setting Mode ----------\r\n"); + strcpy(snd, "wifi.setmode(wifi.STATION)\r\n"); + SendCMD(); + timeout=4; + getreply(); + pcSerial.printf(buf); +} + +void ESPconnect() { + pcSerial.printf("\n---------- Connecting to AP ----------\r\n"); + pcSerial.printf("ssid = %s pwd = %s\r\n",ssid,pwd); + strcpy(snd, "wifi.sta.config(\""); + strcat(snd, ssid); + strcat(snd, "\",\""); + strcat(snd, pwd); + strcat(snd, "\")\r\n"); + SendCMD(); + timeout=10; + getreply(); + pcSerial.printf(buf); + wait(2); +} + +void ESPip() { + pcSerial.printf("\n---------- Get chip's IP ----------\r\n"); + + strcpy(snd, "print(wifi.sta.getip())\r\n"); + SendCMD(); // get device IP + timeout=3; + getreply(); + pcSerial.printf(buf); + + wait(1); +} + +void ESPstatus() { + pcSerial.printf("\n---------- Get Connection Status ----------\r\n"); + strcpy(snd, "print(wifi.sta.status())\r\n"); + SendCMD(); + timeout=5; + getreply(); + pcSerial.printf(buf); + + pcSerial.printf("\n\n\n If you get a valid (non zero) IP, ESP8266 has been set up.\r\n"); + pcSerial.printf(" Run this if you want to reconfig the ESP8266 at any time.\r\n"); + pcSerial.printf(" It saves the SSID and password settings internally\r\n"); + wait(5); +} + +// +++++++++++++++++++++++++++++++++ This is for ESP8266 config only, run this once to set up the ESP8266 +++++++++++++++ +void ESPconfig() +{ + ESPstart(); + ESPreset(); + ESPversion(); + ESPmode(); + ESPconnect(); + ESPip(); + ESPstatus(); + + /* + pcSerial.printf("\n---------- Connecting to website -----------\r\n"); + + strcpy(snd, "conn=net.createConnection(net.TCP, 0)\r\n"); + SendCMD(); + wait(1); + + strcpy(snd, "conn:on(\"receive\",function(conn,payload)\r\n"); + SendCMD(); + wait(1); + + strcpy(snd, "end)\r\n"); + SendCMD(); + wait(1); + + strcpy(snd, "conn:connect(80,\"https://sites.google.com/site/4180echo/home\")"); + SendCMD(); + wait(1); + + strcpy("conn:on(\"connection\", function(conn, payload)"); + SendCMD(); + wait(1); + */ + + + + + + pcSerial.printf("\n---------- Setting up http server ----------\r\n"); + strcpy(snd, "srv=net.createServer(net.TCP)\r\n"); + SendCMD(); + wait(1); + strcpy(snd, "srv:listen(80,function(conn)\r\n"); + SendCMD(); + wait(1); + strcpy(snd, "conn:on(\"receive\",function(conn,payload)\r\n"); + SendCMD(); + wait(1); + strcpy(snd, "print(payload)\r\n"); + SendCMD(); + wait(1); + + strcpy(snd, "conn:send(\"<!DOCTYPE html>\")\r\n"); + SendCMD(); + wait(1); + + strcpy(snd, "conn:send(\"<html>\")\r\n"); + SendCMD(); + wait(1); + + strcpy(snd, "conn:send(\"<h1> Hi Jonathan!</h1>\")\r\n"); + SendCMD(); + wait(1); + + strcpy(snd, "conn:send(\"<h2> test</h2>\")\r\n"); + SendCMD(); + wait(1); + + strcpy(snd, "conn:send(\"</html>\")\r\n"); + SendCMD(); + wait(1); + + strcpy(snd, "end)\r\n"); + SendCMD(); + wait(1); + + strcpy(snd, "conn:on(\"sent\",function(conn) conn:close() end)\r\n"); + SendCMD(); + wait(1); + strcpy(snd, "end)\r\n"); + SendCMD(); + wait(1); + timeout=17; + getreply(); + pcSerial.printf(buf); + pcSerial.printf("\r\nDONE"); +} + +void SendCMD() +{ + esp.printf("%s", snd); +} + +void getreply() +{ + memset(buf, '\0', sizeof(buf)); + t.start(); + ended=0; + count=0; + while(!ended) { + if(esp.readable()) { + buf[count] = esp.getc(); + count++; + } + if(t.read() > timeout) { + ended = 1; + t.stop(); + t.reset(); + } + } +} \ No newline at end of file
diff -r 000000000000 -r 1271d15b4d4b emic2.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emic2.lib Tue May 02 03:13:27 2017 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/4180_1/code/emic2/#b95ede38e19d
diff -r 000000000000 -r 1271d15b4d4b main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue May 02 03:13:27 2017 +0000 @@ -0,0 +1,668 @@ +// By: Jonathan Osei-Owusu, Alex Mussa +// 4180 Final Project + +// Goal: ESP8266 static page WEB server to send text queries to Alexa via Mbed and TExt-to-Speech module. +// WEB server accessible from any network. +// Also uses FONA chip to allow Alexa text queries via SMS. + + +#include "mbed.h" +#include "emic2.h" +#include <string.h> +#include <ctype.h> +#include "Adafruit_FONA.h" + +/////// ------ Begin FONA Global Region ----- //////// + +#define FONA_RST p12 +#define FONA_TX p13 +#define FONA_RX p14 +#define FONA_RI p11 + +// this is a large buffer for replies +char replybuffer[255]; +char smsText[255], smsPhoneNo[11]; ///// By Jonathan: Text to send to Text -> Speech chip & phone # to send to +int count; // by Jonathan +Serial pcSerial(USBTX, USBRX); +Adafruit_FONA fona(FONA_TX, FONA_RX, FONA_RST, FONA_RI); +void replySMS(char*); + +// Turn on a LED when somebody call the FONA +emic2 myTTS(p9, p10); +DigitalOut led1(LED1); +DigitalOut led2(LED2); +DigitalOut led3(LED3); +DigitalOut led4(LED4); + +class FonaEventListener : public Adafruit_FONA::EventListener { + virtual void onRing() { + led1 = 1; + } + + virtual void onNoCarrier() { + led1 = 0; + } +}; +FonaEventListener fonaEventListener; + +// Functions defined after main() +uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout = 0); +void printMenu(void); +void flushSerial(); +char readBlocking(); +uint16_t readnumber(); +long map(long x, long in_min, long in_max, long out_min, long out_max); + +/////// ------ End FONA Global Region ----- //////// + + +////// ------- Begin ESP Global Region -------- ////// + +Serial esp(p28, p27); // tx, rx + +// some test values to show on web page +AnalogIn Ain1(p18); +AnalogIn Ain2(p19); + +/* +char ssid[32] = "hsd"; // enter WiFi router ssid inside the quotes +char pwd [32] = "austin123"; // enter WiFi router password inside the quotes +*/ +float temperature, AdcIn, Ht; +float R1=100000, R2=10000; // resistor values to give a 10:1 reduction of measured AnalogIn voltage +char Vcc[10]; +char Temp[10]; + +// things for sending/receiving data over serial +volatile int tx_in=0; +volatile int tx_out=0; +volatile int rx_in=0; +volatile int rx_out=0; +const int buffer_size = 4095; +char tx_buffer[buffer_size+1]; +char rx_buffer[buffer_size+1]; +void Tx_interrupt(); +void Rx_interrupt(); +void send_line(); +void read_line(); + +int DataRX; +int update; +int espCount; +char cmdbuff[1024]; +char replybuff[4096]; +char webdata[4096]; // This may need to be bigger depending on WEB browser used +char webbuff[4096]; // Currently using 1986 characters, Increase this if more web page data added +char timebuf[30]; +void SendCMD(),getreply(),ReadWebData(),startserver(); +void gettime(),setRTC(),gettemp(),getbattery(); +char rx_line[1024]; +int port =80; // set server port +int SERVtimeout =5; // set server timeout in seconds in case link breaks. +struct tm t; +// manual set RTC values +int minute =00; // 0-59 +int hour =12; // 2-23 +int dayofmonth =26; // 1-31 +int month =8; // 1-12 +int year =15; // last 2 digits + + +//// -------- End ESP Global region -------- ///// + +int main() +{ + myTTS.volume(5); + myTTS.voice(0); + + pcSerial.baud(9600); + esp.baud(9600); + wait(1); + + ////---------------- Begin FONA init setup Region -------// + + pcSerial.printf("\r\n"); + + pcSerial.printf("FONA basic test\r\n"); + pcSerial.printf("Initializing....(May take 3 seconds)\r\n"); + + // See if the FONA is responding + if (! fona.begin(9600)) { + pcSerial.printf("Couldn't find FONA\r\n"); + while (1); + } + fona.setEventListener(&fonaEventListener); + pcSerial.printf("FONA is OK\r\n"); + + // Print SIM card IMEI number. + char imei[15] = {0}; // MUST use a 16 character buffer for IMEI! + uint8_t imeiLen = fona.getIMEI(imei); + if (imeiLen > 0) { + pcSerial.printf("SIM card IMEI: %s\r\n", imei); + } + + ////----- End FONA init setup region -----//// + + + ////----- Begin ESP init setup region ----//// + + led1 = 0, led2 = 0, led3 = 0, led4 = 0; + // Setup a serial interrupt function to receive data + esp.attach(&Rx_interrupt, Serial::RxIrq); + // Setup a serial interrupt function to transmit data + esp.attach(&Tx_interrupt, Serial::TxIrq); + if (time(NULL) < 1420070400) { + setRTC(); + } + startserver(); + DataRX=0; + espCount=0; + wait(3); + + ////----- End ESP init setup region ----//// + + while(1) { + ////---- Begin ESP loop ----//// + if(DataRX==1) { + ReadWebData(); + esp.attach(&Rx_interrupt, Serial::RxIrq); + } + if(update==1) // update time, hit count, and analog levels in the HUZZAH chip + { + // get new values + gettime(); + gettemp(); + getbattery(); + espCount++; + // send new values + sprintf(cmdbuff, "espCount,time,analog1,analog2=%d,\"%s\",\"%s\",\"%s\"\r\n",espCount,timebuf,Temp,Vcc); + SendCMD(); + getreply(); + update=0; + } + ////---- End ESP loop ----//// + + ////---- Begin FONA loop ----//// + + //pcSerial.printf("FONA waiting for SMS...\r\n"); + + //while (! pcSerial.readable()) { + //if (fona.readable()) { + while (fona.readable() && ! pcSerial.readable()) { + //// Printf that incoming SMS detected + pcSerial.putc(fona.getc()); + + + // ----------------------------------------------------------------// + + // read an SMS + send -> TTS chip + flushSerial(); + pcSerial.printf("\r\nReading SMS #1\r\n"); + + // Retrieve SMS sender address/phone number. + if (! fona.getSMSSender(1, replybuffer, 250)) { + pcSerial.printf("Failed!\r\n"); + break; + } + pcSerial.printf("FROM: %s\r\n", replybuffer); + for (int i = 0; i < 10; i++) { /////// BY JONATHAN to store phone # to respond to + smsPhoneNo[i] = replybuffer[i + 2]; // chop off the "+1" from phone # returned by replybuffer + } + smsPhoneNo[10] = '\0'; // null terminate.... NECESSARY?? + pcSerial.printf("FROM: %s\r\n", smsPhoneNo); + + // Retrieve SMS value. + uint16_t smslen; + if (! fona.readSMS(1, replybuffer, 250, &smslen)) { // pass in buffer and max len! + pcSerial.printf("Failed!\r\n"); + break; + } + pcSerial.printf("***** SMS #1 (%d) bytes *****\r\n", smslen); + pcSerial.printf("%s\r\n", replybuffer); + pcSerial.printf("*****\r\n"); + + + + //char message[255]; // CHANGED BY JONATHAN. 141 -> 255 + char myString[255]; + + for (int i = 0; i < 255; i++) { + myString[i] = replybuffer[i + 5]; // chop of the "Alexa string" + } + + strcpy(smsText, "Uh lex uh "); //Pronunciation Correction. + strcat(smsText, myString); + pcSerial.printf("DEBUG::%s\r\n", smsText); + myTTS.speakf("S%s\r", smsText); // Send text message to the text to speech module. + + + // ----------------------------------------------------------------// + + // Send SMS back! + replySMS(replybuffer); + + // ----------------------------------------------------------------// + + // delete an SMS after response sent back + flushSerial(); + pcSerial.printf("\r\nDeleting SMS #1\r\n"); + if (fona.deleteSMS(1)) // delete SMS #1 + pcSerial.printf("OK!\r\n"); + else + pcSerial.printf("Couldn't delete\r\n"); + + // } // end if + } // end inner fona.readable() while + + ////---- End FONA loop ----//// + + } // end outer loop +} // end main + + +// +void replySMS(char* inMsg) +{ + // send an SMS back! + char message[255]; + + strcpy(message, ""); + + flushSerial(); + + pcSerial.printf("Replying to %s\r\n", smsPhoneNo); + + + if(strstr(inMsg, "how old are you")) { // if reply buffer contains that string + strcpy(message, "I'm 2 in human years, 14 in dog years, and 25 in cat years. I think AI years are marked in nanoseconds, so that makes me, like, a scrillion!"); + } + else if(strstr(inMsg, "what is the world population")) { + strcpy(message, "The population of the world is about 7 Billion 400 Million."); + } + else if(strstr(inMsg, "integral of x squared")) { + strcpy(message, "The integral of x squared is one third x cubed plus a constant."); + } + else if(strstr(inMsg, "discrete co sine transform")) { + strcpy(message, "The discrete cosine transform expresses a finite sequence of data points in terms of a sum of cosine function oscillating at different frequencies."); + } + else { + strcpy(message, "Sorry, command not recognized."); + } + + pcSerial.printf("%s\r\n", message); + if (!fona.sendSMS(smsPhoneNo, message)) + pcSerial.printf("Failed\r\n"); + else + pcSerial.printf("Sent!\r\n"); + +} + +// Reads and processes GET and POST web data +void ReadWebData() +{ + wait_ms(200); + esp.attach(NULL,Serial::RxIrq); + DataRX=0; + memset(webdata, '\0', sizeof(webdata)); + strcpy(webdata, rx_buffer); + memset(rx_buffer, '\0', sizeof(rx_buffer)); + rx_in = 0; + rx_out = 0; + // check web data for form information + if( strstr(webdata, "check=age") != NULL ) { ///////// JONATHAN ::: 'led1v' -> 'age' + strcpy(smsText, "Uh lex uh, how old are you?"); + led1=!led1; + myTTS.speakf("S%s\r", smsText); // Send text message to the text to speech module. + } + if( strstr(webdata, "check=population") != NULL ) { + strcpy(smsText, "Uh lex uh, what is the world population?"); + led2=!led2; + myTTS.speakf("S%s\r", smsText); + } + if( strstr(webdata, "check=integral") != NULL ) { + strcpy(smsText, "Uh lex uh, what is the integral of x squared?"); + led3=!led3; + myTTS.speakf("S%s\r", smsText); + } + if( strstr(webdata, "check=dct") != NULL ) { + strcpy(smsText, "Uh lex uh, what is the discrete co sine transform?"); + led4=!led4; + myTTS.speakf("S%s\r", smsText); + } + if( strstr(webdata, "POST") != NULL ) { // set update flag if POST request + update=1; + } + if( strstr(webdata, "GET") != NULL && strstr(webdata, "favicon") == NULL ) { // set update flag for GET request but do not want to update for favicon requests + update=1; + } +} +// Starts webserver +void startserver() +{ + gettime(); + gettemp(); + getbattery(); + pcSerial.printf("++++++++++ Resetting ESP ++++++++++\r\n"); + strcpy(cmdbuff,"node.restart()\r\n"); + SendCMD(); + wait(2); + getreply(); + + pcSerial.printf("\n++++++++++ Starting Server ++++++++++\r\n> "); + + // initial values + sprintf(cmdbuff, "espCount,time,analog1,analog2=0,\"%s\",\"%s\",\"%s\"\r\n",timebuf,Temp,Vcc); + SendCMD(); + getreply(); + wait(0.5); + + //create server + sprintf(cmdbuff, "srv=net.createServer(net.TCP,%d)\r\n",SERVtimeout); + SendCMD(); + getreply(); + wait(0.5); + strcpy(cmdbuff,"srv:listen(80,function(conn)\r\n"); + SendCMD(); + getreply(); + wait(0.3); + strcpy(cmdbuff,"conn:on(\"receive\",function(conn,payload) \r\n"); + SendCMD(); + getreply(); + wait(0.3); + + //print data to mbed + strcpy(cmdbuff,"print(payload)\r\n"); + SendCMD(); + getreply(); + wait(0.2); + + //web page data + strcpy(cmdbuff,"conn:send('<!DOCTYPE html><html><body><h1>Alexa Server</h1>')\r\n"); + SendCMD(); + getreply(); + wait(0.4); + strcpy(cmdbuff,"conn:send('Hit count: '..espCount..'')\r\n"); + SendCMD(); + getreply(); + wait(0.2); + strcpy(cmdbuff,"conn:send('<br>Last hit (based on mbed RTC time): '..time..'<br><hr>')\r\n"); + SendCMD(); + getreply(); + wait(0.4); + strcpy(cmdbuff,"conn:send('<form method=\"POST\"')\r\n"); + SendCMD(); + getreply(); + wait(0.3); + strcpy(cmdbuff, "conn:send('<p><input type=\"checkbox\" name=\"check\" value=\"x\"> Data Sent')\r\n"); + SendCMD(); + getreply(); + wait(0.3); + + // end web page data + strcpy(cmdbuff, "conn:on(\"sent\",function(conn) conn:close() end)\r\n"); // close current connection + SendCMD(); + getreply(); + wait(0.3); + strcpy(cmdbuff, "end)\r\n"); + SendCMD(); + getreply(); + wait(0.2); + strcpy(cmdbuff, "end)\r\n"); + SendCMD(); + getreply(); + wait(0.2); + + strcpy(cmdbuff, "tmr.alarm(0, 1000, 1, function()\r\n"); + SendCMD(); + getreply(); + wait(0.2); + strcpy(cmdbuff, "if wifi.sta.getip() == nil then\r\n"); + SendCMD(); + getreply(); + wait(0.2); + strcpy(cmdbuff, "print(\"Connecting to AP...\\n\")\r\n"); + SendCMD(); + getreply(); + wait(0.2); + strcpy(cmdbuff, "else\r\n"); + SendCMD(); + getreply(); + wait(0.2); + strcpy(cmdbuff, "ip, nm, gw=wifi.sta.getip()\r\n"); + SendCMD(); + getreply(); + wait(0.2); + strcpy(cmdbuff,"print(\"IP Address: \",ip)\r\n"); + SendCMD(); + getreply(); + wait(0.2); + strcpy(cmdbuff,"tmr.stop(0)\r\n"); + SendCMD(); + getreply(); + wait(0.2); + strcpy(cmdbuff,"end\r\n"); + SendCMD(); + getreply(); + wait(0.2); + strcpy(cmdbuff,"end)\r\n"); + SendCMD(); + getreply(); + wait(0.2); + + pcSerial.printf("\n\n++++++++++ Ready ++++++++++\r\n\n"); +} + +////------- Begin ESP Helper Functions Region ------//// +// ESP Command data send +void SendCMD() +{ + int i; + char temp_char; + bool empty; + i = 0; +// Start Critical Section - don't interrupt while changing global buffer variables + NVIC_DisableIRQ(UART1_IRQn); + empty = (tx_in == tx_out); + while ((i==0) || (cmdbuff[i-1] != '\n')) { +// Wait if buffer full + if (((tx_in + 1) % buffer_size) == tx_out) { +// End Critical Section - need to let interrupt routine empty buffer by sending + NVIC_EnableIRQ(UART1_IRQn); + while (((tx_in + 1) % buffer_size) == tx_out) { + } +// Start Critical Section - don't interrupt while changing global buffer variables + NVIC_DisableIRQ(UART1_IRQn); + } + tx_buffer[tx_in] = cmdbuff[i]; + i++; + tx_in = (tx_in + 1) % buffer_size; + } + if (esp.writeable() && (empty)) { + temp_char = tx_buffer[tx_out]; + tx_out = (tx_out + 1) % buffer_size; +// Send first character to start tx interrupts, if stopped + esp.putc(temp_char); + } +// End Critical Section + NVIC_EnableIRQ(UART1_IRQn); + return; +} + +// Get Command and ESP status replies +void getreply() +{ + read_line(); + sscanf(rx_line,replybuff); +} + +// Read a line from the large rx buffer from rx interrupt routine +void read_line() { + int i; + i = 0; +// Start Critical Section - don't interrupt while changing global buffer variables + NVIC_DisableIRQ(UART1_IRQn); +// Loop reading rx buffer characters until end of line character + while ((i==0) || (rx_line[i-1] != '\r')) { +// Wait if buffer empty + if (rx_in == rx_out) { +// End Critical Section - need to allow rx interrupt to get new characters for buffer + NVIC_EnableIRQ(UART1_IRQn); + while (rx_in == rx_out) { + } +// Start Critical Section - don't interrupt while changing global buffer variables + NVIC_DisableIRQ(UART1_IRQn); + } + rx_line[i] = rx_buffer[rx_out]; + i++; + rx_out = (rx_out + 1) % buffer_size; + } +// End Critical Section + NVIC_EnableIRQ(UART1_IRQn); + rx_line[i-1] = 0; + return; +} + + +// Interupt Routine to read in data from serial port +void Rx_interrupt() { + DataRX=1; + //led3=1; +// Loop just in case more than one character is in UART's receive FIFO buffer +// Stop if buffer full + while ((esp.readable()) && (((rx_in + 1) % buffer_size) != rx_out)) { + rx_buffer[rx_in] = esp.getc(); +// Uncomment to Echo to USB serial to watch data flow + pcSerial.putc(rx_buffer[rx_in]); + rx_in = (rx_in + 1) % buffer_size; + } + //led3=0; + return; +} + + +// Interupt Routine to write out data to serial port +void Tx_interrupt() { + //led2=1; +// Loop to fill more than one character in UART's transmit FIFO buffer +// Stop if buffer empty + while ((esp.writeable()) && (tx_in != tx_out)) { + esp.putc(tx_buffer[tx_out]); + tx_out = (tx_out + 1) % buffer_size; + } + //led2=0; + return; +} + +void gettime() +{ + time_t seconds = time(NULL); + strftime(timebuf,50,"%H:%M:%S %a %d %b %y", localtime(&seconds)); +} + +void setRTC() +{ + t.tm_sec = (0); // 0-59 + t.tm_min = (minute); // 0-59 + t.tm_hour = (hour); // 0-23 + t.tm_mday = (dayofmonth); // 1-31 + t.tm_mon = (month-1); // 0-11 "0" = Jan, -1 added for Mbed RCT clock format + t.tm_year = ((year)+100); // year since 1900, current DCF year + 100 + 1900 = correct year + set_time(mktime(&t)); // set RTC clock +} +// Analog in example +void getbattery() +{ + AdcIn=Ain1.read(); + Ht = (AdcIn*3.3); // set the numeric to the exact MCU analog reference voltage for greater accuracy + sprintf(Vcc,"%2.3f",Ht); +} +// Temperature example +void gettemp() +{ + + AdcIn=Ain2.read(); + Ht = (AdcIn*3.3); // set the numeric to the exact MCU analog reference voltage for greater accuracy + sprintf(Temp,"%2.3f",Ht); +} + +////------ End ESP Helper Functions Region ------//// + +////------ Begin FONA Helper Functions Region ------//// + +void flushSerial() { + while (pcSerial.readable()) + pcSerial.getc(); +} + +char readBlocking() { + while (!pcSerial.readable()); + return pcSerial.getc(); +} + +uint16_t readnumber() { + uint16_t x = 0; + char c; + while (! isdigit(c = readBlocking())) { + //pcSerial.putc(c); + } + pcSerial.putc(c); + x = c - '0'; + while (isdigit(c = readBlocking())) { + pcSerial.putc(c); + x *= 10; + x += c - '0'; + } + return x; +} + +uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout) { + uint16_t buffidx = 0; + bool timeoutvalid = true; + if (timeout == 0) timeoutvalid = false; + + while (true) { + if (buffidx > maxbuff) { + //pcSerial.printf("SPACE\r\n"); + break; + } + + while(pcSerial.readable()) { + char c = pcSerial.getc(); + + //pcSerial.printf("%02x#%c\r\n", c, c); + + if (c == '\r') + continue; + + + if (c == '\r') { /////////////////////////////////////////// CHANGED BY JONATHAN: (0XA -> '\r') + if (buffidx == 0) // the first 0x0A is ignored + continue; + + timeout = 0; // the second 0x0A is the end of the line + timeoutvalid = true; + break; + } + buff[buffidx] = c; + buffidx++; + + count++; ///////////////////////// ADED BY JONATHAN + } + + if (timeoutvalid && timeout == 0) { + //pcSerial.printf("TIMEOUT\r\n"); + break; + } + wait_ms(1); + } + buff[buffidx] = 0; // null term + return buffidx; +} + +long map(long x, long in_min, long in_max, long out_min, long out_max) +{ + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + +////------ End FONA Helper Functions Region ------//// +
diff -r 000000000000 -r 1271d15b4d4b mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Tue May 02 03:13:27 2017 +0000 @@ -0,0 +1,1 @@ +https://mbed.org/users/mbed_official/code/mbed/builds/794e51388b66 \ No newline at end of file