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