fork of VodafoneUSBModem with updated USBHost library
Dependencies: Socket USBHost lwip-sys lwip
Dependents: VodafoneUSBModemSMSTest
SMSInterface.cpp
00001 /* SMSInterface.cpp */ 00002 /* Copyright (C) 2012 mbed.org, MIT License 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00005 * and associated documentation files (the "Software"), to deal in the Software without restriction, 00006 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 00007 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 00008 * furnished to do so, subject to the following conditions: 00009 * 00010 * The above copyright notice and this permission notice shall be included in all copies or 00011 * substantial portions of the Software. 00012 * 00013 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00014 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00015 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00016 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00017 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00018 */ 00019 00020 #define __DEBUG__ 2 00021 #ifndef __MODULE__ 00022 #define __MODULE__ "SMSInterface.cpp" 00023 #endif 00024 00025 #include "core/fwk.h" 00026 00027 #include "SMSInterface.h" 00028 00029 #include <cstdio> 00030 00031 #define DEFAULT_TIMEOUT 10000 00032 00033 SMSInterface::SMSInterface(ATCommandsInterface* pIf) : m_pIf(pIf), m_msg(NULL), m_maxMsgLength(0), m_msisdn(NULL) 00034 { 00035 m_pIf->registerEventsHandler(this); //Add us to the unsolicited result codes handlers 00036 } 00037 00038 int SMSInterface::init() 00039 { 00040 m_msgRefListCount = 0; 00041 m_needsUpdate = true; 00042 m_state = SMS_IDLE; 00043 00044 DBG("Set format"); 00045 //Set Text mode format 00046 int ret = m_pIf->executeSimple("AT+CMGF=1", NULL, DEFAULT_TIMEOUT); 00047 if(ret != OK) 00048 { 00049 return NET_PROTOCOL; 00050 } 00051 00052 DBG("Setup new messages indication"); 00053 //Setup new messages indication 00054 ret = m_pIf->executeSimple("AT+CNMI=2,1,0,0,0", NULL, DEFAULT_TIMEOUT); 00055 if(ret != OK) 00056 { 00057 return NET_PROTOCOL; 00058 } 00059 00060 DBG("Try to fetch inbox"); 00061 m_inboxMtx.lock(); 00062 if( m_needsUpdate ) 00063 { 00064 ret = updateInbox(); //Fetch existing messages references 00065 if(ret) 00066 { 00067 m_inboxMtx.unlock(); 00068 return NET_PROTOCOL; 00069 } 00070 } 00071 m_inboxMtx.unlock(); 00072 00073 DBG("Initialization done"); 00074 return OK; 00075 } 00076 00077 int SMSInterface::send(const char* number, const char* message) 00078 { 00079 if( strlen(number) > 16 ) 00080 { 00081 return NET_INVALID; //Number too long to match 3GPP spec 00082 } 00083 00084 int ret; 00085 00086 //Prepare infos 00087 m_state = SMS_SEND_CMD_SENT; 00088 m_msg = (char*) message; 00089 00090 DBG("Send SM"); 00091 //Send command 00092 char cmd[32]; 00093 std::sprintf(cmd, "AT+CMGS=\"%s\"", number); 00094 ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT); 00095 00096 if( (ret != OK) || (m_state != SMS_CMD_PROCESSED) ) 00097 { 00098 WARN("ret %d, state %d", ret, m_state); 00099 m_state = SMS_IDLE; 00100 return NET_PROTOCOL; 00101 } 00102 00103 DBG("SM sent"); 00104 m_state = SMS_IDLE; 00105 return OK; 00106 } 00107 00108 00109 int SMSInterface::get(char* number, char* message, size_t maxLength) 00110 { 00111 if( maxLength < 1 ) 00112 { 00113 return NET_INVALID; //Buffer too short 00114 } 00115 00116 int ret; 00117 00118 DBG("Get next message"); 00119 m_inboxMtx.lock(); 00120 if(m_msgRefListCount == 0 && m_needsUpdate) 00121 { 00122 DBG("Message list count is 0 and needs updating. Running updateInbox."); 00123 ret = updateInbox(); 00124 00125 if (ret) 00126 { 00127 m_inboxMtx.unlock(); 00128 return ret; 00129 } 00130 } 00131 00132 if(m_msgRefListCount == 0) 00133 { 00134 m_inboxMtx.unlock(); 00135 DBG("Message list count is 0, I think it's empty and returning."); 00136 return NET_EMPTY; //No message to read 00137 } 00138 00139 //Prepare infos 00140 m_state = SMS_GET_CMD_SENT; 00141 m_msisdn = (char*) number; 00142 m_msg = (char*) message; 00143 m_maxMsgLength = maxLength; 00144 00145 DBG("Get SMS"); 00146 //List command 00147 char cmd[32]; 00148 std::sprintf(cmd, "AT+CMGR=%d", m_msgRefList[0]); 00149 ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT); 00150 if( ret != OK ) 00151 { 00152 WARN("AT+CMGR returned %d", ret); 00153 m_state = SMS_IDLE; 00154 m_inboxMtx.unlock(); 00155 return NET_PROTOCOL; 00156 } 00157 00158 if (m_state != SMS_CMD_PROCESSED) 00159 { 00160 WARN("State variable is not 'SMS_CMD_PROCESSED' - returning 'NET_EMPTY'"); 00161 } 00162 00163 DBG("Deleting message from index number: %d", m_msgRefList[0] ); 00164 //Delete message from outbox 00165 std::sprintf(cmd, "AT+CMGD=%d", m_msgRefList[0]); 00166 ret = m_pIf->executeSimple(cmd, NULL, DEFAULT_TIMEOUT); 00167 if(ret != OK) 00168 { 00169 ERR("Could not delete message"); 00170 } 00171 //Remove message from list 00172 std::memmove(m_msgRefList, m_msgRefList+1, m_msgRefListCount-1); 00173 m_msgRefListCount--; 00174 00175 if (m_state != SMS_CMD_PROCESSED) 00176 { 00177 m_state = SMS_IDLE; 00178 m_inboxMtx.unlock(); 00179 return NET_EMPTY; 00180 } 00181 00182 m_state = SMS_IDLE; 00183 m_inboxMtx.unlock(); 00184 00185 return OK; 00186 } 00187 00188 00189 int SMSInterface::getCount(size_t* pCount) 00190 { 00191 int ret; 00192 00193 m_inboxMtx.lock(); 00194 if( m_needsUpdate ) 00195 { 00196 ret = updateInbox(); 00197 if(ret) 00198 { 00199 m_inboxMtx.unlock(); 00200 return NET_PROTOCOL; 00201 } 00202 } 00203 00204 *pCount = m_msgRefListCount; 00205 m_inboxMtx.unlock(); 00206 00207 return OK; 00208 } 00209 00210 00211 /*virtual*/ int SMSInterface::onNewATResponseLine(ATCommandsInterface* pInst, const char* line) 00212 { 00213 if(m_state == SMS_SEND_CMD_SENT) 00214 { 00215 if( std::sscanf(line, "+CMGS: %*d") == 0 ) 00216 { 00217 DBG("SM sent"); 00218 m_state = SMS_CMD_PROCESSED; 00219 } 00220 } 00221 else if(m_state == SMS_GET_CMD_SENT) 00222 { 00223 DBG("Header: %s", line); 00224 if( std::sscanf(line, "+CMGR: %*[^,],\"%16[^\"]\"", m_msisdn) == 1 ) //Get message ref 00225 { 00226 m_state = SMS_GET_HDR_RECEIVED; 00227 } 00228 } 00229 else if(m_state == SMS_GET_HDR_RECEIVED) 00230 { 00231 DBG("Message: %s", line); 00232 size_t cpyLen = MIN( std::strlen(line), m_maxMsgLength - 1 ); 00233 std::memcpy( m_msg, line, cpyLen ); 00234 m_msg[cpyLen] = '\0'; 00235 m_state = SMS_CMD_PROCESSED; 00236 } 00237 else if(m_state == SMS_GET_COUNT_CMD_SENT) 00238 { 00239 DBG("Header: %s", line); 00240 int msgRef; 00241 if( std::sscanf(line, "+CMGL: %d,\"REC", &msgRef) == 1 ) //Filter on REC READ and REC UNREAD messages 00242 { 00243 m_state = SMS_GET_COUNT_HDR_RECEIVED; 00244 //Add message to list 00245 if(m_msgRefListCount < MAX_SM) 00246 { 00247 m_msgRefList[m_msgRefListCount] = msgRef; 00248 } 00249 m_msgRefListCount++; //Always count message 00250 DBG("m_msgRefListCount=%d",m_msgRefListCount); 00251 } 00252 } 00253 else if(m_state == SMS_GET_COUNT_HDR_RECEIVED) 00254 { 00255 DBG("Message (debug only): %s", line); //For debug only 00256 m_state = SMS_GET_COUNT_CMD_SENT; 00257 } 00258 return OK; 00259 } 00260 00261 /*virtual*/ int SMSInterface::onNewEntryPrompt(ATCommandsInterface* pInst) 00262 { 00263 if(m_state == SMS_SEND_CMD_SENT) 00264 { 00265 char* crPtr = strchr(m_msg, CR); 00266 if(crPtr != NULL) 00267 { 00268 int crPos = crPtr - m_msg; 00269 //Replace m_inputBuf[crPos] with null-terminating char 00270 m_msg[crPos] = '\x0'; 00271 00272 //If there is a CR char, split message there 00273 00274 //Do print the message 00275 int ret = pInst->sendData(m_msg); 00276 if(ret) 00277 { 00278 return ret; 00279 } 00280 00281 char cr[2] = {CR, '\0'}; 00282 ret = pInst->sendData(cr); 00283 if(ret) 00284 { 00285 return ret; 00286 } 00287 00288 m_msg += crPos; 00289 00290 if(m_msg[0] == LF) 00291 { 00292 m_msg++; //Discard LF char as well 00293 } 00294 00295 return NET_MOREINFO; 00296 } 00297 else 00298 { 00299 //Do print the message 00300 pInst->sendData(m_msg); 00301 return OK; 00302 } 00303 } 00304 00305 return OK; 00306 } 00307 00308 /*virtual*/ bool SMSInterface::isATCodeHandled(const char* atCode) //Is this AT code handled 00309 { 00310 DBG("AT code is %s", atCode); 00311 if( strcmp("+CMTI", atCode) == 0 ) 00312 { 00313 return true; 00314 } 00315 00316 DBG("Not handled"); 00317 return false; 00318 } 00319 00320 /*virtual*/ void SMSInterface::onDispatchStart() 00321 { 00322 00323 00324 } 00325 00326 /*virtual*/ void SMSInterface::onDispatchStop() 00327 { 00328 00329 } 00330 00331 /*virtual*/ void SMSInterface::onEvent(const char* atCode, const char* evt) 00332 { 00333 if( strcmp("+CMTI", atCode) != 0 ) 00334 { 00335 return; //Not supported 00336 } 00337 00338 DBG("Unsollicited result code: %s - %s", atCode, evt); 00339 00340 //Get index 00341 int msgRef; 00342 if( std::sscanf(evt, "\"SM\",%d", &msgRef) == 1 ) 00343 { 00344 DBG("Adding message to list (ref %d)", msgRef); 00345 if(m_inboxMtx.trylock()) 00346 { 00347 //Add message to list 00348 if(m_msgRefListCount < MAX_SM) 00349 { 00350 m_msgRefList[m_msgRefListCount] = msgRef; 00351 } 00352 else 00353 { 00354 m_needsUpdate = true; 00355 } 00356 m_msgRefListCount++; //Always count message 00357 m_inboxMtx.unlock(); 00358 } 00359 else 00360 { 00361 WARN("Could not get lock"); 00362 m_needsUpdate = true; 00363 } 00364 } 00365 } 00366 00367 int SMSInterface::updateInbox() 00368 { 00369 //Get memory indexes of unread messages 00370 00371 DBG("Updating inbox"); 00372 m_msgRefListCount = 0; //Reset list 00373 m_needsUpdate = false; //Assume we won't need update after this routine (can be set to true by an incoming SM event) 00374 00375 //First list the "REC READ" messages that were not processed in the previous session 00376 m_state = SMS_GET_COUNT_CMD_SENT; 00377 int ret = m_pIf->execute("AT+CMGL=\"REC READ\"", this, NULL, DEFAULT_TIMEOUT); 00378 if( ret != OK ) 00379 { 00380 WARN("AT+CMGL returned %d", ret); 00381 m_state = SMS_IDLE; 00382 m_msgRefListCount = 0; //List could be invalid 00383 m_needsUpdate = true; 00384 return NET_PROTOCOL; 00385 } 00386 00387 //Now list the "REC UNREAD" messages that were received by the modem since 00388 m_state = SMS_GET_COUNT_CMD_SENT; 00389 ret = m_pIf->execute("AT+CMGL=\"REC UNREAD\"", this, NULL, DEFAULT_TIMEOUT); 00390 if( ret != OK ) 00391 { 00392 WARN("AT+CMGL returned %d", ret); 00393 m_state = SMS_IDLE; 00394 m_msgRefListCount = 0; //List could be invalid 00395 m_needsUpdate = true; 00396 return NET_PROTOCOL; 00397 } 00398 00399 DBG("%d incoming messages in inbox", m_msgRefListCount); 00400 00401 if( m_msgRefListCount > MAX_SM ) 00402 { 00403 m_needsUpdate = true; 00404 } 00405 00406 m_state = SMS_IDLE; 00407 00408 return OK; 00409 } 00410 00411
Generated on Wed Jul 13 2022 19:57:21 by
![doxygen](doxygen.png)