Mbed Cloud example program for workshop in W27 2018.

Dependencies:   MMA7660 LM75B

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SPWFSA04.cpp Source File

SPWFSA04.cpp

00001 /* SPWFSA04 Device
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 "SPWFSA04.h"
00018 #include "SpwfSAInterface.h"
00019 #include "mbed_debug.h"
00020 
00021 #if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1
00022 
00023 SPWFSA04::SPWFSA04(PinName tx, PinName rx,
00024                    PinName rts, PinName cts,
00025                    SpwfSAInterface &ifce, bool debug,
00026                    PinName wakeup, PinName reset)
00027 : SPWFSAxx(tx, rx, rts, cts, ifce, debug, wakeup, reset) {
00028 }
00029 
00030 bool SPWFSA04::open(const char *type, int* spwf_id, const char* addr, int port)
00031 {
00032     int socket_id;
00033     int value;
00034     int trials;
00035 
00036     if(!_parser.send("AT+S.SOCKON=%s,%d,NULL,%s", addr, port, type))
00037     {
00038         debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__);
00039         return false;
00040     }
00041 
00042     /* handle both response possibilities here before returning
00043      * otherwise module seems to remain in inconsistent state.
00044      */
00045 
00046     if(!_parser.recv("AT-S.")) { // get prefix
00047         debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__);
00048         empty_rx_buffer();
00049         return false;
00050     }
00051 
00052     /* wait for next character */
00053     trials = 0;
00054     while((value = _parser.getc()) < 0) {
00055         if(++trials >= SPWFXX_MAX_TRIALS) {
00056             debug("\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__);
00057             empty_rx_buffer();
00058             return false;
00059         }
00060     }
00061 
00062     switch(value) {
00063         case 'O':
00064             /* get next character */
00065             value = _parser.getc();
00066             if(value != 'n') {
00067                 debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d) (%d, \'%c\')\r\n",
00068                          __LINE__, value, value);
00069                 empty_rx_buffer();
00070                 return false;
00071             }
00072 
00073             /* get socket id */
00074             if(!(_parser.recv(":%*u.%*u.%*u.%*u:%d\n", &socket_id)
00075                     && _recv_delim_lf()
00076                     && _recv_ok())) {
00077                 debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__);
00078                 empty_rx_buffer();
00079                 return false;
00080             }
00081             debug_if(_dbg_on, "AT^ AT-S.On:%s:%d\r\n", addr, socket_id);
00082 
00083             *spwf_id = socket_id;
00084             return true;
00085         case 'E':
00086             int err_nr;
00087             if(_parser.recv("RROR:%d:%255[^\n]\n", &err_nr, _msg_buffer) && _recv_delim_lf()) {
00088                 debug_if(_dbg_on, "AT^ AT-S.ERROR:%d:%s (%d)\r\n", err_nr, _msg_buffer, __LINE__);
00089             } else {
00090                 debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__);
00091                 empty_rx_buffer();
00092             }
00093             break;
00094         default:
00095             debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d) (%d, \'%c\')\r\n",
00096                      __LINE__, value, value);
00097             empty_rx_buffer();
00098             break;
00099     }
00100 
00101     return false;
00102 }
00103 
00104 int SPWFSA04::_read_in(char* buffer, int spwf_id, uint32_t amount) {
00105     int ret = -1;
00106     int received, cumulative;
00107 
00108     MBED_ASSERT(buffer != NULL);
00109 
00110     /* block asynchronous indications */
00111     if(!_winds_off()) {
00112         return -1;
00113     }
00114 
00115     /* read in data */
00116     if(_parser.send("AT+S.SOCKR=%d,%d", spwf_id, (unsigned int)amount)) {
00117         if(!(_parser.recv("AT-S.Reading:%d:%d\n", &received, &cumulative) &&
00118                 _recv_delim_lf())) {
00119             debug_if(_dbg_on, "\r\nSPWF> failed to receive AT-S.Reading (%s, %d)\r\n", __func__, __LINE__);
00120             empty_rx_buffer();
00121         } else {
00122             /* set high timeout */
00123             _parser.set_timeout(SPWF_READ_BIN_TIMEOUT);
00124             /* read in binary data */
00125             int read = _parser.read(buffer, amount);
00126             /* reset timeout value */
00127             _parser.set_timeout(_timeout);
00128             if(read > 0) {
00129                 if(_recv_ok()) {
00130                     ret = amount;
00131 
00132                     /* remove from pending sizes
00133                      * (MUST be done before next async indications handling (e.g. `_winds_on()`)) */
00134                     _remove_pending_pkt_size(spwf_id, amount);
00135                 } else {
00136                     debug_if(_dbg_on, "\r\nSPWF> failed to receive OK (%s, %d)\r\n", __func__, __LINE__);
00137                     empty_rx_buffer();
00138                 }
00139             } else {
00140                 debug_if(_dbg_on, "\r\nSPWF> failed to read binary data (%s, %d)\r\n", __func__, __LINE__);
00141                 empty_rx_buffer();
00142             }
00143         }
00144     } else {
00145         debug_if(_dbg_on, "%s(%d): failed to send SOCKR\r\n", __func__, __LINE__);
00146     }
00147 
00148     debug_if(_dbg_on, "\r\nSPWF> %s():\t%d:%d\r\n", __func__, spwf_id, amount);
00149 
00150     /* unblock asynchronous indications */
00151     _winds_on();
00152 
00153     return ret;
00154 }
00155 
00156 /* betzw - TODO: improve performance! */
00157 bool SPWFSA04::_recv_ap(nsapi_wifi_ap_t *ap)
00158 {
00159     bool ret;
00160     int curr;
00161     unsigned int channel;
00162     int trials;
00163 
00164     ap->security = NSAPI_SECURITY_UNKNOWN;
00165 
00166     /* determine list end */
00167     curr = _parser.getc();
00168     if(curr == 'A') { // assume end of list ("AT-S.OK")
00169         if(!(_parser.recv("T-S.OK\n") && _recv_delim_lf())) {
00170             empty_rx_buffer();
00171         }
00172         return false;
00173     }
00174 
00175     /* run to 'horizontal tab' */
00176     trials = 0;
00177     while(_parser.getc() != '\x09') {
00178         if(trials++ > SPWFXX_MAX_TRIALS) {
00179             debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__);
00180             empty_rx_buffer();
00181             return false;
00182         }
00183     }
00184 
00185     /* read in next line */
00186     ret = _parser.recv("%255[^\n]\n", _msg_buffer) && _recv_delim_lf();
00187 
00188     /* parse line - first phase */
00189     if(ret) {
00190         int val = sscanf(_msg_buffer,
00191                          " %*s %hhx:%hhx:%hhx:%hhx:%hhx:%hhx CHAN: %u RSSI: %hhd SSID: \'%*255[^\']\'",
00192                          &ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4], &ap->bssid[5],
00193                          &channel, &ap->rssi);
00194         if(val < 8) {
00195             ret = false;
00196         }
00197     }
00198 
00199     /* parse line - second phase */
00200     if(ret) { // ret == true
00201         char value;
00202         char *rest, *first, *last;
00203 
00204         /* decide about position of `CAPS:` */
00205         first = strchr(_msg_buffer, '\'');
00206         if(first == NULL) {
00207             debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__);
00208             empty_rx_buffer();
00209             return false;
00210         }
00211         last = strrchr(_msg_buffer, '\'');
00212         if((last == NULL) || (last < (first+1))) {
00213             debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__);
00214             empty_rx_buffer();
00215             return false;
00216         }
00217         rest = strstr(last, "CAPS:");
00218         if(rest == NULL) {
00219             debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__);
00220             empty_rx_buffer();
00221             return false;
00222         }
00223 
00224         /* substitute '\'' with '\0' */
00225         *last = '\0';
00226 
00227         /* copy values */
00228         memcpy(&ap->ssid, first+1, sizeof(ap->ssid)-1);
00229         ap->ssid[sizeof(ap->ssid)-1] = '\0';
00230         ap->channel = channel;
00231 
00232         /* skip `CAPS: 0421 ` */
00233         if(strlen(rest) < 11) {
00234             debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__);
00235             empty_rx_buffer();
00236             return false;
00237         }
00238         rest += 11;
00239 
00240         /* get next character */
00241         value = *rest++;
00242         if(value != 'W') { // no security
00243             ap->security = NSAPI_SECURITY_NONE;
00244             return true;
00245         }
00246 
00247         /* determine security */
00248         {
00249             char buffer[10];
00250 
00251             if(!(sscanf(rest, "%s%*[\x20]", (char*)&buffer) > 0)) { // '\0x20' == <space>
00252                 return true;
00253             } else if(strncmp("EP", buffer, 10) == 0) {
00254                 ap->security = NSAPI_SECURITY_WEP;
00255                 return true;
00256             } else if(strncmp("PA2", buffer, 10) == 0) {
00257                 ap->security = NSAPI_SECURITY_WPA2;
00258                 return true;
00259             } else if(strncmp("PA", buffer, 10) != 0) {
00260                 return true;
00261             }
00262 
00263             /* got a "WPA", check for "WPA2" */
00264             rest += strlen(buffer);
00265             value = *rest++;
00266             if(value == '\0') { // no further protocol
00267                 ap->security = NSAPI_SECURITY_WPA;
00268                 return true;
00269             } else { // assume "WPA2"
00270                 ap->security = NSAPI_SECURITY_WPA_WPA2;
00271                 return true;
00272             }
00273         }
00274     } else { // ret == false
00275         debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__);
00276         empty_rx_buffer();
00277     }
00278 
00279     return ret;
00280 }
00281 
00282 nsapi_size_or_error_t SPWFSA04::scan(WiFiAccessPoint *res, unsigned limit)
00283 {
00284     unsigned int cnt = 0, found;
00285     nsapi_wifi_ap_t ap;
00286 
00287     if (!_parser.send("AT+S.SCAN=s,")) {
00288         return NSAPI_ERROR_DEVICE_ERROR;
00289     }
00290 
00291     if(!(_parser.recv("AT-S.Parsing Networks:%u\n", &found) && _recv_delim_lf())) {
00292         debug_if(_dbg_on, "SPWF> error start network scanning\r\n");
00293         empty_rx_buffer();
00294         return NSAPI_ERROR_DEVICE_ERROR;
00295     }
00296 
00297     debug_if(_dbg_on, "AT^ AT-S.Parsing Networks:%u\r\n", found);
00298 
00299     if(found > 0) {
00300         while (_recv_ap(&ap)) {
00301             if (cnt < limit) {
00302                 res[cnt] = WiFiAccessPoint(ap);
00303             }
00304 
00305             if (!((limit != 0) && ((cnt + 1) > limit))) {
00306                 cnt++;
00307             }
00308         }
00309     } else {
00310         if(!_recv_ok()) {
00311             empty_rx_buffer();
00312         }
00313     }
00314 
00315     return cnt;
00316 }
00317 
00318 #endif // MBED_CONF_IDW0XX1_EXPANSION_BOARD