wifly/socket interface for wifly modules

Dependents:   WiFi neurGAI_WIFI thingspeak thingspeak2

Revision:
0:6ffb0aeb3972
Child:
1:8f04181f9ad8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Wifly/Wifly.cpp	Fri Aug 17 08:28:04 2012 +0000
@@ -0,0 +1,394 @@
+/* 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 "Wifly.h"
+#include <string>
+
+//Debug is disabled by default
+#if 0
+#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
+
+#define INFO(x, ...) printf("[Wifly : INFO]"x"\r\n", ##__VA_ARGS__);
+
+Wifly * Wifly::inst;
+
+Wifly::Wifly(   PinName tx, PinName rx, PinName _reset, PinName tcp_status, const char * ssid, const char * phrase, bool wpa):
+        wifi(tx, rx), reset_pin(_reset), tcp_status(tcp_status), buf_wifly(256) {
+    this->wpa = wpa;
+    this->phrase = phrase;
+    this->ssid = ssid;
+    inst = this;
+    attach_rx(false);
+    cmd_mode = false;
+}
+
+bool Wifly::join() {
+    char cmd[100];
+
+    if (!sendCommand("set comm time 20\r", "AOK"))
+        return false;
+
+    if (!sendCommand("set comm size 128\r", "AOK"))
+        return false;
+
+    if (!sendCommand("set sys iofunc 0x40\r", "AOK"))
+        return false;
+
+    // no string sent to the tcp client
+    if (!sendCommand("set comm remote 0\r", "AOK"))
+        return false;
+
+    // tcp protocol
+    if (!sendCommand("set ip proto 2\r", "AOK"))
+        return false;
+
+    // tcp retry
+    if (!sendCommand("set ip flags 0x7\r", "AOK"))
+        return false;
+
+    //no echo
+    if (!sendCommand("set u m 1\r", "AOK"))
+        return false;
+        
+    //dhcp
+    sprintf(cmd, "set i d %d\r", (dhcp) ? 1 : 0);
+    if (!sendCommand(cmd, "AOK"))
+        return false;
+
+    if (dhcp) {
+        if (!sendCommand("get w\r", NULL, cmd))
+            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) ) {
+            DBG("ssid found && phrase found\r\n");
+            Timer tmr;
+            tmr.start();
+            while (tmr.read() < 2) {
+                send("show c\r", 7, NULL, cmd);
+                DBG("join: state of conn: %s\r\n", cmd);
+                if ((cmd[2] - '0') & 0x01) {
+                    INFO("\r\nssid: %s\r\nphrase: %s\r\nsecurity: %s\r\n\r\n", this->ssid, this->phrase, (wpa) ? "WPA" : "WEP");
+                    // save
+                    if (!sendCommand("save\r", "Stor"))
+                        return false;
+                    reboot();
+                    return true;
+                }
+                wait(0.2);
+            }
+        }
+
+        DBG("getw: %s\r\n", cmd);
+    }
+
+    // ssid
+    sprintf(cmd, "set w s %s\r", ssid);
+    if (!sendCommand(cmd, "AOK"))
+        return false;
+
+    //auth
+    sprintf(cmd, "set w a %d\r", (wpa) ? 3 : 1);
+    if (!sendCommand(cmd, "AOK"))
+        return false;
+
+    // if no dhcp, set ip, netmask and gateway
+    if (!dhcp) {
+        DBG("not dhcp\r");
+
+        sprintf(cmd, "set i a %s\r\n", ip);
+        if (!sendCommand(cmd, "AOK"))
+            return false;
+
+        sprintf(cmd, "set i n %s\r", netmask);
+        if (!sendCommand(cmd, "AOK"))
+            return false;
+
+        sprintf(cmd, "set i g %s\r", gateway);
+        if (!sendCommand(cmd, "AOK"))
+            return false;
+    }
+
+    //key step
+    if (wpa)
+        sprintf(cmd, "set w p %s\r", phrase);
+    else
+        sprintf(cmd, "set w k %s\r", phrase);
+
+    if (!sendCommand(cmd, "AOK"))
+        return false;
+
+    // auto join
+    if (!sendCommand("set w j 1\r", "AOK"))
+        return false;
+
+    // save
+    if (!sendCommand("save\r", "Stor"))
+        return false;
+
+    //join the network
+    sprintf(cmd, "join %s\r", ssid);
+    if (!sendCommand(cmd, "Associated"))
+        return false;
+
+    reboot();
+
+    INFO("\r\nssid: %s\r\nphrase: %s\r\nsecurity: %s\r\n\r\n", this->ssid, this->phrase, (wpa) ? "WPA" : "WEP");
+    return true;
+}
+
+bool Wifly::reboot() {
+    if (!sendCommand("reboot\r", "boot"))
+        return false;
+    wait(0.2);
+    // wait that the module fetches an IP
+    if (dhcp) {
+        while(send("", 0, "DHCP=ON") == -1);
+    } else {
+        while(send("", 0, "Static") == -1);
+    }
+    flush();
+    cmd_mode = false;
+    return true;
+}
+
+
+void Wifly::flush() {
+    buf_wifly.flush();
+}
+
+bool Wifly::sendCommand(const char * cmd, const char * ack, char * res) {
+    if (!cmd_mode) {
+        cmdMode();
+    }
+    if (send(cmd, strlen(cmd), ack, res) == -1) {
+        ERR("sendCommand: cannot %s\r\n", cmd);
+        exit();
+        return false;
+    }
+    return true;
+}
+
+bool Wifly::cmdMode() {
+    if (send("$$$", 3, "CMD") == -1) {
+        ERR("cannot enter in cmd mode\r\n");
+        return false;
+    }
+    cmd_mode = true;
+    return true;
+}
+
+bool Wifly::leave() {
+    if (!sendCommand("leave\r", "DeAuth"))
+        return false;
+    exit();
+    return true;
+
+}
+
+bool Wifly::is_connected() {
+    return (tcp_status.read() ==  1) ? true : false;
+}
+
+
+void Wifly::reset() {
+    reset_pin = 0;
+    wait(0.2);
+    reset_pin = 1;
+    wait(0.2);
+}
+
+bool Wifly::close() {
+    wait(0.25);
+    if (!cmdMode())
+        return false;
+    if (send("close\r", 6, "CLOS") == -1)
+        return false;
+    exit();
+    return true;
+}
+
+
+int Wifly::putc(char c) {
+    while (!wifi.writeable());
+    return 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(&str[i]);
+    str[length] = 0;
+    return true;
+}
+
+
+bool Wifly::exit() {
+    flush();
+    if (send("exit\r", 5, "EXIT") == -1)
+        return false;
+    cmd_mode = false;
+    return true;
+}
+
+
+int Wifly::readable() {
+    return buf_wifly.available();
+}
+
+int Wifly::writeable() {
+    return wifi.writeable();
+}
+
+char Wifly::getc() {
+    char c;
+    while (!buf_wifly.available());
+    buf_wifly.dequeue(&c);
+    return c;
+}
+
+void Wifly::handler_rx(void) {
+    //read characters
+    while (wifi.readable())
+        buf_wifly.queue(wifi.getc());
+}
+
+void Wifly::attach_rx(bool callback) {
+    if (!callback)
+        wifi.attach(NULL);
+    else
+        wifi.attach(this, &Wifly::handler_rx);
+}
+
+
+int Wifly::send(const char * str, int len, const char * ACK, char * res) {
+    char read;
+    size_t found = string::npos;
+    string checking;
+    Timer tmr;
+    int result = 0;
+
+    DBG("will send: %s\r\n",str);
+
+    attach_rx(false);
+
+    //We flush the buffer
+    while (wifi.readable())
+        wifi.getc();
+
+    if (!ACK || !strcmp(ACK, "NO")) {
+        for (int i = 0; i < len; i++)
+            result = (putc(str[i]) == str[i]) ? result + 1 : result;
+    } else {
+        //We flush the buffer
+        while (wifi.readable())
+            wifi.getc();
+
+        tmr.start();
+        for (int i = 0; i < len; i++)
+            result = (putc(str[i]) == str[i]) ? result + 1 : result;
+
+        while (1) {
+            if (tmr.read() > 3) {
+                //We flush the buffer
+                while (wifi.readable())
+                    wifi.getc();
+
+                DBG("check: %s\r\n", checking.c_str());
+
+                attach_rx(true);
+                return -1;
+            } 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;
+                    }
+                }
+            }
+        }
+        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() > 3) {
+                if (i == 0) {
+                    res = NULL;
+                    break;
+                }
+                res[i] = '\0';
+                DBG("user str 1: %s\r\n", res);
+
+                break;
+            } else {
+                if (tmr.read_ms() > 1000) {
+                    res[i] = '\0';
+                    DBG("user str: %s\r\n", res);
+
+                    break;
+                }
+                if (wifi.readable()) {
+                    tmr.start();
+                    read = wifi.getc();
+
+                    // we drop \r and \n
+                    if ( read != '\r' && read != '\n') {
+                        res[i++] = read;
+                    }
+                }
+            }
+        }
+        DBG("user str: %s\r\n", res);
+    }
+
+    //We flush the buffer
+    while (wifi.readable())
+        wifi.getc();
+
+    attach_rx(true);
+    DBG("result: %d\r\n", result)
+    return result;
+}
\ No newline at end of file