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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NetworkInterface.cpp Source File

NetworkInterface.cpp

00001 /**
00002  * ACKme WiConnect Host Library is licensed under the BSD licence: 
00003  * 
00004  * Copyright (c)2014 ACKme Networks.
00005  * All rights reserved. 
00006  * 
00007  * Redistribution and use in source and binary forms, with or without modification, 
00008  * are permitted provided that the following conditions are met: 
00009  * 
00010  * 1. Redistributions of source code must retain the above copyright notice, 
00011  * this list of conditions and the following disclaimer. 
00012  * 2. Redistributions in binary form must reproduce the above copyright notice, 
00013  * this list of conditions and the following disclaimer in the documentation 
00014  * and/or other materials provided with the distribution. 
00015  * 3. The name of the author may not be used to endorse or promote products 
00016  * derived from this software without specific prior written permission. 
00017  * 
00018  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS AND ANY EXPRESS OR IMPLIED 
00019  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
00020  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
00021  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00022  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
00023  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
00026  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
00027  * OF SUCH DAMAGE.
00028  */
00029 
00030 #include "Wiconnect.h"
00031 #include "internal/common.h"
00032 #include "api/StringUtil.h"
00033 
00034 
00035 #define IPV4_FORMAT "%u.%u.%u.%u"
00036 #define IPV4_ARGS(ip) \
00037     (int)(((ip) >>  0) & 0xff), \
00038     (int)(((ip) >>  8) & 0xff), \
00039     (int)(((ip) >> 16) & 0xff), \
00040     (int)(((ip) >> 24) & 0xff)
00041 
00042 
00043 
00044 /*************************************************************************************************/
00045 NetworkInterface::NetworkInterface(Wiconnect *wiconnect_)
00046 {
00047     wiconnect = wiconnect_;
00048 }
00049 
00050 /*************************************************************************************************/
00051 WiconnectResult NetworkInterface::ping(const char *domain, uint32_t *timeMsPtr)
00052 {
00053     WiconnectResult result;
00054 
00055     CHECK_OTHER_COMMAND_EXECUTING();
00056 
00057     if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("ping %s",  (domain == NULL) ? "-g" : domain)) &&
00058             timeMsPtr != NULL)
00059     {
00060         if(sscanf(wiconnect->internalBuffer, "Ping reply in %ums", (unsigned int*)timeMsPtr) != 1)
00061         {
00062             result = WICONNECT_RESPONSE_PARSE_ERROR;
00063         }
00064     }
00065 
00066     CHECK_CLEANUP_COMMAND();
00067 
00068     return result;
00069 }
00070 
00071 /*************************************************************************************************/
00072 WiconnectResult NetworkInterface::lookup(const char *domain, uint32_t *ipAddressPtr)
00073 {
00074     WiconnectResult result;
00075 
00076     CHECK_OTHER_COMMAND_EXECUTING();
00077 
00078     if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("nlo %s", domain)))
00079     {
00080         if(!NetworkInterface::strToIp(wiconnect->internalBuffer, ipAddressPtr))
00081         {
00082             result = WICONNECT_RESPONSE_PARSE_ERROR;
00083         }
00084     }
00085 
00086     CHECK_CLEANUP_COMMAND();
00087 
00088     return result;
00089 }
00090 
00091 /*************************************************************************************************/
00092 WiconnectResult NetworkInterface::setDhcpEnabled(bool enabled)
00093 {
00094     WiconnectResult result;
00095 
00096     CHECK_OTHER_COMMAND_EXECUTING();
00097 
00098     result = wiconnect->sendCommand(CMD_SET_NETWORK_DHCP, enabled);
00099 
00100     CHECK_CLEANUP_COMMAND();
00101 
00102     return result;
00103 }
00104 
00105 /*************************************************************************************************/
00106 WiconnectResult NetworkInterface::getDhcpEnabled(bool *enabledPtr)
00107 {
00108     WiconnectResult result;
00109 
00110     CHECK_OTHER_COMMAND_EXECUTING();
00111 
00112     if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("get network.dhcp.enabled")))
00113     {
00114         int32_t enabled;
00115         if(WICONNECT_SUCCEEDED(result, wiconnect->responseToInt32(&enabled)))
00116         {
00117             *enabledPtr = (bool)enabled;
00118         }
00119     }
00120 
00121     CHECK_CLEANUP_COMMAND();
00122 
00123     return result;
00124 }
00125 
00126 /*************************************************************************************************/
00127 WiconnectResult NetworkInterface::setIpSettings(uint32_t ip, uint32_t netmask, uint32_t gateway)
00128 {
00129     WiconnectResult result = WICONNECT_ERROR;
00130 
00131     enum
00132     {
00133         FS_SET_IP,
00134         FS_SET_NETMASK,
00135         FS_SET_GATEWAY
00136     };
00137 
00138     CHECK_OTHER_COMMAND_EXECUTING();
00139 
00140     if(wiconnect->internalProcessingState == FS_SET_IP)
00141     {
00142         if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand(CMD_SET_STATIC_IP, IPV4_ARGS(ip))))
00143         {
00144             wiconnect->internalProcessingState = FS_SET_NETMASK;
00145         }
00146     }
00147 
00148     if(wiconnect->internalProcessingState == FS_SET_NETMASK)
00149     {
00150         if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand(CMD_SET_STATIC_NETMASK, IPV4_ARGS(netmask))))
00151         {
00152             wiconnect->internalProcessingState = FS_SET_GATEWAY;
00153         }
00154     }
00155 
00156     if(wiconnect->internalProcessingState == FS_SET_GATEWAY)
00157     {
00158         if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand(CMD_SET_STATIC_GATEWAY, IPV4_ARGS(gateway))))
00159         {
00160         }
00161     }
00162 
00163     CHECK_CLEANUP_COMMAND();
00164 
00165     return result;
00166 }
00167 
00168 /*************************************************************************************************/
00169 WiconnectResult NetworkInterface::setIpSettings(const char* ipStr, const char* netmaskStr, const char* gatewayStr)
00170 {
00171     uint32_t ip, nm, gw;
00172 
00173     if( !NetworkInterface::strToIp(ipStr, &ip) ||
00174         !NetworkInterface::strToIp(netmaskStr, &nm) ||
00175         !NetworkInterface::strToIp(gatewayStr, &gw))
00176     {
00177         return WICONNECT_ERROR;
00178     }
00179     return setIpSettings(ip, nm, gw);
00180 }
00181 
00182 /*************************************************************************************************/
00183 WiconnectResult NetworkInterface::getIpSettings(uint32_t *ip, uint32_t *netmask, uint32_t *gateway)
00184 {
00185     WiconnectResult result = WICONNECT_ERROR;
00186 
00187     enum
00188     {
00189         FS_GET_IP,
00190         FS_GET_NETMASK,
00191         FS_GET_GATEWAY
00192     };
00193 
00194     CHECK_OTHER_COMMAND_EXECUTING();
00195 
00196     if(wiconnect->internalProcessingState == FS_GET_IP)
00197     {
00198         if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("get network.ip")))
00199         {
00200             if(!NetworkInterface::strToIp(wiconnect->internalBuffer, ip))
00201             {
00202                 result = WICONNECT_RESPONSE_PARSE_ERROR;
00203             }
00204             else
00205             {
00206                 wiconnect->internalProcessingState = FS_GET_NETMASK;
00207             }
00208         }
00209     }
00210 
00211     if(wiconnect->internalProcessingState == FS_GET_NETMASK)
00212     {
00213         if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("get network.netmask")))
00214         {
00215             if(!NetworkInterface::strToIp(wiconnect->internalBuffer, netmask))
00216             {
00217                 result = WICONNECT_RESPONSE_PARSE_ERROR;
00218             }
00219             else
00220             {
00221                 wiconnect->internalProcessingState = FS_GET_GATEWAY;
00222             }
00223         }
00224     }
00225 
00226     if(wiconnect->internalProcessingState == FS_GET_GATEWAY)
00227     {
00228         if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("get network.gateway")))
00229         {
00230             if(!NetworkInterface::strToIp(wiconnect->internalBuffer, gateway))
00231             {
00232                 result = WICONNECT_RESPONSE_PARSE_ERROR;
00233             }
00234         }
00235     }
00236 
00237     CHECK_CLEANUP_COMMAND();
00238 
00239     return result;
00240 }
00241 
00242 /*************************************************************************************************/
00243 WiconnectResult NetworkInterface::setDnsAddress(uint32_t dnsAddress)
00244 {
00245     WiconnectResult result;
00246 
00247     CHECK_OTHER_COMMAND_EXECUTING();
00248 
00249     result = wiconnect->sendCommand("set static.dns %d.%d.%d.%d", IPV4_ARGS(dnsAddress));
00250 
00251     CHECK_CLEANUP_COMMAND();
00252 
00253     return result;
00254 }
00255 
00256 /*************************************************************************************************/
00257 WiconnectResult NetworkInterface::getDnsAddress(uint32_t *dnsAddress)
00258 {
00259     WiconnectResult result;
00260 
00261     CHECK_OTHER_COMMAND_EXECUTING();
00262 
00263     if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("get static.dns")))
00264     {
00265         if(!NetworkInterface::strToIp(wiconnect->internalBuffer, dnsAddress))
00266         {
00267             result = WICONNECT_RESPONSE_PARSE_ERROR;
00268         }
00269     }
00270 
00271     CHECK_CLEANUP_COMMAND();
00272 
00273     return result;
00274 }
00275 
00276 /*************************************************************************************************/
00277 WiconnectResult NetworkInterface::getRssi(int32_t *rssiPtr)
00278 {
00279     WiconnectResult result;
00280 
00281     CHECK_OTHER_COMMAND_EXECUTING();
00282 
00283     *rssiPtr = -999;
00284 
00285     if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("rssi")))
00286     {
00287         result = wiconnect->responseToInt32(rssiPtr);
00288     }
00289 
00290     CHECK_CLEANUP_COMMAND();
00291 
00292     return result;
00293 }
00294 
00295 /*************************************************************************************************/
00296 WiconnectResult NetworkInterface::getSignalStrength(NetworkSignalStrength *signalStrengthPtr)
00297 {
00298     WiconnectResult result;
00299     int32_t rssiDbm;
00300 
00301     if(WICONNECT_SUCCEEDED(result, getRssi(&rssiDbm)))
00302     {
00303         *signalStrengthPtr = NetworkInterface::rssiToSignalStrength(rssiDbm);
00304     }
00305     else if(result == WICONNECT_CMD_RESPONSE_ERROR)
00306     {
00307         *signalStrengthPtr = NETWORK_RSSI_UNKNOWN;
00308         result = WICONNECT_SUCCESS;
00309     }
00310 
00311     return result;
00312 }
00313 
00314 /*************************************************************************************************/
00315 WiconnectResult NetworkInterface::getMacAddress(MacAddress *macAddress)
00316 {
00317     WiconnectResult result;
00318 
00319     CHECK_OTHER_COMMAND_EXECUTING();
00320 
00321     if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("get wlan.mac")))
00322     {
00323         if(!Wiconnect::strToMacAddress(wiconnect->internalBuffer, macAddress))
00324         {
00325             result = WICONNECT_RESPONSE_PARSE_ERROR;
00326         }
00327     }
00328 
00329     CHECK_CLEANUP_COMMAND();
00330 
00331     return result;
00332 }
00333 
00334 
00335 /*************************************************************************************************/
00336 const char* NetworkInterface::getIpAddress(char *ipStrBuffer)
00337 {
00338     SET_STR_BUFFER(ipStrBuffer, 17);
00339 
00340     if(wiconnect->nonBlocking)
00341     {
00342         return "Err";
00343     }
00344 
00345     if(wiconnect->sendCommand(ptr, 17, "get network.ip") != WICONNECT_SUCCESS)
00346     {
00347         strcpy(ptr, "0.0.0.0");
00348     }
00349 
00350     return ptr;
00351 }
00352 
00353 
00354 //-----------------------------------------------------------------------------------------------
00355 
00356 
00357 /*************************************************************************************************/
00358 bool NetworkInterface::strToIp(const char *str, uint32_t *intPtr)
00359 {
00360     if (!intPtr)
00361     {
00362         return false;
00363     }
00364     uint32_t ip = 0;
00365     int i;
00366     const char *tok;
00367 
00368     for(i = 0; i < 4; ++i, str = tok)
00369     {
00370         uint8_t nibble;
00371         char buf[4];
00372 
00373         tok = strchr(str, '.');
00374         if(tok == NULL)
00375         {
00376             if(i < 3)
00377             {
00378                 return false;
00379             }
00380             strcpy(buf, str);
00381         }
00382         else
00383         {
00384             strncpy(buf, str, tok - str);
00385             ++tok;
00386         }
00387 
00388         if(!StringUtil::strToUint8(buf, &nibble))
00389         {
00390             return false;
00391         }
00392         ip |= (((uint32_t)nibble) << 24);
00393         if(i < 3)
00394         {
00395             ip = (ip >> 8UL);
00396         }
00397     }
00398 
00399     if(i != 4)
00400     {
00401         return false;
00402     }
00403 
00404     *intPtr = ip;
00405 
00406     return true;
00407 }
00408 
00409 /*************************************************************************************************/
00410 const char* NetworkInterface::ipToStr(uint32_t ip, char *ipStrBuffer)
00411 {
00412     SET_STR_BUFFER(ipStrBuffer, 17);
00413 
00414     sprintf(ptr, IPV4_FORMAT, IPV4_ARGS(ip));
00415     return ptr;
00416 }
00417 
00418 /*************************************************************************************************/
00419 const char* NetworkInterface::networkStatusToStr(NetworkStatus status)
00420 {
00421     switch(status)
00422     {
00423     case NETWORK_STATUS_DOWN:
00424         return "Down";
00425     case NETWORK_STATUS_WIFI_ONLY:
00426         return "WiFi Only";
00427     case NETWORK_STATUS_UP:
00428         return "Up";
00429     default:
00430         return "Unknown";
00431     }
00432 }
00433 
00434 /*************************************************************************************************/
00435 const char* NetworkInterface::networkJoinResultToStr(NetworkJoinResult joinResult)
00436 {
00437     switch(joinResult)
00438     {
00439     case NETWORK_JOIN_RESULT_NONE:
00440         return "None";
00441     case NETWORK_JOIN_RESULT_SUCCESS:
00442         return "Success";
00443     case NETWORK_JOIN_RESULT_JOINING:
00444         return "Joining";
00445     case NETWORK_JOIN_RESULT_NO_SSID:
00446         return "No SSID";
00447     case NETWORK_JOIN_RESULT_NO_PASSWORD:
00448         return "No Password";
00449     case NETWORK_JOIN_RESULT_BAD_SECURITY:
00450         return "Bad Security Setting";
00451     case NETWORK_JOIN_RESULT_NOT_FOUND:
00452         return "Network Not Found";
00453     case NETWORK_JOIN_RESULT_FAILED:
00454         return "Failed";
00455     case NETWORK_JOIN_RESULT_ABORTED:
00456         return "Aborted";
00457     default:
00458         return "Unknown";
00459     }
00460 }
00461 
00462 
00463 /*************************************************************************************************/
00464 const char* NetworkInterface::signalStrengthToStr(NetworkSignalStrength signalStrenth)
00465 {
00466     switch(signalStrenth)
00467     {
00468     case NETWORK_RSSI_EXCELLENT:
00469         return "Excellent";
00470     case NETWORK_RSSI_VERY_GOOD:
00471         return "Very Good";
00472     case NETWORK_RSSI_GOOD:
00473         return "Good";
00474     case NETWORK_RSSI_POOR:
00475         return "Poor";
00476     case NETWORK_RSSI_VERY_POOR:
00477         return "Very Poor";
00478     case NETWORK_RSSI_UNKNOWN:
00479     default:
00480         return "Unknown";
00481     }
00482 }
00483 
00484 /*************************************************************************************************/
00485 NetworkSignalStrength NetworkInterface::rssiToSignalStrength(int rssi_dbm)
00486 {
00487     if(rssi_dbm > -20)
00488     {
00489         return NETWORK_RSSI_EXCELLENT;
00490     }
00491     else if(rssi_dbm > -35)
00492     {
00493         return NETWORK_RSSI_VERY_GOOD;
00494     }
00495     else if(rssi_dbm > -50)
00496     {
00497         return NETWORK_RSSI_GOOD;
00498     }
00499     else if(rssi_dbm > -70)
00500     {
00501         return NETWORK_RSSI_POOR;
00502     }
00503     else
00504     {
00505         return NETWORK_RSSI_VERY_POOR;
00506     }
00507 }
00508 
00509 
00510 typedef struct
00511 {
00512     const char* key;
00513     NetworkSecurity value;
00514 } NetworkSecurityTableEntry;
00515 
00516 static const NetworkSecurityTableEntry networkSecurityTable[] = {
00517         {"Auto",       NETWORK_SECURITY_UNKNOWN},
00518         {"Open",       NETWORK_SECURITY_OPEN},
00519         {"Unknown",    NETWORK_SECURITY_UNKNOWN},
00520         {"WEP",        NETWORK_SECURITY_WEP_PSK},
00521         {"WPA-AES",    NETWORK_SECURITY_WPA_AES_PSK},
00522         {"WPA-TKIP",   NETWORK_SECURITY_WPA_TKIP_PSK},
00523         {"WPA2-AES",   NETWORK_SECURITY_WPA2_AES_PSK},
00524         {"WPA2-Mixed", NETWORK_SECURITY_WPA2_MIXED_PSK},
00525         {"WPA2-TKIP",  NETWORK_SECURITY_WPA2_TKIP_PSK},
00526 };
00527 
00528 
00529 /*************************************************************************************************/
00530 NetworkSecurity NetworkInterface::strToNetworkSecurity(const char *str)
00531 {
00532     const NetworkSecurityTableEntry *end = &networkSecurityTable[ARRAY_COUNT(networkSecurityTable)];
00533 
00534     for(const NetworkSecurityTableEntry *e = networkSecurityTable; e < end; ++e)
00535     {
00536         if(StringUtil::strcasecmp(e->key, str) == 0)
00537         {
00538             return e->value;
00539         }
00540     }
00541     return NETWORK_SECURITY_UNKNOWN;
00542 }
00543 
00544 /*************************************************************************************************/
00545 const char* NetworkInterface::networkSecurityToStr(NetworkSecurity security)
00546 {
00547     const NetworkSecurityTableEntry *end = &networkSecurityTable[ARRAY_COUNT(networkSecurityTable)];
00548 
00549     for(const NetworkSecurityTableEntry *e = networkSecurityTable; e < end; ++e)
00550     {
00551         if(e->value == security)
00552         {
00553             return e->key;
00554         }
00555     }
00556     return "Unknown";
00557 }
00558 
00559 /*************************************************************************************************/
00560 bool NetworkInterface::strToSsid(const char *str, Ssid *ssid)
00561 {
00562 #define ESCAPE_CHARACTER_DELIMITER '\\'
00563 #define HEX_ESCAPE_CHARACTER 'x'
00564     int c;
00565     uint8_t *ssidPtr = ssid->val;
00566     uint32_t ssidLen = 0;
00567 
00568     while((c = (int)(*str++)) != 0)
00569     {
00570         if(c == ESCAPE_CHARACTER_DELIMITER)
00571         {
00572             if(*str == HEX_ESCAPE_CHARACTER)
00573             {
00574                 c = StringUtil::hexToInt(str+1);
00575                 if(c == -1)
00576                     return false;
00577                 str += 3;
00578             }
00579             else
00580             {
00581                 return false;
00582             }
00583         }
00584         if(ssidLen >= sizeof(ssid->val))
00585             return false;
00586         ++ssidLen;
00587         *ssidPtr++ = (uint8_t)c;
00588     }
00589 
00590     ssid->len = ssidLen;
00591 
00592     return true;
00593 }
00594 
00595 /*************************************************************************************************/
00596 const char* NetworkInterface::ssidToStr(const Ssid *ssid, char *ssidStrBuffer)
00597 {
00598     SET_STR_BUFFER(ssidStrBuffer, sizeof(SsidStrBuffer));
00599     const char *src = (const char*)ssid->val;
00600     int len = ssid->len;
00601     char *buf = ptr;
00602 
00603     while(len--)
00604     {
00605         if(*src >= 0x20 && *src <= 0x7E)
00606         {
00607             *ptr++ = *src;
00608         }
00609         else
00610         {
00611             ptr += sprintf(ptr, "\\x%02X", (*src) & 0xff);
00612         }
00613         ++src;
00614     }
00615     *ptr = 0;
00616     return buf;
00617 }
00618 
00619 /*************************************************************************************************/
00620 bool NetworkInterface::strToMacAddress(const char *str, MacAddress *macAddress)
00621 {
00622     const char* strPtr = str;
00623     uint8_t *macPtr = (uint8_t*)macAddress->octet;
00624 
00625     for(int count = 0; count < 6; ++count)
00626     {
00627         if(count < 5)
00628         {
00629             const char *idx = strchr(strPtr, ':');
00630             if(idx == NULL)
00631             {
00632                 return false;
00633             }
00634         }
00635         int num = StringUtil::hexToInt(strPtr);
00636         if(num == -1)
00637         {
00638             return false;
00639         }
00640         *macPtr++ = (uint8_t)num;
00641         strPtr += 3;
00642     }
00643 
00644     return true;
00645 }
00646 
00647 /*************************************************************************************************/
00648 const char* NetworkInterface::macAddressToStr(const MacAddress *macAddress, char *macStrBuffer)
00649 {
00650     SET_STR_BUFFER(macStrBuffer, sizeof(MacAddressStrBuffer));
00651     const uint8_t *mac = macAddress->octet;
00652 
00653     sprintf(ptr, "%02X:%02X:%02X:%02X:%02X:%02X",
00654             (unsigned int)mac[0],
00655             (unsigned int)mac[1],
00656             (unsigned int)mac[2],
00657             (unsigned int)mac[3],
00658             (unsigned int)mac[4],
00659             (unsigned int)mac[5]);
00660 
00661     return ptr;
00662 }