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:
Mon Feb 11 00:05:12 2019 +0000
Revision:
0:64d65feb280c
Child:
2:072248e430d0
Initial commit, OS2 version. Latest ESP8266 firmware integration + functions added- RSSI, Fast NTP Client set RTC, Fast web page send with error handling, added more AT command functions.

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