Library to use a wifly module: RN 131 C/G

Dependents:   RN-XV_simple_server

Wifly.cpp

Committer:
samux
Date:
2012-05-09
Revision:
19:cf1a7a5cc8d6
Parent:
18:88a26cd00ba3

File content as of revision 19:cf1a7a5cc8d6:

#include "mbed.h"
#include "Wifly.h"
#include <string>

//#define DEBUG

Wifly::Wifly(   PinName tx, PinName rx, PinName _reset, char * ssid, char * phrase,
                bool wpa, char * ip, char * netmask, bool dhcp, int baudrate):
        wifi(tx, rx), reset_pin(_reset) {
    wifi.baud(baudrate);
    wifi.format(8, Serial::None, 1);
    this->wpa = wpa;
    this->dhcp = dhcp;
    strcpy(this->phrase, phrase);
    strcpy(this->ssid, ssid);
    strcpy(this->ip, ip);
    strcpy(this->netmask, netmask);
    adhoc = false;

    reset();
}

Wifly::Wifly(   PinName tx, PinName rx, PinName _reset, char * ssid, char * ip, char * netmask, int channel, int baudrate):
        wifi(tx, rx), reset_pin(_reset) {
    wifi.baud(baudrate);
    wifi.format(8, Serial::None, 1);
    adhoc = true;
    strcpy(this->ssid, ssid);
    strcpy(this->ip, ip);
    strcpy(this->netmask, netmask);
    this->channel = channel;

    reset();
}

void Wifly::handler_rx(void) {

    //read the character
    char read = wifi.getc();

    //queue it
    buf_wifly.queue(read);

    //call user callback
    rx.call();
}

void Wifly::attach_rx(bool callback) {
    if (!callback)
        wifi.attach(NULL);
    else
        wifi.attach(this, &Wifly::handler_rx);
}

bool Wifly::send(char * str, char * ACK, char * res) {
    char read;
    size_t found = string::npos;
    string checking;
    Timer tmr;

#ifdef DEBUG
    printf("will send: %s\r\n",str);
#endif

    attach_rx(false);
    if (!ACK || !strcmp(ACK, "NO")) {
        wifi.printf("%s", str);
    } else {
        //We flush the buffer
        while (wifi.readable())
            wifi.getc();

        tmr.start();
        wifi.printf("%s", str);

        while (1) {
            if (tmr.read() > 3) {
                //We flush the buffer
                while (wifi.readable())
                    wifi.getc();
#ifdef DEBUG
                printf("check: %s\r\n", checking.c_str());
#endif
                attach_rx(true);
                return false;
            } else if (wifi.readable()) {
                read = wifi.getc();
                if ( read != '\r' && read != '\n') {
                    checking += read;
                    found = checking.find(ACK);
                    if (found != string::npos) {
                        wait(0.01);

                        //We flush the buffer
                        while (wifi.readable())
                            wifi.getc();

                        break;
                    }
                }
            }
        }
#ifdef DEBUG
        printf("check: %s\r\n", checking.c_str());
#endif
        attach_rx(true);
        return true;
    }

    //the user wants the result from the command (ACK == NULL, res != NULL)
    if ( res != NULL) {
        int i = 0;
        Timer timeout;
        timeout.start();
        while (1) {
            if (timeout.read() > 3) {
                read = NULL;
                attach_rx(true);
                return false;
            } else {
                if (tmr.read_ms() > 500) {
                    res[i] = 0;
#ifdef DEBUG
                    printf("user str: %s\r\n", res);
#endif
                    break;
                }
                if (wifi.readable()) {
                    tmr.start();
                    read = wifi.getc();

                    // wa have detected an end of response
                    if (read == '<') {
                        res[i] = 0;
                        break;
                    }

                    // we drop \r and \n
                    if ( read != '\r' && read != '\n') {
                        res[i++] = read;
                    }
                }
            }
        }
#ifdef DEBUG
        //printf("user str: %s\r\n", res);
#endif
    }
    attach_rx(true);
    return true;
}

