Fork of my MQTTGateway

Dependencies:   mbed-http

Committer:
vpcola
Date:
Sat Apr 08 14:45:51 2017 +0000
Revision:
0:f1d3878b8dd9
Initial commit

Who changed what in which revision?

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