Mbed Cloud example program for workshop in W27 2018.

Dependencies:   MMA7660 LM75B

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SPWFSA01.cpp Source File

SPWFSA01.cpp

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