Fork of my original MQTTGateway

Dependencies:   mbed-http

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