Host library for controlling a WiConnect enabled Wi-Fi module.

Dependents:   wiconnect-ota_example wiconnect-web_setup_example wiconnect-test-console wiconnect-tcp_server_example ... more

Revision:
29:b6af04b77a56
Child:
31:59fac148a8d5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkInterface.cpp	Mon Oct 27 13:42:26 2014 -0700
@@ -0,0 +1,659 @@
+/**
+ * ACKme WiConnect Host Library is licensed under the BSD licence: 
+ * 
+ * Copyright (c)2014 ACKme Networks.
+ * All rights reserved. 
+ * 
+ * Redistribution and use in source and binary forms, with or without modification, 
+ * are permitted provided that the following conditions are met: 
+ * 
+ * 1. Redistributions of source code must retain the above copyright notice, 
+ * this list of conditions and the following disclaimer. 
+ * 2. Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation 
+ * and/or other materials provided with the distribution. 
+ * 3. The name of the author may not be used to endorse or promote products 
+ * derived from this software without specific prior written permission. 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS AND ANY EXPRESS OR IMPLIED 
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * OF SUCH DAMAGE.
+ */
+
+#include "Wiconnect.h"
+#include "internal/common.h"
+#include "api/StringUtil.h"
+
+
+#define IPV4_FORMAT "%u.%u.%u.%u"
+#define IPV4_ARGS(ip) \
+    (int)(((ip) >>  0) & 0xff), \
+    (int)(((ip) >>  8) & 0xff), \
+    (int)(((ip) >> 16) & 0xff), \
+    (int)(((ip) >> 24) & 0xff)
+
+
+
+/*************************************************************************************************/
+NetworkInterface::NetworkInterface(Wiconnect *wiconnect_)
+{
+    wiconnect = wiconnect_;
+}
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::ping(const char *domain, uint32_t *timeMsPtr)
+{
+    WiconnectResult result;
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("ping %s",  (domain == NULL) ? "-g" : domain)) &&
+            timeMsPtr != NULL)
+    {
+        if(sscanf(wiconnect->internalBuffer, "Ping reply in %ums", (unsigned int*)timeMsPtr) != 1)
+        {
+            result = WICONNECT_RESPONSE_PARSE_ERROR;
+        }
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::lookup(const char *domain, uint32_t *ipAddressPtr)
+{
+    WiconnectResult result;
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("nlo %s", domain)))
+    {
+        if(!NetworkInterface::strToIp(wiconnect->internalBuffer, ipAddressPtr))
+        {
+            result = WICONNECT_RESPONSE_PARSE_ERROR;
+        }
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::setDhcpEnabled(bool enabled)
+{
+    WiconnectResult result;
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    result = wiconnect->sendCommand(CMD_SET_NETWORK_DHCP, enabled);
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::getDhcpEnabled(bool *enabledPtr)
+{
+    WiconnectResult result;
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("get network.dhcp.enabled")))
+    {
+        int32_t enabled;
+        if(WICONNECT_SUCCEEDED(result, wiconnect->responseToInt32(&enabled)))
+        {
+            *enabledPtr = (bool)enabled;
+        }
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::setIpSettings(uint32_t ip, uint32_t netmask, uint32_t gateway)
+{
+    WiconnectResult result = WICONNECT_ERROR;
+
+    enum
+    {
+        FS_SET_IP,
+        FS_SET_NETMASK,
+        FS_SET_GATEWAY
+    };
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(wiconnect->internalProcessingState == FS_SET_IP)
+    {
+        if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand(CMD_SET_STATIC_IP, IPV4_ARGS(ip))))
+        {
+            wiconnect->internalProcessingState = FS_SET_NETMASK;
+        }
+    }
+
+    if(wiconnect->internalProcessingState == FS_SET_NETMASK)
+    {
+        if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand(CMD_SET_STATIC_NETMASK, IPV4_ARGS(netmask))))
+        {
+            wiconnect->internalProcessingState = FS_SET_GATEWAY;
+        }
+    }
+
+    if(wiconnect->internalProcessingState == FS_SET_GATEWAY)
+    {
+        if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand(CMD_SET_STATIC_GATEWAY, IPV4_ARGS(gateway))))
+        {
+        }
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::setIpSettings(const char* ipStr, const char* netmaskStr, const char* gatewayStr)
+{
+    uint32_t ip, nm, gw;
+
+    if( !NetworkInterface::strToIp(ipStr, &ip) ||
+        !NetworkInterface::strToIp(netmaskStr, &nm) ||
+        !NetworkInterface::strToIp(gatewayStr, &gw))
+    {
+        return WICONNECT_ERROR;
+    }
+    return setIpSettings(ip, nm, gw);
+}
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::getIpSettings(uint32_t *ip, uint32_t *netmask, uint32_t *gateway)
+{
+    WiconnectResult result = WICONNECT_ERROR;
+
+    enum
+    {
+        FS_GET_IP,
+        FS_GET_NETMASK,
+        FS_GET_GATEWAY
+    };
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(wiconnect->internalProcessingState == FS_GET_IP)
+    {
+        if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("get network.ip")))
+        {
+            if(!NetworkInterface::strToIp(wiconnect->internalBuffer, ip))
+            {
+                result = WICONNECT_RESPONSE_PARSE_ERROR;
+            }
+            else
+            {
+                wiconnect->internalProcessingState = FS_GET_NETMASK;
+            }
+        }
+    }
+
+    if(wiconnect->internalProcessingState == FS_GET_NETMASK)
+    {
+        if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("get network.netmask")))
+        {
+            if(!NetworkInterface::strToIp(wiconnect->internalBuffer, netmask))
+            {
+                result = WICONNECT_RESPONSE_PARSE_ERROR;
+            }
+            else
+            {
+                wiconnect->internalProcessingState = FS_GET_GATEWAY;
+            }
+        }
+    }
+
+    if(wiconnect->internalProcessingState == FS_GET_GATEWAY)
+    {
+        if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("get network.gateway")))
+        {
+            if(!NetworkInterface::strToIp(wiconnect->internalBuffer, gateway))
+            {
+                result = WICONNECT_RESPONSE_PARSE_ERROR;
+            }
+        }
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::setDnsAddress(uint32_t dnsAddress)
+{
+    WiconnectResult result;
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    result = wiconnect->sendCommand("set static.dns %d.%d.%d.%d", IPV4_ARGS(dnsAddress));
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::getDnsAddress(uint32_t *dnsAddress)
+{
+    WiconnectResult result;
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("get static.dns")))
+    {
+        if(!NetworkInterface::strToIp(wiconnect->internalBuffer, dnsAddress))
+        {
+            result = WICONNECT_RESPONSE_PARSE_ERROR;
+        }
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::getRssi(int32_t *rssiPtr)
+{
+    WiconnectResult result;
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    *rssiPtr = -999;
+
+    if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("rssi")))
+    {
+        result = wiconnect->responseToInt32(rssiPtr);
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::getSignalStrength(NetworkSignalStrength *signalStrengthPtr)
+{
+    WiconnectResult result;
+    int32_t rssiDbm;
+
+    if(WICONNECT_SUCCEEDED(result, getRssi(&rssiDbm)))
+    {
+        *signalStrengthPtr = NetworkInterface::rssiToSignalStrength(rssiDbm);
+    }
+    else if(result == WICONNECT_CMD_RESPONSE_ERROR)
+    {
+        *signalStrengthPtr = NETWORK_RSSI_UNKNOWN;
+        result = WICONNECT_SUCCESS;
+    }
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::getMacAddress(MacAddress *macAddress)
+{
+    WiconnectResult result;
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("get wlan.mac")))
+    {
+        if(!Wiconnect::strToMacAddress(wiconnect->internalBuffer, macAddress))
+        {
+            result = WICONNECT_RESPONSE_PARSE_ERROR;
+        }
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+
+/*************************************************************************************************/
+const char* NetworkInterface::getIpAddress(char *ipStrBuffer)
+{
+    SET_STR_BUFFER(ipStrBuffer, 17);
+
+    if(wiconnect->nonBlocking)
+    {
+        return "Err";
+    }
+
+    if(wiconnect->sendCommand(ptr, 17, "get network.ip") != WICONNECT_SUCCESS)
+    {
+        strcpy(ptr, "0.0.0.0");
+    }
+
+    return ptr;
+}
+
+
+//-----------------------------------------------------------------------------------------------
+
+
+/*************************************************************************************************/
+bool NetworkInterface::strToIp(const char *str, uint32_t *intPtr)
+{
+    if (!intPtr)
+    {
+        return false;
+    }
+    uint32_t ip = 0;
+    int i;
+    char *tok;
+
+    for(i = 0; i < 4; ++i, str = tok)
+    {
+        uint8_t nibble;
+
+        tok = strchr(str, '.');
+        if(tok == NULL)
+        {
+            if(i < 3)
+            {
+                return false;
+            }
+        }
+        else
+        {
+            *tok++ = 0;
+        }
+
+        if(!StringUtil::strToUint8(str, &nibble))
+        {
+            return false;
+        }
+        ip |= (((uint32_t)nibble) << 24);
+        if(i < 3)
+        {
+            ip = (ip >> 8UL);
+        }
+    }
+
+    if(i != 4)
+    {
+        return false;
+    }
+
+    *intPtr = ip;
+
+    return true;
+}
+
+/*************************************************************************************************/
+const char* NetworkInterface::ipToStr(uint32_t ip, char *ipStrBuffer)
+{
+    SET_STR_BUFFER(ipStrBuffer, 17);
+
+    sprintf(ptr, IPV4_FORMAT, IPV4_ARGS(ip));
+    return ptr;
+}
+
+/*************************************************************************************************/
+const char* NetworkInterface::networkStatusToStr(NetworkStatus status)
+{
+    switch(status)
+    {
+    case NETWORK_STATUS_DOWN:
+        return "Down";
+    case NETWORK_STATUS_WIFI_ONLY:
+        return "WiFi Only";
+    case NETWORK_STATUS_UP:
+        return "Up";
+    default:
+        return "Unknown";
+    }
+}
+
+/*************************************************************************************************/
+const char* NetworkInterface::networkJoinResultToStr(NetworkJoinResult joinResult)
+{
+    switch(joinResult)
+    {
+    case NETWORK_JOIN_RESULT_NONE:
+        return "None";
+    case NETWORK_JOIN_RESULT_SUCCESS:
+        return "Success";
+    case NETWORK_JOIN_RESULT_JOINING:
+        return "Joining";
+    case NETWORK_JOIN_RESULT_NO_SSID:
+        return "No SSID";
+    case NETWORK_JOIN_RESULT_NO_PASSWORD:
+        return "No Password";
+    case NETWORK_JOIN_RESULT_BAD_SECURITY:
+        return "Bad Security Setting";
+    case NETWORK_JOIN_RESULT_NOT_FOUND:
+        return "Network Not Found";
+    case NETWORK_JOIN_RESULT_FAILED:
+        return "Failed";
+    case NETWORK_JOIN_RESULT_ABORTED:
+        return "Aborted";
+    default:
+        return "Unknown";
+    }
+}
+
+
+/*************************************************************************************************/
+const char* NetworkInterface::signalStrengthToStr(NetworkSignalStrength signalStrenth)
+{
+    switch(signalStrenth)
+    {
+    case NETWORK_RSSI_EXCELLENT:
+        return "Excellent";
+    case NETWORK_RSSI_VERY_GOOD:
+        return "Very Good";
+    case NETWORK_RSSI_GOOD:
+        return "Good";
+    case NETWORK_RSSI_POOR:
+        return "Poor";
+    case NETWORK_RSSI_VERY_POOR:
+        return "Very Poor";
+    case NETWORK_RSSI_UNKNOWN:
+    default:
+        return "Unknown";
+    }
+}
+
+/*************************************************************************************************/
+NetworkSignalStrength NetworkInterface::rssiToSignalStrength(int rssi_dbm)
+{
+    if(rssi_dbm > -20)
+    {
+        return NETWORK_RSSI_EXCELLENT;
+    }
+    else if(rssi_dbm > -35)
+    {
+        return NETWORK_RSSI_VERY_GOOD;
+    }
+    else if(rssi_dbm > -50)
+    {
+        return NETWORK_RSSI_GOOD;
+    }
+    else if(rssi_dbm > -70)
+    {
+        return NETWORK_RSSI_POOR;
+    }
+    else
+    {
+        return NETWORK_RSSI_VERY_POOR;
+    }
+}
+
+
+typedef struct
+{
+    const char* key;
+    NetworkSecurity value;
+} NetworkSecurityTableEntry;
+
+static const NetworkSecurityTableEntry networkSecurityTable[] = {
+        {"Auto",       NETWORK_SECURITY_UNKNOWN},
+        {"Open",       NETWORK_SECURITY_OPEN},
+        {"Unknown",    NETWORK_SECURITY_UNKNOWN},
+        {"WEP",        NETWORK_SECURITY_WEP_PSK},
+        {"WPA-AES",    NETWORK_SECURITY_WPA_AES_PSK},
+        {"WPA-TKIP",   NETWORK_SECURITY_WPA_TKIP_PSK},
+        {"WPA2-AES",   NETWORK_SECURITY_WPA2_AES_PSK},
+        {"WPA2-Mixed", NETWORK_SECURITY_WPA2_MIXED_PSK},
+        {"WPA2-TKIP",  NETWORK_SECURITY_WPA2_TKIP_PSK},
+};
+
+
+/*************************************************************************************************/
+NetworkSecurity NetworkInterface::strToNetworkSecurity(const char *str)
+{
+    const NetworkSecurityTableEntry *end = &networkSecurityTable[ARRAY_COUNT(networkSecurityTable)];
+
+    for(const NetworkSecurityTableEntry *e = networkSecurityTable; e < end; ++e)
+    {
+        if(StringUtil::strcasecmp(e->key, str) == 0)
+        {
+            return e->value;
+        }
+    }
+    return NETWORK_SECURITY_UNKNOWN;
+}
+
+/*************************************************************************************************/
+const char* NetworkInterface::networkSecurityToStr(NetworkSecurity security)
+{
+    const NetworkSecurityTableEntry *end = &networkSecurityTable[ARRAY_COUNT(networkSecurityTable)];
+
+    for(const NetworkSecurityTableEntry *e = networkSecurityTable; e < end; ++e)
+    {
+        if(e->value == security)
+        {
+            return e->key;
+        }
+    }
+    return "Unknown";
+}
+
+/*************************************************************************************************/
+bool NetworkInterface::strToSsid(const char *str, Ssid *ssid)
+{
+#define ESCAPE_CHARACTER_DELIMITER '\\'
+#define HEX_ESCAPE_CHARACTER 'x'
+    int c;
+    uint8_t *ssidPtr = ssid->val;
+    uint32_t ssidLen = 0;
+
+    while((c = (int)(*str++)) != 0)
+    {
+        if(c == ESCAPE_CHARACTER_DELIMITER)
+        {
+            if(*str == HEX_ESCAPE_CHARACTER)
+            {
+                c = StringUtil::hexToInt(str+1);
+                if(c == -1)
+                    return false;
+                str += 3;
+            }
+            else
+            {
+                return false;
+            }
+        }
+        if(ssidLen >= sizeof(ssid->val))
+            return false;
+        ++ssidLen;
+        *ssidPtr++ = (uint8_t)c;
+    }
+
+    ssid->len = ssidLen;
+
+    return true;
+}
+
+/*************************************************************************************************/
+const char* NetworkInterface::ssidToStr(const Ssid *ssid, char *ssidStrBuffer)
+{
+    SET_STR_BUFFER(ssidStrBuffer, sizeof(SsidStrBuffer));
+    const char *src = (const char*)ssid->val;
+    int len = ssid->len;
+    char *buf = ptr;
+
+    while(len--)
+    {
+        if(*src >= 0x20 && *src <= 0x7E)
+        {
+            *ptr++ = *src;
+        }
+        else
+        {
+            ptr += sprintf(ptr, "\\x%02X", (*src) & 0xff);
+        }
+        ++src;
+    }
+    *ptr = 0;
+    return buf;
+}
+
+/*************************************************************************************************/
+bool NetworkInterface::strToMacAddress(const char *str, MacAddress *macAddress)
+{
+    const char* strPtr = str;
+    uint8_t *macPtr = (uint8_t*)macAddress->octet;
+
+    for(int count = 0; count < 6; ++count)
+    {
+        if(count < 5)
+        {
+            const char *idx = strchr(strPtr, ':');
+            if(idx == NULL)
+            {
+                return false;
+            }
+        }
+        int num = StringUtil::hexToInt(strPtr);
+        if(num == -1)
+        {
+            return false;
+        }
+        *macPtr++ = (uint8_t)num;
+        strPtr += 3;
+    }
+
+    return true;
+}
+
+/*************************************************************************************************/
+const char* NetworkInterface::macAddressToStr(const MacAddress *macAddress, char *macStrBuffer)
+{
+    SET_STR_BUFFER(macStrBuffer, sizeof(MacAddressStrBuffer));
+    const uint8_t *mac = macAddress->octet;
+
+    sprintf(ptr, "%02X:%02X:%02X:%02X:%02X:%02X",
+            (unsigned int)mac[0],
+            (unsigned int)mac[1],
+            (unsigned int)mac[2],
+            (unsigned int)mac[3],
+            (unsigned int)mac[4],
+            (unsigned int)mac[5]);
+
+    return ptr;
+}