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

Committer:
star297
Date:
Thu Feb 14 00:25:33 2019 +0000
Revision:
3:ffdde9d17dd1
Parent:
2:072248e430d0
Improve getFirmware functions, other minor timing changes.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
star297 0:64d65feb280c 1
star297 0:64d65feb280c 2 #include "ESP8266.h"
star297 0:64d65feb280c 3
star297 0:64d65feb280c 4 ESP8266::ESP8266(PinName tx, PinName rx, bool debug)
star297 0:64d65feb280c 5 : _serial(tx, rx, 1024), _parser(_serial) // set our buffer to ESP max buffer size
star297 0:64d65feb280c 6 {
star297 0:64d65feb280c 7 _serial.baud(115200);
star297 2:072248e430d0 8 _parser.debugOn(debug);
star297 2:072248e430d0 9 _parser.send("ATE0"); // set no ESP echo
star297 2:072248e430d0 10 }
star297 2:072248e430d0 11
star297 2:072248e430d0 12 bool ESP8266::reset(void)
star297 2:072248e430d0 13 {
star297 2:072248e430d0 14 if (_parser.send("AT+RST") // soft reset ESP
star297 2:072248e430d0 15 && _parser.recv("OK\r\nready")
star297 2:072248e430d0 16 && _parser.send("ATE0") // set no ESP echo
star297 2:072248e430d0 17 && _parser.recv("OK")) {
star297 2:072248e430d0 18 return true;
star297 2:072248e430d0 19 }
star297 2:072248e430d0 20 else return false;
star297 0:64d65feb280c 21 }
star297 0:64d65feb280c 22
star297 0:64d65feb280c 23 bool ESP8266::startup(int mode)
star297 0:64d65feb280c 24 {
star297 0:64d65feb280c 25 //only 3 valid modes
star297 0:64d65feb280c 26 if(mode < 1 || mode > 3) {
star297 0:64d65feb280c 27 return false;
star297 2:072248e430d0 28 }
star297 2:072248e430d0 29 _parser.send("AT+CWMODE=%d", mode) //set mode
star297 0:64d65feb280c 30 && _parser.recv("OK")
star297 0:64d65feb280c 31 && _parser.send("AT+CIPMUX=1")
star297 0:64d65feb280c 32 && _parser.recv("OK");
star297 0:64d65feb280c 33 return true;
star297 0:64d65feb280c 34 }
star297 0:64d65feb280c 35
star297 0:64d65feb280c 36 bool ESP8266::startServer(int mode,int port,int timeout)
star297 0:64d65feb280c 37 {
star297 0:64d65feb280c 38 //only 3 valid modes
star297 0:64d65feb280c 39 if(mode < 1 || mode > 3) {
star297 0:64d65feb280c 40 return false;
star297 0:64d65feb280c 41 }
star297 2:072248e430d0 42 _parser.send("AT+CWMODE=%d",mode) //set mode
star297 0:64d65feb280c 43 && _parser.recv("OK")
star297 0:64d65feb280c 44 && _parser.send("AT+CIPMUX=1")
star297 0:64d65feb280c 45 && _parser.recv("OK")
star297 0:64d65feb280c 46 && _parser.send("AT+CIPSERVER=1,%d",port) //start server at port 80
star297 0:64d65feb280c 47 && _parser.recv("OK")
star297 0:64d65feb280c 48 && _parser.send("AT+CIPSTO=%d",timeout) //Server timeout=5 seconds
star297 0:64d65feb280c 49 && _parser.recv("OK");
star297 0:64d65feb280c 50
star297 0:64d65feb280c 51 return true;
star297 0:64d65feb280c 52 }
star297 0:64d65feb280c 53
star297 0:64d65feb280c 54 const char *ESP8266::getFirmware(void)
star297 0:64d65feb280c 55 {
star297 2:072248e430d0 56 int previous_timeout = _parser._timeout; // get current ESP timeout
star297 2:072248e430d0 57 setTimeout(200);
star297 2:072248e430d0 58 _parser.send("AT+GMR");
star297 2:072248e430d0 59 _parser.getESP((char*)_firmware);
star297 2:072248e430d0 60 setTimeout(previous_timeout); // restore previous ESP timeout
star297 0:64d65feb280c 61 return _firmware;
star297 0:64d65feb280c 62 }
star297 0:64d65feb280c 63
star297 0:64d65feb280c 64 bool ESP8266::dhcp(bool enabled, int mode)
star297 0:64d65feb280c 65 {
star297 0:64d65feb280c 66 //only 3 valid modes
star297 0:64d65feb280c 67 if(mode < 0 || mode > 2) {
star297 0:64d65feb280c 68 return false;
star297 0:64d65feb280c 69 }
star297 0:64d65feb280c 70 return _parser.send("AT+CWDHCP=%d,%d", enabled?1:0, mode)
star297 0:64d65feb280c 71 && _parser.recv("OK");
star297 0:64d65feb280c 72 }
star297 0:64d65feb280c 73
star297 0:64d65feb280c 74 bool ESP8266::connect(const char *ap, const char *passPhrase)
star297 0:64d65feb280c 75 {
star297 0:64d65feb280c 76 strcpy(_ssid, ap);
star297 0:64d65feb280c 77 return _parser.send("AT+CWJAP=\"%s\",\"%s\"", ap, passPhrase)
star297 0:64d65feb280c 78 && _parser.recv("OK");
star297 0:64d65feb280c 79 }
star297 0:64d65feb280c 80
star297 0:64d65feb280c 81 bool ESP8266::disconnect(void)
star297 0:64d65feb280c 82 {
star297 0:64d65feb280c 83 return _parser.send("AT+CWQAP") && _parser.recv("OK");
star297 0:64d65feb280c 84 }
star297 0:64d65feb280c 85
star297 0:64d65feb280c 86 const char *ESP8266::getIPAddress(void)
star297 0:64d65feb280c 87 {
star297 0:64d65feb280c 88 if (!(_parser.send("AT+CIFSR")
star297 0:64d65feb280c 89 && _parser.recv("+CIFSR:APIP,\"%[^\"]\"", _APIP_buffer)
star297 0:64d65feb280c 90 && _parser.recv("+CIFSR:APMAC,\"%[^\"]\"", _APMAC_buffer)
star297 0:64d65feb280c 91 && _parser.recv("+CIFSR:STAIP,\"%[^\"]\"", _STAIP_buffer)
star297 0:64d65feb280c 92 && _parser.recv("+CIFSR:STAMAC,\"%[^\"]\"", _STAMAC_buffer)
star297 0:64d65feb280c 93 && _parser.recv("OK"))) {
star297 0:64d65feb280c 94 return 0;
star297 0:64d65feb280c 95 }
star297 0:64d65feb280c 96 return _STAIP_buffer;
star297 0:64d65feb280c 97 }
star297 0:64d65feb280c 98
star297 0:64d65feb280c 99 const char *ESP8266::getMACAddress(void)
star297 0:64d65feb280c 100 {
star297 0:64d65feb280c 101 if (!(_parser.send("AT+CIFSR")
star297 0:64d65feb280c 102 && _parser.recv("+CIFSR:STAMAC,\"%[^\"]\"", _STAMAC_buffer)
star297 0:64d65feb280c 103 && _parser.recv("OK"))) {
star297 0:64d65feb280c 104 return 0;
star297 0:64d65feb280c 105 }
star297 0:64d65feb280c 106 return _STAMAC_buffer;
star297 0:64d65feb280c 107 }
star297 0:64d65feb280c 108
star297 0:64d65feb280c 109 bool ESP8266::isConnected(void)
star297 0:64d65feb280c 110 {
star297 0:64d65feb280c 111 if(strcmp(getIPAddress(),"0.0.0.0")==0) {return 0;}
star297 0:64d65feb280c 112 else {return 1;}
star297 0:64d65feb280c 113 }
star297 0:64d65feb280c 114
star297 0:64d65feb280c 115 bool ESP8266::open(const char *type, int id, const char* addr, int port)
star297 0:64d65feb280c 116 {
star297 0:64d65feb280c 117 //IDs only 0-4
star297 0:64d65feb280c 118 if(id > 4) {
star297 0:64d65feb280c 119 return false;
star297 0:64d65feb280c 120 }
star297 0:64d65feb280c 121 return _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d", id, type, addr, port)
star297 0:64d65feb280c 122 && _parser.recv("OK");
star297 0:64d65feb280c 123 }
star297 0:64d65feb280c 124
star297 0:64d65feb280c 125 bool ESP8266::send(int id, const void *data, uint32_t amount)
star297 0:64d65feb280c 126 {
star297 0:64d65feb280c 127 //May take a second try if device is busy
star297 0:64d65feb280c 128 for (unsigned i = 0; i < 2; i++) {
star297 0:64d65feb280c 129 if (_parser.send("AT+CIPSEND=%d,%d", id, amount)
star297 0:64d65feb280c 130 && _parser.recv(">")
star297 0:64d65feb280c 131 && _parser.write((char*)data, (int)amount) >= 0) {
star297 0:64d65feb280c 132 while(!_parser.recv("SEND OK")); // wait for ESP response to confirm data sent
star297 0:64d65feb280c 133 return true;
star297 0:64d65feb280c 134 }
star297 0:64d65feb280c 135 }
star297 0:64d65feb280c 136 return false;
star297 0:64d65feb280c 137 }
star297 0:64d65feb280c 138
star297 0:64d65feb280c 139 bool ESP8266::sendWebPage(int id, const char * page, uint32_t amount)
star297 0:64d65feb280c 140 {
star297 0:64d65feb280c 141 unsigned int lenOfPacketToTx;
star297 0:64d65feb280c 142 unsigned int pageToSendAddress=0;
star297 2:072248e430d0 143 // we test for 'SEND OK' otherwise comms fail, this function needs to escape, 3 second timeout.
star297 0:64d65feb280c 144 t.reset();t.start();
star297 0:64d65feb280c 145 while(amount>0 && t.read()<3){
star297 0:64d65feb280c 146 if(amount>2048){amount-=2048;lenOfPacketToTx=2048;} //ESP send buffer limit
star297 0:64d65feb280c 147 else{lenOfPacketToTx=amount;amount=0;}
star297 0:64d65feb280c 148 _parser.send("AT+CIPSEND=%d,%d", id, lenOfPacketToTx);
star297 0:64d65feb280c 149 while(!_parser.recv(">")); // wait for ready to send >
star297 0:64d65feb280c 150 page=(page+pageToSendAddress);
star297 0:64d65feb280c 151 while(lenOfPacketToTx--){
star297 0:64d65feb280c 152 _parser.putc(*page++); // send page data
star297 0:64d65feb280c 153 }
star297 0:64d65feb280c 154 pageToSendAddress+=lenOfPacketToTx;
star297 0:64d65feb280c 155 while(!_parser.recv("SEND OK") && t.read()<2);
star297 0:64d65feb280c 156 }
star297 0:64d65feb280c 157 memset(request,'\0',sizeof(request));
star297 0:64d65feb280c 158 ipdLen=0;t.stop();t.reset();
star297 0:64d65feb280c 159 if(t.read()>2) return false; // comms failed
star297 0:64d65feb280c 160 else return true;
star297 0:64d65feb280c 161 }
star297 0:64d65feb280c 162
star297 0:64d65feb280c 163 const char *ESP8266::recvWebRequest(void )
star297 0:64d65feb280c 164 {
star297 2:072248e430d0 165 char dummy[50]; // this is not working as expected, we need add a 'dummy' field
star297 0:64d65feb280c 166 _parser.recv("+IPD,%d,%d:%s %s %s",&linkId,&ipdLen,requestType,request,dummy);
star297 0:64d65feb280c 167 return request;
star297 0:64d65feb280c 168 }
star297 0:64d65feb280c 169
star297 0:64d65feb280c 170 int32_t ESP8266::recv(int id, void *data, uint32_t amount)
star297 0:64d65feb280c 171 {
star297 0:64d65feb280c 172 int32_t recv_amount = -1;
star297 0:64d65feb280c 173 int recv_id;
star297 0:64d65feb280c 174 if (!(_parser.recv("+IPD,%d,%d:", &recv_id, &recv_amount)
star297 0:64d65feb280c 175 && recv_id == id
star297 0:64d65feb280c 176 && recv_amount <= amount
star297 0:64d65feb280c 177 && _parser.read((char*)data, recv_amount)
star297 0:64d65feb280c 178 && _parser.recv("OK"))) {
star297 0:64d65feb280c 179 }
star297 0:64d65feb280c 180 return recv_amount;
star297 0:64d65feb280c 181 }
star297 0:64d65feb280c 182
star297 0:64d65feb280c 183 bool ESP8266::close(int id)
star297 0:64d65feb280c 184 {
star297 0:64d65feb280c 185 int previous_timeout = _parser._timeout; // get current ESP timeout
star297 0:64d65feb280c 186 setTimeout(100);
star297 0:64d65feb280c 187 // May take a few try's if device is busy but keep short as possible ESP timeout retry delay.
star297 0:64d65feb280c 188 for (unsigned i = 0; i < 3; i++) {
star297 0:64d65feb280c 189 if (_parser.send("AT+CIPCLOSE=%d", id)
star297 0:64d65feb280c 190 && _parser.recv("OK")) {
star297 0:64d65feb280c 191 return true;
star297 0:64d65feb280c 192 }
star297 0:64d65feb280c 193 }
star297 0:64d65feb280c 194 setTimeout(previous_timeout); // restore previous ESP timeout
star297 0:64d65feb280c 195 return false;
star297 0:64d65feb280c 196 }
star297 0:64d65feb280c 197
star297 0:64d65feb280c 198 int8_t ESP8266::getRSSI()
star297 0:64d65feb280c 199 {
star297 2:072248e430d0 200 int previous_timeout = _parser._timeout; // get current ESP timeout
star297 2:072248e430d0 201 setTimeout(5000);
star297 0:64d65feb280c 202 _parser.send("AT+CWLAPOPT=1,4"); // get current connection
star297 0:64d65feb280c 203 _parser.recv("OK");
star297 0:64d65feb280c 204 int8_t rssi;
star297 0:64d65feb280c 205 if (!(_parser.send("AT+CWLAP=\"%s\"", _ssid)
star297 0:64d65feb280c 206 && _parser.recv("+CWLAP:(%d)", &rssi)
star297 0:64d65feb280c 207 && _parser.recv("OK"))) {
star297 2:072248e430d0 208 }
star297 2:072248e430d0 209 setTimeout(previous_timeout); // restore previous ESP timeout
star297 0:64d65feb280c 210 return rssi;
star297 0:64d65feb280c 211 }
star297 0:64d65feb280c 212
star297 0:64d65feb280c 213 int32_t ESP8266::getNTP(char * NTPpool,int tzoffset, int setRTC)
star297 0:64d65feb280c 214 {
star297 0:64d65feb280c 215 // example NTPpool = "1.nl.pool.ntp.org"
star297 3:ffdde9d17dd1 216 // serial.printf("Seconds since 1970 = %d\r\n", esp.getNTP("1.nl.pool.ntp.org",3600));
star297 0:64d65feb280c 217 const int NTP_PACKET_SIZE = 48;
star297 0:64d65feb280c 218 unsigned char packetBuffer[NTP_PACKET_SIZE];
star297 0:64d65feb280c 219 int NTP_OFFSET = (2208988800 - tzoffset);
star297 0:64d65feb280c 220 memset(packetBuffer, 0x00, NTP_PACKET_SIZE);
star297 0:64d65feb280c 221 // Initialize values needed to form NTP request
star297 0:64d65feb280c 222 packetBuffer[0] = 0b11100011; // LI, Version, Mode
star297 0:64d65feb280c 223 packetBuffer[1] = 0; // Stratum, or type of clock
star297 0:64d65feb280c 224 packetBuffer[2] = 6; // Polling Interval
star297 0:64d65feb280c 225 packetBuffer[3] = 0xEC; // Peer Clock Precision
star297 0:64d65feb280c 226 // [4]-[11]: 8 bytes of zero for Root Delay & Root Dispersion
star297 0:64d65feb280c 227 packetBuffer[12] = 49;
star297 0:64d65feb280c 228 packetBuffer[13] = 0x4E;
star297 0:64d65feb280c 229 packetBuffer[14] = 49;
star297 0:64d65feb280c 230 packetBuffer[15] = 52;
star297 2:072248e430d0 231 int previous_timeout = _parser._timeout; // get current ESP timeout
star297 0:64d65feb280c 232 uint32_t recv_size = 0;
star297 0:64d65feb280c 233 int tries1 = 10;
star297 0:64d65feb280c 234 while ((recv_size != NTP_PACKET_SIZE) && (tries1 > 0)){
star297 0:64d65feb280c 235 tries1--;
star297 2:072248e430d0 236 setTimeout(2000);
star297 0:64d65feb280c 237 open("UDP", 1, NTPpool, 123);
star297 0:64d65feb280c 238 setTimeout(100);
star297 0:64d65feb280c 239 send(1, packetBuffer, NTP_PACKET_SIZE);
star297 2:072248e430d0 240 int tries2 = 50;
star297 0:64d65feb280c 241 while ((recv_size != NTP_PACKET_SIZE) && (tries2 > 0)){
star297 0:64d65feb280c 242 tries2--;
star297 0:64d65feb280c 243 recv_size = recv(1, packetBuffer, NTP_PACKET_SIZE);
star297 0:64d65feb280c 244 }
star297 0:64d65feb280c 245 }
star297 2:072248e430d0 246 setTimeout(previous_timeout); // restore previous ESP timeout
star297 0:64d65feb280c 247 close(1);
star297 0:64d65feb280c 248 if(recv_size==48){
star297 0:64d65feb280c 249 uint32_t secsSince1970=((packetBuffer[40]<<24)|(packetBuffer[41]<<16)|(packetBuffer[42]<<8)|packetBuffer[43])-NTP_OFFSET;
star297 3:ffdde9d17dd1 250 if (setRTC){set_time(secsSince1970);} // may need to add a second to offset any MCU delay
star297 0:64d65feb280c 251 return secsSince1970;
star297 0:64d65feb280c 252 }
star297 0:64d65feb280c 253 else{return 0;}
star297 0:64d65feb280c 254 }
star297 0:64d65feb280c 255
star297 0:64d65feb280c 256 void ESP8266::setTimeout(uint32_t timeout_ms)
star297 0:64d65feb280c 257 {
star297 0:64d65feb280c 258 _parser.setTimeout(timeout_ms);
star297 0:64d65feb280c 259 }
star297 0:64d65feb280c 260
star297 0:64d65feb280c 261 bool ESP8266::readable()
star297 0:64d65feb280c 262 {
star297 0:64d65feb280c 263 return _serial.readable();
star297 0:64d65feb280c 264 }
star297 0:64d65feb280c 265
star297 0:64d65feb280c 266 bool ESP8266::writeable()
star297 0:64d65feb280c 267 {
star297 0:64d65feb280c 268 return _serial.writeable();
star297 0:64d65feb280c 269 }
star297 0:64d65feb280c 270