Tuned for OS2 to reduce flash code size for smaller MCU's. Added further functions since 2018 v1.7 firmware. Improved faster large web page sending. Built in fast NTP Client time and RTC setting function. ATParser message handling improvements and updated.

Dependencies:  

Dependents:   ESP8266-NTP-Test

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ESP8266.cpp Source File

ESP8266.cpp

00001 
00002 #include "ESP8266.h"
00003 
00004 ESP8266::ESP8266(PinName tx, PinName rx, bool debug)
00005     : _serial(tx, rx, 1024), _parser(_serial)   // set our buffer to ESP max buffer size
00006 {
00007     _serial.baud(115200);
00008     _parser.debugOn(debug);
00009     _parser.send("ATE0");     // set no ESP echo
00010 }
00011 
00012 bool ESP8266::reset(void)
00013 {
00014     if (_parser.send("AT+RST")          // soft reset ESP
00015         && _parser.recv("OK\r\nready")
00016         && _parser.send("ATE0")     // set no ESP echo
00017         && _parser.recv("OK")) {
00018         return true;
00019         }   
00020     else return false;
00021 }
00022 
00023 bool ESP8266::startup(int mode)
00024 {
00025     //only 3 valid modes
00026     if(mode < 1 || mode > 3) {
00027         return false;
00028     }  
00029          _parser.send("AT+CWMODE=%d", mode)       //set mode 
00030         && _parser.recv("OK")
00031         && _parser.send("AT+CIPMUX=1") 
00032         && _parser.recv("OK");
00033      return true;
00034 }
00035 
00036 bool ESP8266::startServer(int mode,int port,int timeout)
00037 {    
00038         //only 3 valid modes
00039     if(mode < 1 || mode > 3) {
00040         return false;
00041     }
00042          _parser.send("AT+CWMODE=%d",mode)        //set mode
00043         && _parser.recv("OK")
00044         && _parser.send("AT+CIPMUX=1") 
00045         && _parser.recv("OK")
00046         && _parser.send("AT+CIPSERVER=1,%d",port)   //start server at port 80
00047         && _parser.recv("OK")    
00048         && _parser.send("AT+CIPSTO=%d",timeout)     //Server timeout=5 seconds
00049         && _parser.recv("OK");    
00050         
00051      return true;
00052 }
00053 
00054 const char *ESP8266::getFirmware(void)
00055 {
00056     int previous_timeout = _parser._timeout; // get current ESP timeout
00057     setTimeout(200);   
00058     _parser.send("AT+GMR");
00059     _parser.getESP((char*)_firmware);
00060      setTimeout(previous_timeout);   // restore previous ESP timeout       
00061     return _firmware;
00062 }
00063 
00064 bool ESP8266::dhcp(bool enabled, int mode)
00065 {
00066     //only 3 valid modes
00067     if(mode < 0 || mode > 2) {
00068         return false;
00069     }
00070     return _parser.send("AT+CWDHCP=%d,%d", enabled?1:0, mode)
00071         && _parser.recv("OK");
00072 }
00073 
00074 bool ESP8266::connect(const char *ap, const char *passPhrase)
00075 {
00076     strcpy(_ssid, ap);
00077     return _parser.send("AT+CWJAP=\"%s\",\"%s\"", ap, passPhrase)
00078         && _parser.recv("OK");
00079 }
00080 
00081 bool ESP8266::disconnect(void)
00082 {
00083     return _parser.send("AT+CWQAP") && _parser.recv("OK");
00084 }
00085 
00086 const char *ESP8266::getIPAddress(void)
00087 {
00088     if (!(_parser.send("AT+CIFSR")
00089         && _parser.recv("+CIFSR:APIP,\"%[^\"]\"", _APIP_buffer)
00090         && _parser.recv("+CIFSR:APMAC,\"%[^\"]\"", _APMAC_buffer)
00091         && _parser.recv("+CIFSR:STAIP,\"%[^\"]\"", _STAIP_buffer)
00092         && _parser.recv("+CIFSR:STAMAC,\"%[^\"]\"", _STAMAC_buffer)
00093         && _parser.recv("OK"))) {
00094         return 0;
00095     }
00096     return _STAIP_buffer;
00097 }
00098 
00099 const char *ESP8266::getMACAddress(void)
00100 {
00101     if (!(_parser.send("AT+CIFSR")
00102         && _parser.recv("+CIFSR:STAMAC,\"%[^\"]\"", _STAMAC_buffer)
00103         && _parser.recv("OK"))) {
00104         return 0;
00105     }
00106     return _STAMAC_buffer;
00107 }
00108 
00109 bool ESP8266::isConnected(void)
00110 { 
00111     if(strcmp(getIPAddress(),"0.0.0.0")==0) {return 0;}
00112         else {return 1;}
00113 }
00114 
00115 bool ESP8266::open(const char *type, int id, const char* addr, int port)
00116 {
00117     //IDs only 0-4
00118     if(id > 4) {
00119         return false;
00120     }
00121     return _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d", id, type, addr, port)
00122         && _parser.recv("OK");
00123 }
00124 
00125 bool ESP8266::send(int id, const void *data, uint32_t amount)
00126 {
00127     //May take a second try if device is busy
00128     for (unsigned i = 0; i < 2; i++) {
00129         if (_parser.send("AT+CIPSEND=%d,%d", id, amount)
00130             && _parser.recv(">")
00131             && _parser.write((char*)data, (int)amount) >= 0) {
00132             while(!_parser.recv("SEND OK"));    // wait for ESP response to confirm data sent
00133             return true;
00134         }
00135     }
00136     return false;
00137 }
00138 
00139 bool ESP8266::sendWebPage(int id, const char * page, uint32_t amount)
00140 {
00141     unsigned int lenOfPacketToTx;
00142     unsigned int pageToSendAddress=0;
00143     // we test for 'SEND OK' otherwise comms fail, this function needs to escape, 3 second timeout.
00144     t.reset();t.start();    
00145     while(amount>0 && t.read()<3){
00146         if(amount>2048){amount-=2048;lenOfPacketToTx=2048;} //ESP send buffer limit
00147             else{lenOfPacketToTx=amount;amount=0;}                                
00148         _parser.send("AT+CIPSEND=%d,%d", id, lenOfPacketToTx);
00149         while(!_parser.recv(">"));      // wait for ready to send >            
00150         page=(page+pageToSendAddress);            
00151         while(lenOfPacketToTx--){
00152             _parser.putc(*page++);      // send page data
00153         }
00154         pageToSendAddress+=lenOfPacketToTx;
00155         while(!_parser.recv("SEND OK") && t.read()<2);                    
00156     }
00157     memset(request,'\0',sizeof(request));
00158     ipdLen=0;t.stop();t.reset();
00159     if(t.read()>2) return false; // comms failed     
00160         else return true;     
00161 }
00162 
00163 const char *ESP8266::recvWebRequest(void )
00164 {   
00165     char dummy[50]; // this is not working as expected, we need add a 'dummy' field
00166     _parser.recv("+IPD,%d,%d:%s %s %s",&linkId,&ipdLen,requestType,request,dummy);
00167     return request;
00168 }
00169 
00170 int32_t ESP8266::recv(int id, void *data, uint32_t amount)
00171 {
00172     int32_t recv_amount = -1;
00173     int recv_id;
00174     if (!(_parser.recv("+IPD,%d,%d:", &recv_id, &recv_amount)
00175         && recv_id == id
00176         && recv_amount <= amount
00177         && _parser.read((char*)data, recv_amount)
00178         && _parser.recv("OK"))) {
00179     }
00180     return recv_amount;
00181 }
00182 
00183 bool ESP8266::close(int id)
00184 {
00185     int previous_timeout = _parser._timeout; // get current ESP timeout
00186     setTimeout(100);
00187     // May take a few try's if device is busy but keep short as possible ESP timeout retry delay.
00188     for (unsigned i = 0; i < 3; i++) {
00189         if (_parser.send("AT+CIPCLOSE=%d", id)
00190             && _parser.recv("OK")) {
00191             return true;
00192         }
00193     }
00194     setTimeout(previous_timeout);   // restore previous ESP timeout
00195     return false;
00196 }
00197 
00198 int8_t ESP8266::getRSSI()
00199 {
00200     int previous_timeout = _parser._timeout; // get current ESP timeout
00201     setTimeout(5000);
00202     _parser.send("AT+CWLAPOPT=1,4");    // get current connection
00203     _parser.recv("OK");    
00204     int8_t rssi;
00205     if (!(_parser.send("AT+CWLAP=\"%s\"", _ssid)
00206         && _parser.recv("+CWLAP:(%d)", &rssi)
00207         && _parser.recv("OK"))) {
00208     }
00209     setTimeout(previous_timeout);   // restore previous ESP timeout 
00210     return rssi;
00211 }
00212 
00213 int32_t ESP8266::getNTP(char * NTPpool,int tzoffset, int setRTC)
00214 {
00215     // example NTPpool = "1.nl.pool.ntp.org"
00216     // serial.printf("Seconds since 1970 = %d\r\n", esp.getNTP("1.nl.pool.ntp.org",3600));    
00217     const int NTP_PACKET_SIZE = 48;
00218     unsigned char packetBuffer[NTP_PACKET_SIZE];
00219     int NTP_OFFSET = (2208988800 - tzoffset);
00220     memset(packetBuffer, 0x00, NTP_PACKET_SIZE);
00221     // Initialize values needed to form NTP request
00222     packetBuffer[0]  = 0b11100011;      // LI, Version, Mode
00223     packetBuffer[1]  = 0;               // Stratum, or type of clock
00224     packetBuffer[2]  = 6;               // Polling Interval
00225     packetBuffer[3]  = 0xEC;            // Peer Clock Precision
00226     // [4]-[11]: 8 bytes of zero for Root Delay & Root Dispersion
00227     packetBuffer[12] = 49;
00228     packetBuffer[13] = 0x4E;
00229     packetBuffer[14] = 49;
00230     packetBuffer[15] = 52;
00231     int previous_timeout = _parser._timeout; // get current ESP timeout
00232     uint32_t recv_size = 0;
00233     int tries1 = 10;
00234     while ((recv_size != NTP_PACKET_SIZE) && (tries1 > 0)){
00235         tries1--;
00236         setTimeout(2000);        
00237         open("UDP", 1, NTPpool, 123);
00238         setTimeout(100);
00239         send(1, packetBuffer, NTP_PACKET_SIZE);
00240         int tries2 = 50;
00241         while ((recv_size != NTP_PACKET_SIZE) && (tries2 > 0)){
00242             tries2--;
00243             recv_size = recv(1, packetBuffer, NTP_PACKET_SIZE);
00244         }
00245     }
00246     setTimeout(previous_timeout);   // restore previous ESP timeout
00247     close(1);
00248     if(recv_size==48){
00249         uint32_t secsSince1970=((packetBuffer[40]<<24)|(packetBuffer[41]<<16)|(packetBuffer[42]<<8)|packetBuffer[43])-NTP_OFFSET;
00250         if (setRTC){set_time(secsSince1970);} // may need to add a second to offset any MCU delay
00251         return secsSince1970;
00252     }
00253     else{return 0;}   
00254 }
00255 
00256 void ESP8266::setTimeout(uint32_t timeout_ms)
00257 {
00258     _parser.setTimeout(timeout_ms);
00259 }
00260 
00261 bool ESP8266::readable()
00262 {
00263     return _serial.readable();
00264 }
00265 
00266 bool ESP8266::writeable()
00267 {
00268     return _serial.writeable();
00269 }
00270