The driver for the ESP8266 WiFi module

Committer:
group-ESP8266
Date:
Thu Jan 12 21:57:48 2017 +0000
Revision:
0:6946b0b9e323
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
group-ESP8266 0:6946b0b9e323 1 /* ESP8266 Example
group-ESP8266 0:6946b0b9e323 2 * Copyright (c) 2015 ARM Limited
group-ESP8266 0:6946b0b9e323 3 *
group-ESP8266 0:6946b0b9e323 4 * Licensed under the Apache License, Version 2.0 (the "License");
group-ESP8266 0:6946b0b9e323 5 * you may not use this file except in compliance with the License.
group-ESP8266 0:6946b0b9e323 6 * You may obtain a copy of the License at
group-ESP8266 0:6946b0b9e323 7 *
group-ESP8266 0:6946b0b9e323 8 * http://www.apache.org/licenses/LICENSE-2.0
group-ESP8266 0:6946b0b9e323 9 *
group-ESP8266 0:6946b0b9e323 10 * Unless required by applicable law or agreed to in writing, software
group-ESP8266 0:6946b0b9e323 11 * distributed under the License is distributed on an "AS IS" BASIS,
group-ESP8266 0:6946b0b9e323 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
group-ESP8266 0:6946b0b9e323 13 * See the License for the specific language governing permissions and
group-ESP8266 0:6946b0b9e323 14 * limitations under the License.
group-ESP8266 0:6946b0b9e323 15 */
group-ESP8266 0:6946b0b9e323 16
group-ESP8266 0:6946b0b9e323 17 #include "ESP8266.h"
group-ESP8266 0:6946b0b9e323 18
group-ESP8266 0:6946b0b9e323 19 ESP8266::ESP8266(PinName tx, PinName rx, bool debug)
group-ESP8266 0:6946b0b9e323 20 : _serial(tx, rx, 1024), _parser(_serial)
group-ESP8266 0:6946b0b9e323 21 , _packets(0), _packets_end(&_packets)
group-ESP8266 0:6946b0b9e323 22 {
group-ESP8266 0:6946b0b9e323 23 _serial.baud(115200);
group-ESP8266 0:6946b0b9e323 24 _parser.debugOn(debug);
group-ESP8266 0:6946b0b9e323 25 }
group-ESP8266 0:6946b0b9e323 26
group-ESP8266 0:6946b0b9e323 27 bool ESP8266::startup(int mode)
group-ESP8266 0:6946b0b9e323 28 {
group-ESP8266 0:6946b0b9e323 29 //only 3 valid modes
group-ESP8266 0:6946b0b9e323 30 if(mode < 1 || mode > 3) {
group-ESP8266 0:6946b0b9e323 31 return false;
group-ESP8266 0:6946b0b9e323 32 }
group-ESP8266 0:6946b0b9e323 33
group-ESP8266 0:6946b0b9e323 34 bool success = reset()
group-ESP8266 0:6946b0b9e323 35 && _parser.send("AT+CWMODE=%d", mode)
group-ESP8266 0:6946b0b9e323 36 && _parser.recv("OK")
group-ESP8266 0:6946b0b9e323 37 && _parser.send("AT+CIPMUX=1")
group-ESP8266 0:6946b0b9e323 38 && _parser.recv("OK");
group-ESP8266 0:6946b0b9e323 39
group-ESP8266 0:6946b0b9e323 40 _parser.oob("+IPD", this, &ESP8266::_packet_handler);
group-ESP8266 0:6946b0b9e323 41
group-ESP8266 0:6946b0b9e323 42 return success;
group-ESP8266 0:6946b0b9e323 43 }
group-ESP8266 0:6946b0b9e323 44
group-ESP8266 0:6946b0b9e323 45 bool ESP8266::reset(void)
group-ESP8266 0:6946b0b9e323 46 {
group-ESP8266 0:6946b0b9e323 47 for (int i = 0; i < 2; i++) {
group-ESP8266 0:6946b0b9e323 48 if (_parser.send("AT+RST")
group-ESP8266 0:6946b0b9e323 49 && _parser.recv("OK\r\nready")) {
group-ESP8266 0:6946b0b9e323 50 return true;
group-ESP8266 0:6946b0b9e323 51 }
group-ESP8266 0:6946b0b9e323 52 }
group-ESP8266 0:6946b0b9e323 53
group-ESP8266 0:6946b0b9e323 54 return false;
group-ESP8266 0:6946b0b9e323 55 }
group-ESP8266 0:6946b0b9e323 56
group-ESP8266 0:6946b0b9e323 57 bool ESP8266::dhcp(bool enabled, int mode)
group-ESP8266 0:6946b0b9e323 58 {
group-ESP8266 0:6946b0b9e323 59 //only 3 valid modes
group-ESP8266 0:6946b0b9e323 60 if(mode < 0 || mode > 2) {
group-ESP8266 0:6946b0b9e323 61 return false;
group-ESP8266 0:6946b0b9e323 62 }
group-ESP8266 0:6946b0b9e323 63
group-ESP8266 0:6946b0b9e323 64 return _parser.send("AT+CWDHCP=%d,%d", enabled?1:0, mode)
group-ESP8266 0:6946b0b9e323 65 && _parser.recv("OK");
group-ESP8266 0:6946b0b9e323 66 }
group-ESP8266 0:6946b0b9e323 67
group-ESP8266 0:6946b0b9e323 68 bool ESP8266::connect(const char *ap, const char *passPhrase)
group-ESP8266 0:6946b0b9e323 69 {
group-ESP8266 0:6946b0b9e323 70 return _parser.send("AT+CWJAP=\"%s\",\"%s\"", ap, passPhrase)
group-ESP8266 0:6946b0b9e323 71 && _parser.recv("OK");
group-ESP8266 0:6946b0b9e323 72 }
group-ESP8266 0:6946b0b9e323 73
group-ESP8266 0:6946b0b9e323 74 bool ESP8266::disconnect(void)
group-ESP8266 0:6946b0b9e323 75 {
group-ESP8266 0:6946b0b9e323 76 return _parser.send("AT+CWQAP") && _parser.recv("OK");
group-ESP8266 0:6946b0b9e323 77 }
group-ESP8266 0:6946b0b9e323 78
group-ESP8266 0:6946b0b9e323 79 const char *ESP8266::getIPAddress(void)
group-ESP8266 0:6946b0b9e323 80 {
group-ESP8266 0:6946b0b9e323 81 if (!(_parser.send("AT+CIFSR")
group-ESP8266 0:6946b0b9e323 82 && _parser.recv("+CIFSR:STAIP,\"%15[^\"]\"", _ip_buffer)
group-ESP8266 0:6946b0b9e323 83 && _parser.recv("OK"))) {
group-ESP8266 0:6946b0b9e323 84 return 0;
group-ESP8266 0:6946b0b9e323 85 }
group-ESP8266 0:6946b0b9e323 86
group-ESP8266 0:6946b0b9e323 87 return _ip_buffer;
group-ESP8266 0:6946b0b9e323 88 }
group-ESP8266 0:6946b0b9e323 89
group-ESP8266 0:6946b0b9e323 90 const char *ESP8266::getMACAddress(void)
group-ESP8266 0:6946b0b9e323 91 {
group-ESP8266 0:6946b0b9e323 92 if (!(_parser.send("AT+CIFSR")
group-ESP8266 0:6946b0b9e323 93 && _parser.recv("+CIFSR:STAMAC,\"%17[^\"]\"", _mac_buffer)
group-ESP8266 0:6946b0b9e323 94 && _parser.recv("OK"))) {
group-ESP8266 0:6946b0b9e323 95 return 0;
group-ESP8266 0:6946b0b9e323 96 }
group-ESP8266 0:6946b0b9e323 97
group-ESP8266 0:6946b0b9e323 98 return _mac_buffer;
group-ESP8266 0:6946b0b9e323 99 }
group-ESP8266 0:6946b0b9e323 100
group-ESP8266 0:6946b0b9e323 101 const char *ESP8266::getGateway()
group-ESP8266 0:6946b0b9e323 102 {
group-ESP8266 0:6946b0b9e323 103 if (!(_parser.send("AT+CIPSTA?")
group-ESP8266 0:6946b0b9e323 104 && _parser.recv("+CIPSTA:gateway:\"%15[^\"]\"", _gateway_buffer)
group-ESP8266 0:6946b0b9e323 105 && _parser.recv("OK"))) {
group-ESP8266 0:6946b0b9e323 106 return 0;
group-ESP8266 0:6946b0b9e323 107 }
group-ESP8266 0:6946b0b9e323 108
group-ESP8266 0:6946b0b9e323 109 return _gateway_buffer;
group-ESP8266 0:6946b0b9e323 110 }
group-ESP8266 0:6946b0b9e323 111
group-ESP8266 0:6946b0b9e323 112 const char *ESP8266::getNetmask()
group-ESP8266 0:6946b0b9e323 113 {
group-ESP8266 0:6946b0b9e323 114 if (!(_parser.send("AT+CIPSTA?")
group-ESP8266 0:6946b0b9e323 115 && _parser.recv("+CIPSTA:netmask:\"%15[^\"]\"", _netmask_buffer)
group-ESP8266 0:6946b0b9e323 116 && _parser.recv("OK"))) {
group-ESP8266 0:6946b0b9e323 117 return 0;
group-ESP8266 0:6946b0b9e323 118 }
group-ESP8266 0:6946b0b9e323 119
group-ESP8266 0:6946b0b9e323 120 return _netmask_buffer;
group-ESP8266 0:6946b0b9e323 121 }
group-ESP8266 0:6946b0b9e323 122
group-ESP8266 0:6946b0b9e323 123 int8_t ESP8266::getRSSI()
group-ESP8266 0:6946b0b9e323 124 {
group-ESP8266 0:6946b0b9e323 125 int8_t rssi;
group-ESP8266 0:6946b0b9e323 126 char bssid[18];
group-ESP8266 0:6946b0b9e323 127
group-ESP8266 0:6946b0b9e323 128 if (!(_parser.send("AT+CWJAP?")
group-ESP8266 0:6946b0b9e323 129 && _parser.recv("+CWJAP:\"%*[^\"]\",\"%17[^\"]\"", bssid)
group-ESP8266 0:6946b0b9e323 130 && _parser.recv("OK"))) {
group-ESP8266 0:6946b0b9e323 131 return 0;
group-ESP8266 0:6946b0b9e323 132 }
group-ESP8266 0:6946b0b9e323 133
group-ESP8266 0:6946b0b9e323 134 if (!(_parser.send("AT+CWLAP=\"\",\"%s\",", bssid)
group-ESP8266 0:6946b0b9e323 135 && _parser.recv("+CWLAP:(%*d,\"%*[^\"]\",%hhd,", &rssi)
group-ESP8266 0:6946b0b9e323 136 && _parser.recv("OK"))) {
group-ESP8266 0:6946b0b9e323 137 return 0;
group-ESP8266 0:6946b0b9e323 138 }
group-ESP8266 0:6946b0b9e323 139
group-ESP8266 0:6946b0b9e323 140 return rssi;
group-ESP8266 0:6946b0b9e323 141 }
group-ESP8266 0:6946b0b9e323 142
group-ESP8266 0:6946b0b9e323 143 bool ESP8266::isConnected(void)
group-ESP8266 0:6946b0b9e323 144 {
group-ESP8266 0:6946b0b9e323 145 return getIPAddress() != 0;
group-ESP8266 0:6946b0b9e323 146 }
group-ESP8266 0:6946b0b9e323 147
group-ESP8266 0:6946b0b9e323 148 int ESP8266::scan(WiFiAccessPoint *res, unsigned limit)
group-ESP8266 0:6946b0b9e323 149 {
group-ESP8266 0:6946b0b9e323 150 unsigned cnt = 0;
group-ESP8266 0:6946b0b9e323 151 nsapi_wifi_ap_t ap;
group-ESP8266 0:6946b0b9e323 152
group-ESP8266 0:6946b0b9e323 153 if (!_parser.send("AT+CWLAP")) {
group-ESP8266 0:6946b0b9e323 154 return NSAPI_ERROR_DEVICE_ERROR;
group-ESP8266 0:6946b0b9e323 155 }
group-ESP8266 0:6946b0b9e323 156
group-ESP8266 0:6946b0b9e323 157 while (recv_ap(&ap)) {
group-ESP8266 0:6946b0b9e323 158 if (cnt < limit) {
group-ESP8266 0:6946b0b9e323 159 res[cnt] = WiFiAccessPoint(ap);
group-ESP8266 0:6946b0b9e323 160 }
group-ESP8266 0:6946b0b9e323 161
group-ESP8266 0:6946b0b9e323 162 cnt++;
group-ESP8266 0:6946b0b9e323 163 if (limit != 0 && cnt >= limit) {
group-ESP8266 0:6946b0b9e323 164 break;
group-ESP8266 0:6946b0b9e323 165 }
group-ESP8266 0:6946b0b9e323 166 }
group-ESP8266 0:6946b0b9e323 167
group-ESP8266 0:6946b0b9e323 168 return cnt;
group-ESP8266 0:6946b0b9e323 169 }
group-ESP8266 0:6946b0b9e323 170
group-ESP8266 0:6946b0b9e323 171 bool ESP8266::open(const char *type, int id, const char* addr, int port)
group-ESP8266 0:6946b0b9e323 172 {
group-ESP8266 0:6946b0b9e323 173 //IDs only 0-4
group-ESP8266 0:6946b0b9e323 174 if(id > 4) {
group-ESP8266 0:6946b0b9e323 175 return false;
group-ESP8266 0:6946b0b9e323 176 }
group-ESP8266 0:6946b0b9e323 177
group-ESP8266 0:6946b0b9e323 178 return _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d", id, type, addr, port)
group-ESP8266 0:6946b0b9e323 179 && _parser.recv("OK");
group-ESP8266 0:6946b0b9e323 180 }
group-ESP8266 0:6946b0b9e323 181
group-ESP8266 0:6946b0b9e323 182 bool ESP8266::send(int id, const void *data, uint32_t amount)
group-ESP8266 0:6946b0b9e323 183 {
group-ESP8266 0:6946b0b9e323 184 //May take a second try if device is busy
group-ESP8266 0:6946b0b9e323 185 for (unsigned i = 0; i < 2; i++) {
group-ESP8266 0:6946b0b9e323 186 if (_parser.send("AT+CIPSEND=%d,%d", id, amount)
group-ESP8266 0:6946b0b9e323 187 && _parser.recv(">")
group-ESP8266 0:6946b0b9e323 188 && _parser.write((char*)data, (int)amount) >= 0) {
group-ESP8266 0:6946b0b9e323 189 return true;
group-ESP8266 0:6946b0b9e323 190 }
group-ESP8266 0:6946b0b9e323 191 }
group-ESP8266 0:6946b0b9e323 192
group-ESP8266 0:6946b0b9e323 193 return false;
group-ESP8266 0:6946b0b9e323 194 }
group-ESP8266 0:6946b0b9e323 195
group-ESP8266 0:6946b0b9e323 196 void ESP8266::_packet_handler()
group-ESP8266 0:6946b0b9e323 197 {
group-ESP8266 0:6946b0b9e323 198 int id;
group-ESP8266 0:6946b0b9e323 199 uint32_t amount;
group-ESP8266 0:6946b0b9e323 200
group-ESP8266 0:6946b0b9e323 201 // parse out the packet
group-ESP8266 0:6946b0b9e323 202 if (!_parser.recv(",%d,%d:", &id, &amount)) {
group-ESP8266 0:6946b0b9e323 203 return;
group-ESP8266 0:6946b0b9e323 204 }
group-ESP8266 0:6946b0b9e323 205
group-ESP8266 0:6946b0b9e323 206 struct packet *packet = (struct packet*)malloc(
group-ESP8266 0:6946b0b9e323 207 sizeof(struct packet) + amount);
group-ESP8266 0:6946b0b9e323 208 if (!packet) {
group-ESP8266 0:6946b0b9e323 209 return;
group-ESP8266 0:6946b0b9e323 210 }
group-ESP8266 0:6946b0b9e323 211
group-ESP8266 0:6946b0b9e323 212 packet->id = id;
group-ESP8266 0:6946b0b9e323 213 packet->len = amount;
group-ESP8266 0:6946b0b9e323 214 packet->next = 0;
group-ESP8266 0:6946b0b9e323 215
group-ESP8266 0:6946b0b9e323 216 if (!(_parser.read((char*)(packet + 1), amount))) {
group-ESP8266 0:6946b0b9e323 217 free(packet);
group-ESP8266 0:6946b0b9e323 218 return;
group-ESP8266 0:6946b0b9e323 219 }
group-ESP8266 0:6946b0b9e323 220
group-ESP8266 0:6946b0b9e323 221 // append to packet list
group-ESP8266 0:6946b0b9e323 222 *_packets_end = packet;
group-ESP8266 0:6946b0b9e323 223 _packets_end = &packet->next;
group-ESP8266 0:6946b0b9e323 224 }
group-ESP8266 0:6946b0b9e323 225
group-ESP8266 0:6946b0b9e323 226 int32_t ESP8266::recv(int id, void *data, uint32_t amount)
group-ESP8266 0:6946b0b9e323 227 {
group-ESP8266 0:6946b0b9e323 228 while (true) {
group-ESP8266 0:6946b0b9e323 229 // check if any packets are ready for us
group-ESP8266 0:6946b0b9e323 230 for (struct packet **p = &_packets; *p; p = &(*p)->next) {
group-ESP8266 0:6946b0b9e323 231 if ((*p)->id == id) {
group-ESP8266 0:6946b0b9e323 232 struct packet *q = *p;
group-ESP8266 0:6946b0b9e323 233
group-ESP8266 0:6946b0b9e323 234 if (q->len <= amount) { // Return and remove full packet
group-ESP8266 0:6946b0b9e323 235 memcpy(data, q+1, q->len);
group-ESP8266 0:6946b0b9e323 236
group-ESP8266 0:6946b0b9e323 237 if (_packets_end == &(*p)->next) {
group-ESP8266 0:6946b0b9e323 238 _packets_end = p;
group-ESP8266 0:6946b0b9e323 239 }
group-ESP8266 0:6946b0b9e323 240 *p = (*p)->next;
group-ESP8266 0:6946b0b9e323 241
group-ESP8266 0:6946b0b9e323 242 uint32_t len = q->len;
group-ESP8266 0:6946b0b9e323 243 free(q);
group-ESP8266 0:6946b0b9e323 244 return len;
group-ESP8266 0:6946b0b9e323 245 } else { // return only partial packet
group-ESP8266 0:6946b0b9e323 246 memcpy(data, q+1, amount);
group-ESP8266 0:6946b0b9e323 247
group-ESP8266 0:6946b0b9e323 248 q->len -= amount;
group-ESP8266 0:6946b0b9e323 249 memmove(q+1, (uint8_t*)(q+1) + amount, q->len);
group-ESP8266 0:6946b0b9e323 250
group-ESP8266 0:6946b0b9e323 251 return amount;
group-ESP8266 0:6946b0b9e323 252 }
group-ESP8266 0:6946b0b9e323 253 }
group-ESP8266 0:6946b0b9e323 254 }
group-ESP8266 0:6946b0b9e323 255
group-ESP8266 0:6946b0b9e323 256 // Wait for inbound packet
group-ESP8266 0:6946b0b9e323 257 if (!_parser.recv("OK")) {
group-ESP8266 0:6946b0b9e323 258 return -1;
group-ESP8266 0:6946b0b9e323 259 }
group-ESP8266 0:6946b0b9e323 260 }
group-ESP8266 0:6946b0b9e323 261 }
group-ESP8266 0:6946b0b9e323 262
group-ESP8266 0:6946b0b9e323 263 bool ESP8266::close(int id)
group-ESP8266 0:6946b0b9e323 264 {
group-ESP8266 0:6946b0b9e323 265 //May take a second try if device is busy
group-ESP8266 0:6946b0b9e323 266 for (unsigned i = 0; i < 2; i++) {
group-ESP8266 0:6946b0b9e323 267 if (_parser.send("AT+CIPCLOSE=%d", id)
group-ESP8266 0:6946b0b9e323 268 && _parser.recv("OK")) {
group-ESP8266 0:6946b0b9e323 269 return true;
group-ESP8266 0:6946b0b9e323 270 }
group-ESP8266 0:6946b0b9e323 271 }
group-ESP8266 0:6946b0b9e323 272
group-ESP8266 0:6946b0b9e323 273 return false;
group-ESP8266 0:6946b0b9e323 274 }
group-ESP8266 0:6946b0b9e323 275
group-ESP8266 0:6946b0b9e323 276 void ESP8266::setTimeout(uint32_t timeout_ms)
group-ESP8266 0:6946b0b9e323 277 {
group-ESP8266 0:6946b0b9e323 278 _parser.setTimeout(timeout_ms);
group-ESP8266 0:6946b0b9e323 279 }
group-ESP8266 0:6946b0b9e323 280
group-ESP8266 0:6946b0b9e323 281 bool ESP8266::readable()
group-ESP8266 0:6946b0b9e323 282 {
group-ESP8266 0:6946b0b9e323 283 return _serial.readable();
group-ESP8266 0:6946b0b9e323 284 }
group-ESP8266 0:6946b0b9e323 285
group-ESP8266 0:6946b0b9e323 286 bool ESP8266::writeable()
group-ESP8266 0:6946b0b9e323 287 {
group-ESP8266 0:6946b0b9e323 288 return _serial.writeable();
group-ESP8266 0:6946b0b9e323 289 }
group-ESP8266 0:6946b0b9e323 290
group-ESP8266 0:6946b0b9e323 291 void ESP8266::attach(Callback<void()> func)
group-ESP8266 0:6946b0b9e323 292 {
group-ESP8266 0:6946b0b9e323 293 _serial.attach(func);
group-ESP8266 0:6946b0b9e323 294 }
group-ESP8266 0:6946b0b9e323 295
group-ESP8266 0:6946b0b9e323 296 bool ESP8266::recv_ap(nsapi_wifi_ap_t *ap)
group-ESP8266 0:6946b0b9e323 297 {
group-ESP8266 0:6946b0b9e323 298 int sec;
group-ESP8266 0:6946b0b9e323 299 bool ret = _parser.recv("+CWLAP:(%d,\"%32[^\"]\",%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\",%d", &sec, ap->ssid,
group-ESP8266 0:6946b0b9e323 300 &ap->rssi, &ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4],
group-ESP8266 0:6946b0b9e323 301 &ap->bssid[5], &ap->channel);
group-ESP8266 0:6946b0b9e323 302
group-ESP8266 0:6946b0b9e323 303 ap->security = sec < 5 ? (nsapi_security_t)sec : NSAPI_SECURITY_UNKNOWN;
group-ESP8266 0:6946b0b9e323 304
group-ESP8266 0:6946b0b9e323 305 return ret;
group-ESP8266 0:6946b0b9e323 306 }