ESP8266 Socket Library. AT Thinker firmware.

Dependents:   ESP8266_MQTT_HelloWorld ESP8266_IFTTT_Test ECE_4180_Lab_4 websocketmbed ... more

Fork of ESP8266Interface by ESP8266

This repository has been superceded

This project has moved to https://developer.mbed.org/teams/ESP8266/code/esp8266-driver/

This library works with the AT Thinker firmware.

Note

This library is currently in Beta. It is not feature complete and has some bugs, proceed with caution! Fixes and patches are welcome and appreciated!

Currently the ESP8266Interface Library has the following Abilities:

Working

  • TCP Client
  • UDP Client
  • Transparent mode (single connection of 1 type at a time)
  • Station Mode (connects to AP)

To be implemented

  • TCP Server
  • UDP Server
  • Multi Connection Mode (able to have up to 5 sockets at a time)
  • AP Mode (Make ESP Chip act like access point)
  • DNS Support (currently websites must be looked up by IP)
  • Error Recovery

Nice but not necessary

  • colorized text for ESP AT Commands in Command line (easier to differentiate from other text)
Committer:
michaeljkoster
Date:
Mon Dec 01 08:25:23 2014 +0000
Revision:
18:60422852e99c
Parent:
17:d11fa4c3ac65
Child:
19:fb8d5bff2076
sending stuff

Who changed what in which revision?

