now this shit works
Fork of ESP8266NodeMCUInterface by
Embed:
(wiki syntax)
Show/hide line numbers
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