A library for talking to Multi-Tech's Cellular SocketModem Devices.

Dependents:   M2X_dev axeda_wrapper_dev MTS_M2x_Example1 MTS_Cellular_Connect_Example ... more

cellular/Cellular.h

Committer:
sgodinez
Date:
2013-12-19
Revision:
41:81d035fb0b6a
Parent:
34:60682c702c3f
Child:
43:3cacf019ed7d

File content as of revision 41:81d035fb0b6a:

#ifndef CELLULAR_H
#define CELLULAR_H

#include "IPStack.h"
#include "MTSBufferedIO.h"
#include "mbed.h"
#include <string>
#include <vector>

#define PINGDELAY 3 //Time to wait on each ping for a response before timimg out (seconds)
#define PINGNUM 4 //Number of pings to try on ping command

//Special Payload Characters
const char ETX = 0x03;  //Ends socket connection
const char DLE = 0x10;  //Escapes ETX and DLE within Payload

// An array of strings for printing the names of the Code enum.
//const string CodeNames[] = {"OK", "ERROR", "NO_RESPONSE", "FAILURE"};

// An array of strings for printing the names of the Registration enum.
//const string RegistrationNames[] = {"NOT_REGISTERED", "REGISTERED", "SEARCHING", "DENIED", "UNKNOWN", "ROAMING"};


/** This is a class for communicating with a Multi-Tech Systems SocketModem iCell. The 
* SocketModem iCell is a family of carrier certified embedded cellular radio modules with
* a common hardware footprint and AT command set for built in IP-stack functionality.
* This class supports three main types of cellular radio interactions including: 
* configuration and status AT command processing, SMS processing, and TCP/UDP Socket
* data connections. It should be noted that the radio can not process commands or 
* SMS messages while having an open data connection at the same time. The concurrent
* capability may be added in a future release. This class also inherits from IPStack
* providing a common set of commands for communication devices that have an onboard
* IP Stack. It is also integrated with the standard Mbed Sockets package and can therefore
* be used seamlessly with clients and services built on top of this interface already within
* the Mbed library.
* 
* All of the following examples use the Pin Names for the Freedom KL46Z board coupled with
* the SocketModem Shield Arduino compatible board. Please chage Pin Names accordingly to 
* match your hardware configuration. It also assumes the use of RTS/CTS hardware handshaking
* using GPIOs. To disable this you will need to change settings on the radio module and
* and use the MTSSerial class instead of MTSSerialFlowControl. The default baud rate for the
* cellular radio is 115200 bps.
* 
* The following set of example code demonstrates how to send and receive configuration and
* status AT commands with the radio:
* @code
* #include "mbed.h"
* #include "Cellular.h"
* #include "MTSSerialFlowControl.h"
* 
* main() {
*   //Wait for radio to boot up
*   wait(15);
* 
*   //Setup serial interface to radio
*   MTSSerialFlowControl* serial = new MTSSerialFlowControl(PTD3, PTD2, PTA12, PTC8);
*   serial->baud(115200);
*
*   //Setup Cellular class
*   Cellular* cellular = Cellular::getInstance(serial);
*   
*   //Run status and configuration commands
*   printf("Start Status and Configuration Example\n\r");
*   printf("test: %s\n\r", CodeNames[cellular->test()]);
*   printf("Phone Number: %s\n\r", cellular->getPhoneNumber());
*   printf("Signal Strength: %d\n\r", cellular->getSignalStrength());
*   printf("Registration State: %s\n\r", RegistrationNames[cellular->getRegistration()]);
*   printf("Send Basic Command (AT): %s\n\r", CodeNames[cellular->sendBasicCommand("AT", 1000)]);
*   printf("Send Command (AT+CSQ): %s\n\r", sendCommand("AT+CSQ", 1000));  
* 
*   printf("End Program\n\r"); 
* }
* @endcode
*
* The following set of example code demonstrates how process SMS messages:
* @code
* #include "mbed.h"
* @endcode
*
* The following set of example code demonstrates how to setup and verify a cellular data
* connection:
* @code
* #include "mbed.h"
* #include "Cellular.h"
* #include "MTSSerialFlowControl.h"
* 
* main() {
*   //Wait for radio to boot up
*   wait(20);
* 
*   //Setup serial interface to radio
*   MTSSerialFlowControl* serial = new MTSSerialFlowControl(PTD3, PTD2, PTA12, PTC8);
*   serial->baud(115200);
*
*   //Setup Cellular class
*   Cellular* cellular = Cellular::getInstance(serial);
*   
*   //Start Test
*   printf("Start Network Connectivity Example\n\r");
*   printf("test: %s\n\r", CodeNames[cellular->test()]);
*   printf("Set APN: %s\n\r", CodeNames[cellular->setApn("wap.cingular")]) //Use APN from service provider!!!
* 
*   //Setup a data connection
*   printf("Attempting to Connect\n\r");
*   while (cellular->connect()) {
*       wait(1);
*   }
*   printf("Connected to Network!\n\r");
* 
*   //Try pinging default server "8.8.8.8"
*   printf("Ping Valid: %s\n\r", cellular->ping() ? "true" : "false");
* 
*   printf("End Program\n\r");
* }
* @endcode
* 
* The following set of example code demonstrates how to setup and use a TCP socket connection
* using the native commands from this class:
* @code
* #include "mbed.h"
* @endcode
*
* The following set of example code demonstrates how to setup and use a TCP socket connection
* using the Mbed compatible Socket interfaces.
* @code
* #include "mbed.h"
* @endcode
*/

