Added support for WNC M14A2A Cellular LTE Data Module.

Dependencies:   WNC14A2AInterface

Dependents:   http-example-wnc http-example-wnc-modified

Committer:
root@developer-sjc-cyan-compiler.local.mbed.org
Date:
Sun Apr 23 18:40:51 2017 +0000
Revision:
5:391eac6a0a94
Parent:
0:2563b0415d1f
Added tag att_cellular_K64_wnc_14A2A_20170423 for changeset daf182af022b

Who changed what in which revision?

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