Forked mbed official WiflyInterface (interface for Roving Networks Wifly modules) which includes the possibility to use TCPSocketServer::accept as a non-blocking cal.

Dependents:   WiFlyHTTPServerSample MultiThreadingHTTPServer

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