Forked mbed official WiflyInterface (interface for Roving Networks Wifly modules) which includes the possibility to use TCPSocketServer::accept as a non-blocking cal.
Dependents: WiFlyHTTPServerSample MultiThreadingHTTPServer
Fork of WiflyInterface by
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 #ifndef DEBUG 00025 #define DEBUG 00026 #endif 00027 #include "debug.h" 00028 00029 DigitalOut ledrx(LED3); 00030 00031 00032 #define MAX_TRY_JOIN 3 00033 00034 const int std_baudrates[] = { 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 }; 00035 00036 00037 Wifly * Wifly::inst; 00038 00039 Wifly::Wifly( PinName tx, PinName rx, PinName _reset, PinName tcp_status, const char * ssid, const char * phrase, Security sec, WiflyBaudrate_t baud): 00040 wifi(tx, rx), reset_pin(_reset), tcp_status(tcp_status), buf_wifly(512), m_baudrate(baud) 00041 { 00042 memset(&state, 0, sizeof(state)); 00043 state.sec = sec; 00044 00045 // change all ' ' in '$' in the ssid and the passphrase 00046 strcpy(this->ssid, ssid); 00047 for (int i = 0; i < strlen(ssid); i++) { 00048 if (this->ssid[i] == ' ') 00049 this->ssid[i] = '$'; 00050 } 00051 strcpy(this->phrase, phrase); 00052 for (int i = 0; i < strlen(phrase); i++) { 00053 if (this->phrase[i] == ' ') 00054 this->phrase[i] = '$'; 00055 } 00056 00057 inst = this; 00058 attach_rx(false); 00059 state.cmd_mode = false; 00060 00061 reset(); 00062 } 00063 00064 bool Wifly::join() 00065 { 00066 char cmd[50]; 00067 00068 setBaudRate(std_baudrates[m_baudrate]); 00069 00070 for (int i= 0; i < MAX_TRY_JOIN; i++) { 00071 00072 // no auto join 00073 if (!sendCommand("set w j 0\r", "AOK")) 00074 continue; 00075 00076 //no echo 00077 if (!sendCommand("set u m 17\r", "AOK")) 00078 continue; 00079 00080 // set time 00081 if (!sendCommand("set c t 30\r", "AOK")) 00082 continue; 00083 00084 // set size 00085 if (!sendCommand("set c s 1024\r", "AOK")) 00086 continue; 00087 00088 // red led on when tcp connection active 00089 if (!sendCommand("set s i 0x40\r", "AOK")) 00090 continue; 00091 00092 // no string sent to the tcp client 00093 if (!sendCommand("set c r 0\r", "AOK")) 00094 continue; 00095 00096 // tcp protocol 00097 if (!sendCommand("set i p 2\r", "AOK")) 00098 continue; 00099 00100 // tcp retry 00101 if (!sendCommand("set i f 0x7\r", "AOK")) 00102 continue; 00103 00104 // set dns server 00105 if (!sendCommand("set d n rn.microchip.com\r", "AOK")) 00106 continue; 00107 00108 //dhcp 00109 sprintf(cmd, "set i d %d\r", (state.dhcp) ? 1 : 0); 00110 if (!sendCommand(cmd, "AOK")) 00111 continue; 00112 00113 // ssid 00114 sprintf(cmd, "set wlan ssid %s\r", ssid); 00115 if (!sendCommand(cmd, "AOK")) 00116 continue; 00117 00118 //auth 00119 sprintf(cmd, "set w a %d\r", state.sec); 00120 if (!sendCommand(cmd, "AOK")) 00121 continue; 00122 00123 // if no dhcp, set ip, netmask and gateway 00124 if (!state.dhcp) { 00125 INFO("not dhcp\r"); 00126 00127 sprintf(cmd, "set i a %s\r\n", ip); 00128 if (!sendCommand(cmd, "AOK")) 00129 continue; 00130 00131 sprintf(cmd, "set i n %s\r", netmask); 00132 if (!sendCommand(cmd, "AOK")) 00133 continue; 00134 00135 sprintf(cmd, "set i g %s\r", gateway); 00136 if (!sendCommand(cmd, "AOK")) 00137 continue; 00138 } 00139 00140 //key step 00141 if (state.sec != NONE) { 00142 if (state.sec == WPA) 00143 sprintf(cmd, "set w p %s\r", phrase); 00144 else if (state.sec == WEP_128) 00145 sprintf(cmd, "set w k %s\r", phrase); 00146 00147 if (!sendCommand(cmd, "AOK")) 00148 continue; 00149 } 00150 00151 //join the network (10s timeout) 00152 if (state.dhcp) { 00153 if (!sendCommand("join\r", "DHCP=ON", NULL, 10000)) 00154 continue; 00155 } else { 00156 if (!sendCommand("join\r", "Associated", NULL, 10000)) 00157 continue; 00158 } 00159 00160 enableTime(1); 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 int Wifly::enableTime(int minutes, const char* ntp_address) 00175 { 00176 char cmd[30]; 00177 00178 //let module automatically conntect to timeserver and get the actual time 00179 sprintf(cmd, "set t e %d\r", minutes); 00180 if (!sendCommand(cmd, "AOK")) { 00181 ERR("Failed to modify time function !"); 00182 return -1; 00183 } 00184 00185 //set the NTP server address 00186 sprintf(cmd, "set t a %s\r", ntp_address); 00187 if (!sendCommand(cmd, "AOK")) { 00188 ERR("Failed to modify time server address !"); 00189 } 00190 00191 if (!sendCommand("set option format 1\r", "AOK")) { 00192 ERR("Failed to set option format to ASCII !"); 00193 } 00194 00195 if (!sendCommand("set time zone 0\r", "AOK")) { 00196 ERR("Failed to set time zone !"); 00197 } 00198 00199 sendCommand("time\r", NULL, NULL, 1000); 00200 00201 flush(); 00202 00203 exit(); 00204 00205 return 0; 00206 } 00207 00208 string Wifly::getTime(bool uptime) 00209 { 00210 char buf[100]; 00211 00212 sendCommand("time\r", NULL, NULL, 10000); 00213 if (!sendCommand("show time\r", NULL, buf, 10000)) 00214 return ""; 00215 INFO("\r\nReceived Time : %s\r\n", buf); 00216 00217 exit(); 00218 return buf; 00219 } 00220 00221 bool Wifly::setBaudRate(int baud) 00222 { 00223 char str[35]; 00224 bool bfound = true; 00225 00226 INFO("Trying baudrates.\n"); 00227 sprintf(str, "set uart raw %d\r", baud); 00228 00229 wifi.baud(baud); 00230 if (!sendCommand(str, "AOK")) { 00231 for( int i = 0 ; i < sizeof(std_baudrates)/sizeof(int) ; i++) { 00232 // try all standard baudrates until the correct one is found 00233 INFO("Trying at %d baud\n", std_baudrates[i]); 00234 wifi.baud(std_baudrates[i]); 00235 if (sendCommand(str, "AOK")) { 00236 bfound = true; 00237 break; 00238 } 00239 } 00240 } 00241 if (bfound) { 00242 wait(0.05); 00243 if (!sendCommand("save\r", "STOR")) 00244 return false; 00245 00246 reboot(); 00247 00248 wifi.baud(baud); 00249 } 00250 return true; 00251 } 00252 00253 bool Wifly::setProtocol(Protocol p) 00254 { 00255 // use udp auto pairing 00256 char cmd[20]; 00257 sprintf(cmd, "set i p %d\r", p); 00258 if (!sendCommand(cmd, "AOK")) 00259 return false; 00260 00261 switch(p) { 00262 case TCP: 00263 // set ip flags: tcp retry enabled 00264 if (!sendCommand("set i f 0x07\r", "AOK")) 00265 return false; 00266 break; 00267 case UDP: 00268 // set ip flags: udp auto pairing enabled 00269 if (!sendCommand("set i h 0.0.0.0\r", "AOK")) 00270 return false; 00271 if (!sendCommand("set i f 0x40\r", "AOK")) 00272 return false; 00273 break; 00274 } 00275 state.proto = p; 00276 return true; 00277 } 00278 00279 char * Wifly::getStringSecurity() 00280 { 00281 switch(state.sec) { 00282 case NONE: 00283 return "NONE"; 00284 case WEP_128: 00285 return "WEP_128"; 00286 case WPA: 00287 return "WPA"; 00288 } 00289 return "UNKNOWN"; 00290 } 00291 00292 bool Wifly::connect(const char * host, int port) 00293 { 00294 char rcv[20]; 00295 char cmd[50]; 00296 00297 // try to open 00298 sprintf(cmd, "open %s %d\r", host, port); 00299 if (sendCommand(cmd, "OPEN", NULL, 10000)) { 00300 state.tcp = true; 00301 state.cmd_mode = false; 00302 return true; 00303 } 00304 00305 // if failed, retry and parse the response 00306 if (sendCommand(cmd, NULL, rcv, 5000)) { 00307 if (strstr(rcv, "OPEN") == NULL) { 00308 if (strstr(rcv, "Connected") != NULL) { 00309 wait(0.25); 00310 if (!sendCommand("close\r", "CLOS")) 00311 return false; 00312 wait(0.25); 00313 if (!sendCommand(cmd, "OPEN", NULL, 10000)) 00314 return false; 00315 } else { 00316 return false; 00317 } 00318 } 00319 } else { 00320 return false; 00321 } 00322 00323 state.tcp = true; 00324 state.cmd_mode = false; 00325 00326 return true; 00327 } 00328 00329 00330 bool Wifly::gethostbyname(const char * host, char * ip) 00331 { 00332 string h = host; 00333 char cmd[30], rcv[100]; 00334 int l = 0; 00335 char * point; 00336 int nb_digits = 0; 00337 00338 // no dns needed 00339 int pos = h.find("."); 00340 if (pos != string::npos) { 00341 string sub = h.substr(0, h.find(".")); 00342 nb_digits = atoi(sub.c_str()); 00343 } 00344 //printf("substrL %s\r\n", sub.c_str()); 00345 if (count(h.begin(), h.end(), '.') == 3 && nb_digits > 0) { 00346 strcpy(ip, host); 00347 } 00348 // dns needed 00349 else { 00350 nb_digits = 0; 00351 sprintf(cmd, "lookup %s\r", host); 00352 if (!sendCommand(cmd, NULL, rcv)) 00353 return false; 00354 00355 // look for the ip address 00356 char * begin = strstr(rcv, "=") + 1; 00357 for (int i = 0; i < 3; i++) { 00358 point = strstr(begin + l, "."); 00359 INFO("str: %s", begin + l); 00360 l += point - (begin + l) + 1; 00361 } 00362 INFO("str: %s", begin + l); 00363 while(*(begin + l + nb_digits) >= '0' && *(begin + l + nb_digits) <= '9') { 00364 INFO("digit: %c", *(begin + l + nb_digits)); 00365 nb_digits++; 00366 } 00367 memcpy(ip, begin, l + nb_digits); 00368 ip[l+nb_digits] = 0; 00369 INFO("ip from dns: %s", ip); 00370 } 00371 return true; 00372 } 00373 00374 00375 void Wifly::flush() 00376 { 00377 buf_wifly.flush(); 00378 } 00379 00380 bool Wifly::sendCommand(const char * cmd, const char * ack, char * res, int timeout) 00381 { 00382 if (!state.cmd_mode) { 00383 cmdMode(); 00384 } 00385 if (send(cmd, strlen(cmd), ack, res, timeout) == -1) { 00386 ERR("sendCommand: cannot %s\r\n", cmd); 00387 exit(); 00388 return false; 00389 } 00390 return true; 00391 } 00392 00393 bool Wifly::cmdMode() 00394 { 00395 // if already in cmd mode, return 00396 if (state.cmd_mode) 00397 return true; 00398 00399 if (send("$$$", 3, "CMD") == -1) { 00400 ERR("cannot enter in cmd mode\r\n"); 00401 exit(); 00402 return false; 00403 } 00404 state.cmd_mode = true; 00405 return true; 00406 } 00407 00408 bool Wifly::disconnect() 00409 { 00410 // if already disconnected, return 00411 if (!state.associated) 00412 return true; 00413 00414 if (!sendCommand("leave\r", "DeAuth")) 00415 return false; 00416 exit(); 00417 00418 state.associated = false; 00419 return true; 00420 00421 } 00422 00423 bool Wifly::is_connected() 00424 { 00425 return (tcp_status.read() == 1) ? true : false; 00426 } 00427 00428 00429 void Wifly::reset() 00430 { 00431 reset_pin = 0; 00432 wait(0.2); 00433 reset_pin = 1; 00434 wait(0.2); 00435 } 00436 00437 bool Wifly::reboot() 00438 { 00439 // if already in cmd mode, return 00440 if (!sendCommand("reboot\r")) 00441 return false; 00442 00443 wait(0.3); 00444 00445 state.cmd_mode = false; 00446 return true; 00447 } 00448 00449 bool Wifly::close() 00450 { 00451 // if not connected, return 00452 // if (!state.tcp) 00453 // return true; 00454 00455 // Thread::wait(250); 00456 if (!sendCommand("close\r", "CLOS")) 00457 return false; 00458 exit(false); 00459 00460 state.tcp = false; 00461 return true; 00462 } 00463 00464 00465 int Wifly::putc(char c) 00466 { 00467 while (!wifi.writeable()); 00468 return wifi.putc(c); 00469 } 00470 00471 00472 bool Wifly::exit(bool bflush) 00473 { 00474 if (bflush) 00475 flush(); 00476 if (!state.cmd_mode) 00477 return true; 00478 if (!sendCommand("exit\r", "EXIT")) 00479 return false; 00480 state.cmd_mode = false; 00481 if (bflush) 00482 flush(); 00483 return true; 00484 } 00485 00486 00487 int Wifly::readable() 00488 { 00489 return buf_wifly.available(); 00490 } 00491 00492 int Wifly::writeable() 00493 { 00494 return wifi.writeable(); 00495 } 00496 00497 char Wifly::getc() 00498 { 00499 char c; 00500 while (!buf_wifly.available()); 00501 buf_wifly.dequeue(&c); 00502 return c; 00503 } 00504 00505 00506 char Wifly::peek() 00507 { 00508 char c; 00509 while (!buf_wifly.available()) 00510 ; 00511 buf_wifly.peek(&c); 00512 return c; 00513 } 00514 00515 void Wifly::handler_rx(void) 00516 { 00517 //read characters 00518 while (wifi.readable()) { 00519 char c = LPC_UART3->RBR; 00520 buf_wifly.queue(c); 00521 ledrx = !ledrx; 00522 } 00523 } 00524 00525 void Wifly::attach_rx(bool callback) 00526 { 00527 if (!callback) 00528 wifi.attach(NULL); 00529 else 00530 wifi.attach(this, &Wifly::handler_rx); 00531 } 00532 00533 int Wifly::send(const char * str, int len, const char * ACK, char * res, int timeout) 00534 { 00535 char read; 00536 size_t found = string::npos; 00537 string checking; 00538 Timer tmr; 00539 int result = 0; 00540 00541 INFO("will send: %s\r\n",str); 00542 00543 attach_rx(false); 00544 00545 //We flush the buffer 00546 while (wifi.readable()) 00547 { 00548 char c = wifi.getc(); 00549 INFO("Flushing : %c",c); 00550 } 00551 00552 if (!ACK || !strcmp(ACK, "NO")) { 00553 for (int i = 0; i < len; i++) 00554 result = (putc(str[i]) == str[i]) ? result + 1 : result; 00555 } else { 00556 //We flush the buffer 00557 while (wifi.readable()) 00558 { 00559 char c = wifi.getc(); 00560 INFO("Flushing : %c",c); 00561 } 00562 00563 tmr.start(); 00564 for (int i = 0; i < len; i++) 00565 result = (putc(str[i]) == str[i]) ? result + 1 : result; 00566 00567 while (1) { 00568 if (tmr.read_ms() > timeout) { 00569 //We flush the buffer 00570 while (wifi.readable()) { 00571 char c = wifi.getc(); 00572 INFO("Flushing : %c",c); 00573 } 00574 00575 INFO("check: %s\r\n", checking.c_str()); 00576 00577 attach_rx(true); 00578 return -1; 00579 } else if (wifi.readable()) { 00580 read = wifi.getc(); 00581 if ( read != '\r' && read != '\n') { 00582 checking += read; 00583 found = checking.find(ACK); 00584 if (found != string::npos) { 00585 wait(0.01); 00586 //We flush the buffer 00587 while (wifi.readable()) { 00588 char c = wifi.getc(); 00589 INFO("Flushing : %c",c); 00590 } 00591 00592 break; 00593 } 00594 } 00595 } 00596 } 00597 INFO("check: %s\r\n", checking.c_str()); 00598 00599 attach_rx(true); 00600 return result; 00601 } 00602 00603 //the user wants the result from the command (ACK == NULL, res != NULL) 00604 if ( res != NULL) { 00605 int i = 0; 00606 Timer timeout; 00607 timeout.start(); 00608 tmr.reset(); 00609 while (1) { 00610 if (timeout.read() > 2) { 00611 if (i == 0) { 00612 res = NULL; 00613 break; 00614 } 00615 res[i] = '\0'; 00616 INFO("user str 1: %s\r\n", res); 00617 00618 break; 00619 } else { 00620 if (tmr.read_ms() > 300) { 00621 res[i] = '\0'; 00622 INFO("user str: %s\r\n", res); 00623 00624 break; 00625 } 00626 if (wifi.readable()) { 00627 tmr.start(); 00628 read = wifi.getc(); 00629 00630 // we drop \r and \n 00631 if ( read != '\r' && read != '\n') { 00632 res[i++] = read; 00633 } 00634 } 00635 } 00636 } 00637 INFO("user str: %s\r\n", res); 00638 } 00639 00640 //We flush the buffer 00641 while (wifi.readable()) { 00642 char c = wifi.getc(); 00643 INFO("Flushing : %c",c); 00644 } 00645 00646 attach_rx(true); 00647 INFO("result: %d\r\n", result) 00648 return result; 00649 } 00650 00651 00652 int Wifly::sendData(const char* data, int len, int _timeout) 00653 { 00654 int result = 0; 00655 Timer tmr; 00656 00657 tmr.start(); 00658 while (tmr.read_ms() < _timeout) { 00659 if (wifi.writeable()) 00660 break; 00661 } 00662 if (tmr.read_ms() >= _timeout) { 00663 return -1; 00664 } 00665 for (int i = 0; i < len; i++) 00666 result = (putc(data[i]) == data[i]) ? result + 1 : result; 00667 00668 return result; 00669 }
Generated on Sat Jul 16 2022 16:48:24 by 1.7.2