Demo application for using the AT&T IoT Starter Kit Powered by AWS.

Dependencies:   SDFileSystem

Fork of ATT_AWS_IoT_demo by Anthony Phillips

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers WncController.h Source File

WncController.h

Go to the documentation of this file.
00001 /*
00002     Copyright (c) 2016 Fred Kellerman
00003  
00004     Permission is hereby granted, free of charge, to any person obtaining a copy
00005     of this software and associated documentation files (the "Software"), to deal
00006     in the Software without restriction, including without limitation the rights
00007     to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008     copies of the Software, and to permit persons to whom the Software is
00009     furnished to do so, subject to the following conditions:
00010  
00011     The above copyright notice and this permission notice shall be included in
00012     all copies or substantial portions of the Software.
00013  
00014     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017     AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020     THE SOFTWARE.
00021     
00022     @file          WncController.h
00023     @purpose       Controls WNC Cellular Modem
00024     @version       1.0
00025     @date          July 2016
00026     @author        Fred Kellerman
00027     
00028     Notes: This code originates from the following mbed repository:
00029     
00030     https://developer.mbed.org/teams/Avnet/code/WncControllerLibrary/
00031 */
00032 
00033 
00034 #ifndef __WNCCONTROLLER_H_
00035 #define __WNCCONTROLLER_H_
00036 
00037 #include <string>
00038 #include <stdint.h>
00039 
00040 namespace WncController_fk {
00041     
00042 using namespace std;
00043 
00044 /**
00045  *  \file WncController.h
00046  *  \brief This mbed C++ class is for controlling the WNC
00047  *  Cellular modem via the AT command interface.  This was
00048  *  developed with respect to version 1.3 of the WNC authored
00049  *  spec.  This class is only designed to have 1 instantiation
00050  *  it is also not multi-thread safe.
00051  */
00052 
00053 
00054 static const uint8_t  MAX_LEN_IP_STR = 16;         // Length includes room for the extra NULL
00055 
00056 /**
00057  *  \brief  Contains info fields for the WNC Internet Attributes
00058  */
00059 struct WncIpStats
00060 {
00061     string wncMAC;
00062     char ip[MAX_LEN_IP_STR];
00063     char mask[MAX_LEN_IP_STR];
00064     char gateway[MAX_LEN_IP_STR];
00065     char dnsPrimary[MAX_LEN_IP_STR];
00066     char dnsSecondary[MAX_LEN_IP_STR];
00067 };
00068 
00069 class WncController
00070 {
00071 public:
00072     static const unsigned MAX_NUM_WNC_SOCKETS = 5;  // Max number of simultaneous sockets that the WNC supports
00073     static const unsigned MAX_POWERUP_TIMEOUT = 60; // How long the powerUp method will try to turn on the WNC Shield
00074                                                     //  (this is the default if the user does not over-ride on power-up
00075 
00076     // Tracks mode of the WNC Shield hardware
00077     enum WncState_e {
00078         WNC_OFF = 0,
00079         WNC_ON, // This is intended to mean all systems go, including cell link up but socket may not be open
00080         WNC_ON_NO_CELL_LINK,
00081         WNC_NO_RESPONSE
00082     };
00083 
00084     /**
00085      *  \brief Constructor for UART controlled WNC
00086      *
00087      *  \param [in] wnc_uart - Reference to a SerialBuffered object which will
00088      *  be used as the bus to control the WNC.  apnStr = a text string for
00089      *  the cellular APN name.
00090      *
00091      *  \return None.
00092      *
00093      *  \details Adding another way to talk to the WNC, like I2C or USB,
00094      *  a constructor should be added for each type just like the SerialBuffered
00095      *  constructor below.  Assumes UART is enabled, setup and ready to go. This
00096      *  class will read and write to this UART.
00097      */
00098     WncController(void);
00099     
00100     // WncController( const char * const apnStr, MODSERIAL * wnc_uart, MODSERIAL * debug_uart = NULL);
00101     
00102     /**
00103      *  \brief Used internally but also make public for a user of the Class to interrogate state as well.
00104      *
00105      *  \param [in] None.
00106      *
00107      *  \return The state of the WNC Modem.
00108      *
00109      *  \details None.
00110      */
00111     WncState_e getWncStatus(void);
00112     
00113     bool setApnName(const char * const apnStr);
00114 
00115     /**
00116      *  \brief Return signal quality dBm level
00117      *
00118      *  \param [in] None.
00119      *
00120      *  \return The dBm signal level at the time of the request.
00121      *
00122      *  \details This polls (at the time of the call) the cell signal.
00123      */
00124     int16_t getDbmRssi(void);
00125     int16_t get3gBer(void);
00126 
00127     /**
00128      *  \brief  Power up and down (down not implemented yet)
00129      *
00130      *  \param [in] NXP Pins that are critical for the initialization of the WNC Shield.
00131      *
00132      *  \return true if request successful else false.
00133      *
00134      *  \details Power-on works but not power-down.  This will manipulate WNC Shield hardware
00135      *  and bring it to life.  It will also initialize the WNC enough to get it to be able to open sockets
00136      *  (with AT commands)
00137      */
00138     bool powerWncOn(const char * const apn, uint8_t powerUpTimeoutSecs = MAX_POWERUP_TIMEOUT);
00139 
00140     /**
00141      *  \brief  Query the WNC modem for its Internet attributes
00142      *
00143      *  \param [in] Pointer to a struct where to put the info.
00144      *
00145      *  \return true if request successful else false.
00146      *
00147      *  \details This method will do a few sanity checks and then gather the
00148      *  fields of the struct.
00149      */
00150     bool getWncNetworkingStats(WncIpStats * s);
00151 
00152     /**
00153      *  \brief Look-up a URL text string and convert into an IP Address string.
00154      *
00155      *  \param [in] url - the URL to lookup.  numSock - the socket reference.
00156      *
00157      *  \return true - if the IP address has been resolved. false - if the URL could not be resolved.
00158      *
00159      *  \details None.
00160      */
00161     bool resolveUrl(uint16_t numSock, const char * url);
00162 
00163     /**
00164      *  \brief Set IP Address string
00165      *
00166      *  \param [in] numSock - socket reference to set the string for. ipStr - text string of the IP
00167      *  address you want to talk to.  There is no sanity check - beware!!!
00168      *
00169      *  \return true - if the IP address has been set. false - if the IP could not be set.
00170      *
00171      *  \details None.
00172      */
00173     bool setIpAddr(uint16_t numSock, const char * ipStr);
00174 
00175     /**
00176      *  \brief Opens a WNC socket.
00177      *
00178      *  \param [in] sockNum - the number of the socket to open.  ipAddr - a string containing
00179      *  the IP address.  port - the IP port number to open the socket connection.
00180      *
00181      *  \return true - if the socket is/was opened.  false otherwise.
00182      *
00183      *  \details None.
00184      */
00185     bool openSocket(uint16_t numSock, uint16_t port, bool tcp, uint16_t timeOutSec = 30);
00186     
00187     bool openSocketUrl(uint16_t numSock, const char * url, uint16_t port, bool tcp, uint16_t timeOutSec = 30);
00188 
00189     bool openSocketIpAddr(uint16_t numSock, const char * ipAddr, uint16_t port, bool tcp, uint16_t timeOutSec = 30);
00190 
00191 
00192     /**
00193      *  \brief Write bytes of data to an open socket
00194      *
00195      *  \param [in] sockNum - the number of the socket to write.  s - a string containing
00196      *  the byte data to send.
00197      *
00198      *  \return true - if the write was successful.  false otherwise.
00199      *
00200      *  \details The results of the write do not have anything to do with the data
00201      *  arriving at the endpoint.
00202      */
00203      bool write(uint16_t numSock, const char * s, uint32_t n);
00204 
00205     /**
00206      *  \brief Poll and read back data from the WNC (if it has any)
00207      *  If auto poll is enabled this read might fail (return with no data).
00208      *
00209      *  \param [in] sockNum - the number of the socket to read.  result - a string pointer containing
00210      *  the byte data readback from the WNC.
00211      *
00212      *  \return The number of bytes/chars that are read from the socket.
00213      *
00214      *  \details DO NOT use the same string as is passed to the auto poll setup method!
00215      */
00216     size_t read(uint16_t numSock, uint8_t * readBuf, uint32_t maxReadBufLen);
00217     
00218     size_t read(uint16_t numSock, const uint8_t ** readBuf);
00219 
00220     /**
00221      *  \brief Set how many times the above read method will retry if data is not returned.
00222      *
00223      *  \param [in] sockNum - the number of the socket to set.  retries - how many times to
00224      *  poll until data is found.
00225      *
00226      *  \return None.
00227      *
00228      *  \details None.
00229      */
00230     void setReadRetries(uint16_t numSock, uint16_t retries);
00231 
00232     /**
00233      *  \brief Set how long between retries to wait.
00234      *
00235      *  \param [in] sockNum - the number of the socket to set.  waitMs - how long to wait
00236      *  before doing the read poll (calling read(...)).
00237      *
00238      *  \return None.
00239      *
00240      *  \details None.
00241      */
00242     void setReadRetryWait(uint16_t numSock, uint16_t waitMs);
00243 
00244     /**
00245      *  \brief Close the socket.
00246      *
00247      *  \param [in] sockNum - the number of the socket to close.
00248      *
00249      *  \return None.
00250      *
00251      *  \details None.
00252      */
00253     bool closeSocket(uint16_t numSock);
00254 
00255     void setWncCmdTimeout(uint16_t toMs);
00256         
00257     bool getIpAddr(uint16_t numSock, char myIpAddr[MAX_LEN_IP_STR]);
00258     
00259     void enableDebug(bool on, bool moreDebugOn);
00260     
00261     ///////////////////////////////////////////
00262     //  SMS messaging
00263     ///////////////////////////////////////////
00264 
00265     static const uint16_t MAX_WNC_SMS_MSG_SLOTS = 3;   // How many SMS messages the WNC can store and receive at a time.
00266     static const uint16_t MAX_WNC_SMS_LENGTH    = 160; // The maximum length of a 7-bit SMS message the WNC can send and receive.
00267     
00268     struct WncSmsInfo
00269     {
00270         // Content
00271         char   idx;
00272         string number;
00273         string date;
00274         string time;
00275         string msg;
00276         
00277         // Attributes
00278         bool incoming;
00279         bool unsent;
00280         bool unread;
00281         bool pduMode;
00282         bool msgReceipt;
00283     };
00284 
00285     struct WncSmsList
00286     {
00287         uint8_t msgCount;
00288         WncSmsInfo e[MAX_WNC_SMS_MSG_SLOTS];
00289     };
00290 
00291     bool sendSMSText(const char * const phoneNum, const char * const text);
00292 
00293     bool readSMSLog(struct WncSmsList * log);
00294 
00295     bool readUnreadSMSText(struct WncSmsList * w, bool deleteRead = true);
00296     
00297     bool saveSMSText(const char * const phoneNum, const char * const text, char * msgIdx);
00298     
00299     bool sendSMSTextFromMem(char msgIdx);
00300 
00301     bool deleteSMSTextFromMem(char msgIdx);
00302     
00303     bool getICCID(string * iccid);
00304 
00305     bool convertICCIDtoMSISDN(const string & iccid, string * msisdn);
00306     
00307     ///////////////////////////////////////////
00308     // Neighborhood Cell Info
00309     ///////////////////////////////////////////
00310     size_t getSignalQuality(const char ** log);
00311     
00312     //  Date Time
00313     struct WncDateTime
00314     {
00315         uint8_t  year;
00316         uint8_t  month;
00317         uint8_t  day;
00318         uint8_t  hour;
00319         uint8_t  min;
00320         uint8_t  sec;
00321     };
00322 
00323     bool getTimeDate(struct WncDateTime * tod);
00324     
00325     // Ping
00326     bool pingUrl(const char * url);
00327     bool pingIp(const char * ip);
00328     
00329     // User command:
00330     size_t sendCustomCmd(const char * cmd, char * resp, size_t sizeRespBuf, int ms_timeout);
00331 
00332 protected:
00333 
00334     // Debug output methods
00335     int dbgPutsNoTime(const char * s, bool crlf = true);
00336     int dbgPuts(const char * s, bool crlf = true);
00337     const char * _to_string(int64_t value);
00338     const char * _to_hex_string(uint8_t value);    
00339 
00340     // Sends commands to WNC via
00341     enum AtCmdErr_e {
00342         WNC_AT_CMD_OK,
00343         WNC_AT_CMD_ERR,
00344         WNC_AT_CMD_ERREXT,
00345         WNC_AT_CMD_ERRCME,
00346         WNC_AT_CMD_INVALID_RESPONSE,
00347         WNC_AT_CMD_TIMEOUT,
00348         WNC_AT_CMD_NO_CELL_LINK,
00349         WNC_AT_CMD_WNC_NOT_ON
00350     };
00351 
00352     // Users must define these functionalities:
00353     virtual int putc(char c)              = 0;
00354     virtual int puts(const char * s)      = 0;
00355     virtual char getc(void)               = 0;
00356     virtual int charReady(void)           = 0;
00357     virtual int dbgWriteChar(char b)      = 0;
00358     virtual int dbgWriteChars(const char *b) = 0;
00359     virtual void waitMs(int t)            = 0;
00360     virtual void waitUs(int t)            = 0;
00361     virtual bool initWncModem(uint8_t powerUpTimeoutSecs) = 0;
00362     
00363     // Isolate OS timers
00364     virtual int  getLogTimerTicks(void)  = 0;
00365     virtual void startTimerA(void)       = 0;
00366     virtual void stopTimerA(void)        = 0;
00367     virtual int  getTimerTicksA_mS(void) = 0;
00368     virtual void startTimerB(void)       = 0;
00369     virtual void stopTimerB(void)        = 0;
00370     virtual int  getTimerTicksB_mS(void) = 0;
00371         
00372     bool waitForPowerOnModemToRespond(uint8_t powerUpTimeoutSecs);    
00373     AtCmdErr_e sendWncCmd(const char * const s, string ** r, int ms_timeout);
00374     
00375 private:
00376 
00377     bool softwareInitMdm(void);
00378     bool checkCellLink(void);
00379     AtCmdErr_e mdmSendAtCmdRsp(const char * cmd, int timeout_ms, string * rsp, bool crLf = true);
00380     size_t mdmGetline(string * buff, int timeout_ms);
00381     bool at_at_wnc(void);
00382     bool at_init_wnc(bool hardReset = false);
00383     int16_t at_sockopen_wnc(const char * const ip, uint16_t port, uint16_t numSock, bool tcp, uint16_t timeOutSec);
00384     bool at_sockclose_wnc(uint16_t numSock);
00385     bool at_dnsresolve_wnc(const char * s, string * ipStr);
00386     AtCmdErr_e at_sockwrite_wnc(const char * s, uint16_t n, uint16_t numSock, bool isTcp);
00387     AtCmdErr_e at_sockread_wnc(uint8_t * pS, uint16_t * numRead, uint16_t n, uint16_t numSock, bool isTcp);
00388     AtCmdErr_e at_sockread_wnc(string * pS, uint16_t numSock, bool isTcp);
00389     bool at_reinitialize_mdm(void);
00390     AtCmdErr_e at_send_wnc_cmd(const char * s, string ** r, int ms_timeout);
00391     bool at_setapn_wnc(const char * const apnStr);
00392     bool at_sendSMStext_wnc(const char * const phoneNum, const char * const text);
00393     bool at_get_wnc_net_stats(WncIpStats * s);
00394     bool at_readSMSlog_wnc(string ** log);
00395     size_t at_readSMStext_wnc(const char ** log);
00396     size_t at_readSMStext_wnc(const char n, const char ** log);
00397     bool at_getrssiber_wnc(int16_t * dBm, int16_t * ber3g);
00398     void closeOpenSocket(uint16_t numSock);
00399     bool sockWrite(const char * const s, uint16_t n, uint16_t numSock, bool isTcp);
00400     bool at_sendSMStextMem_wnc(char n);
00401     bool at_deleteSMSTextFromMem_wnc(char n);
00402     bool at_saveSMStext_wnc(const char * const phoneNum, const char * const text, char * msgIdx);
00403     size_t at_getSignalQuality_wnc(const char ** log);
00404     bool at_gettimedate_wnc(struct WncDateTime * tod);
00405     bool at_ping_wnc(const char * ip);
00406     bool at_geticcid_wnc(string * iccid);
00407     
00408     // Utility methods
00409     void sendCmd(const char * cmd, bool crLf);
00410     void sendCmd(const char * cmd, unsigned n, unsigned wait_uS, bool crLf);    
00411     inline void rx_char_wait(void) {
00412         // waitUs(1000);
00413     }
00414     
00415     // Important constants
00416     static const uint16_t MAX_WNC_READ_BYTES        = 1500;                            // This bounds the largest amount of data that the WNC read from a socket will return
00417     static const uint16_t MAX_WNC_WRITE_BYTES       = MAX_WNC_READ_BYTES;              // This is the largest amount of data that the WNC can write per sockwrite.
00418     static const uint16_t MAX_LEN_WNC_CMD_RESPONSE  = (MAX_WNC_READ_BYTES * 2 + 100);  // Max number of text characters in a WNC AT response *2 because bytes are converted into 2 hex-digits +100 for other AT@ chars.
00419     static const uint16_t WNC_AUTO_POLL_MS          = 250;   // Sets default (may be overriden with method) poll interval (currently not used, future possible feature.
00420     static const uint16_t WNC_CMD_TIMEOUT_MS        = 40000; // Sets default (may be overriden) time that the software waits for an AT response from the WNC.
00421     static const uint16_t WNC_QUICK_CMD_TIMEOUT_MS  = 2000;  // Used for simple commands that should immediately respond such as "AT", cmds that are quicker than WNC_CMD_TIMEOUT_MS.
00422     static const uint16_t WNC_WAIT_FOR_AT_CMD_MS    = 0;     // Wait this much between multiple in a row AT commands to the WNC.
00423     static const uint16_t WNC_SOFT_INIT_RETRY_COUNT = 10;    // How many times the WNC will be tried to revive if it stops responding.
00424     static const uint16_t WNC_DNS_RESOLVE_WAIT_MS   = 60000; // How much time to wait for the WNC to respond to a DNS resolve/lookup.
00425     static const uint16_t WNC_TRUNC_DEBUG_LENGTH    = 80;    // Always make this an even number, how many chars for the debug output before shortening the debug ouput, this is used when moreDebug = false. 
00426     static const uint16_t WNC_APNSET_TIMEOUT_MS     = 60000; // How long to wait for the WNC to respond to setting the APN string.
00427     static const uint16_t WNC_PING_CMD_TIMEOUT_MS   = 60000; // Amount of time to wait for the WNC to respond to AT@PINGREQ (with cmd default params for timeout, does not change WNC cmd's timeout) 
00428     static const int      WNC_REINIT_MAX_TIME_MS    = 60000; // How long to wait for the WNC to reset after it was already up and running after power-up.
00429     static const uint16_t WNC_SOCK_CLOSE_RETRY_CNT  = 3;     // How many times to try to close the socket if the WNC gives an error.
00430     static const char * const INVALID_IP_STR;                // Just a string set to an IP address when DNS resolve fails.
00431         
00432     struct WncSocketInfo_s {
00433         int16_t numWncSock;
00434         bool open;
00435         string myIpAddressStr;
00436         uint16_t myPort;
00437         uint8_t readRetries;
00438         uint16_t readRetryWaitMs;
00439         bool isTcp;
00440         uint16_t timeOutSec;
00441     };
00442 
00443     static WncSocketInfo_s m_sSock[MAX_NUM_WNC_SOCKETS];
00444     static const WncSocketInfo_s defaultSockStruct;
00445     static WncState_e m_sState;
00446     static uint16_t m_sCmdTimeoutMs;
00447     static string m_sApnStr;
00448     static string m_sWncStr;
00449     static uint8_t m_sPowerUpTimeoutSecs;
00450     static bool m_sDebugEnabled;
00451     static bool m_sMoreDebugEnabled;
00452     static bool m_sCheckNetStatus;
00453     static bool m_sReadyForSMS;
00454 };
00455 
00456 };  // End namespace WncController_fk
00457 
00458 #endif