Mbed Cloud example program for workshop in W27 2018.

Dependencies:   MMA7660 LM75B

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