AT Parser and bufferedSerial based SPWF library

Dependencies:   ATParser

Dependents:   X_NUCLEO_IDW01M1v2

Fork of SPWF01SA by ST Expansion SW Team

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