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