this is using the mbed os version 5-13-1

Dependencies:   mbed-http

source/WiFiManager.cpp

Committer:
ocomeni
Date:
2019-03-29
Revision:
87:99b37d26ff2a
Parent:
86:04fc2fcda7ec
Child:
88:7ffa053be662

File content as of revision 87:99b37d26ff2a:

#include "WiFiManager.h"
#include "common_config.h"


WiFiManager::WiFiManager(wifi_config_t wifi_config, WiFiInterface *wifi, 
                         MemoryPool<wifi_cmd_message_t, 16> *aT2WiFimPool, 
                         Queue<wifi_cmd_message_t, 16> *aT2WiFiCmdQueue, 
                         MemoryPool<at_resp_message_t, 16> *wiFi2ATmPool, 
                         Queue<at_resp_message_t, 16> *wiFi2ATCmdQueue, 
                         MemoryPool<wifi_data_msg_t, PQDSZ> *aT2WiFiDatamPool, 
                         Queue<wifi_data_msg_t, PQDSZ> *aT2WiFiDataQueue, 
                         MemoryPool<at_data_msg_t, PQDSZ> *wiFi2ATDatamPool, 
                         Queue<at_data_msg_t, PQDSZ> *wiFi2ATDataQueue) 
:
     wifi_config(wifi_config),
     network(wifi),
    _aT2WiFimPool(aT2WiFimPool),
    _aT2WiFiCmdQueue(aT2WiFiCmdQueue),
    
    _wiFi2ATmPool(wiFi2ATmPool),
    _wiFi2ATCmdQueue(wiFi2ATCmdQueue),
    
    _aT2WiFiDatamPool(aT2WiFiDatamPool),
    _aT2WiFiDataQueue(aT2WiFiDataQueue),
    
    _wiFi2ATDatamPool(wiFi2ATDatamPool),
    _wiFi2ATDataQueue(wiFi2ATDataQueue)

{
 lastScanCount = 0;
 wifiCmd = WIFI_CMD_NONE;
 internet_config.connectionScheme = ALWAYS_CONNECTED; // set default connection scheme
 is_connected = false;
 chunkNum = 0;
}

WiFiManager::~WiFiManager()
{
}
  
bool WiFiManager::queueATresponse(at_cmd_resp_t resp){
    at_resp_message_t *atResp  = _wiFi2ATmPool->alloc();
    atResp->at_resp            = resp;
    _wiFi2ATCmdQueue->put(atResp);
    return true;
}


bool WiFiManager::queueWiFiDataResponse(at_data_msg_t at_resp){
    at_data_msg_t *atData = _wiFi2ATDatamPool->alloc();
    atData->at_resp        = at_resp.at_resp;
    atData->dataLen        = at_resp.dataLen;
    memcpy(atData->buffer, at_resp.buffer, at_resp.dataLen);
    _wiFi2ATDataQueue->put(atData);
    printf("[WIFI MAN] queued data size = %d : at_resp = %d\n", at_resp.dataLen, at_resp.at_resp);
    return true;
}



void WiFiManager::runMain(){
    nsapi_error_t error;
    printf("\r\n [WIFI MAN]  Thread Id = %d\r\n", Thread::gettid());
    while(true){
        dequeueWiFiCommands();
        dequeueATdataResponse();
        switch(wifiCmd){
            case WIFI_CMD_NONE:
                // IDLE STATE
                break;
            case WIFI_CMD_SCAN:
                error = scanNetworks();
                wifiCmd = WIFI_CMD_NONE;
                queueATresponse(AT_SCAN_RESP);
                break;
            case WIFI_CMD_DETAILED_SCAN:
                nsapi_size_or_error_t cnt_err;
                cnt_err = getAvailableAPs(lastScanCount);
                wifiCmd = WIFI_CMD_NONE;
                queueATresponse(AT_DETAILED_SCAN_RESP);
                break;
            case WIFI_CMD_CONNECT:
                error = connect();
                wifiCmd = WIFI_CMD_NONE;
                queueATresponse(AT_CONNECT_RESP);
                break;
            case WIFI_CMD_DISCONNECT:
                error = disconnect();
                wifiCmd = WIFI_CMD_NONE;
                queueATresponse(AT_DISCONNECT_RESP);
                break;
            case WIFI_CMD_CONFIG:
                set_WIFI_CONFIG();
                wifiCmd = WIFI_CMD_NONE;
                queueATresponse(AT_CONFIG_RESP);
                break;
            case WIFI_CMD_INTERNET_CONFIG:
                set_internet_config();
                wifiCmd = WIFI_CMD_NONE;
                queueATresponse(AT_INTERNET_CONFIG_RESP);
                break;
            case WIFI_CMD_SEND_HTTPS_REQ:
                createHttpsRequest();
                wifiCmd = WIFI_CMD_NONE;
                break;
            case WIFI_CMD_SEND_HTTP_REQ:
                break;
            default:
                break;
        }
        wait_ms(100); // 
    }
    
}

