wifi test

Dependencies:   X_NUCLEO_IKS01A2 mbed-http

Committer:
JMF
Date:
Wed Sep 05 14:28:24 2018 +0000
Revision:
0:24d3eb812fd4
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JMF 0:24d3eb812fd4 1 /* ESP8266 Example
JMF 0:24d3eb812fd4 2 * Copyright (c) 2015 ARM Limited
JMF 0:24d3eb812fd4 3 *
JMF 0:24d3eb812fd4 4 * Licensed under the Apache License, Version 2.0 (the "License");
JMF 0:24d3eb812fd4 5 * you may not use this file except in compliance with the License.
JMF 0:24d3eb812fd4 6 * You may obtain a copy of the License at
JMF 0:24d3eb812fd4 7 *
JMF 0:24d3eb812fd4 8 * http://www.apache.org/licenses/LICENSE-2.0
JMF 0:24d3eb812fd4 9 *
JMF 0:24d3eb812fd4 10 * Unless required by applicable law or agreed to in writing, software
JMF 0:24d3eb812fd4 11 * distributed under the License is distributed on an "AS IS" BASIS,
JMF 0:24d3eb812fd4 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
JMF 0:24d3eb812fd4 13 * See the License for the specific language governing permissions and
JMF 0:24d3eb812fd4 14 * limitations under the License.
JMF 0:24d3eb812fd4 15 */
JMF 0:24d3eb812fd4 16
JMF 0:24d3eb812fd4 17 #include "ESP8266.h"
JMF 0:24d3eb812fd4 18 #include "mbed_debug.h"
JMF 0:24d3eb812fd4 19 #include "nsapi_types.h"
JMF 0:24d3eb812fd4 20
JMF 0:24d3eb812fd4 21 #include <cstring>
JMF 0:24d3eb812fd4 22
JMF 0:24d3eb812fd4 23 #define ESP8266_DEFAULT_BAUD_RATE 115200
JMF 0:24d3eb812fd4 24 #define ESP8266_ALL_SOCKET_IDS -1
JMF 0:24d3eb812fd4 25
JMF 0:24d3eb812fd4 26 ESP8266::ESP8266(PinName tx, PinName rx, bool debug)
JMF 0:24d3eb812fd4 27 : _serial(tx, rx, ESP8266_DEFAULT_BAUD_RATE),
JMF 0:24d3eb812fd4 28 _parser(&_serial),
JMF 0:24d3eb812fd4 29 _packets(0),
JMF 0:24d3eb812fd4 30 _packets_end(&_packets),
JMF 0:24d3eb812fd4 31 _connect_error(0),
JMF 0:24d3eb812fd4 32 _fail(false),
JMF 0:24d3eb812fd4 33 _closed(false),
JMF 0:24d3eb812fd4 34 _socket_open(),
JMF 0:24d3eb812fd4 35 _connection_status(NSAPI_STATUS_DISCONNECTED)
JMF 0:24d3eb812fd4 36 {
JMF 0:24d3eb812fd4 37 _serial.set_baud( ESP8266_DEFAULT_BAUD_RATE );
JMF 0:24d3eb812fd4 38 _parser.debug_on(debug);
JMF 0:24d3eb812fd4 39 _parser.set_delimiter("\r\n");
JMF 0:24d3eb812fd4 40 _parser.oob("+IPD", callback(this, &ESP8266::_packet_handler));
JMF 0:24d3eb812fd4 41 //Note: espressif at command document says that this should be +CWJAP_CUR:<error code>
JMF 0:24d3eb812fd4 42 //but seems that at least current version is not sending it
JMF 0:24d3eb812fd4 43 //https://www.espressif.com/sites/default/files/documentation/4a-esp8266_at_instruction_set_en.pdf
JMF 0:24d3eb812fd4 44 //Also seems that ERROR is not sent, but FAIL instead
JMF 0:24d3eb812fd4 45 _parser.oob("+CWJAP:", callback(this, &ESP8266::_connect_error_handler));
JMF 0:24d3eb812fd4 46 _parser.oob("0,CLOSED", callback(this, &ESP8266::_oob_socket0_closed_handler));
JMF 0:24d3eb812fd4 47 _parser.oob("1,CLOSED", callback(this, &ESP8266::_oob_socket1_closed_handler));
JMF 0:24d3eb812fd4 48 _parser.oob("2,CLOSED", callback(this, &ESP8266::_oob_socket2_closed_handler));
JMF 0:24d3eb812fd4 49 _parser.oob("3,CLOSED", callback(this, &ESP8266::_oob_socket3_closed_handler));
JMF 0:24d3eb812fd4 50 _parser.oob("4,CLOSED", callback(this, &ESP8266::_oob_socket4_closed_handler));
JMF 0:24d3eb812fd4 51 _parser.oob("WIFI ", callback(this, &ESP8266::_connection_status_handler));
JMF 0:24d3eb812fd4 52 _parser.oob("UNLINK", callback(this, &ESP8266::_oob_socket_close_error));
JMF 0:24d3eb812fd4 53 }
JMF 0:24d3eb812fd4 54
JMF 0:24d3eb812fd4 55 int ESP8266::get_firmware_version()
JMF 0:24d3eb812fd4 56 {
JMF 0:24d3eb812fd4 57 int version;
JMF 0:24d3eb812fd4 58
JMF 0:24d3eb812fd4 59 _smutex.lock();
JMF 0:24d3eb812fd4 60 bool done = _parser.send("AT+GMR")
JMF 0:24d3eb812fd4 61 && _parser.recv("SDK version:%d", &version)
JMF 0:24d3eb812fd4 62 && _parser.recv("OK\n");
JMF 0:24d3eb812fd4 63 _smutex.unlock();
JMF 0:24d3eb812fd4 64
JMF 0:24d3eb812fd4 65 if(done) {
JMF 0:24d3eb812fd4 66 return version;
JMF 0:24d3eb812fd4 67 } else {
JMF 0:24d3eb812fd4 68 // Older firmware versions do not prefix the version with "SDK version: "
JMF 0:24d3eb812fd4 69 return -1;
JMF 0:24d3eb812fd4 70 }
JMF 0:24d3eb812fd4 71 }
JMF 0:24d3eb812fd4 72
JMF 0:24d3eb812fd4 73 bool ESP8266::startup(int mode)
JMF 0:24d3eb812fd4 74 {
JMF 0:24d3eb812fd4 75 if (!(mode == WIFIMODE_STATION || mode == WIFIMODE_SOFTAP
JMF 0:24d3eb812fd4 76 || mode == WIFIMODE_STATION_SOFTAP)) {
JMF 0:24d3eb812fd4 77 return false;
JMF 0:24d3eb812fd4 78 }
JMF 0:24d3eb812fd4 79
JMF 0:24d3eb812fd4 80 _smutex.lock();
JMF 0:24d3eb812fd4 81 setTimeout(ESP8266_CONNECT_TIMEOUT);
JMF 0:24d3eb812fd4 82 bool done = _parser.send("AT+CWMODE_CUR=%d", mode)
JMF 0:24d3eb812fd4 83 && _parser.recv("OK\n")
JMF 0:24d3eb812fd4 84 &&_parser.send("AT+CIPMUX=1")
JMF 0:24d3eb812fd4 85 && _parser.recv("OK\n");
JMF 0:24d3eb812fd4 86 setTimeout(); //Restore default
JMF 0:24d3eb812fd4 87 _smutex.unlock();
JMF 0:24d3eb812fd4 88
JMF 0:24d3eb812fd4 89 return done;
JMF 0:24d3eb812fd4 90 }
JMF 0:24d3eb812fd4 91
JMF 0:24d3eb812fd4 92 bool ESP8266::reset(void)
JMF 0:24d3eb812fd4 93 {
JMF 0:24d3eb812fd4 94 _smutex.lock();
JMF 0:24d3eb812fd4 95 setTimeout(ESP8266_CONNECT_TIMEOUT);
JMF 0:24d3eb812fd4 96
JMF 0:24d3eb812fd4 97 for (int i = 0; i < 2; i++) {
JMF 0:24d3eb812fd4 98 if (_parser.send("AT+RST")
JMF 0:24d3eb812fd4 99 && _parser.recv("OK\n")
JMF 0:24d3eb812fd4 100 && _parser.recv("ready")) {
JMF 0:24d3eb812fd4 101 _clear_socket_packets(ESP8266_ALL_SOCKET_IDS);
JMF 0:24d3eb812fd4 102 _smutex.unlock();
JMF 0:24d3eb812fd4 103 return true;
JMF 0:24d3eb812fd4 104 }
JMF 0:24d3eb812fd4 105 }
JMF 0:24d3eb812fd4 106 setTimeout();
JMF 0:24d3eb812fd4 107 _smutex.unlock();
JMF 0:24d3eb812fd4 108
JMF 0:24d3eb812fd4 109 return false;
JMF 0:24d3eb812fd4 110 }
JMF 0:24d3eb812fd4 111
JMF 0:24d3eb812fd4 112 bool ESP8266::dhcp(bool enabled, int mode)
JMF 0:24d3eb812fd4 113 {
JMF 0:24d3eb812fd4 114 //only 3 valid modes
JMF 0:24d3eb812fd4 115 if (mode < 0 || mode > 2) {
JMF 0:24d3eb812fd4 116 return false;
JMF 0:24d3eb812fd4 117 }
JMF 0:24d3eb812fd4 118
JMF 0:24d3eb812fd4 119 _smutex.lock();
JMF 0:24d3eb812fd4 120 bool done = _parser.send("AT+CWDHCP_CUR=%d,%d", mode, enabled?1:0)
JMF 0:24d3eb812fd4 121 && _parser.recv("OK\n");
JMF 0:24d3eb812fd4 122 _smutex.unlock();
JMF 0:24d3eb812fd4 123
JMF 0:24d3eb812fd4 124 return done;
JMF 0:24d3eb812fd4 125 }
JMF 0:24d3eb812fd4 126
JMF 0:24d3eb812fd4 127 nsapi_error_t ESP8266::connect(const char *ap, const char *passPhrase)
JMF 0:24d3eb812fd4 128 {
JMF 0:24d3eb812fd4 129 _smutex.lock();
JMF 0:24d3eb812fd4 130 setTimeout(ESP8266_CONNECT_TIMEOUT);
JMF 0:24d3eb812fd4 131 _connection_status = NSAPI_STATUS_CONNECTING;
JMF 0:24d3eb812fd4 132 if(_connection_status_cb)
JMF 0:24d3eb812fd4 133 _connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connection_status);
JMF 0:24d3eb812fd4 134
JMF 0:24d3eb812fd4 135 _parser.send("AT+CWJAP_CUR=\"%s\",\"%s\"", ap, passPhrase);
JMF 0:24d3eb812fd4 136 if (!_parser.recv("OK\n")) {
JMF 0:24d3eb812fd4 137 if (_fail) {
JMF 0:24d3eb812fd4 138 _smutex.unlock();
JMF 0:24d3eb812fd4 139 nsapi_error_t ret;
JMF 0:24d3eb812fd4 140 if (_connect_error == 1)
JMF 0:24d3eb812fd4 141 ret = NSAPI_ERROR_CONNECTION_TIMEOUT;
JMF 0:24d3eb812fd4 142 else if (_connect_error == 2)
JMF 0:24d3eb812fd4 143 ret = NSAPI_ERROR_AUTH_FAILURE;
JMF 0:24d3eb812fd4 144 else if (_connect_error == 3)
JMF 0:24d3eb812fd4 145 ret = NSAPI_ERROR_NO_SSID;
JMF 0:24d3eb812fd4 146 else
JMF 0:24d3eb812fd4 147 ret = NSAPI_ERROR_NO_CONNECTION;
JMF 0:24d3eb812fd4 148
JMF 0:24d3eb812fd4 149 _fail = false;
JMF 0:24d3eb812fd4 150 _connect_error = 0;
JMF 0:24d3eb812fd4 151 return ret;
JMF 0:24d3eb812fd4 152 }
JMF 0:24d3eb812fd4 153 }
JMF 0:24d3eb812fd4 154 setTimeout();
JMF 0:24d3eb812fd4 155 _smutex.unlock();
JMF 0:24d3eb812fd4 156
JMF 0:24d3eb812fd4 157 return NSAPI_ERROR_OK;
JMF 0:24d3eb812fd4 158 }
JMF 0:24d3eb812fd4 159
JMF 0:24d3eb812fd4 160 bool ESP8266::disconnect(void)
JMF 0:24d3eb812fd4 161 {
JMF 0:24d3eb812fd4 162 _smutex.lock();
JMF 0:24d3eb812fd4 163 bool done = _parser.send("AT+CWQAP") && _parser.recv("OK\n");
JMF 0:24d3eb812fd4 164 _smutex.unlock();
JMF 0:24d3eb812fd4 165
JMF 0:24d3eb812fd4 166 return done;
JMF 0:24d3eb812fd4 167 }
JMF 0:24d3eb812fd4 168
JMF 0:24d3eb812fd4 169 const char *ESP8266::getIPAddress(void)
JMF 0:24d3eb812fd4 170 {
JMF 0:24d3eb812fd4 171 _smutex.lock();
JMF 0:24d3eb812fd4 172 setTimeout(ESP8266_CONNECT_TIMEOUT);
JMF 0:24d3eb812fd4 173 if (!(_parser.send("AT+CIFSR")
JMF 0:24d3eb812fd4 174 && _parser.recv("+CIFSR:STAIP,\"%15[^\"]\"", _ip_buffer)
JMF 0:24d3eb812fd4 175 && _parser.recv("OK\n"))) {
JMF 0:24d3eb812fd4 176 _smutex.unlock();
JMF 0:24d3eb812fd4 177 return 0;
JMF 0:24d3eb812fd4 178 }
JMF 0:24d3eb812fd4 179 setTimeout();
JMF 0:24d3eb812fd4 180 _smutex.unlock();
JMF 0:24d3eb812fd4 181
JMF 0:24d3eb812fd4 182 return _ip_buffer;
JMF 0:24d3eb812fd4 183 }
JMF 0:24d3eb812fd4 184
JMF 0:24d3eb812fd4 185 const char *ESP8266::getMACAddress(void)
JMF 0:24d3eb812fd4 186 {
JMF 0:24d3eb812fd4 187 _smutex.lock();
JMF 0:24d3eb812fd4 188 if (!(_parser.send("AT+CIFSR")
JMF 0:24d3eb812fd4 189 && _parser.recv("+CIFSR:STAMAC,\"%17[^\"]\"", _mac_buffer)
JMF 0:24d3eb812fd4 190 && _parser.recv("OK\n"))) {
JMF 0:24d3eb812fd4 191 _smutex.unlock();
JMF 0:24d3eb812fd4 192 return 0;
JMF 0:24d3eb812fd4 193 }
JMF 0:24d3eb812fd4 194 _smutex.unlock();
JMF 0:24d3eb812fd4 195
JMF 0:24d3eb812fd4 196 return _mac_buffer;
JMF 0:24d3eb812fd4 197 }
JMF 0:24d3eb812fd4 198
JMF 0:24d3eb812fd4 199 const char *ESP8266::getGateway()
JMF 0:24d3eb812fd4 200 {
JMF 0:24d3eb812fd4 201 _smutex.lock();
JMF 0:24d3eb812fd4 202 if (!(_parser.send("AT+CIPSTA_CUR?")
JMF 0:24d3eb812fd4 203 && _parser.recv("+CIPSTA_CUR:gateway:\"%15[^\"]\"", _gateway_buffer)
JMF 0:24d3eb812fd4 204 && _parser.recv("OK\n"))) {
JMF 0:24d3eb812fd4 205 _smutex.unlock();
JMF 0:24d3eb812fd4 206 return 0;
JMF 0:24d3eb812fd4 207 }
JMF 0:24d3eb812fd4 208 _smutex.unlock();
JMF 0:24d3eb812fd4 209
JMF 0:24d3eb812fd4 210 return _gateway_buffer;
JMF 0:24d3eb812fd4 211 }
JMF 0:24d3eb812fd4 212
JMF 0:24d3eb812fd4 213 const char *ESP8266::getNetmask()
JMF 0:24d3eb812fd4 214 {
JMF 0:24d3eb812fd4 215 _smutex.lock();
JMF 0:24d3eb812fd4 216 if (!(_parser.send("AT+CIPSTA_CUR?")
JMF 0:24d3eb812fd4 217 && _parser.recv("+CIPSTA_CUR:netmask:\"%15[^\"]\"", _netmask_buffer)
JMF 0:24d3eb812fd4 218 && _parser.recv("OK\n"))) {
JMF 0:24d3eb812fd4 219 _smutex.unlock();
JMF 0:24d3eb812fd4 220 return 0;
JMF 0:24d3eb812fd4 221 }
JMF 0:24d3eb812fd4 222 _smutex.unlock();
JMF 0:24d3eb812fd4 223
JMF 0:24d3eb812fd4 224 return _netmask_buffer;
JMF 0:24d3eb812fd4 225 }
JMF 0:24d3eb812fd4 226
JMF 0:24d3eb812fd4 227 int8_t ESP8266::getRSSI()
JMF 0:24d3eb812fd4 228 {
JMF 0:24d3eb812fd4 229 int8_t rssi;
JMF 0:24d3eb812fd4 230 char bssid[18];
JMF 0:24d3eb812fd4 231
JMF 0:24d3eb812fd4 232 _smutex.lock();
JMF 0:24d3eb812fd4 233 setTimeout(ESP8266_CONNECT_TIMEOUT);
JMF 0:24d3eb812fd4 234 if (!(_parser.send("AT+CWJAP_CUR?")
JMF 0:24d3eb812fd4 235 && _parser.recv("+CWJAP_CUR:\"%*[^\"]\",\"%17[^\"]\"", bssid)
JMF 0:24d3eb812fd4 236 && _parser.recv("OK\n"))) {
JMF 0:24d3eb812fd4 237 _smutex.unlock();
JMF 0:24d3eb812fd4 238 return 0;
JMF 0:24d3eb812fd4 239 }
JMF 0:24d3eb812fd4 240 setTimeout();
JMF 0:24d3eb812fd4 241 _smutex.unlock();
JMF 0:24d3eb812fd4 242
JMF 0:24d3eb812fd4 243 _smutex.lock();
JMF 0:24d3eb812fd4 244 setTimeout(ESP8266_CONNECT_TIMEOUT);
JMF 0:24d3eb812fd4 245 if (!(_parser.send("AT+CWLAP=\"\",\"%s\",", bssid)
JMF 0:24d3eb812fd4 246 && _parser.recv("+CWLAP:(%*d,\"%*[^\"]\",%hhd,", &rssi)
JMF 0:24d3eb812fd4 247 && _parser.recv("OK\n"))) {
JMF 0:24d3eb812fd4 248 _smutex.unlock();
JMF 0:24d3eb812fd4 249 return 0;
JMF 0:24d3eb812fd4 250 }
JMF 0:24d3eb812fd4 251 setTimeout();
JMF 0:24d3eb812fd4 252 _smutex.unlock();
JMF 0:24d3eb812fd4 253
JMF 0:24d3eb812fd4 254 return rssi;
JMF 0:24d3eb812fd4 255 }
JMF 0:24d3eb812fd4 256
JMF 0:24d3eb812fd4 257 int ESP8266::scan(WiFiAccessPoint *res, unsigned limit)
JMF 0:24d3eb812fd4 258 {
JMF 0:24d3eb812fd4 259 unsigned cnt = 0;
JMF 0:24d3eb812fd4 260 nsapi_wifi_ap_t ap;
JMF 0:24d3eb812fd4 261
JMF 0:24d3eb812fd4 262 _smutex.lock();
JMF 0:24d3eb812fd4 263 setTimeout(ESP8266_CONNECT_TIMEOUT);
JMF 0:24d3eb812fd4 264
JMF 0:24d3eb812fd4 265 if (!_parser.send("AT+CWLAP")) {
JMF 0:24d3eb812fd4 266 _smutex.unlock();
JMF 0:24d3eb812fd4 267 return NSAPI_ERROR_DEVICE_ERROR;
JMF 0:24d3eb812fd4 268 }
JMF 0:24d3eb812fd4 269
JMF 0:24d3eb812fd4 270 while (recv_ap(&ap)) {
JMF 0:24d3eb812fd4 271 if (cnt < limit) {
JMF 0:24d3eb812fd4 272 res[cnt] = WiFiAccessPoint(ap);
JMF 0:24d3eb812fd4 273 }
JMF 0:24d3eb812fd4 274
JMF 0:24d3eb812fd4 275 cnt++;
JMF 0:24d3eb812fd4 276 if (limit != 0 && cnt >= limit) {
JMF 0:24d3eb812fd4 277 break;
JMF 0:24d3eb812fd4 278 }
JMF 0:24d3eb812fd4 279 }
JMF 0:24d3eb812fd4 280 setTimeout();
JMF 0:24d3eb812fd4 281 _smutex.unlock();
JMF 0:24d3eb812fd4 282
JMF 0:24d3eb812fd4 283 return cnt;
JMF 0:24d3eb812fd4 284 }
JMF 0:24d3eb812fd4 285
JMF 0:24d3eb812fd4 286 nsapi_error_t ESP8266::open_udp(int id, const char* addr, int port, int local_port)
JMF 0:24d3eb812fd4 287 {
JMF 0:24d3eb812fd4 288 static const char *type = "UDP";
JMF 0:24d3eb812fd4 289 bool done = false;
JMF 0:24d3eb812fd4 290
JMF 0:24d3eb812fd4 291 if (id >= SOCKET_COUNT) {
JMF 0:24d3eb812fd4 292 return NSAPI_ERROR_PARAMETER;
JMF 0:24d3eb812fd4 293 } else if (_socket_open[id]) {
JMF 0:24d3eb812fd4 294 return NSAPI_ERROR_IS_CONNECTED;
JMF 0:24d3eb812fd4 295 }
JMF 0:24d3eb812fd4 296
JMF 0:24d3eb812fd4 297 _smutex.lock();
JMF 0:24d3eb812fd4 298 if(local_port) {
JMF 0:24d3eb812fd4 299 done = _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d,%d", id, type, addr, port, local_port)
JMF 0:24d3eb812fd4 300 && _parser.recv("OK\n");
JMF 0:24d3eb812fd4 301 } else {
JMF 0:24d3eb812fd4 302 done = _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d", id, type, addr, port)
JMF 0:24d3eb812fd4 303 && _parser.recv("OK\n");
JMF 0:24d3eb812fd4 304 }
JMF 0:24d3eb812fd4 305
JMF 0:24d3eb812fd4 306 if (done) {
JMF 0:24d3eb812fd4 307 _socket_open[id] = 1;
JMF 0:24d3eb812fd4 308 }
JMF 0:24d3eb812fd4 309
JMF 0:24d3eb812fd4 310 _clear_socket_packets(id);
JMF 0:24d3eb812fd4 311
JMF 0:24d3eb812fd4 312 _smutex.unlock();
JMF 0:24d3eb812fd4 313
JMF 0:24d3eb812fd4 314 return done ? NSAPI_ERROR_OK : NSAPI_ERROR_DEVICE_ERROR;
JMF 0:24d3eb812fd4 315 }
JMF 0:24d3eb812fd4 316
JMF 0:24d3eb812fd4 317 bool ESP8266::open_tcp(int id, const char* addr, int port, int keepalive)
JMF 0:24d3eb812fd4 318 {
JMF 0:24d3eb812fd4 319 static const char *type = "TCP";
JMF 0:24d3eb812fd4 320 bool done = false;
JMF 0:24d3eb812fd4 321
JMF 0:24d3eb812fd4 322 if (id >= SOCKET_COUNT || _socket_open[id]) {
JMF 0:24d3eb812fd4 323 return false;
JMF 0:24d3eb812fd4 324 }
JMF 0:24d3eb812fd4 325
JMF 0:24d3eb812fd4 326 _smutex.lock();
JMF 0:24d3eb812fd4 327 if(keepalive) {
JMF 0:24d3eb812fd4 328 done = _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d,%d", id, type, addr, port, keepalive)
JMF 0:24d3eb812fd4 329 && _parser.recv("OK\n");
JMF 0:24d3eb812fd4 330 } else {
JMF 0:24d3eb812fd4 331 done = _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d", id, type, addr, port)
JMF 0:24d3eb812fd4 332 && _parser.recv("OK\n");
JMF 0:24d3eb812fd4 333 }
JMF 0:24d3eb812fd4 334
JMF 0:24d3eb812fd4 335 if (done) {
JMF 0:24d3eb812fd4 336 _socket_open[id] = 1;
JMF 0:24d3eb812fd4 337 }
JMF 0:24d3eb812fd4 338
JMF 0:24d3eb812fd4 339 _clear_socket_packets(id);
JMF 0:24d3eb812fd4 340
JMF 0:24d3eb812fd4 341 _smutex.unlock();
JMF 0:24d3eb812fd4 342
JMF 0:24d3eb812fd4 343 return done;
JMF 0:24d3eb812fd4 344 }
JMF 0:24d3eb812fd4 345
JMF 0:24d3eb812fd4 346 bool ESP8266::dns_lookup(const char* name, char* ip)
JMF 0:24d3eb812fd4 347 {
JMF 0:24d3eb812fd4 348 _smutex.lock();
JMF 0:24d3eb812fd4 349 bool done = _parser.send("AT+CIPDOMAIN=\"%s\"", name) && _parser.recv("+CIPDOMAIN:%s%*[\r]%*[\n]", ip);
JMF 0:24d3eb812fd4 350 _smutex.unlock();
JMF 0:24d3eb812fd4 351
JMF 0:24d3eb812fd4 352 return done;
JMF 0:24d3eb812fd4 353 }
JMF 0:24d3eb812fd4 354
JMF 0:24d3eb812fd4 355 nsapi_error_t ESP8266::send(int id, const void *data, uint32_t amount)
JMF 0:24d3eb812fd4 356 {
JMF 0:24d3eb812fd4 357 //May take a second try if device is busy
JMF 0:24d3eb812fd4 358 for (unsigned i = 0; i < 2; i++) {
JMF 0:24d3eb812fd4 359 _smutex.lock();
JMF 0:24d3eb812fd4 360 setTimeout(ESP8266_SEND_TIMEOUT);
JMF 0:24d3eb812fd4 361 if (_parser.send("AT+CIPSEND=%d,%lu", id, amount)
JMF 0:24d3eb812fd4 362 && _parser.recv(">")
JMF 0:24d3eb812fd4 363 && _parser.write((char*)data, (int)amount) >= 0) {
JMF 0:24d3eb812fd4 364 while (_parser.process_oob()); // multiple sends in a row require this
JMF 0:24d3eb812fd4 365 _smutex.unlock();
JMF 0:24d3eb812fd4 366 return NSAPI_ERROR_OK;
JMF 0:24d3eb812fd4 367 }
JMF 0:24d3eb812fd4 368 setTimeout();
JMF 0:24d3eb812fd4 369 _smutex.unlock();
JMF 0:24d3eb812fd4 370 }
JMF 0:24d3eb812fd4 371
JMF 0:24d3eb812fd4 372 return NSAPI_ERROR_DEVICE_ERROR;
JMF 0:24d3eb812fd4 373 }
JMF 0:24d3eb812fd4 374
JMF 0:24d3eb812fd4 375 void ESP8266::_packet_handler()
JMF 0:24d3eb812fd4 376 {
JMF 0:24d3eb812fd4 377 int id;
JMF 0:24d3eb812fd4 378 int amount;
JMF 0:24d3eb812fd4 379
JMF 0:24d3eb812fd4 380 // parse out the packet
JMF 0:24d3eb812fd4 381 if (!_parser.recv(",%d,%d:", &id, &amount)) {
JMF 0:24d3eb812fd4 382 return;
JMF 0:24d3eb812fd4 383 }
JMF 0:24d3eb812fd4 384
JMF 0:24d3eb812fd4 385 struct packet *packet = (struct packet*)malloc(
JMF 0:24d3eb812fd4 386 sizeof(struct packet) + amount);
JMF 0:24d3eb812fd4 387 if (!packet) {
JMF 0:24d3eb812fd4 388 debug("ESP8266: could not allocate memory for RX data\n");
JMF 0:24d3eb812fd4 389 return;
JMF 0:24d3eb812fd4 390 }
JMF 0:24d3eb812fd4 391
JMF 0:24d3eb812fd4 392 packet->id = id;
JMF 0:24d3eb812fd4 393 packet->len = amount;
JMF 0:24d3eb812fd4 394 packet->next = 0;
JMF 0:24d3eb812fd4 395
JMF 0:24d3eb812fd4 396 if (_parser.read((char*)(packet + 1), amount) < amount) {
JMF 0:24d3eb812fd4 397 free(packet);
JMF 0:24d3eb812fd4 398 return;
JMF 0:24d3eb812fd4 399 }
JMF 0:24d3eb812fd4 400
JMF 0:24d3eb812fd4 401 // append to packet list
JMF 0:24d3eb812fd4 402 *_packets_end = packet;
JMF 0:24d3eb812fd4 403 _packets_end = &packet->next;
JMF 0:24d3eb812fd4 404 }
JMF 0:24d3eb812fd4 405
JMF 0:24d3eb812fd4 406 int32_t ESP8266::recv_tcp(int id, void *data, uint32_t amount, uint32_t timeout)
JMF 0:24d3eb812fd4 407 {
JMF 0:24d3eb812fd4 408 _smutex.lock();
JMF 0:24d3eb812fd4 409 setTimeout(timeout);
JMF 0:24d3eb812fd4 410
JMF 0:24d3eb812fd4 411 // Poll for inbound packets
JMF 0:24d3eb812fd4 412 while (_parser.process_oob()) {
JMF 0:24d3eb812fd4 413 }
JMF 0:24d3eb812fd4 414
JMF 0:24d3eb812fd4 415 setTimeout();
JMF 0:24d3eb812fd4 416
JMF 0:24d3eb812fd4 417 // check if any packets are ready for us
JMF 0:24d3eb812fd4 418 for (struct packet **p = &_packets; *p; p = &(*p)->next) {
JMF 0:24d3eb812fd4 419 if ((*p)->id == id) {
JMF 0:24d3eb812fd4 420 struct packet *q = *p;
JMF 0:24d3eb812fd4 421
JMF 0:24d3eb812fd4 422 if (q->len <= amount) { // Return and remove full packet
JMF 0:24d3eb812fd4 423 memcpy(data, q+1, q->len);
JMF 0:24d3eb812fd4 424
JMF 0:24d3eb812fd4 425 if (_packets_end == &(*p)->next) {
JMF 0:24d3eb812fd4 426 _packets_end = p;
JMF 0:24d3eb812fd4 427 }
JMF 0:24d3eb812fd4 428 *p = (*p)->next;
JMF 0:24d3eb812fd4 429 _smutex.unlock();
JMF 0:24d3eb812fd4 430
JMF 0:24d3eb812fd4 431 uint32_t len = q->len;
JMF 0:24d3eb812fd4 432 free(q);
JMF 0:24d3eb812fd4 433 return len;
JMF 0:24d3eb812fd4 434 } else { // return only partial packet
JMF 0:24d3eb812fd4 435 memcpy(data, q+1, amount);
JMF 0:24d3eb812fd4 436
JMF 0:24d3eb812fd4 437 q->len -= amount;
JMF 0:24d3eb812fd4 438 memmove(q+1, (uint8_t*)(q+1) + amount, q->len);
JMF 0:24d3eb812fd4 439
JMF 0:24d3eb812fd4 440 _smutex.unlock();
JMF 0:24d3eb812fd4 441 return amount;
JMF 0:24d3eb812fd4 442 }
JMF 0:24d3eb812fd4 443 }
JMF 0:24d3eb812fd4 444 }
JMF 0:24d3eb812fd4 445 if(!_socket_open[id]) {
JMF 0:24d3eb812fd4 446 _smutex.unlock();
JMF 0:24d3eb812fd4 447 return 0;
JMF 0:24d3eb812fd4 448 }
JMF 0:24d3eb812fd4 449 _smutex.unlock();
JMF 0:24d3eb812fd4 450
JMF 0:24d3eb812fd4 451 return NSAPI_ERROR_WOULD_BLOCK;
JMF 0:24d3eb812fd4 452 }
JMF 0:24d3eb812fd4 453
JMF 0:24d3eb812fd4 454 int32_t ESP8266::recv_udp(int id, void *data, uint32_t amount, uint32_t timeout)
JMF 0:24d3eb812fd4 455 {
JMF 0:24d3eb812fd4 456 _smutex.lock();
JMF 0:24d3eb812fd4 457 setTimeout(timeout);
JMF 0:24d3eb812fd4 458
JMF 0:24d3eb812fd4 459 // Poll for inbound packets
JMF 0:24d3eb812fd4 460 while (_parser.process_oob()) {
JMF 0:24d3eb812fd4 461 }
JMF 0:24d3eb812fd4 462
JMF 0:24d3eb812fd4 463 setTimeout();
JMF 0:24d3eb812fd4 464
JMF 0:24d3eb812fd4 465 // check if any packets are ready for us
JMF 0:24d3eb812fd4 466 for (struct packet **p = &_packets; *p; p = &(*p)->next) {
JMF 0:24d3eb812fd4 467 if ((*p)->id == id) {
JMF 0:24d3eb812fd4 468 struct packet *q = *p;
JMF 0:24d3eb812fd4 469
JMF 0:24d3eb812fd4 470 // Return and remove packet (truncated if necessary)
JMF 0:24d3eb812fd4 471 uint32_t len = q->len < amount ? q->len : amount;
JMF 0:24d3eb812fd4 472 memcpy(data, q+1, len);
JMF 0:24d3eb812fd4 473
JMF 0:24d3eb812fd4 474 if (_packets_end == &(*p)->next) {
JMF 0:24d3eb812fd4 475 _packets_end = p;
JMF 0:24d3eb812fd4 476 }
JMF 0:24d3eb812fd4 477 *p = (*p)->next;
JMF 0:24d3eb812fd4 478 _smutex.unlock();
JMF 0:24d3eb812fd4 479
JMF 0:24d3eb812fd4 480 free(q);
JMF 0:24d3eb812fd4 481 return len;
JMF 0:24d3eb812fd4 482 }
JMF 0:24d3eb812fd4 483 }
JMF 0:24d3eb812fd4 484 _smutex.unlock();
JMF 0:24d3eb812fd4 485
JMF 0:24d3eb812fd4 486 return NSAPI_ERROR_WOULD_BLOCK;
JMF 0:24d3eb812fd4 487 }
JMF 0:24d3eb812fd4 488
JMF 0:24d3eb812fd4 489 void ESP8266::_clear_socket_packets(int id)
JMF 0:24d3eb812fd4 490 {
JMF 0:24d3eb812fd4 491 struct packet **p = &_packets;
JMF 0:24d3eb812fd4 492
JMF 0:24d3eb812fd4 493 while (*p) {
JMF 0:24d3eb812fd4 494 if ((*p)->id == id || id == ESP8266_ALL_SOCKET_IDS) {
JMF 0:24d3eb812fd4 495 struct packet *q = *p;
JMF 0:24d3eb812fd4 496
JMF 0:24d3eb812fd4 497 if (_packets_end == &(*p)->next) {
JMF 0:24d3eb812fd4 498 _packets_end = p; // Set last packet next field/_packets
JMF 0:24d3eb812fd4 499 }
JMF 0:24d3eb812fd4 500 *p = (*p)->next;
JMF 0:24d3eb812fd4 501
JMF 0:24d3eb812fd4 502 free(q);
JMF 0:24d3eb812fd4 503 } else {
JMF 0:24d3eb812fd4 504 // Point to last packet next field
JMF 0:24d3eb812fd4 505 p = &(*p)->next;
JMF 0:24d3eb812fd4 506 }
JMF 0:24d3eb812fd4 507 }
JMF 0:24d3eb812fd4 508 }
JMF 0:24d3eb812fd4 509
JMF 0:24d3eb812fd4 510 bool ESP8266::close(int id)
JMF 0:24d3eb812fd4 511 {
JMF 0:24d3eb812fd4 512 //May take a second try if device is busy
JMF 0:24d3eb812fd4 513 for (unsigned i = 0; i < 2; i++) {
JMF 0:24d3eb812fd4 514 _smutex.lock();
JMF 0:24d3eb812fd4 515 if (_parser.send("AT+CIPCLOSE=%d", id)) {
JMF 0:24d3eb812fd4 516 if (!_parser.recv("OK\n")) {
JMF 0:24d3eb812fd4 517 if (_closed) { // UNLINK ERROR
JMF 0:24d3eb812fd4 518 _closed = false;
JMF 0:24d3eb812fd4 519 _socket_open[id] = 0;
JMF 0:24d3eb812fd4 520 _clear_socket_packets(id);
JMF 0:24d3eb812fd4 521 _smutex.unlock();
JMF 0:24d3eb812fd4 522 // ESP8266 has a habit that it might close a socket on its own.
JMF 0:24d3eb812fd4 523 //debug("ESP8266: socket %d already closed when calling close\n", id);
JMF 0:24d3eb812fd4 524 return true;
JMF 0:24d3eb812fd4 525 }
JMF 0:24d3eb812fd4 526 } else {
JMF 0:24d3eb812fd4 527 _clear_socket_packets(id);
JMF 0:24d3eb812fd4 528 _smutex.unlock();
JMF 0:24d3eb812fd4 529 return true;
JMF 0:24d3eb812fd4 530 }
JMF 0:24d3eb812fd4 531 }
JMF 0:24d3eb812fd4 532 _smutex.unlock();
JMF 0:24d3eb812fd4 533 }
JMF 0:24d3eb812fd4 534
JMF 0:24d3eb812fd4 535 return false;
JMF 0:24d3eb812fd4 536 }
JMF 0:24d3eb812fd4 537
JMF 0:24d3eb812fd4 538 void ESP8266::setTimeout(uint32_t timeout_ms)
JMF 0:24d3eb812fd4 539 {
JMF 0:24d3eb812fd4 540 _parser.set_timeout(timeout_ms);
JMF 0:24d3eb812fd4 541 }
JMF 0:24d3eb812fd4 542
JMF 0:24d3eb812fd4 543 bool ESP8266::readable()
JMF 0:24d3eb812fd4 544 {
JMF 0:24d3eb812fd4 545 return _serial.FileHandle::readable();
JMF 0:24d3eb812fd4 546 }
JMF 0:24d3eb812fd4 547
JMF 0:24d3eb812fd4 548 bool ESP8266::writeable()
JMF 0:24d3eb812fd4 549 {
JMF 0:24d3eb812fd4 550 return _serial.FileHandle::writable();
JMF 0:24d3eb812fd4 551 }
JMF 0:24d3eb812fd4 552
JMF 0:24d3eb812fd4 553 void ESP8266::sigio(Callback<void()> func)
JMF 0:24d3eb812fd4 554 {
JMF 0:24d3eb812fd4 555 _serial.sigio(func);
JMF 0:24d3eb812fd4 556 }
JMF 0:24d3eb812fd4 557
JMF 0:24d3eb812fd4 558 void ESP8266::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
JMF 0:24d3eb812fd4 559 {
JMF 0:24d3eb812fd4 560 _connection_status_cb = status_cb;
JMF 0:24d3eb812fd4 561 }
JMF 0:24d3eb812fd4 562
JMF 0:24d3eb812fd4 563 bool ESP8266::recv_ap(nsapi_wifi_ap_t *ap)
JMF 0:24d3eb812fd4 564 {
JMF 0:24d3eb812fd4 565 int sec;
JMF 0:24d3eb812fd4 566 int dummy;
JMF 0:24d3eb812fd4 567 bool ret = _parser.recv("+CWLAP:(%d,\"%32[^\"]\",%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\",%hhu,%d,%d)\n",
JMF 0:24d3eb812fd4 568 &sec,
JMF 0:24d3eb812fd4 569 ap->ssid,
JMF 0:24d3eb812fd4 570 &ap->rssi,
JMF 0:24d3eb812fd4 571 &ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4], &ap->bssid[5],
JMF 0:24d3eb812fd4 572 &ap->channel,
JMF 0:24d3eb812fd4 573 &dummy,
JMF 0:24d3eb812fd4 574 &dummy);
JMF 0:24d3eb812fd4 575
JMF 0:24d3eb812fd4 576 ap->security = sec < 5 ? (nsapi_security_t)sec : NSAPI_SECURITY_UNKNOWN;
JMF 0:24d3eb812fd4 577
JMF 0:24d3eb812fd4 578 return ret;
JMF 0:24d3eb812fd4 579 }
JMF 0:24d3eb812fd4 580
JMF 0:24d3eb812fd4 581 void ESP8266::_connect_error_handler()
JMF 0:24d3eb812fd4 582 {
JMF 0:24d3eb812fd4 583 _fail = false;
JMF 0:24d3eb812fd4 584 _connect_error = 0;
JMF 0:24d3eb812fd4 585
JMF 0:24d3eb812fd4 586 if (_parser.recv("%d", &_connect_error) && _parser.recv("FAIL")) {
JMF 0:24d3eb812fd4 587 _fail = true;
JMF 0:24d3eb812fd4 588 _parser.abort();
JMF 0:24d3eb812fd4 589 }
JMF 0:24d3eb812fd4 590 }
JMF 0:24d3eb812fd4 591
JMF 0:24d3eb812fd4 592 void ESP8266::_oob_socket_close_error()
JMF 0:24d3eb812fd4 593 {
JMF 0:24d3eb812fd4 594 if (_parser.recv("ERROR\n")) {
JMF 0:24d3eb812fd4 595 _closed = true; // Not possible to pinpoint to a certain socket
JMF 0:24d3eb812fd4 596 _parser.abort();
JMF 0:24d3eb812fd4 597 }
JMF 0:24d3eb812fd4 598 }
JMF 0:24d3eb812fd4 599
JMF 0:24d3eb812fd4 600 void ESP8266::_oob_socket0_closed_handler()
JMF 0:24d3eb812fd4 601 {
JMF 0:24d3eb812fd4 602 _socket_open[0] = 0;
JMF 0:24d3eb812fd4 603 }
JMF 0:24d3eb812fd4 604
JMF 0:24d3eb812fd4 605 void ESP8266::_oob_socket1_closed_handler()
JMF 0:24d3eb812fd4 606 {
JMF 0:24d3eb812fd4 607 _socket_open[1] = 0;
JMF 0:24d3eb812fd4 608 }
JMF 0:24d3eb812fd4 609
JMF 0:24d3eb812fd4 610 void ESP8266::_oob_socket2_closed_handler()
JMF 0:24d3eb812fd4 611 {
JMF 0:24d3eb812fd4 612 _socket_open[2] = 0;
JMF 0:24d3eb812fd4 613 }
JMF 0:24d3eb812fd4 614
JMF 0:24d3eb812fd4 615 void ESP8266::_oob_socket3_closed_handler()
JMF 0:24d3eb812fd4 616 {
JMF 0:24d3eb812fd4 617 _socket_open[3] = 0;
JMF 0:24d3eb812fd4 618 }
JMF 0:24d3eb812fd4 619
JMF 0:24d3eb812fd4 620 void ESP8266::_oob_socket4_closed_handler()
JMF 0:24d3eb812fd4 621 {
JMF 0:24d3eb812fd4 622 _socket_open[4] = 0;
JMF 0:24d3eb812fd4 623 }
JMF 0:24d3eb812fd4 624
JMF 0:24d3eb812fd4 625 void ESP8266::_connection_status_handler()
JMF 0:24d3eb812fd4 626 {
JMF 0:24d3eb812fd4 627 char status[13];
JMF 0:24d3eb812fd4 628 if (_parser.recv("%12[^\"]\n", status)) {
JMF 0:24d3eb812fd4 629 if (strcmp(status, "GOT IP\n") == 0)
JMF 0:24d3eb812fd4 630 _connection_status = NSAPI_STATUS_GLOBAL_UP;
JMF 0:24d3eb812fd4 631 else if (strcmp(status, "DISCONNECT\n") == 0)
JMF 0:24d3eb812fd4 632 _connection_status = NSAPI_STATUS_DISCONNECTED;
JMF 0:24d3eb812fd4 633 else
JMF 0:24d3eb812fd4 634 return;
JMF 0:24d3eb812fd4 635
JMF 0:24d3eb812fd4 636 if(_connection_status_cb)
JMF 0:24d3eb812fd4 637 _connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connection_status);
JMF 0:24d3eb812fd4 638 }
JMF 0:24d3eb812fd4 639 }
JMF 0:24d3eb812fd4 640
JMF 0:24d3eb812fd4 641 int8_t ESP8266::get_default_wifi_mode()
JMF 0:24d3eb812fd4 642 {
JMF 0:24d3eb812fd4 643 int8_t mode;
JMF 0:24d3eb812fd4 644
JMF 0:24d3eb812fd4 645 _smutex.lock();
JMF 0:24d3eb812fd4 646 if (_parser.send("AT+CWMODE_DEF?")
JMF 0:24d3eb812fd4 647 && _parser.recv("+CWMODE_DEF:%hhd", &mode)
JMF 0:24d3eb812fd4 648 && _parser.recv("OK\n")) {
JMF 0:24d3eb812fd4 649 _smutex.unlock();
JMF 0:24d3eb812fd4 650 return mode;
JMF 0:24d3eb812fd4 651 }
JMF 0:24d3eb812fd4 652 _smutex.unlock();
JMF 0:24d3eb812fd4 653
JMF 0:24d3eb812fd4 654 return 0;
JMF 0:24d3eb812fd4 655 }
JMF 0:24d3eb812fd4 656
JMF 0:24d3eb812fd4 657 bool ESP8266::set_default_wifi_mode(const int8_t mode)
JMF 0:24d3eb812fd4 658 {
JMF 0:24d3eb812fd4 659 _smutex.lock();
JMF 0:24d3eb812fd4 660 bool done = _parser.send("AT+CWMODE_DEF=%hhd", mode)
JMF 0:24d3eb812fd4 661 && _parser.recv("OK\n");
JMF 0:24d3eb812fd4 662 _smutex.unlock();
JMF 0:24d3eb812fd4 663
JMF 0:24d3eb812fd4 664 return done;
JMF 0:24d3eb812fd4 665 }
JMF 0:24d3eb812fd4 666
JMF 0:24d3eb812fd4 667 nsapi_connection_status_t ESP8266::get_connection_status() const
JMF 0:24d3eb812fd4 668 {
JMF 0:24d3eb812fd4 669 return _connection_status;
JMF 0:24d3eb812fd4 670 }