UserRevisionLine numberNew contents of line
samux 1:fb4494783863 1 /* Copyright (C) 2012 mbed.org, MIT License
samux 1:fb4494783863 2 *
samux 1:fb4494783863 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
samux 1:fb4494783863 4 * and associated documentation files (the "Software"), to deal in the Software without restriction,
samux 1:fb4494783863 5 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
samux 1:fb4494783863 6 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
samux 1:fb4494783863 7 * furnished to do so, subject to the following conditions:
samux 1:fb4494783863 8 *
samux 1:fb4494783863 9 * The above copyright notice and this permission notice shall be included in all copies or
samux 1:fb4494783863 10 * substantial portions of the Software.
samux 1:fb4494783863 11 *
samux 1:fb4494783863 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
samux 1:fb4494783863 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
samux 1:fb4494783863 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
samux 1:fb4494783863 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
samux 1:fb4494783863 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
samux 1:fb4494783863 17 */
samux 1:fb4494783863 18
samux 1:fb4494783863 19 #include "mbed.h"
michaeljkoster 13:41098c907200 20 #include "ESP8266.h"
michaeljkoster 16:3f0efaa57a12 21 #include "Endpoint.h"
samux 1:fb4494783863 22 #include <string>
samux 1:fb4494783863 23 #include <algorithm>
samux 1:fb4494783863 24
samux 1:fb4494783863 25 //Debug is disabled by default
screamer 10:131675c17372 26 #if (defined(DEBUG))
michaeljkoster 13:41098c907200 27 #define DBG(x, ...) std::printf("[ESP8266 : DBG]"x"\r\n", ##__VA_ARGS__);
michaeljkoster 13:41098c907200 28 #define WARN(x, ...) std::printf("[ESP8266 : WARN]"x"\r\n", ##__VA_ARGS__);
michaeljkoster 13:41098c907200 29 #define ERR(x, ...) std::printf("[ESP8266 : ERR]"x"\r\n", ##__VA_ARGS__);
samux 1:fb4494783863 30 #else
samux 1:fb4494783863 31 #define DBG(x, ...)
samux 1:fb4494783863 32 #define WARN(x, ...)
samux 1:fb4494783863 33 #define ERR(x, ...)
samux 1:fb4494783863 34 #endif
samux 1:fb4494783863 35
screamer 10:131675c17372 36 #if defined(DEBUG)
michaeljkoster 13:41098c907200 37 #define INFO(x, ...) printf("[ESP8266 : INFO]"x"\r\n", ##__VA_ARGS__);
samux 1:fb4494783863 38 #else
samux 1:fb4494783863 39 #define INFO(x, ...)
samux 1:fb4494783863 40 #endif
samux 1:fb4494783863 41
samux 1:fb4494783863 42 #define MAX_TRY_JOIN 3
samux 1:fb4494783863 43
michaeljkoster 12:c5f0eac67a8a 44 extern Serial pc;
michaeljkoster 12:c5f0eac67a8a 45
michaeljkoster 13:41098c907200 46 ESP8266 * ESP8266::inst;
samux 1:fb4494783863 47
michaeljkoster 13:41098c907200 48 ESP8266::ESP8266( PinName tx, PinName rx, PinName _reset, const char * ssid, const char * phrase ):
michaeljkoster 13:41098c907200 49 wifi(tx, rx), reset_pin(_reset), buf_ESP8266(256)
samux 1:fb4494783863 50 {
samux 1:fb4494783863 51 memset(&state, 0, sizeof(state));
samux 1:fb4494783863 52
samux 1:fb4494783863 53 // change all ' ' in '$' in the ssid and the passphrase
samux 1:fb4494783863 54 strcpy(this->ssid, ssid);
samux 1:fb4494783863 55 for (int i = 0; i < strlen(ssid); i++) {
samux 1:fb4494783863 56 if (this->ssid[i] == ' ')
samux 1:fb4494783863 57 this->ssid[i] = '$';
samux 1:fb4494783863 58 }
samux 1:fb4494783863 59 strcpy(this->phrase, phrase);
samux 1:fb4494783863 60 for (int i = 0; i < strlen(phrase); i++) {
samux 1:fb4494783863 61 if (this->phrase[i] == ' ')
samux 1:fb4494783863 62 this->phrase[i] = '$';
samux 1:fb4494783863 63 }
samux 1:fb4494783863 64
samux 1:fb4494783863 65 inst = this;
samux 1:fb4494783863 66 attach_rx(false);
michaeljkoster 16:3f0efaa57a12 67
michaeljkoster 16:3f0efaa57a12 68 wifi.baud(9600); // initial baud rate of the ESP8266
michaeljkoster 16:3f0efaa57a12 69 pc.printf("ESP8266 test\r\n");
samux 1:fb4494783863 70 }
samux 1:fb4494783863 71
michaeljkoster 13:41098c907200 72 bool ESP8266::join()
samux 1:fb4494783863 73 {
michaeljkoster 16:3f0efaa57a12 74 string cmd="AT+CWJAP=\""+(string)this->ssid+"\",\""+(string)this->phrase+"\"";
michaeljkoster 16:3f0efaa57a12 75 if( sendCommand( cmd.c_str(), "OK", NULL, 10000) ){
michaeljkoster 16:3f0efaa57a12 76 // successfully joined the network
samux 1:fb4494783863 77 state.associated = true;
michaeljkoster 13:41098c907200 78 INFO("\r\nssid: %s\r\nphrase: %s\r\nsecurity: %s\r\n\r\n", this->ssid, this->phrase);
samux 1:fb4494783863 79 return true;
samux 1:fb4494783863 80 }
samux 1:fb4494783863 81 return false;
samux 1:fb4494783863 82 }
samux 1:fb4494783863 83
michaeljkoster 13:41098c907200 84 bool ESP8266::connect()
samux 1:fb4494783863 85 {
michaeljkoster 16:3f0efaa57a12 86 return true;
samux 1:fb4494783863 87 }
samux 1:fb4494783863 88
michaeljkoster 15:37a7a56a424f 89 bool ESP8266::is_connected()
michaeljkoster 15:37a7a56a424f 90 {
michaeljkoster 15:37a7a56a424f 91 return true;
michaeljkoster 15:37a7a56a424f 92 }
michaeljkoster 15:37a7a56a424f 93
michaeljkoster 16:3f0efaa57a12 94 bool ESP8266::startUDP(char* ip, int port){
michaeljkoster 17:d11fa4c3ac65 95 char portstr[5];
michaeljkoster 16:3f0efaa57a12 96 sprintf(portstr, "%d", port);
michaeljkoster 18:60422852e99c 97 sendCommand(( "AT+CIPSTART=\"UDP\",\"" + (string) ip + "\"," + (string) portstr ).c_str(), "OK", NULL, 10000);
michaeljkoster 16:3f0efaa57a12 98
michaeljkoster 17:d11fa4c3ac65 99 sendCommand("AT+CIPMODE=1", "OK", NULL, 1000);// go into transparent mode
michaeljkoster 17:d11fa4c3ac65 100 sendCommand("AT+CIPSEND", ">", NULL, 1000);// go into transparent mode
michaeljkoster 16:3f0efaa57a12 101
michaeljkoster 16:3f0efaa57a12 102 return true;
michaeljkoster 16:3f0efaa57a12 103 }
michaeljkoster 16:3f0efaa57a12 104
michaeljkoster 15:37a7a56a424f 105 bool ESP8266::close()
michaeljkoster 15:37a7a56a424f 106 {
michaeljkoster 17:d11fa4c3ac65 107 send("+++",3);
michaeljkoster 17:d11fa4c3ac65 108 wait(1);
michaeljkoster 16:3f0efaa57a12 109 sendCommand("AT+CIPCLOSE","OK", NULL, 10000);
michaeljkoster 15:37a7a56a424f 110 return true;
michaeljkoster 15:37a7a56a424f 111 }
michaeljkoster 15:37a7a56a424f 112
michaeljkoster 15:37a7a56a424f 113 bool ESP8266::disconnect()
michaeljkoster 15:37a7a56a424f 114 {
michaeljkoster 15:37a7a56a424f 115 // if already disconnected, return
michaeljkoster 15:37a7a56a424f 116 if (!state.associated)
michaeljkoster 15:37a7a56a424f 117 return true;
michaeljkoster 15:37a7a56a424f 118 // send command to quit AP
michaeljkoster 16:3f0efaa57a12 119 sendCommand("AT+CWQAP", "OK", NULL, 10000);
michaeljkoster 15:37a7a56a424f 120 state.associated = false;
michaeljkoster 15:37a7a56a424f 121 return true;
michaeljkoster 15:37a7a56a424f 122 }
michaeljkoster 15:37a7a56a424f 123
michaeljkoster 15:37a7a56a424f 124 char* ESP8266::getIPAddress()
michaeljkoster 15:37a7a56a424f 125 {
michaeljkoster 16:3f0efaa57a12 126 sendCommand("AT+CWLIF", "OK", NULL, 10000);
michaeljkoster 15:37a7a56a424f 127 return ipString;
michaeljkoster 15:37a7a56a424f 128 }
michaeljkoster 15:37a7a56a424f 129
michaeljkoster 13:41098c907200 130 bool ESP8266::gethostbyname(const char * host, char * ip)
samux 1:fb4494783863 131 {
samux 1:fb4494783863 132 string h = host;
samux 1:fb4494783863 133 int nb_digits = 0;
samux 1:fb4494783863 134
samux 1:fb4494783863 135 // no dns needed
samux 1:fb4494783863 136 int pos = h.find(".");
samux 1:fb4494783863 137 if (pos != string::npos) {
samux 1:fb4494783863 138 string sub = h.substr(0, h.find("."));
samux 1:fb4494783863 139 nb_digits = atoi(sub.c_str());
samux 1:fb4494783863 140 }
samux 1:fb4494783863 141 //printf("substrL %s\r\n", sub.c_str());
samux 1:fb4494783863 142 if (count(h.begin(), h.end(), '.') == 3 && nb_digits > 0) {
samux 1:fb4494783863 143 strcpy(ip, host);
michaeljkoster 13:41098c907200 144 return true;
samux 1:fb4494783863 145 }
samux 1:fb4494783863 146 else {
michaeljkoster 13:41098c907200 147 // dns needed, not currently available
michaeljkoster 13:41098c907200 148 return false;
michaeljkoster 13:41098c907200 149 }
michaeljkoster 13:41098c907200 150 }
samux 1:fb4494783863 151
michaeljkoster 13:41098c907200 152 void ESP8266::reset()
samux 1:fb4494783863 153 {
michaeljkoster 16:3f0efaa57a12 154 sendCommand("AT+RST", "ready", NULL, 10000);
michaeljkoster 16:3f0efaa57a12 155 /*
samux 1:fb4494783863 156 reset_pin = 0;
samux 1:fb4494783863 157 wait(0.2);
samux 1:fb4494783863 158 reset_pin = 1;
samux 1:fb4494783863 159 wait(0.2);
michaeljkoster 16:3f0efaa57a12 160 */
samux 1:fb4494783863 161 }
samux 1:fb4494783863 162
michaeljkoster 13:41098c907200 163 bool ESP8266::reboot()
samux 3:9aa05e19c62e 164 {
michaeljkoster 16:3f0efaa57a12 165 reset();
samux 3:9aa05e19c62e 166 return true;
samux 3:9aa05e19c62e 167 }
samux 3:9aa05e19c62e 168
michaeljkoster 15:37a7a56a424f 169 void ESP8266::handler_rx(void)
samux 1:fb4494783863 170 {
michaeljkoster 15:37a7a56a424f 171 //read characters
michaeljkoster 16:3f0efaa57a12 172 char c;
michaeljkoster 16:3f0efaa57a12 173 while (wifi.readable()){
michaeljkoster 16:3f0efaa57a12 174 c=wifi.getc();
michaeljkoster 16:3f0efaa57a12 175 buf_ESP8266.queue(c);
michaeljkoster 17:d11fa4c3ac65 176 pc.printf("%c",c);
michaeljkoster 16:3f0efaa57a12 177 }
michaeljkoster 15:37a7a56a424f 178 }
michaeljkoster 15:37a7a56a424f 179
michaeljkoster 15:37a7a56a424f 180 void ESP8266::attach_rx(bool callback)
michaeljkoster 15:37a7a56a424f 181 {
michaeljkoster 15:37a7a56a424f 182 if (!callback)
michaeljkoster 15:37a7a56a424f 183 wifi.attach(NULL);
michaeljkoster 15:37a7a56a424f 184 else
michaeljkoster 15:37a7a56a424f 185 wifi.attach(this, &ESP8266::handler_rx);
samux 1:fb4494783863 186 }
samux 1:fb4494783863 187
michaeljkoster 13:41098c907200 188 int ESP8266::readable()
samux 1:fb4494783863 189 {
michaeljkoster 13:41098c907200 190 return buf_ESP8266.available();
samux 1:fb4494783863 191 }
samux 1:fb4494783863 192
michaeljkoster 13:41098c907200 193 int ESP8266::writeable()
samux 1:fb4494783863 194 {
samux 1:fb4494783863 195 return wifi.writeable();
samux 1:fb4494783863 196 }
samux 1:fb4494783863 197
michaeljkoster 13:41098c907200 198 char ESP8266::getc()
samux 1:fb4494783863 199 {
michaeljkoster 14:4d1128f72e00 200 char c=0;
michaeljkoster 13:41098c907200 201 while (!buf_ESP8266.available());
michaeljkoster 13:41098c907200 202 buf_ESP8266.dequeue(&c);
samux 1:fb4494783863 203 return c;
samux 1:fb4494783863 204 }
samux 1:fb4494783863 205
michaeljkoster 15:37a7a56a424f 206 int ESP8266::putc(char c)
samux 1:fb4494783863 207 {
michaeljkoster 17:d11fa4c3ac65 208 while (!wifi.writeable() || wifi.readable());
michaeljkoster 15:37a7a56a424f 209 return wifi.putc(c);
samux 1:fb4494783863 210 }
samux 1:fb4494783863 211
michaeljkoster 15:37a7a56a424f 212 void ESP8266::flush()
samux 1:fb4494783863 213 {
michaeljkoster 15:37a7a56a424f 214 buf_ESP8266.flush();
samux 1:fb4494783863 215 }
samux 1:fb4494783863 216
michaeljkoster 16:3f0efaa57a12 217 int ESP8266::send(const char * buf, int len)
michaeljkoster 15:37a7a56a424f 218 {
michaeljkoster 18:60422852e99c 219
michaeljkoster 16:3f0efaa57a12 220 const char* bufptr=buf;
michaeljkoster 16:3f0efaa57a12 221 for(int i=0; i<len; i++){
michaeljkoster 17:d11fa4c3ac65 222 putc((int)*bufptr++);
michaeljkoster 18:60422852e99c 223 wait(.005);
michaeljkoster 18:60422852e99c 224 }
michaeljkoster 18:60422852e99c 225 return true;
michaeljkoster 15:37a7a56a424f 226 }
samux 1:fb4494783863 227
michaeljkoster 16:3f0efaa57a12 228 bool ESP8266::sendCommand(const char * cmd, const char * ACK, char * res, int timeout)
samux 1:fb4494783863 229 {
samux 1:fb4494783863 230 char read;
samux 1:fb4494783863 231 size_t found = string::npos;
samux 1:fb4494783863 232 string checking;
samux 1:fb4494783863 233 Timer tmr;
samux 1:fb4494783863 234 int result = 0;
samux 1:fb4494783863 235
michaeljkoster 17:d11fa4c3ac65 236 //pc.printf("will send: %s\r\n",cmd);
samux 1:fb4494783863 237
michaeljkoster 17:d11fa4c3ac65 238 attach_rx(true);
samux 1:fb4494783863 239
samux 1:fb4494783863 240 //We flush the buffer
michaeljkoster 17:d11fa4c3ac65 241 while (readable())
michaeljkoster 17:d11fa4c3ac65 242 getc();
michaeljkoster 16:3f0efaa57a12 243
samux 1:fb4494783863 244 if (!ACK || !strcmp(ACK, "NO")) {
michaeljkoster 17:d11fa4c3ac65 245 for (int i = 0; i < strlen(cmd); i++){
michaeljkoster 16:3f0efaa57a12 246 result = (putc(cmd[i]) == cmd[i]) ? result + 1 : result;
michaeljkoster 17:d11fa4c3ac65 247 wait(.005);
michaeljkoster 16:3f0efaa57a12 248 }
michaeljkoster 16:3f0efaa57a12 249 putc(13); //CR
michaeljkoster 17:d11fa4c3ac65 250 wait(.005);
michaeljkoster 16:3f0efaa57a12 251 putc(10); //LF
michaeljkoster 16:3f0efaa57a12 252
samux 1:fb4494783863 253 } else {
samux 1:fb4494783863 254 //We flush the buffer
michaeljkoster 17:d11fa4c3ac65 255 while (readable())
michaeljkoster 17:d11fa4c3ac65 256 getc();
samux 1:fb4494783863 257
samux 1:fb4494783863 258 tmr.start();
michaeljkoster 17:d11fa4c3ac65 259 for (int i = 0; i < strlen(cmd); i++){
michaeljkoster 16:3f0efaa57a12 260 result = (putc(cmd[i]) == cmd[i]) ? result + 1 : result;
michaeljkoster 17:d11fa4c3ac65 261 wait(.005);
michaeljkoster 16:3f0efaa57a12 262 }
michaeljkoster 16:3f0efaa57a12 263 putc(13); //CR
michaeljkoster 17:d11fa4c3ac65 264 wait(.005);
michaeljkoster 16:3f0efaa57a12 265 putc(10); //LF
samux 1:fb4494783863 266
samux 1:fb4494783863 267 while (1) {
samux 1:fb4494783863 268 if (tmr.read_ms() > timeout) {
samux 1:fb4494783863 269 //We flush the buffer
michaeljkoster 17:d11fa4c3ac65 270 while (readable())
michaeljkoster 17:d11fa4c3ac65 271 getc();
samux 1:fb4494783863 272
samux 1:fb4494783863 273 DBG("check: %s\r\n", checking.c_str());
samux 1:fb4494783863 274
samux 1:fb4494783863 275 attach_rx(true);
samux 1:fb4494783863 276 return -1;
michaeljkoster 17:d11fa4c3ac65 277 } else if (readable()) {
michaeljkoster 17:d11fa4c3ac65 278 read = getc();
samux 1:fb4494783863 279 if ( read != '\r' && read != '\n') {
samux 1:fb4494783863 280 checking += read;
samux 1:fb4494783863 281 found = checking.find(ACK);
samux 1:fb4494783863 282 if (found != string::npos) {
samux 1:fb4494783863 283 wait(0.01);
samux 1:fb4494783863 284
samux 1:fb4494783863 285 //We flush the buffer
michaeljkoster 17:d11fa4c3ac65 286 while (readable())
michaeljkoster 17:d11fa4c3ac65 287 getc();
samux 1:fb4494783863 288
samux 1:fb4494783863 289 break;
samux 1:fb4494783863 290 }
samux 1:fb4494783863 291 }
samux 1:fb4494783863 292 }
samux 1:fb4494783863 293 }
samux 1:fb4494783863 294 DBG("check: %s\r\n", checking.c_str());
samux 1:fb4494783863 295
samux 1:fb4494783863 296 attach_rx(true);
samux 1:fb4494783863 297 return result;
samux 1:fb4494783863 298 }
samux 1:fb4494783863 299
samux 1:fb4494783863 300 //the user wants the result from the command (ACK == NULL, res != NULL)
samux 1:fb4494783863 301 if ( res != NULL) {
samux 1:fb4494783863 302 int i = 0;
samux 1:fb4494783863 303 Timer timeout;
samux 1:fb4494783863 304 timeout.start();
samux 1:fb4494783863 305 tmr.reset();
samux 1:fb4494783863 306 while (1) {
samux 1:fb4494783863 307 if (timeout.read() > 2) {
samux 1:fb4494783863 308 if (i == 0) {
samux 1:fb4494783863 309 res = NULL;
samux 1:fb4494783863 310 break;
samux 1:fb4494783863 311 }
samux 1:fb4494783863 312 res[i] = '\0';
samux 1:fb4494783863 313 DBG("user str 1: %s\r\n", res);
samux 1:fb4494783863 314
samux 1:fb4494783863 315 break;
samux 1:fb4494783863 316 } else {
samux 1:fb4494783863 317 if (tmr.read_ms() > 300) {
samux 1:fb4494783863 318 res[i] = '\0';
samux 1:fb4494783863 319 DBG("user str: %s\r\n", res);
samux 1:fb4494783863 320
samux 1:fb4494783863 321 break;
samux 1:fb4494783863 322 }
michaeljkoster 17:d11fa4c3ac65 323 if (readable()) {
samux 1:fb4494783863 324 tmr.start();
michaeljkoster 17:d11fa4c3ac65 325 read = getc();
samux 1:fb4494783863 326
samux 1:fb4494783863 327 // we drop \r and \n
samux 1:fb4494783863 328 if ( read != '\r' && read != '\n') {
samux 1:fb4494783863 329 res[i++] = read;
samux 1:fb4494783863 330 }
samux 1:fb4494783863 331 }
samux 1:fb4494783863 332 }
samux 1:fb4494783863 333 }
samux 1:fb4494783863 334 DBG("user str: %s\r\n", res);
samux 1:fb4494783863 335 }
samux 1:fb4494783863 336
samux 1:fb4494783863 337 //We flush the buffer
michaeljkoster 17:d11fa4c3ac65 338 while (readable())
michaeljkoster 17:d11fa4c3ac65 339 getc();
samux 1:fb4494783863 340
samux 1:fb4494783863 341 attach_rx(true);
samux 1:fb4494783863 342 DBG("result: %d\r\n", result)
samux 1:fb4494783863 343 return result;
michaeljkoster 15:37a7a56a424f 344 }
michaeljkoster 16:3f0efaa57a12 345
michaeljkoster 16:3f0efaa57a12 346 void ESP8266::ATcommand(char* command){
michaeljkoster 16:3f0efaa57a12 347 char* cmd=command;
michaeljkoster 16:3f0efaa57a12 348 while(!wifi.writeable() || wifi.readable()){}
michaeljkoster 16:3f0efaa57a12 349 while(*cmd){
michaeljkoster 16:3f0efaa57a12 350 wifi.putc((int)*cmd++);
michaeljkoster 16:3f0efaa57a12 351 wait(.005); // wait for the echo
michaeljkoster 16:3f0efaa57a12 352 while(!wifi.writeable() || wifi.readable()){}
michaeljkoster 16:3f0efaa57a12 353 }
michaeljkoster 16:3f0efaa57a12 354 wifi.putc(13); //CR
michaeljkoster 16:3f0efaa57a12 355 while(!wifi.writeable() || wifi.readable()){}
michaeljkoster 16:3f0efaa57a12 356 wifi.putc(10); //LF
michaeljkoster 16:3f0efaa57a12 357 }