Base library for cellular modem implementations

Dependencies:   Socket lwip-sys lwip

Dependents:   CellularUSBModem CellularUSBModem

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LinkMonitor.cpp Source File

LinkMonitor.cpp

00001 /* LinkMonitor.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__ "LinkMonitor.cpp"
00023 #endif
00024 
00025 #include "core/fwk.h"
00026 
00027 #include "LinkMonitor.h"
00028 
00029 #include <cstdio>
00030 using std::sscanf;
00031 
00032 #define DEFAULT_TIMEOUT 10000
00033 
00034 LinkMonitor::LinkMonitor(ATCommandsInterface* pIf) : m_pIf(pIf), m_rssi(0), m_registrationState(REGISTRATION_STATE_UNKNOWN), m_bearer(BEARER_UNKNOWN)
00035 {
00036   m_gsm = true;
00037 }
00038 
00039 int LinkMonitor::init(bool gsm)
00040 {
00041   m_gsm = gsm;
00042   if (m_gsm)
00043   {
00044     // we need to make sure that we setup the operator selection to be in 'numeric' format.
00045     // i.e. it is made up of a network and country code when returned by the modem e.g. Operator = 23415. This allows easy logic parsing for
00046     // setting up other network parameters in future.
00047     DBG("LinkMonitor::init() being called. This should only happen once: executinging AT+COPS=0,2");  
00048     int ret = m_pIf->executeSimple("AT+COPS=0,2", NULL, DEFAULT_TIMEOUT); //Configure to set the operator string to Country Code and mobile network code
00049     if(ret != OK)
00050     {
00051       WARN(" NET_PROTOCOL error from sending the AT+COPS command to the modem. ");
00052       return NET_PROTOCOL;
00053     }
00054   }
00055   return OK;
00056 }
00057 
00058 /*virtual*/ int LinkMonitor::onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
00059 {
00060   DBG("Line is %s", line);
00061   char n[32] = "";
00062   char s[32] = "";
00063   int v;
00064   if( sscanf(line, "+CREG: %*d,%d", &v) >= 1 ) //Reg state is valid
00065   {
00066     DBG("+CREG %d", v);
00067     switch( v )
00068     {
00069       case 0:
00070         m_registrationState = REGISTRATION_STATE_UNKNOWN;
00071         break;
00072       case 1:
00073         m_registrationState = REGISTRATION_STATE_HOME_NETWORK;
00074         break;
00075       case 2:
00076         m_registrationState = REGISTRATION_STATE_REGISTERING;
00077         break;
00078       case 3:
00079         m_registrationState = REGISTRATION_STATE_DENIED;  
00080         break;
00081       case 4:
00082         m_registrationState = REGISTRATION_STATE_NO_SIGNAL;  
00083         break;        
00084       case 5:
00085         m_registrationState = REGISTRATION_STATE_ROAMING;  
00086         break;
00087       default:
00088         m_registrationState = REGISTRATION_STATE_UNKNOWN;  
00089         break;
00090     }
00091   }
00092   else if( sscanf(line, "+COPS: %*d,%*d,\"%*[^\"]\",%d", &v) >= 1 )
00093   {
00094     DBG("+COPS %d", v);
00095     switch( v )
00096     {
00097       case 0:
00098         m_bearer = BEARER_GSM;
00099         break;
00100       case 2:
00101         m_bearer = BEARER_UMTS;
00102         break;
00103       case 3:
00104         m_bearer = BEARER_EDGE;
00105         break;
00106       case 4: //HSDPA
00107       case 5: //HSUPA
00108       case 6: //HSDPA + HSUPA
00109         m_bearer = BEARER_HSPA;
00110         break;
00111       case 7:
00112         m_bearer = BEARER_LTE;
00113         break;  
00114       case 1: //GSM Compact
00115       default:
00116         m_bearer = BEARER_UNKNOWN;
00117         break;
00118     }
00119   }
00120   else if( sscanf(line, "+CSQ: %d,%*d", &v) >= 1 )
00121   {
00122     DBG("+CSQ %d", v);
00123     if(v == 99) //Unknown
00124     {
00125       m_rssi = 0; //Unknown
00126     }
00127     else
00128     {
00129       m_rssi = -113 + 2*v;
00130     }
00131   }
00132   else if ( (sscanf(line, "+CNUM: \"%[^\"]\",\"%[^\"]\",%d", n, s, &v) == 3) || 
00133             (sscanf(line, "+CNUM: \"\",\"%[^\"]\",%d", s, &v) == 2) )
00134   {
00135       if (*s && ((v == 145/*number includes + */) || (v == 129/*otherwise*/))) {
00136         strcpy(m_phoneNumber, s);
00137       }
00138   }
00139   return OK;
00140 }
00141 
00142 /*virtual*/ int LinkMonitor::onNewEntryPrompt(ATCommandsInterface* pInst)
00143 {
00144   return OK;
00145 }
00146 
00147 int LinkMonitor::getState(int* pRssi, REGISTRATION_STATE* pRegistrationState, BEARER* pBearer)
00148 {
00149   m_rssi = 0;
00150   m_registrationState = REGISTRATION_STATE_UNKNOWN;
00151   m_bearer = BEARER_UNKNOWN;
00152   int ret = m_pIf->execute(m_gsm ? "AT+CREG?;+COPS?;+CSQ" : "AT+CREG?;+CSQ", this, NULL, DEFAULT_TIMEOUT); //Configure to get registration info & get it; get signal quality
00153   if(ret != OK)
00154   {
00155     return NET_PROTOCOL;
00156   }
00157   *pRssi = m_rssi;
00158   *pRegistrationState = m_registrationState;
00159   *pBearer = m_bearer;
00160   return OK;
00161 }
00162 
00163 int LinkMonitor::getPhoneNumber(char* phoneNumber)
00164 {
00165   *m_phoneNumber = '\0';
00166   if (m_gsm) {
00167     int ret = m_pIf->execute("AT+CNUM", this, NULL, DEFAULT_TIMEOUT);
00168     if(ret != OK)
00169     {
00170       return NET_PROTOCOL;
00171     }
00172   }
00173   strcpy(phoneNumber, m_phoneNumber);
00174   return OK;
00175 }