The driver for the ESP32 WiFi module

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