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
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 }
Generated on Wed Jul 13 2022 02:45:01 by 1.7.2