A library for talking to Multi-Tech's Cellular SocketModem Devices.

Dependents:   M2X_dev axeda_wrapper_dev MTS_M2x_Example1 MTS_Cellular_Connect_Example ... more

wifi/Wifi.cpp

Committer:
jengbrecht
Date:
2013-12-26
Revision:
74:9f87bd22c222
Parent:
69:f3e696bbb0d5
Child:
75:7ad32827b39e

File content as of revision 74:9f87bd22c222:

#include "Wifi.h"

Wifi* Wifi::instance = NULL;

Wifi* Wifi::getInstance()
{
    if(instance == NULL) {
        instance = new Wifi(NULL);
    }
    return instance;
}

bool Wifi::init(MTSBufferedIO* io)
{
    if (io == NULL) {
        return false;
    }
    instance->io = io;
    if(cmdMode()) {
        return true;
    }
    printf("[ERROR] Failed to enter command mode\r\n");
    return false;
}

Wifi::Wifi(MTSBufferedIO* io)
    : io(io)
    , echoMode(true)
    , wifiConnected(false)
    , mode(TCP)
    , socketOpened(false)
    , socketCloseable(true)
    , local_port(0)
    , host_port(0)
    , _ssid("")
{

}

Wifi::~Wifi()
{
}

bool Wifi::connect()
{
    //Check if socket is open
    if(socketOpened) {
        return true;
    }

    //Run Test first to validate a good state
    if(isConnected()) {
        return true;
    }

    //Check RSSI: AT+CSQ
    //int rssi = getSignalStrength();
    //printf("[DEBUG] Signal strength: %d\r\n", rssi);

    //Possibly add a scan command here and look for the network....

    printf("Starting Setup\n\r");
    //Set device to manual infrastructure mode
    if (sendBasicCommand("set wlan join 0", 1000) != Cellular::CELL_OK) {
        return false;
    }

    printf("Set Manual Mode\n\r");
    //Set device to channel auto-scanning mode
    if (sendBasicCommand("set wlan channel 0", 1000) != Cellular::CELL_OK) {
        return false;
    }

    //Set device so no data is transmitted immediately following a socket connection
    if (sendBasicCommand("set comm remote 0", 1000) != Cellular::CELL_OK) {
        return false;
    }

    //Set device into DHCP mode
    if (sendBasicCommand("set ip dhcp 1", 1000) != Cellular::CELL_OK) {
        return false;
    }

    //join my_network

    //AT#CONNECTIONSTART: Make a PPP connection
    printf("[DEBUG] Making SSID Connection Attempt. SSID[%s]\r\n", _ssid.c_str());
    std::string result = sendCommand("join " + _ssid, 10000);
    printf("Connect Status: %s\n\r", result.c_str());
    //std::string pppResult = sendCommand("AT#CONNECTIONSTART", 120000);
    // std::vector<std::string> parts = Text::split(pppResult, "\r\n");

    /*
    if(pppResult.find("Ok_Info_GprsActivation") != std::string::npos) {
        if(parts.size() >= 2) {
            local_address = parts[1];
        }
        printf("[INFO] PPP Connection Established: IP[%s]\r\n", local_address.c_str());
        pppConnected = true;

    } else {
        pppConnected = false;
    }
    */

    wifiConnected = true;
    return wifiConnected;
}

void Wifi::disconnect()
{
}

bool Wifi::isConnected()
{
    return false;
}

bool Wifi::bind(unsigned int port)
{
    return true;
}

bool Wifi::open(const std::string& address, unsigned int port, Mode mode)
{
    //set comm size??? are advanced Socket settings
    //set comm time??? are advanced Socket settings
    return true;
}

bool Wifi::isOpen()
{
    return true;
}

bool Wifi::close()
{
    return true;
}

int Wifi::read(char* data, int max, int timeout)
{
    return 0;
}

int Wifi::write(const char* data, int length, int timeout)
{
    return 0;
}

unsigned int Wifi::readable()
{
    if(io == NULL) {
        printf("[ERROR] MTSBufferedIO not set\r\n");
        return 0;
    }
    if(!socketOpened) {
        printf("[ERROR] Socket is not open\r\n");
        return 0;
    }
    return io->readable();
}

unsigned int Wifi::writeable()
{
    if(io == NULL) {
        printf("[ERROR] MTSBufferedIO not set\r\n");
        return 0;
    }
    if(!socketOpened) {
        printf("[ERROR] Socket is not open\r\n");
        return 0;
    }

    return io->writeable();
}

