This is a fork specifically for seeed wifi shield

Dependents:   seeed_Wifi_HelloWorld Wifly_Xively_HelloWorld

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