A metronome using the FRDM K64F board

Committer:
ram54288
Date:
Sun May 14 18:40:18 2017 +0000
Revision:
0:a7a43371b306
Initial commit

Who changed what in which revision?

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