Use this interface to connect to and interact with the WNC M14A2A LTE Cellular Data Module which is provided by Wistron NeWeb Corporation (WNC) when using ARMmbed v5. The interface provides a Networking interface that can be used with the AT&T Cellular IoT Starter Kit that is sold by Avnet (http://cloudconnectkits.org/product/att-cellular-iot-starter-kit).
Dependencies: WncControllerK64F
Dependents: easy-connect-wnc easy-connect easy-connect111
WNC14A2AInterface.cpp
00001 00002 #include "WNC14A2AInterface.h" 00003 #include <Thread.h> 00004 #include <string> 00005 00006 /** WNC14A2AInterface class 00007 * Implementation of the NetworkInterface for the AT&T IoT Starter Kit 00008 * based on the WNC 14A2A LTE Data Module 00009 */ 00010 00011 #define WNC14A2A_MISC_TIMEOUT 3000 00012 #define WNC14A2A_RESTART_TIMEOUT 10000 00013 #define WNC14A2A_COMMUNICATION_TIMEOUT 100 00014 #define READ_EVERYMS 500 00015 00016 ///////////////////////////////////////////////////// 00017 // NXP GPIO Pins that are used to initialize the WNC Shield 00018 ///////////////////////////////////////////////////// 00019 DigitalOut mdm_uart2_rx_boot_mode_sel(PTC17); // on powerup, 0 = boot mode, 1 = normal boot 00020 DigitalOut mdm_power_on(PTB9); // 0 = modem on, 1 = modem off (hold high for >5 seconds to cycle modem) 00021 DigitalOut mdm_wakeup_in(PTC2); // 0 = let modem sleep, 1 = keep modem awake -- Note: pulled high on shield 00022 DigitalOut mdm_reset(PTC12); // active high 00023 DigitalOut shield_3v3_1v8_sig_trans_ena(PTC4); // 0 = disabled (all signals high impedence, 1 = translation active 00024 DigitalOut mdm_uart1_cts(PTD0); 00025 00026 // Define pin associations for the controller class to use be careful to 00027 // keep the order of the pins in the initialization list. 00028 00029 using namespace WncControllerK64F_fk; // namespace for the controller class use 00030 00031 WncGpioPinListK64F wncPinList = { 00032 &mdm_uart2_rx_boot_mode_sel, 00033 &mdm_power_on, 00034 &mdm_wakeup_in, 00035 &mdm_reset, 00036 &shield_3v3_1v8_sig_trans_ena, 00037 &mdm_uart1_cts 00038 }; 00039 00040 Thread smsThread; 00041 static Mutex _pwnc_mutex; 00042 00043 static WNCSOCKET _sockets[WNC14A2A_SOCKET_COUNT]; 00044 BufferedSerial mdmUart(PTD3,PTD2,1024,1); //UART for WNC Module 00045 00046 //------------------------------------------------------------------------- 00047 // 00048 // Class constructor. May be invoked with or without the APN and/or pointer 00049 // to a debug output. After the constructor has completed, the user can 00050 // check _errors to determine if any errors occured during instanciation. 00051 // _errors = 0 when no errors occured 00052 // 1 when power-on error occured 00053 // 2 when settng the APN error occured 00054 // 4 when unable to get the network configuration 00055 // 8 when allocating a new WncControllerK64F object failed 00056 // NSAPI_ERROR_UNSUPPORTED when attempting to create a second object 00057 // 00058 00059 WNC14A2AInterface::WNC14A2AInterface(WNCDebug *dbg) : 00060 m_wncpoweredup(0), 00061 _pwnc(NULL), 00062 m_active_socket(-1), 00063 m_smsmoning(0) 00064 { 00065 _errors = NSAPI_ERROR_OK; 00066 00067 m_debug=false; 00068 00069 if( _pwnc ) { //can only have a single instance of class 00070 _errors = NSAPI_ERROR_UNSUPPORTED; 00071 return; 00072 } 00073 for( int i=0; i<WNC14A2A_SOCKET_COUNT; i++ ) { 00074 _sockets[i].socket = i; 00075 _sockets[i].addr = NULL; 00076 _sockets[i].opened=false; 00077 _sockets[i].proto=NSAPI_TCP; 00078 } 00079 00080 00081 memset(_mac_address,0x00,sizeof(_mac_address)); 00082 00083 _debugUart = dbg; 00084 if( dbg != NULL ) { 00085 dbg->printf("Adding DEBUG output\n"); 00086 _pwnc = new WncControllerK64F(&wncPinList, &mdmUart, dbg); 00087 m_debug=true; 00088 if( _pwnc ) 00089 _pwnc->enableDebug(1,1); 00090 } 00091 else 00092 _pwnc = new WncControllerK64F_fk::WncControllerK64F(&wncPinList, &mdmUart, NULL); 00093 00094 if( !_pwnc ) { 00095 debugOutput(_debugUart,(char*)", FAILED!\n"); 00096 _errors = NSAPI_ERROR_DEVICE_ERROR; 00097 } 00098 else 00099 debugOutput(_debugUart, (char*)"\n"); 00100 } 00101 00102 /*------------------------------------------------------------------------- 00103 * standard destructor... free up allocated memory 00104 */ 00105 00106 WNC14A2AInterface::~WNC14A2AInterface() 00107 { 00108 delete _pwnc; //free the existing WncControllerK64F object 00109 } 00110 00111 nsapi_error_t WNC14A2AInterface::connect() 00112 { 00113 debugOutput(_debugUart,(char*)"+CALLED connect(void)\n"); 00114 return connect(NULL,NULL,NULL); 00115 } 00116 00117 /*------------------------------------------------------------------------- 00118 * This call powers up the WNC module and connects to the user specified APN. If no APN is provided 00119 * a default one of 'm2m.com.attz' will be used (the NA APN) 00120 * 00121 * Input: *apn is the APN string to use 00122 * *username - NOT CURRENTLY USED 00123 * *password - NOT CURRENTLY USED 00124 * 00125 * Output: none 00126 * 00127 * Return: nsapi_error_t 00128 */ 00129 nsapi_error_t WNC14A2AInterface::connect(const char *apn, const char *username, const char *password) 00130 { 00131 debugOutput(_debugUart,(char*)"+ENTER connect(apn,user,pass)\n"); 00132 if( !_pwnc ) 00133 return (_errors=NSAPI_ERROR_NO_CONNECTION); 00134 00135 if (!apn) 00136 apn = "m2m.com.attz"; 00137 00138 if (!m_wncpoweredup) { 00139 debugOutput(_debugUart,(char*)"+call powerWncOn using '%s'\n",apn); 00140 _pwnc_mutex.lock(); 00141 m_wncpoweredup=_pwnc->powerWncOn(apn,40); 00142 _pwnc_mutex.unlock(); 00143 _errors = m_wncpoweredup? 1:0; 00144 } 00145 else { //we've already called powerWncOn and set the APN, so just set the APN 00146 debugOutput(_debugUart,(char*)"+already powered on, set APN to: %s\n",apn); 00147 _pwnc_mutex.lock(); 00148 _errors = _pwnc->setApnName(apn)? 1:0; 00149 _pwnc_mutex.unlock(); 00150 } 00151 00152 _pwnc_mutex.lock(); 00153 _errors |= _pwnc->getWncNetworkingStats(&myNetStats)? 2:0; 00154 _pwnc_mutex.unlock(); 00155 00156 debugOutput(_debugUart,(char*)"+EXIT connect %02X\n",_errors); 00157 return (!_errors)? NSAPI_ERROR_NO_CONNECTION : NSAPI_ERROR_OK; 00158 } 00159 00160 /*-------------------------------------------------------------------------- 00161 * This function calls the WNC to retrieve the device (this WNC) connected IP 00162 * address once we are connected to the APN. 00163 * 00164 * Inputs: NONE. 00165 * 00166 * Output: none. 00167 * 00168 * Return: pointer to the IP string or NULL 00169 */ 00170 const char *WNC14A2AInterface::get_ip_address() 00171 { 00172 const char *ptr=NULL; 00173 00174 _pwnc_mutex.lock(); 00175 if ( _pwnc->getWncNetworkingStats(&myNetStats) ) { 00176 CHK_WNCFE(( _pwnc->getWncStatus() == FATAL_FLAG ), null); 00177 ptr = &myNetStats.ip[0]; 00178 } 00179 _pwnc_mutex.unlock(); 00180 _errors=NSAPI_ERROR_NO_CONNECTION; 00181 return ptr; 00182 } 00183 00184 #if 0 00185 /*-------------------------------------------------------------------------- 00186 * This function calls the WNC to retrieve the currently connected IP address 00187 * it will be a bogus 192.168.0.1 if we are not connected to anyone 00188 * 00189 * Inputs: NONE. 00190 * 00191 * Output: none. 00192 * 00193 * Return: pointer to the IP string or NULL 00194 */ 00195 const char *WNC14A2AInterface::get_ip_address() 00196 { 00197 static char *ptr=NULL, ipAddrStr[25]; 00198 debugOutput(_debugUart,(char*)"+ENTER get_ip_address()\n"); 00199 00200 memset(ipAddrStr, 0x00, sizeof(ipAddrStr)); 00201 _pwnc_mutex.lock(); 00202 00203 if( _pwnc && m_active_socket != -1 ) 00204 if( _pwnc->getIpAddr(m_active_socket, ipAddrStr) ) 00205 ptr=ipAddrStr; 00206 _pwnc_mutex.unlock(); 00207 _errors=NSAPI_ERROR_NO_CONNECTION; 00208 return ptr; 00209 } 00210 #endif 00211 00212 /* ------------------------------------------------------------------------- 00213 * Open a socket for the WNC. This doesn't actually open the socket within 00214 * the WNC, it only allocates a socket device and saves the pertinet info 00215 * that will be required with the WNC socket is opened. The m_active_socket 00216 * is also updated to this socket as it is assumed this socket should be used 00217 * for subsequent interactions. 00218 * 00219 * Input: 00220 * - a pointer to a handle pointer. 00221 * - The type of socket this will be, either NSAPI_UDP or NSAP_TCP 00222 * 00223 * Output: *handle is updated 00224 * 00225 * Return: 00226 * - socket being used if successful, -1 on failure 00227 */ 00228 int WNC14A2AInterface::socket_open(void **handle, nsapi_protocol_t proto) 00229 { 00230 int i; 00231 debugOutput(_debugUart,(char*)"+ENTER socket_open()\n"); 00232 00233 // search through the available sockets (WNC can only support a max amount). 00234 for( i=0; i<WNC14A2A_SOCKET_COUNT; i++ ) 00235 if( !_sockets[i].opened ) 00236 break; 00237 00238 if( i == WNC14A2A_SOCKET_COUNT ) { 00239 _errors=NSAPI_ERROR_NO_SOCKET; 00240 return -1; 00241 } 00242 00243 m_active_socket = i; 00244 _sockets[i].socket = i; //save this index to make easier later-on 00245 _sockets[i].url=""; 00246 _sockets[i].opened = true; //ok, we are using this socket now 00247 _sockets[i].addr = NULL; //but we haven't opened it yet 00248 _sockets[i].proto = (proto == NSAPI_UDP) ? 0 : 1; //set it up for what WNC wants 00249 *handle = &_sockets[i]; 00250 00251 debugOutput(_debugUart,(char*)"+USING Socket index %d, OPEN=%s, proto =%d\nEXIT socket_open()\n", 00252 i, _sockets[i].opened?"YES":"NO", _sockets[i].proto); 00253 00254 _errors = NSAPI_ERROR_OK; 00255 return i; 00256 } 00257 00258 /*------------------------------------------------------------------------- 00259 * Connect a socket to a IP/PORT. Before you can connect a socket, you must have opened 00260 * it. 00261 * 00262 * Input: handle - pointer to the socket to use 00263 * address- the IP/Port pair that will be used 00264 * 00265 * Output: none 00266 * 00267 * return: 0 or greater on success (value is the socket ID) 00268 * -1 on failure 00269 */ 00270 int WNC14A2AInterface::socket_connect(void *handle, const SocketAddress &address) 00271 { 00272 WNCSOCKET *wnc = (WNCSOCKET *)handle; 00273 00274 debugOutput(_debugUart,(char*)"+ENTER socket_connect()\n"); 00275 debugOutput(_debugUart,(char*)"+IP = %s\n+PORT= %d\n", address.get_ip_address(), address.get_port()); 00276 00277 if (!_pwnc || m_active_socket == -1) { 00278 _errors = NSAPI_ERROR_NO_SOCKET; 00279 return -1; 00280 } 00281 00282 if( !wnc->opened ) { 00283 _errors = NSAPI_ERROR_NO_SOCKET; 00284 return -1; 00285 } 00286 m_active_socket = wnc->socket; //in case the user is asking for a different socket 00287 wnc->addr = address; 00288 00289 //we will always connect using the URL if possible, if no url has been provided, try the IP address 00290 if( wnc->url.empty() ) { 00291 debugOutput(_debugUart,(char*)"+call openSocketIpAddr(%d,%s,%d,%d)\n",m_active_socket, 00292 address.get_ip_address(), address.get_port(), wnc->proto); 00293 if( !_pwnc->openSocketIpAddr(m_active_socket, address.get_ip_address(), address.get_port(), 00294 wnc->proto, WNC14A2A_COMMUNICATION_TIMEOUT) ) { 00295 _errors = NSAPI_ERROR_NO_SOCKET; 00296 return -1; 00297 } 00298 } 00299 else { 00300 debugOutput(_debugUart,(char*)"+call openSocketUrl(%d,%s,%d,%d)\n", m_active_socket, 00301 wnc->url.c_str(), wnc->addr.get_port(), wnc->proto); 00302 if( !_pwnc->openSocketUrl(m_active_socket, wnc->url.c_str(), wnc->addr.get_port(), wnc->proto) ) { 00303 _errors = NSAPI_ERROR_NO_SOCKET; 00304 return -1; 00305 } 00306 } 00307 00308 debugOutput(_debugUart,(char*)"+SOCKET %d CONNECTED!\n+URL=%s\n+IP=%s; PORT=%d\n+EXIT socket_connect()\n\n",m_active_socket, 00309 wnc->url.c_str(), wnc->addr.get_ip_address(), wnc->addr.get_port()); 00310 return 0; 00311 } 00312 00313 /*------------------------------------------------------------------------- 00314 * Perform a URL name resolve, update the IP/Port pair, and nsapi_version. nsapi_version 00315 * could be either NSAPI_IPv4 or NSAPI_IPv6 but this functional is hard coded ti NSAPI_IPv4 00316 * for now. The currently active socket is used for the resolution. 00317 * 00318 * Input: name - the URL to resolve 00319 * 00320 * Output: address - the IP/PORT pair this URL resolves to 00321 * version - always assumed to be NSAPI_IPv4 currently 00322 * 00323 * Return: nsapi_error_t 00324 */ 00325 00326 nsapi_error_t WNC14A2AInterface::gethostbyname(const char* name, SocketAddress *address, nsapi_version_t version) 00327 { 00328 nsapi_error_t ret = NSAPI_ERROR_OK; 00329 char ipAddrStr[25]; 00330 int t_socket = 0; //use a temporary socket place holder 00331 00332 debugOutput(_debugUart,(char*)"+ENTER gethostbyname()()\n+CURRENTLY:\n"); 00333 debugOutput(_debugUart,(char*)"+URL = %s\n+IP = %s\n+PORT= %d\n", name, address->get_ip_address(), address->get_port()); 00334 memset(ipAddrStr,0x00,sizeof(ipAddrStr)); 00335 00336 if (!_pwnc) 00337 return (_errors = NSAPI_ERROR_NO_SOCKET); 00338 00339 if (m_active_socket != -1) //we might have been called before a socket was opened 00340 t_socket = m_active_socket; //if so, do nothing with the active socket index 00341 00342 //Execute DNS query. 00343 if( !_pwnc->resolveUrl(t_socket, name) ) 00344 return (_errors = NSAPI_ERROR_DEVICE_ERROR); 00345 00346 //Now, get the IP address that the URL was resolved to 00347 if( !_pwnc->getIpAddr(t_socket, ipAddrStr) ) 00348 return (_errors = NSAPI_ERROR_DEVICE_ERROR); 00349 00350 address->set_ip_address(ipAddrStr); 00351 debugOutput(_debugUart,(char*)"+resolveUrl returned IP=%s\n",ipAddrStr); 00352 if( t_socket == m_active_socket ) { 00353 _sockets[m_active_socket].url=name; 00354 _sockets[m_active_socket].addr.set_ip_address(ipAddrStr); 00355 } 00356 00357 debugOutput(_debugUart,(char*)"+EXIT gethostbyname()\n+URL = %s\n+IP = %s\n+PORT= %d\n\n", 00358 _sockets[m_active_socket].url.c_str(), address->get_ip_address(), 00359 address->get_port()); 00360 _errors = ret; 00361 return ret; 00362 } 00363 00364 /*------------------------------------------------------------------------- 00365 * using the specified socket, send the data. 00366 * 00367 * Input: handle of the socket to use 00368 * pointer to the data to send 00369 * amount of data being sent 00370 * 00371 * Output: none 00372 * 00373 * Return: number of bytes that was sent 00374 */ 00375 int WNC14A2AInterface::socket_send(void *handle, const void *data, unsigned size) 00376 { 00377 WNCSOCKET *wnc = (WNCSOCKET *)handle; 00378 int r = -1; 00379 debugOutput(_debugUart,(char*)"+ENTER socket_send()\n"); 00380 00381 if (!_pwnc || m_active_socket == -1) { 00382 _errors = NSAPI_ERROR_NO_SOCKET; 00383 return 0; 00384 } 00385 else 00386 m_active_socket = wnc->socket; //just in case sending to a socket that wasn't last used 00387 00388 debugOutput(_debugUart,(char*)"+SOCKET %d is %s, URL=%s, IP=%s, PORT=%d\n",m_active_socket, 00389 (char*)wnc->opened?"OPEN":"CLOSED",wnc->url.c_str(),wnc->addr.get_ip_address(),wnc->addr.get_port()); 00390 debugOutput(_debugUart,(char*)"+WRITE [%s] (%d bytes) to socket #%d\n",data,size,wnc->socket); 00391 00392 _pwnc_mutex.lock(); 00393 if( _pwnc->write(m_active_socket, (const uint8_t*)data, size) ) 00394 r = size; 00395 else 00396 debugOutput(_debugUart,(char*)"+ERROR: write to socket %d failed!\n",m_active_socket); 00397 _pwnc_mutex.unlock(); 00398 00399 debugOutput(_debugUart,(char*)"+EXIT socket_send(), successful: %d\n\n",r); 00400 return r; 00401 } 00402 00403 /*------------------------------------------------------------------------- 00404 * Called to receive data. 00405 * 00406 * Input: handle to the socket we want to read from 00407 * 00408 * Output: data we receive is placed into the data buffer 00409 * size is the size of the buffer 00410 * 00411 * Returns: The number of bytes received or -1 if an error occured 00412 */ 00413 int WNC14A2AInterface::socket_recv(void *handle, void *data, unsigned size) 00414 { 00415 WNCSOCKET *wnc = (WNCSOCKET *)handle; 00416 size_t done, cnt; 00417 Timer t; 00418 00419 debugOutput(_debugUart,(char*)"+ENTER socket_recv(); read up to %d bytes\n",size); 00420 00421 memset(data,0x00,size); 00422 if (!_pwnc || m_active_socket == -1) { 00423 _errors = NSAPI_ERROR_NO_SOCKET; 00424 return -1; 00425 } 00426 else 00427 m_active_socket = wnc->socket; //just in case sending to a socket that wasn't last used 00428 00429 t.start(); 00430 do { 00431 if( !(t.read_ms() % READ_EVERYMS) ) 00432 cnt = done = _pwnc->read(m_active_socket, (uint8_t *)data, (uint32_t) size); 00433 done = (cnt || (t.read_ms() > WNC14A2A_MISC_TIMEOUT))? 1:0; 00434 } 00435 while( !done ); 00436 t.stop(); 00437 00438 if( _pwnc->getWncStatus() != WNC_GOOD ) { 00439 _errors = NSAPI_ERROR_DEVICE_ERROR; 00440 return -1; 00441 } 00442 00443 debugOutput(_debugUart,(char*)"+EXIT socket_recv(), ret=%d\n",cnt); 00444 return cnt; 00445 } 00446 00447 /*------------------------------------------------------------------------- 00448 * Close a socket 00449 * 00450 * Input: the handle to the socket to close 00451 * 00452 * Output: none 00453 * 00454 * Return: -1 on error, otherwise 0 00455 */ 00456 int WNC14A2AInterface::socket_close(void *handle) 00457 { 00458 WNCSOCKET *wnc = (WNCSOCKET*)handle; 00459 debugOutput(_debugUart,(char*)"+CALLED socket_close()\n"); 00460 00461 if (!_pwnc || m_active_socket == -1) { 00462 _errors = NSAPI_ERROR_NO_SOCKET; 00463 return -1; 00464 } 00465 else 00466 m_active_socket = wnc->socket; //just in case sending to a socket that wasn't last used 00467 00468 if( !_pwnc->closeSocket(m_active_socket) ) { 00469 _errors = NSAPI_ERROR_DEVICE_ERROR; 00470 return -1; 00471 } 00472 00473 wnc->opened = false; //no longer in use 00474 wnc->addr = NULL; //not open 00475 wnc->proto = 0; //assume TCP for now 00476 _errors = NSAPI_ERROR_OK; 00477 return 0; 00478 } 00479 00480 /*------------------------------------------------------------------------- 00481 * return the MAC for this device. Because there is no MAC Ethernet 00482 * address to return, this function returns a bogus MAC address created 00483 * from the ICCD on the SIM that is being used. 00484 * 00485 * Input: none 00486 * 00487 * Output: none 00488 * 00489 * Return: MAC string containing "NN:NN:NN:NN:NN:NN" or NULL 00490 */ 00491 const char *WNC14A2AInterface::get_mac_address() 00492 { 00493 string mac, str; 00494 debugOutput(_debugUart,(char*)"+ENTER get_mac_address()\n"); 00495 00496 if( _pwnc->getICCID(&str) ) { 00497 CHK_WNCFE((_pwnc->getWncStatus()==FATAL_FLAG), null); 00498 mac = str.substr(3,20); 00499 mac[2]=mac[5]=mac[8]=mac[11]=mac[14]=':'; 00500 strncpy(_mac_address, mac.c_str(), mac.length()); 00501 return _mac_address; 00502 } 00503 return NULL; 00504 } 00505 00506 /*------------------------------------------------------------------------- 00507 * return a pointer to the current WNC14A2AInterface 00508 */ 00509 NetworkStack *WNC14A2AInterface::get_stack() { 00510 debugOutput(_debugUart,(char*)"+CALLED get_stack()\n"); 00511 return this; 00512 } 00513 00514 /*------------------------------------------------------------------------- 00515 * Disconnnect from the 14A2A, but we can not do that 00516 * so just return saying everything is ok. 00517 */ 00518 nsapi_error_t WNC14A2AInterface::disconnect() 00519 { 00520 debugOutput(_debugUart,(char*)"+CALLED disconnect()\n"); 00521 return NSAPI_ERROR_OK; 00522 } 00523 00524 /*------------------------------------------------------------------------- 00525 * allow the user to change the APN. The API takes username and password 00526 * but they are not used. 00527 * 00528 * Input: apn string 00529 * username - not used 00530 * password - not used 00531 * 00532 * Output: none 00533 * 00534 * Return: nsapi_error_t 00535 */ 00536 nsapi_error_t WNC14A2AInterface::set_credentials(const char *apn, const char *username, const char *password) 00537 { 00538 debugOutput(_debugUart,(char*)"+ENTER set_credentials()\n"); 00539 if( !_pwnc ) 00540 return (_errors=NSAPI_ERROR_NO_CONNECTION); 00541 00542 if( !apn ) 00543 return (_errors=NSAPI_ERROR_PARAMETER); 00544 00545 if( !_pwnc->setApnName(apn) ) 00546 return (_errors=NSAPI_ERROR_DEVICE_ERROR); 00547 00548 return (_errors=NSAPI_ERROR_OK); 00549 } 00550 00551 /*------------------------------------------------------------------------- 00552 * Register a callback on state change of the socket.FROM NetworkStack 00553 * @param handle Socket handle 00554 * @param callback Function to call on state change 00555 * @param data Argument to pass to callback 00556 * @note Callback may be called in an interrupt context. 00557 */ 00558 void WNC14A2AInterface::socket_attach(void *handle, void (*callback)(void *), void *data) 00559 { 00560 debugOutput(_debugUart,(char*)"+CALLED socket_attach()\n"); 00561 } 00562 00563 /*------------------------------------------------------------------------- 00564 * check to see if we are currently regisered with the network. 00565 * 00566 * Input: none 00567 * 00568 * Output: none 00569 * 00570 * Return: ture if we are registerd, false if not or an error occured 00571 */ 00572 bool WNC14A2AInterface::registered() 00573 { 00574 debugOutput(_debugUart,(char*)"+ENTER registered()\n"); 00575 if( !_pwnc ) { 00576 _errors=NSAPI_ERROR_NO_CONNECTION; 00577 return false; 00578 } 00579 00580 if ( _pwnc->getWncStatus() == WNC_GOOD ){ 00581 _errors=NSAPI_ERROR_OK; 00582 return true; 00583 } 00584 _errors=NSAPI_ERROR_NO_CONNECTION; 00585 return false; 00586 } 00587 00588 /*------------------------------------------------------------------------- 00589 * doDebug is just a handy way to allow a developer to set different levels 00590 * of debug for the WNC14A2A device. 00591 * 00592 * Input: a Bitfield of - 00593 * basic debug = 0x01 00594 * more debug = 0x02 00595 * network debug = 0x04 00596 * all debug = 0x07 00597 * 00598 * Output: none 00599 * 00600 * Returns: void 00601 */ 00602 void WNC14A2AInterface::doDebug( int v ) 00603 { 00604 if( !_pwnc ) 00605 _errors = NSAPI_ERROR_DEVICE_ERROR; 00606 else 00607 _pwnc->enableDebug( (v&1), (v&2) ); 00608 00609 m_debug=(v&4); 00610 debugOutput(_debugUart,(char*)"+SETTING debug flag to 0x%02X\n",v); 00611 } 00612 00613 /*------------------------------------------------------------------------- 00614 * Simple function to allow for writing debug messages. It always 00615 * checks to see if debug has been enabled or not before it 00616 * outputs the message. 00617 * 00618 * Input: The debug uart pointer followed by format string and vars 00619 * 00620 * Output: none 00621 * 00622 * Return: void 00623 */ 00624 void WNC14A2AInterface::debugOutput(WNCDebug *dbgOut, char * format, ...) 00625 { 00626 if( dbgOut && m_debug ) { 00627 char buffer[256]; 00628 va_list args; 00629 va_start (args, format); 00630 vsnprintf(buffer, sizeof(buffer), format, args); 00631 dbgOut->puts(buffer); 00632 va_end (args); 00633 } 00634 } 00635 00636 00637 //////////////////////////////////////////////////////////////////// 00638 // UDP methods 00639 /////////////////////////////////////////////////////////////////// 00640 00641 //------------------------------------------------------------------------- 00642 //sends data to a UDP socket 00643 int WNC14A2AInterface::socket_sendto(void *handle, const SocketAddress &address, const void *data, unsigned size) 00644 { 00645 WNCSOCKET *wnc = (WNCSOCKET *)handle; 00646 00647 debugOutput(_debugUart,(char*)"+CALLED socket_sendto()\n"); 00648 CHK_WNCFE(( _pwnc->getWncStatus() == FATAL_FLAG ), fail); 00649 if (!wnc->opened) { 00650 int err = socket_connect(wnc, address); 00651 if (err < 0) 00652 return err; 00653 } 00654 wnc->addr = address; 00655 00656 return socket_send(wnc, data, size); 00657 } 00658 00659 //receives from a UDP socket 00660 int WNC14A2AInterface::socket_recvfrom(void *handle, SocketAddress *address, void *buffer, unsigned size) 00661 { 00662 WNCSOCKET *wnc = (WNCSOCKET *)handle; 00663 debugOutput(_debugUart,(char*)"+CALLED socket_recvfrom()\n"); 00664 int ret = socket_recv(wnc, (char *)buffer, size); 00665 if (ret >= 0 && address) 00666 *address = wnc->addr; 00667 return ret; 00668 } 00669 00670 //////////////////////////////////////////////////////////////////// 00671 // SMS methods 00672 /////////////////////////////////////////////////////////////////// 00673 00674 /*------------------------------------------------------------------------- 00675 * IOTSMS message don't use a phone number, they use the device ICCID. This 00676 * function returns the ICCID based number that is used for this device. 00677 * 00678 * Input: none 00679 * Output: none 00680 * Return: string containing the IOTSMS number to use 00681 */ 00682 char* WNC14A2AInterface::getSMSnbr( void ) 00683 { 00684 char * ret=NULL; 00685 string iccid_str; 00686 static string msisdn_str; 00687 00688 if( !_pwnc ) { 00689 _errors=NSAPI_ERROR_NO_CONNECTION; 00690 return NULL; 00691 } 00692 00693 CHK_WNCFE(( _pwnc->getWncStatus() == FATAL_FLAG ), null); 00694 00695 if( !_pwnc->getICCID(&iccid_str) ) 00696 return ret; 00697 00698 CHK_WNCFE(( _pwnc->getWncStatus() == FATAL_FLAG ), null); 00699 00700 if( _pwnc->convertICCIDtoMSISDN(iccid_str, &msisdn_str) ) 00701 ret = (char*)msisdn_str.c_str(); 00702 return ret; 00703 } 00704 00705 00706 /*------------------------------------------------------------------------- 00707 * Normally the user attaches his call-back function when performing 00708 * the listen call which enables the SMS system, but this function 00709 * allows them to update the callback if desired. 00710 * 00711 * input: pointer to the function to call 00712 * output: none 00713 * return: none 00714 */ 00715 void WNC14A2AInterface::sms_attach(void (*callback)(IOTSMS *)) 00716 { 00717 debugOutput(_debugUart,(char*)"+CALLED sms_attach() called\n"); 00718 _sms_cb = callback; 00719 } 00720 00721 /*------------------------------------------------------------------------- 00722 * Call this to start the SMS system. It is needed to reset the WNC 00723 * internal data structures related to SMS messaging 00724 */ 00725 void WNC14A2AInterface::sms_start(void) 00726 { 00727 _pwnc_mutex.lock(); //delete any message currently in storage 00728 _pwnc->deleteSMSTextFromMem('*'); //so we are notified of new incomming messages 00729 _pwnc_mutex.unlock(); 00730 } 00731 00732 /*------------------------------------------------------------------------- 00733 * Initialize the IoT SMS system. Initializing it allows the user to set a 00734 * polling period to check for SMS messages, and a SMS is recevied, then 00735 * a user provided function is called. 00736 * 00737 * Input: polling period in seconds. If not specified 30 seconds is used. 00738 * pointer to a users calllback function 00739 * Output: none 00740 * 00741 * Returns: void 00742 */ 00743 void WNC14A2AInterface::sms_listen(uint16_t pp) 00744 { 00745 debugOutput(_debugUart,(char*)"+CALLED sms_listen(%d) called\n",pp); 00746 if( !_pwnc ) { 00747 _errors=NSAPI_ERROR_NO_CONNECTION; 00748 return; 00749 } 00750 00751 CHK_WNCFE(( _pwnc->getWncStatus() == FATAL_FLAG ), fail); 00752 00753 if( m_smsmoning ) 00754 m_smsmoning = false; 00755 if( pp < 1) 00756 pp = 30; 00757 00758 00759 debugOutput(_debugUart,(char*)"+setup event queue\n"); 00760 smsThread.start(callback(&sms_queue,&EventQueue::dispatch_forever)); 00761 00762 _pwnc_mutex.lock(); //delete any message currently in storage 00763 _pwnc->deleteSMSTextFromMem('*'); //so we are notified of new incomming messages 00764 _pwnc_mutex.unlock(); 00765 sms_queue.call_every(pp*1000, mbed::Callback<void()>((WNC14A2AInterface*)this,&WNC14A2AInterface::handle_sms_event)); 00766 00767 m_smsmoning = true; 00768 debugOutput(_debugUart,(char*)"+EXIT sms_listen()\n"); 00769 } 00770 00771 /*------------------------------------------------------------------------- 00772 * process to check SMS messages that is called at the user specified period 00773 * 00774 * input: none 00775 * output:none 00776 * return:void 00777 */ 00778 void WNC14A2AInterface::handle_sms_event() 00779 { 00780 int msgs_available; 00781 debugOutput(_debugUart,(char*)"+CALLED handle_sms_event() called\n"); 00782 00783 if ( _sms_cb && m_smsmoning ) { 00784 CHK_WNCFE((_pwnc->getWncStatus()==FATAL_FLAG), fail); 00785 _pwnc_mutex.lock(); 00786 msgs_available = _pwnc->readUnreadSMSText(&m_smsmsgs, true); 00787 _pwnc_mutex.unlock(); 00788 if( msgs_available ) { 00789 debugOutput(_debugUart,(char*)"+Have %d unread texts present\n",m_smsmsgs.msgCount); 00790 for( int i=0; i< m_smsmsgs.msgCount; i++ ) { 00791 m_MsgText.number = m_smsmsgs.e[i].number; 00792 m_MsgText.date = m_smsmsgs.e[i].date; 00793 m_MsgText.time = m_smsmsgs.e[i].time; 00794 m_MsgText.msg = m_smsmsgs.e[i].msg; 00795 _sms_cb(&m_MsgText); 00796 } 00797 } 00798 } 00799 debugOutput(_debugUart,(char*)"+EXIT handle_sms_event\n"); 00800 } 00801 00802 00803 /*------------------------------------------------------------------------- 00804 * Check for any SMS messages that are present. If there are, then 00805 * fetch them and pass to the users call-back function for processing 00806 * 00807 * input: pointer to a IOTSMS message buffer array (may be more than 1 msg) 00808 * output:message buffer pointer is updated 00809 * return: the number of messages being returned 00810 */ 00811 int WNC14A2AInterface::getSMS(IOTSMS **pmsg) 00812 { 00813 int msgs_available; 00814 00815 debugOutput(_debugUart,(char*)"+CALLED getSMS()\n"); 00816 CHK_WNCFE((_pwnc->getWncStatus()==FATAL_FLAG), fail); 00817 00818 _pwnc_mutex.lock(); 00819 msgs_available = _pwnc->readUnreadSMSText(&m_smsmsgs, true); 00820 _pwnc_mutex.unlock(); 00821 00822 if( msgs_available ) { 00823 debugOutput(_debugUart,(char*)"+Have %d unread texts present\n",m_smsmsgs.msgCount); 00824 for( int i=0; i< m_smsmsgs.msgCount; i++ ) { 00825 m_MsgText_array[i].number = m_smsmsgs.e[i].number; 00826 m_MsgText_array[i].date = m_smsmsgs.e[i].date; 00827 m_MsgText_array[i].time = m_smsmsgs.e[i].time; 00828 m_MsgText_array[i].msg = m_smsmsgs.e[i].msg; 00829 pmsg[i] = (IOTSMS*)&m_MsgText_array[i]; 00830 } 00831 debugOutput(_debugUart,(char*)"+DONE getting messages\n"); 00832 msgs_available = m_smsmsgs.msgCount; 00833 } 00834 debugOutput(_debugUart,(char*)"+EXIT getSMS\n"); 00835 return msgs_available; 00836 } 00837 00838 00839 /*------------------------------------------------------------------------- 00840 * send a message to the specified user number. 00841 * 00842 * input: string containing users number 00843 * string with users message 00844 * ouput: none 00845 * 00846 * return: true if no problems occures, false if failed to send 00847 */ 00848 int WNC14A2AInterface::sendIOTSms(const string& number, const string& message) 00849 { 00850 00851 debugOutput(_debugUart,(char*)"+CALLED sendIOTSms(%s,%s)\n",number.c_str(), message.c_str()); 00852 _pwnc_mutex.lock(); 00853 int i = _pwnc->sendSMSText((char*)number.c_str(), message.c_str()); 00854 _pwnc_mutex.unlock(); 00855 00856 return i; 00857 } 00858 00859 // 00860 //------------------------------------------------------------------------- 00861 //------------------------------------------------------------------------- 00862 //------------------------------------------------------------------------- 00863 // NetworkStack API's that are not support in the WNC14A2A 00864 //------------------------------------------------------------------------- 00865 //------------------------------------------------------------------------- 00866 //------------------------------------------------------------------------- 00867 // 00868 00869 int inline WNC14A2AInterface::socket_accept(nsapi_socket_t server, nsapi_socket_t *handle, SocketAddress *address) 00870 { 00871 debugOutput(_debugUart,(char*)"+CALLED socket_accept()\n"); 00872 _errors = NSAPI_ERROR_UNSUPPORTED; 00873 return -1; 00874 } 00875 00876 int inline WNC14A2AInterface::socket_bind(void *handle, const SocketAddress &address) 00877 { 00878 debugOutput(_debugUart,(char*)"+CALLED socket_bind()\n"); 00879 _errors = NSAPI_ERROR_UNSUPPORTED; 00880 return -1; 00881 } 00882 00883 00884 int inline WNC14A2AInterface::socket_listen(void *handle, int backlog) 00885 { 00886 debugOutput(_debugUart,(char*)"+CALLED socket_listen()\n"); 00887 _errors = NSAPI_ERROR_UNSUPPORTED; 00888 return -1; 00889 } 00890
Generated on Wed Jul 13 2022 08:07:17 by
1.7.2