1 /* CDMASMSInterface.cpp */
2 /* Copyright (C) 2012 mbed.org, MIT License
4 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 * and associated documentation files (the "Software"), to deal in the Software without restriction,
6 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice shall be included in all copies or
11 * substantial portions of the Software.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 #define __MODULE__ "CDMASMSInterface.cpp"
27 #include "CDMASMSInterface.h"
34 #define DEFAULT_TIMEOUT 10000
36 CDMASMSInterface::CDMASMSInterface(ATCommandsInterface
* pIf
) : m_pIf(pIf
), m_msg(NULL
), m_maxMsgLength(0), m_msisdn(NULL
)
40 int CDMASMSInterface::init()
44 DBG("Get number of messages in the different inboxes");
45 int ret
= updateInbox();
51 DBG("Initialization done");
55 int CDMASMSInterface::send(const char* number
, const char* message
)
57 if( strlen(number
) > 16 )
59 return NET_INVALID
; //Number too long
65 m_state
= SMS_SEND_CMD_SENT
;
67 bool intlNumber
=(number
[0]=='+'); //If the number starts with the + sign, replace it with 011 instead (int'l dialing code in the US)
71 char cmd
[32+strlen(message
)];
72 std::sprintf(cmd
, "AT!SSMS=0,%s%s,,\"%s\"",intlNumber
?"011":"", intlNumber
?(number
+1):number
, message
); //Send with normal priority
73 ret
= m_pIf
->execute(cmd
, this, NULL
, DEFAULT_TIMEOUT
);
83 m_txState
= SMS_PENDING
;
88 m_state
= SMS_GET_TX_STATUS_CMD_SENT
;
89 ret
= m_pIf
->execute("AT!SSMS?", this, NULL
, DEFAULT_TIMEOUT
);
96 if(m_txState
== SMS_PENDING
) //Wait more
101 else if(m_txState
== SMS_FAILED
)
103 ERR("The modem could not send the SM");
104 return NET_CONN
; //Probably a conenction issue, the user can retry
113 ERR("The is still trying to send the SM");
120 int CDMASMSInterface::get(char* number
, char* message
, size_t maxLength
)
124 return NET_INVALID
; //Buffer too short
129 DBG("Get next message");
130 if( (m_msgInListsCount
[0] + m_msgInListsCount
[1] + m_msgInListsCount
[2]) == 0)
132 DBG("Message list count is 0 and needs updating. Running updateInbox.");
140 if( (m_msgInListsCount
[0] + m_msgInListsCount
[1] + m_msgInListsCount
[2]) == 0)
142 DBG("Message list count is 0");
143 return NET_EMPTY
; //No message to read
146 //Determine which index to use : 3 (read), then 1 (urgent), then 2 (regular)
148 if(m_msgInListsCount
[2])
152 else if(m_msgInListsCount
[0])
156 else //if(m_msgInListsCount[1])
162 m_state
= SMS_GET_CMD_SENT
;
163 m_msisdn
= (char*) number
;
164 m_msg
= (char*) message
;
165 m_maxMsgLength
= maxLength
;
173 std::sprintf(cmd
, "AT!GSMS?%d,1", index
); //1 is the oldest message
174 ret
= m_pIf
->execute(cmd
, this, NULL
, DEFAULT_TIMEOUT
);
177 WARN("AT!GSMS returned %d", ret
);
182 //If message is not read, it will be put at the end of the read list
186 //Decrement count in relevant list
187 m_msgInListsCount
[index
-1]--;
188 //Increment count in read list
189 m_msgInListsCount
[3-1]++;
190 item
= m_msgInListsCount
[3-1];
191 //Normally item should be equal to 1 as we'd have read any older messages first
194 WARN("Still some older messages pending in the read inbox");
199 //The item is still the oldest one
203 DBG("Deleting message");
204 //Delete message from inbox
205 std::sprintf(cmd
, "AT!DSMS=3"/*,%d", item*/); //FIXME why doesn't that work when specifying the index??
206 ret
= m_pIf
->executeSimple(cmd
, NULL
, DEFAULT_TIMEOUT
);
209 ERR("Could not delete message");
213 //Now we can decrease the number of read messages
214 m_msgInListsCount
[3-1]--;
217 if (m_state
!= SMS_CMD_PROCESSED
)
219 WARN("Message could not be retrieved properly");
230 int CDMASMSInterface::getCount(size_t* pCount
)
232 int ret
= updateInbox();
238 *pCount
= m_msgInListsCount
[0] + m_msgInListsCount
[1] + m_msgInListsCount
[2]; //Urgent messages + regular messages + read messages
244 /*virtual*/ int CDMASMSInterface::onNewATResponseLine(ATCommandsInterface
* pInst
, const char* line
)
246 if(m_state
== SMS_SEND_CMD_SENT
)
248 DBG("SMS Send: %s", line
);
250 else if(m_state
== SMS_GET_TX_STATUS_CMD_SENT
)
252 if(!strcmp(line
, "sent"))
254 m_txState
= SMS_SENT
;
255 m_state
= SMS_CMD_PROCESSED
;
257 else if(!strcmp(line
, "failed"))
259 m_txState
= SMS_FAILED
;
260 m_state
= SMS_CMD_PROCESSED
;
262 else if(!strcmp(line
, "none"))
264 m_txState
= SMS_NONE
;
265 m_state
= SMS_CMD_PROCESSED
;
267 else if(!strcmp(line
, "pending"))
269 m_txState
= SMS_PENDING
;
270 m_state
= SMS_CMD_PROCESSED
;
273 else if(m_state
== SMS_GET_CMD_SENT
)
275 DBG("Header: %s", line
);
277 if(m_msisdn
[0]=='\0')
279 sscanf(line
, "From: %16s", m_msisdn
);
284 if(m_headersToRead
==0) //End of headers
286 if(m_msisdn
[0]!='\0') //Checks that the incoming number has been retrieved
288 m_state
= SMS_GET_HDR_RECEIVED
;
292 m_state
= SMS_IDLE
; //Error, signal it
296 else if(m_state
== SMS_GET_HDR_RECEIVED
)
298 DBG("Message: %s", line
);
299 size_t cpyLen
= MIN( std::strlen(line
), m_maxMsgLength
- 1 );
300 std::memcpy( m_msg
, line
, cpyLen
);
301 m_msg
[cpyLen
] = '\0';
302 m_state
= SMS_CMD_PROCESSED
;
304 else if(m_state
== SMS_GET_COUNT_CMD_SENT
)
306 DBG("Inbox: %s", line
);
309 if((strlen(line
) > 16) && sscanf(line
+ 16, "{Index = %d}: %d", &index
, &count
) == 2)
311 if((index
> 0) && (index
<=4))
313 m_msgInListsCount
[index
-1] = count
;
317 m_state
= SMS_CMD_PROCESSED
;
324 /*virtual*/ int CDMASMSInterface::onNewEntryPrompt(ATCommandsInterface
* pInst
)
330 int CDMASMSInterface::updateInbox()
332 //Get number of unread/read messages
334 DBG("Updating inbox");
335 m_msgInListsCount
[0] = m_msgInListsCount
[1] = m_msgInListsCount
[2] = m_msgInListsCount
[3] = 0; //Reset counts
338 m_state
= SMS_GET_COUNT_CMD_SENT
;
339 int ret
= m_pIf
->execute("AT!CNTSMS", this, NULL
, DEFAULT_TIMEOUT
);
342 WARN("AT!CNTSMS returned %d", ret
);
343 m_msgInListsCount
[0] = m_msgInListsCount
[1] = m_msgInListsCount
[2] = m_msgInListsCount
[3] = 0; //Invalidate counts