Advantech / Mbed OS pelion-example-common
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ESP32.cpp Source File

ESP32.cpp

00001 /* ESP32 Example
00002  * Copyright (c) 2015 ARM Limited
00003  * Copyright (c) 2017 Renesas Electronics Corporation
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #if DEVICE_SERIAL && defined(MBED_CONF_EVENTS_PRESENT) && defined(MBED_CONF_NSAPI_PRESENT) && defined(MBED_CONF_RTOS_PRESENT)
00019 #include "ESP32.h"
00020 
00021 #define ESP32_DEFAULT_BAUD_RATE   115200
00022 #define ESP32_ALL_SOCKET_IDS      -1
00023 
00024 using namespace mbed;
00025 using namespace rtos;
00026 
00027 ESP32 * ESP32::instESP32 = NULL;
00028 
00029 ESP32 * ESP32::getESP32Inst(PinName en, PinName io0, PinName tx, PinName rx, bool debug,
00030                             PinName rts, PinName cts, int baudrate)
00031 {
00032     if (instESP32 == NULL) {
00033         instESP32 = new ESP32(en, io0, tx, rx, debug, rts, cts, baudrate);
00034     } else {
00035         if (debug) {
00036             instESP32->debugOn(debug);
00037         }
00038     }
00039     return instESP32;
00040 }
00041 
00042 ESP32::ESP32(PinName en, PinName io0, PinName tx, PinName rx, bool debug,
00043     PinName rts, PinName cts, int baudrate)
00044     : _p_wifi_en(NULL), _p_wifi_io0(NULL), init_end(false)
00045     , _serial(tx, rx, ESP32_DEFAULT_BAUD_RATE), _parser(&_serial, "\r\n")
00046     , _packets(0), _packets_end(&_packets)
00047     , _id_bits(0), _id_bits_close(0), _server_act(false)
00048     , _wifi_status(STATUS_DISCONNECTED)
00049     , _wifi_status_cb(NULL)
00050 {
00051     if ((int)en != NC) {
00052         _p_wifi_en = new DigitalOut(en);
00053     }
00054     if ((int)io0 != NC) {
00055         _p_wifi_io0 = new DigitalOut(io0);
00056     }
00057 
00058     _wifi_mode = WIFIMODE_STATION;
00059     _baudrate = baudrate;
00060     memset(_ids, 0, sizeof(_ids));
00061     memset(_cbs, 0, sizeof(_cbs));
00062 
00063     _rts = rts;
00064     _cts = cts;
00065 
00066     if ((_rts != NC) && (_cts != NC)) {
00067         _flow_control = 3;
00068     } else if (_rts != NC) {
00069         _flow_control = 1;
00070     } else if (_cts != NC) {
00071         _flow_control = 2;
00072     } else {
00073         _flow_control = 0;
00074     }
00075 
00076     _serial.set_baud(ESP32_DEFAULT_BAUD_RATE);
00077     debugOn(debug);
00078 
00079     _parser.oob("+IPD", callback(this, &ESP32::_packet_handler));
00080     _parser.oob("0,CONNECT", callback(this, &ESP32::_connect_handler_0));
00081     _parser.oob("1,CONNECT", callback(this, &ESP32::_connect_handler_1));
00082     _parser.oob("2,CONNECT", callback(this, &ESP32::_connect_handler_2));
00083     _parser.oob("3,CONNECT", callback(this, &ESP32::_connect_handler_3));
00084     _parser.oob("4,CONNECT", callback(this, &ESP32::_connect_handler_4));
00085     _parser.oob("0,CLOSED", callback(this, &ESP32::_closed_handler_0));
00086     _parser.oob("1,CLOSED", callback(this, &ESP32::_closed_handler_1));
00087     _parser.oob("2,CLOSED", callback(this, &ESP32::_closed_handler_2));
00088     _parser.oob("3,CLOSED", callback(this, &ESP32::_closed_handler_3));
00089     _parser.oob("4,CLOSED", callback(this, &ESP32::_closed_handler_4));
00090     _parser.oob("WIFI ", callback(this, &ESP32::_connection_status_handler));
00091 
00092     _serial.sigio(Callback<void()>(this, &ESP32::event));
00093 
00094     setTimeout();
00095 }
00096 
00097 void ESP32::debugOn(bool debug)
00098 {
00099     _parser.debug_on((debug) ? 1 : 0);
00100 }
00101 
00102 int ESP32::get_firmware_version()
00103 {
00104     int version;
00105 
00106     _smutex.lock();
00107     startup();
00108     bool done = _parser.send("AT+GMR")
00109            && _parser.recv("SDK version:%d", &version)
00110            && _parser.recv("OK");
00111     _smutex.unlock();
00112 
00113     if(done) {
00114         return version;
00115     } else { 
00116         // Older firmware versions do not prefix the version with "SDK version: "
00117         return -1;
00118     }
00119 }
00120 
00121 bool ESP32::startup()
00122 {
00123     if (init_end) {
00124         return true;
00125     }
00126 
00127     if (_p_wifi_io0 != NULL) {
00128         _p_wifi_io0->write(1);
00129     }
00130     if (_p_wifi_en != NULL) {
00131         _p_wifi_en->write(0);
00132         ThisThread::sleep_for(10);
00133         _p_wifi_en->write(1);
00134         _parser.recv("ready");
00135     } else {
00136         setTimeout(100);
00137         _parser.recv("ready");
00138     }
00139 
00140     reset();
00141     bool success = _parser.send("AT+CWMODE=%d", _wifi_mode)
00142                 && _parser.recv("OK")
00143                 && _parser.send("AT+CIPMUX=1")
00144                 && _parser.recv("OK")
00145                 && _parser.send("AT+CWAUTOCONN=0")
00146                 && _parser.recv("OK")
00147                 && _parser.send("AT+CWQAP")
00148                 && _parser.recv("OK");
00149     if (success) {
00150         init_end = true;
00151     }
00152 
00153     return success;
00154 }
00155 
00156 bool ESP32::restart()
00157 {
00158     bool success;
00159 
00160     _smutex.lock();
00161     if (!init_end) {
00162         success = startup();
00163     } else {
00164         reset();
00165         success = _parser.send("AT+CWMODE=%d", _wifi_mode)
00166                && _parser.recv("OK")
00167                && _parser.send("AT+CIPMUX=1")
00168                && _parser.recv("OK");
00169     }
00170     _smutex.unlock();
00171 
00172     return success;
00173 }
00174 
00175 bool ESP32::set_mode(int mode)
00176 {
00177     //only 3 valid modes
00178     if (mode < 1 || mode > 3) {
00179         return false;
00180     }
00181     if (_wifi_mode != mode) {
00182         _wifi_mode = mode;
00183         return restart();
00184     }
00185     return true;
00186 }
00187 
00188 bool ESP32::cre_server(int port)
00189 {
00190     if (_server_act) {
00191         return false;
00192     }
00193     _smutex.lock();
00194     startup();
00195     if (!(_parser.send("AT+CIPSERVER=1,%d", port)
00196         && _parser.recv("OK"))) {
00197         _smutex.unlock();
00198         return false;
00199     }
00200     _server_act = true;
00201     _smutex.unlock();
00202     return true;
00203 }
00204 
00205 bool ESP32::del_server()
00206 {
00207     _smutex.lock();
00208     startup();
00209     if (!(_parser.send("AT+CIPSERVER=0")
00210         && _parser.recv("OK"))) {
00211         _smutex.unlock();
00212         return false;
00213     }
00214     _server_act = false;
00215     _smutex.unlock();
00216     return true;
00217 }
00218 
00219 void ESP32::socket_handler(bool connect, int id)
00220 {
00221     _cbs[id].Notified = 0;
00222     if (connect) {
00223         _id_bits |= (1 << id);
00224         if (_server_act) {
00225             _accept_id.push_back(id);
00226         }
00227     } else {
00228         _id_bits &= ~(1 << id);
00229         _id_bits_close |= (1 << id);
00230         if (_server_act) {
00231             for (size_t i = 0; i < _accept_id.size(); i++) {
00232                 if (id == _accept_id[i]) {
00233                     _accept_id.erase(_accept_id.begin() + i);
00234                 }
00235             }
00236         }
00237     }
00238 }
00239 
00240 bool ESP32::accept(int * p_id)
00241 {
00242     bool ret = false;
00243 
00244     while (!ret) {
00245         if (!_server_act) {
00246             break;
00247         }
00248 
00249         _smutex.lock();
00250         startup();
00251         if (!_accept_id.empty()) {
00252             ret = true;
00253         } else {
00254             _parser.process_oob(); // Poll for inbound packets
00255             if (!_accept_id.empty()) {
00256                 ret = true;
00257             }
00258         }
00259         if (ret) {
00260             *p_id = _accept_id[0];
00261             _accept_id.erase(_accept_id.begin());
00262         }
00263         _smutex.unlock();
00264         if (!ret) {
00265             ThisThread::sleep_for(5);
00266         }
00267     }
00268 
00269     if (ret) {
00270         for (int i = 0; i < 50; i++) {
00271             if ((_id_bits_close & (1 << *p_id)) == 0) {
00272                 break;
00273             }
00274             ThisThread::sleep_for(10);
00275         }
00276     }
00277 
00278     return ret;
00279 }
00280 
00281 bool ESP32::reset(void)
00282 {
00283     for (int i = 0; i < 2; i++) {
00284         if (_parser.send("AT+RST")
00285             && _parser.recv("OK")) {
00286             _serial.set_baud(ESP32_DEFAULT_BAUD_RATE);
00287 #if DEVICE_SERIAL_FC
00288             _serial.set_flow_control(SerialBase::Disabled);
00289 #endif
00290             _parser.recv("ready");
00291             _clear_socket_packets(ESP32_ALL_SOCKET_IDS);
00292 
00293             if (_parser.send("AT+UART_CUR=%d,8,1,0,%d", _baudrate, _flow_control)
00294                 && _parser.recv("OK")) {
00295                 _serial.set_baud(_baudrate);
00296 #if DEVICE_SERIAL_FC
00297                 switch (_flow_control) {
00298                     case 1:
00299                         _serial.set_flow_control(SerialBase::RTS, _rts);
00300                         break;
00301                     case 2:
00302                         _serial.set_flow_control(SerialBase::CTS, _cts);
00303                         break;
00304                     case 3:
00305                         _serial.set_flow_control(SerialBase::RTSCTS, _rts, _cts);
00306                         break;
00307                     case 0:
00308                     default:
00309                         // do nothing
00310                         break;
00311                 }
00312 #endif
00313             }
00314 
00315             return true;
00316         }
00317     }
00318 
00319     return false;
00320 }
00321 
00322 bool ESP32::dhcp(bool enabled, int mode)
00323 {
00324     //only 3 valid modes
00325     if (mode < 0 || mode > 2) {
00326         return false;
00327     }
00328 
00329     _smutex.lock();
00330     startup();
00331     bool done = _parser.send("AT+CWDHCP=%d,%d", enabled?1:0, mode)
00332        && _parser.recv("OK");
00333     _smutex.unlock();
00334 
00335     return done;
00336 }
00337 
00338 bool ESP32::connect(const char *ap, const char *passPhrase)
00339 {
00340     bool ret;
00341 
00342     _wifi_status = STATUS_DISCONNECTED;
00343 
00344     _smutex.lock();
00345     startup();
00346 
00347     setTimeout(ESP32_CONNECT_TIMEOUT);
00348     ret = _parser.send("AT+CWJAP=\"%s\",\"%s\"", ap, passPhrase)
00349        && _parser.recv("OK");
00350     setTimeout();
00351     _smutex.unlock();
00352     return ret;
00353 }
00354 
00355 bool ESP32::config_soft_ap(const char *ap, const char *passPhrase, uint8_t chl, uint8_t ecn)
00356 {
00357     bool ret;
00358 
00359     _smutex.lock();
00360     startup();
00361     ret = _parser.send("AT+CWSAP=\"%s\",\"%s\",%hhu,%hhu", ap, passPhrase, chl, ecn)
00362        && _parser.recv("OK");
00363     _smutex.unlock();
00364     return ret;
00365 }
00366 
00367 bool ESP32::get_ssid(char *ap)
00368 {
00369     bool ret;
00370 
00371     _smutex.lock();
00372     startup();
00373     ret = _parser.send("AT+CWJAP?")
00374        && _parser.recv("+CWJAP:\"%33[^\"]\",", ap)
00375        && _parser.recv("OK");
00376     _smutex.unlock();
00377     return ret;
00378 }
00379 
00380 bool ESP32::disconnect(void)
00381 {
00382     bool ret;
00383 
00384     _smutex.lock();
00385     startup();
00386     ret = _parser.send("AT+CWQAP") && _parser.recv("OK");
00387     _smutex.unlock();
00388     return ret;
00389 }
00390 
00391 const char *ESP32::getIPAddress(void)
00392 {
00393     bool ret;
00394 
00395     _smutex.lock();
00396     startup();
00397     ret = _parser.send("AT+CIFSR")
00398        && _parser.recv("+CIFSR:STAIP,\"%15[^\"]\"", _ip_buffer)
00399        && _parser.recv("OK");
00400     _smutex.unlock();
00401     if (!ret) {
00402         return 0;
00403     }
00404     return _ip_buffer;
00405 }
00406 
00407 const char *ESP32::getIPAddress_ap(void)
00408 {
00409     bool ret;
00410 
00411     _smutex.lock();
00412     startup();
00413     ret = _parser.send("AT+CIFSR")
00414        && _parser.recv("+CIFSR:APIP,\"%15[^\"]\"", _ip_buffer_ap)
00415        && _parser.recv("OK");
00416     _smutex.unlock();
00417     if (!ret) {
00418         return 0;
00419     }
00420     return _ip_buffer_ap;
00421 }
00422 
00423 const char *ESP32::getMACAddress(void)
00424 {
00425     bool ret;
00426 
00427     _smutex.lock();
00428     startup();
00429     ret = _parser.send("AT+CIFSR")
00430        && _parser.recv("+CIFSR:STAMAC,\"%17[^\"]\"", _mac_buffer)
00431        && _parser.recv("OK");
00432     _smutex.unlock();
00433 
00434     if (!ret) {
00435         return 0;
00436     }
00437     return _mac_buffer;
00438 }
00439 
00440 const char *ESP32::getMACAddress_ap(void)
00441 {
00442     bool ret;
00443 
00444     _smutex.lock();
00445     startup();
00446     ret = _parser.send("AT+CIFSR")
00447        && _parser.recv("+CIFSR:APMAC,\"%17[^\"]\"", _mac_buffer_ap)
00448        && _parser.recv("OK");
00449     _smutex.unlock();
00450 
00451     if (!ret) {
00452         return 0;
00453     }
00454     return _mac_buffer_ap;
00455 }
00456 
00457 const char *ESP32::getGateway()
00458 {
00459     bool ret;
00460 
00461     _smutex.lock();
00462     startup();
00463     ret = _parser.send("AT+CIPSTA?")
00464        && _parser.recv("+CIPSTA:gateway:\"%15[^\"]\"", _gateway_buffer)
00465        && _parser.recv("OK");
00466     _smutex.unlock();
00467 
00468     if (!ret) {
00469         return 0;
00470     }
00471     return _gateway_buffer;
00472 }
00473 
00474 const char *ESP32::getGateway_ap()
00475 {
00476     bool ret;
00477 
00478     _smutex.lock();
00479     startup();
00480     ret = _parser.send("AT+CIPAP?")
00481        && _parser.recv("+CIPAP:gateway:\"%15[^\"]\"", _gateway_buffer_ap)
00482        && _parser.recv("OK");
00483     _smutex.unlock();
00484 
00485     if (!ret) {
00486         return 0;
00487     }
00488     return _gateway_buffer_ap;
00489 }
00490 
00491 const char *ESP32::getNetmask()
00492 {
00493     bool ret;
00494 
00495     _smutex.lock();
00496     startup();
00497     ret = _parser.send("AT+CIPSTA?")
00498        && _parser.recv("+CIPSTA:netmask:\"%15[^\"]\"", _netmask_buffer)
00499        && _parser.recv("OK");
00500     _smutex.unlock();
00501 
00502     if (!ret) {
00503         return 0;
00504     }
00505     return _netmask_buffer;
00506 }
00507 
00508 const char *ESP32::getNetmask_ap()
00509 {
00510     bool ret;
00511 
00512     _smutex.lock();
00513     startup();
00514     ret = _parser.send("AT+CIPAP?")
00515        && _parser.recv("+CIPAP:netmask:\"%15[^\"]\"", _netmask_buffer_ap)
00516        && _parser.recv("OK");
00517     _smutex.unlock();
00518 
00519     if (!ret) {
00520         return 0;
00521     }
00522     return _netmask_buffer_ap;
00523 }
00524 
00525 int8_t ESP32::getRSSI()
00526 {
00527     bool ret;
00528     int8_t rssi;
00529     char ssid[33];
00530     char bssid[18];
00531 
00532     _smutex.lock();
00533     startup();
00534     ret = _parser.send("AT+CWJAP?")
00535        && _parser.recv("+CWJAP:\"%32[^\"]\",\"%17[^\"]\"", ssid, bssid)
00536        && _parser.recv("OK");
00537     if (!ret) {
00538         _smutex.unlock();
00539         return 0;
00540     }
00541 
00542     ret = _parser.send("AT+CWLAP=\"%s\",\"%s\"", ssid, bssid)
00543        && _parser.recv("+CWLAP:(%*d,\"%*[^\"]\",%hhd,", &rssi)
00544        && _parser.recv("OK");
00545     _smutex.unlock();
00546 
00547     if (!ret) {
00548         return 0;
00549     }
00550 
00551     return rssi;
00552 }
00553 
00554 int ESP32::scan(WiFiAccessPoint *res, unsigned limit)
00555 {
00556     unsigned cnt = 0;
00557     nsapi_wifi_ap_t ap;
00558 
00559     if (!init_end) {
00560         _smutex.lock();
00561         startup();
00562         _smutex.unlock();
00563         ThisThread::sleep_for(1500);
00564     }
00565 
00566     _smutex.lock();
00567     setTimeout(5000);
00568     if (!_parser.send("AT+CWLAP")) {
00569         _smutex.unlock();
00570         return NSAPI_ERROR_DEVICE_ERROR;
00571     }
00572 
00573     while (recv_ap(&ap)) {
00574         if (cnt < limit) {
00575             res[cnt] = WiFiAccessPoint(ap);
00576         }
00577 
00578         cnt++;
00579         if ((limit != 0) && (cnt >= limit)) {
00580             break;
00581         }
00582         setTimeout(500);
00583     }
00584     setTimeout(10);
00585     _parser.recv("OK");
00586     setTimeout();
00587     _smutex.unlock();
00588 
00589     return cnt;
00590 }
00591 
00592 bool ESP32::isConnected(void)
00593 {
00594     return getIPAddress() != 0;
00595 }
00596 
00597 bool ESP32::open(const char *type, int id, const char* addr, int port, int opt)
00598 {
00599     bool ret;
00600 
00601     if (id >= SOCKET_COUNT) {
00602         return false;
00603     }
00604     _cbs[id].Notified = 0;
00605 
00606     _smutex.lock();
00607     startup();
00608     setTimeout(500);
00609     if (opt != 0) {
00610         ret = _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d, %d", id, type, addr, port, opt)
00611            && _parser.recv("OK");
00612     } else {
00613         ret = _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d", id, type, addr, port)
00614            && _parser.recv("OK");
00615     }
00616     setTimeout();
00617     _clear_socket_packets(id);
00618     _smutex.unlock();
00619 
00620     return ret;
00621 }
00622 
00623 bool ESP32::send(int id, const void *data, uint32_t amount)
00624 {
00625     int send_size;
00626     bool ret;
00627     int error_cnt = 0;
00628     int index = 0;
00629 
00630     _cbs[id].Notified = 0;
00631     if (amount == 0) {
00632         return true;
00633     }
00634 
00635     //May take a second try if device is busy
00636     _smutex.lock();
00637     while (error_cnt < 2) {
00638         if (((_id_bits & (1 << id)) == 0)
00639          || ((_id_bits_close & (1 << id)) != 0)) {
00640             _smutex.unlock();
00641             return false;
00642         }
00643         send_size = amount;
00644         if (send_size > 2048) {
00645             send_size = 2048;
00646         }
00647         startup();
00648         setTimeout(ESP32_SEND_TIMEOUT);
00649         ret = _parser.send("AT+CIPSEND=%d,%d", id, send_size)
00650            && _parser.recv(">")
00651            && (_parser.write((char*)data + index, (int)send_size) >= 0)
00652            && _parser.recv("SEND OK");
00653         setTimeout();
00654         if (ret) {
00655             amount -= send_size;
00656             index += send_size;
00657             error_cnt = 0;
00658             if (amount == 0) {
00659                 _smutex.unlock();
00660                 return true;
00661             }
00662         } else {
00663             error_cnt++;
00664         }
00665     }
00666     _smutex.unlock();
00667 
00668     return false;
00669 }
00670 
00671 void ESP32::_packet_handler()
00672 {
00673     int id;
00674     int amount;
00675     uint32_t tmp_timeout;
00676 
00677     // parse out the packet
00678     if (!_parser.recv(",%d,%d:", &id, &amount)) {
00679         return;
00680     }
00681 
00682     struct packet *packet = (struct packet*)malloc(
00683             sizeof(struct packet) + amount);
00684     if (!packet) {
00685         return;
00686     }
00687 
00688     packet->id = id;
00689     packet->len = amount;
00690     packet->next = 0;
00691     packet->index = 0;
00692 
00693     tmp_timeout = last_timeout_ms;
00694     setTimeout(500);
00695     if (!(_parser.read((char*)(packet + 1), amount))) {
00696         free(packet);
00697         setTimeout(tmp_timeout);
00698         return;
00699     }
00700 
00701     // append to packet list
00702     *_packets_end = packet;
00703     _packets_end = &packet->next;
00704 }
00705 
00706 int32_t ESP32::recv(int id, void *data, uint32_t amount, uint32_t timeout)
00707 {
00708     struct packet **p;
00709     uint32_t idx = 0;
00710 
00711     _cbs[id].Notified = 0;
00712 
00713     _smutex.lock();
00714     setTimeout(timeout);
00715     if (_rts == NC) {
00716         while (_parser.process_oob()); // Poll for inbound packets
00717     } else {
00718         _parser.process_oob(); // Poll for inbound packets
00719     }
00720     setTimeout();
00721 
00722     // check if any packets are ready for us
00723     p = &_packets;
00724     while (*p) {
00725         if ((*p)->id == id) {
00726             struct packet *q = *p;
00727 
00728             if (q->len <= amount) { // Return and remove full packet
00729                 memcpy(&(((uint8_t *)data)[idx]), (uint8_t*)(q+1) + q->index, q->len);
00730                 if (_packets_end == &(*p)->next) {
00731                     _packets_end = p;
00732                 }
00733                 *p = (*p)->next;
00734                 idx += q->len;
00735                 amount -= q->len;
00736                 free(q);
00737             } else { // return only partial packet
00738                 memcpy(&(((uint8_t *)data)[idx]), (uint8_t*)(q+1) + q->index, amount);
00739                 q->len -= amount;
00740                 q->index += amount;
00741                 idx += amount;
00742                 break;
00743             }
00744         } else {
00745             p = &(*p)->next;
00746         }
00747     }
00748     _smutex.unlock();
00749 
00750     if (idx > 0) {
00751         return idx;
00752     } else if (((_id_bits & (1 << id)) == 0) || ((_id_bits_close & (1 << id)) != 0)) {
00753         return -2;
00754     } else {
00755         return -1;
00756     }
00757 }
00758 
00759 void ESP32::_clear_socket_packets(int id)
00760 {
00761     struct packet **p = &_packets;
00762 
00763     while (*p) {
00764         if ((*p)->id == id || id == ESP32_ALL_SOCKET_IDS) {
00765             struct packet *q = *p;
00766 
00767             if (_packets_end == &(*p)->next) {
00768                 _packets_end = p; // Set last packet next field/_packets
00769             }
00770             *p = (*p)->next;
00771 
00772             free(q);
00773         } else {
00774             // Point to last packet next field
00775             p = &(*p)->next;
00776         }
00777     }
00778 }
00779 
00780 bool ESP32::close(int id, bool wait_close)
00781 {
00782     if (wait_close) {
00783         _smutex.lock();
00784         for (int j = 0; j < 2; j++) {
00785             if (((_id_bits & (1 << id)) == 0)
00786              || ((_id_bits_close & (1 << id)) != 0)) {
00787                 _id_bits_close &= ~(1 << id);
00788                 _ids[id] = false;
00789                 _clear_socket_packets(id);
00790                 _smutex.unlock();
00791                 return true;
00792             }
00793             startup();
00794             setTimeout(500);
00795             _parser.process_oob(); // Poll for inbound packets
00796             setTimeout();
00797         }
00798         _smutex.unlock();
00799     }
00800 
00801     //May take a second try if device is busy
00802     for (unsigned i = 0; i < 2; i++) {
00803         _smutex.lock();
00804         if ((_id_bits & (1 << id)) == 0) {
00805             _id_bits_close &= ~(1 << id);
00806             _ids[id] = false;
00807             _clear_socket_packets(id);
00808             _smutex.unlock();
00809             return true;
00810         }
00811         startup();
00812         setTimeout(500);
00813         if (_parser.send("AT+CIPCLOSE=%d", id)
00814             && _parser.recv("OK")) {
00815             setTimeout();
00816             _clear_socket_packets(id);
00817             _id_bits_close &= ~(1 << id);
00818             _ids[id] = false;
00819             _smutex.unlock();
00820             return true;
00821         }
00822         setTimeout();
00823         _smutex.unlock();
00824     }
00825 
00826     _ids[id] = false;
00827     return false;
00828 }
00829 
00830 void ESP32::setTimeout(uint32_t timeout_ms)
00831 {
00832     last_timeout_ms = timeout_ms;
00833     _parser.set_timeout(timeout_ms);
00834 }
00835 
00836 bool ESP32::readable()
00837 {
00838     return _serial.FileHandle::readable();
00839 }
00840 
00841 bool ESP32::writeable()
00842 {
00843     return _serial.FileHandle::writable();
00844 }
00845 
00846 void ESP32::socket_attach(int id, void (*callback)(void *), void *data)
00847 {
00848     _cbs[id].callback = callback;
00849     _cbs[id].data = data;
00850     _cbs[id].Notified = 0;
00851 }
00852 
00853 bool ESP32::recv_ap(nsapi_wifi_ap_t *ap)
00854 {
00855     int sec;
00856     bool ret = _parser.recv("+CWLAP:(%d,\"%32[^\"]\",%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\",%hhu)", &sec, ap->ssid,
00857                             &ap->rssi, &ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4],
00858                             &ap->bssid[5], &ap->channel);
00859 
00860     ap->security = sec < 5 ? (nsapi_security_t)sec : NSAPI_SECURITY_UNKNOWN;
00861 
00862     return ret;
00863 }
00864 
00865 void ESP32::_connect_handler_0() { socket_handler(true, 0);  }
00866 void ESP32::_connect_handler_1() { socket_handler(true, 1);  }
00867 void ESP32::_connect_handler_2() { socket_handler(true, 2);  }
00868 void ESP32::_connect_handler_3() { socket_handler(true, 3);  }
00869 void ESP32::_connect_handler_4() { socket_handler(true, 4);  }
00870 void ESP32::_closed_handler_0()  { socket_handler(false, 0); }
00871 void ESP32::_closed_handler_1()  { socket_handler(false, 1); }
00872 void ESP32::_closed_handler_2()  { socket_handler(false, 2); }
00873 void ESP32::_closed_handler_3()  { socket_handler(false, 3); }
00874 void ESP32::_closed_handler_4()  { socket_handler(false, 4); }
00875 
00876 void ESP32::_connection_status_handler()
00877 {
00878     char status[13];
00879     if (_parser.recv("%12[^\"]\n", status)) {
00880         if (strcmp(status, "CONNECTED\n") == 0) {
00881             _wifi_status = STATUS_CONNECTED;
00882         } else if (strcmp(status, "GOT IP\n") == 0) {
00883             _wifi_status = STATUS_GOT_IP;
00884         } else if (strcmp(status, "DISCONNECT\n") == 0) {
00885             _wifi_status = STATUS_DISCONNECTED;
00886         } else {
00887             return;
00888         }
00889 
00890         if(_wifi_status_cb) {
00891             _wifi_status_cb(_wifi_status);
00892         }
00893     }
00894 }
00895 
00896 int ESP32::get_free_id()
00897 {
00898     // Look for an unused socket
00899     int id = -1;
00900 
00901     for (int i = 0; i < SOCKET_COUNT; i++) {
00902         if ((!_ids[i]) && ((_id_bits & (1 << i)) == 0)) {
00903             id = i;
00904             _ids[i] = true;
00905             break;
00906         }
00907     }
00908 
00909     return id;
00910 }
00911 
00912 void ESP32::event() {
00913     for (int i = 0; i < SOCKET_COUNT; i++) {
00914         if ((_cbs[i].callback) && (_cbs[i].Notified == 0)) {
00915             _cbs[i].callback(_cbs[i].data);
00916             _cbs[i].Notified = 1;
00917         }
00918     }
00919 }
00920 
00921 bool ESP32::set_network(const char *ip_address, const char *netmask, const char *gateway)
00922 {
00923     bool ret;
00924 
00925     if (ip_address == NULL) {
00926         return false;
00927     }
00928 
00929     _smutex.lock();
00930     if ((netmask != NULL) && (gateway != NULL)) {
00931         ret = _parser.send("AT+CIPSTA=\"%s\",\"%s\",\"%s\"", ip_address, gateway, netmask)
00932            && _parser.recv("OK");
00933     } else {
00934         ret = _parser.send("AT+CIPSTA=\"%s\"", ip_address)
00935            && _parser.recv("OK");
00936     }
00937     _smutex.unlock();
00938 
00939     return ret;
00940 }
00941 
00942 bool ESP32::set_network_ap(const char *ip_address, const char *netmask, const char *gateway)
00943 {
00944     bool ret;
00945 
00946     if (ip_address == NULL) {
00947         return false;
00948     }
00949 
00950     _smutex.lock();
00951     if ((netmask != NULL) && (gateway != NULL)) {
00952         ret = _parser.send("AT+CIPAP=\"%s\",\"%s\",\"%s\"", ip_address, gateway, netmask)
00953            && _parser.recv("OK");
00954     } else {
00955         ret = _parser.send("AT+CIPAP=\"%s\"", ip_address)
00956            && _parser.recv("OK");
00957     }
00958     _smutex.unlock();
00959 
00960     return ret;
00961 }
00962 
00963 void ESP32::attach_wifi_status(mbed::Callback<void(int8_t)> status_cb)
00964 {
00965     _wifi_status_cb = status_cb;
00966 }
00967 
00968 int8_t ESP32::get_wifi_status() const
00969 {
00970     return _wifi_status;
00971 }
00972 #endif
00973