Cellular library for MTS Socket Modem Arduino Shield devices from Multi-Tech Systems

Dependents:   mtsas mtsas mtsas mtsas

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Cellular.h Source File

Cellular.h

00001 #ifndef CELLULAR_H
00002 #define CELLULAR_H
00003 
00004 #include <string>
00005 #include <vector>
00006 
00007 #include "IPStack.h"
00008 #include "MTSBufferedIO.h"
00009 #include "CellUtils.h"
00010 
00011 namespace mts
00012 {
00013 
00014 /** This is a class for communicating with a Cellular radio device.
00015 * This class supports three main types of cellular radio interactions including:
00016 * configuration and status processing, SMS processing, and TCP/UDP Socket
00017 * data connections. This class also inherits from IPStack providing a common set of commands
00018 * for communication devices that support IP protocols. It is also integrated with the standard
00019 * mbed Sockets package and can therefore be used seamlessly with clients and services built
00020 * on top of this interface already within the mbed library.
00021 *
00022 * For all examples below please change Pin Names to match your hardware configuration.
00023 * It also assumes the use of RTS/CTS hardware handshaking using GPIOs. To disable this
00024 * you will need to change settings on the radio module and and use the MTSSerial class
00025 * instead of MTSSerialFlowControl.
00026 *
00027 * The following set of example code demonstrates how to send and receive configuration and
00028 * status AT commands with the radio, create a data connection and test it:
00029 * @code
00030 * #include "mbed.h"
00031 * #include "mtsas.h"
00032 *
00033 * int main(){
00034 *    //Modify to match your apn if you are using an HSPA radio with a SIM card
00035 *    const char APN[] = "";
00036 *    
00037 *    //Sets the log level to INFO, higher log levels produce more log output.
00038 *    //Possible levels: NONE, FATAL, ERROR, WARNING, INFO, DEBUG, TRACE
00039 *    MTSLog::setLogLevel(MTSLog::INFO_LEVEL);
00040 *    
00041 *    // STMicro Nucelo F401RE
00042 *    // The supported jumper configurations of the MTSAS do not line up with
00043 *    // the pin mapping of the Nucleo F401RE. Therefore, the MTSAS serial TX
00044 *    // pin (JP8 Pin 2) must be manually jumped to Serial1 RX (Shield pin D2)
00045 *    // and the MTSAS serial RX pin (JP9 Pin 2) pin must be manually jumped to
00046 *    // Serial1 TX (Shield pin D8).
00047 *    // Uncomment the following line to use the STMicro Nuceleo F401RE
00048 *    //
00049 *    MTSSerialFlowControl* io = new MTSSerialFlowControl(D8, D2, D3, D6);
00050 *    
00051 *    // Freescale KL46Z
00052 *    // To configure the pins for the Freescale KL46Z board, use configuration B
00053 *    // Uncomment the following line to use the Freescale KL46Z board
00054 *    //
00055 *    //MTSSerialFlowControl* io = new MTSSerialFlowControl(D2, D9, D3, D6);
00056 *    
00057 *    // Freescale K64F
00058 *    // To configure the pins for the Freescale KL46Z board, use configuration A
00059 *    // Uncomment the following line to use the Freescale KL46F board
00060 *    //
00061 *    //MTSSerialFlowControl* io = new MTSSerialFlowControl(D1, D0, D3, D6);
00062 *    
00063 *    //Sets the baud rate for communicating with the radio
00064 *    io->baud(115200);
00065 *    
00066 *    //Create radio object
00067 *    Cellular* radio = CellularFactory::create(io);
00068 *    radio->configureSignals(D4,D7,RESET);
00069 *    Transport::setTransport(radio);
00070 *    
00071 *    if (! radio) {
00072 *        logFatal("Failed to initialize radio");
00073 *        return 1;
00074 *    }
00075 *    
00076 *    //Set radio APN
00077 *    for (int i = 0; i < 10; i++) {
00078 *        if (i >= 10) {
00079 *            logError("Failed to set APN to %s", APN);
00080 *        }
00081 *        if (radio->setApn(APN) == MTS_SUCCESS) {
00082 *            logInfo("Successfully set APN to %s", APN);
00083 *            break;
00084 *        } else {
00085 *            wait(1);
00086 *        }
00087 *    }
00088 *    
00089 *    //Establish PPP link
00090 *    for (int i = 0; i < 10; i++) {
00091 *        if (i >= 10) {
00092 *            logError("Failed to establish PPP link");
00093 *        }
00094 *        if (radio->connect() == true) {
00095 *            logInfo("Successfully established PPP link");
00096 *            break;
00097 *        } else {
00098 *            wait(1);
00099 *        }
00100 *    }
00101 *    
00102 *    //Ping google.com
00103 *    for (int i = 0; i < 10; i++) {
00104 *        if (i >= 10) {
00105 *            logError("Failed to ping www.google.com");
00106 *        }
00107 *        if (radio->ping("www.google.com") == true) {
00108 *            logInfo("Successfully pinged www.google.com");
00109 *            break;
00110 *        } else {
00111 *            wait(1);
00112 *        }
00113 *    }
00114 *    
00115 *    //Disconnect ppp link
00116 *    radio->disconnect();
00117 *    
00118 *    logInfo("End of example code");
00119 *    return 0;
00120 * }
00121 *
00122 * @endcode
00123 *
00124 * The following set of example code demonstrates how to process SMS messages:
00125 * @code
00126 * #include "mbed.h"
00127 * #include "mtsas.h"
00128 *
00129 * int main(){
00130 *    
00131 *    //Sets the log level to INFO, higher log levels produce more log output.
00132 *    //Possible levels: NONE, FATAL, ERROR, WARNING, INFO, DEBUG, TRACE
00133 *    MTSLog::setLogLevel(MTSLog::INFO_LEVEL);
00134 *    
00135 *    //Modify to match your apn if you are using an HSPA radio with a SIM card
00136 *    const char APN[] = "";
00137 *    
00138 *    //Phone number to send to and receive from. Must be in the form "1xxxxxxxxxx"
00139 *    string PHONE_NUMBER = "";
00140 *    
00141 *    Cellular::Sms txtmsg;
00142 *    txtmsg.phoneNumber = PHONE_NUMBER;
00143 *    txtmsg.message = "Hello World! MTSAS is up and running!";
00144 *    
00145 *    // STMicro Nucelo F401RE
00146 *    // The supported jumper configurations of the MTSAS do not line up with
00147 *    // the pin mapping of the Nucleo F401RE. Therefore, the MTSAS serial TX
00148 *    // pin (JP8 Pin 2) must be manually jumped to Serial1 RX (Shield pin D2)
00149 *    // and the MTSAS serial RX pin (JP9 Pin 2) pin must be manually jumped to
00150 *    // Serial1 TX (Shield pin D8).
00151 *    // Uncomment the following line to use the STMicro Nuceleo F401RE
00152 *    //
00153 *    MTSSerialFlowControl* io = new MTSSerialFlowControl(D8, D2, D3, D6);
00154 *    
00155 *    // Freescale KL46Z
00156 *    // To configure the pins for the Freescale KL46Z board, use configuration B
00157 *    // Uncomment the following line to use the Freescale KL46Z board
00158 *    //
00159 *    //MTSSerialFlowControl* io = new MTSSerialFlowControl(D2, D9, D3, D6);
00160 *    
00161 *    // Freescale K64F
00162 *    // To configure the pins for the Freescale KL46Z board, use configuration A
00163 *    // Uncomment the following line to use the Freescale KL46F board
00164 *    //
00165 *    //MTSSerialFlowControl* io = new MTSSerialFlowControl(D1, D0, D3, D6);
00166 *    
00167 *    //Sets the baudrate for communicating with the radio
00168 *    io->baud(115200); 
00169 *    
00170 *    //Creates a radio object
00171 *    Cellular* radio = CellularFactory::create(io);
00172 *    radio->configureSignals(D4,D7,RESET);
00173 *    Transport::setTransport(radio);
00174 *    
00175 *    if (! radio) {
00176 *        logFatal("Failed to initialize radio");
00177 *        return 1;
00178 *    }
00179 *    
00180 *    //Set radio APN
00181 *    for (int i = 0; i < 10; i++) {
00182 *        if (i >= 10) {
00183 *            logError("Failed to set APN\n");
00184 *        }
00185 *        if (radio->setApn(APN) == MTS_SUCCESS) {
00186 *            logInfo("Successfully set APN\n");
00187 *            break;
00188 *        } else {
00189 *            wait(1);
00190 *        }
00191 *    }
00192 *    
00193 *    //Delete any previously received SMS messages
00194 *    for (int i = 0; i < 10; i++) {
00195 *        if (i >= 10) {
00196 *            logError("Failed to delete SMS messages\n");
00197 *        }
00198 *        if (radio->deleteAllReceivedSms() == MTS_SUCCESS) {
00199 *            logInfo("Deleted all SMS messages\n");
00200 *            break;
00201 *        } else {
00202 *            wait(1);
00203 *        }
00204 *    }
00205 *    
00206 *    // Send SMS message to phone
00207 *    for (int i = 1; i < 10; i++) {
00208 *        if(radio->sendSMS(txtmsg) == MTS_SUCCESS) {
00209 *            logInfo("Sent SMS successfully:<%s>\n", txtmsg.message.c_str());
00210 *            break;
00211 *        } else {
00212 *            logError("Failed to send SMS<%s>\n", txtmsg.message.c_str());
00213 *        }
00214 *    }
00215 *    
00216 *    //Checking for received SMS messages
00217 *    while (true) {
00218 *        logInfo("Checking for received messages");
00219 *        vector<Cellular::Sms> recv = radio->getReceivedSms();
00220 *        if(recv.size() > 0) {
00221 *            int size = recv.size();
00222 *            for (int i = 0; i < size; i++) {
00223 *                logInfo("Message %d: [%s] [%s] [%s]", i, recv[i].phoneNumber.c_str(), recv[i].timestamp.c_str(), recv[i].message.c_str());
00224 *            }
00225 *        }
00226 *        
00227 *        if(radio->deleteOnlyReceivedReadSms() != MTS_SUCCESS) {
00228 *            logError("Failed to delete received and read SMS messages");
00229 *        }
00230 *        wait(10);
00231 *    }
00232 *    
00233 *    logDebug("End of example code\n");
00234 *    return 0;
00235 * }
00236 * @endcode
00237 */
00238 
00239 class Cellular : public IPStack
00240 {
00241 public:
00242     // Class ping paramter constants
00243     static const unsigned int PINGDELAY = 3; //Time to wait on each ping for a response before timimg out (seconds)
00244     static const unsigned int PINGNUM = 4; //Number of pings to try on ping command
00245 
00246     /// Enumeration for different cellular radio types.
00247     enum Radio {
00248         NA, MTSMC_H5, MTSMC_EV3, MTSMC_G3, MTSMC_C2, MTSMC_H5_IP, MTSMC_EV3_IP, MTSMC_C2_IP, MTSMC_LAT1, MTSMC_LVW2, MTSMC_LEU1,
00249             MTQ_LAT3, MTQ_LVW3, MTQ_MAT1, MTQ_MVW1
00250     };
00251 
00252     /// An enumeration of radio registration states with a cell tower.
00253     enum Registration {
00254         NOT_REGISTERED, REGISTERED, SEARCHING, DENIED, UNKNOWN, ROAMING
00255     };
00256 
00257     /** This structure contains the data for an SMS message.
00258     */
00259     struct Sms {
00260         /// Message Phone Number
00261         std::string phoneNumber;
00262         /// Message Body
00263         std::string message;
00264         /// Message Timestamp
00265         std::string timestamp;
00266     };
00267 
00268     /** This structure contains the data for GPS position.
00269     */
00270     struct gpsData {
00271         bool success;
00272         /// Format is ddmm.mmmm N/S. Where: dd - degrees 00..90; mm.mmmm - minutes 00.0000..59.9999; N/S: North/South.
00273         std::string latitude;
00274         /// Format is dddmm.mmmm E/W. Where: ddd - degrees 000..180; mm.mmmm - minutes 00.0000..59.9999; E/W: East/West.
00275         std::string longitude;
00276         /// Horizontal Diluition of Precision.
00277         float hdop;
00278         /// Altitude - mean-sea-level (geoid) in meters.
00279         float altitude;
00280         /// 0 or 1 - Invalid Fix; 2 - 2D fix; 3 - 3D fix.
00281         int fix;
00282         /// Format is ddd.mm - Course over Ground. Where: ddd - degrees 000..360; mm - minutes 00..59.
00283         std::string cog;
00284         /// Speed over ground (Km/hr).
00285         float kmhr;
00286         /// Speed over ground (knots).
00287         float knots;
00288         /// Total number of satellites in use.
00289         int satellites;
00290         /// Date and time in the format YY/MM/DD,HH:MM:SS.
00291         std::string timestamp;
00292     };
00293     
00294     /** This method initializes the object with the underlying radio
00295     * interface to use. Note that this function MUST be called before
00296     * any other calls will function correctly on a Cellular object. Also
00297     * note that MTSBufferedIO is abstract, so you must use one of
00298     * its inherited classes like MTSSerial, MTSSerialFlowControl or write a class
00299     * similar to MTSSerialFlowControl which maps the MTSBufferedIO API
00300     * to your favorite serial library.
00301     *
00302     * @param io the io interface that is attached to the cellular radio.
00303     * The default is not connected.
00304     * @returns true if the init was successful, otherwise false.
00305     */
00306     virtual bool init(MTSBufferedIO* io);
00307     
00308     /** Sets up the physical connection pins
00309     *   (DTR,DCD, and RESET)
00310     */
00311     bool configureSignals(unsigned int DCD = NC, unsigned int DTR = NC, unsigned int RESET = NC);
00312 
00313     /** A method for testing command access to the radio.  This method sends the
00314     * command "AT" to the radio, which is a standard radio test to see if you
00315     * have command access to the radio.  The function returns when it receives
00316     * the expected response from the radio.
00317     *
00318     * @returns the standard AT Code enumeration.
00319     */
00320     virtual Code test();
00321 
00322     /** A method for getting the signal strength of the radio. This method allows you to
00323     * get a value that maps to signal strength in dBm. Here 0-1 is Poor, 2-9 is Marginal,
00324     * 10-14 is Ok, 15-19 is Good, and 20+ is Excellent.  If you get a result of 99 the
00325     * signal strength is not known or not detectable.
00326     *
00327     * @returns an integer representing the signal strength.
00328     */
00329     virtual int getSignalStrength();
00330 
00331     /** This method is used to check the registration state of the radio with the cell tower.
00332     * If not appropriatley registered with the tower you cannot make a cellular connection.
00333     *
00334     * @returns the registration state as an enumeration type.
00335     */
00336     virtual Registration getRegistration();
00337 
00338     /** This method is used to set the radios APN if using a SIM card. Note that the APN
00339     * must be set correctly before you can make a data connection. The APN for your SIM
00340     * can be obtained by contacting your cellular service provider.
00341     *
00342     * @param the APN as a string.
00343     * @returns the standard AT Code enumeration.
00344     */
00345     virtual Code setApn(const std::string& apn) = 0;
00346 
00347     /** This method is used to set the DNS which enables the use of URLs instead
00348     * of IP addresses when making a socket connection.
00349     *
00350     * @param the DNS server address as a string in form xxx.xxx.xxx.xxx.
00351     * @returns the standard AT Code enumeration.
00352     */
00353     virtual Code setDns(const std::string& primary, const std::string& secondary = "0.0.0.0");
00354 
00355     /** This method is used to send an SMS message. Note that you cannot send an
00356     * SMS message and have a data connection open at the same time.
00357     *
00358     * @param phoneNumber the phone number to send the message to as a string.
00359     * @param message the text message to be sent.
00360     * @returns the standard AT Code enumeration.
00361     */
00362     virtual Code sendSMS(const std::string& phoneNumber, const std::string& message);
00363 
00364     /** This method is used to send an SMS message. Note that you cannot send an
00365     * SMS message and have a data connection open at the same time.
00366     *
00367     * @param sms an Sms struct that contains all SMS transaction information.
00368     * @returns the standard AT Code enumeration.
00369     */
00370     virtual Code sendSMS(const Sms& sms);
00371 
00372     /** This method retrieves all of the SMS messages currently available for
00373     * this phone number.
00374     *
00375     * @returns a vector of existing SMS messages each as an Sms struct.
00376     */
00377     virtual std::vector<Cellular::Sms> getReceivedSms();
00378 
00379     /** This method can be used to remove/delete all received SMS messages
00380     * even if they have never been retrieved or read.
00381     *
00382     * @returns the standard AT Code enumeration.
00383     */
00384     virtual Code deleteAllReceivedSms();
00385 
00386     /** This method can be used to remove/delete all received SMS messages
00387     * that have been retrieved by the user through the getReceivedSms method.
00388     * Messages that have not been retrieved yet will be unaffected.
00389     *
00390     * @returns the standard AT Code enumeration.
00391     */
00392     virtual Code deleteOnlyReceivedReadSms();
00393 
00394     //Cellular Radio Specific
00395     /** A method for sending a generic AT command to the radio. Note that you cannot
00396     * send commands and have a data connection at the same time.
00397     *
00398     * @param command the command to send to the radio without the escape character.
00399     * @param timeoutMillis the time in millis to wait for a response before returning.
00400     * @param esc escape character to add at the end of the command, defaults to
00401     * carriage return (CR).  Does not append any character if esc == 0.
00402     * @returns all data received from the radio after the command as a string.
00403     */
00404     virtual std::string sendCommand(const std::string& command, unsigned int timeoutMillis, char esc = CR);
00405 
00406     /** A method for sending a basic AT command to the radio. A basic AT command is
00407     * one that simply has a response of either OK or ERROR without any other information.
00408     * Note that you cannot send commands and have a data connection at the same time.
00409     *
00410     * @param command the command to send to the radio without the escape character.
00411     * @param timeoutMillis the time in millis to wait for a response before returning.
00412     * @param esc escape character to add at the end of the command, defaults to
00413     * carriage return (CR).
00414     * @returns the standard Code enumeration.
00415     */
00416     virtual Code sendBasicCommand(const std::string& command, unsigned int timeoutMillis, char esc = CR);
00417 
00418     /** A static method for getting a string representation for the Registration
00419     * enumeration.
00420     *
00421     * @param code a Registration enumeration.
00422     * @returns the enumeration name as a string.
00423     */
00424     static std::string getRegistrationNames(Registration registration);
00425 
00426     /** A static method for getting a string representation for the Radio
00427     * enumeration.
00428     *
00429     * @param type a Radio enumeration.
00430     * @returns the enumeration name as a string.
00431     */
00432     static std::string getRadioNames(Radio radio);
00433     
00434     /** A method for changing the echo commands from radio.
00435     * @param state Echo mode is off (an argument of 1 turns echos off, anything else turns echo on)
00436     * @returns standard Code enumeration
00437     */
00438     virtual Code echo(bool state);
00439     
00440     /** This method can be used to trade socket functionality for performance.
00441     * Can disable checking socket closed messages from the data socket, and thus the socket
00442     * will only be visibly closed to the local side if the radio is explicitly checked, or
00443     * the socket is closed by the local side through the use of physical pin manipulation.
00444     *
00445     * Uses the Hayes escape sequence (1 second pause, "+++", 1 second pause) to exit the socket
00446     * connection to check if a received "NO CARRIER" string is from the radio indicating the socket
00447     * has been closed, or is merely part of the data stream. Should not occur very often, however, if 
00448     * data carrying the string "NO CARRIER" is going to be transmitted frequently, then the socket should
00449     * be set closeable and physical-socket-closing-means be used instead to reduce the large amount of
00450     * overhead switching from checking the validity of the "NO CARRIER" message being and indication of
00451     * the socket connection being closed.
00452     *
00453     * @param enabled set to true if you want the socket closeable, otherwise false. The default
00454     * is true.
00455     * @returns the standard AT Code enumeration.
00456     */
00457     virtual Code setSocketCloseable(bool enabled);
00458     
00459     /** Binds the socket to a specific port if able
00460     * @param port integer to bind the socket to.
00461     *   
00462     * @returns true if successfully bound port, false if bind failed.
00463     */
00464     virtual bool bind(unsigned int port);
00465     
00466     /** Checks if a socket is open.
00467     * @returns true if socket is open, false if socket is closed
00468     */
00469     virtual bool isOpen();
00470     
00471     /** Checks if there is data available from the socket.
00472     * @returns number of bytes of data available to read.
00473     */
00474     virtual unsigned int readable();
00475     
00476     /** Checks data to output on the socket
00477     * @returns number of bytes to be written to the socket.
00478     */
00479     virtual unsigned int writeable();
00480     
00481     /** Gets the device IP
00482     * @returns string containing the IP address
00483     */
00484     virtual std::string getDeviceIP();
00485     
00486     /** Sets the device IP
00487     * (Not implemented, IP address values are assigned by DHCP)
00488     * @returns true if the IP was set, false if IP address assignment failed.
00489     */
00490     virtual bool setDeviceIP(std::string address = "DHCP");
00491     
00492     /** Get the device IMEI or MEID (whichever is available)
00493     * @returns string containing the IMEI for GSM, the MEID for CDMA, or an empty string
00494     * if it failed to parse the number.
00495     */
00496     std::string getEquipmentIdentifier();
00497 
00498     /** Get radio type
00499     * @returns the radio type (MTSMC-H5, etc)
00500     */
00501     int getRadioType();
00502 
00503     /** Get string representation of radio type
00504     * @returns string containing the radio type (MTSMC-H5, etc)
00505     */
00506     std::string getRadioTypeString();
00507 
00508     /** Enables GPS.
00509     * @returns true if GPS is enabled, false if GPS is not supported.
00510     */
00511     virtual bool GPSenable();
00512 
00513     /** Disables GPS.
00514     * @returns true if GPS is disabled, false if GPS does not disable.
00515     */
00516     virtual bool GPSdisable();
00517 
00518     /** Checks if GPS is enabled.
00519     * @returns true if GPS is enabled, false if GPS is disabled.
00520     */
00521     virtual bool GPSenabled();
00522         
00523     /** Get GPS position.
00524     * @returns a structure containing the GPS data field information.
00525     */
00526     virtual gpsData GPSgetPosition();
00527 
00528     /** Check for GPS fix.
00529     * @returns true if there is a fix and false otherwise.
00530     */
00531     virtual bool GPSgotFix();
00532             
00533 protected:
00534     MTSBufferedIO* io; //IO interface obect that the radio is accessed through.
00535     bool echoMode; //Specifies if the echo mode is currently enabled.
00536 
00537     bool gpsEnabled;    //true if GPS is enabled, else false.
00538         
00539     bool pppConnected; //Specifies if a PPP session is currently connected.
00540     std::string apn; //A string that holds the APN for the radio.
00541 
00542     Radio type; //The type of radio being used
00543 
00544     Mode socketMode; //The current socket Mode.
00545     bool socketOpened; //Specifies if a Socket is presently opened.
00546     bool socketCloseable; //Specifies is a Socket can be closed.
00547     unsigned int local_port; //Holds the local port for socket connections.
00548     std::string local_address; //Holds the local address for socket connections.
00549     unsigned int host_port; //Holds the remote port for socket connections.
00550     std::string host_address; //Holds the remote address for socket connections.
00551 
00552     DigitalIn* dcd; //Maps to the radio's dcd signal
00553     DigitalOut* dtr; //Maps to the radio's dtr signal
00554     DigitalOut* resetLine; //Maps to the radio's reset signal 
00555 };
00556 
00557 }
00558 
00559 #endif /* CELLULAR_H */