bool  WiFiManager::dequeueWiFiCommands(){
    if(wifiCmd != WIFI_CMD_NONE) return false; // busy
    osEvent evt = _aT2WiFiCmdQueue->get(0);
    if(evt.status == osEventMessage){
        wifi_cmd_message_t *cmd = (wifi_cmd_message_t*)evt.value.p;
        setNextCommand(cmd->wifi_cmd);
        _aT2WiFimPool->free(cmd);
    }
    return true;
}


bool WiFiManager::dequeueATdataResponse(){
    if(wifiCmd != WIFI_CMD_NONE) return false; // busy
    osEvent evt = _aT2WiFiDataQueue->get(0);
    if(evt.status == osEventMessage){
        data_msg = (wifi_data_msg_t*)evt.value.p;
        setNextCommand(data_msg->wifi_cmd);
        //_wiFi2ATDatamPool->free(data_msg);
    }
    return true;
}


bool WiFiManager::setNextCommand(wifi_cmd_t cmd)
{
    printf("\n [WIFI-MAN] About to set next WiFi manager command \n");
    if(wifiCmd == WIFI_CMD_NONE){
        wifiCmd = cmd;
        return true; // success
    }
    return false; // wiFiManager busy
}

const char * WiFiManager::sec2str(nsapi_security_t sec)
{
    switch (sec) {
        case NSAPI_SECURITY_NONE:
            return "None";
        case NSAPI_SECURITY_WEP:
            return "WEP";
        case NSAPI_SECURITY_WPA:
            return "WPA";
        case NSAPI_SECURITY_WPA2:
            return "WPA2";
        case NSAPI_SECURITY_WPA_WPA2:
            return "WPA/WPA2";
        case NSAPI_SECURITY_UNKNOWN:
        default:
            return "Unknown";
    }
}


nsapi_size_or_error_t WiFiManager::scanNetworks()
{
    nsapi_error_t error;
    printf("\n [WIFI-MAN] About to start scan for WiFi networks\n");
    lastScanCount = network->scan(NULL, 0);
    printf("\n [WIFI-MAN] Scan for WiFi networks completed - \n");
    return lastScanCount;
}


//nsapi_size_or_error_t WiFiManager::getAvailableAPs(WiFiAccessPoint * res, 
//                                                   nsapi_size_t ncount)
nsapi_size_or_error_t WiFiManager::getAvailableAPs(nsapi_size_t ncount)
{
    WiFiAccessPoint       *ap;
    nsapi_size_or_error_t count;
    count = ncount;
    //count = wiFiManager->scanNetworks();
    if (count <= 0) {
        //_smutex.lock();
        printf("[WIFI-MAN] scan() failed with return value: %d\n", count);
        //_smutex.unlock();
        return;
    }
    /* Limit number of network arbitrary to 15 */
    count = count < 15 ? count : 15;
    ap = new WiFiAccessPoint[count];
    count = network->scan(ap, count);
    if (count <= 0) {
        printf("[WIFI-MAN] scan() failed with return value: %d\n", count);
        return;
    }

    for (int i = 0; i < count; i++) {
        printf("[WIFI-MAN]: %s secured: %s BSSID: %hhX:%hhX:%hhX:%hhx:%hhx:%hhx RSSI: %hhd Ch: %hhd\n", ap[i].get_ssid(),
               sec2str(ap[i].get_security()), ap[i].get_bssid()[0], ap[i].get_bssid()[1], ap[i].get_bssid()[2],
               ap[i].get_bssid()[3], ap[i].get_bssid()[4], ap[i].get_bssid()[5], ap[i].get_rssi(), ap[i].get_channel());
    }
    printf("[WIFI-MAN]  %d networks available.\n", count);

    delete[] ap;
    return count;
}