bool Wifly::join() {
    char cmd[150];

    if (!adhoc) {
        //enter in command mode
        if (!cmdMode()) {
#ifdef DEBUG
            printf("join: cannot enter in cmd mode\r\n");
#endif
            // send fake command otherwise exit() will fail as $$$exit\r will be sent
            // this is because there is no \ê at the end of $$$
            send("a\r");
            wait(0.2);
            exit();
            if (!cmdMode())
                return false;
        }

        // to get all wlan parameters
        if (!send("get w\r", NULL, cmd)) {
#ifdef DEBUG
            printf("join: cannot get wlan settings\r\n");
#endif
            exit();
            return false;
        }

        // if the wlan parameters are already known, we just connect without resending all commands
        if ((string(cmd).find(ssid) != string::npos) && (string(cmd).find(phrase) != string::npos) ) {
#ifdef DEBUG
            printf("ssid found && phrase found\r\n");
#endif
            Timer tmr;
            tmr.start();
            while (tmr.read() < 2) {
                send("show c\r", NULL, cmd);
#ifdef DEBUG
                printf("join: state of conn: %s\r\n", cmd);
#endif
                if ((cmd[2] - '0') & 0x01) {
                    exit();
                    return true;
                }
                wait(0.2);
            }
        }

#ifdef DEBUG
        printf("getw: %s\r\n", cmd);
#endif

        // ssid
        sprintf(cmd, "set w s %s\r", ssid);
        if (!send(cmd, "AOK")) {
#ifdef DEBUG
            printf("join: cannot set ssid\r\n");
#endif
            exit();
            return false;
        }

        //auth
        sprintf(cmd, "set w a %d\r", (wpa) ? 3 : 1);
        if (!send(cmd, "AOK")) {
#ifdef DEBUG
            printf("join: cannot set auth\r\n");
#endif
            exit();
            return false;
        }

        //dhcp
        sprintf(cmd, "set i d %d\r", (dhcp) ? 1 : 0);
        if (!send(cmd, "AOK")) {
#ifdef DEBUG
            printf("join: cannot set dhcp\r\n");
#endif
            exit();
            return false;
        }

        //no echo
        if (!send("set u m 1\r", "AOK")) {
#ifdef DEBUG
            printf("join: cannot set no echo\r\n");
#endif
            exit();
            return false;
        }

        // if no dhcp, set ip and netmask
        if (!dhcp) {
#ifdef DEBUG
            printf("not dhcp\r");
#endif
            sprintf(cmd, "set i a %s\r\n", ip);
            if (!send(cmd, "AOK")) {
#ifdef DEBUG
                printf("Wifly::join: cannot set ip address\r\n");
#endif
                exit();
                return false;
            }

            sprintf(cmd, "set i n %s\r", netmask);
            if (!send(cmd, "AOK")) {
#ifdef DEBUG
                printf("Wifly::join: cannot set netmask\r\n");
#endif
                exit();
                return false;
            }
        }

        //key step
        if (wpa)
            sprintf(cmd, "set w p %s\r", phrase);
        else
            sprintf(cmd, "set w k %s\r", phrase);

        if (!send(cmd, "AOK")) {
#ifdef DEBUG
            printf("join: cannot set phrase\r\n");
#endif
            exit();
            return false;
        }

        // auto join
        if (!send("set w j 1\r", "AOK")) {
#ifdef DEBUG
            printf("Wifly::join: cannot set join 1\r\n");
#endif
            exit();
            return false;
        }

        // save
        if (!send("save\r", "Stor")) {
#ifdef DEBUG
            printf("Wifly::join: cannot save\r\n");
#endif
            exit();
            return false;
        }

        //join the network
        sprintf(cmd, "join %s\r", ssid);

        if (!send(cmd, "Associated!")) {
#ifdef DEBUG
            printf("join: cannot join %s\r\n", ssid);
#endif
            exit();
            return false;
        }
        exit();

#ifdef DEBUG
        printf("\r\nssid: %s\r\nphrase: %s\r\nsecurity: %s\r\n\r\n", this->ssid, this->phrase, (wpa) ? "WPA" : "WEP");
#endif
        return true;
    } else {
#ifdef DEBUG
        printf("Wifly::join: You didn't choose the right constructor to join a network!\r\n");
#endif
        return false;
    }
}



