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.
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 00023 //#include <string> 00024 //#include <algorithm> 00025 00026 //Debug is disabled by default 00027 #if 0 00028 #define DBG(x, ...) pc.printf("[ESP8266 : DBG]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 00029 #define WARN(x, ...) pc.printf("[ESP8266 : WARN]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 00030 #define ERR(x, ...) pc.printf("[ESP8266 : ERR]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 00031 #else 00032 #define DBG(x, ...) //wait_us(10); 00033 #define WARN(x, ...) //wait_us(10); 00034 #define ERR(x, ...) 00035 #endif 00036 00037 #if 0 00038 #define INFO(x, ...) printf("[ESP8266 : INFO]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 00039 #else 00040 #define INFO(x, ...) 00041 #endif 00042 00043 #define ESP_MAX_TRY_JOIN 3 00044 #define ESP_MAXID 4 // the largest possible ID Value (max num of sockets possible) 00045 00046 ESP8266 * ESP8266::inst; 00047 char* ip = NULL; 00048 00049 ESP8266::ESP8266(PinName tx, PinName rx, PinName reset, const char *ssid, const char *phrase, uint32_t baud) : 00050 wifi(tx, rx), reset_pin(reset), buf_ESP8266(ESP_MBUFFE_MAX) 00051 { 00052 INFO("Initializing ESP8266 object"); 00053 memset(&state, 0, sizeof(state)); 00054 00055 00056 strcpy(this->ssid, ssid); 00057 strcpy(this->phrase, phrase); 00058 inst = this; 00059 attach_rx(false); 00060 00061 wifi.baud(baud); // initial baud rate of the ESP8266 00062 00063 state.associated = false; 00064 state.cmdMode = false; 00065 } 00066 00067 bool ESP8266::join() 00068 { 00069 char cmd[100]; 00070 sendCommand( "AT+CWMODE=1", "change", NULL, 1000); 00071 //string cmd="AT+CWJAP=\""+(string)this->ssid+"\",\""+(string)this->phrase+"\""; 00072 sprintf(cmd,"AT+CWJAP=\"%s\",\"%s\"",this->ssid,this->phrase); 00073 if( sendCommand( cmd, "OK", NULL, 10000) ) { 00074 // successfully joined the network 00075 state.associated = true; 00076 INFO("ssid: %s, phrase: %s", this->ssid, this->phrase); 00077 return true; 00078 } 00079 return false; 00080 } 00081 00082 bool ESP8266::connect() 00083 { 00084 sendCommand("AT+CWDHCP=1,1","OK",NULL,1000); // DHCP Enabled in Station Mode 00085 return ESP8266::join(); 00086 } 00087 00088 bool ESP8266::is_connected() 00089 { 00090 return true; 00091 } 00092 00093 bool ESP8266::start(bool type,char* ip, int port, int id) 00094 { 00095 char cmd[256]; 00096 // Error Check 00097 if(id > ESP_MAXID) { 00098 ERR("startUDPMulti: max id is: %d, id given is %d",ESP_MAXID,id); 00099 return false; 00100 } 00101 // Single Connection Mode 00102 if(id < 0) { 00103 DBG("Start Single Connection Mode"); 00104 //char portstr[5]; 00105 bool check [3] = {0}; 00106 //sprintf(portstr, "%d", port); 00107 switch(type) { 00108 case ESP_UDP_TYPE : //UDP 00109 sprintf(cmd,"AT+CIPSTART=\"UDP\",\"%s\",%d",ip,port); 00110 check[0] = sendCommand(cmd, "OK", NULL, 10000); 00111 //check[0] = sendCommand(( "AT+CIPSTART=\"UDP\",\"" + (string) ip + "\"," + (string) portstr ).c_str(), "OK", NULL, 10000); 00112 break; 00113 case ESP_TCP_TYPE : //TCP 00114 sprintf(cmd,"AT+CIPSTART=\"TCP\",\"%s\",%d",ip,port); 00115 check[0] = sendCommand(cmd, "OK", NULL, 10000); 00116 //check[0] = sendCommand(( "AT+CIPSTART=\"TCP\",\"" + (string) ip + "\"," + (string) portstr ).c_str(), "OK", NULL, 10000); 00117 break; 00118 default: 00119 ERR("Default hit for starting connection, this shouldnt be possible!!"); 00120 break; 00121 } 00122 check[1] = sendCommand("AT+CIPMODE=1", "OK", NULL, 1000);// go into transparent mode 00123 check[2] = sendCommand("AT+CIPSEND", ">", NULL, 1000);// go into transparent mode 00124 // check that all commands were sucessful 00125 if(check[0] and check[1] and check[2]) { 00126 state.cmdMode = false; 00127 return true; 00128 } else { 00129 ERR("startUDPTransparent Failed for ip:%s, port:%d",ip,port); 00130 return false; 00131 } 00132 } 00133 // Multi Connection Mode 00134 else { 00135 //TODO: impliment Multi Connection Mode 00136 ERR("Not currently Supported!"); 00137 return false; 00138 } 00139 } 00140 00141 bool ESP8266::startUDP(char* ip, int port, int id, int length) 00142 { 00143 char cmd[256]; 00144 char portstr[5]; 00145 char idstr[1]; 00146 char lenstr[2]; 00147 00148 sprintf(portstr, "%d", port); 00149 sprintf(idstr, "%d", id); 00150 sprintf(lenstr, "%d", length); 00151 00152 sendCommand("AT+CIPMUX=1", "OK", NULL, 1000); 00153 sprintf(cmd,"AT+CIPSTART=%d,\"UDP\",\"%s\",%d,1112,0",id,ip,port); 00154 sendCommand(cmd, "OK", NULL, 10000); 00155 //sendCommand(( "AT+CIPSTART=" + string(idstr) + ",\"UDP\",\"" + (string) ip + "\"," + (string) portstr + ",1112,0").c_str(), "OK", NULL, 10000); 00156 sprintf(cmd,"AT+CIPSEND=%d,%d",id,length); 00157 sendCommand(cmd, ">", NULL, 1000);// go into transparent mode 00158 //sendCommand(("AT+CIPSEND=" + (string)idstr + "," + (string)lenstr).c_str(), ">", NULL, 1000);// go into transparent mode 00159 DBG("Data Mode\r\n"); 00160 state.cmdMode = false; 00161 00162 return true; 00163 } 00164 00165 bool ESP8266::startTCPServer(int port) 00166 { 00167 char cmd[100]; 00168 bool command_results[3]; 00169 command_results[0]=sendCommand("AT+CWMODE=3", "OK", NULL, 1000); 00170 command_results[1]=sendCommand("AT+CIPMUX=1", "OK", NULL, 1000); 00171 if(port == 333){ 00172 command_results[2]=sendCommand("AT+CIPSERVER=1", "OK", NULL, 1000); 00173 } 00174 else{ 00175 sprintf(cmd,"AT+CIPSERVER=1,%d",port); 00176 command_results[2]=sendCommand(cmd, "OK", NULL, 1000); 00177 } 00178 //sendCommand("AT+CIFSR", "OK", NULL, 1000); 00179 DBG("Data Mode\r\n"); 00180 state.cmdMode = false; 00181 if (command_results[0] and command_results[1] and command_results[2]){ 00182 return true; 00183 } 00184 else{ 00185 return false; 00186 } 00187 } 00188 00189 bool ESP8266::close() 00190 { 00191 wait(0.1f); 00192 send("+++",3); 00193 wait(1.0f); 00194 state.cmdMode = true; 00195 sendCommand("AT+CIPCLOSE","OK", NULL, 10000); 00196 return true; 00197 } 00198 00199 bool ESP8266::disconnect() 00200 { 00201 // if already disconnected, return 00202 if (!state.associated) 00203 return true; 00204 // send command to quit AP 00205 sendCommand("AT+CWQAP", "OK", NULL, 10000); 00206 state.associated = false; 00207 return true; 00208 } 00209 00210 int ESP8266::strfind(const char *str,const char *chkstr,int pos) 00211 { 00212 if( (strlen(str)-pos) < strlen(chkstr) ) return(-1); 00213 00214 00215 for(int i=pos;i<strlen(str);i++) 00216 { 00217 if(memcmp(chkstr,&str[i],strlen(chkstr))==0) 00218 { 00219 return(i); 00220 } 00221 } 00222 return(-1); 00223 } 00224 00225 char* ESP8266::substr(const char *str , char *outstr , int pos1 , int pos2 ) 00226 { 00227 int size = pos2 - pos1; 00228 00229 memcpy(outstr , &str[pos1] , size ); 00230 outstr[size] = '\0'; 00231 00232 return(outstr); 00233 } 00234 00235 int ESP8266::strcount(const char *str , char countstr ) 00236 { 00237 int ret = 0; 00238 00239 for(int i = 0 ; i < strlen(str) ; i++) 00240 { 00241 if( str[i] == countstr ) 00242 { 00243 ret++; 00244 } 00245 00246 } 00247 00248 return(ret); 00249 } 00250 00251 /* 00252 Assuming Returned data looks like this: 00253 +CIFSR:STAIP,"192.168.11.2" 00254 +CIFSR:STAMAC,"18:fe:34:9f:3a:f5" 00255 grabbing IP from first set of quotation marks 00256 */ 00257 char* ESP8266::getIPAddress() 00258 { 00259 char result[30] = {0}; 00260 char tmp[30] = {0}; 00261 int check = 0; 00262 check = sendCommand("AT+CIFSR", NULL, result, 1000); 00263 //pc.printf("\r\nReceivedInfo for IP Command is: %s\r\n",result); 00264 ip = ipString; 00265 if(check) { 00266 // Success 00267 uint8_t pos1 = 0, pos2 = 0; 00268 //uint8_t pos3 = 0, pos4 = 0; 00269 pos1 = strfind(result,"+CIFSR:STAIP",0); 00270 //pos1 = resultString.find("+CIFSR:STAIP"); 00271 pos1 = strfind(result,"\"",pos1); 00272 //pos1 = resultString.find('"',pos1); 00273 pos2 = strfind(result,"\"",pos1+1); 00274 //pos2 = resultString.find('"',pos1+1); 00275 //pos3 = resultString.find('"',pos2+1); //would find mac address 00276 //pos4 = resultString.find('"',pos3+1); 00277 strncpy(ipString,substr(result,tmp,pos1,pos2),sizeof(ipString)); 00278 INFO("IP: %s",ipString); 00279 ip = ipString; 00280 00281 } else { 00282 // Failure 00283 ERR("getIPAddress() failed"); 00284 ip = NULL; 00285 } 00286 return ip; 00287 } 00288 00289 bool ESP8266::gethostbyname(const char * host, char * ip) 00290 { 00291 int nb_digits = 0; 00292 char tmp[100]; 00293 00294 strcpy(ip,host); 00295 00296 return true; 00297 00298 // no dns needed 00299 int pos = strfind(host,".",0); 00300 if (pos != -1) { 00301 nb_digits = atoi(substr(host,tmp,0,pos)); 00302 } 00303 //printf("substrL %s\r\n", sub.c_str()); 00304 if (strcount(host,'.') == 3 && nb_digits > 0) { 00305 strcpy(ip, host); 00306 return true; 00307 } else { 00308 // dns needed, not currently available 00309 ERR("gethostbyname(): DNS Not currently available, only use IP Addresses!"); 00310 return false; 00311 } 00312 } 00313 00314 void ESP8266::reset() 00315 { 00316 reset_pin = 0; 00317 wait_us(20); 00318 reset_pin = 1; 00319 //wait(1); 00320 //reset_pin = !reset_pin 00321 //send("+++",3); 00322 wait(1); 00323 state.cmdMode = true; 00324 sendCommand("AT", "OK", NULL, 1000); 00325 sendCommand("AT+RST", "ready", NULL, 10000); 00326 state.associated = false; 00327 00328 } 00329 00330 bool ESP8266::reboot() 00331 { 00332 reset(); 00333 return true; 00334 } 00335 00336 void ESP8266::handler_rx(void) 00337 { 00338 //read characters 00339 char c; 00340 while (wifi.readable()) { 00341 c=wifi.getc(); 00342 buf_ESP8266.queue(c); 00343 //if (state.cmdMode) pc.printf("%c",c); //debug echo, needs fast serial console to prevent UART overruns 00344 } 00345 } 00346 00347 void ESP8266::attach_rx(bool callback) 00348 { 00349 if (!callback) { 00350 wifi.attach(NULL); 00351 } 00352 else { 00353 wifi.attach(this, &ESP8266::handler_rx); 00354 } 00355 } 00356 00357 int ESP8266::readable() 00358 { 00359 return buf_ESP8266.available(); 00360 } 00361 00362 int ESP8266::writeable() 00363 { 00364 return wifi.writeable(); 00365 } 00366 00367 char ESP8266::getc() 00368 { 00369 char c=0; 00370 while (!buf_ESP8266.available()); 00371 buf_ESP8266.dequeue(&c); 00372 return c; 00373 } 00374 00375 int ESP8266::putc(char c) 00376 { 00377 while (!wifi.writeable() || wifi.readable()); //wait for echoed command characters to be read first 00378 return wifi.putc(c); 00379 } 00380 00381 void ESP8266::flush() 00382 { 00383 buf_ESP8266.flush(); 00384 } 00385 00386 int ESP8266::send(const char * buf, int len) 00387 { 00388 //TODO: need to add handler for data > 2048B, this is the max packet size of the ESP8266. 00389 if(len >= 2048){ 00390 WARN("send buffer >= 2048B, need to chunk this up to be less."); 00391 } 00392 const char* bufptr=buf; 00393 for(int i=0; i<len; i++) { 00394 putc((int)*bufptr++); 00395 } 00396 return len; 00397 } 00398 00399 bool ESP8266::sendCommand(const char * cmd, const char * ACK, char * res, int timeout) 00400 { 00401 char read; 00402 char checking[512] = ""; 00403 int checking_size = 0; 00404 int fond = -1; 00405 Timer tmr; 00406 int result = 0; 00407 00408 DBG("sendCmd:\t %s",cmd); 00409 00410 attach_rx(true); 00411 00412 //We flush the buffer 00413 while (readable()) 00414 getc(); 00415 00416 if (!ACK || !strcmp(ACK, "NO")) { 00417 for (int i = 0; i < strlen(cmd); i++) { 00418 result = (putc(cmd[i]) == cmd[i]) ? result + 1 : result; 00419 wait(0.005f); // prevents stuck recieve ready (?) need to let echoed character get read first 00420 } 00421 putc(13); //CR 00422 wait(0.005f); // wait for echo 00423 putc(10); //LF 00424 00425 } else { 00426 //We flush the buffer 00427 while (readable()) 00428 getc(); 00429 00430 tmr.start(); 00431 for (int i = 0; i < strlen(cmd); i++) { 00432 result = (putc(cmd[i]) == cmd[i]) ? result + 1 : result; 00433 wait(.005); // wait for echo 00434 } 00435 putc(13); //CR 00436 wait(0.005f); // wait for echo 00437 putc(10); //LF 00438 00439 while (1) { 00440 if (tmr.read_ms() > timeout) { 00441 //We flush the buffer 00442 while (readable()) 00443 getc(); 00444 00445 DBG("check:\t %s", checking); 00446 00447 attach_rx(true); 00448 return -1; 00449 } else if (readable()) { 00450 read = getc(); 00451 //pc.printf("%c",read); //debug echo 00452 if ( read != '\r' && read != '\n') { 00453 checking[checking_size] = read; 00454 checking_size++; 00455 checking[checking_size] = '\0'; 00456 fond = strfind(checking,ACK,0); 00457 if (fond != -1) { 00458 wait(0.01f); 00459 00460 //We flush the buffer 00461 while (readable()) 00462 read = getc(); 00463 //printf("%c",read); //debug echo 00464 break; 00465 } 00466 } 00467 } 00468 } 00469 DBG("check: %s", checking); 00470 00471 attach_rx(true); 00472 return result; 00473 } 00474 00475 //the user wants the result from the command (ACK == NULL, res != NULL) 00476 if (res != NULL) { 00477 int i = 0; 00478 Timer timeout; 00479 timeout.start(); 00480 tmr.reset(); 00481 while (1) { 00482 if (timeout.read() > 2) { 00483 if (i == 0) { 00484 res = NULL; 00485 break; 00486 } 00487 res[i] = '\0'; 00488 DBG("user str 1: %s", res); 00489 00490 break; 00491 } else { 00492 if (tmr.read_ms() > 300) { 00493 res[i] = '\0'; 00494 DBG("user str: %s", res); 00495 00496 break; 00497 } 00498 if (readable()) { 00499 tmr.start(); 00500 read = getc(); 00501 00502 // we drop \r and \n 00503 if ( read != '\r' && read != '\n') { 00504 res[i++] = read; 00505 } 00506 } 00507 } 00508 } 00509 DBG("user str: %s", res); 00510 } 00511 00512 //We flush the buffer 00513 while (readable()) 00514 getc(); 00515 00516 attach_rx(true); 00517 DBG("result: %d", result) 00518 return result; 00519 }
Generated on Thu Jul 14 2022 01:56:10 by