void Wifi::reset()
{
}

Cellular::Code Wifi::echo(bool state)
{
    //Code code;
    if (state) {
        //code = sendBasicCommand("ATE0", 1000);
        //set uart mode 1 - Disabled
        //echoMode = (code == CELL_OK) ? false : echoMode;
    } else {
        //code = sendBasicCommand("ATE1", 1000);
        //set uart mode 0 - Enabled
        //echoMode = (code == CELL_OK) ? true : echoMode;
    }
    return Cellular::CELL_OK;
}

Cellular::Code Wifi::setNetwork(const std::string& ssid, const std::string& key, SecurityType type)
{
    Cellular::Code code;

    //Set the appropraite SSID
    code = sendBasicCommand("set wlan ssid " + ssid, 2000);
    if (code != Cellular::CELL_OK) {
        return code;
    }

    //Set the security key
    if (type == WEP64 || type == WEP128) {
        //Set the WEP key if using WEP encryption
        code = sendBasicCommand("set wlan key " + key, 2000);
        if (code != Cellular::CELL_OK) {
            return code;
        }
    } else if (type == WPA || type == WPA2) {
        //Set the WPA key if using WPA encryption
        code = sendBasicCommand("set wlan phrase " + key, 2000);
        if (code != Cellular::CELL_OK) {
            return code;
        }
    }

    _ssid = ssid;
    return Cellular::CELL_OK;
}

int Wifi::getSignalStrength()
{
    string response = sendCommand("show rssi", 2000);
    if (response.find("RSSI") == string::npos) {
        return -1;
    }
    int start = response.find('(');
    int stop = response.find(')', start);
    string signal = response.substr(start + 1, stop - start - 1);
    int value;
    sscanf(signal.c_str(), "%d", &value);
    return value;
}

bool Wifi::cmdMode()
{
    wait(.5);
    std::string response = sendCommand("$$$", 2000, Cellular::NONE);
    if (response.find("CMD") != string::npos) {
        return true;
    }
    return false;
}

Cellular::Code Wifi::sendBasicCommand(string command, int timeoutMillis, Cellular::ESC_CHAR esc)
{
    if(socketOpened) {
        printf("[ERROR] socket is open. Can not send AT commands\r\n");
        return Cellular::CELL_ERROR;
    }

    string response = sendCommand(command, timeoutMillis, esc);
    //printf("Response: %s\n\r", response.c_str());
    if (response.size() == 0) {
        return Cellular::CELL_NO_RESPONSE;
    } else if (response.find("AOK") != string::npos) {
        return Cellular::CELL_OK;
    } else if (response.find("ERR") != string::npos) {
        return Cellular::CELL_ERROR;
    } else {
        return Cellular::CELL_FAILURE;
    }
}

string Wifi::sendCommand(string command, int timeoutMillis, Cellular::ESC_CHAR esc)
{
    if(io == NULL) {
        printf("[ERROR] MTSBufferedIO not set\r\n");
        return "";
    }
    if(socketOpened) {
        printf("[ERROR] socket is open. Can not send AT commands\r\n");
        return "";
    }

    int size = command.size() + 1;
    char cmd[size];
    strcpy(cmd, command.c_str());
    if (esc == Cellular::CR) {
        cmd[size -1] = '\r';
    } else if (esc == Cellular::CTRL_Z) {
        cmd[size -1] = 0x1A;
    } else if(esc == NONE) {
        size = size - 1;
    }

    io->rxClear();
    io->txClear();
    std::string result;
    int status = io->write(cmd, size);
    int available = io->readable();
    int previous = -1;
    int timer = 0;
    char tmp[256];
    tmp[255] = 0;
    bool started = !echoMode;
    bool done = false;
    do {
        wait(.2);
        timer = timer + 200;
        previous = available;
        available = io->readable();

        int size = io->read(tmp,255);    //1 less than allocated
        if(size > 0) {
            result.append(tmp, size);
        }

        if(!started) {
            //In Echo Mode (Command will have echo'd + 2 characters for \r\n)
            if(result.size() > command.size() + 2) {
                started = true;
            }
        } else {
            done =  (available == previous);
        }
        if(timer >= timeoutMillis) {
            printf("[WARNING] sendCommand timed out after %d milliseconds\r\n", timeoutMillis);
            done = true;
        }
    } while (!done);

    return result;
}