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:
76:371aab9902a4
Parent:
73:bb5bbca971ae
Parent:
75:7ad32827b39e
Child:
79:f356009dbc12

File content as of revision 76:371aab9902a4:

#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) != SUCCESS) {
        return false;
    }

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

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

    //Set device into DHCP mode
    if (sendBasicCommand("set ip dhcp 1", 1000) != SUCCESS) {
        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()
{
}

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

    //Set the appropraite SSID
    code = sendBasicCommand("set wlan ssid " + ssid, 1000);
    if (code != SUCCESS) {
        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, 1000);
        if (code != SUCCESS) {
            return code;
        }
    } else if (type == WPA || type == WPA2) {
        //Set the WPA key if using WPA encryption
        code = sendBasicCommand("set wlan phrase " + key, 1000);
        if (code != SUCCESS) {
            return code;
        }
    }

    _ssid = ssid;
    return SUCCESS;
}

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, NONE);
    if (response.find("CMD") != string::npos) {
        return true;
    }
    return false;
}

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

    string response = sendCommand(command, timeoutMillis, esc);
    //printf("Response: %s\n\r", response.c_str());
    if (response.size() == 0) {
        return NO_RESPONSE;
    } else if (response.find("AOK") != string::npos) {
        return SUCCESS;
    } else if (response.find("ERR") != string::npos) {
        return ERROR;
    } else {
        return FAILURE;
    }
}

string Wifi::sendCommand(string command, int timeoutMillis, 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 "";
    }

    io->rxClear();
    io->txClear();
    std::string result;
    
    //Attempt to write command
    if(io->write(command.data(), command.size(), timeoutMillis) != command.size()) {
        //Failed to write command
        printf("[ERROR] failed to send command to radio within %d milliseconds\r\n", timeoutMillis);
        return "";
    }
    
    //Send Escape Character
    if (esc != 0x00) {
        if(io->write(esc, timeoutMillis) != 1) {
            printf("[ERROR] failed to send '%c' to radio within %d milliseconds\r\n", esc, timeoutMillis);
            return "";
        }
    }

    int timer = 0;
    size_t previous = 0;
    char tmp[256];
    tmp[255] = 0;
    bool started = !echoMode;
    bool done = false;
    do {
        wait(.1);
        timer = timer + 100;
        previous = result.size();
        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 =  (result.size() == previous);
        }
        if(timer >= timeoutMillis) {
            printf("[WARNING] sendCommand timed out after %d milliseconds\r\n", timeoutMillis);
            done = true;
        }
    } while (!done);
    
    return result;
}