modified to get more signal info
Dependencies: WncControllerK64F
Fork of WNC14A2AInterface by
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 Tue Jul 12 2022 23:00:47 by 1.7.2