void WiFiManager::set_WIFI_CONFIG()
{
    wifi_config_t *wifi_cfg= (wifi_config_t *) data_msg->buffer;
    if(wifi_cfg->ssid[0] != NULL)set_WIFI_SSID(wifi_cfg->ssid);
    if(wifi_cfg->pass[0] != NULL)set_WIFI_PASSWORD(wifi_cfg->pass);
    if(wifi_cfg->security != NSAPI_SECURITY_UNKNOWN)set_WIFI_SECURITY(wifi_cfg->security);
    free_DataMsg();
}

void WiFiManager::set_WIFI_SSID(char * wifi_ssid)
{
    strcpy(wifi_config.ssid, wifi_ssid);
    printf("[WIFI-MAN]  wifi_ssid set to %s\n", wifi_config.ssid);

}


void WiFiManager::set_WIFI_PASSWORD(char * wifi_pass)
{
    strcpy(wifi_config.pass, wifi_pass);
    printf("[WIFI-MAN]  wifi_pass set to %s\n", wifi_config.pass);
}


void WiFiManager::set_WIFI_SECURITY(nsapi_security_t wifi_security)
{
    wifi_config.security = wifi_security;
    printf("[WIFI-MAN]  wifi_security set to %s\n", sec2str(wifi_config.security));
}



void WiFiManager::set_internet_config()
{
    internet_config_t *internet_cfg  = (internet_config_t *) data_msg->buffer;
    internet_config.peer_id          = internet_cfg->peer_id;
    strncpy(internet_config.url,internet_cfg->url, strlen(internet_cfg->url)+1);
    internet_config.connectionScheme = internet_cfg->connectionScheme;
    free_DataMsg();
    printf("[WIFI MAN] Internet configuration setup completed\n"); 
    printf("peer_id = %1d, url = %s, connScheme = %1d\n", internet_config.peer_id, 
                                                      internet_config.url, 
                                                      internet_config.connectionScheme);
}

void WiFiManager::free_DataMsg()
{
    // free memory after processing
    _aT2WiFiDatamPool->free(data_msg);
}


void WiFiManager::status_callback(nsapi_event_t status, intptr_t param)
{
    //if (status == NSAPI_EVENT_CONNECTION_STATUS_CHANGE) {
    //}
    switch(param) {
        case NSAPI_STATUS_LOCAL_UP:
            printf("[WIFI-MAN] Local IP address set!\r\n");
            printf("[WIFI-MAN] IP address: %s\n", network->get_ip_address());
            break;
        case NSAPI_STATUS_GLOBAL_UP:
            printf("Global IP address set!\r\n");
            printf("[WIFI-MAN] IP address: %s\n", network->get_ip_address());
            printf("[WIFI-MAN] Connected to the network %s\n", wifi_config.ssid);
            is_connected = true;
            break;
        case NSAPI_STATUS_DISCONNECTED:
            printf("No connection to network!\r\n");
            printf("\n [WIFI-MAN] No connection to network!\n");
            is_connected = false;
            //queueATresponse(AT_DISCONNECT_RESP);
            // attempt reconnection if always connected scheme is set
            if(internet_config.connectionScheme == ALWAYS_CONNECTED)
            {
                nsapi_error_t error;
                error = scanNetworks();
                queueATresponse(WIFI_RECONNECT_INFO);
            }
            break;
        case NSAPI_STATUS_CONNECTING:
            printf("Connecting to network!\r\n");
            break;
        default:
            printf("Not supported");
            break;
    }
}



   //     NSAPI_STATUS_LOCAL_UP           = 0,        /*!< local IP address set */
   //     NSAPI_STATUS_GLOBAL_UP          = 1,        /*!< global IP address set */
   //     NSAPI_STATUS_DISCONNECTED       = 2,        /*!< no connection to network */
   //     NSAPI_STATUS_CONNECTING         = 3,        /*!< connecting to network */
   //     NSAPI_STATUS_ERROR_UNSUPPORTED  = NSAPI_ERROR_UNSUPPORTED   
   
