Connection Manager library for u-blox cellular modules. It manages the modem for keeping data connection always active.
Revision 1:29ad1d1ac1f9, committed 2016-01-21
- Comitter:
- msinig
- Date:
- Thu Jan 21 14:00:25 2016 +0000
- Parent:
- 0:86284a262735
- Commit message:
- fix bugs
Changed in this revision
--- 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, ®Status); + res = cnRegLoop(cnLib, ®Status); + 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