This library controls the WNC. There is a derived class for usage from the K64F board.
Fork of WncControllerLibrary by
Diff: WncController.h
- Revision:
- 0:affdbb35faa4
- Child:
- 1:ac2de545b981
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/WncController.h Wed Aug 31 02:06:26 2016 +0000
@@ -0,0 +1,412 @@
+/*
+ Copyright (c) 2016 Fred Kellerman
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
+ @file WncController.h
+ @purpose Controls WNC Cellular Modem
+ @version 1.0
+ @date July 2016
+ @author Fred Kellerman
+*/
+
+#ifndef __WNCCONTROLLER_H_
+#define __WNCCONTROLLER_H_
+
+#include <string>
+#include <stdint.h>
+
+namespace WncController_fk {
+
+using namespace std;
+
+/**
+ * \file WncController.h
+ * \brief This mbed C++ class is for controlling the WNC
+ * Cellular modem via the AT command interface. This was
+ * developed with respect to version 1.3 of the WNC authored
+ * spec. This class is only designed to have 1 instantiation
+ * it is also not multi-thread safe.
+ */
+
+
+static const uint8_t MAX_LEN_IP_STR = 16; // Length includes room for the extra NULL
+
+
+/**
+ * \brief Contains info fields for the WNC Internet Attributes
+ */
+struct WncIpStats
+{
+ char ip[MAX_LEN_IP_STR];
+ char mask[MAX_LEN_IP_STR];
+ char gateway[MAX_LEN_IP_STR];
+ char dnsPrimary[MAX_LEN_IP_STR];
+ char dnsSecondary[MAX_LEN_IP_STR];
+};
+
+struct WncDateTime
+{
+ uint8_t year;
+ uint8_t month;
+ uint8_t day;
+ uint8_t hour;
+ uint8_t min;
+ uint8_t sec;
+};
+
+class WncController
+{
+public:
+
+ static const unsigned MAX_NUM_WNC_SOCKETS = 1; // Max number of simultaneous sockets that the WNC supports
+ static const unsigned MAX_POWERUP_TIMEOUT = 60; // How long the powerUp method will try to turn on the WNC Shield
+ // (this is the default if the user does not over-ride on power-up
+
+ // Tracks mode of the WNC Shield hardware
+ enum WncState_e {
+ WNC_OFF = 0,
+ WNC_ON, // This is intended to mean all systems go, including cell link up but socket may not be open
+ WNC_ON_NO_CELL_LINK
+ };
+
+ /**
+ * \brief Constructor for UART controlled WNC
+ *
+ * \param [in] wnc_uart - Reference to a SerialBuffered object which will
+ * be used as the bus to control the WNC. apnStr = a text string for
+ * the cellular APN name.
+ *
+ * \return None.
+ *
+ * \details Adding another way to talk to the WNC, like I2C or USB,
+ * a constructor should be added for each type just like the SerialBuffered
+ * constructor below. Assumes UART is enabled, setup and ready to go. This
+ * class will read and write to this UART.
+ */
+ WncController(const char * const apnStr);
+
+ // WncController( const char * const apnStr, MODSERIAL * wnc_uart, MODSERIAL * debug_uart = NULL);
+
+ /**
+ * \brief Used internally but also make public for a user of the Class to interrogate state as well.
+ *
+ * \param [in] None.
+ *
+ * \return The state of the WNC Modem.
+ *
+ * \details None.
+ */
+ WncState_e getWncStatus(void);
+
+ bool setApnName(const char * const apnStr);
+
+ /**
+ * \brief Return signal quality dBm level
+ *
+ * \param [in] None.
+ *
+ * \return The dBm signal level at the time of the request.
+ *
+ * \details This polls (at the time of the call) the cell signal.
+ */
+ int16_t getDbmRssi(void);
+ int16_t get3gBer(void);
+
+ /**
+ * \brief Power up and down (down not implemented yet)
+ *
+ * \param [in] NXP Pins that are critical for the initialization of the WNC Shield.
+ *
+ * \return true if request successful else false.
+ *
+ * \details Power-on works but not power-down. This will manipulate WNC Shield hardware
+ * and bring it to life. It will also initialize the WNC enough to get it to be able to open sockets
+ * (with AT commands)
+ */
+ bool powerWncOn(uint8_t powerUpTimeoutSecs = MAX_POWERUP_TIMEOUT);
+
+ /**
+ * \brief Query the WNC modem for its Internet attributes
+ *
+ * \param [in] Pointer to a struct where to put the info.
+ *
+ * \return true if request successful else false.
+ *
+ * \details This method will do a few sanity checks and then gather the
+ * fields of the struct.
+ */
+ bool getWncNetworkingStats(WncIpStats * s);
+
+ /**
+ * \brief Look-up a URL text string and convert into an IP Address string.
+ *
+ * \param [in] url - the URL to lookup. numSock - the socket reference.
+ *
+ * \return true - if the IP address has been resolved. false - if the URL could not be resolved.
+ *
+ * \details None.
+ */
+ bool resolveUrl(uint16_t numSock, const char * url);
+
+ /**
+ * \brief Set IP Address string
+ *
+ * \param [in] numSock - socket reference to set the string for. ipStr - text string of the IP
+ * address you want to talk to. There is no sanity check - beware!!!
+ *
+ * \return true - if the IP address has been set. false - if the IP could not be set.
+ *
+ * \details None.
+ */
+ bool setIpAddr(uint16_t numSock, const char * ipStr);
+
+ /**
+ * \brief Opens a WNC socket.
+ *
+ * \param [in] sockNum - the number of the socket to open. ipAddr - a string containing
+ * the IP address. port - the IP port number to open the socket connection.
+ *
+ * \return true - if the socket is/was opened. false otherwise.
+ *
+ * \details None.
+ */
+ bool openSocket(uint16_t numSock, uint16_t port, bool tcp, uint16_t timeOutSec = 30);
+
+ /**
+ * \brief Write bytes of data to an open socket
+ *
+ * \param [in] sockNum - the number of the socket to write. s - a string containing
+ * the byte data to send.
+ *
+ * \return true - if the write was successful. false otherwise.
+ *
+ * \details The results of the write do not have anything to do with the data
+ * arriving at the endpoint.
+ */
+ bool write(uint16_t numSock, const char * s, uint32_t n);
+
+ /**
+ * \brief Poll and read back data from the WNC (if it has any)
+ * If auto poll is enabled this read might fail (return with no data).
+ *
+ * \param [in] sockNum - the number of the socket to read. result - a string pointer containing
+ * the byte data readback from the WNC.
+ *
+ * \return The number of bytes/chars that are read from the socket.
+ *
+ * \details DO NOT use the same string as is passed to the auto poll setup method!
+ */
+ size_t read(uint16_t numSock, uint8_t * readBuf, uint32_t maxReadBufLen);
+
+ /**
+ * \brief Set how many times the above read method will retry if data is not returned.
+ *
+ * \param [in] sockNum - the number of the socket to set. retries - how many times to
+ * poll until data is found.
+ *
+ * \return None.
+ *
+ * \details None.
+ */
+ void setReadRetries(uint16_t numSock, uint16_t retries);
+
+ /**
+ * \brief Set how long between retries to wait.
+ *
+ * \param [in] sockNum - the number of the socket to set. waitMs - how long to wait
+ * before doing the read poll (calling read(...)).
+ *
+ * \return None.
+ *
+ * \details None.
+ */
+ void setReadRetryWait(uint16_t numSock, uint16_t waitMs);
+
+ /**
+ * \brief Close the socket.
+ *
+ * \param [in] sockNum - the number of the socket to close.
+ *
+ * \return None.
+ *
+ * \details None.
+ */
+ bool closeSocket(uint16_t numSock);
+
+ void setWncCmdTimeout(uint16_t toMs) {
+ m_sCmdTimeoutMs = toMs;
+ };
+
+ bool getIpAddr(uint16_t numSock, char myIpAddr[MAX_LEN_IP_STR]);
+
+ void enableDebug(bool on, bool moreDebugOn);
+
+ ///////////////////////////////////////////
+ // SMS messaging
+ ///////////////////////////////////////////
+
+ bool sendSMSText(const char * const phoneNum, const char * const text);
+
+ size_t readSMSLog(const char ** log);
+
+ bool saveSMSText(const char * const phoneNum, const char * const text, char * msgIdx);
+
+ bool sendSMSTextFromMem(char msgIdx);
+
+ bool deleteSMSTextFromMem(char msgIdx);
+
+ size_t readSMSText(const char ** log);
+
+ ///////////////////////////////////////////
+ // Neighborhood Cell Info
+ ///////////////////////////////////////////
+ size_t getSignalQuality(const char ** log);
+
+ // Date Time
+ bool getTimeDate(struct WncDateTime * tod);
+
+ // Ping
+ bool pingUrl(const char * url);
+ bool pingIp(const char * ip);
+
+ // User command:
+ size_t sendCustomCmd(const char * cmd, char * resp, size_t sizeRespBuf, int ms_timeout);
+
+protected:
+
+ // Debug output methods
+ int dbgPutsNoTime(const char * s, bool crlf = true);
+ int dbgPuts(const char * s, bool crlf = true);
+ const char * _to_string(int64_t value);
+
+ // Sends commands to WNC via
+ enum AtCmdErr_e {
+ WNC_AT_CMD_OK,
+ WNC_AT_CMD_ERR,
+ WNC_AT_CMD_ERREXT,
+ WNC_AT_CMD_ERRCME,
+ WNC_AT_CMD_INVALID_RESPONSE,
+ WNC_AT_CMD_TIMEOUT,
+ WNC_AT_CMD_NO_CELL_LINK,
+ WNC_AT_CMD_WNC_NOT_ON
+ };
+
+ // Users must define these functionalities:
+ virtual int putc(char c) = 0;
+ virtual int puts(const char * s) = 0;
+ virtual char getc(void) = 0;
+ virtual int byteReady(void) = 0;
+ virtual int dbgWriteByte(char b) = 0;
+ virtual int dbgWriteBytes(const char *b) = 0;
+ virtual void waitMs(int t) = 0;
+ virtual void waitUs(int t) = 0;
+ virtual bool initWncModem(uint8_t powerUpTimeoutSecs) = 0;
+
+ // Isolate OS timers
+ virtual int getLogTimerTicks(void) = 0;
+ virtual void startTimerA(void) = 0;
+ virtual void stopTimerA(void) = 0;
+ virtual int getUsTimerTicksA(void) = 0;
+ virtual void startTimerB(void) = 0;
+ virtual void stopTimerB(void) = 0;
+ virtual int getUsTimerTicksB(void) = 0;
+
+ bool waitForPowerOnModemToRespond(uint8_t powerUpTimeoutSecs);
+
+private:
+
+ bool softwareInitMdm(void);
+ bool checkCellLink(void);
+ AtCmdErr_e mdmSendAtCmdRsp(const char * cmd, int timeout_ms, string * rsp, bool crLf = true);
+ size_t mdmGetline(string & buff, int timeout_ms);
+ AtCmdErr_e sendWncCmd(const char * const s, string ** r, int ms_timeout);
+ bool at_at_wnc(void);
+ bool at_init_wnc(bool hardReset = false);
+ bool at_sockopen_wnc(const string & ipStr, uint16_t port, uint16_t numSock, bool tcp, uint16_t timeOutSec);
+ bool at_sockclose_wnc(uint16_t numSock);
+ bool at_dnsresolve_wnc(const char * s, string * ipStr);
+ AtCmdErr_e at_sockwrite_wnc(const char * s, uint32_t n, uint16_t numSock, bool isTcp);
+ AtCmdErr_e at_sockread_wnc(uint8_t * pS, uint32_t * numRead, uint16_t n, uint16_t numSock, bool isTcp);
+ bool at_reinitialize_mdm(void);
+ AtCmdErr_e at_send_wnc_cmd(const char * s, string ** r, int ms_timeout);
+ bool at_setapn_wnc(const char * const apnStr);
+ bool at_sendSMStext_wnc(const char * const phoneNum, const char * const text);
+ bool at_get_wnc_net_stats(WncIpStats * s);
+ size_t at_readSMSlog_wnc(const char ** log);
+ size_t at_readSMStext_wnc(const char ** log);
+ bool at_getrssiber_wnc(int16_t * dBm, int16_t * ber3g);
+ void closeOpenSocket(uint16_t numSock);
+ bool sockWrite(const char * s, uint32_t n, uint16_t numSock, bool isTcp);
+ bool at_sendSMStextMem_wnc(char n);
+ bool at_deleteSMSTextFromMem_wnc(char n);
+ bool at_saveSMStext_wnc(const char * const phoneNum, const char * const text, char * msgIdx);
+ size_t at_getSignalQuality_wnc(const char ** log);
+ bool at_gettimedate_wnc(struct WncDateTime * tod);
+ bool at_ping_wnc(const char * ip);
+
+ // Utility methods
+ void sendCmd(const char * cmd, bool crLf);
+ void sendCmd(const char * cmd, unsigned n, unsigned wait_uS, bool crLf);
+ inline void rx_char_wait(void) {
+ // waitUs(1000);
+ }
+
+ // Important constants
+ 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, careful here large chunks come out of the heap
+ static const uint16_t MAX_WNC_WRITE_BYTES = MAX_WNC_READ_BYTES;
+ 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
+ static const uint16_t WNC_AUTO_POLL_MS = 250; // Sets default (may be overriden with method) poll interval
+ 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
+ static const uint16_t WNC_QUICK_CMD_TIMEOUT_MS = 2000; // Used for simple commands that should immediately respond such as "AT"
+ static const uint16_t WNC_WAIT_FOR_AT_CMD_MS = 0; // 40; // Wait this much between AT commands, this is what WNC advises (they said 20mS, I added margin).
+ static const uint16_t MAX_WNC_SMS_LENGTH = 150;
+ static const uint16_t WNC_SOFT_INIT_RETRY_COUNT = 10;
+ static const uint16_t WNC_DNS_RESOLVE_WAIT_MS = 60000;
+ static const uint16_t WNC_TRUNC_DEBUG_LENGTH = 80; // Always make this an even number
+ static const uint16_t WNC_APNSET_TIMEOUT_MS = 60000;
+ static const uint16_t WNC_PING_CMD_TIMEOUT_MS = 60000; // Amount of time to wait for AT@PINGREQ with default params to timeout
+ static const int WNC_REINIT_MAX_TIME_MS = 60000;
+ static const char * const INVALID_IP_STR;
+
+ struct WncSocketInfo_s {
+ bool open;
+ string myIpAddressStr;
+ uint16_t myPort;
+ uint8_t readRetries;
+ uint16_t readRetryWaitMs;
+ bool isTcp;
+ uint16_t timeOutSec;
+ };
+
+ static WncSocketInfo_s m_sSock[MAX_NUM_WNC_SOCKETS];
+ static WncState_e m_sState;
+ static uint16_t m_sCmdTimeoutMs;
+ static string m_sApnStr;
+ static string m_sWncStr;
+ static uint8_t m_sPowerUpTimeoutSecs;
+ static bool m_sDebugEnabled;
+ static bool m_sMoreDebugEnabled;
+ static bool m_sCheckNetStatus;
+ static bool m_sReadyForSMS;
+};
+
+}; // End namespace WncController_fk
+
+#endif
\ No newline at end of file