nsapi_error_t WiFiManager::connect()
{
    nsapi_error_t error;
    printf("\n [WIFI-MAN] About to connect to WiFi network\n");
    network->attach(callback(this, &WiFiManager::status_callback));
    error = network->set_blocking(false);
    if(error)
    {
        printf("\n [WIFI-MAN] Could not set non-blocking mode for Wifi -- aborting!! - \n");
        return error;
    }
    printf("[WIFI-MAN] Connecting to network %s\n", wifi_config.ssid);
    error = network->connect(wifi_config.ssid,
                     wifi_config.pass,
                     wifi_config.security);
    return error;
}


nsapi_error_t WiFiManager::disconnect()
{
    nsapi_error_t error;
    error = network->disconnect();
    return error;
}



void WiFiManager::return_response(HttpResponse* res) {
    
    //queueWiFiDataResponse(at_data_msg_t at_data_resp);
    
    at_data_msg_t at_data_resp; 
    int numChars = 0;
    // create message pointer for response header generation
    char * msgPtr = (char *)at_data_resp.buffer;
    // do status line
    numChars = sprintf(msgPtr, "HTTP/1.1 %d %s\r\n", res->get_status_code(), res->get_status_message().c_str());
    msgPtr += numChars;
    //at_data_resp = &at_data;
    at_data_resp.dataLen = sizeof(*res); // start with minimum size of response
    for (size_t ix = 0; ix < res->get_headers_length(); ix++) {
        numChars = sprintf(msgPtr, "%s: %s\r\n", 
                           res->get_headers_fields()[ix]->c_str(), 
                           res->get_headers_values()[ix]->c_str());
        msgPtr += numChars;
    }
    numChars = sprintf(msgPtr, "\r\n\r\n");
    msgPtr += numChars;
    strncpy(msgPtr, res->get_body_as_string().c_str(), res->get_body_length()+1);
    // print out generated header
    printf("generated response:\n");
    printf("%s\r\n", (char *)at_data_resp.buffer);
    //printf("\nBody (%lu bytes):\n\n%s\n", res->get_body_length(), res->get_body_as_string().c_str());
    at_data_resp.dataLen = (msgPtr - (char *)at_data_resp.buffer) + res->get_body_length();
    //printf("WIFI MAN]: wifi_cfg.security = %s\n", sec2str(wifi_cfg.security));
    // package and send on wifi data queue
    
    at_data_resp.at_resp = AT_HTTPS_RESP;
    //at_data_resp.at_data_resp = sizeof(wifi_config_t);
    //memcpy(at_data_resp.buffer, res, at_data_resp.dataLen);
    queueWiFiDataResponse(at_data_resp);
    
    delete res;

}
#define TRY_PRINTF

void WiFiManager::body_callback(const char *at, uint32_t length) {
    
    printf("\n Chunked response: Chunk %d : Total Bytes = %d\n", chunkNum , length);
    //device->printf("\n Try Print Header as string:\n\n ");
    //device->printf("recv %d [%.*s]\n", length, strstr((char *)at, "\r\n")-(char *)at, (char *)at);
    //if(false)
    //if(chunkNum < 2)
    //for(int i=0; i < length; i++){
    //    
    //putc((uint8_t)at[i]);
        //int resp = write( (const uint8_t *)at, (int) length, &completed, SERIAL_EVENT_TX_COMPLETE);
    //}
    //if(false)
    if(chunkNum < 2)
    for (size_t ix = 0; ix < length; ix++) {
        printf("%02X: ", (uint8_t)at[ix]);
        if((ix % 32) == 0 and ix)
        printf("\n");
    }
#ifdef TRY_PRINTF
    printf("%s\n", at);
#endif    

    printf("\n\n");
    chunkNum++;
}

