PHS module SMA-01 library. see: https://developer.mbed.org/users/phsfan/notebook/abitusbmodem/

Dependencies:   Socket lwip-sys lwip

Dependents:   AbitUSBModem_HTTPTest AbitUSBModem_MQTTTest AbitUSBModem_WebsocketTest AbitUSBModem_SMSTest

Fork of VodafoneUSBModem by mbed official

/media/uploads/phsfan/sma01_003.png

sms/SMSInterface.cpp

Committer:
phsfan
Date:
2015-02-25
Revision:
99:514e67a69ad6
Parent:
97:7d9cc95e2ea7

File content as of revision 99:514e67a69ad6:

/* SMSInterface.cpp */
/* Modified by 2015 phsfan
 *  for ABIT SMA-01
 */
/* 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__ "SMSInterface.cpp"
#endif

#include "core/fwk.h"

#include "SMSInterface.h"

#include <cstdio>
#include <cstring>

#define DEFAULT_TIMEOUT 10000
#define SHORT_MAIL_CODE "128145000013"

SMSInterface::SMSInterface(ATCommandsInterface* pIf) : m_pIf(pIf), m_msg(NULL), m_maxMsgLength(0), m_msisdn(NULL)
{
  DBG("registering sms");
  m_pIf->registerEventsHandler(this); //Add us to the unsolicited result codes handlers
  m_caller[0] = 0;
}

int SMSInterface::init()
{
  m_state = SMS_IDLE;

  DBG("Enable sms");
  //Enable sms
  int ret = m_pIf->executeSimple("AT#P1", NULL, DEFAULT_TIMEOUT);
  if(ret != OK)
  {
    return NET_PROTOCOL;
  }
  //Enable caller id
  ret = m_pIf->executeSimple("AT#B1", NULL, DEFAULT_TIMEOUT);
  if(ret != OK)
  {
    return NET_PROTOCOL;
  }

  DBG("Initialization done");
  return OK;
}

int SMSInterface::send(const char* number, const char* message)
{
  if( strlen(number) != 11 )
  {
    return NET_INVALID; //Number too long to match 3GPP spec
  }

  int ret;

  DBG("Send SM");
  //Send command
  char cmd[300];
  // set S register
  strcpy(cmd, "ATS202=" SHORT_MAIL_CODE);
  for (int i = 0; i < strlen(message); i ++) {
    std::sprintf(&cmd[strlen(cmd)], "%03d", (unsigned char)message[i]);
  }
  ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);

  if( ret != OK )
  {
    WARN("ret %d, state %d", ret, m_state);
    m_state = SMS_IDLE;
    return NET_PROTOCOL;
  }

  m_state = SMS_SEND_CMD_SENT;
  // send light mail
  std::sprintf(cmd, "ATDI%s##0", number);
  ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
  Thread::wait(500);

  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");
  // since unsolicited events are blocked during send SM events,it makes sense to update the mailbox
  m_state = SMS_IDLE;
  return OK;
}


int SMSInterface::get(char* number, char* message, size_t maxLength)
{
  if( maxLength < 1  )
  {
    return NET_INVALID; //Buffer too short
  }
  if (m_caller[0] == 0) {
    return NET_INVALID; //No sms
  }

  int ret;

  DBG("Get next message");

  //Prepare infos
  m_state = SMS_GET_CMD_SENT;
  m_msisdn = (char*) number;
  m_msg = (char*) message;
  m_maxMsgLength = maxLength;

  DBG("Get SMS");
  //Show register
  char cmd[32] = "ATS211?";
  ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
  if( ret != OK )
  {
    WARN("ATS211 returned %d", ret);
    m_state = SMS_IDLE;
    return NET_PROTOCOL;
  }

  if (m_state != SMS_CMD_PROCESSED)
  {
    WARN("State variable is not 'SMS_CMD_PROCESSED' - returning 'NET_EMPTY'");
  }

  strcpy(m_msisdn, m_caller);
  m_caller[0] = 0;
  m_state = SMS_IDLE;

  return OK;
}


/*virtual*/ int SMSInterface::onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
{
  if(m_state == SMS_SEND_CMD_SENT)
  {
    if( strncmp(line, "ALERT", 5) == 0 ) {
      DBG("SM send ALERT");
      m_state = SMS_CMD_PROCESSED;
    } else
    if( strncmp(line, "BUSY", 5) == 0 ) {
      DBG("SM send BUSY");
      m_state = SMS_CMD_BUSY;
    } else
    if( strncmp(line, "NO CARRIER", 10) == 0 ) {
      DBG("SM send NO CARRIER");
      m_state = SMS_IDLE;
    }
  }
  else if(m_state == SMS_GET_CMD_SENT)
  {
    DBG("SM recv: %s", line);
    if( strncmp(line, SHORT_MAIL_CODE, 12) == 0 ) { // light mail code
      int j = 0, c = 0, len = 0;
      for (int i = 12; i < strlen(line); i ++) {
        c = (c * 10) + (line[i] - '0');
        j ++;
        if (j >=3) {
          m_msg[len] = c;
          len ++;
          if (len >= m_maxMsgLength - 1) break;
          j = 0;
          c = 0;
        }
      }
      m_msg[len] = 0;
      DBG("message '%s'", m_msg);
      m_state = SMS_CMD_PROCESSED;
    }
  }
  return OK;
}

/*virtual*/ int SMSInterface::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] = '\0';

      //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 SMSInterface::isATCodeHandled(const char* atCode) //Is this AT code handled
{
    if(m_state == SMS_IDLE) {
        if( strncmp(atCode, "RING", 4) == 0 ) {
            m_caller[0] = 0;
            DBG("RING");
            m_state = SMS_RING;
        }
        return true;
    } else
    if(m_state == SMS_RING) {
        if( strncmp(atCode, "ID=", 3) == 0 ) {
            strncpy(m_caller, &atCode[3], sizeof(m_caller));
            m_caller[11] = 0;
            DBG("ID %s", m_caller);
        } else
        if( strncmp(atCode, "NO CARRIER", 10) == 0 ) {
            DBG("NO CARRIER");
            m_state = SMS_IDLE;
        }
        return true;
    }
    return false;
}

/*virtual*/ void SMSInterface::onDispatchStart()
{
    
}

/*virtual*/ void SMSInterface::onDispatchStop()
{
    
}

/*virtual*/ char* SMSInterface::getEventsEnableCommand()
{
    return NULL;
}

/*virtual*/ char* SMSInterface::getEventsDisableCommand()
{
    return NULL;
}

/*virtual*/ void SMSInterface::onEvent(const char* atCode, const char* evt)
{
}