Bender Robotics / Mbed 2 deprecated PLAUCI_full

Dependencies:   FatFileSystemCpp mbed PowerControl USBHostLite

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