a

Fork of ESE519_Lab6_part1_skeleton by Carter Sharer

Committer:
hydroguy45
Date:
Fri Nov 01 18:52:45 2019 +0000
Revision:
12:ea030e3181d3
Parent:
7:ca226305d28b
Cleaned up the header

Who changed what in which revision?

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