Chuck Swiger / WNCInterface2

Dependencies:   WncControllerK64F

Fork of WNCInterface by Avnet

Files at this revision

API Documentation at this revision

Comitter:
JMF
Date:
Thu Oct 06 21:17:18 2016 +0000
Parent:
6:7cda15f762fe
Child:
8:4b38bfb1704d
Child:
20:8b3599a611b3
Commit message:
This version adds the SMS class and adds support for multi-threading to eliminate re-entrant with the WncController class

Changed in this revision

Sms/IOTSMS.cpp Show annotated file Show diff for this revision Revisions of this file
Sms/IOTSMS.h Show annotated file Show diff for this revision Revisions of this file
Sms/SMS.h Show annotated file Show diff for this revision Revisions of this file
Socket/Endpoint.cpp Show annotated file Show diff for this revision Revisions of this file
Socket/Socket.cpp Show annotated file Show diff for this revision Revisions of this file
Socket/TCPSocketConnection.cpp Show annotated file Show diff for this revision Revisions of this file
WNCInterface.cpp Show annotated file Show diff for this revision Revisions of this file
WNCInterface.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sms/IOTSMS.cpp	Thu Oct 06 21:17:18 2016 +0000
@@ -0,0 +1,175 @@
+/* =====================================================================
+   Copyright © 2016, Avnet (R)
+
+   Contributors:
+     * James M Flynn, www.em.avnet.com 
+ 
+   Licensed under the Apache License, Version 2.0 (the "License"); 
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, 
+   software distributed under the License is distributed on an 
+   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
+   either express or implied. See the License for the specific 
+   language governing permissions and limitations under the License.
+
+    @file          IOTSMS.cpp
+    @version       1.0
+    @date          Oct 2016
+
+======================================================================== */
+
+#ifndef __MODULE__
+#define __MODULE__ "WNCSms.cpp"
+#endif
+
+#include "IOTSMS.h"
+#include "mbed.h"
+#include "rtos.h"
+
+#include <cstdio>
+#include <cstring>
+
+//
+// this is a user specified function that checks for SMS messages if enabled.  It will
+// check to see if a message is available, and if there is, it will call the users
+// supplied call-back function with the message.
+//
+
+WNCSms::WNCSms(void ) : m_smsinit(false)  
+{
+    m_SMStimer = new RtosTimer(this, &WNCSms::m_smscheck, osTimerPeriodic);
+    m_SMStimer->stop();
+}
+
+void WNCSms::m_smscheck( void ){
+  
+  //we don't know what the frequency was the user selected to check for
+  //SMS messages, but we don't want to run into the problem where we are
+  //not completing our tasks wihin the timeperiod.  So stop the timer when
+  //we come in and start it when we leave.
+  //
+  if( WNCInterface::_pwnc->getWncStatus() == FATAL_FLAG )
+    FATAL_WNC_ERROR(void);
+    
+  m_SMStimer->stop();  //stop the timer while we check for SMS messages
+  M_LOCK;       
+  if( WNCInterface::_pwnc->readUnreadSMSText(&m_smsmsgs, true) ) {
+    for( int i=0; i< m_smsmsgs.msgCount; i++ ) {
+        m_MsgText.number = m_smsmsgs.e[i].number;
+        m_MsgText.date = m_smsmsgs.e[i].date;
+        m_MsgText.time = m_smsmsgs.e[i].time;
+        m_MsgText.msg = m_smsmsgs.e[i].msg;
+        m_callback.call(m_MsgText);
+        }
+    }
+  M_ULOCK;
+  m_SMStimer->start(m_timer);  //start it back up
+}
+
+//
+// initialize the IoT SMS class.  Allow a user to set a polling period to check for
+// SMS messages, and if one is recevied, call a uer defined function.  A caller can
+// not ask for a polling period with no call-back function, and they can not provide
+// a callback function with no polling period.
+//
+// Prior to initializing WNCSms, you must call and create a WNCInterface class object 
+// because the WNCSms object utilizes services of WNCInterface.
+//
+// Input:     poll - polling frequency in sec.
+//      m_callback - pointer to a user defined function
+// Output:
+//      0 if no error 
+//   != 0 if any error
+//
+int WNCSms::init(uint32_t p, void (*cb)(WNCSmsMsg& s)) {
+
+  if( WNCInterface::_pwnc->getWncStatus() == FATAL_FLAG )
+    FATAL_WNC_ERROR(fail);
+  
+  if( WNCInterface::_pwnc == NULL )  //must have already initialized WNCInterface
+    return -1;
+
+  if(( p == 0 && cb != NULL ) || (p != 0 && cb == NULL)) 
+    return -1;
+    
+  if( p != 0 && cb != NULL ) {
+    m_callback.attach(cb);
+    m_timer = p*1000;
+    m_SMStimer->start(m_timer);
+    }
+    
+  M_LOCK;
+  WNCInterface::_pwnc->deleteSMSTextFromMem('*');  //delete any message currently in storage
+  M_ULOCK;
+  m_smsinit = true;
+
+  return 0;
+}
+
+//
+// send a message to a user specified number.
+//
+int WNCSms::send(const string& number, const string& message) {
+
+  if( !m_smsinit )
+    return -1;
+  M_LOCK;
+  int ret=WNCInterface::_pwnc->sendSMSText(number.c_str(), message.c_str());
+  M_ULOCK;
+  return ret;
+  }
+
+
+//
+// get a message and put it into the callers string buffer.  When returned, this method will
+// let the caller know that there are more SMS messages to get or 0 when all messages have
+// been read.
+//
+// input:  pointer to a string for the senders number
+//         pointer to a string for the senders message
+// output: 0 if no additional messages available
+//        !0 if additional message available
+//
+
+int WNCSms::get(string& number, string& message) {
+  if( !m_smsinit )
+    return -1;
+
+  if( WNCInterface::_pwnc->getWncStatus() == FATAL_FLAG )
+    FATAL_WNC_ERROR(fail);
+  M_LOCK;
+  int ret = WNCInterface::_pwnc->readUnreadSMSText(&m_smsmsgs, true);
+  M_ULOCK;
+  return ret;
+  }
+  
+
+char * WNCSms::getSMSNbr( void ) {
+    char * ret=NULL;
+    string iccid_str;
+    static string msisdn_str;
+    
+    if( WNCInterface::_pwnc->getWncStatus() == FATAL_FLAG )
+      FATAL_WNC_ERROR(null);
+
+    M_LOCK;
+    if( !WNCInterface::_pwnc->getICCID(&iccid_str) ) {
+       M_ULOCK;
+       return NULL;
+       }
+      
+    if( WNCInterface::_pwnc->getWncStatus() == FATAL_FLAG ) {
+       M_ULOCK;
+       FATAL_WNC_ERROR(null);
+       }
+
+    if( WNCInterface::_pwnc->convertICCIDtoMSISDN(iccid_str, &msisdn_str) )
+        ret = (char*)msisdn_str.c_str();    
+    M_ULOCK;
+    return ret;
+}
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sms/IOTSMS.h	Thu Oct 06 21:17:18 2016 +0000
@@ -0,0 +1,90 @@
+/* =====================================================================
+   Copyright © 2016, Avnet (R)
+
+   Contributors:
+     * James M Flynn, www.em.avnet.com 
+ 
+   Licensed under the Apache License, Version 2.0 (the "License"); 
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, 
+   software distributed under the License is distributed on an 
+   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
+   either express or implied. See the License for the specific 
+   language governing permissions and limitations under the License.
+
+    @file          IOTSMS.h
+    @version       1.0
+    @date          Oct 2016
+
+======================================================================== */
+
+#ifndef WNCSms_H_
+#define WNCSms_H_
+
+#include "mbed.h"
+#include "rtos.h"
+
+#include "WNCInterface.h"
+#include "RtosTimer.h"
+#include "Callback.h"
+
+typedef struct SmsMsg {
+        string number;
+        string date;
+        string time;
+        string msg;
+    } WNCSmsMsg;
+
+/** Component to use the Short Messages Service (SMS) **/
+class WNCSms 
+{
+private:
+  unsigned int m_smsinit;
+  void m_smscheck(void);
+  uint32_t m_timer;
+
+protected:
+  WNCSmsMsg m_MsgText;
+  RtosTimer *m_SMStimer;
+  struct WncController_fk::WncController::WncSmsList m_smsmsgs;     //use the WncSmsList structure to hold messages
+  mbed::Callback<void (WNCSmsMsg&)> m_callback;    //pointer to the call-back function the user specified
+  
+public:
+  WNCSms();             /** Create SMSInterface instance */
+
+  /** Initialize interface **/
+  int init(uint32_t poll=0, void ((*cb)(WNCSmsMsg& s))=NULL);
+
+  /** Send a SM
+     @param string& receiver's contact number
+     @param string& the message to send
+     @return 0 on success, error code on failure
+   */
+  int send(const string& number, const string& message);
+
+
+  /** Receive a SM
+     @param string Pointer to the sender's phone number 
+     @param string Pointer to store the the incoming message into
+     @return 0 on success, error code on failure
+   */
+  int get(string& number, string& message);
+  
+  /** Get the users number to use for SMS messaging
+     @param none 
+     @return character pointer on success, NULL on failure
+   */
+  char * getSMSNbr( void );
+  
+  /** Attached a callback function for a Receive SMS
+     @param fp(string&) a function that takes a string as an input argument
+   */
+  void attach(void (*fp)(WNCSmsMsg& s)) {m_callback.attach(fp);}
+ 
+};
+
+#endif /* WNCSms_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sms/SMS.h	Thu Oct 06 21:17:18 2016 +0000
@@ -0,0 +1,53 @@
+/* =====================================================================
+   Copyright © 2016, Avnet (R)
+
+   Contributors:
+     * James M Flynn, www.em.avnet.com 
+ 
+   Licensed under the Apache License, Version 2.0 (the "License"); 
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, 
+   software distributed under the License is distributed on an 
+   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
+   either express or implied. See the License for the specific 
+   language governing permissions and limitations under the License.
+
+    @file          SMS.h
+    @version       1.0
+    @date          Oct 2016
+
+======================================================================== */
+
+#ifndef SMS_H_
+#define SMS_H_
+
+/** Virtual calss for IoT Short Messages Service (SMS) **/
+
+class SMSInterface {
+public:
+  /** Initialize interface
+   */
+  virtual int init() = 0;
+
+
+  /** Send a SM
+     @param number The receiver's contact number
+     @param message The message to send
+     @return 0 on success, error code on failure
+   */
+  virtual int send(const string& number, const string& message) = 0;
+
+
+  /** Receive a SM
+     @param msg_orig string containing the sender's phone number
+     @param Pointer to a string that contains the incoming message
+     @return 0 on success, error code on failure
+   */
+  virtual int get(string& number, string& message) = 0;
+};
+
+#endif /* SMS_H_ */
--- a/Socket/Endpoint.cpp	Wed Sep 28 00:17:57 2016 +0000
+++ b/Socket/Endpoint.cpp	Thu Oct 06 21:17:18 2016 +0000
@@ -58,14 +58,15 @@
             (unsigned int*)&address[0], (unsigned int*)&address[1],
             (unsigned int*)&address[2], (unsigned int*)&address[3]);
 
