Axeda Ready Demo for Freescale FRDM-KL46Z as accident alert system

Dependencies:   FRDM_MMA8451Q KL46Z-USBHost MAG3110 SocketModem TSI mbed FATFileSystem

Fork of AxedaGo-Freescal_FRDM-KL46Z revert by Axeda Corp

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Cellular.cpp Source File

Cellular.cpp

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 
00018 #include "Cellular.h"
00019 #include "MTSText.h"
00020 #include "MTSSerial.h"
00021 
00022 using namespace mts;
00023 
00024 Cellular* Cellular::instance = NULL;
00025 
00026 Cellular* Cellular::getInstance()
00027 {
00028     if(instance == NULL) {
00029         instance = new Cellular(NULL);
00030     }
00031     return instance;
00032 }
00033 
00034 Cellular::Cellular(MTSBufferedIO* io)
00035     : io(io)
00036     , echoMode(true)
00037     , pppConnected(false)
00038     , mode(TCP)
00039     , socketOpened(false)
00040     , socketCloseable(true)
00041     , local_port(0)
00042     , local_address("")
00043     , host_port(0)
00044     , dcd(NULL)
00045     , dtr(NULL)
00046 {
00047 }
00048 
00049 Cellular::~Cellular()
00050 {
00051     if (dtr != NULL) {
00052         dtr->write(1);
00053     }
00054 
00055     delete dcd;
00056     delete dtr;
00057 }
00058 
00059 bool Cellular::init(MTSBufferedIO* io, PinName DCD, PinName DTR)
00060 {
00061     if (io == NULL) {
00062         return false;
00063     }
00064 
00065     if(dcd) {
00066         delete dcd;
00067         dcd = NULL;
00068     }
00069     if(dtr) {
00070         delete dtr;
00071         dtr = NULL;
00072     }
00073 
00074     if (DCD != NC) {
00075         // the radio will raise and lower this line
00076         dcd = new DigitalIn(DCD); //PTA4 - KL46
00077     }
00078     if (DTR != NC) {
00079         dtr = new DigitalOut(DTR); //PTC9 - KL46
00080         /* This line should be lowered when we want to talk to the radio and raised when we're done
00081         for now we will lower it in the constructor and raise it in the destructor
00082         */
00083         dtr->write(0);
00084     }
00085     instance->io = io;
00086     
00087     test();
00088     // Reset radio to make sure it's in a good state and wait for it to come back
00089     reset();
00090     test();
00091     
00092     return SUCCESS;
00093 }
00094 
00095 
00096 bool Cellular::connect()
00097 {
00098     //Check if socket is open
00099     if(socketOpened) {
00100         return true;
00101     }
00102 
00103     //Check if already connected
00104     if(isConnected()) {
00105         return true;
00106     }
00107 
00108     Timer tmr;
00109 
00110     //Check Registration: AT+CREG? == 0,1
00111     tmr.start();
00112     do {
00113         Registration registration = getRegistration();
00114         if(registration != REGISTERED) {
00115             printf("[WARNING] Not Registered [%d] ... waiting\r\n", (int)registration);
00116             wait(1);
00117         } else {
00118             break;
00119         }
00120     } while(tmr.read() < 30);
00121 
00122     //Check RSSI: AT+CSQ
00123     tmr.reset();
00124     do {
00125         int rssi = getSignalStrength();
00126         printf("[DEBUG] Signal strength: %d\r\n", rssi);
00127         if(rssi == 99) {
00128             printf("[WARNING] No Signal ... waiting\r\n");
00129             wait(1);
00130         } else {
00131             break;
00132         }
00133     } while(tmr.read() < 30);
00134 
00135     //AT#CONNECTIONSTART: Make a PPP connection
00136     printf("[DEBUG] Making PPP Connection Attempt. APN[%s]\r\n", apn.c_str());
00137     std::string pppResult = sendCommand("AT#CONNECTIONSTART", 120000);
00138     std::vector<std::string> parts = Text::split(pppResult, "\r\n");
00139 
00140     if(pppResult.find("Ok_Info_GprsActivation") != std::string::npos) {
00141         if(parts.size() >= 2) {
00142             local_address = parts[1];
00143         }
00144         printf("[INFO] PPP Connection Established: IP[%s]\r\n", local_address.c_str());
00145         pppConnected = true;
00146 
00147     } else {
00148         pppConnected = false;
00149     }
00150 
00151     return pppConnected;
00152 }
00153 
00154 void Cellular::disconnect()
00155 {
00156     //AT#CONNECTIONSTOP: Close a PPP connection
00157     printf("[DEBUG] Closing PPP Connection\r\n");
00158 
00159     if(socketOpened) {
00160         close();
00161     }
00162 
00163     Code code = sendBasicCommand("AT#CONNECTIONSTOP", 10000);
00164     if(code == SUCCESS) {
00165         printf("[DEBUG] Successfully closed PPP Connection\r\n");
00166     } else {
00167         printf("[ERROR] Closing PPP Connection [%d].  Continuing ...\r\n", (int)code);
00168     }
00169 
00170     pppConnected = false;
00171 }
00172 
00173 bool Cellular::isConnected()
00174 {
00175     //1) Check if APN was set
00176     if(apn.size() == 0) {
00177         printf("[DEBUG] APN is not set\r\n");
00178         return false;
00179     }
00180 
00181     //1) Check that we do not have a live connection up
00182     if(socketOpened) {
00183         printf("[DEBUG] Socket is opened\r\n");
00184         return true;
00185     }
00186     //2) Query the radio
00187     std::string result = sendCommand("AT#VSTATE", 3000);
00188     if(result.find("CONNECTED") != std::string::npos) {
00189         if(pppConnected == false) {
00190             printf("[WARNING] Internal PPP state tracking differs from radio (DISCONNECTED:CONNECTED)\r\n");
00191         }
00192         pppConnected = true;
00193     } else {
00194         if(pppConnected == true) {
00195             //Find out what state is
00196             size_t pos = result.find("STATE:");
00197             if(pos != std::string::npos) {
00198                 result = Text::getLine(result, pos + sizeof("STATE:"), pos);
00199                 printf("[WARNING] Internal PPP state tracking differs from radio (CONNECTED:%s)\r\n", result.c_str());
00200             } else {
00201                 printf("[ERROR] Unable to parse radio state: [%s]\r\n", result.c_str());
00202             }
00203 
00204         }
00205         pppConnected = false;
00206     }
00207 
00208     return pppConnected;
00209 }
00210 
00211 bool Cellular::bind(unsigned int port)
00212 {
00213     if(socketOpened) {
00214         printf("[ERROR] socket is open. Can not set local port\r\n");
00215         return false;
00216     }
00217     if(port > 65535) {
00218         printf("[ERROR] port out of range (0-65535)\r\n");
00219         return false;
00220     }
00221     local_port = port;
00222     return true;
00223 }
00224 
00225 bool Cellular::open(const std::string& address, unsigned int port, Mode mode)
00226 {
00227     char buffer[256] = {0};
00228     Code portCode, addressCode;
00229 
00230     //1) Check that we do not have a live connection up
00231     if(socketOpened) {
00232         //Check that the address, port, and mode match
00233         if(host_address != address || host_port != port || this->mode != mode) {
00234             if(this->mode == TCP) {
00235                 printf("[ERROR] TCP socket already opened [%s:%d]\r\n", host_address.c_str(), host_port);
00236             } else {
00237                 printf("[ERROR] UDP socket already opened [%s:%d]\r\n", host_address.c_str(), host_port);
00238             }
00239             return false;
00240         }
00241 
00242         printf("[DEBUG] Socket already opened\r\n");
00243         return true;
00244     }
00245 
00246     //2) Check Parameters
00247     if(port > 65535) {
00248         printf("[ERROR] port out of range (0-65535)\r\n");
00249         return false;
00250     }
00251 
00252     //3) Check PPP connection
00253     if(!isConnected()) {
00254         printf("[ERROR] PPP not established.  Attempting to connect\r\n");
00255         if(!connect()) {
00256             printf("[ERROR] PPP connection failed\r\n");
00257             return false;
00258         } else {
00259             printf("[DEBUG] PPP connection established\r\n");
00260         }
00261     }
00262 
00263     //Set Local Port
00264     if(local_port != 0) {
00265         //Attempt to set local port
00266         sprintf(buffer, "AT#OUTPORT=%d", local_port);
00267         Code code = sendBasicCommand(buffer, 1000);
00268         if(code != SUCCESS) {
00269             printf("[WARNING] Unable to set local port (%d) [%d]\r\n", local_port, (int) code);
00270         }
00271     }
00272 
00273     //Set TCP/UDP parameters
00274     if(mode == TCP) {
00275         if(socketCloseable) {
00276             Code code = sendBasicCommand("AT#DLEMODE=1,1", 1000);
00277             if(code != SUCCESS) {
00278                 printf("[WARNING] Unable to set socket closeable [%d]\r\n", (int) code);
00279             }
00280         }
00281         sprintf(buffer, "AT#TCPPORT=1,%d", port);
00282         portCode = sendBasicCommand(buffer, 1000);
00283         addressCode = sendBasicCommand("AT#TCPSERV=1,\"" + address + "\"", 1000);
00284     } else {
00285         if(socketCloseable) {
00286             Code code = sendBasicCommand("AT#UDPDLEMODE=1", 1000);
00287             if(code != SUCCESS) {
00288                 printf("[WARNING] Unable to set socket closeable [%d]\r\n", (int) code);
00289             }
00290         }
00291         sprintf(buffer, "AT#UDPPORT=%d", port);
00292         portCode = sendBasicCommand(buffer, 1000);
00293         addressCode = sendBasicCommand("AT#UDPSERV=\"" + address + "\"", 1000);
00294     }
00295 
00296     if(portCode == SUCCESS) {
00297         host_port = port;
00298     } else {
00299         printf("[ERROR] Host port could not be set\r\n");
00300     }
00301 
00302     if(addressCode == SUCCESS) {
00303         host_address = address;
00304     } else {
00305         printf("[ERROR] Host address could not be set\r\n");
00306     }
00307 
00308     // Try and Connect
00309     std::string sMode;
00310     std::string sOpenSocketCmd;
00311     if(mode == TCP) {
00312         sOpenSocketCmd = "AT#OTCP=1";
00313         sMode = "TCP";
00314     } else {
00315         sOpenSocketCmd = "AT#OUDP";
00316         sMode = "UDP";
00317     }
00318 
00319     string response = sendCommand(sOpenSocketCmd, 30000);
00320     if (response.find("Ok_Info_WaitingForData") != string::npos) {
00321         printf("[INFO] Opened %s Socket [%s:%d]\r\n", sMode.c_str(), address.c_str(), port);
00322         socketOpened = true;
00323     } else {
00324         printf("[WARNING] Unable to open %s Socket [%s:%d]\r\n", sMode.c_str(),  address.c_str(), port);
00325         socketOpened = false;
00326     }
00327 
00328     return socketOpened;
00329 }
00330 
00331 bool Cellular::isOpen()
00332 {
00333     if(io->readable()) {
00334         printf("[DEBUG] Assuming open, data available to read.\n\r");
00335         return true;
00336     }
00337     return socketOpened;
00338 }
00339 
00340 bool Cellular::close()
00341 {
00342     if(io == NULL) {
00343         printf("[ERROR] MTSBufferedIO not set\r\n");
00344         return false;
00345     }
00346 
00347     if(!socketOpened) {
00348         printf("[WARNING] Socket close() called, but socket was not open\r\n");
00349         return true;
00350     }
00351 
00352     if(!socketCloseable) {
00353         printf("[ERROR] Socket is not closeable\r\n");
00354         return false;
00355     }
00356 
00357 
00358 
00359     if(io->write(ETX, 1000) != 1) {
00360         printf("[ERROR] Timed out attempting to close socket\r\n");
00361         return false;
00362     }
00363 
00364     Timer tmr;
00365     int counter = 0;
00366     char tmp[256];
00367     tmr.start();
00368     do {
00369         if(socketOpened == false) {
00370             break;
00371         }
00372         read(tmp, 256, 1000);
00373     } while(counter++ < 10);
00374 
00375     io->rxClear();
00376     io->txClear();
00377 
00378     socketOpened = false;
00379     return true;
00380 }
00381 
00382 int Cellular::read(char* data, int max, int timeout)
00383 {
00384     if(io == NULL) {
00385         printf("[ERROR] MTSBufferedIO not set\r\n");
00386         return -1;
00387     }
00388 
00389     //Check that nothing is in the rx buffer
00390     if(!socketOpened && !io->readable()) {
00391         printf("[ERROR] Socket is not open\r\n");
00392         return -1;
00393     }
00394 
00395     int bytesRead = 0;
00396 
00397     if(timeout >= 0) {
00398         bytesRead = io->read(data, max, static_cast<unsigned int>(timeout));
00399     } else {
00400         bytesRead = io->read(data, max);
00401     }
00402 
00403     if(bytesRead > 0 && socketCloseable) {
00404         //Remove escape characters
00405         int index = 0;
00406         bool escapeFlag = false;
00407         for(int i = 0; i < bytesRead; i++) {
00408             if(data[i] == DLE || data[i] == ETX) {
00409                 if(escapeFlag == true) {
00410                     //This character has been escaped
00411                     escapeFlag = false;
00412                 } else if(data[bytesRead] == DLE) {
00413                     //Found escape character
00414                     escapeFlag = true;
00415                     continue;
00416                 } else {
00417                     //ETX sent without escape -> Socket closed
00418                     printf("[INFO] Read ETX character without DLE escape. Socket closed\r\n");
00419                     socketOpened = false;
00420                     continue;
00421                 }
00422             }
00423 
00424             if(index != i) {
00425                 data[index] = data[i];
00426             }
00427             index++;
00428         }
00429         bytesRead = index;
00430     }
00431 
00432     //Scan for socket closed message
00433     for(size_t i = 0; i < bytesRead; i++) {
00434         if(data[i] == 'O') {
00435             if(strstr(&data[i], "Ok_Info_SocketClosed")) {
00436                 printf("[INFO] Found socket closed message. Socket closed\r\n");
00437                 //Close socket and Cut Off End of Message
00438                 socketOpened = false;
00439                 data[i] = '\0';
00440                 bytesRead = i;
00441                 break;
00442             }
00443         }
00444     }
00445     return bytesRead;
00446 }
00447 
00448 int Cellular::write(const char* data, int length, int timeout)
00449 {
00450     if(io == NULL) {
00451         printf("[ERROR] MTSBufferedIO not set\r\n");
00452         return -1;
00453     }
00454 
00455     if(!socketOpened) {
00456         printf("[ERROR] Socket is not open\r\n");
00457         return -1;
00458     }
00459 
00460     //In order to avoid allocating another buffer, capture indices of
00461     //characters to escape during write
00462     int specialWritten = 0;
00463     std::vector<int> vSpecial;
00464     if(socketCloseable) {
00465         for(int i = 0; i < length; i++) {
00466             if(data[i] == ETX || data[i] == DLE) {
00467                 //Push back index of special characters
00468                 vSpecial.push_back(i);
00469             }
00470         }
00471     }
00472 
00473     int bytesWritten = 0;
00474     if(timeout >= 0) {
00475         Timer tmr;
00476         tmr.start();
00477         do {
00478             int available = io->writeable();
00479             if (available > 0) {
00480                 if(specialWritten < vSpecial.size()) {
00481                     //Check if current index is at a special character
00482                     if(bytesWritten == vSpecial[specialWritten]) {
00483                         if(available < 2) {
00484                             //Requires at least two bytes of space
00485                             wait(0.05);
00486                             continue;
00487                         }
00488                         //Ready to write special character
00489                         if(io->write(DLE)) {
00490                             specialWritten++;
00491                             if(io->write(data[bytesWritten])) {
00492                                 bytesWritten++;
00493                             }
00494                         } else {
00495                             //Unable to write escape character, try again next round
00496                             wait(0.05);
00497                         }
00498                     } else {
00499                         //We want to write all the way up to the next special character
00500                         int relativeIndex = vSpecial[specialWritten] - bytesWritten;
00501                         int size = MIN(available, relativeIndex);
00502                         bytesWritten += io->write(&data[bytesWritten], size);
00503                     }
00504                 } else {
00505                     int size = MIN(available, length - bytesWritten);
00506                     bytesWritten += io->write(&data[bytesWritten], size);
00507                 }
00508             } else {
00509                 wait(0.05);
00510             }
00511         } while (tmr.read_ms() <= timeout && bytesWritten < length);
00512     } else {
00513         for(int i = 0; i < vSpecial.size(); i++) {
00514             //Write up to the special character, then write the special character
00515             int size = vSpecial[i] - bytesWritten;
00516             int currentWritten = io->write(&data[bytesWritten], size);
00517             bytesWritten += currentWritten;
00518             if(currentWritten != size) {
00519                 //Failed to write up to the special character.
00520                 return bytesWritten;
00521             }
00522             if(io->write(DLE) && io->write(data[bytesWritten])) {
00523                 bytesWritten++;
00524             } else {
00525                 //Failed to write the special character.
00526                 return bytesWritten;
00527             }
00528         }
00529 
00530         bytesWritten = io->write(&data[bytesWritten], length - bytesWritten);
00531     }
00532 
00533     return bytesWritten;
00534 }
00535 
00536 unsigned int Cellular::readable()
00537 {
00538     if(io == NULL) {
00539         printf("[WARNING] MTSBufferedIO not set\r\n");
00540         return 0;
00541     }
00542     if(!socketOpened && !io->readable()) {
00543         printf("[WARNING] Socket is not open\r\n");
00544         return 0;
00545     }
00546     return io->readable();
00547 }
00548 
00549 unsigned int Cellular::writeable()
00550 {
00551     if(io == NULL) {
00552         printf("[WARNING] MTSBufferedIO not set\r\n");
00553         return 0;
00554     }
00555     if(!socketOpened) {
00556         printf("[WARNING] Socket is not open\r\n");
00557         return 0;
00558     }
00559 
00560     return io->writeable();
00561 }
00562 
00563 void Cellular::reset()
00564 {
00565     disconnect();
00566     Code code = sendBasicCommand("AT#RESET=0", 10000);
00567     if(code != SUCCESS) {
00568         printf("[ERROR] Socket Modem did not accept RESET command\n\r");
00569     } else {
00570         printf("[WARNING] Socket Modem is resetting, allow 30 seconds for it to come back\n\r");
00571     }
00572 }
00573 
00574 std::string Cellular::getDeviceIP()
00575 {
00576     return local_address;
00577 }
00578 
00579 Code Cellular::test()
00580 {
00581     Code code;
00582     int i = 0;
00583     while (sendBasicCommand("AT", 1000) != SUCCESS) {
00584         i++;
00585         if (i >= 30) {
00586             printf("[ERROR] Could not talk to radio after 30 tries\r\n");
00587             i = 0;
00588         }
00589         wait(1);
00590     }
00591 
00592     return SUCCESS;
00593 }
00594 
00595 Code Cellular::echo(bool state)
00596 {
00597     Code code;
00598     if (state) {
00599         code = sendBasicCommand("ATE0", 1000);
00600         echoMode = (code == SUCCESS) ? false : echoMode;
00601     } else {
00602         code = sendBasicCommand("ATE1", 1000);
00603         echoMode = (code == SUCCESS) ? true : echoMode;
00604     }
00605     return code;
00606 }
00607 
00608 int Cellular::getSignalStrength()
00609 {
00610     string response = sendCommand("AT+CSQ", 1000);
00611     if (response.find("OK") == string::npos) {
00612         return -1;
00613     }
00614     int start = response.find(':');
00615     int stop = response.find(',', start);
00616     string signal = response.substr(start + 2, stop - start - 2);
00617     int value;
00618     sscanf(signal.c_str(), "%d", &value);
00619     return value;
00620 }
00621 
00622 Cellular::Registration Cellular::getRegistration()
00623 {
00624     string response = sendCommand("AT+CREG?", 5000);
00625     if (response.find("OK") == string::npos) {
00626         return UNKNOWN;
00627     }
00628     int start = response.find(',');
00629     int stop = response.find(' ', start);
00630     string regStat = response.substr(start + 1, stop - start - 1);
00631     int value;
00632     sscanf(regStat.c_str(), "%d", &value);
00633     switch (value) {
00634         case 0:
00635             return NOT_REGISTERED;
00636         case 1:
00637             return REGISTERED;
00638         case 2:
00639             return SEARCHING;
00640         case 3:
00641             return DENIED;
00642         case 4:
00643             return UNKNOWN;
00644         case 5:
00645             return ROAMING;
00646     }
00647     return UNKNOWN;
00648 }
00649 
00650 Code Cellular::setApn(const std::string& apn)
00651 {
00652     Code code = sendBasicCommand("AT#APNSERV=\"" + apn + "\"", 1000);
00653     if (code != SUCCESS) {
00654         return code;
00655     }
00656     this->apn = apn;
00657     return code;
00658 }
00659 
00660 
00661 Code Cellular::setDns(const std::string& primary, const std::string& secondary)
00662 {
00663     return sendBasicCommand("AT#DNS=1," + primary + "," + secondary, 1000);
00664 }
00665 
00666 bool Cellular::ping(const std::string& address)
00667 {
00668     char buffer[256] = {0};
00669     Code code;
00670 
00671     code = sendBasicCommand("AT#PINGREMOTE=\"" + address + "\"", 1000);
00672     if (code != SUCCESS) {
00673         return false;
00674     }
00675 
00676     sprintf(buffer, "AT#PINGNUM=%d", 1);
00677     code = sendBasicCommand(buffer , 1000);
00678     if (code != SUCCESS) {
00679         return false;
00680     }
00681 
00682     sprintf(buffer, "AT#PINGDELAY=%d", PINGDELAY);
00683     code = sendBasicCommand(buffer , 1000);
00684     if (code != SUCCESS) {
00685         return false;
00686     }
00687 
00688     std::string response;
00689     for (int i = 0; i < PINGNUM; i++) {
00690         response = sendCommand("AT#PING", PINGDELAY * 1000);
00691         if (response.find("alive") != std::string::npos) {
00692             return true;
00693         }
00694     }
00695     return false;
00696 }
00697 
00698 Code Cellular::setSocketCloseable(bool enabled)
00699 {
00700     if(socketCloseable == enabled) {
00701         return SUCCESS;
00702     }
00703 
00704     if(socketOpened) {
00705         printf("[ERROR] socket is already opened. Can not set closeable\r\n");
00706         return ERROR;
00707     }
00708 
00709     socketCloseable = enabled;
00710 
00711     return SUCCESS;
00712 }
00713 
00714 Code Cellular::sendSMS(const Sms& sms)
00715 {
00716     return sendSMS(sms.phoneNumber, sms.message);
00717 }
00718 
00719 Code Cellular::sendSMS(const std::string& phoneNumber, const std::string& message)
00720 {
00721     Code code = sendBasicCommand("AT+CMGF=1", 1000);
00722     if (code != SUCCESS) {
00723         return code;
00724     }
00725     string cmd = "AT+CMGS=\"+";
00726     cmd.append(phoneNumber);
00727     cmd.append("\"");
00728     string response1 = sendCommand(cmd, 1000);
00729     if (response1.find('>') == string::npos) {
00730         return NO_RESPONSE;
00731     }
00732     wait(.2);
00733     string  response2 = sendCommand(message, 4000, CTRL_Z);
00734     printf("SMS Response: %s\r\n", response2.c_str());
00735     if (response2.find("+CMGS:") == string::npos) {
00736         return FAILURE;
00737     }
00738     return SUCCESS;
00739 }
00740 
00741 std::vector<Cellular::Sms> Cellular::getReceivedSms()
00742 {
00743     int smsNumber = 0;
00744     std::vector<Sms> vSms;
00745     std::string received = sendCommand("AT+CMGL=\"ALL\"", 4000);
00746     size_t pos = received.find("+CMGL: ");
00747 
00748     while (pos != std::string::npos) {
00749         Cellular::Sms sms;
00750         std::string line(Text::getLine(received, pos, pos));
00751         //printf("[DEBUG] Top of SMS Parse Loop. LINE[%s]\r\n", line.c_str());
00752         if(line.find("+CMGL: ") == std::string::npos) {
00753             continue;
00754         }
00755 
00756         //Start of SMS message
00757         std::vector<std::string> vSmsParts = Text::split(line, ',');
00758         if(vSmsParts.size() != 6) {
00759             printf("[WARNING] Expected 6 commas. SMS[%d] DATA[%s]. Continuing ...\r\n", smsNumber, line.c_str());
00760             continue;
00761         }
00762 
00763         sms.phoneNumber = vSmsParts[2];
00764         sms.timestamp = vSmsParts[4] + ", " + vSmsParts[5];
00765 
00766         if(pos == std::string::npos) {
00767             printf("[WARNING] Expected SMS body. SMS[%d]. Leaving ...\r\n", smsNumber);
00768             break;
00769         }
00770         //Check for the start of the next SMS message
00771         size_t bodyEnd = received.find("\r\n+CMGL: ", pos);
00772         if(bodyEnd == std::string::npos) {
00773             //printf("[DEBUG] Parsing Last SMS. SMS[%d]\r\n", smsNumber);
00774             //This must be the last SMS message
00775             bodyEnd = received.find("\r\n\r\nOK", pos);
00776         }
00777 
00778         //Safety check that we found the boundary of this current SMS message
00779         if(bodyEnd != std::string::npos) {
00780             sms.message = received.substr(pos, bodyEnd - pos);
00781         } else {
00782             sms.message = received.substr(pos);
00783             printf("[WARNING] Expected to find end of SMS list. SMS[%d] DATA[%s].\r\n", smsNumber, sms.message.c_str());
00784         }
00785         vSms.push_back(sms);
00786         pos = bodyEnd;
00787         //printf("[DEBUG] Parsed SMS[%d].  Starting Next at position [%d]\r\n", smsNumber, pos);
00788         smsNumber++;
00789     }
00790     printf("Received %d SMS\r\n", smsNumber);
00791     return vSms;
00792 }
00793 
00794 Code Cellular::deleteOnlyReceivedReadSms()
00795 {
00796     return sendBasicCommand("AT+CMGD=1,1", 1000);
00797 }
00798 
00799 Code Cellular::deleteAllReceivedSms()
00800 {
00801     return sendBasicCommand("AT+CMGD=1,4", 1000);
00802 }
00803 
00804 Code Cellular::sendBasicCommand(const std::string& command, unsigned int timeoutMillis, char esc)
00805 {
00806     if(socketOpened) {
00807         printf("[ERROR] socket is open. Can not send AT commands\r\n");
00808         return ERROR;
00809     }
00810 
00811     string response = sendCommand(command, timeoutMillis, esc);
00812     if (response.size() == 0) {
00813         return NO_RESPONSE;
00814     } else if (response.find("OK") != string::npos) {
00815         return SUCCESS;
00816     } else if (response.find("ERROR") != string::npos) {
00817         return ERROR;
00818     } else {
00819         return FAILURE;
00820     }
00821 }
00822 
00823 string Cellular::sendCommand(const std::string& command, unsigned int timeoutMillis, char esc)
00824 {
00825     if(io == NULL) {
00826         printf("[ERROR] MTSBufferedIO not set\r\n");
00827         return "";
00828     }
00829     if(socketOpened) {
00830         printf("[ERROR] socket is open. Can not send AT commands\r\n");
00831         return "";
00832     }
00833 
00834     io->rxClear();
00835     io->txClear();
00836     std::string result;
00837 
00838     //Attempt to write command
00839     if(io->write(command.data(), command.size(), timeoutMillis) != command.size()) {
00840         //Failed to write command
00841         if (command != "AT" && command != "at") {
00842             printf("[ERROR] failed to send command to radio within %d milliseconds\r\n", timeoutMillis);
00843         }
00844         return "";
00845     }
00846 
00847     //Send Escape Character
00848     if (esc != 0x00) {
00849         if(io->write(esc, timeoutMillis) != 1) {
00850             if (command != "AT" && command != "at") {
00851                 printf("[ERROR] failed to send character '%c' (0x%02X) to radio within %d milliseconds\r\n", esc, esc, timeoutMillis);
00852             }
00853             return "";
00854         }
00855     }
00856 
00857     int timer = 0;
00858     size_t previous = 0;
00859     char tmp[256];
00860     tmp[255] = 0;
00861     bool started = !echoMode;
00862     bool done = false;
00863     do {
00864         wait(0.1);
00865         timer += 100;
00866 
00867         previous = result.size();
00868         //Make a non-blocking read call by passing timeout of zero
00869         int size = io->read(tmp,255,0);    //1 less than allocated (timeout is instant)
00870         if(size > 0) {
00871             result.append(tmp, size);
00872         }
00873         if(!started) {
00874             //In Echo Mode (Command will have echo'd + 2 characters for \r\n)
00875             if(result.size() > command.size() + 2) {
00876                 started = true;
00877             }
00878         } else {
00879             done =  (result.size() == previous);
00880         }
00881         if(timer >= timeoutMillis) {
00882             if (command != "AT" && command != "at") {
00883                 printf("[WARNING] sendCommand [%s] timed out after %d milliseconds\r\n", command.c_str(), timeoutMillis);
00884             }
00885             done = true;
00886         }
00887     } while (!done);
00888 
00889     return result;
00890 }
00891 
00892 std::string Cellular::getRegistrationNames(Registration registration)
00893 {
00894     switch(registration) {
00895         case NOT_REGISTERED:
00896             return "NOT_REGISTERED";
00897         case REGISTERED:
00898             return "REGISTERED";
00899         case SEARCHING:
00900             return "SEARCHING";
00901         case DENIED:
00902             return "DENIED";
00903         case UNKNOWN:
00904             return "UNKNOWN";
00905         case ROAMING:
00906             return "ROAMING";
00907         default:
00908             return "UNKNOWN ENUM";
00909     }
00910 }