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.h
00001 /* Universal Socket Modem Interface Library 00002 * Copyright (c) 2013 Multi-Tech Systems 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #ifndef CELLULAR_H 00018 #define CELLULAR_H 00019 00020 #include "IPStack.h" 00021 #include "MTSBufferedIO.h" 00022 #include "mbed.h" 00023 #include <string> 00024 #include <vector> 00025 00026 namespace mts 00027 { 00028 00029 /** This is a class for communicating with a Multi-Tech Systems SocketModem iCell. The 00030 * SocketModem iCell is a family of carrier certified embedded cellular radio modules with 00031 * a common hardware footprint and AT command set for built in IP-stack functionality. 00032 * This class supports three main types of cellular radio interactions including: 00033 * configuration and status AT command processing, SMS processing, and TCP Socket 00034 * data connections. It should be noted that the radio can not process commands or 00035 * SMS messages while having an open data connection at the same time. The concurrent 00036 * capability may be added in a future release. This class also inherits from IPStack 00037 * providing a common set of commands for communication devices that have an onboard 00038 * IP Stack. It is also integrated with the standard mbed Sockets package and can therefore 00039 * be used seamlessly with clients and services built on top of this interface already within 00040 * the mbed library. 00041 * 00042 * All of the following examples use the Pin Names for the Freedom KL46Z board coupled with 00043 * the SocketModem Shield Arduino compatible board. Please chage Pin Names accordingly to 00044 * match your hardware configuration. It also assumes the use of RTS/CTS hardware handshaking 00045 * using GPIOs. To disable this you will need to change settings on the radio module and 00046 * and use the MTSSerial class instead of MTSSerialFlowControl. The default baud rate for the 00047 * cellular radio is 115200 bps. 00048 * 00049 * The following set of example code demonstrates how to send and receive configuration and 00050 * status AT commands with the radio, create a data connection and test it: 00051 * @code 00052 * #include "mbed.h" 00053 * #include "Cellular.h" 00054 * #include "MTSSerialFlowControl.h" 00055 * 00056 * using namespace mts; 00057 * 00058 * main() { 00059 * //Setup serial interface to radio 00060 * MTSSerialFlowControl* serial = new MTSSerialFlowControl(PTD3, PTD2, PTA12, PTC8); 00061 * serial->baud(115200); 00062 * 00063 * //Setup Cellular class 00064 * Cellular* cellular = Cellular::getInstance(); 00065 * cellular->init(serial, PTA4, PTC9); //DCD and DTR pins for KL46Z 00066 * 00067 * //Run status and configuration commands 00068 * printf("\n\r////Start Status and Configuration Commands////\n\r"); 00069 * printf("Command Test: %s\n\r", getCodeNames(cellular->test()).c_str()); 00070 * printf("Signal Strength: %d\n\r", cellular->getSignalStrength()); 00071 * printf("Registration State: %s\n\r", Cellular::getRegistrationNames(cellular->getRegistration()).c_str()); 00072 * printf("Send Basic Command (AT): %s\n\r", getCodeNames(cellular->sendBasicCommand("AT", 1000)).c_str()); 00073 * printf("Send Command (AT+CSQ): %s\n\r", cellular->sendCommand("AT+CSQ", 1000).c_str()); 00074 * 00075 * //Start Test 00076 * printf("\n\r////Start Network Connectivity Test////\n\r"); 00077 * printf("Set APN: %s\n\r", getCodeNames(cellular->setApn("wap.cingular")).c_str()); //Use APN from service provider!!! 00078 * 00079 * //Setup a data connection 00080 * printf("Attempting to Connect, this may take some time...\n\r"); 00081 * while (!cellular->connect()) { 00082 * printf("Failed to connect... Trying again.\n\r"); 00083 * wait(1); 00084 * } 00085 * printf("Connected to the Network!\n\r"); 00086 * 00087 * //Try pinging default server "8.8.8.8" 00088 * printf("Ping Valid: %s\n\r", cellular->ping() ? "true" : "false"); 00089 * 00090 * printf("End Program\n\r"); 00091 * } 00092 * @endcode 00093 * 00094 * The following set of example code demonstrates how process SMS messages: 00095 * @code 00096 * #include "mbed.h" 00097 * #include "Cellular.h" 00098 * #include "MTSSerialFlowControl.h" 00099 * 00100 * using namespace mts; 00101 * 00102 * main() { 00103 * //Setup serial interface to radio 00104 * MTSSerialFlowControl* serial = new MTSSerialFlowControl(PTD3, PTD2, PTA12, PTC8); 00105 * serial->baud(115200); 00106 * 00107 * //Setup Cellular class 00108 * Cellular* cellular = Cellular::getInstance(); 00109 * cellular->init(serial, PTA4, PTC9); //DCD and DTR pins for KL46Z 00110 * 00111 * //Start test 00112 * printf("AT Test: %s\n\r", getCodeNames(cellular->test()).c_str()); 00113 * 00114 * //Waiting for network registration 00115 * printf("Checking Network Registration, this may take some time...\n\r"); 00116 * while (cellular->getRegistration() != Cellular::REGISTERED) { 00117 * printf("Still waiting... Checking again.\n\r"); 00118 * wait(1); 00119 * } 00120 * printf("Connected to the Network!\n\r"); 00121 * 00122 * //Send SMS Message 00123 * Code code; 00124 * std::string sMsg("Hello from Multi-Tech MBED!"); 00125 * std::string sPhoneNum("16128675309"); //Put your phone number here or leave Jenny's... 00126 * 00127 * printf("Sending message [%s] to [%s]\r\n", sMsg.c_str(), sPhoneNum.c_str()); 00128 * code = cellular->sendSMS(sPhoneNum, sMsg); 00129 * 00130 * if(code != SUCCESS) { 00131 * printf("Error during SMS send [%s]\r\n", getCodeNames(code).c_str()); 00132 * } else { 00133 * printf("Success!\r\n"); 00134 * } 00135 * 00136 * //Try and receive SMS messages 00137 * //To determine your radio's phone number send yourself an SMS and check the received # 00138 * printf("Checking Received Messages\r\n"); 00139 * std::vector<Cellular::Sms> vSms = cellular->getReceivedSms(); 00140 * printf("\r\n"); 00141 * for(unsigned int i = 0; i < vSms.size(); i++) { 00142 * printf("[%d][%s][%s][%s]\r\n", i, vSms[i].timestamp.c_str(), 00143 * vSms[i].phoneNumber.c_str(), vSms[i].message.c_str()); 00144 * } 00145 * printf("End Program\n\r"); 00146 * } 00147 * @endcode 00148 * 00149 * The following set of example code demonstrates how to setup and use a TCP socket connection 00150 * using the native commands from this class: 00151 * @code 00152 * #include "mbed.h" 00153 * #include "Cellular.h" 00154 * #include "MTSSerialFlowControl.h" 00155 * 00156 * using namespace mts; 00157 * 00158 * main() { 00159 * //Define connection parameters 00160 * Code code; 00161 * const int TEST_PORT = 5798; 00162 * const std::string TEST_SERVER("204.26.122.96"); 00163 * 00164 * //Setup serial interface to radio 00165 * MTSSerialFlowControl* serial = new MTSSerialFlowControl(PTD3, PTD2, PTA12, PTC8); 00166 * serial->baud(115200); 00167 * 00168 * //Setup Cellular class 00169 * Cellular* cellular = Cellular::getInstance(); 00170 * cellular->init(serial, PTA4, PTC9); //DCD and DTR pins for KL46Z 00171 * 00172 * //Start test 00173 * printf("AT Test: %s\n\r", getCodeNames(cellular->test()).c_str()); 00174 * 00175 * printf("Setting APN\r\n"); 00176 * code = cellular->setApn("wap.cingular"); // Use from your service provider! 00177 * if(code == SUCCESS) { 00178 * printf("Success!\r\n"); 00179 * } else { 00180 * printf("Error during APN setup [%s]\r\n", getCodeNames(code).c_str()); 00181 * } 00182 * 00183 * //Setup a data connection 00184 * printf("Attempting to Connect, this may take some time...\n\r"); 00185 * while (!cellular->connect()) { 00186 * printf("Failed to connect... Trying again.\n\r"); 00187 * wait(1); 00188 * } 00189 * printf("Connected to the Network!\n\r"); 00190 * 00191 * printf("Opening a TCP Socket...\r\n"); 00192 * if(cellular->open(TEST_SERVER, TEST_PORT, IPStack::TCP)) { 00193 * printf("Success!\r\n"); 00194 * } else { 00195 * printf("Error during TCP socket open [%s:%d]\r\n", TEST_SERVER.c_str(), TEST_PORT); 00196 * } 00197 * 00198 * char data[] = "My Test Echo Message"; 00199 * int size = sizeof(data); 00200 * printf("WRITE: [%d] [%s]\r\n", size, data); 00201 * int bytesWritten = cellular->write(data, size, 10000); 00202 * if(bytesWritten == size) { 00203 * printf("Successfully wrote message!\r\n"); 00204 * } else { 00205 * printf("Failed to write message!\r\n"); 00206 * } 00207 * 00208 * printf("Waiting 5 seconds\r\n"); 00209 * wait(5); 00210 * 00211 * printf("Reading from socket for 10 seconds\r\n"); 00212 * char response[size]; 00213 * int bytesRead = cellular->read(response, size, 10000); 00214 * response[size - 1] = '\0'; 00215 * printf("READ: [%d] [%s]\r\n", bytesRead, response); 00216 * 00217 * //Check to see if echo was successful 00218 * if (strcmp(data, response) == 0) { 00219 * printf("Echo Successful!\n\r"); 00220 * } else { 00221 * printf("Echo failed!\n\r"); 00222 * } 00223 * 00224 * //Cleaning up the connection 00225 * printf("Closing socket: %s\r\n", cellular->close() ? "Success" : "Failure"); 00226 * printf("Disconnecting...\r\n"); 00227 * cellular->disconnect(); 00228 * printf("End Program\n\r"); 00229 * } 00230 * @endcode 00231 */ 00232 00233 class Cellular : virtual mts::IPStack 00234 { 00235 public: 00236 00237 /// An enumeration of radio registration states with a cell tower. 00238 enum Registration { 00239 NOT_REGISTERED, REGISTERED, SEARCHING, DENIED, UNKNOWN, ROAMING 00240 }; 00241 00242 /** This structure contains the data for an SMS message. 00243 */ 00244 struct Sms { 00245 /// Message Phone Number 00246 std::string phoneNumber; 00247 /// Message Body 00248 std::string message; 00249 /// Message Timestamp 00250 std::string timestamp; 00251 }; 00252 00253 /** Destructs a Cellular object and frees all related resources. 00254 */ 00255 ~Cellular(); 00256 00257 /** This static function is used to create or get a reference to a 00258 * Cellular object. Cellular uses the singleton pattern, which means 00259 * that you can only have one existing at a time. The first time you 00260 * call getInstance this method creates a new uninitialized Cellular 00261 * object and returns it. All future calls to this method will return 00262 * a reference to the instance created during the first call. Note that 00263 * you must call init on the returned instance before mnaking any other 00264 * calls. If using this class's bindings to any of the Socket package 00265 * classes like TCPSocketConnection, you must call this method and the 00266 * init method on the returned object first, before even creating the 00267 * other objects. 00268 * 00269 * @returns a reference to the single Cellular obect that has been created. 00270 */ 00271 static Cellular* getInstance(); 00272 00273 /** This method initializes the object with the underlying radio 00274 * interface to use. Note that this function MUST be called before 00275 * any other calls will function correctly on a Cellular object. Also 00276 * note that MTSBufferedIO is abstract, so you must use one of 00277 * its inherited classes like MTSSerial or MTSSerialFlowControl. 00278 * 00279 * @param io the buffered io interface that is attached to the cellular 00280 * radio. 00281 * @param DCD this is the dcd signal from the radio. If attached the 00282 * the pin must be passed in here for this class to operate correctly. 00283 * The default is not connected. 00284 * @param DTR this is the dtr signal from the radio. If attached the 00285 * the pin must be passed in here for this class to operate correctly. 00286 * The default is not connected. 00287 * @returns true if the init was successful, otherwise false. 00288 */ 00289 bool init(MTSBufferedIO* io, PinName DCD = NC, PinName DTR = NC); 00290 00291 // Radio link related commands 00292 /** This method establishes a data connection on the cellular radio. 00293 * Note that before calling you must have an activated radio and if 00294 * using a SIM card set the APN using the setApn method. The APN can 00295 * be obtained from your cellular service provider. 00296 * 00297 * @returns true if the connection was successfully established, otherwise 00298 * false on an error. 00299 */ 00300 virtual bool connect(); 00301 00302 /** This method is used to stop a previously established cellular data connection. 00303 */ 00304 virtual void disconnect(); 00305 00306 /** This method is used to check if the radio currently has a data connection 00307 * established. 00308 * 00309 * @returns true if a data connection exists, otherwise false. 00310 */ 00311 virtual bool isConnected(); 00312 00313 // TCP and UDP Socket related commands 00314 // For behavior of the following methods refer to IPStack.h documentation 00315 virtual bool bind(unsigned int port); 00316 virtual bool open(const std::string& address, unsigned int port, Mode mode); 00317 virtual bool isOpen(); 00318 virtual bool close(); 00319 virtual int read(char* data, int max, int timeout = -1); 00320 virtual int write(const char* data, int length, int timeout = -1); 00321 virtual unsigned int readable(); 00322 virtual unsigned int writeable(); 00323 00324 //Other 00325 /** A method to reset the Multi-Tech Socket Modem. This command brings down the 00326 * PPP link if it is up. After this function is called, at least 30 seconds should 00327 * be allowed for the cellular radio to come back up before any other Cellular 00328 * functions are called. 00329 */ 00330 virtual void reset(); 00331 00332 //Cellular Radio Specific 00333 /** A method for sending a generic AT command to the radio. Note that you cannot 00334 * send commands and have a data connection at the same time. 00335 * 00336 * @param command the command to send to the radio without the escape character. 00337 * @param timeoutMillis the time in millis to wait for a response before returning. 00338 * @param esc escape character to add at the end of the command, defaults to 00339 * carriage return (CR). Does not append any character if esc == 0. 00340 * @returns all data received from the radio after the command as a string. 00341 */ 00342 std::string sendCommand(const std::string& command, unsigned int timeoutMillis, char esc = CR); 00343 00344 /** A method for sending a basic AT command to the radio. A basic AT command is 00345 * one that simply has a response of either OK or ERROR without any other information. 00346 * Note that you cannot send commands and have a data connection at the same time. 00347 * 00348 * @param command the command to send to the radio without the escape character. 00349 * @param timeoutMillis the time in millis to wait for a response before returning. 00350 * @param esc escape character to add at the end of the command, defaults to 00351 * carriage return (CR). 00352 * @returns the standard Code enumeration. 00353 */ 00354 Code sendBasicCommand(const std::string& command, unsigned int timeoutMillis, char esc = CR); 00355 00356 /** This method is used to get the IP address of the device, which is determined 00357 * via DHCP by the cellular carrier. 00358 * 00359 * @returns the devices IP address. 00360 */ 00361 std::string getDeviceIP(); 00362 00363 /** A method for testing command access to the radio. This method sends the 00364 * command "AT" to the radio, which is a standard radio test to see if you 00365 * have command access to the radio. The function returns when it receives 00366 * the expected response from the radio. 00367 * 00368 * @returns the standard AT Code enumeration. 00369 */ 00370 Code test(); 00371 00372 /** A method for configuring command ehco capability on the radio. This command 00373 * sets whether sent characters are echoed back from the radio, in which case you 00374 * will receive back every command you send. 00375 * 00376 * @param state if true echo will be turned off, otherwise it will be turned on. 00377 * @returns the standard AT Code enumeration. 00378 */ 00379 Code echo(bool state); 00380 00381 /** A method for getting the signal strength of the radio. This method allows you to 00382 * get a value that maps to signal strength in dBm. Here 0-1 is Poor, 2-9 is Marginal, 00383 * 10-14 is Ok, 15-19 is Good, and 20+ is Excellent. If you get a result of 99 the 00384 * signal strength is not known or not detectable. 00385 * 00386 * @returns an integer representing the signal strength. 00387 */ 00388 int getSignalStrength(); 00389 00390 /** This method is used to check the registration state of the radio with the cell tower. 00391 * If not appropriatley registered with the tower you cannot make a cellular connection. 00392 * 00393 * @returns the registration state as an enumeration type. 00394 */ 00395 Registration getRegistration(); 00396 00397 /** This method is used to set the radios APN if using a SIM card. Note that the APN 00398 * must be set correctly before you can make a data connection. The APN for your SIM 00399 * can be obtained by contacting your cellular service provider. 00400 * 00401 * @param the APN as a string. 00402 * @returns the standard AT Code enumeration. 00403 */ 00404 Code setApn(const std::string& apn); 00405 00406 /** This method is used to set the DNS which enables the use of URLs instead 00407 * of IP addresses when making a socket connection. 00408 * 00409 * @param the DNS server address as a string in form xxx.xxx.xxx.xxx. 00410 * @returns the standard AT Code enumeration. 00411 */ 00412 Code setDns(const std::string& primary, const std::string& secondary = "0.0.0.0"); 00413 00414 /** This method is used test network connectivity by pinging a server. 00415 * 00416 * @param address the address of the server in format xxx.xxx.xxx.xxx. 00417 * @returns true if the ping was successful, otherwise false. 00418 */ 00419 bool ping(const std::string& address = "8.8.8.8"); 00420 00421 /** This method can be used to trade socket functionality for performance. 00422 * In order to enable a socket connection to be closed by the client side programtically, 00423 * this class must process all read and write data on the socket to guard the special 00424 * escape character used to close an open socket connection. It is recommened that you 00425 * use the default of true unless the overhead of these operations is too significant. 00426 * 00427 * @param enabled set to true if you want the socket closeable, otherwise false. The default 00428 * is true. 00429 * @returns the standard AT Code enumeration. 00430 */ 00431 Code setSocketCloseable(bool enabled = true); //ETX closes socket (ETX and DLE in payload are escaped with DLE) 00432 00433 /** This method is used to send an SMS message. Note that you cannot send an 00434 * SMS message and have a data connection open at the same time. 00435 * 00436 * @param phoneNumber the phone number to send the message to as a string. 00437 * @param message the text message to be sent. 00438 * @returns the standard AT Code enumeration. 00439 */ 00440 Code sendSMS(const std::string& phoneNumber, const std::string& message); 00441 00442 /** This method is used to send an SMS message. Note that you cannot send an 00443 * SMS message and have a data connection open at the same time. 00444 * 00445 * @param sms an Sms struct that contains all SMS transaction information. 00446 * @returns the standard AT Code enumeration. 00447 */ 00448 Code sendSMS(const Sms& sms); 00449 00450 /** This method retrieves all of the SMS messages currently available for 00451 * this phone number. 00452 * 00453 * @returns a vector of existing SMS messages each as an Sms struct. 00454 */ 00455 std::vector<Cellular::Sms> getReceivedSms(); 00456 00457 /** This method can be used to remove/delete all received SMS messages 00458 * even if they have never been retrieved or read. 00459 * 00460 * @returns the standard AT Code enumeration. 00461 */ 00462 Code deleteAllReceivedSms(); 00463 00464 /** This method can be used to remove/delete all received SMS messages 00465 * that have been retrieved by the user through the getReceivedSms method. 00466 * Messages that have not been retrieved yet will be unaffected. 00467 * 00468 * @returns the standard AT Code enumeration. 00469 */ 00470 Code deleteOnlyReceivedReadSms(); 00471 00472 /** A static method for getting a string representation for the Registration 00473 * enumeration. 00474 * 00475 * @param code a Registration enumeration. 00476 * @returns the enumeration name as a string. 00477 */ 00478 static std::string getRegistrationNames(Registration registration); 00479 00480 private: 00481 static Cellular* instance; //Static pointer to the single Cellular object. 00482 00483 MTSBufferedIO* io; //IO interface obect that the radio is accessed through. 00484 bool echoMode; //Specifies if the echo mode is currently enabled. 00485 00486 bool pppConnected; //Specifies if a PPP session is currently connected. 00487 std::string apn; //A string that holds the APN for the radio. 00488 00489 Mode mode; //The current socket Mode. 00490 bool socketOpened; //Specifies if a Socket is presently opened. 00491 bool socketCloseable; //Specifies is a Socket can be closed. 00492 unsigned int local_port; //Holds the local port for socket connections. 00493 std::string local_address; //Holds the local address for socket connections. 00494 unsigned int host_port; //Holds the remote port for socket connections. 00495 std::string host_address; //Holds the remote address for socket connections. 00496 DigitalIn* dcd; //Maps to the radios dcd signal 00497 DigitalOut* dtr; //Maps to the radios dtr signal 00498 00499 Cellular(); //Private constructor, use the getInstance() method. 00500 Cellular(MTSBufferedIO* io); //Private constructor, use the getInstance() method. 00501 }; 00502 00503 } 00504 00505 #endif /* CELLULAR_H */
Generated on Tue Jul 12 2022 21:46:23 by 1.7.2