+    M_LOCK;
     if (rslt != 4)    // No, need to resolve address with DNS
         WNCInterface::_pwnc->resolveUrl(0,host);
     else
         WNCInterface::_pwnc->setIpAddr(0,host);
     
     rslt = WNCInterface::_pwnc->getIpAddr(0,_epAddr.IP);
-    
-   return rslt;
+    M_ULOCK;
+    return rslt;
 }
 
 char* Endpoint::get_address() {
--- a/Socket/Socket.cpp	Wed Sep 28 00:17:57 2016 +0000
+++ b/Socket/Socket.cpp	Thu Oct 06 21:17:18 2016 +0000
@@ -48,7 +48,10 @@
 int Socket::init(int timeout) {
 
     _timeout = timeout;
-    return (WNCInterface::_pwnc->getWncNetworkingStats(&WNCInterface::myNetStats))? 0:-1;
+    M_LOCK;
+    int ret = WNCInterface::_pwnc->getWncNetworkingStats(&WNCInterface::myNetStats)? 0:-1;
+    M_ULOCK;
+    return ret;
 }
 
 //
@@ -67,7 +70,7 @@
   rslt = std::sscanf(url, "%3u.%3u.%3u.%3u",
             (unsigned int*)&address[0], (unsigned int*)&address[1],
             (unsigned int*)&address[2], (unsigned int*)&address[3]);
-    
+  M_LOCK;  
   if (rslt == 4) 
     rslt = WNCInterface::_pwnc->setIpAddr(0,url);
   else 
@@ -77,6 +80,7 @@
     _sock_type = type;             //resolved the URL indicate socket 0 is open
     rslt = WNCInterface::_pwnc->openSocket(0, port, (_sock_type==SOCK_STREAM)? 1:0, _timeout);
     } 
