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.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 MTS_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 == MTS_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 != MTS_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 != MTS_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 != MTS_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 == MTS_SUCCESS) { 00297 host_port = port; 00298 } else { 00299 printf("[ERROR] Host port could not be set\r\n"); 00300 } 00301 00302 if(addressCode == MTS_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 != MTS_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 int i = 0; 00582 while (sendBasicCommand("AT", 1000) != MTS_SUCCESS) { 00583 i++; 00584 if (i >= 30) { 00585 printf("[ERROR] Could not talk to radio after 30 tries\r\n"); 00586 i = 0; 00587 } 00588 wait(1); 00589 } 00590 return MTS_SUCCESS; 00591 } 00592 00593 Code Cellular::echo(bool state) 00594 { 00595 Code code; 00596 if (state) { 00597 code = sendBasicCommand("ATE0", 1000); 00598 echoMode = (code == MTS_SUCCESS) ? false : echoMode; 00599 } else { 00600 code = sendBasicCommand("ATE1", 1000); 00601 echoMode = (code == MTS_SUCCESS) ? true : echoMode; 00602 } 00603 return code; 00604 } 00605 00606 int Cellular::getSignalStrength() 00607 { 00608 string response = sendCommand("AT+CSQ", 1000); 00609 if (response.find("OK") == string::npos) { 00610 return -1; 00611 } 00612 int start = response.find(':'); 00613 int stop = response.find(',', start); 00614 string signal = response.substr(start + 2, stop - start - 2); 00615 int value; 00616 sscanf(signal.c_str(), "%d", &value); 00617 return value; 00618 } 00619 00620 Cellular::Registration Cellular::getRegistration() 00621 { 00622 string response = sendCommand("AT+CREG?", 5000); 00623 if (response.find("OK") == string::npos) { 00624 return UNKNOWN; 00625 } 00626 int start = response.find(','); 00627 int stop = response.find(' ', start); 00628 string regStat = response.substr(start + 1, stop - start - 1); 00629 int value; 00630 sscanf(regStat.c_str(), "%d", &value); 00631 switch (value) { 00632 case 0: 00633 return NOT_REGISTERED; 00634 case 1: 00635 return REGISTERED; 00636 case 2: 00637 return SEARCHING; 00638 case 3: 00639 return DENIED; 00640 case 4: 00641 return UNKNOWN; 00642 case 5: 00643 return ROAMING; 00644 } 00645 return UNKNOWN; 00646 } 00647 00648 Code Cellular::setApn(const std::string& apn) 00649 { 00650 Code code = sendBasicCommand("AT#APNSERV=\"" + apn + "\"", 1000); 00651 if (code != MTS_SUCCESS) { 00652 return code; 00653 } 00654 this->apn = apn; 00655 return code; 00656 } 00657 00658 00659 Code Cellular::setDns(const std::string& primary, const std::string& secondary) 00660 { 00661 return sendBasicCommand("AT#DNS=1," + primary + "," + secondary, 1000); 00662 } 00663 00664 bool Cellular::ping(const std::string& address) 00665 { 00666 char buffer[256] = {0}; 00667 Code code; 00668 00669 code = sendBasicCommand("AT#PINGREMOTE=\"" + address + "\"", 1000); 00670 if (code != MTS_SUCCESS) { 00671 return false; 00672 } 00673 00674 sprintf(buffer, "AT#PINGNUM=%d", 1); 00675 code = sendBasicCommand(buffer , 1000); 00676 if (code != MTS_SUCCESS) { 00677 return false; 00678 } 00679 00680 sprintf(buffer, "AT#PINGDELAY=%d", PINGDELAY); 00681 code = sendBasicCommand(buffer , 1000); 00682 if (code != MTS_SUCCESS) { 00683 return false; 00684 } 00685 00686 std::string response; 00687 for (int i = 0; i < PINGNUM; i++) { 00688 response = sendCommand("AT#PING", PINGDELAY * 1000); 00689 if (response.find("alive") != std::string::npos) { 00690 return true; 00691 } 00692 } 00693 return false; 00694 } 00695 00696 Code Cellular::setSocketCloseable(bool enabled) 00697 { 00698 if(socketCloseable == enabled) { 00699 return MTS_SUCCESS; 00700 } 00701 00702 if(socketOpened) { 00703 printf("[ERROR] socket is already opened. Can not set closeable\r\n"); 00704 return MTS_ERROR; 00705 } 00706 00707 socketCloseable = enabled; 00708 00709 return MTS_SUCCESS; 00710 } 00711 00712 Code Cellular::sendSMS(const Sms& sms) 00713 { 00714 return sendSMS(sms.phoneNumber, sms.message); 00715 } 00716 00717 Code Cellular::sendSMS(const std::string& phoneNumber, const std::string& message) 00718 { 00719 Code code = sendBasicCommand("AT+CMGF=1", 1000); 00720 if (code != MTS_SUCCESS) { 00721 return code; 00722 } 00723 string cmd = "AT+CMGS=\"+"; 00724 cmd.append(phoneNumber); 00725 cmd.append("\""); 00726 string response1 = sendCommand(cmd, 1000); 00727 if (response1.find('>') == string::npos) { 00728 return MTS_NO_RESPONSE; 00729 } 00730 wait(.2); 00731 string response2 = sendCommand(message, 4000, CTRL_Z); 00732 printf("SMS Response: %s\r\n", response2.c_str()); 00733 if (response2.find("+CMGS:") == string::npos) { 00734 return MTS_FAILURE; 00735 } 00736 return MTS_SUCCESS; 00737 } 00738 00739 std::vector<Cellular::Sms> Cellular::getReceivedSms() 00740 { 00741 int smsNumber = 0; 00742 std::vector<Sms> vSms; 00743 std::string received = sendCommand("AT+CMGL=\"ALL\"", 4000); 00744 size_t pos = received.find("+CMGL: "); 00745 00746 while (pos != std::string::npos) { 00747 Cellular::Sms sms; 00748 std::string line(Text::getLine(received, pos, pos)); 00749 //printf("[DEBUG] Top of SMS Parse Loop. LINE[%s]\r\n", line.c_str()); 00750 if(line.find("+CMGL: ") == std::string::npos) { 00751 continue; 00752 } 00753 00754 //Start of SMS message 00755 std::vector<std::string> vSmsParts = Text::split(line, ','); 00756 if(vSmsParts.size() != 6) { 00757 printf("[WARNING] Expected 6 commas. SMS[%d] DATA[%s]. Continuing ...\r\n", smsNumber, line.c_str()); 00758 continue; 00759 } 00760 00761 sms.phoneNumber = vSmsParts[2]; 00762 sms.timestamp = vSmsParts[4] + ", " + vSmsParts[5]; 00763 00764 if(pos == std::string::npos) { 00765 printf("[WARNING] Expected SMS body. SMS[%d]. Leaving ...\r\n", smsNumber); 00766 break; 00767 } 00768 //Check for the start of the next SMS message 00769 size_t bodyEnd = received.find("\r\n+CMGL: ", pos); 00770 if(bodyEnd == std::string::npos) { 00771 //printf("[DEBUG] Parsing Last SMS. SMS[%d]\r\n", smsNumber); 00772 //This must be the last SMS message 00773 bodyEnd = received.find("\r\n\r\nOK", pos); 00774 } 00775 00776 //Safety check that we found the boundary of this current SMS message 00777 if(bodyEnd != std::string::npos) { 00778 sms.message = received.substr(pos, bodyEnd - pos); 00779 } else { 00780 sms.message = received.substr(pos); 00781 printf("[WARNING] Expected to find end of SMS list. SMS[%d] DATA[%s].\r\n", smsNumber, sms.message.c_str()); 00782 } 00783 vSms.push_back(sms); 00784 pos = bodyEnd; 00785 //printf("[DEBUG] Parsed SMS[%d]. Starting Next at position [%d]\r\n", smsNumber, pos); 00786 smsNumber++; 00787 } 00788 printf("Received %d SMS\r\n", smsNumber); 00789 return vSms; 00790 } 00791 00792 Code Cellular::deleteOnlyReceivedReadSms() 00793 { 00794 return sendBasicCommand("AT+CMGD=1,1", 1000); 00795 } 00796 00797 Code Cellular::deleteAllReceivedSms() 00798 { 00799 return sendBasicCommand("AT+CMGD=1,4", 1000); 00800 } 00801 00802 Code Cellular::sendBasicCommand(const std::string& command, unsigned int timeoutMillis, char esc) 00803 { 00804 if(socketOpened) { 00805 printf("[ERROR] socket is open. Can not send AT commands\r\n"); 00806 return MTS_ERROR; 00807 } 00808 00809 string response = sendCommand(command, timeoutMillis, esc); 00810 if (response.size() == 0) { 00811 return MTS_NO_RESPONSE; 00812 } else if (response.find("OK") != string::npos) { 00813 return MTS_SUCCESS; 00814 } else if (response.find("ERROR") != string::npos) { 00815 return MTS_ERROR; 00816 } else { 00817 return MTS_FAILURE; 00818 } 00819 } 00820 00821 string Cellular::sendCommand(const std::string& command, unsigned int timeoutMillis, char esc) 00822 { 00823 if(io == NULL) { 00824 printf("[ERROR] MTSBufferedIO not set\r\n"); 00825 return ""; 00826 } 00827 if(socketOpened) { 00828 printf("[ERROR] socket is open. Can not send AT commands\r\n"); 00829 return ""; 00830 } 00831 00832 io->rxClear(); 00833 io->txClear(); 00834 std::string result; 00835 00836 //Attempt to write command 00837 if(io->write(command.data(), command.size(), timeoutMillis) != command.size()) { 00838 //Failed to write command 00839 if (command != "AT" && command != "at") { 00840 printf("[ERROR] failed to send command to radio within %d milliseconds\r\n", timeoutMillis); 00841 } 00842 return ""; 00843 } 00844 00845 //Send Escape Character 00846 if (esc != 0x00) { 00847 if(io->write(esc, timeoutMillis) != 1) { 00848 if (command != "AT" && command != "at") { 00849 printf("[ERROR] failed to send character '%c' (0x%02X) to radio within %d milliseconds\r\n", esc, esc, timeoutMillis); 00850 } 00851 return ""; 00852 } 00853 } 00854 00855 int timer = 0; 00856 size_t previous = 0; 00857 char tmp[256]; 00858 tmp[255] = 0; 00859 bool started = !echoMode; 00860 bool done = false; 00861 do { 00862 wait(0.1); 00863 timer += 100; 00864 00865 previous = result.size(); 00866 //Make a non-blocking read call by passing timeout of zero 00867 int size = io->read(tmp,255,0); //1 less than allocated (timeout is instant) 00868 if(size > 0) { 00869 result.append(tmp, size); 00870 } 00871 if(!started) { 00872 //In Echo Mode (Command will have echo'd + 2 characters for \r\n) 00873 if(result.size() > command.size() + 2) { 00874 started = true; 00875 } 00876 } else { 00877 done = (result.size() == previous); 00878 } 00879 if(timer >= timeoutMillis) { 00880 if (command != "AT" && command != "at") { 00881 printf("[WARNING] sendCommand [%s] timed out after %d milliseconds\r\n", command.c_str(), timeoutMillis); 00882 } 00883 done = true; 00884 } 00885 } while (!done); 00886 00887 return result; 00888 } 00889 00890 std::string Cellular::getRegistrationNames(Registration registration) 00891 { 00892 switch(registration) { 00893 case NOT_REGISTERED: 00894 return "NOT_REGISTERED"; 00895 case REGISTERED: 00896 return "REGISTERED"; 00897 case SEARCHING: 00898 return "SEARCHING"; 00899 case DENIED: 00900 return "DENIED"; 00901 case UNKNOWN: 00902 return "UNKNOWN"; 00903 case ROAMING: 00904 return "ROAMING"; 00905 default: 00906 return "UNKNOWN ENUM"; 00907 } 00908 }
Generated on Tue Jul 12 2022 21:46:23 by 1.7.2