bool Wifly::createAdhocNetwork() {
    if (adhoc) {
        char cmd[50];

        if (!cmdMode()) {
#ifdef DEBUG
            printf("Wifly::CreateAdhocNetwork: cannot enter in cmd mode\r\n");
#endif
            exit();
            return false;
        }

        if (!send("set w j 4\r", "AOK")) {
#ifdef DEBUG
            printf("Wifly::CreateAdhocNetwork: cannot set join 4\r\n");
#endif
            exit();
            return false;
        }

        //no echo
        if (!send("set u m 1\r", "AOK")) {
#ifdef DEBUG
            printf("Wifly::CreateAdhocNetwork: cannot set no echo\r\n");
#endif
            exit();
            return false;
        }

        //ssid
        sprintf(cmd, "set w s %s\r", ssid);
        if (!send(cmd, "AOK")) {
#ifdef DEBUG
            printf("Wifly::CreateAdhocNetwork: cannot set ssid\r\n");
#endif
            exit();
            return false;
        }

        sprintf(cmd, "set w c %d\r", channel);
        if (!send(cmd, "AOK")) {
#ifdef DEBUG
            printf("Wifly::CreateAdhocNetwork: cannot set channel\r\n");
#endif
            exit();
            return false;
        }

        sprintf(cmd, "set i a %s\r", ip);
        if (!send(cmd, "AOK")) {
#ifdef DEBUG
            printf("Wifly::CreateAdhocNetwork: cannot set ip address\r\n");
#endif
            exit();
            return false;
        }

        sprintf(cmd, "set i n %s\r", netmask);
        if (!send(cmd, "AOK")) {
#ifdef DEBUG
            printf("Wifly::CreateAdhocNetwork: cannot set netmask\r\n");
#endif
            exit();
            return false;
        }

        if (!send("set i d 0\r", "AOK")) {
#ifdef DEBUG
            printf("Wifly::CreateAdhocNetwork: cannot set dhcp off\r\n");
#endif
            exit();
            return false;
        }

        if (!send("save\r", "Stor")) {
#ifdef DEBUG
            printf("Wifly::CreateAdhocNetwork: cannot save\r\n");
#endif
            exit();
            return false;
        }

        send("reboot\r", NULL);
#ifdef DEBUG
        printf("\r\ncreating an adhoc\r\nnetwork: %s\r\nip: %s\r\nnetmask: %s\r\nchannel: %d\r\n\r\n", ssid, ip, netmask, channel);
#endif
        return true;
    } else {
#ifdef DEBUG
        printf("Wifly::CreateAdhocNetwork: You didn't choose the right constructor for creating an adhoc mode!\r\n");
#endif
        return false;
    }
}

void Wifly::flush() {
    while (readable())
        getc();
}

bool Wifly::cmdMode() {
    if (!send("$$$", "CMD")) {
#ifdef DEBUG
        printf("Wifly::cmdMode: cannot enter in cmd mode\r\n");
#endif
        return false;
    }
    return true;
}


void Wifly::reset() {
    reset_pin = 0;
    wait(0.2);
    reset_pin = 1;
    wait(0.2);
}




void Wifly::putc(char c) {
    while (!wifi.writeable());
    wifi.putc(c);
}




bool Wifly::read(char * str) {
    int length = buf_wifly.available();
    if (length == 0)
        return false;
    for (int i = 0; i < length; i++)
        buf_wifly.dequeue((uint8_t *)&str[i]);
    str[length] = 0;
    return true;
}




bool Wifly::exit() {
    flush();
    return send("exit\r", "EXIT");
}



int Wifly::readable() {
    return buf_wifly.available();
}

bool Wifly::changeBaudrate(int baudrate) {
    char cmd[20];
    exit();
    if (!cmdMode()) {
#ifdef DEBUG
        printf("Wifly::changeBaudrate: cannot enter in cmd mode\r\n");
#endif
        return false;
    }

    sprintf(cmd, "set u b %d\r", baudrate);
    if (!send(cmd, "AOK")) {
#ifdef DEBUG
        printf("Wifly::changeBaudrate: cannot set new baudrate\r\n");
#endif
        exit();
        return false;
    }

    if (!send("save\r", "Stor")) {
#ifdef DEBUG
        printf("Wifly::changeBaudrate: cannot save\r\n");
#endif
        exit();
        return false;
    }

    return true;
}


char Wifly::getc() {
    char c;
    while (!buf_wifly.available());
    buf_wifly.dequeue((uint8_t *)&c);
    return c;
}