+  M_ULOCK;
   return rslt;
 } 
 
@@ -92,8 +96,10 @@
 
   if( WNCInterface::_pwnc->getWncStatus() == FATAL_FLAG )
       FATAL_WNC_ERROR(fail);
- 
-  return !WNCInterface::_pwnc->closeSocket(0);
+  M_LOCK;
+  int ret = !WNCInterface::_pwnc->closeSocket(0);
+  M_ULOCK;
+  return ret;
 }
 
 void Socket::set_blocking(bool blocking, unsigned int timeout) {
@@ -102,9 +108,10 @@
 
     if( WNCInterface::_pwnc->getWncStatus() == FATAL_FLAG )
         FATAL_WNC_ERROR(void);
- 
+    M_LOCK;
     WNCInterface::_pwnc->setReadRetryWait(0, 0);
     WNCInterface::_pwnc->setReadRetries(0, 0);
+    M_ULOCK;
 }
 
 
--- a/Socket/TCPSocketConnection.cpp	Wed Sep 28 00:17:57 2016 +0000
+++ b/Socket/TCPSocketConnection.cpp	Thu Oct 06 21:17:18 2016 +0000
@@ -38,9 +38,10 @@
 
     if( WNCInterface::_pwnc->getWncStatus() == FATAL_FLAG )
         FATAL_WNC_ERROR(void);
