Jim Flynn / Mbed OS wifi_Example

Dependencies:   X_NUCLEO_IKS01A2 mbed-http

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers WizFi310.cpp Source File

WizFi310.cpp

Go to the documentation of this file.
00001 /* 
00002  * Copyright (c) 2015 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 /**
00018   ******************************************************************************
00019   * @file    WizFi310.cpp
00020   * @author  Gateway Team
00021   * @brief   Implementation file of the WizFi310 WiFi Device
00022   ******************************************************************************
00023   * @attention
00024   *
00025   * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
00026   * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
00027   * TIME. AS A RESULT, WIZnet SHALL NOT BE HELD LIABLE FOR ANY
00028   * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
00029   * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
00030   * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
00031   *
00032   * <h2><center>&copy; COPYRIGHT 2017 WIZnet Co.,Ltd.</center></h2>
00033   ******************************************************************************
00034   */
00035 
00036 #include "WizFi310.h"
00037 #define WIZFI310_DEFAULT_BAUD_RATE      115200
00038 
00039 #define AT_CMD_PARSER_DEFAULT_TIMEOUT     500
00040 #define AT_CMD_PARSER_INIT_TIMEOUT       1000
00041 #define AT_CMD_PARSER_RECV_TIMEOUT      20000
00042 
00043 using namespace mbed;
00044 WizFi310::WizFi310(PinName tx, PinName rx, bool debug)
00045     : _serial(tx, rx, WIZFI310_DEFAULT_BAUD_RATE),
00046       _parser(&_serial),
00047       _packets(0),
00048       _packets_end(&_packets)
00049 {
00050     _serial.set_baud( WIZFI310_DEFAULT_BAUD_RATE );
00051     _parser.debug_on(debug);
00052     _parser.set_delimiter("\r\n");
00053 
00054     setTimeout(AT_CMD_PARSER_INIT_TIMEOUT);
00055     for(int i=0; i<10; i++)
00056     {
00057         if( _parser.send("AT") && _parser.recv("[OK]") )
00058         {
00059             _parser.send("AT+MECHO=0");
00060             _parser.recv("[OK]");
00061             _parser.send("AT+MPROF=S");
00062             _parser.recv("[OK]");
00063             _parser.send("AT+MRESET");
00064             _parser.recv("[OK]");
00065             break;
00066         }
00067     }
00068 
00069     _parser.recv("WizFi310 Version %s (WIZnet Co.Ltd)", _firmware_version);
00070 }
00071 
00072 const char* WizFi310::get_firmware_version()
00073 {
00074     if( strlen(_firmware_version) != 0 )
00075     {
00076         return _firmware_version;
00077     }
00078 
00079     _parser.send("AT+MINFO");
00080     if( _parser.recv("%s/WizFi310 Rev", _firmware_version) )
00081     {
00082         return _firmware_version;
00083     }
00084 
00085     return 0;
00086 }
00087 
00088 bool WizFi310::startup(int mode)
00089 {
00090     if( mode != 0 && mode != 1 )
00091     {
00092         return false;
00093     }
00094     _op_mode = mode;
00095 
00096     _parser.oob("{", callback(this, &WizFi310::_packet_handler));
00097     //_parser.oob("\n{", callback(this, &WizFi310::_packet_handler));
00098     return true;
00099 }
00100 
00101 bool WizFi310::reset(void)
00102 {
00103     for (int i=0; i<2; i++)
00104     {
00105         if(_parser.send("AT+MRESET")
00106            && _parser.recv("[OK]"))
00107         {
00108             return true;
00109         }
00110     }
00111 
00112     return false;
00113 }
00114 
00115 bool WizFi310::dhcp(bool enabled)
00116 {
00117     _dhcp = enabled;
00118     return _dhcp;
00119 }
00120 
00121 bool WizFi310::connect(const char *ap, const char *passPhrase, const char *sec)
00122 {
00123    if ( !(_parser.send("AT+WSET=0,%s", ap) && _parser.recv("[OK]")) )
00124    {
00125        return false;
00126    }
00127 
00128    //if ( !(_parser.send("AT+WSEC=0,%s,%s", sec, passPhrase) && _parser.recv("[OK]")) )
00129    if ( !(_parser.send("AT+WSEC=0,,%s", passPhrase) && _parser.recv("[OK]")) )
00130    {
00131        return false;
00132    }
00133 
00134    if (_dhcp)
00135    {
00136        if ( !(_parser.send("AT+WNET=1") && _parser.recv("[OK]")) )
00137        {
00138            return false;
00139        }
00140    }
00141    else
00142    {
00143        if ( !(_parser.send("AT+WNET=0,%s,%s,%s",_ip_buffer,_netmask_buffer,_gateway_buffer)
00144              && _parser.recv("[OK]")) )
00145        {
00146            return false;
00147        }
00148    }
00149 
00150    if ( !(_parser.send("AT+WJOIN") && _parser.recv("[Link-Up Event]")
00151        && _parser.recv("  IP Addr    : %[^\n]\r\n",_ip_buffer)
00152        && _parser.recv("  Gateway    : %[^\n]\r\n",_gateway_buffer)
00153        && _parser.recv("[OK]")) )
00154    {
00155         return false;
00156    }
00157 
00158    return true;
00159 }
00160 
00161 bool WizFi310::disconnect(void)
00162 {
00163     return _parser.send("AT+WLEAVE") && _parser.recv("[OK]");
00164 }
00165 
00166 const char *WizFi310::getIPAddress(void)
00167 {
00168     if (!(_parser.send("AT+WSTATUS") && _parser.recv("IF/SSID/IP-Addr/Gateway/MAC/TxPower(dBm)/RSSI(-dBm)")
00169          && _parser.recv("%*[^/]/%*[^/]/%15[^/]/",_ip_buffer)
00170          && _parser.recv("[OK]")) )
00171     {
00172         return 0;
00173     }
00174 
00175     return _ip_buffer;
00176 }
00177 
00178 const char *WizFi310::getMACAddress(void)
00179 {
00180     if (!(_parser.send("AT+MMAC=?")
00181         && _parser.recv("%[^\n]\r\n",_mac_buffer)
00182         && _parser.recv("[OK]"))) {
00183         return 0;
00184     }
00185 
00186     return _mac_buffer;
00187 }
00188 
00189 const char *WizFi310::getGateway()
00190 {
00191    return _gateway_buffer; 
00192 }
00193 
00194 const char *WizFi310::getNetmask()
00195 {
00196     return _netmask_buffer;
00197 }
00198 
00199 int8_t WizFi310::getRSSI()
00200 {
00201     char rssi[3];
00202 
00203     if (!(_parser.send("AT+WSTATUS") && _parser.recv("IF/SSID/IP-Addr/Gateway/MAC/TxPower(dBm)/RSSI(-dBm)")
00204          //&& _parser.recv("%*[^/]/%*[^/]/%*[^/]/%*[^/]/%*[^/]/%*[^/]/%[^\n]\r\n",&rssi)
00205          && _parser.recv("%*[^/]/%*[^/]/%*[^/]/%*[^/]/%*[^/]//%[^\n]\r\n",rssi)
00206          && _parser.recv("[OK]")) )
00207     {
00208         return 0;
00209     }
00210 
00211     return atoi(rssi);
00212 }
00213 
00214 bool WizFi310::isConnected(void)
00215 {
00216     return getIPAddress() != 0;
00217 }
00218 
00219 int WizFi310::scan(WiFiAccessPoint *res, unsigned limit)
00220 {
00221     unsigned int cnt = 0;
00222     nsapi_wifi_ap_t ap;
00223 
00224     // Scan Time out : 50ms
00225     if (!(_parser.send("AT+WSCAN=,,,50")
00226         && _parser.recv("Index/SSID/BSSID/RSSI(-dBm)/MaxDataRate(Mbps)/Security/RadioBand(GHz)/Channel")))
00227     {
00228         return NSAPI_ERROR_DEVICE_ERROR;
00229     }
00230     
00231     while (recv_ap(&ap)) {
00232         if (cnt < limit)
00233         {
00234             res[cnt] = WiFiAccessPoint(ap);
00235         }
00236         cnt++;
00237         if (limit != 0 && cnt >= limit)
00238         {
00239             break;
00240         }
00241     }
00242 
00243     return cnt;
00244 }
00245 
00246 bool WizFi310::open(const char *type, int id, const char* addr, int port)
00247 {
00248     int created_sock_id;
00249 
00250     //IDs only 0-7
00251     if(id > 7) {
00252         return false;
00253     }
00254 
00255     if( !(_parser.send("AT+SCON=O,%s,%s,%d,,0",type,addr,port) && _parser.recv("[OK]")
00256             && _parser.recv("[CONNECT %d]",&created_sock_id))) {
00257         return false;
00258     }
00259 
00260     if( created_sock_id != id ) {
00261        close(created_sock_id); 
00262        return false;
00263     }
00264 
00265     return true;
00266 }
00267 
00268 bool WizFi310::dns_lookup(const char* name, char* ip)
00269 {
00270     return (_parser.send("AT+FDNS=%s,5000", name) && _parser.recv("%[^\n]\r\n",ip) && _parser.recv("[OK]"));
00271 }
00272 
00273 bool WizFi310::send(int id, const void *data, uint32_t amount)
00274 {
00275     char str_result[20];
00276 
00277     if(id > 8) {
00278         return false;
00279     }
00280 
00281     sprintf(str_result,"[%d,,,%d]",id,(int)amount);
00282     
00283     // Using _parser.printf because MCU can't send CR LF
00284     if( _parser.printf("AT+SSEND=%d,,,%d\r",id, (int)amount)
00285      && _parser.recv(str_result)
00286      && _parser.write((char*)data, (int)amount) >= 0
00287      && _parser.recv("[OK]") ){
00288         return true;
00289     }
00290 
00291     return false;
00292 }
00293 
00294 void WizFi310::_packet_handler()
00295 {
00296     int id;
00297     char ip_addr[16];
00298     int port;
00299     uint32_t amount;
00300 
00301     // parse out the packet
00302     _parser.set_timeout(AT_CMD_PARSER_RECV_TIMEOUT);
00303     if (!_parser.recv("%d,%[^,],%d,%d}",&id, ip_addr,&port, &amount) ) {
00304         setTimeout(_timeout_ms);
00305         return;
00306     }
00307 
00308     struct packet *packet = new struct packet;
00309     if (!packet) {
00310         return;
00311     }
00312 
00313     packet->id = id;
00314     packet->len = amount;
00315     packet->next = 0;
00316     packet->data = (char*)malloc(amount);
00317 
00318     
00319     if (!(_parser.read((char*)packet->data, amount))) {
00320         free(packet);
00321         setTimeout(_timeout_ms);
00322         return;
00323     }
00324     setTimeout(_timeout_ms);
00325 
00326     *_packets_end = packet;
00327     _packets_end = &packet->next;
00328 }
00329 
00330 int32_t WizFi310::recv(int id, void *data, uint32_t amount)
00331 {
00332     while (true) {
00333         // check if any packets are ready for us
00334         for (struct packet **p = &_packets; *p; p = &(*p)->next) {
00335             if ((*p)->id == id) {
00336                 struct packet *q = *p;
00337                 
00338                 if (q->len <= amount) {
00339                     memcpy(data,q->data, q->len);
00340 
00341                     if (_packets_end == &(*p)->next) {
00342                         _packets_end = p;
00343                     }
00344                     *p = (*p)->next;
00345 
00346                     uint32_t len = q->len;
00347                     free(q);
00348                     return len;
00349                 } else { // return only partial packet
00350                     memcpy(data, q->data, amount);
00351                     
00352                     q->len -= amount;
00353                     memmove(q->data, (uint8_t*)(q->data) + amount, q->len);
00354                     return amount;
00355                 }
00356             }
00357         }
00358 
00359         // check for inbound packets
00360         if (!_parser.process_oob()) {
00361             return -1;
00362         }
00363     }
00364 }
00365 
00366 bool WizFi310::close(int id)
00367 {
00368     char sock_event_msg[15];
00369 
00370     if(id > 7) {
00371         return false;
00372     }
00373 
00374     if (_parser.send("AT+SMGMT=%d", id) && _parser.recv(sock_event_msg) && _parser.recv("[OK]") )
00375     {
00376         return true;
00377     }
00378 
00379     return false;
00380 }
00381 
00382 void WizFi310::setTimeout(uint32_t timeout_ms)
00383 {
00384     _parser.set_timeout(timeout_ms);
00385     _timeout_ms = timeout_ms;
00386 }
00387 
00388 bool WizFi310::readable()
00389 {
00390     return _serial.FileHandle::readable();
00391 }
00392 
00393 bool WizFi310::writeable()
00394 {
00395     return _serial.FileHandle::writable();
00396 }
00397 
00398 void WizFi310::attach(Callback<void()> func)
00399 {
00400     _serial.sigio(func);
00401 }
00402 
00403 bool WizFi310::recv_ap(nsapi_wifi_ap_t *ap)
00404 {
00405     char scan_result[100];
00406     char sec[10];
00407     char bssid[32];
00408     char* idx_ptr;
00409     char* bssid_ptr;
00410     
00411     _parser.recv("%s\r\n",scan_result);
00412     if( strcmp(scan_result,"[OK]") == 0 )
00413     {
00414         return false;
00415     }
00416 
00417     idx_ptr = strtok((char*)scan_result, "/");      // index
00418 
00419     idx_ptr = strtok( NULL, "/" );                  // ssid
00420     strncpy(ap->ssid,idx_ptr,strlen(idx_ptr));
00421     ap->ssid[strlen(idx_ptr)] = '\0';
00422 
00423     idx_ptr = strtok( NULL, "/" );                  // bssid
00424     strncpy(bssid,idx_ptr,strlen(idx_ptr));
00425     bssid[strlen(idx_ptr)] = '\0';
00426     
00427     idx_ptr = strtok( NULL, "/" );                  // RSSI
00428     ap->rssi = atoi(idx_ptr);
00429 
00430     //idx_ptr = strtok( NULL, "/" );                  // DataRate
00431     
00432     idx_ptr = strtok( NULL, "/" );                  // Security
00433     strncpy(sec,idx_ptr,strlen(idx_ptr));
00434     sec[strlen(idx_ptr)] = '\0';
00435     ap->security = str2sec(sec);
00436 
00437     idx_ptr = strtok( NULL, "/" );                  // RadioBand
00438 
00439     idx_ptr = strtok( NULL, "/" );                  // Channel
00440     ap->channel = atoi(idx_ptr);
00441 
00442     // Set BSSID
00443     bssid_ptr = strtok( (char*)bssid, ":");
00444     ap->bssid[0] = hex_str_to_int(bssid_ptr);
00445 
00446     for(int i=1; i<6; i++)
00447     {
00448         bssid_ptr = strtok( NULL, ":");
00449         ap->bssid[i] = hex_str_to_int(bssid_ptr);
00450     }
00451 
00452     return true; 
00453 }
00454 
00455 nsapi_security_t WizFi310::str2sec(const char *str_sec)
00456 {
00457     if( strcmp(str_sec,"Open") == 0 )
00458     {
00459         return NSAPI_SECURITY_NONE;
00460     }
00461     else if( strcmp(str_sec,"WEP") == 0 )
00462     {
00463         return NSAPI_SECURITY_WEP;
00464     }
00465     else if( strcmp(str_sec,"WPA") == 0 )
00466     {
00467         return NSAPI_SECURITY_WPA;
00468     }
00469     else if( strcmp(str_sec,"WPA2") == 0 )
00470     {
00471         return NSAPI_SECURITY_WPA2;
00472     }
00473     else if( strcmp(str_sec,"WPAWPA2") == 0 )
00474     {
00475         return NSAPI_SECURITY_WPA_WPA2;
00476     }
00477 
00478     return NSAPI_SECURITY_UNKNOWN;
00479 }
00480 
00481 int WizFi310::hex_str_to_int(const char* hex_str)
00482 {
00483     int n = 0;
00484     uint32_t value = 0;
00485     int shift = 7;
00486     while (hex_str[n] != '\0' && n < 8)
00487     {
00488         if ( hex_str[n] > 0x21 && hex_str[n] < 0x40 )
00489         {
00490             value |= (hex_str[n] & 0x0f) << (shift << 2);
00491         }
00492         else if ( (hex_str[n] >= 'a' && hex_str[n] <= 'f') || (hex_str[n] >= 'A' && hex_str[n] <= 'F') )
00493         {
00494             value |= ((hex_str[n] & 0x0f) + 9) << (shift << 2);
00495         }
00496         else
00497         {
00498             break;
00499         }
00500         n++;
00501         shift--;
00502     }
00503 
00504     return (value >> ((shift + 1) << 2));
00505 }
00506