https://developer.mbed.org/users/ds4279/code/WiflySocket/
Wifly.cpp
- Committer:
- ds4279
- Date:
- 2017-02-22
- Revision:
- 0:374a8a31f262
File content as of revision 0:374a8a31f262:
/* Copyright (C) 2012 mbed.org, MIT License * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, publish, distribute, * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "mbed.h" #include "headerStuff.h" #include "Wifly.h" #include <string> #include <algorithm> //extern void sendToDisplay(int cmd,int canID,char *canMsg); extern Serial myDebug; //Debug is disabled by default #if (0 && !defined(TARGET_LPC11U24)) #define DBG(x, ...) std::printf("[Wifly : DBG]"x"\r\n", ##__VA_ARGS__); #define WARN(x, ...) std::printf("[Wifly : WARN]"x"\r\n", ##__VA_ARGS__); #define ERR(x, ...) std::printf("[Wifly : ERR]"x"\r\n", ##__VA_ARGS__); #else #define DBG(x, ...) #define WARN(x, ...) #define ERR(x, ...) #endif #if !defined(TARGET_LPC11U24) #define INFO(x, ...) printf("[Wifly : INFO]"x"\r\n", ##__VA_ARGS__); #else #define INFO(x, ...) #endif #define MAX_TRY_JOIN 3 ///////////////////////////////////////// ///Make this object visible to the other ///classes. UDPSocket, etc... Wifly * Wifly::inst; // PB_4/D5/GPIO6 short pad P6 on shield Wifly::Wifly( PinName tx, PinName rx, PinName _reset, PinName tcp_status, const char * ssid, const char * phrase, Security sec): wifiSer(tx, rx,512,2), reset_pin(_reset), tcp_status(tcp_status)//, buf_wifly(256) //PinName tx, PinName rx, uint32_t buf_size = 512, uint32_t tx_multiple = 4 { memset(&state, 0, sizeof(state)); state.sec = sec; /////////////////////////////////////////// ///The default baud rate 9600. Once change ///It will never have to be changed again. wifiSer.baud(19200); wifiSer.format(8,Serial::None,1); // change all ' ' in '$' in the ssid and the passphrase strcpy(this->ssid, ssid); for (int i = 0; i < strlen(ssid); i++) { if (this->ssid[i] == ' ') this->ssid[i] = '$'; } strcpy(this->phrase, phrase); for (int i = 0; i < strlen(phrase); i++) { if (this->phrase[i] == ' ') this->phrase[i] = '$'; } strcpy(this->staticIP,"0.0.0.0"); inst = this; //make this class visible to other classes // attach_rx(false); state.cmd_mode = false; state.dhcp = true; //assume initial connection DHCP } void Wifly::getDHCPhostInfo(char *SSID, char *passPhrase, int &auth) { auth = state.sec; strcpy(SSID,this->ssid); strcpy(passPhrase,this->phrase); } bool Wifly::init() { //set uart mode <value> //Bit Position Function //0 NOECHO - disables echo of RX data while in // command mode //1 DATA TRIGGER makes connection on RX data //2 Reserved for future use //3 Enable Sleep on RX BREAK signal //4 UART RX data buffer. See note below for details* //no echo: set uart mode <value> //myDebug.printf("set u m 1\r"); if (!sendCommand("set u m 1\r", "AOK",NULL,1000)) { myDebug.printf("Error: set u m 1\n"); } // //continue; wait_ms(10); //myDebug.printf("set c t 30\r"); // set time: set comm timer <30ms> if (!sendCommand("set c t 30\r", "AOK",NULL,1000)) // { myDebug.printf("Error: set c t 30\n"); } wait_ms(10); //myDebug.printf("set c s 1024\r"); // set size if (!sendCommand("set c s 1024\r", "AOK",NULL,1000)) { myDebug.printf("Error: set c s 1024\n"); } wait_ms(10); //myDebug.printf("set s i 0x40\r"); // red led on when tcp connection active if (!sendCommand("set s i 0x40\r", "AOK",NULL,1000)) { myDebug.printf("Error: set s i 0x40\n"); } wait_ms(100); // Do not auto auto if (!sendCommand("set w j 0\r", "AOK",NULL,500) ) { myDebug.printf("Error: set w j 0\n"); } //continue; wait_ms(10); //For the RN module to accept both TCP and UDP, set bits 1 and 2 (value = 3). if (!sendCommand("set ip p 3\r", "AOK",NULL,500) ) { myDebug.printf("Error: set w j 0\n"); } /* wait_ms(10); //uart baudrate if (!sendCommand("set uart baud 19200\r", "AOK",NULL,500) ) { myDebug.printf("Error: set w j 0\n"); } */ if (!sendCommand("save\r", "Stor")) { // sendToDisplay(RS485Cmd,0,"Error: save, Stor\n"); } wait_ms(10); // sendCommand("reboot\r", "ree") ; // exitCmdMode(); //leave command mode myDebug.printf("sending Reboot\n"); //cmd, ack, res, int timeout if(sendCommand("reboot\r", "Reboot",NULL,5000,false)) { //myDebug.printf("DHCP=ON\n"); } else { //myDebug.printf("DHCP Error\n"); } state.cmd_mode = false; return true; } void Wifly::setConnectionType(bool DHCP_STATIC) { state.dhcp = DHCP_STATIC; } bool Wifly::join(const char *ssid, const char *phrase, int auth) { char cmd[200]; unsigned char retries = 3; ////////////////////////////////////// ///auth set wlan auth <value> sprintf(cmd, "set w a %d\r", auth); sendCommand(cmd, "AOK"); wait_ms(10); ////////////////////////////////////// ///Pass Phrase sprintf(cmd, "set w p %s\r", phrase); //Returns 450ms sendCommand(cmd, "AOK"); //key step /* if (state.sec != NONE) { myDebug.printf("state.sec != NONE\n"); //Create command string if (state.sec == WPA) { /////////////////////////////////////////// ///set wlan phrase <string> myDebug.printf("set WPA\n"); sprintf(cmd, "set w p %s\r", phrase); } else if (state.sec == WEP_128) { myDebug.printf("set WEP\n"); sprintf(cmd, "set w k %s\r", phrase); } if (!sendCommand(cmd, "AOK")) //returns 500ms { } } */ wait_ms(10); if(state.dhcp) { state.dhcp = true; myDebug.printf("Connect DHCP...\n"); sendCommand("set ip dhcp 1", "AOK",NULL,1000); wait_ms(10); sprintf(cmd, "join %s\r", ssid); //join the SSID network while(retries) { if( sendCommand(cmd, "DHCP=ON",NULL,10000,true) ) { exitCmdMode(); //exit command mode return true; } else{ retries--; //myDebug.printf("Trying to JOIN...\n"); } }; } else //setup for static IP { //myDebug.printf("Connect Static IP\n"); sprintf(cmd, "set ip a %s\r", this->staticIP); sendCommand(cmd, "AOK",NULL,2000); sendCommand("set ip dhcp 0", "AOK",NULL,2000); state.dhcp = false; retries = 3; sprintf(cmd, "join %s\r", ssid); //join the SSID network while(retries) { if( sendCommand(cmd, "Associated",NULL,10000,true) ) { exitCmdMode(); //leave command mode return true; } else{ retries--; myDebug.printf("Trying to JOIN Static...\n"); } }; } exitCmdMode(); //leave command mode return false; //could not connect } ///////////////////////////////////////// //::join() // //The SSID and pass pharse are saved //when the constructor is called //////////////////////////////////////// bool Wifly::join() { char cmd[200]; unsigned char retries = 3; ////////////////////////////////////// ///auth set wlan auth <value> sprintf(cmd, "set w a %d\r", state.sec); sendCommand(cmd, "AOK"); wait_ms(10); sprintf(cmd, "set w p %s\r", this->phrase); //Returns 450ms myDebug.printf(cmd); sendCommand(cmd, "AOK"); wait_ms(10); sendCommand("set ip dhcp 1", "AOK"); wait_ms(10); //key step /* if (state.sec != NONE) { myDebug.printf("state.sec != NONE\n"); //Create command string if (state.sec == WPA) { /////////////////////////////////////////// ///set wlan phrase <string> myDebug.printf("set WPA\n"); sprintf(cmd, "set w p %s\r", phrase); } else if (state.sec == WEP_128) { myDebug.printf("set WEP\n"); sprintf(cmd, "set w k %s\r", phrase); } if (!sendCommand(cmd, "AOK")) //returns 500ms { } } */ wait_ms(10); if(state.dhcp) { myDebug.printf("Connect DHCP...\n"); sprintf(cmd, "join %s\r", this->ssid); state.dhcp = true; while(retries) { if( sendCommand(cmd, "DHCP=ON",NULL,10000,true) ) { exitCmdMode(); //leave command mode return true; } else{ retries--; myDebug.printf("Trying to JOIN...\n"); } }; } else //setup for static IP { //myDebug.printf("Connect Static IP\n"); sprintf(cmd, "set ip a %s\r", this->staticIP); sendCommand(cmd, "AOK",NULL,2000); sendCommand("set ip dhcp 0", "AOK",NULL,2000); state.dhcp = false; retries = 3; sprintf(cmd, "join %s\r", ssid); //join the SSID network while(retries) { if( sendCommand(cmd, "Associated",NULL,10000,true) ) { exitCmdMode(); //leave command mode return true; } else{ retries--; myDebug.printf("Trying to JOIN Static...\n"); } }; } exitCmdMode(); //leave command mode return false; } void Wifly::enableDHCP(bool DHCP_STATIC) { state.dhcp = DHCP_STATIC; } void Wifly::setStaticIP(const char *staticIP) { char buffer[100]; strcpy(this->staticIP,staticIP); sprintf(buffer,"IPset---: %s\n",this->staticIP); myDebug.printf(buffer); } ///////////////////////////////////////// //::setBaudRate() // //Baudrate can be change on the fly //Once the command is sent the RN-171 //will exit the command mode bool Wifly::setBaudRate(int baud) { char cmd[60]; sprintf(cmd, "set u b %i\r", baud); if ( !sendCommand(cmd, "AOK") ) { return false; } //Automatically exits command mode state.cmd_mode = false; return true; } bool Wifly::setProtocol(Protocol p) { // use udp auto pairing char cmd[20]; sprintf(cmd, "set i p %d\r", p); if (!sendCommand(cmd, "AOK")) return false; switch(p) { case TCP: // set ip flags: tcp retry enabled if (!sendCommand("set i f 0x07\r", "AOK")) return false; break; case UDP: // set ip flags: udp auto pairing enabled if (!sendCommand("set i h 0.0.0.0\r", "AOK")) return false; if (!sendCommand("set i f 0x40\r", "AOK")) return false; break; } state.proto = p; return true; } char * Wifly::getStringSecurity() { switch(state.sec) { case NONE: return "NONE"; case WEP_128: return "WEP_128"; case WPA: return "WPA"; } return "UNKNOWN"; } bool Wifly::connect(const char * host, int port) { char rcv[20]; char cmd[20]; // try to open sprintf(cmd, "open %s %d\r", host, port); if (sendCommand(cmd, "OPEN", NULL, 10000)) { state.tcp = true; state.cmd_mode = false; return true; } // if failed, retry and parse the response if (sendCommand(cmd, NULL, rcv, 5000)) { if (strstr(rcv, "OPEN") == NULL) { if (strstr(rcv, "Connected") != NULL) { wait(0.25); if (!sendCommand("close\r", "CLOS")) return false; wait(0.25); if (!sendCommand(cmd, "OPEN", NULL, 10000)) return false; } else { return false; } } } else { return false; } state.tcp = true; state.cmd_mode = false; return true; } bool Wifly::gethostbyname(const char * host, char * ip) { string h = host; char cmd[30], rcv[100]; int l = 0; char * point; int nb_digits = 0; // no dns needed int pos = h.find("."); if (pos != string::npos) { string sub = h.substr(0, h.find(".")); nb_digits = atoi(sub.c_str()); } //printf("substrL %s\r\n", sub.c_str()); if (count(h.begin(), h.end(), '.') == 3 && nb_digits > 0) { strcpy(ip, host); } // dns needed else { nb_digits = 0; sprintf(cmd, "lookup %s\r", host); if (!sendCommand(cmd, NULL, rcv)) return false; // look for the ip address char * begin = strstr(rcv, "=") + 1; for (int i = 0; i < 3; i++) { point = strstr(begin + l, "."); DBG("str: %s", begin + l); l += point - (begin + l) + 1; } DBG("str: %s", begin + l); while(*(begin + l + nb_digits) >= '0' && *(begin + l + nb_digits) <= '9') { DBG("digit: %c", *(begin + l + nb_digits)); nb_digits++; } memcpy(ip, begin, l + nb_digits); ip[l+nb_digits] = 0; DBG("ip from dns: %s", ip); } return true; } void Wifly::flush() { while (wifiSer.readable()) wifiSer.getc(); } //////////////////////////////////////////////////////////// //sendCommand() // // // // // // //////////////////////////////////////////////////////////// bool Wifly::sendCommand(const char * cmd, const char * ack, char * res, int timeout, bool DHCPconn) { if (!state.cmd_mode) { cmdMode(); } // Expected res strRet switch( this->sendString(cmd, strlen(cmd), ack, res, timeout, DHCPconn) ) { case 0: //myDebug.printf("...OK\n"); return true; case 1: // myDebug.printf("Time out\n"); //do a retry // exitCmdMode(); return false; case 2: //DHCP connected state.associated = true; myDebug.printf("DHCP CONNECTED\n"); exitCmdMode(); return true; case 3: myDebug.printf("DHCP Failed\n"); //do a retry // exitCmdMode(); return false; default: exitCmdMode(); return false; }; return false; } bool Wifly::cmdMode() { // if already in cmd mode, return if (state.cmd_mode) return true; if ( this->sendString("$$$", 3, "CMD") == -1) { ERR("cannot enter in cmd mode\r\n"); exitCmdMode(); return false; } state.cmd_mode = true; return true; } bool Wifly::disconnect() { // if already disconnected, return if (!state.associated) return true; if (!sendCommand("leave\r", "DeAuth")) return false; exitCmdMode(); state.associated = false; return true; } bool Wifly::is_connected() { return (tcp_status.read() == 1) ? true : false; } bool Wifly::reset(bool howIreset) { if(howIreset) { reset_pin = 0; wait(0.2); reset_pin = 1; wait(0.2); } else { // sendToDisplay(RS485Cmd,0,"software Reset\n"); sendCommand("factory R\r", "Defaults"); wait_ms(10); sendCommand("save\r", "Stor"); return true; } return true; } bool Wifly::reboot() { // if already in cmd mode, return if ( !sendCommand("reboot\r", "Reboot",NULL,5000,false) ) return false; wait(0.3); state.cmd_mode = false; return true; } ///////////////////////////////////////// //::close() // //disconnect a TCP connection. //////////////////////////////////////// bool Wifly::close() { // if not connected, return if (!state.tcp) return true; wait(0.25); if (!sendCommand("close\r", "CLOS")) return false; exitCmdMode(); state.tcp = false; return true; } ///////////////////////////////////////// //::putc() // //Wrapper for wiFiSerial putc() int Wifly::putc(char c) { return wifiSer.putc(c); } ///////////////////////////////////////// //exitCmdMode() // //Tell WiFi module to exit command mode bool Wifly::exitCmdMode() { flush(); ////////////////////////// ///We flush the buffer while (wifiSer.readable()) wifiSer.getc(); if (!state.cmd_mode) return true; if (!sendCommand("exit\r", "EXIT")) return false; state.cmd_mode = false; ////////////////////////// ///We flush the buffer while (wifiSer.readable()) wifiSer.getc(); return true; } ///////////////////////////////////////// //readable() // //BufferedSerial buffer has data? int Wifly::readable() { return wifiSer.readable(); //// note: look if things are in the buffer; } ///////////////////////////////////////// //writeable() // //BufferedSerial This call will always //return true. the cicular queue will //always allow data int Wifly::writeable() { return wifiSer.writeable(); } char Wifly::getc() { char c; c = wifiSer.getc(); // while (!buf_wifly.available()); // buf_wifly.dequeue(&c); return c; } ///////////////////////////////////////////////////// ///These two functions are no longer needed since ///The BufferedSerial class takes care of this void Wifly::handler_rx(void) { //read characters // while (wifiSer.readable()) // buf_wifly.queue(wifiSer.getc()); } void Wifly::attach_rx(bool callback) { /* if (!callback) wifiSer.attach(NULL); else wifiSer.attach(this, &Wifly::handler_rx);*/ } //////////////////////////////////////////////////////////// //sendString() // // // // // // //////////////////////////////////////////////////////////` int Wifly::sendString(const char * str, int len, const char * ACK, char * res, int timeout,bool DHCPconn) { char read; size_t found = string::npos; //same as -1 substring not found else position of string size_t DHCPnotCONN = string::npos; string AUTH_ERR = "AUTH-ERR"; //Error string on DHCP invalid SSID or PAss Phrase string FAILED = "NONE FAILED"; string DHCP_CONN = "DHCP=ON"; string checking; Timer tmr; int result = 0; char buffer[280]; int pos = 0; int DHCPconnect = 0; // DBG("will send: %s\r\n","checka: %s\r\n",); // attach_rx(false); //sprintf(buffer,"will send: %s\r\n", str); //myDebug.printf(buffer); //We flush the buffer while (wifiSer.readable()) wifiSer.getc(); ////////////////////////////////////////// ///This is probably a get command if (!ACK || !strcmp(ACK, "NO")) { for (int i = 0; i < len; i++) { result = (putc(str[i]) == str[i]) ? result + 1 : result; } } else { // myDebug.printf("here1\n"); //We flush the buffer while (wifiSer.readable()) wifiSer.getc(); tmr.start(); //////////////////////////////////////// ///Send command to wiFly transciver for (int i = 0; i < len; i++) { result = (putc(str[i]) == str[i]) ? result + 1 : result; } //////////////////////////////////////// ///Now get expected results while (1) { ////////////////////////////// ///Time has expired if (tmr.read_ms() > timeout) { // myDebug.printf("timeout!\n"); //We flush the buffer while (wifiSer.readable()) wifiSer.getc(); sprintf(buffer,"timeout: %s\r\n", checking.c_str()); myDebug.printf(buffer); //DBG("check: %s\r\n", checking.c_str()); // attach_rx(true); return 1; } else if (wifiSer.readable()) { read = wifiSer.getc(); if ( read != '\r' && read != '\n') { //////////////////////////////////////// ///This method is ineficient!!! checking += read; found = checking.find(ACK); //////////////////////////////////////// ///if a + value string found if (found != string::npos) { wait(0.01); // sprintf(buffer,"found: %s\n",checking.c_str() ); // myDebug.printf(buffer); ////////////////////////// ///We flush the buffer while (wifiSer.readable()) wifiSer.getc(); if( DHCP_CONN.find(ACK) != string::npos) { return 2; //successful DHCP } return 0; //found string 0 good // break; } /////////////////////////////////////////////////// ///Special case check for DHCP attempt connection if(DHCPconn) { DHCPnotCONN = checking.find(AUTH_ERR); if (DHCPnotCONN != string::npos) { wait(0.01); sprintf(buffer,"AUTH-ERR: %s\n",checking.c_str() ); myDebug.printf(buffer); ////////////////////////////// ///We flush the buffer while (wifiSer.readable()) wifiSer.getc(); return 3; //DHCP Error // break; } DHCPnotCONN = checking.find(FAILED); if (DHCPnotCONN != string::npos) { wait(0.01); sprintf(buffer,"NONE FAILED: %s\n",checking.c_str() ); myDebug.printf(buffer); //We flush the buffer while (wifiSer.readable()) wifiSer.getc(); return 3; // break; } }//if(DHCPconn} }//if ( read != '\r' && read != '\n') }//else if (wifiSer.readable()) } //while (1) // sprintf(buffer,"check2: %s\r\n", checking.c_str()); // myDebug.printf(buffer); // DBG("check: %s\r\n", checking.c_str()); // attach_rx(true); return result; } //the user wants the result from the command (ACK == NULL, res != NULL) if ( res != NULL) { int i = 0; Timer timeout; timeout.start(); tmr.reset(); while (1) { if (timeout.read() > 2) { if (i == 0) { res = NULL; break; } res[i] = '\0'; // DBG("user str 1: %s\r\n", res); break; } else { if (tmr.read_ms() > 300) { res[i] = '\0'; // DBG("user str: %s\r\n", res); break; } if (wifiSer.readable()) { tmr.start(); read = wifiSer.getc(); // we drop \r and \n if ( read != '\r' && read != '\n') { res[i++] = read; } } } } // DBG("user str: %s\r\n", res); return 0; } // //We flush the buffer // while (wifiSer.readable()) // wifiSer.getc(); // attach_rx(true); //DBG("result: %d\r\n", result) return 1; } /* if( read == ACK[pos] ) { pos++; sprintf(buffer,"cmp: %d\n",pos); myDebug.printf(buffer); if(pos == len) { myDebug.printf("myCompare-Break\n"); /////////////////////////// ///We have a compare //We flush the buffer while (wifiSer.readable()) wifiSer.getc(); break; } }//if( read == ACK[pos] ) else { if(pos == len) { myDebug.printf("myCompare2\n"); } else pos = 0; } */