Base library for cellular modem implementations
Dependencies: Socket lwip-sys lwip
Dependents: CellularUSBModem CellularUSBModem
CDMASMSInterface.cpp
00001 /* CDMASMSInterface.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__ "CDMASMSInterface.cpp" 00023 #endif 00024 00025 #include "core/fwk.h" 00026 00027 #include "CDMASMSInterface.h" 00028 00029 #include <cstdio> 00030 #include <cstring> 00031 00032 using std::sscanf; 00033 00034 #define DEFAULT_TIMEOUT 10000 00035 00036 CDMASMSInterface::CDMASMSInterface(ATCommandsInterface* pIf) : m_pIf(pIf), m_msg(NULL), m_maxMsgLength(0), m_msisdn(NULL) 00037 { 00038 } 00039 00040 int CDMASMSInterface::init() 00041 { 00042 m_state = SMS_IDLE; 00043 00044 DBG("Get number of messages in the different inboxes"); 00045 int ret = updateInbox(); 00046 if(ret) 00047 { 00048 return NET_PROTOCOL; 00049 } 00050 00051 DBG("Initialization done"); 00052 return OK; 00053 } 00054 00055 int CDMASMSInterface::send(const char* number, const char* message) 00056 { 00057 if( strlen(number) > 16 ) 00058 { 00059 return NET_INVALID; //Number too long 00060 } 00061 00062 int ret; 00063 00064 //Prepare infos 00065 m_state = SMS_SEND_CMD_SENT; 00066 00067 bool intlNumber=(number[0]=='+'); //If the number starts with the + sign, replace it with 011 instead (int'l dialing code in the US) 00068 00069 DBG("Send SM"); 00070 //Send command 00071 char cmd[32+strlen(message)]; 00072 std::sprintf(cmd, "AT!SSMS=0,%s%s,,\"%s\"",intlNumber?"011":"", intlNumber?(number+1):number, message); //Send with normal priority 00073 ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT); 00074 00075 if(ret != OK) 00076 { 00077 WARN("ret %d", ret); 00078 m_state = SMS_IDLE; 00079 return NET_PROTOCOL; 00080 } 00081 00082 DBG("Check status"); 00083 m_txState = SMS_PENDING; 00084 00085 int tries = 10; 00086 while(tries--) 00087 { 00088 m_state = SMS_GET_TX_STATUS_CMD_SENT; 00089 ret = m_pIf->execute("AT!SSMS?", this, NULL, DEFAULT_TIMEOUT); 00090 if(ret) 00091 { 00092 m_state = SMS_IDLE; 00093 return ret; 00094 } 00095 m_state = SMS_IDLE; 00096 if(m_txState == SMS_PENDING) //Wait more 00097 { 00098 Thread::wait(1000); 00099 continue; 00100 } 00101 else if(m_txState == SMS_FAILED) 00102 { 00103 ERR("The modem could not send the SM"); 00104 return NET_CONN; //Probably a conenction issue, the user can retry 00105 } 00106 else 00107 { 00108 break; 00109 } 00110 } 00111 if(!tries) 00112 { 00113 ERR("The is still trying to send the SM"); 00114 return NET_TIMEOUT; 00115 } 00116 return OK; 00117 } 00118 00119 00120 int CDMASMSInterface::get(char* number, char* message, size_t maxLength) 00121 { 00122 if( maxLength < 1 ) 00123 { 00124 return NET_INVALID; //Buffer too short 00125 } 00126 00127 int ret; 00128 00129 DBG("Get next message"); 00130 if( (m_msgInListsCount[0] + m_msgInListsCount[1] + m_msgInListsCount[2]) == 0) 00131 { 00132 DBG("Message list count is 0 and needs updating. Running updateInbox."); 00133 ret = updateInbox(); 00134 if (ret) 00135 { 00136 return ret; 00137 } 00138 } 00139 00140 if( (m_msgInListsCount[0] + m_msgInListsCount[1] + m_msgInListsCount[2]) == 0) 00141 { 00142 DBG("Message list count is 0"); 00143 return NET_EMPTY; //No message to read 00144 } 00145 00146 //Determine which index to use : 3 (read), then 1 (urgent), then 2 (regular) 00147 int index; 00148 if(m_msgInListsCount[2]) 00149 { 00150 index = 3; 00151 } 00152 else if(m_msgInListsCount[0]) 00153 { 00154 index = 1; 00155 } 00156 else //if(m_msgInListsCount[1]) 00157 { 00158 index = 2; 00159 } 00160 00161 //Prepare infos 00162 m_state = SMS_GET_CMD_SENT; 00163 m_msisdn = (char*) number; 00164 m_msg = (char*) message; 00165 m_maxMsgLength = maxLength; 00166 m_headersToRead = 3; 00167 00168 m_msisdn[0] = '\0'; 00169 00170 DBG("Get SMS"); 00171 //Read command 00172 char cmd[32]; 00173 std::sprintf(cmd, "AT!GSMS?%d,1", index); //1 is the oldest message 00174 ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT); 00175 if( ret != OK ) 00176 { 00177 WARN("AT!GSMS returned %d", ret); 00178 m_state = SMS_IDLE; 00179 return NET_PROTOCOL; 00180 } 00181 00182 //If message is not read, it will be put at the end of the read list 00183 int item; 00184 if( index != 3 ) 00185 { 00186 //Decrement count in relevant list 00187 m_msgInListsCount[index-1]--; 00188 //Increment count in read list 00189 m_msgInListsCount[3-1]++; 00190 item = m_msgInListsCount[3-1]; 00191 //Normally item should be equal to 1 as we'd have read any older messages first 00192 if( item != 1 ) 00193 { 00194 WARN("Still some older messages pending in the read inbox"); 00195 } 00196 } 00197 else 00198 { 00199 //The item is still the oldest one 00200 item = 1; 00201 } 00202 00203 DBG("Deleting message"); 00204 //Delete message from inbox 00205 std::sprintf(cmd, "AT!DSMS=3"/*,%d", item*/); //FIXME why doesn't that work when specifying the index?? 00206 ret = m_pIf->executeSimple(cmd, NULL, DEFAULT_TIMEOUT); 00207 if(ret != OK) 00208 { 00209 ERR("Could not delete message"); 00210 } 00211 else 00212 { 00213 //Now we can decrease the number of read messages 00214 m_msgInListsCount[3-1]--; 00215 } 00216 00217 if (m_state != SMS_CMD_PROCESSED) 00218 { 00219 WARN("Message could not be retrieved properly"); 00220 m_state = SMS_IDLE; 00221 return NET_EMPTY; 00222 } 00223 00224 m_state = SMS_IDLE; 00225 00226 return OK; 00227 } 00228 00229 00230 int CDMASMSInterface::getCount(size_t* pCount) 00231 { 00232 int ret = updateInbox(); 00233 if(ret) 00234 { 00235 return NET_PROTOCOL; 00236 } 00237 00238 *pCount = m_msgInListsCount[0] + m_msgInListsCount[1] + m_msgInListsCount[2]; //Urgent messages + regular messages + read messages 00239 00240 return OK; 00241 } 00242 00243 00244 /*virtual*/ int CDMASMSInterface::onNewATResponseLine(ATCommandsInterface* pInst, const char* line) 00245 { 00246 if(m_state == SMS_SEND_CMD_SENT) 00247 { 00248 DBG("SMS Send: %s", line); 00249 } 00250 else if(m_state == SMS_GET_TX_STATUS_CMD_SENT) 00251 { 00252 if(!strcmp(line, "sent")) 00253 { 00254 m_txState = SMS_SENT; 00255 m_state = SMS_CMD_PROCESSED; 00256 } 00257 else if(!strcmp(line, "failed")) 00258 { 00259 m_txState = SMS_FAILED; 00260 m_state = SMS_CMD_PROCESSED; 00261 } 00262 else if(!strcmp(line, "none")) 00263 { 00264 m_txState = SMS_NONE; 00265 m_state = SMS_CMD_PROCESSED; 00266 } 00267 else if(!strcmp(line, "pending")) 00268 { 00269 m_txState = SMS_PENDING; 00270 m_state = SMS_CMD_PROCESSED; 00271 } 00272 } 00273 else if(m_state == SMS_GET_CMD_SENT) 00274 { 00275 DBG("Header: %s", line); 00276 00277 if(m_msisdn[0]=='\0') 00278 { 00279 sscanf(line, "From: %16s", m_msisdn); 00280 } 00281 00282 m_headersToRead--; 00283 00284 if(m_headersToRead==0) //End of headers 00285 { 00286 if(m_msisdn[0]!='\0') //Checks that the incoming number has been retrieved 00287 { 00288 m_state = SMS_GET_HDR_RECEIVED; 00289 } 00290 else 00291 { 00292 m_state = SMS_IDLE; //Error, signal it 00293 } 00294 } 00295 } 00296 else if(m_state == SMS_GET_HDR_RECEIVED) 00297 { 00298 DBG("Message: %s", line); 00299 size_t cpyLen = MIN( std::strlen(line), m_maxMsgLength - 1 ); 00300 std::memcpy( m_msg, line, cpyLen ); 00301 m_msg[cpyLen] = '\0'; 00302 m_state = SMS_CMD_PROCESSED; 00303 } 00304 else if(m_state == SMS_GET_COUNT_CMD_SENT) 00305 { 00306 DBG("Inbox: %s", line); 00307 int index; 00308 size_t count; 00309 if((strlen(line) > 16) && sscanf(line + 16, "{Index = %d}: %d", &index, &count) == 2) 00310 { 00311 if((index > 0) && (index <=4)) 00312 { 00313 m_msgInListsCount[index-1] = count; 00314 } 00315 if(index == 4) 00316 { 00317 m_state = SMS_CMD_PROCESSED; 00318 } 00319 } 00320 } 00321 return OK; 00322 } 00323 00324 /*virtual*/ int CDMASMSInterface::onNewEntryPrompt(ATCommandsInterface* pInst) 00325 { 00326 return OK; 00327 } 00328 00329 00330 int CDMASMSInterface::updateInbox() 00331 { 00332 //Get number of unread/read messages 00333 00334 DBG("Updating inbox"); 00335 m_msgInListsCount[0] = m_msgInListsCount[1] = m_msgInListsCount[2] = m_msgInListsCount[3] = 0; //Reset counts 00336 00337 //Get counts 00338 m_state = SMS_GET_COUNT_CMD_SENT; 00339 int ret = m_pIf->execute("AT!CNTSMS", this, NULL, DEFAULT_TIMEOUT); 00340 if( ret != OK ) 00341 { 00342 WARN("AT!CNTSMS returned %d", ret); 00343 m_msgInListsCount[0] = m_msgInListsCount[1] = m_msgInListsCount[2] = m_msgInListsCount[3] = 0; //Invalidate counts 00344 m_state = SMS_IDLE; 00345 return NET_PROTOCOL; 00346 } 00347 00348 return OK; 00349 } 00350
Generated on Tue Jul 26 2022 09:42:59 by 1.7.2