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

Revision:
0:64d65feb280c
Child:
2:072248e430d0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266.cpp	Mon Feb 11 00:05:12 2019 +0000
@@ -0,0 +1,282 @@
+
+#include "ESP8266.h"
+
+ESP8266::ESP8266(PinName tx, PinName rx, bool debug)
+    : _serial(tx, rx, 1024), _parser(_serial)   // set our buffer to ESP max buffer size
+{
+    _serial.baud(115200);
+    _parser.debugOn(debug);    
+    //reset();
+}
+
+bool ESP8266::startup(int mode)
+{
+    //only 3 valid modes
+    if(mode < 1 || mode > 3) {
+        return false;
+    }   
+           _parser.send("ATE0\r\n")                 //set no ESP echo
+        && _parser.recv("OK")
+        && _parser.send("AT+CWMODE=%d", mode)       //set mode 
+        && _parser.recv("OK")
+        && _parser.send("AT+CIPMUX=1") 
+        && _parser.recv("OK");
+     return true;
+}
+
+bool ESP8266::startServer(int mode,int port,int timeout)
+{    
+        //only 3 valid modes
+    if(mode < 1 || mode > 3) {
+        return false;
+    }
+           _parser.send("ATE0\r\n")                 //set no ESP echo
+        && _parser.recv("OK")
+        && _parser.send("AT+CWMODE=%d",mode)        //set mode
+        && _parser.recv("OK")
+        && _parser.send("AT+CIPMUX=1") 
+        && _parser.recv("OK")
+        && _parser.send("AT+CIPSERVER=1,%d",port)   //start server at port 80
+        && _parser.recv("OK")    
+        && _parser.send("AT+CIPSTO=%d",timeout)     //Server timeout=5 seconds
+        && _parser.recv("OK");    
+        
+     return true;
+}
+
+bool ESP8266::reset(void)
+{
+    for (int i = 0; i < 2; i++) {
+        if (_parser.send("AT+RST")          // soft reset ESP
+            && _parser.recv("OK\r\nready")
+            && _parser.send("ATE0\r\n")     // set no ESP echo
+            && _parser.recv("OK")); {
+            return true;
+        }
+    }
+    return false;
+}
+
+const char *ESP8266::getFirmware(void)
+{
+/*    
+    if (!(_parser.send("AT+GMR")
+        && _parser.recv("%d", _firmware)
+        && _parser.recv("OK"))) {
+        return 0;
+    }
+     return _firmware;
+*/       
+    int32_t recv_amount = 132;    
+    if (!(_parser.send("AT+GMR")
+        && _parser.read((char*)_firmware,recv_amount)
+        && _parser.recv("OK"))) {
+        return 0;
+    }
+    return _firmware;
+}
+
+bool ESP8266::dhcp(bool enabled, int mode)
+{
+    //only 3 valid modes
+    if(mode < 0 || mode > 2) {
+        return false;
+    }
+    return _parser.send("AT+CWDHCP=%d,%d", enabled?1:0, mode)
+        && _parser.recv("OK");
+}
+
+bool ESP8266::connect(const char *ap, const char *passPhrase)
+{
+    strcpy(_ssid, ap);
+    return _parser.send("AT+CWJAP=\"%s\",\"%s\"", ap, passPhrase)
+        && _parser.recv("OK");
+}
+
+bool ESP8266::disconnect(void)
+{
+    return _parser.send("AT+CWQAP") && _parser.recv("OK");
+}
+
+const char *ESP8266::getIPAddress(void)
+{
+    if (!(_parser.send("AT+CIFSR")
+        && _parser.recv("+CIFSR:APIP,\"%[^\"]\"", _APIP_buffer)
+        && _parser.recv("+CIFSR:APMAC,\"%[^\"]\"", _APMAC_buffer)
+        && _parser.recv("+CIFSR:STAIP,\"%[^\"]\"", _STAIP_buffer)
+        && _parser.recv("+CIFSR:STAMAC,\"%[^\"]\"", _STAMAC_buffer)
+        && _parser.recv("OK"))) {
+        return 0;
+    }
+    return _STAIP_buffer;
+}
+
+const char *ESP8266::getMACAddress(void)
+{
+    if (!(_parser.send("AT+CIFSR")
+        && _parser.recv("+CIFSR:STAMAC,\"%[^\"]\"", _STAMAC_buffer)
+        && _parser.recv("OK"))) {
+        return 0;
+    }
+    return _STAMAC_buffer;
+}
+
+bool ESP8266::isConnected(void)
+{ 
+    if(strcmp(getIPAddress(),"0.0.0.0")==0) {return 0;}
+        else {return 1;}
+}
+
+bool ESP8266::open(const char *type, int id, const char* addr, int port)
+{
+    //IDs only 0-4
+    if(id > 4) {
+        return false;
+    }
+    return _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d", id, type, addr, port)
+        && _parser.recv("OK");
+}
+
+bool ESP8266::send(int id, const void *data, uint32_t amount)
+{
+    //May take a second try if device is busy
+    for (unsigned i = 0; i < 2; i++) {
+        if (_parser.send("AT+CIPSEND=%d,%d", id, amount)
+            && _parser.recv(">")
+            && _parser.write((char*)data, (int)amount) >= 0) {
+            while(!_parser.recv("SEND OK"));    // wait for ESP response to confirm data sent
+            return true;
+        }
+    }
+    return false;
+}
+
+bool ESP8266::sendWebPage(int id, const char * page, uint32_t amount)
+{
+    unsigned int lenOfPacketToTx;
+    unsigned int pageToSendAddress=0;
+    Timer t;    // we test for 'SEND OK' otherwise comms fail, this function needs to escape, 3 second timeout.
+    t.reset();t.start();    
+    while(amount>0 && t.read()<3){
+        if(amount>2048){amount-=2048;lenOfPacketToTx=2048;} //ESP send buffer limit
+            else{lenOfPacketToTx=amount;amount=0;}                                
+        _parser.send("AT+CIPSEND=%d,%d", id, lenOfPacketToTx);
+        while(!_parser.recv(">"));      // wait for ready to send >            
+        page=(page+pageToSendAddress);            
+        while(lenOfPacketToTx--){
+            _parser.putc(*page++);      // send page data
+        }
+        pageToSendAddress+=lenOfPacketToTx;
+        while(!_parser.recv("SEND OK") && t.read()<2);                    
+    }
+    memset(request,'\0',sizeof(request));
+    ipdLen=0;t.stop();t.reset();
+    if(t.read()>2) return false; // comms failed     
+        else return true;     
+}
+
+const char *ESP8266::recvWebRequest(void )
+{   
+    char dummy[50];
+    _parser.recv("+IPD,%d,%d:%s %s %s",&linkId,&ipdLen,requestType,request,dummy);
+    return request;
+}
+
+int32_t ESP8266::recv(int id, void *data, uint32_t amount)
+{
+    int32_t recv_amount = -1;
+    int recv_id;
+    if (!(_parser.recv("+IPD,%d,%d:", &recv_id, &recv_amount)
+        && recv_id == id
+        && recv_amount <= amount
+        && _parser.read((char*)data, recv_amount)
+        && _parser.recv("OK"))) {
+    }
+    return recv_amount;
+}
+
+bool ESP8266::close(int id)
+{
+    int previous_timeout = _parser._timeout; // get current ESP timeout
+    setTimeout(100);
+    // May take a few try's if device is busy but keep short as possible ESP timeout retry delay.
+    for (unsigned i = 0; i < 3; i++) {
+        if (_parser.send("AT+CIPCLOSE=%d", id)
+            && _parser.recv("OK")) {
+            return true;
+        }
+    }
+    setTimeout(previous_timeout);   // restore previous ESP timeout
+    return false;
+}
+
+int8_t ESP8266::getRSSI()
+{
+    _parser.send("AT+CWLAPOPT=1,4");    // get current connection
+    _parser.recv("OK");    
+    int8_t rssi;
+    if (!(_parser.send("AT+CWLAP=\"%s\"", _ssid)
+        && _parser.recv("+CWLAP:(%d)", &rssi)
+        && _parser.recv("OK"))) {
+    } 
+    return rssi;
+}
+
+int32_t ESP8266::getNTP(char * NTPpool,int tzoffset, int setRTC)
+{
+    // example NTPpool = "1.nl.pool.ntp.org"
+    // serial.printf("Seconds ince 1970 = %d\r\n", esp.getNTP("1.nl.pool.ntp.org",3600));    
+    const int NTP_PACKET_SIZE = 48;
+    unsigned char packetBuffer[NTP_PACKET_SIZE];
+    int NTP_OFFSET = (2208988800 - tzoffset);
+    memset(packetBuffer, 0x00, NTP_PACKET_SIZE);
+    // Initialize values needed to form NTP request
+    packetBuffer[0]  = 0b11100011;      // LI, Version, Mode
+    packetBuffer[1]  = 0;               // Stratum, or type of clock
+    packetBuffer[2]  = 6;               // Polling Interval
+    packetBuffer[3]  = 0xEC;            // Peer Clock Precision
+    // [4]-[11]: 8 bytes of zero for Root Delay & Root Dispersion
+    packetBuffer[12] = 49;
+    packetBuffer[13] = 0x4E;
+    packetBuffer[14] = 49;
+    packetBuffer[15] = 52;
+ 
+    uint32_t recv_size = 0;
+    int tries1 = 10;
+    while ((recv_size != NTP_PACKET_SIZE) && (tries1 > 0)){
+        tries1--;
+        setTimeout(1000);        
+        open("UDP", 1, NTPpool, 123);
+        setTimeout(100);
+        send(1, packetBuffer, NTP_PACKET_SIZE);
+        int tries2 = 100;
+        while ((recv_size != NTP_PACKET_SIZE) && (tries2 > 0)){
+            tries2--;
+            recv_size = recv(1, packetBuffer, NTP_PACKET_SIZE);
+        }
+    }
+    setTimeout(5000); //default
+    close(1);
+    if(recv_size==48){
+        uint32_t secsSince1970=((packetBuffer[40]<<24)|(packetBuffer[41]<<16)|(packetBuffer[42]<<8)|packetBuffer[43])-NTP_OFFSET;
+        if (setRTC){set_time(secsSince1970);}
+        return secsSince1970;
+    }
+    else{return 0;}   
+}
+
+void ESP8266::setTimeout(uint32_t timeout_ms)
+{
+    _parser.setTimeout(timeout_ms);
+}
+
+bool ESP8266::readable()
+{
+    return _serial.readable();
+}
+
+bool ESP8266::writeable()
+{
+    return _serial.writeable();
+}
+