RTC auf true

Committer:
kevman
Date:
Wed Mar 13 11:03:24 2019 +0000
Revision:
2:7aab896b1a3b
2019-03-13

Who changed what in which revision?

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