- Added setBaud() function - Added CheckNetworkStatus() function - Improved messaging system
Dependents: IoT_Ex BatteryModelTester BatteryModelTester
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 //#define DEBUG 00025 #define INFOMESSAGES 00026 #define WARNMESSAGES 00027 #define ERRMESSAGES 00028 #define FUNCNAME "Wifly" 00029 #include "messages.h" 00030 00031 #define MAX_TRY_JOIN 3 00032 00033 Wifly * Wifly::inst; 00034 00035 Wifly::Wifly( PinName tx, PinName rx, PinName _reset, PinName tcp_status, const char * ssid, const char * phrase, Security sec): 00036 wifi(tx, rx), reset_pin(_reset), tcp_status(tcp_status), buf_wifly(1024) 00037 { 00038 // Set the default baud rate: 00039 serial_baudrate = 9600; 00040 00041 memset(&state, 0, sizeof(state)); 00042 state.sec = sec; 00043 00044 // change all ' ' in '$' in the ssid and the passphrase 00045 strcpy(this->ssid, ssid); 00046 for (int i = 0; i < strlen(ssid); i++) { 00047 if (this->ssid[i] == ' ') 00048 this->ssid[i] = '$'; 00049 } 00050 strcpy(this->phrase, phrase); 00051 for (int i = 0; i < strlen(phrase); i++) { 00052 if (this->phrase[i] == ' ') 00053 this->phrase[i] = '$'; 00054 } 00055 00056 inst = this; 00057 attach_rx(false); 00058 state.cmd_mode = false; 00059 DBG("Wifly Constructed"); 00060 } 00061 00062 void Wifly::setBaud(int baudrate) 00063 { 00064 char cmd[28]; 00065 // Save the baudrate: 00066 if(baudrate > 0){ 00067 serial_baudrate = baudrate; 00068 } 00069 DBG("Setting wifi shield baudrate to: %d.", serial_baudrate); 00070 // This sets the baud rate 'instantly' 00071 sprintf(cmd, "set u i %d\r", serial_baudrate); 00072 // This one sets it some other way that does not work 00073 //sprintf(cmd, "set u b %d\r", baudrate); 00074 // Set baud rate of wifly: 00075 sendCommand(cmd, NULL); 00076 wait(0.5); 00077 // Set baud rate of UART: 00078 wifi.baud(serial_baudrate); 00079 wait(0.5); 00080 exit(); 00081 } 00082 00083 bool Wifly::join() 00084 { 00085 char cmd[28]; 00086 00087 for (int i= 0; i < MAX_TRY_JOIN; i++) { 00088 00089 // no auto join 00090 if (!sendCommand("set w j 0\r", "AOK")) 00091 continue; 00092 00093 //no echo 00094 if (!sendCommand("set u m 1\r", "AOK")) 00095 continue; 00096 00097 // set time 00098 if (!sendCommand("set c t 30\r", "AOK")) 00099 continue; 00100 00101 // set size 00102 if (!sendCommand("set c s 1024\r", "AOK")) 00103 continue; 00104 00105 // red led on when tcp connection active 00106 if (!sendCommand("set s i 0x40\r", "AOK")) 00107 continue; 00108 00109 // no string sent to the tcp client 00110 if (!sendCommand("set c r 0\r", "AOK")) 00111 continue; 00112 00113 // tcp protocol 00114 if (!sendCommand("set i p 2\r", "AOK")) 00115 continue; 00116 00117 // tcp retry 00118 if (!sendCommand("set i f 0x7\r", "AOK")) 00119 continue; 00120 00121 // set dns server 00122 if (!sendCommand("set d n rn.microchip.com\r", "AOK")) 00123 continue; 00124 00125 //dhcp 00126 sprintf(cmd, "set i d %d\r", (state.dhcp) ? 1 : 0); 00127 if (!sendCommand(cmd, "AOK")) 00128 continue; 00129 00130 // ssid 00131 sprintf(cmd, "set w s %s\r", ssid); 00132 if (!sendCommand(cmd, "AOK", NULL, 1000)) 00133 continue; 00134 00135 //auth 00136 sprintf(cmd, "set w a %d\r", state.sec); 00137 if (!sendCommand(cmd, "AOK")) 00138 continue; 00139 00140 // if no dhcp, set ip, netmask and gateway 00141 if (!state.dhcp) { 00142 DBG("not dhcp\r"); 00143 00144 sprintf(cmd, "set i a %s\r\n", ip); 00145 if (!sendCommand(cmd, "AOK")) 00146 continue; 00147 00148 sprintf(cmd, "set i n %s\r", netmask); 00149 if (!sendCommand(cmd, "AOK")) 00150 continue; 00151 00152 sprintf(cmd, "set i g %s\r", gateway); 00153 if (!sendCommand(cmd, "AOK")) 00154 continue; 00155 } 00156 00157 //key step 00158 if (state.sec != NONE) { 00159 if ((state.sec == WPA)||(state.sec == WPA2)) 00160 sprintf(cmd, "set w p %s\r", phrase); 00161 else if (state.sec == WEP_128) 00162 sprintf(cmd, "set w k %s\r", phrase); 00163 00164 if (!sendCommand(cmd, "AOK", NULL, 1000)) 00165 continue; 00166 } 00167 00168 //join the network 00169 sprintf(cmd, "join\r"); 00170 if (!sendCommand(cmd, "Associated", NULL, 3000)) 00171 continue; 00172 00173 if (!sendCommand("", "IP=", NULL, 10000)) 00174 continue; 00175 00176 if (state.dhcp) { 00177 if (!sendCommand("get i\r", "DHCP=ON", NULL, 3000)) 00178 continue; 00179 } 00180 00181 if (!sendCommand("save\r", "Stor")) 00182 continue; 00183 00184 exit(); 00185 00186 state.associated = true; 00187 INFO("ssid: %s", this->ssid); 00188 INFO("phrase: %s", this->phrase); 00189 INFO("security: %s", getStringSecurity()); 00190 00191 return true; 00192 } 00193 return false; 00194 } 00195 00196 00197 bool Wifly::setProtocol(Protocol p) 00198 { 00199 // use udp auto pairing 00200 char cmd[20]; 00201 sprintf(cmd, "set i p %d\r", p); 00202 if (!sendCommand(cmd, "AOK")) 00203 return false; 00204 00205 switch(p) { 00206 case TCP: 00207 // set ip flags: tcp retry enabled 00208 if (!sendCommand("set i f 0x07\r", "AOK")) 00209 return false; 00210 break; 00211 case UDP: 00212 // set ip flags: udp auto pairing enabled 00213 if (!sendCommand("set i h 0.0.0.0\r", "AOK")) 00214 return false; 00215 if (!sendCommand("set i f 0x40\r", "AOK")) 00216 return false; 00217 break; 00218 } 00219 state.proto = p; 00220 return true; 00221 } 00222 00223 char * Wifly::getStringSecurity() 00224 { 00225 switch(state.sec) { 00226 case NONE: 00227 return "NONE"; 00228 case WEP_128: 00229 return "WEP_128"; 00230 case WPA: 00231 return "WPA"; 00232 case WPA2: 00233 return "WPA2"; 00234 } 00235 return "UNKNOWN"; 00236 } 00237 00238 bool Wifly::connect(const char * host, int port) 00239 { 00240 char rcv[28]; 00241 char cmd[28]; 00242 00243 00244 00245 // try to open 00246 sprintf(cmd, "open %s %d\r", host, port); 00247 DBG("CMD1: %s",cmd); 00248 if (sendCommand(cmd, "OPEN", rcv, 10000)) { 00249 state.tcp = true; 00250 state.cmd_mode = false; 00251 return true; 00252 } 00253 DBG("CMD2: %s",cmd); 00254 DBG("CMD4: %s",rcv); 00255 // if failed, retry and parse the response 00256 if (sendCommand(cmd, NULL, rcv, 5000)) { 00257 DBG("CMD5: %s",rcv); 00258 if (strstr(rcv, "OPEN") == NULL) { 00259 if (strstr(rcv, "Connected") != NULL) { 00260 wait(0.25); 00261 if (!sendCommand("close\r", "CLOS")) 00262 return false; 00263 wait(0.25); 00264 if (!sendCommand(cmd, "OPEN", NULL, 10000)) 00265 return false; 00266 } else { 00267 return false; 00268 } 00269 } 00270 } else { 00271 DBG("CMD5: %s",rcv); 00272 return false; 00273 } 00274 00275 00276 state.tcp = true; 00277 state.cmd_mode = false; 00278 00279 return true; 00280 } 00281 00282 00283 bool Wifly::gethostbyname(const char * host, char * ip) 00284 { 00285 string h = host; 00286 char cmd[30], rcv[100]; 00287 int l = 0; 00288 char * point; 00289 int nb_digits = 0; 00290 00291 // no dns needed 00292 int pos = h.find("."); 00293 if (pos != string::npos) { 00294 string sub = h.substr(0, h.find(".")); 00295 nb_digits = atoi(sub.c_str()); 00296 } 00297 if (count(h.begin(), h.end(), '.') == 3 && nb_digits > 0) { 00298 strcpy(ip, host); 00299 } 00300 // dns needed 00301 else { 00302 nb_digits = 0; 00303 sprintf(cmd, "lookup %s\r", host); 00304 if (!sendCommand(cmd, NULL, rcv)) 00305 return false; 00306 00307 // look for the ip address 00308 char * begin = strstr(rcv, "=") + 1; 00309 for (int i = 0; i < 3; i++) { 00310 point = strstr(begin + l, "."); 00311 DBG("str: %s", begin + l); 00312 l += point - (begin + l) + 1; 00313 } 00314 DBG("str: %s", begin + l); 00315 while(*(begin + l + nb_digits) >= '0' && *(begin + l + nb_digits) <= '9') { 00316 DBG("digit: %c", *(begin + l + nb_digits)); 00317 nb_digits++; 00318 } 00319 memcpy(ip, begin, l + nb_digits); 00320 ip[l+nb_digits] = 0; 00321 DBG("ip from dns: %s", ip); 00322 } 00323 return true; 00324 } 00325 00326 00327 void Wifly::flush() 00328 { 00329 buf_wifly.flush(); 00330 } 00331 00332 bool Wifly::sendCommand(const char * cmd, const char * ack, char * res, int timeout) 00333 { 00334 if (!state.cmd_mode) { 00335 cmdMode(); 00336 } 00337 if (send(cmd, strlen(cmd), ack, res, timeout) == -1) { 00338 ERR("sendCommand: cannot (%s)", cmd); 00339 if(strcmp(cmd, "exit") != 0){ 00340 exit(); 00341 }else{ 00342 WARN("Manually setting cmd_mode to false."); 00343 state.cmd_mode = false; 00344 } 00345 return false; 00346 } 00347 return true; 00348 } 00349 00350 bool Wifly::cmdMode() 00351 { 00352 // if already in cmd mode, return 00353 if (state.cmd_mode) 00354 return true; 00355 00356 if (send("$$$", 3, "CMD") == -1 && send("\r",1,">") != true) { 00357 ERR("cannot enter in cmd mode"); 00358 exit(); 00359 return false; 00360 } 00361 state.cmd_mode = true; 00362 return true; 00363 } 00364 00365 bool Wifly::disconnect() 00366 { 00367 // if already disconnected, return 00368 if (!state.associated) 00369 return true; 00370 00371 if (!sendCommand("leave\r", "DeAuth")) 00372 return false; 00373 exit(); 00374 00375 state.associated = false; 00376 return true; 00377 00378 } 00379 00380 bool Wifly::is_connected() 00381 { 00382 return (tcp_status.read() == 1) ? true : false; 00383 } 00384 00385 00386 void Wifly::reset() 00387 { 00388 00389 reset_pin = 0; 00390 wifi.baud(9600); 00391 flush(); 00392 state.cmd_mode = false; 00393 wait(0.5); 00394 reset_pin = 1; 00395 // Set the serial port baud rate back to default: 00396 wait(0.5); 00397 INFO("Wifi Shield Reset"); 00398 setBaud(-1); 00399 DBG("Baud Rate updated from Reset."); 00400 } 00401 00402 bool Wifly::reboot() 00403 { 00404 // if already in cmd mode, return 00405 if (!sendCommand("reboot\r")) 00406 return false; 00407 00408 wait(0.3); 00409 00410 state.cmd_mode = false; 00411 return true; 00412 } 00413 00414 bool Wifly::close() 00415 { 00416 // if not connected, return 00417 if (!state.tcp) 00418 return true; 00419 00420 wait(0.25); 00421 if (!sendCommand("close\r", "CLOS")) 00422 return false; 00423 exit(); 00424 00425 state.tcp = false; 00426 return true; 00427 } 00428 00429 00430 int Wifly::putc(char c) 00431 { 00432 while (!wifi.writeable()); 00433 return wifi.putc(c); 00434 } 00435 00436 00437 bool Wifly::exit() 00438 { 00439 flush(); 00440 if (!state.cmd_mode) 00441 return true; 00442 if (!sendCommand("exit\r", "EXIT")) 00443 return false; 00444 state.cmd_mode = false; 00445 flush(); 00446 return true; 00447 } 00448 00449 00450 int Wifly::readable() 00451 { 00452 return buf_wifly.available(); 00453 } 00454 00455 int Wifly::writeable() 00456 { 00457 return wifi.writeable(); 00458 } 00459 00460 char Wifly::getc() 00461 { 00462 char c; 00463 //DBG("Waiting for buf_wifly.available() to return true..."); 00464 while (!buf_wifly.available()); 00465 //DBG("Dequeue-ing c..."); 00466 buf_wifly.dequeue(&c); 00467 //DBG("Return c:(%c)",c); 00468 return c; 00469 } 00470 00471 void Wifly::handler_rx(void) 00472 { 00473 //read characters 00474 while (wifi.readable()) 00475 buf_wifly.queue(wifi.getc()); 00476 } 00477 00478 void Wifly::attach_rx(bool callback) 00479 { 00480 if (!callback) 00481 wifi.attach(NULL); 00482 else 00483 wifi.attach(this, &Wifly::handler_rx); 00484 } 00485 00486 00487 int Wifly::send(const char * str, int len, const char * ACK, char * res, int timeout) 00488 { 00489 char read; 00490 size_t found = string::npos; 00491 string checking; 00492 Timer tmr; 00493 int result = 0; 00494 00495 // Don't display the string that we will be sending because it is encoded, thus may screw up printf() 00496 if(ACK == NULL){ 00497 DBG("Will send a string, no ACK requested."); 00498 }else{ 00499 DBG("Will send a string, looking for ACK: %s", ACK); 00500 } 00501 00502 attach_rx(false); 00503 00504 //We flush the buffer 00505 while (wifi.readable()) 00506 wifi.getc(); 00507 00508 if (!ACK || !strcmp(ACK, "NO")) { 00509 for (int i = 0; i < len; i++) 00510 result = (putc(str[i]) == str[i]) ? result + 1 : result; 00511 } else { 00512 //We flush the buffer 00513 while (wifi.readable()) 00514 wifi.getc(); 00515 00516 tmr.start(); 00517 for (int i = 0; i < len; i++) 00518 result = (putc(str[i]) == str[i]) ? result + 1 : result; 00519 00520 while (1) { 00521 if (tmr.read_ms() > timeout) { 00522 //We flush the buffer 00523 while (wifi.readable()) 00524 wifi.getc(); 00525 00526 DBG("check: %s", checking.c_str()); 00527 DBG("result ignored: %d", result) 00528 attach_rx(true); 00529 return -1; 00530 } else if (wifi.readable()) { 00531 read = wifi.getc(); 00532 if ( read != '\r' && read != '\n') { 00533 checking += read; 00534 found = checking.find(ACK); 00535 if (found != string::npos) { 00536 wait(0.01); 00537 00538 //We flush the buffer 00539 while (wifi.readable()) 00540 wifi.getc(); 00541 00542 break; 00543 } 00544 } 00545 } 00546 } 00547 DBG("check: %s", checking.c_str()); 00548 DBG("result: %d", result) 00549 attach_rx(true); 00550 return result; 00551 } 00552 00553 //the user wants the result from the command (ACK == NULL, res != NULL) 00554 if ( res != NULL) { 00555 int i = 0; 00556 Timer timeout; 00557 timeout.start(); 00558 tmr.reset(); 00559 while (1) { 00560 if (timeout.read() > 2) { 00561 if (i == 0) { 00562 res = NULL; 00563 break; 00564 } 00565 res[i] = '\0'; 00566 DBG("user str 1: %s", res); 00567 00568 break; 00569 } else { 00570 if (tmr.read_ms() > 300) { 00571 res[i] = '\0'; 00572 DBG("user str2: %s", res); 00573 00574 break; 00575 } 00576 if (wifi.readable()) { 00577 tmr.start(); 00578 read = wifi.getc(); 00579 00580 // we drop \r and \n 00581 if ( read != '\r' && read != '\n') { 00582 res[i++] = read; 00583 } 00584 } 00585 } 00586 } 00587 DBG("user str3: %s", res); 00588 } 00589 00590 //We flush the buffer 00591 while (wifi.readable()) 00592 wifi.getc(); 00593 00594 attach_rx(true); 00595 DBG("result: %d", result) 00596 return result; 00597 } 00598 00599 int Wifly::checkNetworkStatus(void){ 00600 int status = 0; 00601 char rcv[128]; 00602 unsigned int ConnectionReg; 00603 00604 if(!sendCommand("show c\r", NULL, rcv, 5000)){ 00605 status = 0; 00606 // the sendCommand function quits command mode if there is an error 00607 }else{ 00608 // check the response: 00609 sscanf(rcv, "%x%*s", &ConnectionReg); 00610 if(((ConnectionReg & CC_ASSOCIATION)>0) && ((ConnectionReg & CC_AUTHENTICATION)>0)){ 00611 // Associated and Authenticated: 00612 status = 3; 00613 }else if((ConnectionReg & CC_ASSOCIATION)>0){ 00614 // Associated: 00615 status = 1; 00616 }else if((ConnectionReg & CC_AUTHENTICATION)>0){ 00617 // Athenticated: 00618 status = 2; 00619 }else{ 00620 // Disconnected: 00621 status = 0; 00622 } 00623 INFO("Wifly Check network response: 0x%x, Status: %d", ConnectionReg, status); 00624 exit(); // Quit command mode 00625 } 00626 00627 return status; 00628 } 00629 00630 void Wifly::sleep(void){ 00631 // This function puts the module to sleep: 00632 sendCommand("sleep\r", NULL); 00633 // It will wake up from sleep if any characters are sent to it. 00634 return; 00635 }
Generated on Sat Jul 16 2022 22:55:16 by 1.7.2