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 ESP8266NodeMCUInterface 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 #define INFO(x, ...) printf("[ESP8266 : INFO]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 00031 #ifndef ESP8266_ECHO 00032 #define ESP8266_ECHO 1 00033 #endif 00034 #else 00035 #define DBG(x, ...) 00036 #define WARN(x, ...) 00037 #define ERR(x, ...) 00038 #define INFO(x, ...) 00039 #endif 00040 00041 00042 ESP8266 *ESP8266::_inst; 00043 00044 ESP8266::ESP8266(PinName tx, PinName rx, PinName reset, int baud, int timeout) : 00045 _serial(tx, rx), _reset_pin(reset) { 00046 INFO("Initializing ESP8266 object"); 00047 00048 _baud = baud; 00049 _timeout = timeout; 00050 00051 _serial.baud(_baud); 00052 00053 _inst = this; 00054 } 00055 00056 bool ESP8266::reset() { 00057 _reset_pin = 0; 00058 wait_us(20); 00059 _reset_pin = 1; 00060 00061 // Send reboot command in case reset is not connected 00062 //return command("\x03\r\n" "node.restart()") && execute(); 00063 return true; 00064 } 00065 00066 bool ESP8266::init() { 00067 // Reset device to clear state 00068 return reset(); 00069 } 00070 00071 bool ESP8266::connect(const char *ssid, const char *phrase) { 00072 int ip_len = 15; 00073 // Check if already connected. 00074 if (!(command("ip=wifi.sta.getip();") && 00075 command("print(ip);") && 00076 execute(_ip, &ip_len))) 00077 return false; 00078 00079 _ip[ip_len] = 0; 00080 00081 if (strcmp(_ip, "nil") != 0) 00082 return true; 00083 00084 00085 // Configure as station with passed ssid and passphrase 00086 if (!(command("wifi.setmode(wifi.STATION);") && 00087 command("wifi.sta.config('") && 00088 command(ssid) && 00089 command("','") && 00090 command(phrase) && 00091 command("');") && 00092 command("wifi.sta.connect();") && 00093 execute())) 00094 return false; 00095 00096 // Wait for an IP address 00097 // TODO WISHLIST make this a seperate check so it can run asynch? 00098 Timer timer; 00099 timer.start(); 00100 00101 while (true) { 00102 int ip_len = 15; 00103 00104 if (!(command("ip=wifi.sta.getip();") && 00105 command("print(ip);") && 00106 execute(_ip, &ip_len))) 00107 return false; 00108 00109 _ip[ip_len] = 0; 00110 00111 if (strcmp(_ip, "nil") != 0) 00112 return true; 00113 00114 if (timer.read_ms() > _timeout) 00115 return false; 00116 } 00117 } 00118 00119 bool ESP8266::disconnect() { 00120 int ip_len = 15; 00121 00122 if (!(command("wifi.sta.disconnect();") && 00123 command("ip=wifi.sta.getip();") && 00124 command("print(ip)") && 00125 execute(_ip, &ip_len))) 00126 return false; 00127 00128 _ip[ip_len] = 0; 00129 00130 return (strcmp(_ip, "nil") == 0); 00131 } 00132 00133 bool ESP8266::is_connected() { 00134 return (strcmp(_ip, "nil") != 0); 00135 } 00136 00137 bool ESP8266::open(bool type, char* ip, int port, int id) { 00138 // Create the actual connection 00139 if (!(command("c=net.createConnection(") && 00140 command(type ? "net.TCP" : "net.UDP") && 00141 command(")") && 00142 execute())) 00143 return false; 00144 00145 // Setup handlers for connecting and disconnecting 00146 if (!(command("cc=nil;") && 00147 command("c:on('connection',function() cc=true end);") && 00148 command("c:on('disconnection',function() cc=false end)") && 00149 execute())) 00150 return false; 00151 00152 // Setup functions for sending and recieving characters on the esp side 00153 if (!(command("cm='';") && 00154 command("function cs(n) c:send(n) end;") && 00155 command("function ca() print(#cm) end;") && 00156 command("function cr(n) " 00157 "d=cm:sub(1,n):gsub('.', function(s) return s.format('\\\\%03d', s:byte(1)) end);" 00158 "cm=cm:sub(n+1,-1);" 00159 "end;") && 00160 command("c:on('receive', function(c,n) cm=cm..n;end);") && execute())) 00161 return false; 00162 00163 // Convert port to a string 00164 char port_buf[16]; 00165 sprintf(port_buf, "%d", port); 00166 00167 // Connect to the ip address 00168 if (!(command("c:connect(") && 00169 command(port_buf) && 00170 command(",'") && 00171 command(ip) && 00172 command("')") && 00173 execute())) 00174 return false; 00175 00176 // Wait for it to connect 00177 // TODO WISHLIST make this a seperate check so it can run asynch? 00178 Timer timer; 00179 timer.start(); 00180 00181 while (true) { 00182 char con_buf[5]; 00183 int con_len = 5; 00184 00185 if (!(command("print(cc)") && execute(con_buf, &con_len))) 00186 return false; 00187 00188 if (memcmp(con_buf, "true", con_len) == 0) 00189 return true; 00190 else if (memcmp(con_buf, "false", con_len) == 0) 00191 return false; 00192 00193 if (timer.read_ms() > _timeout) 00194 return false; 00195 } 00196 } 00197 00198 bool ESP8266::close() { 00199 return command("c:close();" "c=nil") && execute(); 00200 } 00201 00202 bool ESP8266::send(const char *buffer, int len) { 00203 for (int line = 0; line < len; line += ESP_MAX_LINE) { 00204 if (!command("cs('")) 00205 return false; 00206 00207 for (int i = 0; i < ESP_MAX_LINE && line+i < len; i++) { 00208 int a = buffer[line+i] / 100; 00209 int b = (buffer[line+i] - a*100) / 10; 00210 int c = (buffer[line+i] - a*100 - b*10); 00211 00212 if (serialputc('\\') < 0 || 00213 serialputc(a + '0') < 0 || 00214 serialputc(b + '0') < 0 || 00215 serialputc(c + '0') < 0) 00216 return false; 00217 } 00218 00219 if (!(command("')") && execute())) 00220 return false; 00221 } 00222 00223 return true; 00224 } 00225 00226 bool ESP8266::recv(char *buffer, int *len) { 00227 // Nick 00228 if (!(command("print(cm)") && execute_full_length(buffer, len))) { 00229 return false; 00230 } 00231 00232 return true; 00233 // /Nick 00234 00235 char len_buf[16]; 00236 sprintf(len_buf, "%d", *len); 00237 if (!(command("cr(") && 00238 command(len_buf) && 00239 command(")"))) 00240 return false; 00241 00242 if (!(command("\r\n") && discardEcho())) 00243 return false; 00244 00245 // Read in response 00246 for (int i = 0; i < *len; i++) { 00247 int e = serialgetc(); 00248 if (e == '\r') { 00249 *len = i; 00250 break; 00251 } else if (e != '\\') { 00252 return false; 00253 } 00254 00255 int a = serialgetc(); 00256 int b = serialgetc(); 00257 int c = serialgetc(); 00258 00259 if (a < 0 || b < 0 || c < 0) 00260 return false; 00261 00262 buffer[i] = (a-'0')*100 + (b-'0')*10 + (c-'0'); 00263 } 00264 00265 // Flush to next prompt 00266 return flush(); 00267 } 00268 00269 int ESP8266::putc(char c) { 00270 char buffer[1] = { c }; 00271 00272 return send(buffer, 1) ? 0 : -1; 00273 } 00274 00275 int ESP8266::getc() { 00276 char buffer[1]; 00277 00278 while (true) { 00279 int len = 1; 00280 00281 if (!recv(buffer, &len)) 00282 return -1; 00283 00284 if (len > 0) 00285 break; 00286 } 00287 00288 return buffer[0]; 00289 } 00290 00291 int ESP8266::writeable() { 00292 // Always succeeds since message can be temporarily stored on the esp 00293 return 1; 00294 } 00295 00296 int ESP8266::readable() { 00297 char count_buf[16]; 00298 int count_len = 15; 00299 00300 if (!(command("ca()") && execute(count_buf, &count_len))) 00301 return false; 00302 00303 count_buf[count_len] = 0; 00304 return atoi(count_buf); 00305 } 00306 00307 const char *ESP8266::getIPAddress() { 00308 if (strcmp(_ip, "nil") != 0) 00309 return _ip; 00310 else 00311 return 0; 00312 } 00313 00314 bool ESP8266::getHostByName(const char *host, char *ip) { 00315 if (!(command("dh='") && 00316 command(host) && 00317 command("';") && 00318 command("dn=nil;") && 00319 command("if dh:match('%d+.%d+.%d+.%d+') then ") && 00320 command("dn=dh ") && 00321 command("else ") && 00322 command("dc=net.createConnection(net.TCP);") && 00323 command("dc:dns(dh,function(dc,ip) dn=ip end);") && 00324 command("dc=nil ") && 00325 command("end") && 00326 execute())) 00327 return false; 00328 00329 // Wait for a response 00330 Timer timer; 00331 timer.start(); 00332 00333 while (true) { 00334 int ip_len = 15; 00335 00336 if (!(command("print(dn)") && execute(ip, &ip_len))) 00337 return false; 00338 00339 ip[ip_len] = 0; 00340 00341 if (strcmp(ip, "nil") != 0) 00342 return true; 00343 00344 if (timer.read_ms() > _timeout) 00345 return false; 00346 } 00347 } 00348 00349 int ESP8266::serialgetc() { 00350 Timer timer; 00351 timer.start(); 00352 00353 while (true) { 00354 if (_serial.readable()) { 00355 char c = _serial.getc(); 00356 #ifdef ESP8266_ECHO 00357 printf("%c", c); 00358 #endif 00359 return c; 00360 } 00361 00362 if (timer.read_ms() > _timeout) 00363 return -1; 00364 } 00365 } 00366 00367 int ESP8266::serialputc(char c) { 00368 Timer timer; 00369 timer.start(); 00370 00371 while (true) { 00372 if (_serial.writeable()) 00373 return _serial.putc(c); 00374 00375 if (timer.read_ms() > _timeout) 00376 return -1; 00377 } 00378 } 00379 00380 bool ESP8266::discardEcho() { 00381 while (true) { 00382 int c = serialgetc(); 00383 00384 if (c < 0) 00385 return false; 00386 else if (c == '\n') 00387 return true; 00388 } 00389 } 00390 00391 bool ESP8266::flush() { 00392 while (true) { 00393 int c = serialgetc(); 00394 00395 if (c < 0) 00396 return false; 00397 else if (c == '>') 00398 return true; 00399 } 00400 } 00401 00402 bool ESP8266::command(const char *cmd) { 00403 DBG("command sent:\t %s", cmd); 00404 00405 for (int i = 0; cmd[i]; i++) { 00406 if (serialputc(cmd[i]) < 0) 00407 return false; 00408 } 00409 00410 return true; 00411 } 00412 00413 bool ESP8266::execute_full_length(char *resp_buf, int *resp_len) { 00414 // Finish command with a newline 00415 if (!(command("\r\n") && discardEcho())) 00416 return false; 00417 00418 int brace_count = 0; 00419 00420 // Read in response if any 00421 if (resp_buf && resp_len) { 00422 int i; 00423 00424 for (i = 0; i < *resp_len; i++) { 00425 int c = serialgetc(); 00426 00427 if (c < 0) 00428 return false; 00429 00430 if (c == '>') { 00431 *resp_len = i; 00432 break; 00433 } 00434 00435 resp_buf[i] = c; 00436 } 00437 00438 DBG("command response:\t %.*s", *resp_len, resp_buf); 00439 } 00440 00441 flush(); 00442 return true; 00443 } 00444 00445 bool ESP8266::execute(char *resp_buf, int *resp_len) { 00446 // Finish command with a newline 00447 if (!(command("\r\n") && discardEcho())) 00448 return false; 00449 00450 // Read in response if any 00451 if (resp_buf && resp_len) { 00452 int i; 00453 00454 for (i = 0; i < *resp_len; i++) { 00455 int c = serialgetc(); 00456 00457 if (c < 0) 00458 return false; 00459 00460 if (c == '\r') { 00461 *resp_len = i; 00462 break; 00463 } 00464 00465 resp_buf[i] = c; 00466 } 00467 00468 DBG("command response:\t %.*s", *resp_len, resp_buf); 00469 } 00470 00471 return flush(); 00472 }
Generated on Thu Jul 14 2022 16:33:07 by
1.7.2
