version 1.6

Dependents:   iot_water_monitor_v2

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