- 
+    M_LOCK;
     WNCInterface::_pwnc->setReadRetryWait(0, 0);
     WNCInterface::_pwnc->setReadRetries(0, 0);
+    M_ULOCK;
 }
 
 
@@ -55,18 +56,20 @@
 }
 
 int TCPSocketConnection::send(char* data, int length) {
+    int ret = -1;
+    
     WncController_fk::WncController::WncState_e s = WNCInterface::_pwnc->getWncStatus();
 
     if( s == FATAL_FLAG )
         FATAL_WNC_ERROR(fail);
  
-    if( s != WncController_fk::WncController::WNC_ON )
-        return -1;
-
-    if( WNCInterface::_pwnc->write(0, data, length) )
-        return length;
-    else
-        return -1;
+    if( s == WncController_fk::WncController::WNC_ON ) {
+      M_LOCK;
+      if( WNCInterface::_pwnc->write(0, data, length) )
+        ret = length;
+      M_ULOCK;
+      }
+    return ret;
 }
 
 int TCPSocketConnection::receive(char *readBuf, int length) {
@@ -83,6 +86,7 @@
         return ret;
 
     t.start();
+    M_LOCK;
     do {
         cnt = WNCInterface::_pwnc->read(0, (uint8_t *)readBuf, (uint32_t) length);
         if( _is_blocking )
@@ -92,7 +96,8 @@
         }
     while( !done );
     t.stop();
-
+    M_ULOCK;
+    
     if( WNCInterface::_pwnc->getWncStatus() == WNC_GOOD ) {
         readBuf[cnt] = '\0';
         ret = (int)cnt;
@@ -113,6 +118,9 @@
 
 int TCPSocketConnection::close(void) {
   Socket::disconnect();
-  return ( WNCInterface::_pwnc->getWncStatus() == WncController_fk::WncController::WNC_ON )? 0:-1;
+  M_LOCK;
+  int ret = ( WNCInterface::_pwnc->getWncStatus() == WncController_fk::WncController::WNC_ON )? 0:-1;
+  M_ULOCK;
+  return ret;
 }
 
--- a/WNCInterface.cpp	Wed Sep 28 00:17:57 2016 +0000
+++ b/WNCInterface.cpp	Thu Oct 06 21:17:18 2016 +0000
@@ -41,6 +41,7 @@
 DigitalOut  mdm_uart1_cts(PTD0);
 
 char * _fatal_err_loc;                          //GLOBAL::holds any error location info
+MODSERIAL * _dbgout;
 
 using namespace WncControllerK64F_fk;       // namespace for the controller class use
 
@@ -60,15 +61,21 @@
 WncControllerK64F *WNCInterface::_pwnc;
 WncIpStats WNCInterface::myNetStats;
 string WNCInterface::mac;
-  
+Mutex *WNCInterface::WNCLock;
+    
 WNCInterface::WNCInterface() {
+    _dbgout = NULL;
+    WNCLock = new Mutex();
+    WNCLock->unlock();
 }
 
 void WNCInterface::doDebug( int v ) {
     //basic debug = 0x01
     //more debug  = 0x02
     //all debug   = 0x03
+    WNCLock->lock();
     _pwnc->enableDebug( (v&1), (v&2) );
+    WNCLock->unlock();
 }
     
 //
@@ -84,8 +91,10 @@
 //
 int WNCInterface::init(const char* apn, MODSERIAL * debug) {
     int ret = 0;
-
+    
+    WNCLock->lock();
     if( debug ) {
+        _dbgout = debug;
         _pwnc = new WncControllerK64F_fk::WncControllerK64F::WncControllerK64F(&wncPinList, &mdmUart, debug);
 #if WNC_DEBUG == 1
     _pwnc->enableDebug(1,1);
@@ -100,7 +109,8 @@
     ret =  ( _pwnc->powerWncOn(apn,40) )? 2:0;
     ret |= ( _pwnc->setApnName(apn) )? 1:0;
     ret |= ( _pwnc->getWncNetworkingStats(&myNetStats) )? 4:0;
-
+    WNCLock->unlock();
+    
     return ret;
 }
 
@@ -125,11 +135,14 @@
 // update the networking stats and return the IP Address
 //
 char * WNCInterface::getIPAddress() {
+    WNCLock->lock();
     if ( _pwnc->getWncNetworkingStats(&myNetStats) ) {
         if( WNCInterface::_pwnc->getWncStatus() == FATAL_FLAG )
             FATAL_WNC_ERROR(null);
+        WNCLock->unlock();
         return &myNetStats.ip[0];
     }
+    WNCLock->unlock();
     return NULL;
 }
 
@@ -137,11 +150,14 @@
 // update the networking stats and return the Gateway Address
 //
 char * WNCInterface::getGateway() {
+    WNCLock->lock();
     if ( _pwnc->getWncNetworkingStats(&myNetStats) ) {
         if( WNCInterface::_pwnc->getWncStatus() == FATAL_FLAG )
             FATAL_WNC_ERROR(null);
+        WNCLock->unlock();
         return &WNCInterface::myNetStats.gateway[0];
     }
+    WNCLock->unlock();
     return NULL;
 }
 
@@ -149,11 +165,14 @@
 // update the networking stats and return the Network Mask
 //
 char * WNCInterface::getNetworkMask() {
+    WNCLock->lock();
     if ( _pwnc->getWncNetworkingStats(&myNetStats) ) {
         if( WNCInterface::_pwnc->getWncStatus() == FATAL_FLAG )
             FATAL_WNC_ERROR(null);
+        WNCLock->unlock();    
         return &WNCInterface::myNetStats.mask[0];
     }
+    WNCLock->unlock();    
     return NULL;
 }
 
@@ -162,14 +181,17 @@
 //
 char* WNCInterface::getMACAddress( void ) {
     string str;
-  
+    
+    WNCLock->lock();
     if( _pwnc->getICCID(&str) ) {
         if( WNCInterface::_pwnc->getWncStatus() == FATAL_FLAG )
             FATAL_WNC_ERROR(null);
         mac = str.substr(3,20);
         mac[2]=mac[5]=mac[8]=mac[11]=mac[14]=':';
-    return (char*)mac.c_str();
+        WNCLock->unlock();
+        return (char*)mac.c_str();
     }
+    WNCLock->unlock();
     return NULL;
 }
 
--- a/WNCInterface.h	Wed Sep 28 00:17:57 2016 +0000
+++ b/WNCInterface.h	Thu Oct 06 21:17:18 2016 +0000
@@ -25,6 +25,8 @@
 
 #include <stddef.h>
 #include "WncControllerK64F/WncControllerK64F.h"
+#include "WncControllerK64F/WncController/WncController.h"
+#include <Mutex.h>
 
 #ifndef _WNCINTERFACE_H_
 #define _WNCINTERFACE_H_
@@ -56,6 +58,7 @@
 #define INTSTR(x) TOSTR(x)
 #define FATAL_STR __FILE__ ":" INTSTR(__LINE__)
 
+
 #if RESETON_FE == 1
 #define MCURESET     ((*((volatile unsigned long *)0xE000ED0CU))=(unsigned long)((0x5fa<<16) | 0x04L))
 #define RSTMSG       "RESET MCU! "
@@ -65,7 +68,7 @@
 #endif
 
 #if DISPLAY_FE == 1
-#define PFE     printf(RSTMSG "WNC FAILED @ %s\r\n", FATAL_STR)
+#define PFE     {extern MODSERIAL *_dbgout;if(_dbgout)_dbgout->printf(RSTMSG "WNC FAILED @ %s\r\n", FATAL_STR);}
 #else
 #define PFE
 #endif
@@ -76,6 +79,9 @@
 #define FATAL_WNC_ERROR(v)  {extern char *_fatal_err_loc;_fatal_err_loc=FATAL_STR;PFE;DORET(v);}
 #endif
 
+#define M_LOCK  WNCInterface::WNCLock->lock()
+#define M_ULOCK WNCInterface::WNCLock->unlock()
+
 // Because the WncController has intermixed socket & interface functionallity
 // will need to make the Socket class a friend of the Interface class. This 
 // will allow the Socket class to get to the WNC functions needed for the
@@ -85,6 +91,7 @@
 class Endpoint;
 class UDPSocket;
 class TCPSocketConnection;
+class WNCSms;
 
 class WNCInterface
 {
@@ -93,6 +100,7 @@
   friend class UDPSocket;
   friend class Endpoint;
   friend class Socket;
+  friend class WNCSms;
 
 public:
   /** Create WNC Data Module Interface Instance for the device (M14A2A) */
@@ -139,11 +147,14 @@
    * \return nothing.
    */
   void doDebug(int val);  //doing this so I can get to the wnc controller pointer
-
+  
+  
 private:
   static WncController_fk::WncIpStats myNetStats;     //maintaint the network statistics
   static WncControllerK64F_fk::WncControllerK64F *_pwnc;  //pointer to the WncController instance
+  static Mutex *WNCLock;
   static string mac;
+
 };
 
 #endif /* _WNCINTERFACE_ */