Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
GSMSMSInterface.cpp
00001 /* GSMSMSInterface.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__ "GSMSMSInterface.cpp" 00023 #endif 00024 00025 #include "core/fwk.h" 00026 00027 #include "GSMSMSInterface.h" 00028 00029 #include <cstdio> 00030 #include <cstring> 00031 00032 #define DEFAULT_TIMEOUT 10000 00033 00034 GSMSMSInterface::GSMSMSInterface(ATCommandsInterface* pIf) : m_pIf(pIf), m_msg(NULL), m_maxMsgLength(0), m_msisdn(NULL) 00035 { 00036 m_pIf->registerEventsHandler(this); //Add us to the unsolicited result codes handlers 00037 } 00038 00039 int GSMSMSInterface::init() 00040 { 00041 m_msgRefListCount = 0; 00042 m_needsUpdate = true; 00043 m_state = SMS_IDLE; 00044 00045 DBG("Set format"); 00046 //Set Text mode format 00047 int ret = m_pIf->executeSimple("AT+CMGF=1", NULL, DEFAULT_TIMEOUT); 00048 if(ret != OK) 00049 { 00050 return NET_PROTOCOL; 00051 } 00052 00053 DBG("Setup new messages indication"); 00054 //Setup new messages indication 00055 ret = m_pIf->executeSimple("AT+CNMI=2,1,0,0,0", NULL, DEFAULT_TIMEOUT); 00056 if(ret != OK) 00057 { 00058 return NET_PROTOCOL; 00059 } 00060 00061 DBG("Try to fetch inbox"); 00062 m_inboxMtx.lock(); 00063 if( m_needsUpdate ) 00064 { 00065 ret = updateInbox(); //Fetch existing messages references 00066 if(ret) 00067 { 00068 m_inboxMtx.unlock(); 00069 return NET_PROTOCOL; 00070 } 00071 } 00072 m_inboxMtx.unlock(); 00073 00074 DBG("Initialization done"); 00075 return OK; 00076 } 00077 00078 int GSMSMSInterface::send(const char* number, const char* message) 00079 { 00080 if( strlen(number) > 16 ) 00081 { 00082 return NET_INVALID; //Number too long to match 3GPP spec 00083 } 00084 00085 int ret; 00086 00087 //Prepare infos 00088 m_state = SMS_SEND_CMD_SENT; 00089 m_msg = (char*) message; 00090 00091 DBG("Send SM"); 00092 //Send command 00093 char cmd[32]; 00094 std::sprintf(cmd, "AT+CMGS=\"%s\"", number); 00095 ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT); 00096 00097 if( (ret != OK) || (m_state != SMS_CMD_PROCESSED) ) 00098 { 00099 WARN("ret %d, state %d", ret, m_state); 00100 m_state = SMS_IDLE; 00101 return NET_PROTOCOL; 00102 } 00103 00104 DBG("SM sent"); 00105 m_state = SMS_IDLE; 00106 return OK; 00107 } 00108 00109 00110 int GSMSMSInterface::get(char* number, char* message, size_t maxLength) 00111 { 00112 if( maxLength < 1 ) 00113 { 00114 return NET_INVALID; //Buffer too short 00115 } 00116 00117 int ret; 00118 00119 DBG("Get next message"); 00120 m_inboxMtx.lock(); 00121 if( ((m_msgRefListCount == 0) && m_needsUpdate) || ((m_msgRefListCount > 0) && (m_msgRefList[0] == -1)) ) 00122 { 00123 DBG("Message list count is 0 and needs updating or next index is unknown, calling updateInbox()"); 00124 ret = updateInbox(); 00125 00126 if (ret) 00127 { 00128 m_inboxMtx.unlock(); 00129 return ret; 00130 } 00131 } 00132 00133 DBG("%d messages to read", m_msgRefListCount); 00134 00135 if(m_msgRefListCount == 0) 00136 { 00137 m_inboxMtx.unlock(); 00138 DBG("Message list count is 0, I think it's empty and returning."); 00139 return NET_EMPTY; //No message to read 00140 } 00141 00142 //Prepare infos 00143 m_state = SMS_GET_CMD_SENT; 00144 m_msisdn = (char*) number; 00145 m_msg = (char*) message; 00146 m_maxMsgLength = maxLength; 00147 00148 DBG("Get SMS"); 00149 //List command 00150 char cmd[32]; 00151 std::sprintf(cmd, "AT+CMGR=%d", m_msgRefList[0]); 00152 ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT); 00153 if( ret != OK ) 00154 { 00155 WARN("AT+CMGR returned %d", ret); 00156 m_state = SMS_IDLE; 00157 m_inboxMtx.unlock(); 00158 return NET_PROTOCOL; 00159 } 00160 00161 if (m_state != SMS_CMD_PROCESSED) 00162 { 00163 WARN("State variable is not 'SMS_CMD_PROCESSED' - returning 'NET_EMPTY'"); 00164 } 00165 00166 DBG("Deleting message from index number: %d", m_msgRefList[0] ); 00167 //Delete message from outbox 00168 std::sprintf(cmd, "AT+CMGD=%d", m_msgRefList[0]); 00169 ret = m_pIf->executeSimple(cmd, NULL, DEFAULT_TIMEOUT); 00170 if(ret != OK) 00171 { 00172 ERR("Could not delete message"); 00173 } 00174 //Remove message from list 00175 std::memmove(&m_msgRefList[0], &m_msgRefList[1], MIN(m_msgRefListCount-1,MAX_SM-1)*sizeof(m_msgRefList[0])); 00176 m_msgRefListCount--; 00177 00178 if(m_msgRefListCount > MAX_SM - 1) //Last message index is unknown, so put -1 to tell the lib to fetch it when needed 00179 { 00180 DBG("Last message index is unknown, will need to be updated"); 00181 m_msgRefList[MAX_SM - 1] = -1; 00182 } 00183 00184 DBG("%d messages to read", m_msgRefListCount); 00185 00186 if (m_state != SMS_CMD_PROCESSED) 00187 { 00188 m_state = SMS_IDLE; 00189 m_inboxMtx.unlock(); 00190 return NET_EMPTY; 00191 } 00192 00193 m_state = SMS_IDLE; 00194 m_inboxMtx.unlock(); 00195 00196 return OK; 00197 } 00198 00199 00200 int GSMSMSInterface::getCount(size_t* pCount) 00201 { 00202 int ret; 00203 00204 m_inboxMtx.lock(); 00205 if( m_needsUpdate ) 00206 { 00207 ret = updateInbox(); 00208 if(ret) 00209 { 00210 m_inboxMtx.unlock(); 00211 return NET_PROTOCOL; 00212 } 00213 } 00214 00215 *pCount = m_msgRefListCount; 00216 m_inboxMtx.unlock(); 00217 00218 return OK; 00219 } 00220 00221 00222 /*virtual*/ int GSMSMSInterface::onNewATResponseLine(ATCommandsInterface* pInst, const char* line) 00223 { 00224 if(m_state == SMS_SEND_CMD_SENT) 00225 { 00226 if( std::sscanf(line, "+CMGS: %*d") == 0 ) 00227 { 00228 DBG("SM sent"); 00229 m_state = SMS_CMD_PROCESSED; 00230 } 00231 } 00232 else if(m_state == SMS_GET_CMD_SENT) 00233 { 00234 DBG("Header: %s", line); 00235 if( std::sscanf(line, "+CMGR: %*[^,],\"%16[^\"]\"", m_msisdn) == 1 ) //Get message ref 00236 { 00237 m_state = SMS_GET_HDR_RECEIVED; 00238 } 00239 } 00240 else if(m_state == SMS_GET_HDR_RECEIVED) 00241 { 00242 DBG("Message: %s", line); 00243 size_t cpyLen = MIN( std::strlen(line), m_maxMsgLength - 1 ); 00244 std::memcpy( m_msg, line, cpyLen ); 00245 m_msg[cpyLen] = '\0'; 00246 m_state = SMS_CMD_PROCESSED; 00247 } 00248 else if(m_state == SMS_GET_COUNT_CMD_SENT) 00249 { 00250 DBG("Header: %s", line); 00251 int msgRef; 00252 if( std::sscanf(line, "+CMGL: %d,\"REC", &msgRef) == 1 ) //Filter on REC READ and REC UNREAD messages 00253 { 00254 m_state = SMS_GET_COUNT_HDR_RECEIVED; 00255 //Add message to list 00256 if(m_msgRefListCount < MAX_SM) 00257 { 00258 m_msgRefList[m_msgRefListCount] = msgRef; 00259 } 00260 m_msgRefListCount++; //Always count message 00261 DBG("m_msgRefListCount=%d",m_msgRefListCount); 00262 } 00263 } 00264 else if(m_state == SMS_GET_COUNT_HDR_RECEIVED) 00265 { 00266 DBG("Message (debug only): %s", line); //For debug only 00267 m_state = SMS_GET_COUNT_CMD_SENT; 00268 } 00269 return OK; 00270 } 00271 00272 /*virtual*/ int GSMSMSInterface::onNewEntryPrompt(ATCommandsInterface* pInst) 00273 { 00274 if(m_state == SMS_SEND_CMD_SENT) 00275 { 00276 char* crPtr = strchr(m_msg, CR); 00277 if(crPtr != NULL) 00278 { 00279 int crPos = crPtr - m_msg; 00280 //Replace m_inputBuf[crPos] with null-terminating char 00281 m_msg[crPos] = '\x0'; 00282 00283 //If there is a CR char, split message there 00284 00285 //Do print the message 00286 int ret = pInst->sendData(m_msg); 00287 if(ret) 00288 { 00289 return ret; 00290 } 00291 00292 char cr[2] = {CR, '\0'}; 00293 ret = pInst->sendData(cr); 00294 if(ret) 00295 { 00296 return ret; 00297 } 00298 00299 m_msg += crPos; 00300 00301 if(m_msg[0] == LF) 00302 { 00303 m_msg++; //Discard LF char as well 00304 } 00305 00306 return NET_MOREINFO; 00307 } 00308 else 00309 { 00310 //Do print the message 00311 pInst->sendData(m_msg); 00312 return OK; 00313 } 00314 } 00315 00316 return OK; 00317 } 00318 00319 /*virtual*/ bool GSMSMSInterface::isATCodeHandled(const char* atCode) //Is this AT code handled 00320 { 00321 DBG("AT code is %s", atCode); 00322 if( strcmp("+CMTI", atCode) == 0 ) 00323 { 00324 return true; 00325 } 00326 00327 DBG("Not handled"); 00328 return false; 00329 } 00330 00331 /*virtual*/ void GSMSMSInterface::onDispatchStart() 00332 { 00333 00334 } 00335 00336 /*virtual*/ void GSMSMSInterface::onDispatchStop() 00337 { 00338 00339 } 00340 00341 /*virtual*/ char* GSMSMSInterface::getEventsEnableCommand() 00342 { 00343 return "AT+CNMI=2,1,0,0,0"; 00344 } 00345 00346 /*virtual*/ char* GSMSMSInterface::getEventsDisableCommand() 00347 { 00348 return "AT+CNMI=0,0,0,0,0"; //Indications will be buffered within the modem and flushed back when the former command is executed 00349 } 00350 00351 /*virtual*/ void GSMSMSInterface::onEvent(const char* atCode, const char* evt) 00352 { 00353 if( strcmp("+CMTI", atCode) != 0 ) 00354 { 00355 return; //Not supported 00356 } 00357 00358 DBG("Unsollicited result code: %s - %s", atCode, evt); 00359 00360 //Get index 00361 int msgRef; 00362 if(( std::sscanf(evt, "\"SM\",%d", &msgRef) == 1 ) || 00363 ( std::sscanf(evt, "\"ME\",%d", &msgRef) == 1 )) 00364 { 00365 DBG("Adding message to list (ref %d)", msgRef); 00366 if(m_inboxMtx.trylock()) 00367 { 00368 //Add message to list 00369 if(m_msgRefListCount < MAX_SM) 00370 { 00371 m_msgRefList[m_msgRefListCount] = msgRef; 00372 } 00373 m_msgRefListCount++; //Always count message 00374 m_inboxMtx.unlock(); 00375 } 00376 else 00377 { 00378 WARN("Could not get lock"); 00379 m_needsUpdate = true; 00380 } 00381 } 00382 } 00383 00384 int GSMSMSInterface::updateInbox() 00385 { 00386 //Get memory indexes of unread messages 00387 00388 DBG("Updating inbox"); 00389 m_msgRefListCount = 0; //Reset list 00390 m_needsUpdate = false; //Assume we won't need update after this routine (can be set to true by an incoming SM event) 00391 00392 //First list the "REC READ" messages that were not processed in the previous session 00393 m_state = SMS_GET_COUNT_CMD_SENT; 00394 int ret = m_pIf->execute("AT+CMGL=\"REC READ\"", this, NULL, DEFAULT_TIMEOUT); 00395 if( ret != OK ) 00396 { 00397 WARN("AT+CMGL returned %d", ret); 00398 m_state = SMS_IDLE; 00399 m_msgRefListCount = 0; //List could be invalid 00400 m_needsUpdate = true; 00401 return NET_PROTOCOL; 00402 } 00403 00404 //Now list the "REC UNREAD" messages that were received by the modem since 00405 m_state = SMS_GET_COUNT_CMD_SENT; 00406 ret = m_pIf->execute("AT+CMGL=\"REC UNREAD\"", this, NULL, DEFAULT_TIMEOUT); 00407 if( ret != OK ) 00408 { 00409 WARN("AT+CMGL returned %d", ret); 00410 m_state = SMS_IDLE; 00411 m_msgRefListCount = 0; //List could be invalid 00412 m_needsUpdate = true; 00413 return NET_PROTOCOL; 00414 } 00415 00416 DBG("%d incoming messages in inbox", m_msgRefListCount); 00417 00418 m_state = SMS_IDLE; 00419 00420 return OK; 00421 } 00422 00423
Generated on Tue Jul 12 2022 17:34:43 by
