Mike Pulice / ublox_C200Test

Fork of SprintUSBModemHTTPClientTest by Donatien Garnier

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SMSInterface.cpp Source File

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