Squashed 'tmk_core/' changes from 7967731..b9e0ea0
b9e0ea0 Merge commit '7fa9d8bdea3773d1195b04d98fcf27cf48ddd81d' as 'tool/mbed/mbed-sdk' 7fa9d8b Squashed 'tool/mbed/mbed-sdk/' content from commit 7c21ce5 git-subtree-dir: tmk_core git-subtree-split: b9e0ea08cb940de20b3610ecdda18e9d8cd7c552
This commit is contained in:
parent
a20ef7052c
commit
1fe4406f37
4198 changed files with 2016457 additions and 0 deletions
|
@ -0,0 +1,350 @@
|
|||
/* CDMASMSInterface.cpp */
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define __DEBUG__ 0
|
||||
#ifndef __MODULE__
|
||||
#define __MODULE__ "CDMASMSInterface.cpp"
|
||||
#endif
|
||||
|
||||
#include "core/fwk.h"
|
||||
|
||||
#include "CDMASMSInterface.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
using std::sscanf;
|
||||
|
||||
#define DEFAULT_TIMEOUT 10000
|
||||
|
||||
CDMASMSInterface::CDMASMSInterface(ATCommandsInterface* pIf) : m_pIf(pIf), m_msg(NULL), m_maxMsgLength(0), m_msisdn(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
int CDMASMSInterface::init()
|
||||
{
|
||||
m_state = SMS_IDLE;
|
||||
|
||||
DBG("Get number of messages in the different inboxes");
|
||||
int ret = updateInbox();
|
||||
if(ret)
|
||||
{
|
||||
return NET_PROTOCOL;
|
||||
}
|
||||
|
||||
DBG("Initialization done");
|
||||
return OK;
|
||||
}
|
||||
|
||||
int CDMASMSInterface::send(const char* number, const char* message)
|
||||
{
|
||||
if( strlen(number) > 16 )
|
||||
{
|
||||
return NET_INVALID; //Number too long
|
||||
}
|
||||
|
||||
int ret;
|
||||
|
||||
//Prepare infos
|
||||
m_state = SMS_SEND_CMD_SENT;
|
||||
|
||||
bool intlNumber=(number[0]=='+'); //If the number starts with the + sign, replace it with 011 instead (int'l dialing code in the US)
|
||||
|
||||
DBG("Send SM");
|
||||
//Send command
|
||||
char cmd[32+strlen(message)];
|
||||
std::sprintf(cmd, "AT!SSMS=0,%s%s,,\"%s\"",intlNumber?"011":"", intlNumber?(number+1):number, message); //Send with normal priority
|
||||
ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
|
||||
|
||||
if(ret != OK)
|
||||
{
|
||||
WARN("ret %d", ret);
|
||||
m_state = SMS_IDLE;
|
||||
return NET_PROTOCOL;
|
||||
}
|
||||
|
||||
DBG("Check status");
|
||||
m_txState = SMS_PENDING;
|
||||
|
||||
int tries = 10;
|
||||
while(tries--)
|
||||
{
|
||||
m_state = SMS_GET_TX_STATUS_CMD_SENT;
|
||||
ret = m_pIf->execute("AT!SSMS?", this, NULL, DEFAULT_TIMEOUT);
|
||||
if(ret)
|
||||
{
|
||||
m_state = SMS_IDLE;
|
||||
return ret;
|
||||
}
|
||||
m_state = SMS_IDLE;
|
||||
if(m_txState == SMS_PENDING) //Wait more
|
||||
{
|
||||
Thread::wait(1000);
|
||||
continue;
|
||||
}
|
||||
else if(m_txState == SMS_FAILED)
|
||||
{
|
||||
ERR("The modem could not send the SM");
|
||||
return NET_CONN; //Probably a conenction issue, the user can retry
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!tries)
|
||||
{
|
||||
ERR("The is still trying to send the SM");
|
||||
return NET_TIMEOUT;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
int CDMASMSInterface::get(char* number, char* message, size_t maxLength)
|
||||
{
|
||||
if( maxLength < 1 )
|
||||
{
|
||||
return NET_INVALID; //Buffer too short
|
||||
}
|
||||
|
||||
int ret;
|
||||
|
||||
DBG("Get next message");
|
||||
if( (m_msgInListsCount[0] + m_msgInListsCount[1] + m_msgInListsCount[2]) == 0)
|
||||
{
|
||||
DBG("Message list count is 0 and needs updating. Running updateInbox.");
|
||||
ret = updateInbox();
|
||||
if (ret)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if( (m_msgInListsCount[0] + m_msgInListsCount[1] + m_msgInListsCount[2]) == 0)
|
||||
{
|
||||
DBG("Message list count is 0");
|
||||
return NET_EMPTY; //No message to read
|
||||
}
|
||||
|
||||
//Determine which index to use : 3 (read), then 1 (urgent), then 2 (regular)
|
||||
int index;
|
||||
if(m_msgInListsCount[2])
|
||||
{
|
||||
index = 3;
|
||||
}
|
||||
else if(m_msgInListsCount[0])
|
||||
{
|
||||
index = 1;
|
||||
}
|
||||
else //if(m_msgInListsCount[1])
|
||||
{
|
||||
index = 2;
|
||||
}
|
||||
|
||||
//Prepare infos
|
||||
m_state = SMS_GET_CMD_SENT;
|
||||
m_msisdn = (char*) number;
|
||||
m_msg = (char*) message;
|
||||
m_maxMsgLength = maxLength;
|
||||
m_headersToRead = 3;
|
||||
|
||||
m_msisdn[0] = '\0';
|
||||
|
||||
DBG("Get SMS");
|
||||
//Read command
|
||||
char cmd[32];
|
||||
std::sprintf(cmd, "AT!GSMS?%d,1", index); //1 is the oldest message
|
||||
ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
|
||||
if( ret != OK )
|
||||
{
|
||||
WARN("AT!GSMS returned %d", ret);
|
||||
m_state = SMS_IDLE;
|
||||
return NET_PROTOCOL;
|
||||
}
|
||||
|
||||
//If message is not read, it will be put at the end of the read list
|
||||
int item;
|
||||
if( index != 3 )
|
||||
{
|
||||
//Decrement count in relevant list
|
||||
m_msgInListsCount[index-1]--;
|
||||
//Increment count in read list
|
||||
m_msgInListsCount[3-1]++;
|
||||
item = m_msgInListsCount[3-1];
|
||||
//Normally item should be equal to 1 as we'd have read any older messages first
|
||||
if( item != 1 )
|
||||
{
|
||||
WARN("Still some older messages pending in the read inbox");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//The item is still the oldest one
|
||||
item = 1;
|
||||
}
|
||||
|
||||
DBG("Deleting message");
|
||||
//Delete message from inbox
|
||||
std::sprintf(cmd, "AT!DSMS=3"/*,%d", item*/); //FIXME why doesn't that work when specifying the index??
|
||||
ret = m_pIf->executeSimple(cmd, NULL, DEFAULT_TIMEOUT);
|
||||
if(ret != OK)
|
||||
{
|
||||
ERR("Could not delete message");
|
||||
}
|
||||
else
|
||||
{
|
||||
//Now we can decrease the number of read messages
|
||||
m_msgInListsCount[3-1]--;
|
||||
}
|
||||
|
||||
if (m_state != SMS_CMD_PROCESSED)
|
||||
{
|
||||
WARN("Message could not be retrieved properly");
|
||||
m_state = SMS_IDLE;
|
||||
return NET_EMPTY;
|
||||
}
|
||||
|
||||
m_state = SMS_IDLE;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
int CDMASMSInterface::getCount(size_t* pCount)
|
||||
{
|
||||
int ret = updateInbox();
|
||||
if(ret)
|
||||
{
|
||||
return NET_PROTOCOL;
|
||||
}
|
||||
|
||||
*pCount = m_msgInListsCount[0] + m_msgInListsCount[1] + m_msgInListsCount[2]; //Urgent messages + regular messages + read messages
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*virtual*/ int CDMASMSInterface::onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
|
||||
{
|
||||
if(m_state == SMS_SEND_CMD_SENT)
|
||||
{
|
||||
DBG("SMS Send: %s", line);
|
||||
}
|
||||
else if(m_state == SMS_GET_TX_STATUS_CMD_SENT)
|
||||
{
|
||||
if(!strcmp(line, "sent"))
|
||||
{
|
||||
m_txState = SMS_SENT;
|
||||
m_state = SMS_CMD_PROCESSED;
|
||||
}
|
||||
else if(!strcmp(line, "failed"))
|
||||
{
|
||||
m_txState = SMS_FAILED;
|
||||
m_state = SMS_CMD_PROCESSED;
|
||||
}
|
||||
else if(!strcmp(line, "none"))
|
||||
{
|
||||
m_txState = SMS_NONE;
|
||||
m_state = SMS_CMD_PROCESSED;
|
||||
}
|
||||
else if(!strcmp(line, "pending"))
|
||||
{
|
||||
m_txState = SMS_PENDING;
|
||||
m_state = SMS_CMD_PROCESSED;
|
||||
}
|
||||
}
|
||||
else if(m_state == SMS_GET_CMD_SENT)
|
||||
{
|
||||
DBG("Header: %s", line);
|
||||
|
||||
if(m_msisdn[0]=='\0')
|
||||
{
|
||||
sscanf(line, "From: %16s", m_msisdn);
|
||||
}
|
||||
|
||||
m_headersToRead--;
|
||||
|
||||
if(m_headersToRead==0) //End of headers
|
||||
{
|
||||
if(m_msisdn[0]!='\0') //Checks that the incoming number has been retrieved
|
||||
{
|
||||
m_state = SMS_GET_HDR_RECEIVED;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_state = SMS_IDLE; //Error, signal it
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(m_state == SMS_GET_HDR_RECEIVED)
|
||||
{
|
||||
DBG("Message: %s", line);
|
||||
size_t cpyLen = MIN( std::strlen(line), m_maxMsgLength - 1 );
|
||||
std::memcpy( m_msg, line, cpyLen );
|
||||
m_msg[cpyLen] = '\0';
|
||||
m_state = SMS_CMD_PROCESSED;
|
||||
}
|
||||
else if(m_state == SMS_GET_COUNT_CMD_SENT)
|
||||
{
|
||||
DBG("Inbox: %s", line);
|
||||
int index;
|
||||
size_t count;
|
||||
if((strlen(line) > 16) && sscanf(line + 16, "{Index = %d}: %d", &index, &count) == 2)
|
||||
{
|
||||
if((index > 0) && (index <=4))
|
||||
{
|
||||
m_msgInListsCount[index-1] = count;
|
||||
}
|
||||
if(index == 4)
|
||||
{
|
||||
m_state = SMS_CMD_PROCESSED;
|
||||
}
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*virtual*/ int CDMASMSInterface::onNewEntryPrompt(ATCommandsInterface* pInst)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
int CDMASMSInterface::updateInbox()
|
||||
{
|
||||
//Get number of unread/read messages
|
||||
|
||||
DBG("Updating inbox");
|
||||
m_msgInListsCount[0] = m_msgInListsCount[1] = m_msgInListsCount[2] = m_msgInListsCount[3] = 0; //Reset counts
|
||||
|
||||
//Get counts
|
||||
m_state = SMS_GET_COUNT_CMD_SENT;
|
||||
int ret = m_pIf->execute("AT!CNTSMS", this, NULL, DEFAULT_TIMEOUT);
|
||||
if( ret != OK )
|
||||
{
|
||||
WARN("AT!CNTSMS returned %d", ret);
|
||||
m_msgInListsCount[0] = m_msgInListsCount[1] = m_msgInListsCount[2] = m_msgInListsCount[3] = 0; //Invalidate counts
|
||||
m_state = SMS_IDLE;
|
||||
return NET_PROTOCOL;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/* SMSInterface.h */
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CDMASMSINTERFACE_H_
|
||||
#define CDMASMSINTERFACE_H_
|
||||
|
||||
#include "SMSInterface.h"
|
||||
|
||||
#define MAX_SM 8
|
||||
|
||||
/** Component to use the Short Messages Service (SMS)
|
||||
*
|
||||
*/
|
||||
class CDMASMSInterface : public ISMSInterface, protected IATCommandsProcessor
|
||||
{
|
||||
public:
|
||||
/** Create SMSInterface instance
|
||||
@param pIf Pointer to the ATCommandsInterface instance to use
|
||||
*/
|
||||
CDMASMSInterface(ATCommandsInterface* pIf);
|
||||
|
||||
/** Initialize interface
|
||||
Configure SMS commands & register for SMS-related unsolicited result codes
|
||||
*/
|
||||
virtual int init();
|
||||
|
||||
/** Send a SM
|
||||
@param number The receiver's phone number
|
||||
@param message The message to send
|
||||
@return 0 on success, error code on failure
|
||||
*/
|
||||
virtual int send(const char* number, const char* message);
|
||||
|
||||
|
||||
/** Receive a SM
|
||||
@param number Pointer to a buffer to store the sender's phone number (must be at least 17 characters-long, including the space for the null-terminating char)
|
||||
@param message Pointer to a buffer to store the the incoming message
|
||||
@param maxLength Maximum message length that can be stored in buffer (including null-terminating character)
|
||||
@return 0 on success, error code on failure
|
||||
*/
|
||||
virtual int get(char* number, char* message, size_t maxLength);
|
||||
|
||||
|
||||
/** Get the number of SMs in the incoming box
|
||||
@param pCount pointer to store the number of unprocessed SMs on
|
||||
@return 0 on success, error code on failure
|
||||
*/
|
||||
virtual int getCount(size_t* pCount);
|
||||
|
||||
protected:
|
||||
//IATCommandsProcessor
|
||||
virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line);
|
||||
virtual int onNewEntryPrompt(ATCommandsInterface* pInst);
|
||||
|
||||
int updateInbox(); //Update messages count in the different inboxes
|
||||
|
||||
private:
|
||||
ATCommandsInterface* m_pIf;
|
||||
|
||||
//Current message
|
||||
char* m_msg;
|
||||
size_t m_maxMsgLength;
|
||||
char* m_msisdn;
|
||||
|
||||
//Messages list
|
||||
size_t m_msgInListsCount[4]; //4 lists
|
||||
|
||||
size_t m_headersToRead;
|
||||
|
||||
enum { SMS_NONE, SMS_SENT, SMS_PENDING, SMS_FAILED } m_txState;
|
||||
enum { SMS_IDLE, SMS_SEND_CMD_SENT, SMS_GET_TX_STATUS_CMD_SENT, SMS_GET_CMD_SENT, SMS_GET_HDR_RECEIVED, SMS_GET_COUNT_CMD_SENT, SMS_CMD_PROCESSED } m_state;
|
||||
};
|
||||
|
||||
#endif /* CDMASMSINTERFACE_H_ */
|
|
@ -0,0 +1,423 @@
|
|||
/* GSMSMSInterface.cpp */
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define __DEBUG__ 2
|
||||
#ifndef __MODULE__
|
||||
#define __MODULE__ "GSMSMSInterface.cpp"
|
||||
#endif
|
||||
|
||||
#include "core/fwk.h"
|
||||
|
||||
#include "GSMSMSInterface.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#define DEFAULT_TIMEOUT 10000
|
||||
|
||||
GSMSMSInterface::GSMSMSInterface(ATCommandsInterface* pIf) : m_pIf(pIf), m_msg(NULL), m_maxMsgLength(0), m_msisdn(NULL)
|
||||
{
|
||||
m_pIf->registerEventsHandler(this); //Add us to the unsolicited result codes handlers
|
||||
}
|
||||
|
||||
int GSMSMSInterface::init()
|
||||
{
|
||||
m_msgRefListCount = 0;
|
||||
m_needsUpdate = true;
|
||||
m_state = SMS_IDLE;
|
||||
|
||||
DBG("Set format");
|
||||
//Set Text mode format
|
||||
int ret = m_pIf->executeSimple("AT+CMGF=1", NULL, DEFAULT_TIMEOUT);
|
||||
if(ret != OK)
|
||||
{
|
||||
return NET_PROTOCOL;
|
||||
}
|
||||
|
||||
DBG("Setup new messages indication");
|
||||
//Setup new messages indication
|
||||
ret = m_pIf->executeSimple("AT+CNMI=2,1,0,0,0", NULL, DEFAULT_TIMEOUT);
|
||||
if(ret != OK)
|
||||
{
|
||||
return NET_PROTOCOL;
|
||||
}
|
||||
|
||||
DBG("Try to fetch inbox");
|
||||
m_inboxMtx.lock();
|
||||
if( m_needsUpdate )
|
||||
{
|
||||
ret = updateInbox(); //Fetch existing messages references
|
||||
if(ret)
|
||||
{
|
||||
m_inboxMtx.unlock();
|
||||
return NET_PROTOCOL;
|
||||
}
|
||||
}
|
||||
m_inboxMtx.unlock();
|
||||
|
||||
DBG("Initialization done");
|
||||
return OK;
|
||||
}
|
||||
|
||||
int GSMSMSInterface::send(const char* number, const char* message)
|
||||
{
|
||||
if( strlen(number) > 16 )
|
||||
{
|
||||
return NET_INVALID; //Number too long to match 3GPP spec
|
||||
}
|
||||
|
||||
int ret;
|
||||
|
||||
//Prepare infos
|
||||
m_state = SMS_SEND_CMD_SENT;
|
||||
m_msg = (char*) message;
|
||||
|
||||
DBG("Send SM");
|
||||
//Send command
|
||||
char cmd[32];
|
||||
std::sprintf(cmd, "AT+CMGS=\"%s\"", number);
|
||||
ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
|
||||
|
||||
if( (ret != OK) || (m_state != SMS_CMD_PROCESSED) )
|
||||
{
|
||||
WARN("ret %d, state %d", ret, m_state);
|
||||
m_state = SMS_IDLE;
|
||||
return NET_PROTOCOL;
|
||||
}
|
||||
|
||||
DBG("SM sent");
|
||||
m_state = SMS_IDLE;
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
int GSMSMSInterface::get(char* number, char* message, size_t maxLength)
|
||||
{
|
||||
if( maxLength < 1 )
|
||||
{
|
||||
return NET_INVALID; //Buffer too short
|
||||
}
|
||||
|
||||
int ret;
|
||||
|
||||
DBG("Get next message");
|
||||
m_inboxMtx.lock();
|
||||
if( ((m_msgRefListCount == 0) && m_needsUpdate) || ((m_msgRefListCount > 0) && (m_msgRefList[0] == -1)) )
|
||||
{
|
||||
DBG("Message list count is 0 and needs updating or next index is unknown, calling updateInbox()");
|
||||
ret = updateInbox();
|
||||
|
||||
if (ret)
|
||||
{
|
||||
m_inboxMtx.unlock();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
DBG("%d messages to read", m_msgRefListCount);
|
||||
|
||||
if(m_msgRefListCount == 0)
|
||||
{
|
||||
m_inboxMtx.unlock();
|
||||
DBG("Message list count is 0, I think it's empty and returning.");
|
||||
return NET_EMPTY; //No message to read
|
||||
}
|
||||
|
||||
//Prepare infos
|
||||
m_state = SMS_GET_CMD_SENT;
|
||||
m_msisdn = (char*) number;
|
||||
m_msg = (char*) message;
|
||||
m_maxMsgLength = maxLength;
|
||||
|
||||
DBG("Get SMS");
|
||||
//List command
|
||||
char cmd[32];
|
||||
std::sprintf(cmd, "AT+CMGR=%d", m_msgRefList[0]);
|
||||
ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
|
||||
if( ret != OK )
|
||||
{
|
||||
WARN("AT+CMGR returned %d", ret);
|
||||
m_state = SMS_IDLE;
|
||||
m_inboxMtx.unlock();
|
||||
return NET_PROTOCOL;
|
||||
}
|
||||
|
||||
if (m_state != SMS_CMD_PROCESSED)
|
||||
{
|
||||
WARN("State variable is not 'SMS_CMD_PROCESSED' - returning 'NET_EMPTY'");
|
||||
}
|
||||
|
||||
DBG("Deleting message from index number: %d", m_msgRefList[0] );
|
||||
//Delete message from outbox
|
||||
std::sprintf(cmd, "AT+CMGD=%d", m_msgRefList[0]);
|
||||
ret = m_pIf->executeSimple(cmd, NULL, DEFAULT_TIMEOUT);
|
||||
if(ret != OK)
|
||||
{
|
||||
ERR("Could not delete message");
|
||||
}
|
||||
//Remove message from list
|
||||
std::memmove(&m_msgRefList[0], &m_msgRefList[1], MIN(m_msgRefListCount-1,MAX_SM-1)*sizeof(m_msgRefList[0]));
|
||||
m_msgRefListCount--;
|
||||
|
||||
if(m_msgRefListCount > MAX_SM - 1) //Last message index is unknown, so put -1 to tell the lib to fetch it when needed
|
||||
{
|
||||
DBG("Last message index is unknown, will need to be updated");
|
||||
m_msgRefList[MAX_SM - 1] = -1;
|
||||
}
|
||||
|
||||
DBG("%d messages to read", m_msgRefListCount);
|
||||
|
||||
if (m_state != SMS_CMD_PROCESSED)
|
||||
{
|
||||
m_state = SMS_IDLE;
|
||||
m_inboxMtx.unlock();
|
||||
return NET_EMPTY;
|
||||
}
|
||||
|
||||
m_state = SMS_IDLE;
|
||||
m_inboxMtx.unlock();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
int GSMSMSInterface::getCount(size_t* pCount)
|
||||
{
|
||||
int ret;
|
||||
|
||||
m_inboxMtx.lock();
|
||||
if( m_needsUpdate )
|
||||
{
|
||||
ret = updateInbox();
|
||||
if(ret)
|
||||
{
|
||||
m_inboxMtx.unlock();
|
||||
return NET_PROTOCOL;
|
||||
}
|
||||
}
|
||||
|
||||
*pCount = m_msgRefListCount;
|
||||
m_inboxMtx.unlock();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*virtual*/ int GSMSMSInterface::onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
|
||||
{
|
||||
if(m_state == SMS_SEND_CMD_SENT)
|
||||
{
|
||||
if( std::sscanf(line, "+CMGS: %*d") == 0 )
|
||||
{
|
||||
DBG("SM sent");
|
||||
m_state = SMS_CMD_PROCESSED;
|
||||
}
|
||||
}
|
||||
else if(m_state == SMS_GET_CMD_SENT)
|
||||
{
|
||||
DBG("Header: %s", line);
|
||||
if( std::sscanf(line, "+CMGR: %*[^,],\"%16[^\"]\"", m_msisdn) == 1 ) //Get message ref
|
||||
{
|
||||
m_state = SMS_GET_HDR_RECEIVED;
|
||||
}
|
||||
}
|
||||
else if(m_state == SMS_GET_HDR_RECEIVED)
|
||||
{
|
||||
DBG("Message: %s", line);
|
||||
size_t cpyLen = MIN( std::strlen(line), m_maxMsgLength - 1 );
|
||||
std::memcpy( m_msg, line, cpyLen );
|
||||
m_msg[cpyLen] = '\0';
|
||||
m_state = SMS_CMD_PROCESSED;
|
||||
}
|
||||
else if(m_state == SMS_GET_COUNT_CMD_SENT)
|
||||
{
|
||||
DBG("Header: %s", line);
|
||||
int msgRef;
|
||||
if( std::sscanf(line, "+CMGL: %d,\"REC", &msgRef) == 1 ) //Filter on REC READ and REC UNREAD messages
|
||||
{
|
||||
m_state = SMS_GET_COUNT_HDR_RECEIVED;
|
||||
//Add message to list
|
||||
if(m_msgRefListCount < MAX_SM)
|
||||
{
|
||||
m_msgRefList[m_msgRefListCount] = msgRef;
|
||||
}
|
||||
m_msgRefListCount++; //Always count message
|
||||
DBG("m_msgRefListCount=%d",m_msgRefListCount);
|
||||
}
|
||||
}
|
||||
else if(m_state == SMS_GET_COUNT_HDR_RECEIVED)
|
||||
{
|
||||
DBG("Message (debug only): %s", line); //For debug only
|
||||
m_state = SMS_GET_COUNT_CMD_SENT;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*virtual*/ int GSMSMSInterface::onNewEntryPrompt(ATCommandsInterface* pInst)
|
||||
{
|
||||
if(m_state == SMS_SEND_CMD_SENT)
|
||||
{
|
||||
char* crPtr = strchr(m_msg, CR);
|
||||
if(crPtr != NULL)
|
||||
{
|
||||
int crPos = crPtr - m_msg;
|
||||
//Replace m_inputBuf[crPos] with null-terminating char
|
||||
m_msg[crPos] = '\x0';
|
||||
|
||||
//If there is a CR char, split message there
|
||||
|
||||
//Do print the message
|
||||
int ret = pInst->sendData(m_msg);
|
||||
if(ret)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
char cr[2] = {CR, '\0'};
|
||||
ret = pInst->sendData(cr);
|
||||
if(ret)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
m_msg += crPos;
|
||||
|
||||
if(m_msg[0] == LF)
|
||||
{
|
||||
m_msg++; //Discard LF char as well
|
||||
}
|
||||
|
||||
return NET_MOREINFO;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Do print the message
|
||||
pInst->sendData(m_msg);
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*virtual*/ bool GSMSMSInterface::isATCodeHandled(const char* atCode) //Is this AT code handled
|
||||
{
|
||||
DBG("AT code is %s", atCode);
|
||||
if( strcmp("+CMTI", atCode) == 0 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
DBG("Not handled");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*virtual*/ void GSMSMSInterface::onDispatchStart()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*virtual*/ void GSMSMSInterface::onDispatchStop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*virtual*/ char* GSMSMSInterface::getEventsEnableCommand()
|
||||
{
|
||||
return "AT+CNMI=2,1,0,0,0";
|
||||
}
|
||||
|
||||
/*virtual*/ char* GSMSMSInterface::getEventsDisableCommand()
|
||||
{
|
||||
return "AT+CNMI=0,0,0,0,0"; //Indications will be buffered within the modem and flushed back when the former command is executed
|
||||
}
|
||||
|
||||
/*virtual*/ void GSMSMSInterface::onEvent(const char* atCode, const char* evt)
|
||||
{
|
||||
if( strcmp("+CMTI", atCode) != 0 )
|
||||
{
|
||||
return; //Not supported
|
||||
}
|
||||
|
||||
DBG("Unsollicited result code: %s - %s", atCode, evt);
|
||||
|
||||
//Get index
|
||||
int msgRef;
|
||||
if(( std::sscanf(evt, "\"SM\",%d", &msgRef) == 1 ) ||
|
||||
( std::sscanf(evt, "\"ME\",%d", &msgRef) == 1 ))
|
||||
{
|
||||
DBG("Adding message to list (ref %d)", msgRef);
|
||||
if(m_inboxMtx.trylock())
|
||||
{
|
||||
//Add message to list
|
||||
if(m_msgRefListCount < MAX_SM)
|
||||
{
|
||||
m_msgRefList[m_msgRefListCount] = msgRef;
|
||||
}
|
||||
m_msgRefListCount++; //Always count message
|
||||
m_inboxMtx.unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN("Could not get lock");
|
||||
m_needsUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int GSMSMSInterface::updateInbox()
|
||||
{
|
||||
//Get memory indexes of unread messages
|
||||
|
||||
DBG("Updating inbox");
|
||||
m_msgRefListCount = 0; //Reset list
|
||||
m_needsUpdate = false; //Assume we won't need update after this routine (can be set to true by an incoming SM event)
|
||||
|
||||
//First list the "REC READ" messages that were not processed in the previous session
|
||||
m_state = SMS_GET_COUNT_CMD_SENT;
|
||||
int ret = m_pIf->execute("AT+CMGL=\"REC READ\"", this, NULL, DEFAULT_TIMEOUT);
|
||||
if( ret != OK )
|
||||
{
|
||||
WARN("AT+CMGL returned %d", ret);
|
||||
m_state = SMS_IDLE;
|
||||
m_msgRefListCount = 0; //List could be invalid
|
||||
m_needsUpdate = true;
|
||||
return NET_PROTOCOL;
|
||||
}
|
||||
|
||||
//Now list the "REC UNREAD" messages that were received by the modem since
|
||||
m_state = SMS_GET_COUNT_CMD_SENT;
|
||||
ret = m_pIf->execute("AT+CMGL=\"REC UNREAD\"", this, NULL, DEFAULT_TIMEOUT);
|
||||
if( ret != OK )
|
||||
{
|
||||
WARN("AT+CMGL returned %d", ret);
|
||||
m_state = SMS_IDLE;
|
||||
m_msgRefListCount = 0; //List could be invalid
|
||||
m_needsUpdate = true;
|
||||
return NET_PROTOCOL;
|
||||
}
|
||||
|
||||
DBG("%d incoming messages in inbox", m_msgRefListCount);
|
||||
|
||||
m_state = SMS_IDLE;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/* SMSInterface.h */
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef GSMSMSINTERFACE_H_
|
||||
#define GSMSMSINTERFACE_H_
|
||||
|
||||
#include "SMSInterface.h"
|
||||
|
||||
/** Component to use the Short Messages Service (SMS)
|
||||
*
|
||||
*/
|
||||
class GSMSMSInterface : public ISMSInterface, protected IATCommandsProcessor, IATEventsHandler
|
||||
{
|
||||
public:
|
||||
/** Create SMSInterface instance
|
||||
@param pIf Pointer to the ATCommandsInterface instance to use
|
||||
*/
|
||||
GSMSMSInterface(ATCommandsInterface* pIf);
|
||||
|
||||
/** Initialize interface
|
||||
Configure SMS commands & register for SMS-related unsolicited result codes
|
||||
*/
|
||||
virtual int init();
|
||||
|
||||
/** Send a SM
|
||||
@param number The receiver's phone number
|
||||
@param message The message to send
|
||||
@return 0 on success, error code on failure
|
||||
*/
|
||||
virtual int send(const char* number, const char* message);
|
||||
|
||||
|
||||
/** Receive a SM
|
||||
@param number Pointer to a buffer to store the sender's phone number (must be at least 17 characters-long, including the space for the null-terminating char)
|
||||
@param message Pointer to a buffer to store the the incoming message
|
||||
@param maxLength Maximum message length that can be stored in buffer (including null-terminating character)
|
||||
@return 0 on success, error code on failure
|
||||
*/
|
||||
virtual int get(char* number, char* message, size_t maxLength);
|
||||
|
||||
|
||||
/** Get the number of SMs in the incoming box
|
||||
@param pCount pointer to store the number of unprocessed SMs on
|
||||
@return 0 on success, error code on failure
|
||||
*/
|
||||
virtual int getCount(size_t* pCount);
|
||||
|
||||
protected:
|
||||
//IATCommandsProcessor
|
||||
virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line);
|
||||
virtual int onNewEntryPrompt(ATCommandsInterface* pInst);
|
||||
|
||||
//IATEventsHandler
|
||||
virtual bool isATCodeHandled(const char* atCode); //Is this AT code handled
|
||||
virtual void onDispatchStart();
|
||||
virtual void onDispatchStop();
|
||||
virtual char* getEventsEnableCommand();
|
||||
virtual char* getEventsDisableCommand();
|
||||
virtual void onEvent(const char* atCode, const char* evt);
|
||||
|
||||
//Updates messages count/references
|
||||
int updateInbox();
|
||||
|
||||
private:
|
||||
ATCommandsInterface* m_pIf;
|
||||
|
||||
//Current message
|
||||
char* m_msg;
|
||||
size_t m_maxMsgLength;
|
||||
char* m_msisdn;
|
||||
|
||||
//Messages list
|
||||
int m_msgRefList[MAX_SM];
|
||||
size_t m_msgRefListCount;
|
||||
bool m_needsUpdate;
|
||||
Mutex m_inboxMtx; //To protect concurrent accesses btw the user's thread and the AT thread
|
||||
|
||||
enum { SMS_IDLE, SMS_SEND_CMD_SENT, SMS_GET_CMD_SENT, SMS_GET_HDR_RECEIVED, SMS_GET_COUNT_CMD_SENT, SMS_GET_COUNT_HDR_RECEIVED, SMS_CMD_PROCESSED } m_state;
|
||||
};
|
||||
|
||||
#endif /* GSMSMSINTERFACE_H_ */
|
|
@ -0,0 +1,67 @@
|
|||
/* SMSInterface.h */
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ISMSINTERFACE_H_
|
||||
#define ISMSINTERFACE_H_
|
||||
|
||||
#include "core/fwk.h"
|
||||
|
||||
#include "rtos.h"
|
||||
|
||||
#include "at/ATCommandsInterface.h"
|
||||
|
||||
#define MAX_SM 8
|
||||
|
||||
/** Component to use the Short Messages Service (SMS)
|
||||
*
|
||||
*/
|
||||
class ISMSInterface
|
||||
{
|
||||
public:
|
||||
/** Initialize interface
|
||||
Configure SMS commands & register for SMS-related unsolicited result codes
|
||||
*/
|
||||
virtual int init() = 0;
|
||||
|
||||
|
||||
/** Send a SM
|
||||
@param number The receiver's phone number
|
||||
@param message The message to send
|
||||
@return 0 on success, error code on failure
|
||||
*/
|
||||
virtual int send(const char* number, const char* message) = 0;
|
||||
|
||||
|
||||
/** Receive a SM
|
||||
@param number Pointer to a buffer to store the sender's phone number (must be at least 17 characters-long, including the space for the null-terminating char)
|
||||
@param message Pointer to a buffer to store the the incoming message
|
||||
@param maxLength Maximum message length that can be stored in buffer (including null-terminating character)
|
||||
@return 0 on success, error code on failure
|
||||
*/
|
||||
virtual int get(char* number, char* message, size_t maxLength) = 0;
|
||||
|
||||
|
||||
/** Get the number of SMs in the incoming box
|
||||
@param pCount pointer to store the number of unprocessed SMs on
|
||||
@return 0 on success, error code on failure
|
||||
*/
|
||||
virtual int getCount(size_t* pCount) = 0;
|
||||
};
|
||||
|
||||
#endif /* ISMSINTERFACE_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue