Cellular library for MTS Socket Modem Arduino Shield devices from Multi-Tech Systems
Dependents: mtsas mtsas mtsas mtsas
Revision 26:2b769ed8de4f, committed 2014-06-26
- Comitter:
- Vanger
- Date:
- Thu Jun 26 21:12:37 2014 +0000
- Parent:
- 24:32d29cdfc1fa
- Child:
- 27:ec44d5a9544f
- Commit message:
- Made setApn() a pure virtual in Cellular.; Implemented setApn in both UIP and EasyIP; Implemented connect(), disconnect(), and ping() in EasyIP; Uncommented cell instantiation for EasyIP type models in CellularFactory
Changed in this revision
--- a/Cellular/Cellular.cpp Mon Jun 23 14:33:01 2014 +0000 +++ b/Cellular/Cellular.cpp Thu Jun 26 21:12:37 2014 +0000 @@ -132,21 +132,8 @@ return UNKNOWN; } -Code Cellular::setApn(const std::string& apn) -{ - if (type == MTSMC_H5_IP || type == MTSMC_H5 || type == MTSMC_G3) { - Code code = sendBasicCommand("AT#APNSERV=\"" + apn + "\"", 1000); - if (code != MTS_SUCCESS) { - return code; - } - this->apn = apn; - return code; - } else { - logInfo("CDMA radios don't need an APN"); - return MTS_SUCCESS; - } -} - +//Removed setAPN to be implemented in the individual cellular classes, +//as UIP and EasyIP implement it in different ways. Code Cellular::setDns(const std::string& primary, const std::string& secondary) {
--- a/Cellular/Cellular.h Mon Jun 23 14:33:01 2014 +0000 +++ b/Cellular/Cellular.h Thu Jun 26 21:12:37 2014 +0000 @@ -197,8 +197,8 @@ */ virtual bool init(MTSBufferedIO* io); - /** - * + /** Sets up the physical connection pins + * (DTR,DCD, and RESET obviously) */ bool configureSignals(unsigned int DCD = NC, unsigned int DTR = NC, unsigned int RESET = NC); @@ -234,7 +234,7 @@ * @param the APN as a string. * @returns the standard AT Code enumeration. */ - virtual Code setApn(const std::string& apn); + virtual Code setApn(const std::string& apn)=0; /** This method is used to set the DNS which enables the use of URLs instead * of IP addresses when making a socket connection.
--- a/Cellular/CellularFactory.cpp Mon Jun 23 14:33:01 2014 +0000 +++ b/Cellular/CellularFactory.cpp Thu Jun 26 21:12:37 2014 +0000 @@ -35,14 +35,15 @@ wait(1); } - /* AT#VVERSION is a IUP specific AT command + /* AT#VVERSION is a UIP specific AT command * if we get an error response, we're not using a UIP board */ reply = sendCommand(io, "AT#VVERSION", 2000); - if (reply.find("error") != string::npos) { + if (reply.find("ERROR") != string::npos) { uip = false; } else { uip = true; } + if (uip && model.find("HE910") != string::npos) { type = Cellular::MTSMC_H5_IP; @@ -56,7 +57,7 @@ type = Cellular::MTSMC_C2_IP; logDebug("radio model: CE910"); cell = new UIP(type); - /* + } else if (model.find("HE910") != string::npos) { type = Cellular::MTSMC_H5; logDebug("radio model: HE910"); @@ -73,7 +74,7 @@ type = Cellular::MTSMC_C2; logDebug("radio model: CE910"); cell = new EasyIP(type); - */ + } else { logError("cannot continue - could not determine radio type"); return NULL;
--- a/Cellular/CellularFactory.h Mon Jun 23 14:33:01 2014 +0000 +++ b/Cellular/CellularFactory.h Thu Jun 26 21:12:37 2014 +0000 @@ -2,7 +2,7 @@ #define CELLULARFACTORY_H #include "UIP.h" -//#include "EasyIP.h" +#include "EasyIP.h" #include "MTSBufferedIO.h" namespace mts {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Cellular/EasyIP.cpp Thu Jun 26 21:12:37 2014 +0000 @@ -0,0 +1,265 @@ +// This is a template from UIP.cpp for now, will modify code and implement it as I go + + + +#include "mbed.h" +#include "EasyIP.h" +#include "MTSText.h" +#include "MTSLog.h" +#include "CellUtils.h" + + + +using namespace mts; + +EasyIP::EasyIP(Radio type) +{ + //Not sure how the construction process is done, + //but assuming it works for both EasyIP and UIP the same way. + this->type = type; + io = NULL; + dcd = NULL; + dtr = NULL; + resetLine = NULL; + echoMode = true; + pppConnected = false; + socketMode = TCP; + socketOpened = false; + socketCloseable = true; + local_port = 0; + local_address = ""; + host_port = 0; +} + +EasyIP::~EasyIP() +{ + //Same reasoning for the destructor as the constructor, + //assuming it works for UIP, it will work for EasyIP + if (dtr != NULL) { + dtr->write(1); + } + + delete dcd; + delete dtr; + delete resetLine; +} + +//Initializes the MTS IO Buffer +bool EasyIP::init(MTSBufferedIO* io) +{ + if (! Cellular::init(io)) { + return false; + } + + logDebug("radio type: %s", Cellular::getRadioNames(type).c_str()); + return true; +} + +bool EasyIP::connect() +{ + //Check if socket is open + //flag stored in Cellular.h + if(socketOpened) { + return true; + } + + //Check if already connected + //by calling the function isConnected() in EasyIP.cpp + if(isConnected()) { + return true; + } + //Create an mbed timer object + Timer tmr; + + //Check Registration: AT+CREG? == 0,1 + //(Does the AT command inside Cellular class) + tmr.start(); + do { + Registration registration = getRegistration(); + if(registration != REGISTERED) { + logTrace("Not Registered [%d] ... waiting", (int)registration); + wait(1); + } else { + break; + } + } while(tmr.read() < 30); + + //Check RSSI: AT+CSQ + //Does the command inside Cellular + tmr.reset(); + do { + int rssi = getSignalStrength(); + logDebug("Signal strength: %d", rssi); + if(rssi == 99) { + logTrace("No Signal ... waiting"); + wait(1); + } else { + break; + } + } while(tmr.read() < 30); + + //AT#CONNECTIONSTART: Make a PPP connection + if (type == MTSMC_H5 || type == MTSMC_G3) { + logDebug("Making PPP Connection Attempt. APN[%s]", apn.c_str()); + } else { + logDebug("Making PPP Connection Attempt"); + } + //The main thing going on; Sends the AT command to start a connection + //Assuming context is already stored in the modem...If not, will need to set context from classes/data + std::string pppResult = sendCommand("AT#SGACT=1,1", 120000); + + if(pppResult.find("OK") != std::string::npos) { + std::vector<std::string> parts = Text::split(pppResult, "\r\n"); + if(parts.size() >= 2) { + parts = Text::split(parts[1], " "); + local_address = parts[1]; + } + logInfo("PPP Connection Established: IP[%s]", local_address.c_str()); + pppConnected = true; + + } else { + pppConnected = false; + } + + return pppConnected; +} + +void EasyIP::disconnect() +{ + //AT#SGACT=1,0: Close a PPP connection + logDebug("Closing PPP Connection"); + + if(socketOpened) { + close(); //Calls another EasyIP + //function to close socket before disconnect + } + //Sends AT#SGACT=1,0 command + + if(sendBasicCommand("AT#SGACT=1,0", 10000) == MTS_SUCCESS) { + logDebug("Successfully closed PPP Connection"); + } else { + logError("Closing PPP Connection. Continuing ..."); + } + pppConnected = false; +} +//++++++++++++++++++++++++++++++++++++++++++++ +bool EasyIP::isConnected() +{ + + return pppConnected; +} +//Binds the socket to a specific port if able +bool EasyIP::bind(unsigned int port) +{ + + + return true; +} +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +bool EasyIP::open(const std::string& address, unsigned int port, Mode mode) +{ + + return socketOpened; +} +//++++++++++++++++++++++++++++++++++++++++++++++++++++++ +bool EasyIP::isOpen() +{ + + return socketOpened; +} +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +bool EasyIP::close() +{ + + return true; +} + +int EasyIP::read(char* data, int max, int timeout) +{ + + return 1; +} + +int EasyIP::write(const char* data, int length, int timeout) +{ + + return 1; +} + +unsigned int EasyIP::readable() +{ + + return io->readable(); +} + +unsigned int EasyIP::writeable() +{ + + + return io->writeable(); +} + +bool EasyIP::setDeviceIP(std::string address) +{ + if (address.compare("DHCP") == 0) { + return true; + } else { + logWarning("Radio does not support static IPs, using DHCP.\n\r"); + return false; + } +} + +Code EasyIP::setApn(const std::string& apn) +{ + if (type == MTSMC_H5 || type == MTSMC_G3) { + //Set IP,PPP,IPv6 + Code code = sendBasicCommand("AT+CGDCONT=1,PPP," + apn, 1000); + if (code != MTS_SUCCESS) { + return code; + } + this->apn = apn; + return code; //This will return MTS_SUCCESS + } else { + logInfo("CDMA radios don't need an APN"); + return MTS_SUCCESS; + } +} +//++++++++++++++++++++++++++++++++++++++++++++++++++ +void EasyIP::reset() +{ +} + +std::string EasyIP::getDeviceIP() +{ + return local_address; +} + +//Turns off echo when it receives a 1, turns on when it receives anything else +Code EasyIP::echo(bool state) +{ + return MTS_SUCCESS; +} + +bool EasyIP::ping(const std::string& address) +{ + char buffer[256] = {0}; + std::string response; + + //Sends "PINGNUM" of pings to "address" with a timeout of "PINGDELAY" + //AT command takes pingdelay as units of 100ms, so seconds would be 10 times bigger + //Concatenate parameters into one string + sprintf(buffer, "AT#PING=%s,%d,32,%d", address.c_str(), PINGNUM, (10*PINGDELAY)); + response = sendCommand(buffer,PINGDELAY*10000); + if(response.find("OK") != std::string::npos) { + //Not sure if I need a wait here, or if it is included in the sendcommand wait time + return true; + } + + + return false; +} + +Code EasyIP::setSocketCloseable(bool enabled) +{ + return MTS_SUCCESS; +}
--- a/Cellular/EasyIP.h Mon Jun 23 14:33:01 2014 +0000 +++ b/Cellular/EasyIP.h Thu Jun 26 21:12:37 2014 +0000 @@ -1,4 +1,97 @@ #ifndef SMC_H #define SMC_H +#include <string> +#include <vector> + +#include "MTSBufferedIO.h" +#include "Cellular.h" + +namespace mts +{ +/** This is a class for communicating without a Multi-Tech Systems SocketModem iCell. Instead, +* it uses the hayes command set to implement the same commands and functions as the UIP class. +* (See the UIP class and documentation, "UIP.h") +* This class supports three main types of cellular radio interactions including: +* configuration and status AT command processing, SMS processing, and TCP 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. +* The default baud rate for the cellular radio is 115200 bps. +*/ +class EasyIP : public Cellular //Inherits from Cellular. +{ +public: +/** This static function is used to create or get a reference to a + * Cellular object. Cellular uses the singleton pattern, which means + * that you can only have one existing at a time. The first time you + * call getInstance this method creates a new uninitialized Cellular + * object and returns it. All future calls to this method will return + * a reference to the instance created during the first call. Note that + * you must call init on the returned instance before mnaking any other + * calls. If using this class's bindings to any of the Socket package + * classes like TCPSocketConnection, you must call this method and the + * init method on the returned object first, before even creating the + * other objects. + * + * @returns a reference to the single Cellular obect that has been created. + */ + EasyIP(Radio type); + + /** Destructs a Cellular object and frees all related resources. + */ + ~EasyIP(); + + virtual bool init(MTSBufferedIO* io); + + // Wifi connection based commands derived from CommInterface.h + virtual bool connect(); + virtual void disconnect(); + virtual bool isConnected(); + virtual void reset(); + + // TCP and UDP Socket related commands + // For behavior of the following methods refer to IPStack.h documentation + 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); //-1 times for no timeout? + virtual int write(const char* data, int length, int timeout = -1); + virtual unsigned int readable(); + virtual unsigned int writeable(); + virtual bool ping(const std::string& address = "8.8.8.8"); //Can this default address be different? + virtual std::string getDeviceIP(); + virtual bool setDeviceIP(std::string address = "DHCP");//What does this do? Run DHCP to configure the IP? + + //Sets the APN, also sets mode to IP, might need to change + virtual Code setApn(const std::string& apn); + /** 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); + + /** This method can be used to trade socket functionality for performance. + * In order to enable a socket connection to be closed by the client side programtically, + * this class must process all read and write data on the socket to guard the special + * escape character used to close an open socket connection. It is recommened that you + * use the default of true unless the overhead of these operations is too significant. + * + * @param enabled set to true if you want the socket closeable, otherwise false. The default + * is true. + * @returns the standard AT Code enumeration. + */ + Code setSocketCloseable(bool enabled = true); //ETX closes socket (ETX and DLE in payload are escaped with DLE) +}; + +} + #endif
--- a/Cellular/UIP.cpp Mon Jun 23 14:33:01 2014 +0000 +++ b/Cellular/UIP.cpp Thu Jun 26 21:12:37 2014 +0000 @@ -90,9 +90,10 @@ logDebug("Making PPP Connection Attempt"); } std::string pppResult = sendCommand("AT#CONNECTIONSTART", 120000); - std::vector<std::string> parts = Text::split(pppResult, "\r\n"); + if(pppResult.find("Ok_Info_GprsActivation") != std::string::npos) { + std::vector<std::string> parts = Text::split(pppResult, "\r\n"); if(parts.size() >= 2) { local_address = parts[1]; } @@ -165,6 +166,7 @@ return pppConnected; } + bool UIP::bind(unsigned int port) { if(socketOpened) { @@ -528,6 +530,21 @@ } } +Code UIP::setApn(const std::string& apn) +{ + if (type == MTSMC_H5_IP) { + Code code = sendBasicCommand("AT#APNSERV=\"" + apn + "\"", 1000); + if (code != MTS_SUCCESS) { + return code; + } + this->apn = apn; + return code; //This will return MTS_SUCCESS + } else { + logInfo("CDMA radios don't need an APN"); + return MTS_SUCCESS; + } +} + void UIP::reset() { disconnect();
--- a/Cellular/UIP.h Mon Jun 23 14:33:01 2014 +0000 +++ b/Cellular/UIP.h Thu Jun 26 21:12:37 2014 +0000 @@ -75,6 +75,9 @@ virtual bool ping(const std::string& address = "8.8.8.8"); virtual std::string getDeviceIP(); virtual bool setDeviceIP(std::string address = "DHCP"); + + /** A method for setting the APN */ + virtual Code setApn(const std::string& apn); /** 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