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 #if 0 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 #endif 00316 } 00317 00318 void ESP8266::reset() 00319 { 00320 reset_pin = 0; 00321 wait_us(20); 00322 reset_pin = 1; 00323 //wait(1); 00324 //reset_pin = !reset_pin 00325 //send("+++",3); 00326 wait(1); 00327 state.cmdMode = true; 00328 sendCommand("AT", "OK", NULL, 1000); 00329 sendCommand("AT+RST", "ready", NULL, 10000); 00330 state.associated = false; 00331 00332 } 00333 00334 bool ESP8266::reboot() 00335 { 00336 reset(); 00337 return true; 00338 } 00339 00340 void ESP8266::handler_rx(void) 00341 { 00342 //read characters 00343 char c; 00344 while (wifi.readable()) { 00345 c=wifi.getc(); 00346 buf_ESP8266.queue(c); 00347 //if (state.cmdMode) pc.printf("%c",c); //debug echo, needs fast serial console to prevent UART overruns 00348 } 00349 } 00350 00351 void ESP8266::attach_rx(bool callback) 00352 { 00353 if (!callback) { 00354 wifi.attach(NULL); 00355 } 00356 else { 00357 wifi.attach(this, &ESP8266::handler_rx); 00358 } 00359 } 00360 00361 int ESP8266::readable() 00362 { 00363 return buf_ESP8266.available(); 00364 } 00365 00366 int ESP8266::writeable() 00367 { 00368 return wifi.writeable(); 00369 } 00370 00371 char ESP8266::getc() 00372 { 00373 char c=0; 00374 while (!buf_ESP8266.available()); 00375 buf_ESP8266.dequeue(&c); 00376 return c; 00377 } 00378 00379 int ESP8266::putc(char c) 00380 { 00381 while (!wifi.writeable() || wifi.readable()); //wait for echoed command characters to be read first 00382 return wifi.putc(c); 00383 } 00384 00385 void ESP8266::flush() 00386 { 00387 buf_ESP8266.flush(); 00388 } 00389 00390 int ESP8266::send(const char * buf, int len) 00391 { 00392 //TODO: need to add handler for data > 2048B, this is the max packet size of the ESP8266. 00393 if(len >= 2048){ 00394 WARN("send buffer >= 2048B, need to chunk this up to be less."); 00395 } 00396 const char* bufptr=buf; 00397 for(int i=0; i<len; i++) { 00398 putc((int)*bufptr++); 00399 } 00400 return len; 00401 } 00402 00403 bool ESP8266::sendCommand(const char * cmd, const char * ACK, char * res, int timeout) 00404 { 00405 char read; 00406 char checking[512] = ""; 00407 int checking_size = 0; 00408 int fond = -1; 00409 Timer tmr; 00410 int result = 0; 00411 00412 DBG("sendCmd:\t %s",cmd); 00413 00414 attach_rx(true); 00415 00416 //We flush the buffer 00417 while (readable()) 00418 getc(); 00419 00420 if (!ACK || !strcmp(ACK, "NO")) { 00421 for (int i = 0; i < strlen(cmd); i++) { 00422 result = (putc(cmd[i]) == cmd[i]) ? result + 1 : result; 00423 wait(0.005f); // prevents stuck recieve ready (?) need to let echoed character get read first 00424 } 00425 putc(13); //CR 00426 wait(0.005f); // wait for echo 00427 putc(10); //LF 00428 00429 } else { 00430 //We flush the buffer 00431 while (readable()) 00432 getc(); 00433 00434 tmr.start(); 00435 for (int i = 0; i < strlen(cmd); i++) { 00436 result = (putc(cmd[i]) == cmd[i]) ? result + 1 : result; 00437 wait(.005); // wait for echo 00438 } 00439 putc(13); //CR 00440 wait(0.005f); // wait for echo 00441 putc(10); //LF 00442 00443 while (1) { 00444 if (tmr.read_ms() > timeout) { 00445 //We flush the buffer 00446 while (readable()) 00447 getc(); 00448 00449 DBG("check:\t %s", checking); 00450 00451 attach_rx(true); 00452 return -1; 00453 } else if (readable()) { 00454 read = getc(); 00455 //pc.printf("%c",read); //debug echo 00456 if ( read != '\r' && read != '\n') { 00457 checking[checking_size] = read; 00458 checking_size++; 00459 checking[checking_size] = '\0'; 00460 fond = strfind(checking,ACK,0); 00461 if (fond != -1) { 00462 wait(0.01f); 00463 00464 //We flush the buffer 00465 while (readable()) 00466 read = getc(); 00467 //printf("%c",read); //debug echo 00468 break; 00469 } 00470 } 00471 } 00472 } 00473 DBG("check: %s", checking); 00474 00475 attach_rx(true); 00476 return result; 00477 } 00478 00479 //the user wants the result from the command (ACK == NULL, res != NULL) 00480 if (res != NULL) { 00481 int i = 0; 00482 Timer timeout; 00483 timeout.start(); 00484 tmr.reset(); 00485 while (1) { 00486 if (timeout.read() > 2) { 00487 if (i == 0) { 00488 res = NULL; 00489 break; 00490 } 00491 res[i] = '\0'; 00492 DBG("user str 1: %s", res); 00493 00494 break; 00495 } else { 00496 if (tmr.read_ms() > 300) { 00497 res[i] = '\0'; 00498 DBG("user str: %s", res); 00499 00500 break; 00501 } 00502 if (readable()) { 00503 tmr.start(); 00504 read = getc(); 00505 00506 // we drop \r and \n 00507 if ( read != '\r' && read != '\n') { 00508 res[i++] = read; 00509 } 00510 } 00511 } 00512 } 00513 DBG("user str: %s", res); 00514 } 00515 00516 //We flush the buffer 00517 while (readable()) 00518 getc(); 00519 00520 attach_rx(true); 00521 DBG("result: %d", result) 00522 return result; 00523 }
Generated on Wed Jul 13 2022 01:59:28 by
