Connection Manager library for u-blox cellular modules. It manages the modem for keeping data connection always active.

Dependents:   C027_demo_ConnMan

Files at this revision

API Documentation at this revision

Comitter:
msinig
Date:
Thu Jan 21 14:00:25 2016 +0000
Parent:
0:86284a262735
Commit message:
fix bugs

Changed in this revision

CNData.cpp Show annotated file Show diff for this revision Revisions of this file
CNManager.cpp Show annotated file Show diff for this revision Revisions of this file
CNManager.h Show annotated file Show diff for this revision Revisions of this file
CNReg.cpp Show annotated file Show diff for this revision Revisions of this file
CNReg.h Show annotated file Show diff for this revision Revisions of this file
--- a/CNData.cpp	Tue Jan 12 09:08:15 2016 +0000
+++ b/CNData.cpp	Thu Jan 21 14:00:25 2016 +0000
@@ -25,6 +25,7 @@
 static MDMParser::Auth auth;       //!<authentication mode (CHAP,PAP,NONE or DETECT)
 
 void cnDataInit(){
+    TRACE("%s enter \r\n", __FUNCTION__); 
     state =  DATA_DOWN;
     dataIsEnable = false;
     tmDataPullStatus.setExpireTimeout(TIMEOUT_CHECK_STATUS_DATA_CONNECITION);
@@ -36,6 +37,7 @@
 }
 
 void cnDataEnable(bool enabled){
+    TRACE("%s enter enabled: %d\r\n", __FUNCTION__, enabled);
     dataIsEnable = enabled;
 }
 
@@ -63,7 +65,8 @@
     *dataStatus = DATA_NO_CHANGES;
     MDMParser::IP ip;
     char *apn, *username, *password;
