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