Example of AWS IoT connection and Web Dashboard thru STM32 Nucleo evaluation board and mbed OS.

Dependencies:   X_NUCLEO_IKS01A1 mbed FP MQTTPacket DnsQuery ATParser

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SPWFSA01.cpp Source File

SPWFSA01.cpp

00001 /* SPWFInterface Example
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 #include "SPWFSA01.h"
00018 #include "mbed_debug.h"
00019 #include "stdint.h"
00020 
00021 #define SPWFSA01_CONNECT_TIMEOUT    15000
00022 #define SPWFSA01_SEND_TIMEOUT       5000
00023 #define SPWFSA01_RECV_TIMEOUT       1500//some commands like AT&F/W takes some time to get the result back!
00024 #define SPWFSA01_MISC_TIMEOUT       500
00025 #define SPWFSA01_SOCKQ_TIMEOUT      3000
00026 
00027 #define EPOCH_TIME                  1453727657//Human time (GMT): Mon, 25 Jan 2016 13:14:17 GMT
00028 
00029    SPWFSA01::SPWFSA01(PinName tx, PinName rx, PinName reset, PinName wakeup, bool debug)
00030     : _serial(tx, rx, 1024), _parser(_serial,"\r\n", 2048),      
00031       _wakeup(wakeup, PIN_OUTPUT, PullNone, 0),
00032       _reset(reset, PIN_OUTPUT, PullNone, 1),
00033       dbg_on(debug)
00034 {
00035     _serial.baud(115200);  // LICIO  FIXME increase the speed
00036     _parser.debugOn(debug);
00037 }
00038 
00039 bool SPWFSA01::startup(int mode)
00040 {
00041     _parser.setTimeout(SPWFSA01_MISC_TIMEOUT);    
00042     /*Test module before reset*/
00043     waitSPWFReady();
00044     /*Reset module*/
00045     reset();
00046      
00047     /*set local echo to 0*/
00048     if(!(_parser.send("AT+S.SCFG=localecho1,%d\r", 0) && _parser.recv("OK"))) 
00049         {
00050             debug_if(dbg_on, "SPWF> error local echo set\r\n");
00051             return false;
00052         }   
00053     /*reset factory settings*/
00054     if(!(_parser.send("AT&F") && _parser.recv("OK"))) 
00055         {
00056             debug_if(dbg_on, "SPWF> error AT&F\r\n");
00057             return false;
00058         }
00059         
00060     /*set Wi-Fi mode and rate to b/g*/
00061     if(!(_parser.send("AT+S.SCFG=wifi_ht_mode,%d\r", 0) && _parser.recv("OK")))
00062     {
00063         debug_if(dbg_on, "SPWF> error setting ht_mode\r\n");
00064         return false;
00065     }
00066         
00067     //if(!(_parser.send("AT+S.SCFG=wifi_opr_rate_mask,0x003FFFCF\r") && _parser.recv("OK")))
00068     if(!(_parser.send("AT+S.SCFG=wifi_opr_rate_mask,0x00000001\r") && _parser.recv("OK")))// set most effective speed for such kind of device
00069         {
00070             debug_if(dbg_on, "SPWF> error setting operational rates\r\n");
00071             return false;
00072         }
00073 
00074     if(!(_parser.send("AT+S.SCFG=wifi_bas_rate_mask,0x0000000F\r") && _parser.recv("OK")))// set most effective speed for such kind of device
00075     {
00076         debug_if(dbg_on, "SPWF> error setting basic rates\r\n");
00077         return false;
00078     }
00079 
00080     if(!(_parser.send("AT+S.SCFG=wifi_powersave,0\r") && _parser.recv("OK")))// set most effective speed for such kind of device
00081     {
00082        debug_if(dbg_on, "SPWF> error setting power save mode\r\n");
00083        return false;
00084     }
00085 
00086     if(!(_parser.send("AT+S.SCFG=sleep_enabled,0\r") && _parser.recv("OK")))// set most effective speed for such kind of device
00087     {
00088        debug_if(dbg_on, "SPWF> error setting sleep  mode\r\n");
00089        return false;
00090     }
00091 
00092     if(!(_parser.send("AT+S.SCFG=wifi_tx_power,18\r") && _parser.recv("OK")))// set most effective speed for such kind of device
00093     {
00094        debug_if(dbg_on, "SPWF> error setting transmit power\r\n");
00095        return false;
00096     }
00097 
00098     if(!(_parser.send("AT+S.SCFG=ip_use_dhcp,1\r") && _parser.recv("OK")))// set most effective speed for such kind of device
00099     {
00100        debug_if(dbg_on, "SPWF> error setting dhcp on\r\n");
00101        return false;
00102     }
00103 
00104     if(!(_parser.send("AT+S.SCFG=ip_dhcp_timeout,20\r") && _parser.recv("OK")))// set most effective speed for such kind of device
00105     {
00106        debug_if(dbg_on, "SPWF> error setting dhcp timeout\r\n");
00107        return false;
00108     }
00109 
00110     /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/
00111     if(!(_parser.send("AT+S.SCFG=wifi_mode,%d\r", mode) && _parser.recv("OK")))
00112         {
00113             debug_if(dbg_on, "SPWF> error wifi mode set\r\n");
00114             return false;
00115         } 
00116 
00117     /* save current setting in flash */
00118     if(!(_parser.send("AT&W") && _parser.recv("OK")))
00119         {
00120             debug_if(dbg_on, "SPWF> error AT&W\r\n");
00121             return false;
00122         }
00123         
00124     /*reset again and send AT command and check for result (AT->OK)*/
00125     reset();
00126         
00127     return true;    
00128 }
00129 
00130 bool SPWFSA01::hw_reset(void)
00131 {    
00132     if (_reset.is_connected()) {
00133     /* reset the pin PC12 */  
00134     _reset.write(0);
00135     wait_ms(200);
00136     _reset.write(1); 
00137     wait_ms(100);
00138     return 1;
00139     } else { return 0; }
00140 }
00141 
00142 bool SPWFSA01::reset(void)
00143 {
00144     if(!_parser.send("AT+CFUN=1")) return false;
00145     while(1) {
00146         if (_parser.recv("+WIND:32:WiFi Hardware Started\r")) {
00147             return true;
00148         }
00149     }
00150 }
00151 
00152 void SPWFSA01::waitSPWFReady(void)
00153 {
00154     //wait_ms(200);
00155     while(1) 
00156         if(_parser.send("AT") && _parser.recv("OK"))
00157             //till we get OK from AT command
00158             //printf("\r\nwaiting for reset to complete..\n");
00159             return;
00160                  
00161 }
00162 
00163 /* Security Mode
00164     None          = 0, 
00165     WEP           = 1,
00166     WPA_Personal  = 2,
00167 */
00168 bool SPWFSA01::connect(const char *ap, const char *passPhrase, int securityMode)
00169 {
00170     uint32_t n1, n2, n3, n4;
00171 
00172     _parser.setTimeout(SPWFSA01_CONNECT_TIMEOUT);       
00173     //AT+S.SCFG=wifi_wpa_psk_text,%s\r
00174     if(!(_parser.send("AT+S.SCFG=wifi_wpa_psk_text,%s", passPhrase) && _parser.recv("OK"))) 
00175         {
00176             debug_if(dbg_on, "SPWF> error pass set\r\n");
00177             return false;
00178         } 
00179     //AT+S.SSIDTXT=%s\r
00180     if(!(_parser.send("AT+S.SSIDTXT=%s", ap) && _parser.recv("OK"))) 
00181         {
00182             debug_if(dbg_on, "SPWF> error ssid set\r\n");
00183             return false;
00184         }
00185     //AT+S.SCFG=wifi_priv_mode,%d\r
00186     if(!(_parser.send("AT+S.SCFG=wifi_priv_mode,%d", securityMode) && _parser.recv("OK"))) 
00187         {
00188             debug_if(dbg_on, "SPWF> error security mode set\r\n");
00189             return false;
00190         } 
00191     //"AT+S.SCFG=wifi_mode,%d\r"
00192     /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/
00193     if(!(_parser.send("AT+S.SCFG=wifi_mode,%d\r", 1) && _parser.recv("OK")))
00194         {
00195             debug_if(dbg_on, "SPWF> error wifi mode set\r\n");
00196             return false;
00197         }
00198     //AT&W
00199     /* save current setting in flash */
00200     if(!(_parser.send("AT&W") && _parser.recv("OK")))
00201         {
00202             debug_if(dbg_on, "SPWF> error AT&W\r\n");
00203             return false;
00204         }
00205     //reset module
00206     reset();
00207     
00208     while(1)
00209         if((_parser.recv("+WIND:24:WiFi Up:%u.%u.%u.%u",&n1, &n2, &n3, &n4)))
00210             {
00211                 break;
00212             }            
00213         
00214     return true;
00215 }
00216 
00217 bool SPWFSA01::disconnect(void)
00218 {
00219     //"AT+S.SCFG=wifi_mode,%d\r"
00220     /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/
00221     if(!(_parser.send("AT+S.SCFG=wifi_mode,%d\r", 0) && _parser.recv("OK")))
00222         {
00223             debug_if(dbg_on, "SPWF> error wifi mode set\r\n");
00224             return false;
00225         }
00226     //AT&W
00227     /* save current setting in flash */
00228     if(!(_parser.send("AT&W") && _parser.recv("OK")))
00229         {
00230             debug_if(dbg_on, "SPWF> error AT&W\r\n");
00231             return false;
00232         }
00233     //reset module
00234     reset();
00235     return true;
00236 }
00237 
00238 bool SPWFSA01::dhcp(int mode)
00239 {
00240     //only 3 valid modes
00241     //0->off(ip_addr must be set by user), 1->on(auto set by AP), 2->on&customize(miniAP ip_addr can be set by user)
00242     if(mode < 0 || mode > 2) {
00243         return false;
00244     }
00245         
00246     return _parser.send("AT+S.SCFG=ip_use_dhcp,%d\r", mode)
00247         && _parser.recv("OK");
00248 }
00249 
00250 
00251 const char *SPWFSA01::getIPAddress(void)
00252 {
00253     uint32_t n1, n2, n3, n4;
00254     
00255     if (!(_parser.send("AT+S.STS=ip_ipaddr")
00256         && _parser.recv("#  ip_ipaddr = %u.%u.%u.%u", &n1, &n2, &n3, &n4)
00257         && _parser.recv("OK"))) {
00258             debug_if(dbg_on, "SPWF> getIPAddress error\r\n");
00259         return 0;
00260     }
00261 
00262     sprintf((char*)_ip_buffer,"%u.%u.%u.%u", n1, n2, n3, n4);
00263 
00264     return _ip_buffer;
00265 }
00266 
00267 const char *SPWFSA01::getMACAddress(void)
00268 {
00269     uint32_t n1, n2, n3, n4, n5, n6;
00270     
00271     if (!(_parser.send("AT+S.GCFG=nv_wifi_macaddr")
00272         && _parser.recv("#  nv_wifi_macaddr = %x:%x:%x:%x:%x:%x", &n1, &n2, &n3, &n4, &n5, &n6)
00273         && _parser.recv("OK"))) {
00274             debug_if(dbg_on, "SPWF> getMACAddress error\r\n");
00275         return 0;
00276     }
00277 
00278     sprintf((char*)_mac_buffer,"%02X:%02X:%02X:%02X:%02X:%02X", n1, n2, n3, n4, n5, n6);
00279 
00280     return _mac_buffer;
00281 }
00282 
00283 bool SPWFSA01::isConnected(void)
00284 {
00285     return getIPAddress() != 0; 
00286 }
00287 
00288 bool SPWFSA01::open(const char *type, int* id, const char* addr, int port)
00289 {
00290     Timer timer;
00291     timer.start();
00292     socket_closed = 0; 
00293        
00294     if(!_parser.send("AT+S.SOCKON=%s,%d,%s,ind", addr, port, type))
00295         {
00296             debug_if(dbg_on, "SPWF> error opening socket\r\n");
00297             return false;
00298         }
00299         
00300     while(1)
00301         {
00302             if( _parser.recv(" ID: %d", id)
00303                 && _parser.recv("OK"))
00304                 break;
00305             
00306             if (timer.read_ms() > SPWFSA01_CONNECT_TIMEOUT) {
00307                 return false;
00308             }
00309         
00310             //TODO:implement time-out functionality in case of no response
00311             //if(timeout) return false;
00312             //TODO: deal with errors like "ERROR: Failed to resolve name"
00313             //TODO: deal with errors like "ERROR: Data mode not available"
00314         }
00315 
00316     return true;
00317 }
00318 
00319 bool SPWFSA01::send(int id, const void *data, uint32_t amount)
00320 {    
00321     char _buf[18];
00322     _parser.setTimeout(SPWFSA01_SEND_TIMEOUT);
00323     
00324     sprintf((char*)_buf,"AT+S.SOCKW=%d,%d\r", id, amount);   
00325     
00326     //May take a second try if device is busy
00327     for (unsigned i = 0; i < 2; i++) {
00328         if (_parser.write((char*)_buf, strlen(_buf)) >=0
00329             && _parser.write((char*)data, (int)amount) >= 0
00330             && _parser.recv("OK")) {
00331             return true;
00332         }     
00333     }
00334     return false;
00335 }
00336 
00337 
00338 int32_t SPWFSA01::recv(int id, void *data, uint32_t amount)
00339 {
00340     uint32_t recv_amount=0;
00341     int wind_id;    
00342  
00343     if (socket_closed) {
00344         socket_closed = 0;
00345         return -3;
00346     }
00347     if(!(_parser.send("AT+S.SOCKQ=%d", id)  //send a query (will be required for secure sockets)
00348         && _parser.recv(" DATALEN: %u", &recv_amount)
00349         && _parser.recv("OK"))) {
00350         return -2;
00351     }            
00352     if (recv_amount==0) { return -1; } 
00353     if(recv_amount > amount)
00354         recv_amount = amount;
00355         
00356     int par_timeout = _parser.getTimeout();        
00357     _parser.setTimeout(0);
00358     
00359      while(_parser.recv("+WIND:%d:", &wind_id)) {
00360 //        printf("Wind received: %d\n\r", wind_id);
00361         if (wind_id == 58) {
00362             socket_closed = 1;
00363             _parser.flush();            
00364         }
00365     }       
00366     _parser.setTimeout(par_timeout);
00367     
00368     _parser.flush();
00369     if(!(_parser.send("AT+S.SOCKR=%d,%d", id, recv_amount))){
00370         return -2;    
00371     }
00372     if(!((_parser.read((char*)data, recv_amount) >0)
00373             && _parser.recv("OK"))) {
00374         return -2;
00375     }    
00376     return recv_amount;
00377 }
00378 
00379 bool SPWFSA01::close(int id)
00380 {
00381     uint32_t recv_amount=0;    
00382     void * data = NULL;    
00383 
00384     _parser.setTimeout(SPWFSA01_MISC_TIMEOUT);    
00385     _parser.flush();
00386     /* socket flush */
00387     if(!(_parser.send("AT+S.SOCKQ=%d", id)  //send a query (will be required for secure sockets)
00388         && _parser.recv(" DATALEN: %u", &recv_amount)
00389         && _parser.recv("OK"))) {
00390             return -2;
00391     } 
00392     if (recv_amount>0) {
00393         data = malloc (recv_amount+4);
00394         if(!(_parser.send("AT+S.SOCKR=%d,%d", id, recv_amount))) { 
00395             free (data); 
00396             return -2; 
00397         }
00398  //       printf ("--->>>Close flushing recv_amount: %d  \n\r",recv_amount);            
00399         if(!((_parser.read((char*)data, recv_amount) >0)
00400             && _parser.recv("OK"))) {
00401              free (data);
00402              return -2;
00403         }
00404         free (data);                            
00405     }     
00406     
00407     //May take a second try if device is busy or error is returned
00408     for (unsigned i = 0; i < 2; i++) {
00409         if (_parser.send("AT+S.SOCKC=%d", id)
00410             && _parser.recv("OK")) {
00411             socket_closed = 1;     
00412             return true;
00413         }
00414         else
00415         {
00416             if(_parser.recv("ERROR: Pending data")) {
00417                     debug_if(dbg_on, "SPWF> ERROR!!!!\r\n");
00418                     return false;
00419             }
00420         }
00421         //TODO: Deal with "ERROR: Pending data" (Closing a socket with pending data)
00422     }
00423     return false;
00424 }
00425 
00426 
00427 bool SPWFSA01::readable()
00428 {
00429     return _serial.readable();
00430 }
00431 
00432 bool SPWFSA01::writeable()
00433 {
00434     return _serial.writeable();
00435 }
00436 
00437 int SPWFSA01::setSocketClientSecurity(uint8_t* tls_mode, uint8_t* root_ca_server, uint8_t* client_cert, uint8_t* client_key, uint8_t* client_domain, uint32_t tls_epoch_time)
00438 {
00439     int err = 0;
00440     unsigned long epoch_time;
00441 
00442     if(!(_parser.send("AT+S.TLSCERT2=clean,all\r", 0) && _parser.recv("OK")))
00443     {
00444       debug_if(dbg_on, "SPWF> TLSCERT2 cleared\r\n");
00445       return -1;
00446     }
00447 
00448     if(tls_epoch_time==0)
00449         epoch_time = EPOCH_TIME;
00450     else
00451         epoch_time = tls_epoch_time;
00452 
00453     if(!(_parser.send("AT+S.SETTIME=%lu\r", (unsigned long)epoch_time) && _parser.recv("OK")))
00454     {
00455       debug_if(dbg_on, "SPWF> time is set to %d\r\n", epoch_time);
00456       return -1;
00457     }
00458 
00459     /*AT+S.TLSCERT=f_ca,<size><CR><data>*/
00460     if(!(_parser.send("AT+S.TLSCERT=f_ca,%d\r%s\r", strlen((const char *)root_ca_server) - 1, root_ca_server) && _parser.recv("OK")))
00461     {
00462       debug_if(dbg_on, "SPWF> error TLSCERT=f_ca set\r\n");
00463       return -1;
00464     }
00465 
00466     /*AT+S.TLSCERT=f_cert,<size><CR><data>*/
00467     if(tls_mode[0]=='m')
00468     {
00469         if(!(_parser.send("AT+S.TLSCERT=f_cert,%d\r%s", strlen((const char *)client_cert) - 1, client_cert) && _parser.recv("OK")))
00470         {
00471           debug_if(dbg_on, "SPWF> error TLSCERT=f_cert set\r\n");
00472           return -1;
00473         }
00474 
00475         /*AT+S.TLSCERT=f_key,<size><CR><data>*/
00476         if(!(_parser.send("AT+S.TLSCERT=f_key,%d\r%s", strlen((const char *)client_key) - 1, client_key) && _parser.recv("OK")))
00477         {
00478           debug_if(dbg_on, "SPWF> error TLSCERT=f_key set\r\n");
00479           return -1;
00480         }
00481     }
00482 
00483     /*AT+S.TLSDOMAIN=f_domain,<server domain>*/
00484     if(!(_parser.send("AT+S.TLSDOMAIN=f_domain,%s\r", client_domain) && _parser.recv("OK")))
00485     {
00486       debug_if(dbg_on, "SPWF> error TLSDOMAIN=f_domain set\r\n");
00487       return -1;
00488     }
00489 
00490     return err;
00491 }
00492