-
+    
+    TRACE("%s enter \r\n", __FUNCTION__); 
     //enable data connection
     if (dataIsEnable && IS_DATA_DISCONNECTED(state) && regStatus == REG_REGISTERED){
         if (!tmDataRetry.isOn() || tmDataRetry.isExpired()){
@@ -110,12 +113,13 @@
         *dataStatus = DATA_IS_DISCONNECTED;
         tmDataPullStatus.stop();
     }
+    
     //dump info
     if (getUtilDebugLevel() > 1 && ( HAS_DATA_ATTACHED(state, newState) ||  HAS_DATA_DEATTACHED(state, newState))){
         INFO("CNM Data Dump\r\n");
         const char* txtState[] = { "Undefined", "Up", "Down"};
         if (newState < sizeof(txtState)/sizeof(*txtState) && newState != DATA_UNDEFINED)
-            INFO("  State is now:  %s\r\n", txtState[newState]);
+            INFO("  State is now:  %s\r\n", txtState[newState]);    
         INFO("  Data is enabled: %s, has Data Attached: %s, has Data Detached: %s\r\n", BOOLTOSTR(dataIsEnable),\
                 BOOLTOSTR(HAS_DATA_ATTACHED(state, newState)), BOOLTOSTR(HAS_DATA_DEATTACHED(state, newState)));
         INFO("  Timer for Data Retry:  %d, Timer for Check Data %d \r\n", tmDataRetry.getRetryContunter(), \
--- a/CNManager.cpp	Tue Jan 12 09:08:15 2016 +0000
+++ b/CNManager.cpp	Thu Jan 21 14:00:25 2016 +0000
@@ -5,7 +5,7 @@
 #include "CNLib.h"
 #include "CNReg.h"
 
-//! internal state
+//! Manager internal state
 typedef enum {
     MNG_NOT_INIT = 0,       //!< not initiated
     MNG_RADIO_OFF,          //!< radio is off
@@ -16,26 +16,27 @@
     MNG_ERROR_STUCK         //!< unrecoverable error
 } MngState;
 
-
 static MngState state = MNG_NOT_INIT;    //!< Manager state
 static bool moduleOn;                    //!< Module power requested power status
 static bool dataOn;
 static CNLib* cnLib;                      //!< Pointer to CN library
 static char simPin[10];                   //!< Sim Pin
 static int errorCounter;                  //!< Error counter
-static evDataHandler clientHandler;       //!< function point handler
+static evMngHandler mngHandler;         //!< Function point handler
+static void* paramDataHandler;            //!< Pointer to pass to the handler    
+static int respError;
 
 static CNResp radioSwitchOn(CNLib*& lib);
 static CNResp radioSwitchOff(CNLib*& lib);
 static CNResp simInit(CNLib* lib, char* simPin);
 
-static void dump();
-
-bool cnInit(evDataHandler handler /*=NULL*/, bool powerOn /*=true*/, bool dataEnabled /*=true*/, bool roomingEnabled /*=true*/){
-    clientHandler = handler;
+bool cnInit(bool powerOn /*=true*/, bool dataEnabled /*=true*/, bool roomingEnabled /*=true*/){
+    mngHandler = NULL;
+    paramDataHandler = NULL;
     state = MNG_RADIO_OFF;
     moduleOn = powerOn;
     errorCounter = 0;
+    respError = 0;
     cnRegInit();
     cnDataInit();
     dataOn = dataEnabled;
@@ -43,8 +44,14 @@
     return true;
 }
 
-CNLib* cnGetMDM(){
-    return cnLib;
+void cnRegHandler(evMngHandler handler, void* param/*=NULL*/)
+{
+     mngHandler = handler;     
+     paramDataHandler = param;
+}
+
+MDMSerial* cnGetMDM(){
+    return (MDMSerial*) cnLib;
 }
 
 void cnSetPower(bool on){
@@ -52,6 +59,7 @@
 }
 
 void cnSetDataEnabled(bool hasDataConnToBeEnabled){
+     TRACE("%s enter \r\n", __FUNCTION__); 
     dataOn = hasDataConnToBeEnabled;
     cnDataEnable(dataOn);
 }
@@ -65,12 +73,12 @@
 }
 
 void cnSetSimPin(const char* pin){
-    if (pin!=NULL)
+    if (pin)
         strncpy(simPin,pin, sizeof(simPin)); 
 }
 
-DataStatus cnGetDataConnStatus(){
-    return (state == MNG_DATA_UP)? DATA_CONNECTED : DATA_DISCONNECTED;
+bool cnIsDataUp(){
+    return (state == MNG_DATA_UP)? true : false;
 }
 
 bool cnSetDebug(int level){
@@ -95,6 +103,7 @@
         cnDataEnable(dataOn);
         ret = radioSwitchOn(cnLib);
         state = (ret == RES_OK) ? MNG_RADIO_ON : MNG_ERROR_RESET;
+        
     }
     //switch off
     if (state != MNG_RADIO_OFF && !moduleOn){
@@ -114,22 +123,27 @@
     if (state == MNG_RADIO_ON ){
         ret = simInit(cnLib, simPin);
         state = (ret == RES_OK) ? MNG_IDLE : MNG_ERROR_RESET;
+        if (state == MNG_IDLE && mngHandler)
+            mngHandler(MNG_EV_IDLE, paramDataHandler);
     }
     //cycle the registration and data service
     if (state == MNG_IDLE ||  state == MNG_DATA_UP){
         RegStatus regStatus;
+        int res;
         DataConnStatus dataStatus;
         //Tick the registration service
-        cnRegLoop(cnLib, &regStatus);
+        res = cnRegLoop(cnLib, &regStatus);        
+        if (res != RES_OK && ++respError > MEX_RESP_ERROR)
+            state = MNG_ERROR_RESET;            
         //Tick Data service
         cnDataLoop(cnLib, regStatus, &dataStatus);
         //manage data status
         if (dataStatus == DATA_IS_CONNECTED){
-            state = MNG_DATA_UP;
-            if (clientHandler!=NULL) clientHandler(DATA_CONNECTED);
+            state = MNG_DATA_UP;            
+            if (mngHandler) mngHandler(MNG_EV_DATA_UP, paramDataHandler);
         } else if (dataStatus == DATA_IS_DISCONNECTED){
             state = MNG_IDLE;
-            if (clientHandler!=NULL) clientHandler(DATA_DISCONNECTED);
+            if (mngHandler) mngHandler(MNG_EV_DATA_DOWN, paramDataHandler);
         }
     }
     //error management
@@ -139,7 +153,8 @@
             state = MNG_ERROR_STUCK;
         else{
             //otherwise start reset procedure
-            ERROR("State machine is in Error state, doing Reset.\r\n");
+            ERROR("%s: State machine is in Error state, doing Reset.\r\n", __FUNCTION__);
+            respError=0;
             cnDataReset();
             cnRegReset();
             radioSwitchOff(cnLib);
@@ -148,23 +163,20 @@
     }
     //when the state is stuck stay here forever
     if (state == MNG_ERROR_STUCK){
-        ERROR("State machine is in Blocked state, please change setting.\r\n");
+        ERROR("%s: State machine is in Blocked state, please change setting.\r\n", __FUNCTION__);
         return false;
     }
     //dump info
-    if (getUtilDebugLevel() > 1 && oldState != state)
-        dump();
+    if (getUtilDebugLevel() > 1 && oldState != state){
+        INFO("CNManager Dump\r\n");
+        const char* txtState[] = { "Not Initiated", "Radio is Off", "Radio is On", \
+        "Idle", "Connected", "Reset Error", "Blocked Error"};
+        if (state < sizeof(txtState)/sizeof(*txtState))
+            INFO("  Internal State: %s\r\n", txtState[state]);
+    }
     return true;
 }
 
-void dump(){
-    INFO("cnanager Dump\r\n");
-    const char* txtState[] = { "Not Initiated", "Radio is Off", "Radio is On", \
-            "Idle", "Connected", "Reset Error", "Blocked Error"};
-    if (state < sizeof(txtState)/sizeof(*txtState))
-        INFO("  Internal State: %s\r\n", txtState[state]);
-}
-
 /** Switch On Radio
    \param lib pointer to library
  */
@@ -173,23 +185,23 @@
     TRACE("%s enter \r\n", __FUNCTION__);
     lib =  new CNLib();
     if (lib == NULL){
-        ERROR("Error on allocating lib\r\n");
+        ERROR("%s: Error on allocating lib\r\n", __FUNCTION__);
         goto error;
     }
     lib->setDebug(getUtilDebugLevel());
     //power on the module and detect if alive
     if (!RESPOK(lib->powerOnModem())){
-        ERROR("Error on detecting the modem\r\n");
+        ERROR("%s: Error on detecting the modem\r\n", __FUNCTION__);
         goto error;
     }
     //init generic modem
     if (!RESPOK(lib->initModem())){
-        ERROR("Error on init device\r\n");
+        ERROR("%s: Error on init device\r\n", __FUNCTION__);
         goto error;
     }
     //handle unknown device
     if (lib->getDev()->dev == MDMParser::DEV_UNKNOWN){
-        ERROR("Device is unknown\r\n");
+        ERROR("%s: Device is unknown\r\n", __FUNCTION__);
         goto error;
     }
     return RES_OK;
@@ -219,14 +231,14 @@
     int res;
 
     if (simPin == NULL){
-        ERROR("Sim Pin is required but not provided\r\n");
+        ERROR("%s: Sim Pin is required but not provided\r\n", __FUNCTION__);
         return RES_ERROR_STUCK;
     }
     res = lib->simInit(simPin);
     if (RESPOK(res) )
         return RES_OK;
     if (lib->getDev()->sim == MDMParser::WRONG_PIN){
-        ERROR("Sim pin, %s ,provided is wrong\r\n", simPin);
+        ERROR("%s: Sim pin, %s ,provided is wrong\r\n", simPin);
         return RES_ERROR_STUCK;
         }
     return RES_ERROR;
@@ -251,27 +263,27 @@
     //handle sim status
     switch (lib->getDev()->sim){
       case MDMParser::SIM_READY:
-          INFO("Sim has been initiated correctly\r\n");
+          INFO("%s: Sim has been initiated correctly\r\n", __FUNCTION__);
           res = RES_OK;
           break;
       case MDMParser::SIM_PIN:
-          INFO("Sim Pin is requested\r\n");
+          INFO("%s: Sim Pin is requested\r\n");
           res = simEnterPin(lib, simPin);
           break;
       case MDMParser::SIM_MISSING:
-          ERROR("Sim has not been inserted, HALT\r\n");
+          ERROR("%s: Sim has not been inserted, HALT\r\n", __FUNCTION__);
           res = RES_ERROR;
           break;
       case MDMParser::SIM_PUK:
-          ERROR("Sim Puk is required, HALT\r\n");
+          ERROR("%s: Sim Puk is required, HALT\r\n", __FUNCTION__);
           res = RES_ERROR_STUCK;
           break;
       case MDMParser::SIM_UNKNOWN:
-          ERROR("Sim Unknown state\r\n");
+          ERROR("%s: Sim Unknown state\r\n", __FUNCTION__);
           res = RES_ERROR_STUCK;
           break;
       case MDMParser::WRONG_PIN:
-          ERROR("Wrong sim pin provided, HALT\r\n");
+          ERROR("%s: Wrong sim pin provided, HALT\r\n", __FUNCTION__);
           res = RES_ERROR_STUCK;
           break;
     }
@@ -280,4 +292,13 @@
         lib->getSimInfo();
     }
     return res;
+}
+
+void getNetStatus(MDMParser::NetStatus* net){
+    if (net && cnLib)
+        memcpy(net, cnLib->getNet(), sizeof(MDMParser::NetStatus));
+}
+void getDevStatus(MDMParser::DevStatus* dev){
+    if (dev && cnLib)
+        memcpy(dev, cnLib->getDev(), sizeof(MDMParser::DevStatus));
 }
\ No newline at end of file
--- a/CNManager.h	Tue Jan 12 09:08:15 2016 +0000
+++ b/CNManager.h	Thu Jan 21 14:00:25 2016 +0000
@@ -7,30 +7,40 @@
 #define TIMEOUT_POLLING_NETWORK_STATUS          (5 * 1000)  //!< timeout for polling the network status
 #define MAX_ERROR_RETRIES                       5           //!< number of error before reset
 #define SIM_WAIT_MAX_CYCLE                      15          //!< wait cycle for sim init
+#define MEX_RESP_ERROR                          5
 
-//! Data events
-typedef enum{
-    DATA_DISCONNECTED = 0,  //!< Data channel is down
-    DATA_CONNECTED = 1,     //!< Data channel is up
-} DataStatus;
+//! Manager events
+typedef enum {    
+    MNG_EV_IDLE,               //!< idle
+    MNG_EV_DATA_UP,            //!< data connection is active
+    MNG_EV_DATA_DOWN,            //!< data connection is active
+} MngEvents;
+
 
 /** Function handler for data status updates
-  /param ev new data status 
+  /param ev new data status
+  /param param void pointer
 */
-typedef void (*evDataHandler) (DataStatus ev);
+typedef void (*evMngHandler) (MngEvents ev, void* param);
 
 /** Init Function
-  This function has to be called prior to CNMLoop
-   \param handler        Handler for data status changes
+  This function has to be called before CNMLoop
    \param powerOn        module power status at boot: enabled on, disabled off
    \param dataEnabled    data connection status at boot: enabled on, disabled off
    \param roomingEnabled unsolicited messages status: enabled on, disabled off
    \return true if successful false otherwise
  */
-bool cnInit(evDataHandler handler = NULL, bool powerOn = true, bool dataEnabled = true, bool roomingEnabled = true);
+bool cnInit(bool powerOn = true, bool dataEnabled = true, bool roomingEnabled = true);
+
+/**Handler registration
+   
+    \param handler   Handler for data status changes
+    \param param     void paramter to be passed to the handler
+*/
+void cnRegHandler(evMngHandler handler, void* param=NULL);
 
 /** Set the debug level.
-  This function has to be called prior to CNMLoop
+  This function has to be called before CNMLoop
    \param level -1 = OFF, 0 = ERROR, 1 = INFO(default), 2 = TRACE, 3 = ATCMD,TEST
    \return true if successful, false not possible
  */
@@ -60,7 +70,7 @@
 void cnSetDataEnabled(bool enabled);
 
 /** Set parameters for the GPRS service.
-This function has to be called prior to CNMLoop.
+This function has to be called before CNMLoop.
 If Apn parameters are not set, the internal APN info database will be used.
  \param apn the of the network provider e.g. "internet" or "apn.provider.com"
  \param username is the user name text string for the authentication phase
@@ -81,12 +91,21 @@
 void cnSetRoamingOn(bool enabled);
 
 /** Get data connection status.
- * \return dataStatus
+ * \return yes if connection is up, false otherways
  */
-DataStatus cnGetDataConnStatus();
+bool cnIsDataUp();
 
+/** Get the MDM library's pointer.
+ * \return the MDM pointer
+ */
+MDMSerial* cnGetMDM();
 
-/** Get the modem library's pointer.
- * \return the MDMParser pointer
+/** Get a copy of NetStatus.
+ * \param net pointer where NetStatus will be copied into
  */
-CNLib* cnGetMDM();
\ No newline at end of file
+void getNetStatus(MDMParser::NetStatus* net);
+
+/** Get a copy of DevStatus.
+ * \param dev pointer where DevStatus will be copied into
+ */
+void getDevStatus(MDMParser::DevStatus* dev);
\ No newline at end of file
--- a/CNReg.cpp	Tue Jan 12 09:08:15 2016 +0000
+++ b/CNReg.cpp	Thu Jan 21 14:00:25 2016 +0000
@@ -28,14 +28,19 @@
     statePS = MDMParser::REG_UNKNOWN;
 }
 
-CNResp cnRegLoop(CNLib* cnLib, RegStatus* status){
+CNResp cnRegLoop(CNLib* cnLib, RegStatus* regStatus){
     MDMParser::Reg newStateCS = cnLib->getNet()->csd;
     MDMParser::Reg newStatePS = cnLib->getNet()->psd;
     bool isRoamingRegister, isCSRegistered, hasCsRegister, hasCsDeRegister, isPSRegistered, hasPsRegister, hasPsDeRegister;
+    *regStatus = REG_NO_CHANGES;
+    int res;
     
+    TRACE("%s enter \r\n", __FUNCTION__); 
     //read and set COPS if necessary
-    if (cnLib->getNet()->regStatus == MDMParser::COPS_UNKOWN)
-        cnLib->getNetworkInfo();
+    if (cnLib->getNet()->regStatus == MDMParser::COPS_UNKOWN){
+        res = cnLib->getNetworkInfo();
+        if (!RESPOK(res)) return RES_ERROR;
+    }
     if (cnLib->getNet()->regStatus != MDMParser::COPS_AUTOMATIC_REG)
         cnLib->setNetAutoReg();    
     // poll registration info when timer expires
@@ -64,15 +69,15 @@
         if ((isCSRegistered && hasPsRegister) || (isPSRegistered &&  hasCsRegister) || \
                 (hasPsRegister && hasCsRegister) ){
             TRACE("%s CS and PS have just registered\r\n", __FUNCTION__);
-            *status = REG_REGISTERED;
+            *regStatus = REG_REGISTERED;
         }
         else if (hasPsDeRegister || hasCsDeRegister){
             TRACE("%s CS or PS are not registered\r\n", __FUNCTION__);
-            *status = REG_NOT_REGISTERED;
+            *regStatus = REG_NOT_REGISTERED;
         }
     }else{
         INFO("%s Roaming not allowed\r\n", __FUNCTION__);
-        *status = REG_NOT_REGISTERED;
+        *regStatus = REG_NOT_REGISTERED;
     }
     //Perform action in base of registration status
     if (hasCsRegister){
@@ -83,18 +88,18 @@
     }
     //Dump info
     if (getUtilDebugLevel() > 1 && (newStatePS != statePS || newStateCS != stateCS )){
-        const char* txtStatus[] = { "unchanged", "registered", "NOT anymore registered"};
+        const char* txtStatus[] = { "unchanged", "registered", "NOT registered"};
         INFO("cn registration Dump\r\n");
-        if (*status < sizeof(txtStatus)/sizeof(*txtStatus))
-                INFO("  Status is now %s\r\n", txtStatus[*status]);
+        if (*regStatus < sizeof(txtStatus)/sizeof(*txtStatus))
+                INFO("  Status is now %s\r\n", txtStatus[*regStatus]);
         INFO("  has CS Registered = %s, has CS DeRegistered = %s\r\n", BOOLTOSTR(hasCsRegister), BOOLTOSTR(hasCsDeRegister));
         INFO("  is Roaming active = %s, polling Timer %d\r\n", \
                 BOOLTOSTR(isRoamingRegister), tmStatusPull.read());
-        cnLib->dumpNetStatus(cnLib->getNet());
+        //cnLib->dumpNetStatus(cnLib->getNet());
     }
     //update status
     stateCS = newStateCS;
     statePS = newStatePS;
-
+    
     return RES_OK;    
 }
\ No newline at end of file
--- a/CNReg.h	Tue Jan 12 09:08:15 2016 +0000
+++ b/CNReg.h	Thu Jan 21 14:00:25 2016 +0000
@@ -5,8 +5,9 @@
 
 //! Registration Status
 typedef enum{
-    REG_NOT_REGISTERED = 0,   //!< Not registered
-    REG_REGISTERED = 1,       //!< Registered
+    REG_NO_CHANGES = 0,       //!< No changes
+    REG_NOT_REGISTERED = 1,   //!< Not registered
+    REG_REGISTERED = 2,       //!< Registered
 } RegStatus;
 
 /** Reg Init