modified to get more signal info

Dependencies:   WncControllerK64F

Fork of WNC14A2AInterface by Avnet

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers WNC14A2AInterface.cpp Source File

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