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.
ESP8266Interface.cpp
00001 /* ESP8266 implementation of NetworkInterfaceAPI 00002 * Copyright (c) 2015 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include <cstring> 00018 #include "ESP8266.h" 00019 #include "ESP8266Interface.h" 00020 #include "mbed_debug.h" 00021 #include "nsapi_types.h" 00022 00023 00024 #ifndef MBED_CONF_ESP8266_TX 00025 #ifdef TARGET_FF_ARDUINO 00026 #define MBED_CONF_ESP8266_TX D1 00027 #else 00028 #define MBED_CONF_ESP8266_TX NC 00029 #endif 00030 #endif 00031 00032 #ifndef MBED_CONF_ESP8266_RX 00033 #ifdef TARGET_FF_ARDUINO 00034 #define MBED_CONF_ESP8266_RX D0 00035 #else 00036 #define MBED_CONF_ESP8266_RX NC 00037 #endif 00038 #endif 00039 00040 // Firmware version 00041 #define ESP8266_VERSION 2 00042 00043 ESP8266Interface::ESP8266Interface() 00044 : _esp(MBED_CONF_ESP8266_TX, MBED_CONF_ESP8266_RX, MBED_CONF_ESP8266_DEBUG), 00045 _initialized(false), 00046 _started(false) 00047 { 00048 memset(_ids, 0, sizeof(_ids)); 00049 memset(_cbs, 0, sizeof(_cbs)); 00050 memset(ap_ssid, 0, sizeof(ap_ssid)); 00051 memset(ap_pass, 0, sizeof(ap_pass)); 00052 memset(_local_ports, 0, sizeof(_local_ports)); 00053 ap_sec = NSAPI_SECURITY_UNKNOWN ; 00054 00055 _esp.sigio(this, &ESP8266Interface::event); 00056 _esp.setTimeout(); 00057 } 00058 00059 // ESP8266Interface implementation 00060 ESP8266Interface::ESP8266Interface(PinName tx, PinName rx, bool debug) 00061 : _esp(tx, rx, debug), 00062 _initialized(false), 00063 _started(false) 00064 { 00065 memset(_ids, 0, sizeof(_ids)); 00066 memset(_cbs, 0, sizeof(_cbs)); 00067 memset(ap_ssid, 0, sizeof(ap_ssid)); 00068 memset(ap_pass, 0, sizeof(ap_pass)); 00069 memset(_local_ports, 0, sizeof(_local_ports)); 00070 ap_sec = NSAPI_SECURITY_UNKNOWN ; 00071 00072 _esp.sigio(this, &ESP8266Interface::event); 00073 _esp.setTimeout(); 00074 } 00075 00076 int ESP8266Interface::connect(const char *ssid, const char *pass, nsapi_security_t security, 00077 uint8_t channel) 00078 { 00079 if (channel != 0) { 00080 return NSAPI_ERROR_UNSUPPORTED ; 00081 } 00082 00083 int err = set_credentials(ssid, pass, security); 00084 if(err) { 00085 return err; 00086 } 00087 00088 return connect(); 00089 } 00090 00091 int ESP8266Interface::connect() 00092 { 00093 nsapi_error_t status; 00094 00095 if (strlen(ap_ssid) == 0) { 00096 return NSAPI_ERROR_NO_SSID ; 00097 } 00098 00099 if (ap_sec != NSAPI_SECURITY_NONE ) { 00100 if (strlen(ap_pass) < ESP8266_PASSPHRASE_MIN_LENGTH) { 00101 return NSAPI_ERROR_PARAMETER ; 00102 } 00103 } 00104 00105 status = _init(); 00106 if(status != NSAPI_ERROR_OK ) { 00107 return status; 00108 } 00109 00110 if(get_ip_address()) { 00111 return NSAPI_ERROR_IS_CONNECTED ; 00112 } 00113 00114 status = _startup(ESP8266::WIFIMODE_STATION); 00115 if(status != NSAPI_ERROR_OK ) { 00116 return status; 00117 } 00118 _started = true; 00119 00120 if (!_esp.dhcp(true, 1)) { 00121 return NSAPI_ERROR_DHCP_FAILURE ; 00122 } 00123 00124 int connect_error = _esp.connect(ap_ssid, ap_pass); 00125 if (connect_error) { 00126 return connect_error; 00127 } 00128 00129 if (!get_ip_address()) { 00130 return NSAPI_ERROR_DHCP_FAILURE ; 00131 } 00132 00133 return NSAPI_ERROR_OK ; 00134 } 00135 00136 int ESP8266Interface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security) 00137 { 00138 ap_sec = security; 00139 00140 if (!ssid) { 00141 return NSAPI_ERROR_PARAMETER ; 00142 } 00143 00144 int ssid_length = strlen(ssid); 00145 00146 if (ssid_length > 0 00147 && ssid_length <= ESP8266_SSID_MAX_LENGTH) { 00148 memset(ap_ssid, 0, sizeof(ap_ssid)); 00149 strncpy(ap_ssid, ssid, sizeof(ap_ssid)); 00150 } else { 00151 return NSAPI_ERROR_PARAMETER ; 00152 } 00153 00154 if (ap_sec != NSAPI_SECURITY_NONE ) { 00155 00156 if (!pass) { 00157 return NSAPI_ERROR_PARAMETER ; 00158 } 00159 00160 int pass_length = strlen(pass); 00161 if (pass_length >= ESP8266_PASSPHRASE_MIN_LENGTH 00162 && pass_length <= ESP8266_PASSPHRASE_MAX_LENGTH ) { 00163 memset(ap_pass, 0, sizeof(ap_pass)); 00164 strncpy(ap_pass, pass, sizeof(ap_pass)); 00165 } else { 00166 return NSAPI_ERROR_PARAMETER ; 00167 } 00168 } else { 00169 memset(ap_pass, 0, sizeof(ap_pass)); 00170 } 00171 00172 return NSAPI_ERROR_OK ; 00173 } 00174 00175 int ESP8266Interface::set_channel(uint8_t channel) 00176 { 00177 return NSAPI_ERROR_UNSUPPORTED ; 00178 } 00179 00180 00181 int ESP8266Interface::disconnect() 00182 { 00183 _started = false; 00184 _initialized = false; 00185 00186 return _esp.disconnect() ? NSAPI_ERROR_OK : NSAPI_ERROR_DEVICE_ERROR ; 00187 } 00188 00189 const char *ESP8266Interface::get_ip_address() 00190 { 00191 if(!_started) { 00192 return NULL; 00193 } 00194 00195 const char *ip_buff = _esp.getIPAddress(); 00196 if(!ip_buff || std::strcmp(ip_buff, "0.0.0.0") == 0) { 00197 return NULL; 00198 } 00199 00200 return ip_buff; 00201 } 00202 00203 const char *ESP8266Interface::get_mac_address() 00204 { 00205 return _esp.getMACAddress(); 00206 } 00207 00208 const char *ESP8266Interface::get_gateway() 00209 { 00210 return _started ? _esp.getGateway() : NULL; 00211 } 00212 00213 const char *ESP8266Interface::get_netmask() 00214 { 00215 return _started ? _esp.getNetmask() : NULL; 00216 } 00217 00218 int8_t ESP8266Interface::get_rssi() 00219 { 00220 return _started ? _esp.getRSSI() : 0; 00221 } 00222 00223 int ESP8266Interface::scan(WiFiAccessPoint *res, unsigned count) 00224 { 00225 nsapi_error_t status; 00226 00227 status = _init(); 00228 if(status != NSAPI_ERROR_OK ) { 00229 return status; 00230 } 00231 00232 status = _startup(ESP8266::WIFIMODE_STATION); 00233 if(status != NSAPI_ERROR_OK ) { 00234 return status; 00235 } 00236 00237 return _esp.scan(res, count); 00238 } 00239 00240 bool ESP8266Interface::_get_firmware_ok() 00241 { 00242 if (_esp.get_firmware_version() != ESP8266_VERSION) { 00243 debug("ESP8266: ERROR: Firmware incompatible with this driver.\ 00244 \r\nUpdate to v%d - https://developer.mbed.org/teams/ESP8266/wiki/Firmware-Update\r\n",ESP8266_VERSION); 00245 return false; 00246 } 00247 00248 return true; 00249 } 00250 00251 bool ESP8266Interface::_disable_default_softap() 00252 { 00253 static int disabled = false; 00254 00255 if (disabled || _esp.get_default_wifi_mode() == ESP8266::WIFIMODE_STATION) { 00256 disabled = true; 00257 return true; 00258 } 00259 if (_esp.set_default_wifi_mode(ESP8266::WIFIMODE_STATION)) { 00260 disabled = true; 00261 return true; 00262 } 00263 00264 return false; 00265 } 00266 00267 nsapi_error_t ESP8266Interface::_init(void) 00268 { 00269 if (!_initialized) { 00270 if (!_esp.reset()) { 00271 return NSAPI_ERROR_DEVICE_ERROR ; 00272 } 00273 if (!_get_firmware_ok()) { 00274 return NSAPI_ERROR_DEVICE_ERROR ; 00275 } 00276 if (_disable_default_softap() == false) { 00277 return NSAPI_ERROR_DEVICE_ERROR ; 00278 } 00279 _initialized = true; 00280 } 00281 return NSAPI_ERROR_OK ; 00282 } 00283 00284 nsapi_error_t ESP8266Interface::_startup(const int8_t wifi_mode) 00285 { 00286 if (!_started) { 00287 if (!_esp.startup(wifi_mode)) { 00288 return NSAPI_ERROR_DEVICE_ERROR ; 00289 } 00290 } 00291 return NSAPI_ERROR_OK ; 00292 } 00293 00294 struct esp8266_socket { 00295 int id; 00296 nsapi_protocol_t proto; 00297 bool connected; 00298 SocketAddress addr; 00299 int keepalive; // TCP 00300 }; 00301 00302 int ESP8266Interface::socket_open(void **handle, nsapi_protocol_t proto) 00303 { 00304 // Look for an unused socket 00305 int id = -1; 00306 00307 for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) { 00308 if (!_ids[i]) { 00309 id = i; 00310 _ids[i] = true; 00311 break; 00312 } 00313 } 00314 00315 if (id == -1) { 00316 return NSAPI_ERROR_NO_SOCKET ; 00317 } 00318 00319 struct esp8266_socket *socket = new struct esp8266_socket; 00320 if (!socket) { 00321 return NSAPI_ERROR_NO_SOCKET ; 00322 } 00323 00324 socket->id = id; 00325 socket->proto = proto; 00326 socket->connected = false; 00327 socket->keepalive = 0; 00328 *handle = socket; 00329 return 0; 00330 } 00331 00332 int ESP8266Interface::socket_close(void *handle) 00333 { 00334 struct esp8266_socket *socket = (struct esp8266_socket *)handle; 00335 int err = 0; 00336 00337 if (!socket) { 00338 return NSAPI_ERROR_NO_SOCKET ; 00339 } 00340 00341 if (socket->connected && !_esp.close(socket->id)) { 00342 err = NSAPI_ERROR_DEVICE_ERROR ; 00343 } 00344 00345 socket->connected = false; 00346 _ids[socket->id] = false; 00347 _local_ports[socket->id] = 0; 00348 delete socket; 00349 return err; 00350 } 00351 00352 int ESP8266Interface::socket_bind(void *handle, const SocketAddress &address) 00353 { 00354 struct esp8266_socket *socket = (struct esp8266_socket *)handle; 00355 00356 if (!socket) { 00357 return NSAPI_ERROR_NO_SOCKET ; 00358 } 00359 00360 if (socket->proto == NSAPI_UDP ) { 00361 if(address.get_addr().version != NSAPI_UNSPEC ) { 00362 return NSAPI_ERROR_UNSUPPORTED ; 00363 } 00364 00365 for(int id = 0; id < ESP8266_SOCKET_COUNT; id++) { 00366 if(_local_ports[id] == address.get_port() && id != socket->id) { // Port already reserved by another socket 00367 return NSAPI_ERROR_PARAMETER ; 00368 } else if (id == socket->id && socket->connected) { 00369 return NSAPI_ERROR_PARAMETER ; 00370 } 00371 } 00372 _local_ports[socket->id] = address.get_port(); 00373 return 0; 00374 } 00375 00376 return NSAPI_ERROR_UNSUPPORTED ; 00377 } 00378 00379 int ESP8266Interface::socket_listen(void *handle, int backlog) 00380 { 00381 return NSAPI_ERROR_UNSUPPORTED ; 00382 } 00383 00384 int ESP8266Interface::socket_connect(void *handle, const SocketAddress &addr) 00385 { 00386 struct esp8266_socket *socket = (struct esp8266_socket *)handle; 00387 nsapi_error_t ret; 00388 00389 if (!socket) { 00390 return NSAPI_ERROR_NO_SOCKET ; 00391 } 00392 00393 if (socket->proto == NSAPI_UDP ) { 00394 ret = _esp.open_udp(socket->id, addr.get_ip_address(), addr.get_port(), _local_ports[socket->id]); 00395 if (ret != NSAPI_ERROR_OK ) { 00396 return ret; 00397 } 00398 } else { 00399 if (!_esp.open_tcp(socket->id, addr.get_ip_address(), addr.get_port(), socket->keepalive)) { 00400 return NSAPI_ERROR_DEVICE_ERROR ; 00401 } 00402 } 00403 00404 socket->connected = true; 00405 return 0; 00406 } 00407 00408 int ESP8266Interface::socket_accept(void *server, void **socket, SocketAddress *addr) 00409 { 00410 return NSAPI_ERROR_UNSUPPORTED ; 00411 } 00412 00413 int ESP8266Interface::socket_send(void *handle, const void *data, unsigned size) 00414 { 00415 nsapi_error_t status; 00416 struct esp8266_socket *socket = (struct esp8266_socket *)handle; 00417 00418 if (!socket) { 00419 return NSAPI_ERROR_NO_SOCKET ; 00420 } 00421 00422 status = _esp.send(socket->id, data, size); 00423 00424 return status != NSAPI_ERROR_OK ? status : size; 00425 } 00426 00427 int ESP8266Interface::socket_recv(void *handle, void *data, unsigned size) 00428 { 00429 struct esp8266_socket *socket = (struct esp8266_socket *)handle; 00430 00431 if (!socket) { 00432 return NSAPI_ERROR_NO_SOCKET ; 00433 } 00434 00435 int32_t recv; 00436 if (socket->proto == NSAPI_TCP ) { 00437 recv = _esp.recv_tcp(socket->id, data, size); 00438 if (recv <= 0 && recv != NSAPI_ERROR_WOULD_BLOCK ) { 00439 socket->connected = false; 00440 } 00441 } else { 00442 recv = _esp.recv_udp(socket->id, data, size); 00443 } 00444 00445 return recv; 00446 } 00447 00448 int ESP8266Interface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size) 00449 { 00450 struct esp8266_socket *socket = (struct esp8266_socket *)handle; 00451 00452 if (!socket) { 00453 return NSAPI_ERROR_NO_SOCKET ; 00454 } 00455 00456 if((strcmp(addr.get_ip_address(), "0.0.0.0") == 0) || !addr.get_port()) { 00457 return NSAPI_ERROR_DNS_FAILURE ; 00458 } 00459 00460 if (socket->connected && socket->addr != addr) { 00461 if (!_esp.close(socket->id)) { 00462 return NSAPI_ERROR_DEVICE_ERROR ; 00463 } 00464 socket->connected = false; 00465 } 00466 00467 if (!socket->connected) { 00468 int err = socket_connect(socket, addr); 00469 if (err < 0) { 00470 return err; 00471 } 00472 socket->addr = addr; 00473 } 00474 00475 return socket_send(socket, data, size); 00476 } 00477 00478 int ESP8266Interface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size) 00479 { 00480 struct esp8266_socket *socket = (struct esp8266_socket *)handle; 00481 00482 if (!socket) { 00483 return NSAPI_ERROR_NO_SOCKET ; 00484 } 00485 00486 int ret = socket_recv(socket, data, size); 00487 if (ret >= 0 && addr) { 00488 *addr = socket->addr; 00489 } 00490 00491 return ret; 00492 } 00493 00494 void ESP8266Interface::socket_attach(void *handle, void (*callback)(void *), void *data) 00495 { 00496 struct esp8266_socket *socket = (struct esp8266_socket *)handle; 00497 _cbs[socket->id].callback = callback; 00498 _cbs[socket->id].data = data; 00499 } 00500 00501 nsapi_error_t ESP8266Interface::setsockopt(nsapi_socket_t handle, int level, 00502 int optname, const void *optval, unsigned optlen) 00503 { 00504 struct esp8266_socket *socket = (struct esp8266_socket *)handle; 00505 00506 if (!optlen) { 00507 return NSAPI_ERROR_PARAMETER ; 00508 } else if (!socket) { 00509 return NSAPI_ERROR_NO_SOCKET ; 00510 } 00511 00512 if (level == NSAPI_SOCKET && socket->proto == NSAPI_TCP ) { 00513 switch (optname) { 00514 case NSAPI_KEEPALIVE : { 00515 if(socket->connected) {// ESP8266 limitation, keepalive needs to be given before connecting 00516 return NSAPI_ERROR_UNSUPPORTED ; 00517 } 00518 00519 if (optlen == sizeof(int)) { 00520 int secs = *(int *)optval; 00521 if (secs >= 0 && secs <= 7200) { 00522 socket->keepalive = secs; 00523 return NSAPI_ERROR_OK ; 00524 } 00525 } 00526 return NSAPI_ERROR_PARAMETER ; 00527 } 00528 } 00529 } 00530 00531 return NSAPI_ERROR_UNSUPPORTED ; 00532 } 00533 00534 nsapi_error_t ESP8266Interface::getsockopt(nsapi_socket_t handle, int level, int optname, void *optval, unsigned *optlen) 00535 { 00536 struct esp8266_socket *socket = (struct esp8266_socket *)handle; 00537 00538 if (!optval || !optlen) { 00539 return NSAPI_ERROR_PARAMETER ; 00540 } else if (!socket) { 00541 return NSAPI_ERROR_NO_SOCKET ; 00542 } 00543 00544 if (level == NSAPI_SOCKET && socket->proto == NSAPI_TCP ) { 00545 switch (optname) { 00546 case NSAPI_KEEPALIVE : { 00547 if(*optlen > sizeof(int)) { 00548 *optlen = sizeof(int); 00549 } 00550 memcpy(optval, &(socket->keepalive), *optlen); 00551 return NSAPI_ERROR_OK ; 00552 } 00553 } 00554 } 00555 00556 return NSAPI_ERROR_UNSUPPORTED ; 00557 } 00558 00559 00560 void ESP8266Interface::event() 00561 { 00562 for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) { 00563 if (_cbs[i].callback) { 00564 _cbs[i].callback(_cbs[i].data); 00565 } 00566 } 00567 } 00568 00569 void ESP8266Interface::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb) 00570 { 00571 _esp.attach(status_cb); 00572 } 00573 00574 nsapi_connection_status_t ESP8266Interface::get_connection_status() const 00575 { 00576 return _esp.get_connection_status(); 00577 } 00578 00579 #if MBED_CONF_ESP8266_PROVIDE_DEFAULT 00580 00581 WiFiInterface *WiFiInterface::get_default_instance() { 00582 static ESP8266Interface esp; 00583 return &esp; 00584 } 00585 00586 #endif
Generated on Tue Aug 9 2022 00:37:06 by
1.7.2