Easily add all supported connectivity methods to your mbed OS project

Dependencies:   type-yd-driver

Committer:
MACRUM
Date:
Wed Jul 12 10:52:58 2017 +0000
Revision:
0:615f90842ce8
Initial commit

Who changed what in which revision?

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