Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FatFileSystemCpp mbed PowerControl USBHostLite
Wifly.cpp
00001 /* Copyright (C) 2012 mbed.org, MIT License 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00004 * and associated documentation files (the "Software"), to deal in the Software without restriction, 00005 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 00006 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 00007 * furnished to do so, subject to the following conditions: 00008 * 00009 * The above copyright notice and this permission notice shall be included in all copies or 00010 * substantial portions of the Software. 00011 * 00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00017 */ 00018 00019 #include "mbed.h" 00020 #include "Wifly.h" 00021 #include <string> 00022 #include <algorithm> 00023 00024 //Debug is disabled by default 00025 #if (0 && !defined(TARGET_LPC11U24)) 00026 #define DBG(x, ...) std::printf("[Wifly : DBG]"x"\r\n", ##__VA_ARGS__); 00027 #define WARN(x, ...) std::printf("[Wifly : WARN]"x"\r\n", ##__VA_ARGS__); 00028 #define ERR(x, ...) std::printf("[Wifly : ERR]"x"\r\n", ##__VA_ARGS__); 00029 #else 00030 #define DBG(x, ...) 00031 #define WARN(x, ...) 00032 #define ERR(x, ...) 00033 #endif 00034 00035 #if !defined(TARGET_LPC11U24) 00036 #define INFO(x, ...) printf("[Wifly : INFO]"x"\r\n", ##__VA_ARGS__); 00037 #else 00038 #define INFO(x, ...) 00039 #endif 00040 00041 #define MAX_TRY_JOIN 3 00042 00043 Wifly * Wifly::inst; 00044 00045 Wifly::Wifly( PinName tx, PinName rx, PinName _reset, PinName tcp_status, const char * ssid, const char * phrase, Security sec): 00046 wifi(tx, rx), reset_pin(_reset), tcp_status(tcp_status), buf_wifly(256) 00047 { 00048 memset(&state, 0, sizeof(state)); 00049 state.sec = sec; 00050 00051 // change all ' ' in '$' in the ssid and the passphrase 00052 strcpy(this->ssid, ssid); 00053 for (int i = 0; i < strlen(ssid); i++) { 00054 if (this->ssid[i] == ' ') 00055 this->ssid[i] = '$'; 00056 } 00057 strcpy(this->phrase, phrase); 00058 for (int i = 0; i < strlen(phrase); i++) { 00059 if (this->phrase[i] == ' ') 00060 this->phrase[i] = '$'; 00061 } 00062 00063 inst = this; 00064 attach_rx(false); 00065 state.cmd_mode = false; 00066 } 00067 00068 void Wifly::baudr(int baudrate) 00069 { 00070 char cmd[50]; 00071 00072 sprintf(cmd, "set uart instant %d\r", baudrate); 00073 sendCommand(cmd, NULL); 00074 wait(1); 00075 00076 wifi.baud(baudrate); 00077 } 00078 00079 void Wifly::flowCTS(PinName cts) 00080 { 00081 wifi.set_flow_control(SerialBase::CTS, cts); 00082 } 00083 00084 bool Wifly::join() 00085 { 00086 char cmd[75]; 00087 00088 for (int i= 0; i < MAX_TRY_JOIN; i++) { 00089 00090 // no auto join 00091 if (!sendCommand("set w j 0\r", "AOK")) 00092 continue; 00093 00094 //no echo 00095 if (!sendCommand("set u m 1\r", "AOK")) 00096 continue; 00097 00098 // set time 00099 if (!sendCommand("set c t 30\r", "AOK")) 00100 continue; 00101 00102 // set size 00103 if (!sendCommand("set c s 1024\r", "AOK")) 00104 continue; 00105 00106 // red led on when tcp connection active 00107 if (!sendCommand("set s i 0x40\r", "AOK")) 00108 continue; 00109 00110 // no string sent to the tcp client 00111 if (!sendCommand("set c r 0\r", "AOK")) 00112 continue; 00113 00114 // tcp protocol 00115 if (!sendCommand("set i p 2\r", "AOK")) 00116 continue; 00117 00118 // tcp retry 00119 if (!sendCommand("set i f 0x7\r", "AOK")) 00120 continue; 00121 00122 // set dns server 00123 if (!sendCommand("set d n rn.microchip.com\r", "AOK")) 00124 continue; 00125 00126 //dhcp 00127 sprintf(cmd, "set i d %d\r", (state.dhcp) ? 1 : 0); 00128 if (!sendCommand(cmd, "AOK")) 00129 continue; 00130 00131 // ssid 00132 sprintf(cmd, "set w s %s\r", ssid); 00133 if (!sendCommand(cmd, "AOK")) 00134 continue; 00135 00136 //auth 00137 sprintf(cmd, "set w a %d\r", state.sec); 00138 if (!sendCommand(cmd, "AOK")) 00139 continue; 00140 00141 // if no dhcp, set ip, netmask and gateway 00142 if (!state.dhcp) { 00143 DBG("not dhcp\r"); 00144 00145 sprintf(cmd, "set i a %s\r\n", ip); 00146 if (!sendCommand(cmd, "AOK")) 00147 continue; 00148 00149 sprintf(cmd, "set i n %s\r", netmask); 00150 if (!sendCommand(cmd, "AOK")) 00151 continue; 00152 00153 sprintf(cmd, "set i g %s\r", gateway); 00154 if (!sendCommand(cmd, "AOK")) 00155 continue; 00156 } 00157 00158 //key step 00159 if (state.sec != NONE) { 00160 if (state.sec == WPA) 00161 sprintf(cmd, "set w p %s\r", phrase); 00162 else if (state.sec == WEP_128) 00163 sprintf(cmd, "set w k %s\r", phrase); 00164 00165 if (!sendCommand(cmd, "AOK")) 00166 continue; 00167 } 00168 00169 //join the network (10s timeout) 00170 if (state.dhcp) { 00171 if (!sendCommand("join\r", "DHCP=ON", NULL, 10000)) 00172 continue; 00173 } else { 00174 if (!sendCommand("join\r", "Associated", NULL, 10000)) 00175 continue; 00176 } 00177 00178 if (!sendCommand("save\r", "Stor")) 00179 continue; 00180 00181 exit(); 00182 00183 state.associated = true; 00184 INFO("\r\nssid: %s\r\nphrase: %s\r\nsecurity: %s\r\n\r\n", this->ssid, this->phrase, getStringSecurity()); 00185 return true; 00186 } 00187 return false; 00188 } 00189 00190 00191 bool Wifly::setProtocol(Protocol p) 00192 { 00193 // use udp auto pairing 00194 char cmd[20]; 00195 sprintf(cmd, "set i p %d\r", p); 00196 if (!sendCommand(cmd, "AOK")) 00197 return false; 00198 00199 switch(p) { 00200 case TCP: 00201 // set ip flags: tcp retry enabled 00202 if (!sendCommand("set i f 0x07\r", "AOK")) 00203 return false; 00204 break; 00205 case UDP: 00206 // set ip flags: udp auto pairing enabled 00207 if (!sendCommand("set i h 0.0.0.0\r", "AOK")) 00208 return false; 00209 if (!sendCommand("set i f 0x40\r", "AOK")) 00210 return false; 00211 break; 00212 } 00213 state.proto = p; 00214 return true; 00215 } 00216 00217 char * Wifly::getStringSecurity() 00218 { 00219 switch(state.sec) { 00220 case NONE: 00221 return "NONE"; 00222 case WEP_128: 00223 return "WEP_128"; 00224 case WPA: 00225 return "WPA"; 00226 } 00227 return "UNKNOWN"; 00228 } 00229 00230 bool Wifly::connect(const char * host, int port) 00231 { 00232 char rcv[20]; 00233 char cmd[20]; 00234 00235 // try to open 00236 sprintf(cmd, "open %s %d\r", host, port); 00237 if (sendCommand(cmd, "OPEN", NULL, 10000)) { 00238 state.tcp = true; 00239 state.cmd_mode = false; 00240 return true; 00241 } 00242 00243 // if failed, retry and parse the response 00244 if (sendCommand(cmd, NULL, rcv, 5000)) { 00245 if (strstr(rcv, "OPEN") == NULL) { 00246 if (strstr(rcv, "Connected") != NULL) { 00247 wait(0.25); 00248 if (!sendCommand("close\r", "CLOS")) 00249 return false; 00250 wait(0.25); 00251 if (!sendCommand(cmd, "OPEN", NULL, 10000)) 00252 return false; 00253 } else { 00254 return false; 00255 } 00256 } 00257 } else { 00258 return false; 00259 } 00260 00261 state.tcp = true; 00262 state.cmd_mode = false; 00263 00264 return true; 00265 } 00266 00267 00268 bool Wifly::gethostbyname(const char * host, char * ip) 00269 { 00270 string h = host; 00271 char cmd[30], rcv[100]; 00272 int l = 0; 00273 char * point; 00274 int nb_digits = 0; 00275 00276 // no dns needed 00277 int pos = h.find("."); 00278 if (pos != string::npos) { 00279 string sub = h.substr(0, h.find(".")); 00280 nb_digits = atoi(sub.c_str()); 00281 } 00282 //printf("substrL %s\r\n", sub.c_str()); 00283 if (count(h.begin(), h.end(), '.') == 3 && nb_digits > 0) { 00284 strcpy(ip, host); 00285 } 00286 // dns needed 00287 else { 00288 nb_digits = 0; 00289 sprintf(cmd, "lookup %s\r", host); 00290 if (!sendCommand(cmd, NULL, rcv)) 00291 return false; 00292 00293 // look for the ip address 00294 char * begin = strstr(rcv, "=") + 1; 00295 for (int i = 0; i < 3; i++) { 00296 point = strstr(begin + l, "."); 00297 DBG("str: %s", begin + l); 00298 l += point - (begin + l) + 1; 00299 } 00300 DBG("str: %s", begin + l); 00301 while(*(begin + l + nb_digits) >= '0' && *(begin + l + nb_digits) <= '9') { 00302 DBG("digit: %c", *(begin + l + nb_digits)); 00303 nb_digits++; 00304 } 00305 memcpy(ip, begin, l + nb_digits); 00306 ip[l+nb_digits] = 0; 00307 DBG("ip from dns: %s", ip); 00308 } 00309 return true; 00310 } 00311 00312 00313 void Wifly::flush() 00314 { 00315 buf_wifly.flush(); 00316 } 00317 00318 bool Wifly::sendCommand(const char * cmd, const char * ack, char * res, int timeout) 00319 { 00320 if (!state.cmd_mode) { 00321 cmdMode(); 00322 } 00323 if (send(cmd, strlen(cmd), ack, res, timeout) == -1) { 00324 ERR("sendCommand: cannot %s\r\n", cmd); 00325 exit(); 00326 return false; 00327 } 00328 return true; 00329 } 00330 00331 bool Wifly::cmdMode() 00332 { 00333 // if already in cmd mode, return 00334 if (state.cmd_mode) 00335 return true; 00336 00337 if (send("$$$", 3, "CMD") == -1) { 00338 ERR("cannot enter in cmd mode\r\n"); 00339 exit(); 00340 return false; 00341 } 00342 state.cmd_mode = true; 00343 return true; 00344 } 00345 00346 bool Wifly::disconnect() 00347 { 00348 // if already disconnected, return 00349 if (!state.associated) 00350 return true; 00351 00352 if (!sendCommand("leave\r", "DeAuth")) 00353 return false; 00354 exit(); 00355 00356 state.associated = false; 00357 return true; 00358 00359 } 00360 00361 bool Wifly::is_connected() 00362 { 00363 return (tcp_status.read() == 1) ? true : false; 00364 } 00365 00366 00367 void Wifly::reset() 00368 { 00369 reset_pin = 0; 00370 wait(0.2); 00371 reset_pin = 1; 00372 wait(0.2); 00373 } 00374 00375 bool Wifly::reboot() 00376 { 00377 // if already in cmd mode, return 00378 if (!sendCommand("reboot\r")) 00379 return false; 00380 00381 wait(0.3); 00382 00383 state.cmd_mode = false; 00384 return true; 00385 } 00386 00387 bool Wifly::close() 00388 { 00389 // if not connected, return 00390 if (!state.tcp) 00391 return true; 00392 00393 wait(0.25); 00394 if (!sendCommand("close\r", "CLOS")) 00395 return false; 00396 exit(); 00397 00398 state.tcp = false; 00399 return true; 00400 } 00401 00402 00403 int Wifly::putc(char c) 00404 { 00405 while (!wifi.writeable()); 00406 return wifi.putc(c); 00407 } 00408 00409 00410 bool Wifly::exit() 00411 { 00412 flush(); 00413 if (!state.cmd_mode) 00414 return true; 00415 if (!sendCommand("exit\r", "EXIT")) 00416 return false; 00417 state.cmd_mode = false; 00418 flush(); 00419 return true; 00420 } 00421 00422 00423 int Wifly::readable() 00424 { 00425 return buf_wifly.available(); 00426 } 00427 00428 int Wifly::writeable() 00429 { 00430 return wifi.writeable(); 00431 } 00432 00433 char Wifly::getc() 00434 { 00435 char c; 00436 while (!buf_wifly.available()); 00437 buf_wifly.dequeue(&c); 00438 return c; 00439 } 00440 00441 void Wifly::handler_rx(void) 00442 { 00443 //read characters 00444 while (wifi.readable()) 00445 buf_wifly.queue(wifi.getc()); 00446 } 00447 00448 void Wifly::attach_rx(bool callback) 00449 { 00450 if (!callback) 00451 wifi.attach(NULL); 00452 else 00453 wifi.attach(this, &Wifly::handler_rx); 00454 } 00455 00456 00457 int Wifly::send(const char * str, int len, const char * ACK, char * res, int timeout) 00458 { 00459 char read; 00460 size_t found = string::npos; 00461 string checking; 00462 Timer tmr; 00463 int result = 0; 00464 00465 DBG("will send: %s\r\n",str); 00466 00467 attach_rx(false); 00468 00469 //We flush the buffer 00470 while (wifi.readable()) 00471 wifi.getc(); 00472 00473 if (!ACK || !strcmp(ACK, "NO")) { 00474 for (int i = 0; i < len; i++) 00475 result = (putc(str[i]) == str[i]) ? result + 1 : result; 00476 } else { 00477 //We flush the buffer 00478 while (wifi.readable()) 00479 wifi.getc(); 00480 00481 tmr.start(); 00482 for (int i = 0; i < len; i++) 00483 result = (putc(str[i]) == str[i]) ? result + 1 : result; 00484 00485 while (1) { 00486 if (tmr.read_ms() > timeout) { 00487 //We flush the buffer 00488 while (wifi.readable()) 00489 wifi.getc(); 00490 00491 DBG("check: %s\r\n", checking.c_str()); 00492 00493 attach_rx(true); 00494 return -1; 00495 } else if (wifi.readable()) { 00496 read = wifi.getc(); 00497 if ( read != '\r' && read != '\n') { 00498 checking += read; 00499 found = checking.find(ACK); 00500 if (found != string::npos) { 00501 wait(0.01); 00502 00503 //We flush the buffer 00504 while (wifi.readable()) 00505 wifi.getc(); 00506 00507 break; 00508 } 00509 } 00510 } 00511 } 00512 DBG("check: %s\r\n", checking.c_str()); 00513 00514 attach_rx(true); 00515 return result; 00516 } 00517 00518 //the user wants the result from the command (ACK == NULL, res != NULL) 00519 if ( res != NULL) { 00520 int i = 0; 00521 Timer timeout; 00522 timeout.start(); 00523 tmr.reset(); 00524 while (1) { 00525 if (timeout.read() > 2) { 00526 if (i == 0) { 00527 res = NULL; 00528 break; 00529 } 00530 res[i] = '\0'; 00531 DBG("user str 1: %s\r\n", res); 00532 00533 break; 00534 } else { 00535 if (tmr.read_ms() > 300) { 00536 res[i] = '\0'; 00537 DBG("user str: %s\r\n", res); 00538 00539 break; 00540 } 00541 if (wifi.readable()) { 00542 tmr.start(); 00543 read = wifi.getc(); 00544 00545 // we drop \r and \n 00546 if ( read != '\r' && read != '\n') { 00547 res[i++] = read; 00548 } 00549 } 00550 } 00551 } 00552 DBG("user str: %s\r\n", res); 00553 } 00554 00555 //We flush the buffer 00556 while (wifi.readable()) 00557 wifi.getc(); 00558 00559 attach_rx(true); 00560 DBG("result: %d\r\n", result) 00561 return result; 00562 }
Generated on Mon Jul 18 2022 01:02:56 by
