u-blox / easy-connect

Dependents:   HelloMQTT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ESP8266.cpp Source File

ESP8266.cpp

00001 /* ESP8266 Example
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 "ESP8266.h"
00018 
00019 ESP8266::ESP8266(PinName tx, PinName rx, bool debug)
00020     : _serial(tx, rx, 1024), _parser(_serial)
00021     , _packets(0), _packets_end(&_packets)
00022 {
00023     _serial.baud(115200);
00024     _parser.debugOn(debug);
00025 }
00026 
00027 int ESP8266::get_firmware_version()
00028 {
00029     _parser.send("AT+GMR");
00030     int version;
00031     if(_parser.recv("SDK version:%d", &version) && _parser.recv("OK")) {
00032         return version;
00033     } else { 
00034         // Older firmware versions do not prefix the version with "SDK version: "
00035         return -1;
00036     }
00037     
00038 }
00039 
00040 bool ESP8266::startup(int mode)
00041 {
00042     //only 3 valid modes
00043     if(mode < 1 || mode > 3) {
00044         return false;
00045     }
00046 
00047     bool success = _parser.send("AT+CWMODE_CUR=%d", mode)
00048         && _parser.recv("OK")
00049         && _parser.send("AT+CIPMUX=1")
00050         && _parser.recv("OK");
00051 
00052     _parser.oob("+IPD", this, &ESP8266::_packet_handler);
00053 
00054     return success;
00055 }
00056 
00057 bool ESP8266::reset(void)
00058 {
00059     for (int i = 0; i < 2; i++) {
00060         if (_parser.send("AT+RST")
00061             && _parser.recv("OK\r\nready")) {
00062             return true;
00063         }
00064     }
00065 
00066     return false;
00067 }
00068 
00069 bool ESP8266::dhcp(bool enabled, int mode)
00070 {
00071     //only 3 valid modes
00072     if(mode < 0 || mode > 2) {
00073         return false;
00074     }
00075 
00076     return _parser.send("AT+CWDHCP_CUR=%d,%d", enabled?1:0, mode)
00077         && _parser.recv("OK");
00078 }
00079 
00080 bool ESP8266::connect(const char *ap, const char *passPhrase)
00081 {
00082     return _parser.send("AT+CWJAP_CUR=\"%s\",\"%s\"", ap, passPhrase)
00083         && _parser.recv("OK");
00084 }
00085 
00086 bool ESP8266::disconnect(void)
00087 {
00088     return _parser.send("AT+CWQAP") && _parser.recv("OK");
00089 }
00090 
00091 const char *ESP8266::getIPAddress(void)
00092 {
00093     if (!(_parser.send("AT+CIFSR")
00094         && _parser.recv("+CIFSR:STAIP,\"%15[^\"]\"", _ip_buffer)
00095         && _parser.recv("OK"))) {
00096         return 0;
00097     }
00098 
00099     return _ip_buffer;
00100 }
00101 
00102 const char *ESP8266::getMACAddress(void)
00103 {
00104     if (!(_parser.send("AT+CIFSR")
00105         && _parser.recv("+CIFSR:STAMAC,\"%17[^\"]\"", _mac_buffer)
00106         && _parser.recv("OK"))) {
00107         return 0;
00108     }
00109 
00110     return _mac_buffer;
00111 }
00112 
00113 const char *ESP8266::getGateway()
00114 {
00115     if (!(_parser.send("AT+CIPSTA_CUR?")
00116         && _parser.recv("+CIPSTA_CUR:gateway:\"%15[^\"]\"", _gateway_buffer)
00117         && _parser.recv("OK"))) {
00118         return 0;
00119     }
00120 
00121     return _gateway_buffer;
00122 }
00123 
00124 const char *ESP8266::getNetmask()
00125 {
00126     if (!(_parser.send("AT+CIPSTA_CUR?")
00127         && _parser.recv("+CIPSTA_CUR:netmask:\"%15[^\"]\"", _netmask_buffer)
00128         && _parser.recv("OK"))) {
00129         return 0;
00130     }
00131 
00132     return _netmask_buffer;
00133 }
00134 
00135 int8_t ESP8266::getRSSI()
00136 {
00137     int8_t rssi;
00138     char bssid[18];
00139 
00140    if (!(_parser.send("AT+CWJAP_CUR?")
00141         && _parser.recv("+CWJAP_CUR::\"%*[^\"]\",\"%17[^\"]\"", bssid)
00142         && _parser.recv("OK"))) {
00143         return 0;
00144     }
00145 
00146     if (!(_parser.send("AT+CWLAP=\"\",\"%s\",", bssid)
00147         && _parser.recv("+CWLAP:(%*d,\"%*[^\"]\",%hhd,", &rssi)
00148         && _parser.recv("OK"))) {
00149         return 0;
00150     }
00151 
00152     return rssi;
00153 }
00154 
00155 bool ESP8266::isConnected(void)
00156 {
00157     return getIPAddress() != 0;
00158 }
00159 
00160 int ESP8266::scan(WiFiAccessPoint *res, unsigned limit)
00161 {
00162     unsigned cnt = 0;
00163     nsapi_wifi_ap_t ap;
00164 
00165     if (!_parser.send("AT+CWLAP")) {
00166         return NSAPI_ERROR_DEVICE_ERROR;
00167     }
00168 
00169     while (recv_ap(&ap)) {
00170         if (cnt < limit) {
00171             res[cnt] = WiFiAccessPoint(ap);
00172         }
00173 
00174         cnt++;
00175         if (limit != 0 && cnt >= limit) {
00176             break;
00177         }
00178     }
00179 
00180     return cnt;
00181 }
00182 
00183 bool ESP8266::open(const char *type, int id, const char* addr, int port)
00184 {
00185     //IDs only 0-4
00186     if(id > 4) {
00187         return false;
00188     }
00189     return _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d", id, type, addr, port)
00190         && _parser.recv("OK");
00191 }
00192 
00193 bool ESP8266::dns_lookup(const char* name, char* ip)
00194 {
00195     return _parser.send("AT+CIPDOMAIN=\"%s\"", name) && _parser.recv("+CIPDOMAIN:%s%*[\r]%*[\n]", ip);
00196 }
00197 
00198 bool ESP8266::send(int id, const void *data, uint32_t amount)
00199 {
00200     //May take a second try if device is busy
00201     for (unsigned i = 0; i < 2; i++) {
00202         if (_parser.send("AT+CIPSEND=%d,%d", id, amount)
00203             && _parser.recv(">")
00204             && _parser.write((char*)data, (int)amount) >= 0) {
00205             return true;
00206         }
00207     }
00208 
00209     return false;
00210 }
00211 
00212 void ESP8266::_packet_handler()
00213 {
00214     int id;
00215     uint32_t amount;
00216 
00217     // parse out the packet
00218     if (!_parser.recv(",%d,%d:", &id, &amount)) {
00219         return;
00220     }
00221 
00222     struct packet *packet = (struct packet*)malloc(
00223             sizeof(struct packet) + amount);
00224     if (!packet) {
00225         return;
00226     }
00227 
00228     packet->id = id;
00229     packet->len = amount;
00230     packet->next = 0;
00231 
00232     if (!(_parser.read((char*)(packet + 1), amount))) {
00233         free(packet);
00234         return;
00235     }
00236 
00237     // append to packet list
00238     *_packets_end = packet;
00239     _packets_end = &packet->next;
00240 }
00241 
00242 int32_t ESP8266::recv(int id, void *data, uint32_t amount)
00243 {
00244     while (true) {
00245         // check if any packets are ready for us
00246         for (struct packet **p = &_packets; *p; p = &(*p)->next) {
00247             if ((*p)->id == id) {
00248                 struct packet *q = *p;
00249 
00250                 if (q->len <= amount) { // Return and remove full packet
00251                     memcpy(data, q+1, q->len);
00252 
00253                     if (_packets_end == &(*p)->next) {
00254                         _packets_end = p;
00255                     }
00256                     *p = (*p)->next;
00257 
00258                     uint32_t len = q->len;
00259                     free(q);
00260                     return len;
00261                 } else { // return only partial packet
00262                     memcpy(data, q+1, amount);
00263 
00264                     q->len -= amount;
00265                     memmove(q+1, (uint8_t*)(q+1) + amount, q->len);
00266 
00267                     return amount;
00268                 }
00269             }
00270         }
00271 
00272         // Wait for inbound packet
00273         if (!_parser.recv("OK")) {
00274             return -1;
00275         }
00276     }
00277 }
00278 
00279 bool ESP8266::close(int id)
00280 {
00281     //May take a second try if device is busy
00282     for (unsigned i = 0; i < 2; i++) {
00283         if (_parser.send("AT+CIPCLOSE=%d", id)
00284             && _parser.recv("OK")) {
00285             return true;
00286         }
00287     }
00288 
00289     return false;
00290 }
00291 
00292 void ESP8266::setTimeout(uint32_t timeout_ms)
00293 {
00294     _parser.setTimeout(timeout_ms);
00295 }
00296 
00297 bool ESP8266::readable()
00298 {
00299     return _serial.readable();
00300 }
00301 
00302 bool ESP8266::writeable()
00303 {
00304     return _serial.writeable();
00305 }
00306 
00307 void ESP8266::attach(Callback<void()> func)
00308 {
00309     _serial.attach(func);
00310 }
00311 
00312 bool ESP8266::recv_ap(nsapi_wifi_ap_t *ap)
00313 {
00314     int sec;
00315     bool ret = _parser.recv("+CWLAP:(%d,\"%32[^\"]\",%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\",%d", &sec, ap->ssid,
00316                             &ap->rssi, &ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4],
00317                             &ap->bssid[5], &ap->channel);
00318 
00319     ap->security = sec < 5 ? (nsapi_security_t)sec : NSAPI_SECURITY_UNKNOWN;
00320 
00321     return ret;
00322 }