yap yee king / WiflyInterface2

Fork of WiflyInterface by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Wifly.cpp Source File

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