Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of ESP8266Interface by
ESP8266.cpp
00001 /* Copyright (C) 2012 mbed.org, MIT License 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00004 * and associated documentation files (the "Software"), to deal in the Software without restriction, 00005 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 00006 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 00007 * furnished to do so, subject to the following conditions: 00008 * 00009 * The above copyright notice and this permission notice shall be included in all copies or 00010 * substantial portions of the Software. 00011 * 00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00017 */ 00018 00019 #include "mbed.h" 00020 #include "ESP8266.h" 00021 #include "Endpoint.h" 00022 #include <string> 00023 #include <algorithm> 00024 00025 //Debug is disabled by default 00026 #if 0 00027 #define DBG(x, ...) printf("[ESP8266 : DBG]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 00028 #define WARN(x, ...) printf("[ESP8266 : WARN]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 00029 #define ERR(x, ...) printf("[ESP8266 : ERR]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 00030 #else 00031 #define DBG(x, ...) //wait_us(10); 00032 #define WARN(x, ...) //wait_us(10); 00033 #define ERR(x, ...) 00034 #endif 00035 00036 #if 0 00037 #define INFO(x, ...) printf("[ESP8266 : INFO]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 00038 #else 00039 #define INFO(x, ...) 00040 #endif 00041 00042 #define ESP_MAX_TRY_JOIN 3 00043 #define ESP_MAXID 4 // the largest possible ID Value (max num of sockets possible) 00044 00045 ESP8266 * ESP8266::inst; 00046 char* ip = NULL; 00047 00048 ESP8266::ESP8266(PinName tx, PinName rx, PinName reset, const char *ssid, const char *phrase, uint32_t baud) : 00049 wifi(tx, rx), reset_pin(reset), buf_ESP8266(ESP_MBUFFE_MAX) 00050 { 00051 INFO("Initializing ESP8266 object"); 00052 memset(&state, 0, sizeof(state)); 00053 00054 00055 strcpy(this->ssid, ssid); 00056 strcpy(this->phrase, phrase); 00057 inst = this; 00058 attach_rx(false); 00059 00060 wifi.baud(baud); // initial baud rate of the ESP8266 00061 00062 state.associated = false; 00063 state.cmdMode = false; 00064 } 00065 00066 bool ESP8266::join() 00067 { 00068 sendCommand( "AT+CWMODE=1", "change", NULL, 1000); 00069 string cmd="AT+CWJAP=\""+(string)this->ssid+"\",\""+(string)this->phrase+"\""; 00070 if( sendCommand( cmd.c_str(), "OK", NULL, 10000) ) { 00071 // successfully joined the network 00072 state.associated = true; 00073 INFO("ssid: %s, phrase: %s", this->ssid, this->phrase); 00074 return true; 00075 } 00076 return false; 00077 } 00078 00079 bool ESP8266::connect() 00080 { 00081 sendCommand("AT+CWDHCP=1,1","OK",NULL,1000); // DHCP Enabled in Station Mode 00082 return ESP8266::join(); 00083 } 00084 00085 bool ESP8266::is_connected() 00086 { 00087 return true; 00088 } 00089 00090 bool ESP8266::start(bool type,char* ip, int port, int id) 00091 { 00092 // Error Check 00093 if(id > ESP_MAXID) { 00094 ERR("startUDPMulti: max id is: %d, id given is %d",ESP_MAXID,id); 00095 return false; 00096 } 00097 // Single Connection Mode 00098 if(id < 0) { 00099 DBG("Start Single Connection Mode"); 00100 char portstr[5]; 00101 char idstr[2]; 00102 bool check [3] = {0}; 00103 sprintf(idstr,"%d",id); 00104 sprintf(portstr, "%d", port); 00105 switch(type) { 00106 case ESP_UDP_TYPE : //UDP 00107 check[0] = sendCommand(( "AT+CIPSTART=\"UDP\",\"" + (string) ip + "\"," + (string) portstr ).c_str(), "OK", NULL, 10000); 00108 break; 00109 case ESP_TCP_TYPE : //TCP 00110 check[0] = sendCommand(( "AT+CIPSTART=\"TCP\",\"" + (string) ip + "\"," + (string) portstr ).c_str(), "OK", NULL, 10000); 00111 break; 00112 default: 00113 ERR("Default hit for starting connection, this shouldnt be possible!!"); 00114 break; 00115 } 00116 check[1] = sendCommand("AT+CIPMODE=1", "OK", NULL, 1000);// go into transparent mode 00117 check[2] = sendCommand("AT+CIPSEND", ">", NULL, 1000);// go into transparent mode 00118 // check that all commands were sucessful 00119 if(check[0] and check[1] and check[2]) { 00120 state.cmdMode = false; 00121 return true; 00122 } else { 00123 ERR("startUDPTransparent Failed for ip:%s, port:%d",ip,port); 00124 return false; 00125 } 00126 } 00127 // Multi Connection Mode 00128 else { 00129 //TODO: impliment Multi Connection Mode 00130 ERR("Not currently Supported!"); 00131 return false; 00132 00133 // DBG("Start Multi Connection Mode"); 00134 // char portstr[5]; 00135 // char idstr[2]; 00136 // bool check [3] = {0}; 00137 // sprintf(idstr,"%d",id); 00138 // sprintf(portstr, "%d", port); 00139 // switch(type) { 00140 // case ESP_UDP_TYPE : //UDP 00141 // check[0] = sendCommand(( "AT+CIPSTART=" + (string) idstr + ",\"UDP\",\"" + (string) ip + "\"," + (string) portstr ).c_str(), "OK", NULL, 10000); 00142 // break; 00143 // case ESP_TCP_TYPE : //TCP 00144 // check[0] = sendCommand(( "AT+CIPSTART=" + (string) idstr + ",\"TCP\",\"" + (string) ip + "\"," + (string) portstr ).c_str(), "OK", NULL, 10000); 00145 // break; 00146 // default: 00147 // ERR("Default hit for starting connection, this shouldnt be possible!!"); 00148 // break; 00149 // } 00150 } 00151 } 00152 00153 bool ESP8266::startUDP(char* ip, int port, int id, int length) 00154 { 00155 char portstr[5]; 00156 char idstr[1]; 00157 char lenstr[2]; 00158 00159 sprintf(portstr, "%d", port); 00160 sprintf(idstr, "%d", id); 00161 sprintf(lenstr, "%d", length); 00162 00163 sendCommand("AT+CIPMUX=1", "OK", NULL, 1000); 00164 sendCommand(( "AT+CIPSTART=" + string(idstr) + ",\"UDP\",\"" + (string) ip + "\"," + (string) portstr + ",1112,0").c_str(), "OK", NULL, 10000); 00165 sendCommand(("AT+CIPSEND=" + (string)idstr + "," + (string)lenstr).c_str(), ">", NULL, 1000);// go into transparent mode 00166 DBG("Data Mode\r\n"); 00167 state.cmdMode = false; 00168 00169 return true; 00170 } 00171 00172 bool ESP8266::startTCPServer(int port) 00173 { 00174 bool command_results[3]; 00175 command_results[0]=sendCommand("AT+CWMODE=3", "OK", NULL, 1000); 00176 command_results[1]=sendCommand("AT+CIPMUX=1", "OK", NULL, 1000); 00177 if(port == 333){ 00178 command_results[2]=sendCommand("AT+CIPSERVER=1", "OK", NULL, 1000); 00179 } 00180 else{ 00181 char portstr[5]; 00182 sprintf(portstr, "%d", port); 00183 command_results[2]=sendCommand(("AT+CIPSERVER=1," + (string)portstr).c_str(), "OK", NULL, 1000); 00184 } 00185 //sendCommand("AT+CIFSR", "OK", NULL, 1000); 00186 DBG("Data Mode\r\n"); 00187 state.cmdMode = false; 00188 if (command_results[0] and command_results[1] and command_results[2]){ 00189 return true; 00190 } 00191 else{ 00192 return false; 00193 } 00194 } 00195 00196 bool ESP8266::close() 00197 { 00198 wait(0.1f); 00199 send("+++",3); 00200 wait(1.0f); 00201 state.cmdMode = true; 00202 sendCommand("AT+CIPCLOSE","OK", NULL, 10000); 00203 return true; 00204 } 00205 00206 bool ESP8266::disconnect() 00207 { 00208 // if already disconnected, return 00209 if (!state.associated) 00210 return true; 00211 // send command to quit AP 00212 sendCommand("AT+CWQAP", "OK", NULL, 10000); 00213 state.associated = false; 00214 return true; 00215 } 00216 00217 /* 00218 Assuming Returned data looks like this: 00219 +CIFSR:STAIP,"192.168.11.2" 00220 +CIFSR:STAMAC,"18:fe:34:9f:3a:f5" 00221 grabbing IP from first set of quotation marks 00222 */ 00223 char* ESP8266::getIPAddress() 00224 { 00225 char result[80] = {0}; 00226 int check = 0; 00227 check = sendCommand("AT+CIFSR", NULL, result, 1000); 00228 //pc.printf("\r\nReceivedInfo for IP Command is: %s\r\n",result); 00229 ip = ipString; 00230 if(check) { 00231 // Success 00232 string resultString(result); 00233 uint8_t pos1 = 0, pos2 = 0; 00234 //uint8_t pos3 = 0, pos4 = 0; 00235 pos1 = resultString.find("+CIFSR:STAIP"); 00236 pos1 = resultString.find('"',pos1); 00237 pos2 = resultString.find('"',pos1+1); 00238 //pos3 = resultString.find('"',pos2+1); //would find mac address 00239 //pos4 = resultString.find('"',pos3+1); 00240 strncpy(ipString,resultString.substr(pos1,pos2).c_str(),sizeof(ipString)); 00241 ipString[pos2 - pos1 +1] = 0; // null terminate string correctly. 00242 INFO("IP: %s",ipString); 00243 ip = ipString; 00244 00245 } else { 00246 // Failure 00247 ERR("getIPAddress() failed"); 00248 ip = NULL; 00249 } 00250 return ip; 00251 } 00252 00253 bool ESP8266::gethostbyname(const char * host, char * ip) 00254 { 00255 string h = host; 00256 int nb_digits = 0; 00257 00258 // no dns needed 00259 int pos = h.find("."); 00260 if (pos != string::npos) { 00261 string sub = h.substr(0, h.find(".")); 00262 nb_digits = atoi(sub.c_str()); 00263 } 00264 //printf("substrL %s\r\n", sub.c_str()); 00265 if (count(h.begin(), h.end(), '.') == 3 && nb_digits > 0) { 00266 strcpy(ip, host); 00267 return true; 00268 } else { 00269 // dns needed, not currently available 00270 ERR("gethostbyname(): DNS Not currently available, only use IP Addresses!"); 00271 return false; 00272 } 00273 } 00274 00275 void ESP8266::reset() 00276 { 00277 reset_pin = 0; 00278 wait_us(20); 00279 reset_pin = 1; 00280 //wait(1); 00281 //reset_pin = !reset_pin 00282 //send("+++",3); 00283 wait(1); 00284 state.cmdMode = true; 00285 sendCommand("AT", "OK", NULL, 1000); 00286 sendCommand("AT+RST", "ready", NULL, 10000); 00287 state.associated = false; 00288 00289 } 00290 00291 bool ESP8266::reboot() 00292 { 00293 reset(); 00294 return true; 00295 } 00296 00297 void ESP8266::handler_rx(void) 00298 { 00299 //read characters 00300 char c; 00301 while (wifi.readable()) { 00302 c=wifi.getc(); 00303 buf_ESP8266.queue(c); 00304 //if (state.cmdMode) pc.printf("%c",c); //debug echo, needs fast serial console to prevent UART overruns 00305 } 00306 } 00307 00308 void ESP8266::attach_rx(bool callback) 00309 { 00310 if (!callback) { 00311 wifi.attach(NULL); 00312 } 00313 else { 00314 wifi.attach(this, &ESP8266::handler_rx); 00315 } 00316 } 00317 00318 int ESP8266::readable() 00319 { 00320 return buf_ESP8266.available(); 00321 } 00322 00323 int ESP8266::writeable() 00324 { 00325 return wifi.writeable(); 00326 } 00327 00328 char ESP8266::getc() 00329 { 00330 char c=0; 00331 while (!buf_ESP8266.available()); 00332 buf_ESP8266.dequeue(&c); 00333 return c; 00334 } 00335 00336 int ESP8266::putc(char c) 00337 { 00338 while (!wifi.writeable() || wifi.readable()); //wait for echoed command characters to be read first 00339 return wifi.putc(c); 00340 } 00341 00342 void ESP8266::flush() 00343 { 00344 buf_ESP8266.flush(); 00345 } 00346 00347 int ESP8266::send(const char * buf, int len) 00348 { 00349 //TODO: need to add handler for data > 2048B, this is the max packet size of the ESP8266. 00350 if(len >= 2048){ 00351 WARN("send buffer >= 2048B, need to chunk this up to be less."); 00352 } 00353 const char* bufptr=buf; 00354 for(int i=0; i<len; i++) { 00355 putc((int)*bufptr++); 00356 } 00357 return len; 00358 } 00359 00360 bool ESP8266::sendCommand(const char * cmd, const char * ACK, char * res, int timeout) 00361 { 00362 char read; 00363 size_t found = string::npos; 00364 string checking = ""; 00365 Timer tmr; 00366 int result = 0; 00367 00368 DBG("sendCmd:\t %s",cmd); 00369 00370 attach_rx(true); 00371 00372 //We flush the buffer 00373 while (readable()) 00374 getc(); 00375 00376 if (!ACK || !strcmp(ACK, "NO")) { 00377 for (int i = 0; i < strlen(cmd); i++) { 00378 result = (putc(cmd[i]) == cmd[i]) ? result + 1 : result; 00379 wait(0.005f); // prevents stuck recieve ready (?) need to let echoed character get read first 00380 } 00381 putc(13); //CR 00382 wait(0.005f); // wait for echo 00383 putc(10); //LF 00384 00385 } else { 00386 //We flush the buffer 00387 while (readable()) 00388 getc(); 00389 00390 tmr.start(); 00391 for (int i = 0; i < strlen(cmd); i++) { 00392 result = (putc(cmd[i]) == cmd[i]) ? result + 1 : result; 00393 wait(.005); // wait for echo 00394 } 00395 putc(13); //CR 00396 wait(0.005f); // wait for echo 00397 putc(10); //LF 00398 00399 while (1) { 00400 if (tmr.read_ms() > timeout) { 00401 //We flush the buffer 00402 while (readable()) 00403 getc(); 00404 00405 DBG("check:\t %s", checking.c_str()); 00406 00407 attach_rx(true); 00408 return -1; 00409 } else if (readable()) { 00410 read = getc(); 00411 //printf("%c",read); //debug echo 00412 if ( read != '\r' && read != '\n') { 00413 checking += read; 00414 found = checking.find(ACK); 00415 if (found != string::npos) { 00416 wait(0.01f); 00417 00418 //We flush the buffer 00419 while (readable()) 00420 read = getc(); 00421 //printf("%c",read); //debug echo 00422 break; 00423 } 00424 } 00425 } 00426 } 00427 DBG("check: %s", checking.c_str()); 00428 00429 attach_rx(true); 00430 return result; 00431 } 00432 00433 //the user wants the result from the command (ACK == NULL, res != NULL) 00434 if (res != NULL) { 00435 int i = 0; 00436 Timer timeout; 00437 timeout.start(); 00438 tmr.reset(); 00439 while (1) { 00440 if (timeout.read() > 2) { 00441 if (i == 0) { 00442 res = NULL; 00443 break; 00444 } 00445 res[i] = '\0'; 00446 DBG("user str 1: %s", res); 00447 00448 break; 00449 } else { 00450 if (tmr.read_ms() > 300) { 00451 res[i] = '\0'; 00452 DBG("user str: %s", res); 00453 00454 break; 00455 } 00456 if (readable()) { 00457 tmr.start(); 00458 read = getc(); 00459 00460 // we drop \r and \n 00461 if ( read != '\r' && read != '\n') { 00462 res[i++] = read; 00463 } 00464 } 00465 } 00466 } 00467 DBG("user str: %s", res); 00468 } 00469 00470 //We flush the buffer 00471 while (readable()) 00472 getc(); 00473 00474 attach_rx(true); 00475 DBG("result: %d", result) 00476 return result; 00477 }
Generated on Thu Jul 14 2022 01:44:42 by
1.7.2
