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
NetworkInterface.cpp
- Committer:
- dan_ackme
- Date:
- 2014-10-27
- Revision:
- 31:59fac148a8d5
- Parent:
- 29:b6af04b77a56
- Child:
- 40:4b4306f3d829
File content as of revision 31:59fac148a8d5:
/** * 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; const char *tok; for(i = 0; i < 4; ++i, str = tok) { uint8_t nibble; char buf[4]; tok = strchr(str, '.'); if(tok == NULL) { if(i < 3) { return false; } strcpy(buf, str); } else { strncpy(buf, str, tok - str); ++tok; } if(!StringUtil::strToUint8(buf, &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; }