Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: WncControllerK64F
Fork of WNCInterface by
Revision 7:fded23f50479, committed 2016-10-06
- 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
--- /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_ */
