Connection Manager library for u-blox cellular modules. It manages the modem for keeping data connection always active.
CNManager.cpp
- Committer:
- msinig
- Date:
- 2016-01-12
- Revision:
- 0:86284a262735
- Child:
- 1:29ad1d1ac1f9
File content as of revision 0:86284a262735:
#include "CNManager.h" #include "CNData.h" #include "CNUtil.h" #include "CNLib.h" #include "CNReg.h" //! internal state typedef enum { MNG_NOT_INIT = 0, //!< not initiated MNG_RADIO_OFF, //!< radio is off MNG_RADIO_ON, //!< radio is on MNG_IDLE, //!< idle MNG_DATA_UP, //!< data connection is active MNG_ERROR_RESET, //!< reset 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 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; state = MNG_RADIO_OFF; moduleOn = powerOn; errorCounter = 0; cnRegInit(); cnDataInit(); dataOn = dataEnabled; cnRegSetRoaming(roomingEnabled); return true; } CNLib* cnGetMDM(){ return cnLib; } void cnSetPower(bool on){ moduleOn = on; } void cnSetDataEnabled(bool hasDataConnToBeEnabled){ dataOn = hasDataConnToBeEnabled; cnDataEnable(dataOn); } void cnSetRoamingOn(bool isRoomingEnabled){ cnRegSetRoaming(isRoomingEnabled); } void cnSetApn(const char *apn,const char* username/*= NULL*/,const char* password/*= NULL*/){ cnDataSetupApn(apn, username, password); } void cnSetSimPin(const char* pin){ if (pin!=NULL) strncpy(simPin,pin, sizeof(simPin)); } DataStatus cnGetDataConnStatus(){ return (state == MNG_DATA_UP)? DATA_CONNECTED : DATA_DISCONNECTED; } bool cnSetDebug(int level){ if (!setUtilDebugLevel(level)) return false; return true; } int cnLoop(){ int ret; MngState oldState = state; TRACE("%s enter \r\n", __FUNCTION__); //check if init has been called if (state == MNG_NOT_INIT){ ERROR("%s Module has not been initiated\r\n", __FUNCTION__); return false; } //switch on if (state == MNG_RADIO_OFF && moduleOn ){ INFO("%s: Switching ON radio \r\n", __FUNCTION__); cnDataEnable(dataOn); ret = radioSwitchOn(cnLib); state = (ret == RES_OK) ? MNG_RADIO_ON : MNG_ERROR_RESET; } //switch off if (state != MNG_RADIO_OFF && !moduleOn){ INFO("%s: Switching OFF radio \r\n", __FUNCTION__); if (state == MNG_DATA_UP) //disable data cnDataEnable(false); else if (state == MNG_IDLE){ //switching off cnDataReset(); cnRegReset(); radioSwitchOff(cnLib); state = MNG_RADIO_OFF; } } //sim initialization if (state == MNG_RADIO_ON ){ ret = simInit(cnLib, simPin); state = (ret == RES_OK) ? MNG_IDLE : MNG_ERROR_RESET; } //cycle the registration and data service if (state == MNG_IDLE || state == MNG_DATA_UP){ RegStatus regStatus; DataConnStatus dataStatus; //Tick the registration service cnRegLoop(cnLib, ®Status); //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); } else if (dataStatus == DATA_IS_DISCONNECTED){ state = MNG_IDLE; if (clientHandler!=NULL) clientHandler(DATA_DISCONNECTED); } } //error management if (state == MNG_ERROR_RESET){ //block state machine when errors reach a max value counter if (++errorCounter > MAX_ERROR_RETRIES) state = MNG_ERROR_STUCK; else{ //otherwise start reset procedure ERROR("State machine is in Error state, doing Reset.\r\n"); cnDataReset(); cnRegReset(); radioSwitchOff(cnLib); state = MNG_RADIO_OFF; } } //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"); return false; } //dump info if (getUtilDebugLevel() > 1 && oldState != state) dump(); 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 */ CNResp radioSwitchOn(CNLib*& lib) { TRACE("%s enter \r\n", __FUNCTION__); lib = new CNLib(); if (lib == NULL){ ERROR("Error on allocating lib\r\n"); 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"); goto error; } //init generic modem if (!RESPOK(lib->initModem())){ ERROR("Error on init device\r\n"); goto error; } //handle unknown device if (lib->getDev()->dev == MDMParser::DEV_UNKNOWN){ ERROR("Device is unknown\r\n"); goto error; } return RES_OK; error: return RES_ERROR; } /** Switch off the radio \param lib pointer to CN library */ CNResp radioSwitchOff(CNLib*& lib){ TRACE("%s enter \r\n", __FUNCTION__); if (lib != NULL){ lib->powerOff(); delete lib; } return RES_OK; } /** Sim Pin initialization \param lib pointer to CN library \param simPin sim pin */ CNResp simEnterPin(CNLib* lib, char* simPin){ int res; if (simPin == NULL){ ERROR("Sim Pin is required but not provided\r\n"); 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); return RES_ERROR_STUCK; } return RES_ERROR; } /** Sim initialization \param lib pointer to CN library \param simPin sim pin */ CNResp simInit(CNLib* lib, char* simPin) { CNResp res = RES_ERROR; int _simWaitCounter=0; TRACE("CNLib::%s enter\r\n", __FUNCTION__); do{ if (RESPOK(lib->simInit(NULL))) break; wait_ms(10); } while(_simWaitCounter++ < SIM_WAIT_MAX_CYCLE); INFO("Sim status is %d \r\n", lib->getDev()->sim); //handle sim status switch (lib->getDev()->sim){ case MDMParser::SIM_READY: INFO("Sim has been initiated correctly\r\n"); res = RES_OK; break; case MDMParser::SIM_PIN: INFO("Sim Pin is requested\r\n"); res = simEnterPin(lib, simPin); break; case MDMParser::SIM_MISSING: ERROR("Sim has not been inserted, HALT\r\n"); res = RES_ERROR; break; case MDMParser::SIM_PUK: ERROR("Sim Puk is required, HALT\r\n"); res = RES_ERROR_STUCK; break; case MDMParser::SIM_UNKNOWN: ERROR("Sim Unknown state\r\n"); res = RES_ERROR_STUCK; break; case MDMParser::WRONG_PIN: ERROR("Wrong sim pin provided, HALT\r\n"); res = RES_ERROR_STUCK; break; } //sim has been successfully initialized if (res == RES_OK){ lib->getSimInfo(); } return res; }