class Cellular : virtual IPStack
{
public:
    /// An enumeration for common responses to an AT command.
    enum Code {
        OK, ERROR, NO_RESPONSE, FAILURE
    };

    /// An enumeration for escape characters at the end of AT commands.
    enum ESC_CHAR {
        CR, CTRL_Z, NONE
    };

    /// An enumeration of radio registration states with a cell tower.
    enum Registration {
        NOT_REGISTERED, REGISTERED, SEARCHING, DENIED, UNKNOWN, ROAMING
    };

    struct Sms {
        std::string phoneNumber;
        std::string message;
        std::string timestamp;
    };

    /** Destructs a Cellular object and frees all related resources.
    */
    ~Cellular();

    static Cellular* getInstance();
    static Cellular* getInstance(MTSBufferedIO* io);

    /** This method establishes a data connection on the cellular radio.
    * Note that before calling you must have an activated radio and if
    * using a SIM card set the APN using the setApn method. The APN can
    * be obtained from your cellular service provider.
    *
    * @returns true if the connection was successfully established, otherwise
    * false on an error.
    */
    virtual bool connect();

    /** This method is used to stop a previously established cellular data connection.
    */
    virtual void disconnect();

    /** This method is used to check if the radio currently has a data connection
    * established.
    *
    * @returns true if a data connection exists, otherwise false.
    */
    virtual bool isConnected();

    // Used for TCPSocketConnection & UDPSocketConnection
    virtual bool bind(unsigned int port);
    virtual bool open(const std::string& address, unsigned int port, Mode mode);
    virtual bool isOpen();
    virtual bool close();
    virtual int read(char* data, int max, int timeout = -1);
    virtual int write(const char* data, int length, int timeout = -1);
    virtual unsigned int readable();
    virtual unsigned int writeable();

    //Other
    /** A method to reset the Multi-Tech Socket Modem.  This command brings down the
    * PPP link if it is up.  After this function is called, at least 30 seconds should
    * be allowed for the cellular radio to come back up before any other Cellular
    * functions are called.
    */
    /** this needs to be investigated.  After we tell the radio to reset and wait 30 seconds,
    * we can't seem to get it to respond to even a simple signal strength query.
    */
    virtual void reset();

    //Cellular Radio Specific
    /** A method for sending a generic AT command to the radio. Note that you cannot
    * send commands and have a data connection at the same time.
    * 
    * @param command the command to send to the radio without the escape character.
    * @param timeoutMillis the time in millis to wait for a response before returning.
    * @param esc escape character to add at the end of the command, defaults to
    * carriage return (CR).
    * @returns all data received from the radio after the command as a string.
    */
    std::string sendCommand(std::string command, int timeoutMillis, ESC_CHAR esc = CR);
    
    /** A method for sending a basic AT command to the radio. A basic AT command is 
    * one that simply has a response of either OK or ERROR without any other information.
    * Note that you cannot send commands and have a data connection at the same time.
    * 
    * @param command the command to send to the radio without the escape character.
    * @param timeoutMillis the time in millis to wait for a response before returning.
    * @param esc escape character to add at the end of the command, defaults to
    * carriage return (CR).
    * @returns the standard AT Code enumeration.
    */
    Code sendBasicCommand(std::string command, int timeoutMillis, ESC_CHAR esc = CR);

