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