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.
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 bool Wifly::join() 00069 { 00070 char cmd[20]; 00071 00072 for (int i= 0; i < MAX_TRY_JOIN; i++) { 00073 00074 // no auto join 00075 if (!sendCommand("set w j 0\r", "AOK")) 00076 continue; 00077 00078 //no echo 00079 if (!sendCommand("set u m 1\r", "AOK")) 00080 continue; 00081 00082 // set time 00083 if (!sendCommand("set c t 30\r", "AOK")) 00084 continue; 00085 00086 // set size 00087 if (!sendCommand("set c s 1024\r", "AOK")) 00088 continue; 00089 00090 // red led on when tcp connection active 00091 if (!sendCommand("set s i 0x40\r", "AOK")) 00092 continue; 00093 00094 // no string sent to the tcp client 00095 if (!sendCommand("set c r 0\r", "AOK")) 00096 continue; 00097 00098 // tcp protocol 00099 if (!sendCommand("set i p 2\r", "AOK")) 00100 continue; 00101 00102 // tcp retry 00103 if (!sendCommand("set i f 0x7\r", "AOK")) 00104 continue; 00105 00106 // set dns server 00107 if (!sendCommand("set d n rn.microchip.com\r", "AOK")) 00108 continue; 00109 00110 //dhcp 00111 sprintf(cmd, "set i d %d\r", (state.dhcp) ? 1 : 0); 00112 if (!sendCommand(cmd, "AOK")) 00113 continue; 00114 00115 // ssid 00116 sprintf(cmd, "set w s %s\r", ssid); 00117 if (!sendCommand(cmd, "AOK")) 00118 continue; 00119 00120 //auth 00121 sprintf(cmd, "set w a %d\r", state.sec); 00122 if (!sendCommand(cmd, "AOK")) 00123 continue; 00124 00125 // if no dhcp, set ip, netmask and gateway 00126 if (!state.dhcp) { 00127 DBG("not dhcp\r"); 00128 00129 sprintf(cmd, "set i a %s\r\n", ip); 00130 if (!sendCommand(cmd, "AOK")) 00131 continue; 00132 00133 sprintf(cmd, "set i n %s\r", netmask); 00134 if (!sendCommand(cmd, "AOK")) 00135 continue; 00136 00137 sprintf(cmd, "set i g %s\r", gateway); 00138 if (!sendCommand(cmd, "AOK")) 00139 continue; 00140 } 00141 00142 //key step 00143 if (state.sec != NONE) { 00144 if (state.sec == WPA) 00145 sprintf(cmd, "set w p %s\r", phrase); 00146 else if (state.sec == WEP_128) 00147 sprintf(cmd, "set w k %s\r", phrase); 00148 00149 if (!sendCommand(cmd, "AOK")) 00150 continue; 00151 } 00152 00153 //join the network (10s timeout) 00154 if (state.dhcp) { 00155 if (!sendCommand("join\r", "DHCP=ON", NULL, 10000)) 00156 continue; 00157 } else { 00158 if (!sendCommand("join\r", "Associated", NULL, 10000)) 00159 continue; 00160 } 00161 00162 if (!sendCommand("save\r", "Stor")) 00163 continue; 00164 00165 exit(); 00166 00167 state.associated = true; 00168 INFO("\r\nssid: %s\r\nphrase: %s\r\nsecurity: %s\r\n\r\n", this->ssid, this->phrase, getStringSecurity()); 00169 return true; 00170 } 00171 return false; 00172 } 00173 00174 00175 bool Wifly::setProtocol(Protocol p) 00176 { 00177 // use udp auto pairing 00178 char cmd[20]; 00179 sprintf(cmd, "set i p %d\r", p); 00180 if (!sendCommand(cmd, "AOK")) 00181 return false; 00182 00183 switch(p) { 00184 case TCP: 00185 // set ip flags: tcp retry enabled 00186 if (!sendCommand("set i f 0x07\r", "AOK")) 00187 return false; 00188 break; 00189 case UDP: 00190 // set ip flags: udp auto pairing enabled 00191 if (!sendCommand("set i h 0.0.0.0\r", "AOK")) 00192 return false; 00193 if (!sendCommand("set i f 0x40\r", "AOK")) 00194 return false; 00195 break; 00196 } 00197 state.proto = p; 00198 return true; 00199 } 00200 00201 char * Wifly::getStringSecurity() 00202 { 00203 switch(state.sec) { 00204 case NONE: 00205 return "NONE"; 00206 case WEP_128: 00207 return "WEP_128"; 00208 case WPA: 00209 return "WPA"; 00210 } 00211 return "UNKNOWN"; 00212 } 00213 00214 bool Wifly::connect(const char * host, int port) 00215 { 00216 char rcv[20]; 00217 char cmd[20]; 00218 00219 // try to open 00220 sprintf(cmd, "open %s %d\r", host, port); 00221 if (sendCommand(cmd, "OPEN", NULL, 10000)) { 00222 state.tcp = true; 00223 state.cmd_mode = false; 00224 return true; 00225 } 00226 00227 // if failed, retry and parse the response 00228 if (sendCommand(cmd, NULL, rcv, 5000)) { 00229 if (strstr(rcv, "OPEN") == NULL) { 00230 if (strstr(rcv, "Connected") != NULL) { 00231 wait(0.25); 00232 if (!sendCommand("close\r", "CLOS")) 00233 return false; 00234 wait(0.25); 00235 if (!sendCommand(cmd, "OPEN", NULL, 10000)) 00236 return false; 00237 } else { 00238 return false; 00239 } 00240 } 00241 } else { 00242 return false; 00243 } 00244 00245 state.tcp = true; 00246 state.cmd_mode = false; 00247 00248 return true; 00249 } 00250 00251 00252 bool Wifly::gethostbyname(const char * host, char * ip) 00253 { 00254 string h = host; 00255 char cmd[30], rcv[100]; 00256 int l = 0; 00257 char * point; 00258 int nb_digits = 0; 00259 00260 // no dns needed 00261 int pos = h.find("."); 00262 if (pos != string::npos) { 00263 string sub = h.substr(0, h.find(".")); 00264 nb_digits = atoi(sub.c_str()); 00265 } 00266 //printf("substrL %s\r\n", sub.c_str()); 00267 if (count(h.begin(), h.end(), '.') == 3 && nb_digits > 0) { 00268 strcpy(ip, host); 00269 } 00270 // dns needed 00271 else { 00272 nb_digits = 0; 00273 sprintf(cmd, "lookup %s\r", host); 00274 if (!sendCommand(cmd, NULL, rcv)) 00275 return false; 00276 00277 // look for the ip address 00278 char * begin = strstr(rcv, "=") + 1; 00279 for (int i = 0; i < 3; i++) { 00280 point = strstr(begin + l, "."); 00281 DBG("str: %s", begin + l); 00282 l += point - (begin + l) + 1; 00283 } 00284 DBG("str: %s", begin + l); 00285 while(*(begin + l + nb_digits) >= '0' && *(begin + l + nb_digits) <= '9') { 00286 DBG("digit: %c", *(begin + l + nb_digits)); 00287 nb_digits++; 00288 } 00289 memcpy(ip, begin, l + nb_digits); 00290 ip[l+nb_digits] = 0; 00291 DBG("ip from dns: %s", ip); 00292 } 00293 return true; 00294 } 00295 00296 00297 void Wifly::flush() 00298 { 00299 buf_wifly.flush(); 00300 } 00301 00302 bool Wifly::sendCommand(const char * cmd, const char * ack, char * res, int timeout) 00303 { 00304 if (!state.cmd_mode) { 00305 cmdMode(); 00306 } 00307 if (send(cmd, strlen(cmd), ack, res, timeout) == -1) { 00308 ERR("sendCommand: cannot %s\r\n", cmd); 00309 exit(); 00310 return false; 00311 } 00312 return true; 00313 } 00314 00315 bool Wifly::cmdMode() 00316 { 00317 // if already in cmd mode, return 00318 if (state.cmd_mode) 00319 return true; 00320 00321 if (send("$$$", 3, "CMD") == -1) { 00322 ERR("cannot enter in cmd mode\r\n"); 00323 exit(); 00324 return false; 00325 } 00326 state.cmd_mode = true; 00327 return true; 00328 } 00329 00330 bool Wifly::disconnect() 00331 { 00332 // if already disconnected, return 00333 if (!state.associated) 00334 return true; 00335 00336 if (!sendCommand("leave\r", "DeAuth")) 00337 return false; 00338 exit(); 00339 00340 state.associated = false; 00341 return true; 00342 00343 } 00344 00345 bool Wifly::is_connected() 00346 { 00347 return (tcp_status.read() == 1) ? true : false; 00348 } 00349 00350 00351 void Wifly::reset() 00352 { 00353 reset_pin = 0; 00354 wait(0.2); 00355 reset_pin = 1; 00356 wait(0.2); 00357 } 00358 00359 bool Wifly::reboot() 00360 { 00361 // if already in cmd mode, return 00362 if (!sendCommand("reboot\r")) 00363 return false; 00364 00365 wait(0.3); 00366 00367 state.cmd_mode = false; 00368 return true; 00369 } 00370 00371 bool Wifly::close() 00372 { 00373 // if not connected, return 00374 if (!state.tcp) 00375 return true; 00376 00377 wait(0.25); 00378 if (!sendCommand("close\r", "CLOS")) 00379 return false; 00380 exit(); 00381 00382 state.tcp = false; 00383 return true; 00384 } 00385 00386 00387 int Wifly::putc(char c) 00388 { 00389 while (!wifi.writeable()); 00390 return wifi.putc(c); 00391 } 00392 00393 00394 bool Wifly::exit() 00395 { 00396 flush(); 00397 if (!state.cmd_mode) 00398 return true; 00399 if (!sendCommand("exit\r", "EXIT")) 00400 return false; 00401 state.cmd_mode = false; 00402 flush(); 00403 return true; 00404 } 00405 00406 00407 int Wifly::readable() 00408 { 00409 return buf_wifly.available(); 00410 } 00411 00412 int Wifly::writeable() 00413 { 00414 return wifi.writeable(); 00415 } 00416 00417 char Wifly::getc() 00418 { 00419 char c; 00420 while (!buf_wifly.available()); 00421 buf_wifly.dequeue(&c); 00422 return c; 00423 } 00424 00425 void Wifly::handler_rx(void) 00426 { 00427 //read characters 00428 while (wifi.readable()) 00429 buf_wifly.queue(wifi.getc()); 00430 } 00431 00432 void Wifly::attach_rx(bool callback) 00433 { 00434 if (!callback) 00435 wifi.attach(NULL); 00436 else 00437 wifi.attach(this, &Wifly::handler_rx); 00438 } 00439 00440 00441 int Wifly::send(const char * str, int len, const char * ACK, char * res, int timeout) 00442 { 00443 char read; 00444 size_t found = string::npos; 00445 string checking; 00446 Timer tmr; 00447 int result = 0; 00448 00449 DBG("will send: %s\r\n",str); 00450 00451 attach_rx(false); 00452 00453 //We flush the buffer 00454 while (wifi.readable()) 00455 wifi.getc(); 00456 00457 if (!ACK || !strcmp(ACK, "NO")) { 00458 for (int i = 0; i < len; i++) 00459 result = (putc(str[i]) == str[i]) ? result + 1 : result; 00460 } else { 00461 //We flush the buffer 00462 while (wifi.readable()) 00463 wifi.getc(); 00464 00465 tmr.start(); 00466 for (int i = 0; i < len; i++) 00467 result = (putc(str[i]) == str[i]) ? result + 1 : result; 00468 00469 while (1) { 00470 if (tmr.read_ms() > timeout) { 00471 //We flush the buffer 00472 while (wifi.readable()) 00473 wifi.getc(); 00474 00475 DBG("check: %s\r\n", checking.c_str()); 00476 00477 attach_rx(true); 00478 return -1; 00479 } else if (wifi.readable()) { 00480 read = wifi.getc(); 00481 if ( read != '\r' && read != '\n') { 00482 checking += read; 00483 found = checking.find(ACK); 00484 if (found != string::npos) { 00485 wait(0.01); 00486 00487 //We flush the buffer 00488 while (wifi.readable()) 00489 wifi.getc(); 00490 00491 break; 00492 } 00493 } 00494 } 00495 } 00496 DBG("check: %s\r\n", checking.c_str()); 00497 00498 attach_rx(true); 00499 return result; 00500 } 00501 00502 //the user wants the result from the command (ACK == NULL, res != NULL) 00503 if ( res != NULL) { 00504 int i = 0; 00505 Timer timeout; 00506 timeout.start(); 00507 tmr.reset(); 00508 while (1) { 00509 if (timeout.read() > 2) { 00510 if (i == 0) { 00511 res = NULL; 00512 break; 00513 } 00514 res[i] = '\0'; 00515 DBG("user str 1: %s\r\n", res); 00516 00517 break; 00518 } else { 00519 if (tmr.read_ms() > 300) { 00520 res[i] = '\0'; 00521 DBG("user str: %s\r\n", res); 00522 00523 break; 00524 } 00525 if (wifi.readable()) { 00526 tmr.start(); 00527 read = wifi.getc(); 00528 00529 // we drop \r and \n 00530 if ( read != '\r' && read != '\n') { 00531 res[i++] = read; 00532 } 00533 } 00534 } 00535 } 00536 DBG("user str: %s\r\n", res); 00537 } 00538 00539 //We flush the buffer 00540 while (wifi.readable()) 00541 wifi.getc(); 00542 00543 attach_rx(true); 00544 DBG("result: %d\r\n", result) 00545 return result; 00546 }
Generated on Tue Jul 12 2022 18:24:44 by
1.7.2