void WiFiManager::createHttpsRequest()
{
    // reset chunk #;
    chunkNum = 0;
    printf("\n[WIFI MAN] Http Request received:");
    http_req_cfg = (http_request_t *) data_msg->buffer;
    printf("\n[WIFI MAN] uri = %s", http_req_cfg->request_URI.c_str());
    printf("\n[WIFI MAN] internet cfg url = %s", internet_config.url);
    char full_url[100];
    strncpy(full_url,internet_config.url, strlen(internet_config.url)+1);
    printf("\n[WIFI MAN] server url = %s\n", full_url);
    //strncat(internet_config.url, http_req_cfg->request_URI.c_str(), http_req_cfg->request_URI.size());
    strncat(full_url, http_req_cfg->request_URI.c_str(), http_req_cfg->request_URI.size());
    //printf("\n[WIFI MAN] server url = %s\n", internet_config.url);
    printf("\n[WIFI MAN] server url+uri = %s\n", full_url);
    printf("\n[WIFI MAN] Host = %s\n", http_req_cfg->hostName.c_str());
    printf("\n[WIFI MAN] Accept = %s\n", http_req_cfg->AcceptVal.c_str());
    printf("\n[WIFI MAN] Content-Type = %s\n", http_req_cfg->contentType.c_str());
    printf("\n[WIFI MAN] contentLenstr = %s\n", http_req_cfg->contentLen.c_str());
    //printf("\n[WIFI MAN] server url = %s\n", internet_config.url.c_str());
    //const char* url = internet_config.url;
                                           
    print_memory_info();
    //    http_request = new HttpRequest(network, 
    //   http_request = new HttpRequest(network, 
    int bodyLen;
    sscanf(http_req_cfg->contentLen.c_str(), "%d", &bodyLen);
    printf("contenLenstr = %s bodyLen = %d\n", http_req_cfg->contentLen.c_str(), bodyLen);
    if(strstr(internet_config.url, "http:")!=NULL) // http request
    {
        http_request = new HttpRequest(network,  
                                         //SSL_CA_PEM, 
                                         http_req_cfg->method, 
                                         internet_config.url,
                                         callback(this, &WiFiManager::body_callback));
        setHttpHeader("Host", http_req_cfg->hostName);
        setHttpHeader("Accept", http_req_cfg->AcceptVal);
        setHttpHeader("Content-Type", http_req_cfg->contentType);
        setHttpHeader("Content-Length", http_req_cfg->contentLen);
        http_response = http_request->send(http_req_cfg->body, bodyLen);
        free_DataMsg();
        if (!http_response) {
            char buf[100];
            mbedtls_strerror(http_request->get_error(), buf, 100);
            printf("HttpRequest failed (error code %s)\n", buf);
            //printf("HttpsRequest failed (error code %d)\n", https_request->get_error());
            delete http_request; // free the memory
            return;
        }
        printf("\n----- HTTP POST response -----\n");
    }
    else
    {
        https_request = new HttpsRequest(network, 
                                         SSL_CA_PEM, 
                                         http_req_cfg->method, 
                                         internet_config.url,
                                         callback(this, &WiFiManager::body_callback));
        
        setHttpsHeader("Host", http_req_cfg->hostName);
        setHttpsHeader("Accept", http_req_cfg->AcceptVal);
        setHttpsHeader("Content-Type", http_req_cfg->contentType);
        setHttpsHeader("Content-Length", http_req_cfg->contentLen);
        http_response = https_request->send(http_req_cfg->body, bodyLen);
        free_DataMsg();
        if (!http_response) {
            char buf[100];
            mbedtls_strerror(https_request->get_error(), buf, 100);
            printf("HttpRequest failed (error code %s)\n", buf);
            //printf("HttpsRequest failed (error code %d)\n", https_request->get_error());
            delete https_request; // free the memory
            return;
        }
        printf("\n----- HTTPS POST response -----\r\n");
   }
    return_response(http_response);
}

void WiFiManager::createHttpRequest(http_method method,
                                    const char* url,
                                    Callback<void(const char *at, uint32_t length)> body_callback)
{
    http_request = new HttpRequest(network, 
                                   method, url, body_callback);;
}

void WiFiManager::setHttpHeader(string key, string value)
{
    http_request->set_header(key, value);
}

void WiFiManager::setHttpsHeader(string key, string value)
{
    https_request->set_header(key, value);
}

void WiFiManager::sendHttpsRequest(const char * body, int bodyLen)
{
}

void WiFiManager::sendHttpRequest(const char * body, int bodyLen)
{
}