    /** A method for testing command access to the radio.  This method sends the
    * command "AT" to the radio, which is a standard radio test to see if you
    * have command access to the radio.
    *
    * @returns the standard AT Code enumeration.
    */
    Code test();

    /** A method for configuring command ehco capability on the radio. This command
    * sets whether sent characters are echoed back from the radio, in which case you
    * will receive back every command you send.
    *
    * @param state if true echo will be turned off, otherwise it will be turned on.
    * @returns the standard AT Code enumeration.
    */
    Code echo(bool state);
    
    /** A method for getting the signal strength of the radio. This method allows you to
    * get a value that maps to signal strength in dBm. Here 0-1 is Poor, 2-9 is Marginal,
    * 10-14 is Ok, 15-19 is Good, and 20+ is Excellent.  If you get a result of 99 the
    * signal strength is not known or not detectable.
    *
    * @returns an integer representing the signal strength.
    */
    int getSignalStrength();
    
    /** This method is used to get the phone number of the cellular radio if one exists.
    *
    * @returns the phone number as a string, otherwise "unknown" if it does not exist.
    */
    std::string getPhoneNumber();

    /** This method is used to check the registration state of the radio with the cell tower.
    * If not appropriatley registered with the tower you cannot make a cellular connection.
    *
    * @returns the registration state as an enumeration type.
    */
    Registration getRegistration();

    /** This method is used to set the radios APN if using a SIM card. Note that the APN
    * must be set correctly before you can make a data connection. The APN for your SIM
    * can be obtained by contacting your cellular service provider.
    *
    * @param the APN as a string.
    * @returns the standard AT Code enumeration.
    */
    Code setApn(const std::string& apn);

    /** This method is used to set the DNS which enables the use of URLs instead
    * of IP addresses when making a socket connection.
    *
    * @param the DNS server address as a string in form xxx.xxx.xxx.xxx.
    * @returns the standard AT Code enumeration.
    */
    Code setDns(const std::string& primary, const std::string& secondary = "0.0.0.0");

    /** This method is used test network connectivity by pinging a server.
    *
    * @param address the address of the server in format xxx.xxx.xxx.xxx.
    * @returns true if the ping was successful, otherwise false.
    */
    bool ping(const std::string& address = "8.8.8.8");
    Code setSocketCloseable(bool enabled = true);  //ETX closes socket (ETX and DLE in payload are escaped with DLE)

    /** This method is used to send an SMS message. Note that you cannot send an
    * SMS message and have a data connection open at the same time.
    *
    * @param phoneNumber the phone number to send the message to as a string.
    * @param message the text message to be sent.
    * @returns the standard AT Code enumeration.
    */
    Code sendSMS(const std::string& phoneNumber, const std::string& message);
    
    /** This method is used to send an SMS message. Note that you cannot send an
    * SMS message and have a data connection open at the same time.
    *
    * @param sms an Sms struct that contains all SMS transaction information.
    * @returns the standard AT Code enumeration.
    */
    Code sendSMS(const Sms& sms);
    
    /**
    *
    */
    std::vector<Cellular::Sms> getReceivedSms();
    Code deleteAllReceivedSms();
    Code deleteOnlyReceivedReadSms();


private:
    static Cellular* instance; //Static pointer to the single Cellular object.

    MTSBufferedIO* io; //IO interface obect that the radio is accessed through.
    bool echoMode; //Specifies if the echo mode is currently enabled.

    bool pppConnected; //Specifies if a PPP session is currently connected.
    std::string apn; //A string that holds the APN for the radio.

    Mode mode;
    bool socketOpened; //Specifies if a Socket is presently opened.
    bool socketCloseable; //Specifies is a Socket can be closed.
    unsigned int local_port; //Holds the local port for socket connections.
    std::string local_address; //Holds the local address for socket connections.
    unsigned int host_port; //Holds the remote port for socket connections.
    std::string host_address; //Holds the remote address for socket connections.
    DigitalIn* dcd;
    DigitalOut* dtr;

    Cellular(); //Private constructor, use the getInstance() method.
    Cellular(MTSBufferedIO* io); //Private constructor, use the getInstance() method.
};

#endif /* CELLULAR_H */