Connection Manager library for u-blox cellular modules. It manages the modem for keeping data connection always active.
CNManager.cpp@0:86284a262735, 2016-01-12 (annotated)
- Committer:
- msinig
- Date:
- Tue Jan 12 09:08:15 2016 +0000
- Revision:
- 0:86284a262735
- Child:
- 1:29ad1d1ac1f9
first drop
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
msinig | 0:86284a262735 | 1 | #include "CNManager.h" |
msinig | 0:86284a262735 | 2 | |
msinig | 0:86284a262735 | 3 | #include "CNData.h" |
msinig | 0:86284a262735 | 4 | #include "CNUtil.h" |
msinig | 0:86284a262735 | 5 | #include "CNLib.h" |
msinig | 0:86284a262735 | 6 | #include "CNReg.h" |
msinig | 0:86284a262735 | 7 | |
msinig | 0:86284a262735 | 8 | //! internal state |
msinig | 0:86284a262735 | 9 | typedef enum { |
msinig | 0:86284a262735 | 10 | MNG_NOT_INIT = 0, //!< not initiated |
msinig | 0:86284a262735 | 11 | MNG_RADIO_OFF, //!< radio is off |
msinig | 0:86284a262735 | 12 | MNG_RADIO_ON, //!< radio is on |
msinig | 0:86284a262735 | 13 | MNG_IDLE, //!< idle |
msinig | 0:86284a262735 | 14 | MNG_DATA_UP, //!< data connection is active |
msinig | 0:86284a262735 | 15 | MNG_ERROR_RESET, //!< reset |
msinig | 0:86284a262735 | 16 | MNG_ERROR_STUCK //!< unrecoverable error |
msinig | 0:86284a262735 | 17 | } MngState; |
msinig | 0:86284a262735 | 18 | |
msinig | 0:86284a262735 | 19 | |
msinig | 0:86284a262735 | 20 | static MngState state = MNG_NOT_INIT; //!< Manager state |
msinig | 0:86284a262735 | 21 | static bool moduleOn; //!< Module power requested power status |
msinig | 0:86284a262735 | 22 | static bool dataOn; |
msinig | 0:86284a262735 | 23 | static CNLib* cnLib; //!< Pointer to CN library |
msinig | 0:86284a262735 | 24 | static char simPin[10]; //!< Sim Pin |
msinig | 0:86284a262735 | 25 | static int errorCounter; //!< Error counter |
msinig | 0:86284a262735 | 26 | static evDataHandler clientHandler; //!< function point handler |
msinig | 0:86284a262735 | 27 | |
msinig | 0:86284a262735 | 28 | static CNResp radioSwitchOn(CNLib*& lib); |
msinig | 0:86284a262735 | 29 | static CNResp radioSwitchOff(CNLib*& lib); |
msinig | 0:86284a262735 | 30 | static CNResp simInit(CNLib* lib, char* simPin); |
msinig | 0:86284a262735 | 31 | |
msinig | 0:86284a262735 | 32 | static void dump(); |
msinig | 0:86284a262735 | 33 | |
msinig | 0:86284a262735 | 34 | bool cnInit(evDataHandler handler /*=NULL*/, bool powerOn /*=true*/, bool dataEnabled /*=true*/, bool roomingEnabled /*=true*/){ |
msinig | 0:86284a262735 | 35 | clientHandler = handler; |
msinig | 0:86284a262735 | 36 | state = MNG_RADIO_OFF; |
msinig | 0:86284a262735 | 37 | moduleOn = powerOn; |
msinig | 0:86284a262735 | 38 | errorCounter = 0; |
msinig | 0:86284a262735 | 39 | cnRegInit(); |
msinig | 0:86284a262735 | 40 | cnDataInit(); |
msinig | 0:86284a262735 | 41 | dataOn = dataEnabled; |
msinig | 0:86284a262735 | 42 | cnRegSetRoaming(roomingEnabled); |
msinig | 0:86284a262735 | 43 | return true; |
msinig | 0:86284a262735 | 44 | } |
msinig | 0:86284a262735 | 45 | |
msinig | 0:86284a262735 | 46 | CNLib* cnGetMDM(){ |
msinig | 0:86284a262735 | 47 | return cnLib; |
msinig | 0:86284a262735 | 48 | } |
msinig | 0:86284a262735 | 49 | |
msinig | 0:86284a262735 | 50 | void cnSetPower(bool on){ |
msinig | 0:86284a262735 | 51 | moduleOn = on; |
msinig | 0:86284a262735 | 52 | } |
msinig | 0:86284a262735 | 53 | |
msinig | 0:86284a262735 | 54 | void cnSetDataEnabled(bool hasDataConnToBeEnabled){ |
msinig | 0:86284a262735 | 55 | dataOn = hasDataConnToBeEnabled; |
msinig | 0:86284a262735 | 56 | cnDataEnable(dataOn); |
msinig | 0:86284a262735 | 57 | } |
msinig | 0:86284a262735 | 58 | |
msinig | 0:86284a262735 | 59 | void cnSetRoamingOn(bool isRoomingEnabled){ |
msinig | 0:86284a262735 | 60 | cnRegSetRoaming(isRoomingEnabled); |
msinig | 0:86284a262735 | 61 | } |
msinig | 0:86284a262735 | 62 | |
msinig | 0:86284a262735 | 63 | void cnSetApn(const char *apn,const char* username/*= NULL*/,const char* password/*= NULL*/){ |
msinig | 0:86284a262735 | 64 | cnDataSetupApn(apn, username, password); |
msinig | 0:86284a262735 | 65 | } |
msinig | 0:86284a262735 | 66 | |
msinig | 0:86284a262735 | 67 | void cnSetSimPin(const char* pin){ |
msinig | 0:86284a262735 | 68 | if (pin!=NULL) |
msinig | 0:86284a262735 | 69 | strncpy(simPin,pin, sizeof(simPin)); |
msinig | 0:86284a262735 | 70 | } |
msinig | 0:86284a262735 | 71 | |
msinig | 0:86284a262735 | 72 | DataStatus cnGetDataConnStatus(){ |
msinig | 0:86284a262735 | 73 | return (state == MNG_DATA_UP)? DATA_CONNECTED : DATA_DISCONNECTED; |
msinig | 0:86284a262735 | 74 | } |
msinig | 0:86284a262735 | 75 | |
msinig | 0:86284a262735 | 76 | bool cnSetDebug(int level){ |
msinig | 0:86284a262735 | 77 | if (!setUtilDebugLevel(level)) |
msinig | 0:86284a262735 | 78 | return false; |
msinig | 0:86284a262735 | 79 | return true; |
msinig | 0:86284a262735 | 80 | } |
msinig | 0:86284a262735 | 81 | |
msinig | 0:86284a262735 | 82 | int cnLoop(){ |
msinig | 0:86284a262735 | 83 | int ret; |
msinig | 0:86284a262735 | 84 | MngState oldState = state; |
msinig | 0:86284a262735 | 85 | |
msinig | 0:86284a262735 | 86 | TRACE("%s enter \r\n", __FUNCTION__); |
msinig | 0:86284a262735 | 87 | //check if init has been called |
msinig | 0:86284a262735 | 88 | if (state == MNG_NOT_INIT){ |
msinig | 0:86284a262735 | 89 | ERROR("%s Module has not been initiated\r\n", __FUNCTION__); |
msinig | 0:86284a262735 | 90 | return false; |
msinig | 0:86284a262735 | 91 | } |
msinig | 0:86284a262735 | 92 | //switch on |
msinig | 0:86284a262735 | 93 | if (state == MNG_RADIO_OFF && moduleOn ){ |
msinig | 0:86284a262735 | 94 | INFO("%s: Switching ON radio \r\n", __FUNCTION__); |
msinig | 0:86284a262735 | 95 | cnDataEnable(dataOn); |
msinig | 0:86284a262735 | 96 | ret = radioSwitchOn(cnLib); |
msinig | 0:86284a262735 | 97 | state = (ret == RES_OK) ? MNG_RADIO_ON : MNG_ERROR_RESET; |
msinig | 0:86284a262735 | 98 | } |
msinig | 0:86284a262735 | 99 | //switch off |
msinig | 0:86284a262735 | 100 | if (state != MNG_RADIO_OFF && !moduleOn){ |
msinig | 0:86284a262735 | 101 | INFO("%s: Switching OFF radio \r\n", __FUNCTION__); |
msinig | 0:86284a262735 | 102 | if (state == MNG_DATA_UP) |
msinig | 0:86284a262735 | 103 | //disable data |
msinig | 0:86284a262735 | 104 | cnDataEnable(false); |
msinig | 0:86284a262735 | 105 | else if (state == MNG_IDLE){ |
msinig | 0:86284a262735 | 106 | //switching off |
msinig | 0:86284a262735 | 107 | cnDataReset(); |
msinig | 0:86284a262735 | 108 | cnRegReset(); |
msinig | 0:86284a262735 | 109 | radioSwitchOff(cnLib); |
msinig | 0:86284a262735 | 110 | state = MNG_RADIO_OFF; |
msinig | 0:86284a262735 | 111 | } |
msinig | 0:86284a262735 | 112 | } |
msinig | 0:86284a262735 | 113 | //sim initialization |
msinig | 0:86284a262735 | 114 | if (state == MNG_RADIO_ON ){ |
msinig | 0:86284a262735 | 115 | ret = simInit(cnLib, simPin); |
msinig | 0:86284a262735 | 116 | state = (ret == RES_OK) ? MNG_IDLE : MNG_ERROR_RESET; |
msinig | 0:86284a262735 | 117 | } |
msinig | 0:86284a262735 | 118 | //cycle the registration and data service |
msinig | 0:86284a262735 | 119 | if (state == MNG_IDLE || state == MNG_DATA_UP){ |
msinig | 0:86284a262735 | 120 | RegStatus regStatus; |
msinig | 0:86284a262735 | 121 | DataConnStatus dataStatus; |
msinig | 0:86284a262735 | 122 | //Tick the registration service |
msinig | 0:86284a262735 | 123 | cnRegLoop(cnLib, ®Status); |
msinig | 0:86284a262735 | 124 | //Tick Data service |
msinig | 0:86284a262735 | 125 | cnDataLoop(cnLib, regStatus, &dataStatus); |
msinig | 0:86284a262735 | 126 | //manage data status |
msinig | 0:86284a262735 | 127 | if (dataStatus == DATA_IS_CONNECTED){ |
msinig | 0:86284a262735 | 128 | state = MNG_DATA_UP; |
msinig | 0:86284a262735 | 129 | if (clientHandler!=NULL) clientHandler(DATA_CONNECTED); |
msinig | 0:86284a262735 | 130 | } else if (dataStatus == DATA_IS_DISCONNECTED){ |
msinig | 0:86284a262735 | 131 | state = MNG_IDLE; |
msinig | 0:86284a262735 | 132 | if (clientHandler!=NULL) clientHandler(DATA_DISCONNECTED); |
msinig | 0:86284a262735 | 133 | } |
msinig | 0:86284a262735 | 134 | } |
msinig | 0:86284a262735 | 135 | //error management |
msinig | 0:86284a262735 | 136 | if (state == MNG_ERROR_RESET){ |
msinig | 0:86284a262735 | 137 | //block state machine when errors reach a max value counter |
msinig | 0:86284a262735 | 138 | if (++errorCounter > MAX_ERROR_RETRIES) |
msinig | 0:86284a262735 | 139 | state = MNG_ERROR_STUCK; |
msinig | 0:86284a262735 | 140 | else{ |
msinig | 0:86284a262735 | 141 | //otherwise start reset procedure |
msinig | 0:86284a262735 | 142 | ERROR("State machine is in Error state, doing Reset.\r\n"); |
msinig | 0:86284a262735 | 143 | cnDataReset(); |
msinig | 0:86284a262735 | 144 | cnRegReset(); |
msinig | 0:86284a262735 | 145 | radioSwitchOff(cnLib); |
msinig | 0:86284a262735 | 146 | state = MNG_RADIO_OFF; |
msinig | 0:86284a262735 | 147 | } |
msinig | 0:86284a262735 | 148 | } |
msinig | 0:86284a262735 | 149 | //when the state is stuck stay here forever |
msinig | 0:86284a262735 | 150 | if (state == MNG_ERROR_STUCK){ |
msinig | 0:86284a262735 | 151 | ERROR("State machine is in Blocked state, please change setting.\r\n"); |
msinig | 0:86284a262735 | 152 | return false; |
msinig | 0:86284a262735 | 153 | } |
msinig | 0:86284a262735 | 154 | //dump info |
msinig | 0:86284a262735 | 155 | if (getUtilDebugLevel() > 1 && oldState != state) |
msinig | 0:86284a262735 | 156 | dump(); |
msinig | 0:86284a262735 | 157 | return true; |
msinig | 0:86284a262735 | 158 | } |
msinig | 0:86284a262735 | 159 | |
msinig | 0:86284a262735 | 160 | void dump(){ |
msinig | 0:86284a262735 | 161 | INFO("cnanager Dump\r\n"); |
msinig | 0:86284a262735 | 162 | const char* txtState[] = { "Not Initiated", "Radio is Off", "Radio is On", \ |
msinig | 0:86284a262735 | 163 | "Idle", "Connected", "Reset Error", "Blocked Error"}; |
msinig | 0:86284a262735 | 164 | if (state < sizeof(txtState)/sizeof(*txtState)) |
msinig | 0:86284a262735 | 165 | INFO(" Internal State: %s\r\n", txtState[state]); |
msinig | 0:86284a262735 | 166 | } |
msinig | 0:86284a262735 | 167 | |
msinig | 0:86284a262735 | 168 | /** Switch On Radio |
msinig | 0:86284a262735 | 169 | \param lib pointer to library |
msinig | 0:86284a262735 | 170 | */ |
msinig | 0:86284a262735 | 171 | CNResp radioSwitchOn(CNLib*& lib) |
msinig | 0:86284a262735 | 172 | { |
msinig | 0:86284a262735 | 173 | TRACE("%s enter \r\n", __FUNCTION__); |
msinig | 0:86284a262735 | 174 | lib = new CNLib(); |
msinig | 0:86284a262735 | 175 | if (lib == NULL){ |
msinig | 0:86284a262735 | 176 | ERROR("Error on allocating lib\r\n"); |
msinig | 0:86284a262735 | 177 | goto error; |
msinig | 0:86284a262735 | 178 | } |
msinig | 0:86284a262735 | 179 | lib->setDebug(getUtilDebugLevel()); |
msinig | 0:86284a262735 | 180 | //power on the module and detect if alive |
msinig | 0:86284a262735 | 181 | if (!RESPOK(lib->powerOnModem())){ |
msinig | 0:86284a262735 | 182 | ERROR("Error on detecting the modem\r\n"); |
msinig | 0:86284a262735 | 183 | goto error; |
msinig | 0:86284a262735 | 184 | } |
msinig | 0:86284a262735 | 185 | //init generic modem |
msinig | 0:86284a262735 | 186 | if (!RESPOK(lib->initModem())){ |
msinig | 0:86284a262735 | 187 | ERROR("Error on init device\r\n"); |
msinig | 0:86284a262735 | 188 | goto error; |
msinig | 0:86284a262735 | 189 | } |
msinig | 0:86284a262735 | 190 | //handle unknown device |
msinig | 0:86284a262735 | 191 | if (lib->getDev()->dev == MDMParser::DEV_UNKNOWN){ |
msinig | 0:86284a262735 | 192 | ERROR("Device is unknown\r\n"); |
msinig | 0:86284a262735 | 193 | goto error; |
msinig | 0:86284a262735 | 194 | } |
msinig | 0:86284a262735 | 195 | return RES_OK; |
msinig | 0:86284a262735 | 196 | |
msinig | 0:86284a262735 | 197 | error: |
msinig | 0:86284a262735 | 198 | return RES_ERROR; |
msinig | 0:86284a262735 | 199 | |
msinig | 0:86284a262735 | 200 | } |
msinig | 0:86284a262735 | 201 | |
msinig | 0:86284a262735 | 202 | /** Switch off the radio |
msinig | 0:86284a262735 | 203 | \param lib pointer to CN library |
msinig | 0:86284a262735 | 204 | */ |
msinig | 0:86284a262735 | 205 | CNResp radioSwitchOff(CNLib*& lib){ |
msinig | 0:86284a262735 | 206 | TRACE("%s enter \r\n", __FUNCTION__); |
msinig | 0:86284a262735 | 207 | if (lib != NULL){ |
msinig | 0:86284a262735 | 208 | lib->powerOff(); |
msinig | 0:86284a262735 | 209 | delete lib; |
msinig | 0:86284a262735 | 210 | } |
msinig | 0:86284a262735 | 211 | return RES_OK; |
msinig | 0:86284a262735 | 212 | } |
msinig | 0:86284a262735 | 213 | |
msinig | 0:86284a262735 | 214 | /** Sim Pin initialization |
msinig | 0:86284a262735 | 215 | \param lib pointer to CN library |
msinig | 0:86284a262735 | 216 | \param simPin sim pin |
msinig | 0:86284a262735 | 217 | */ |
msinig | 0:86284a262735 | 218 | CNResp simEnterPin(CNLib* lib, char* simPin){ |
msinig | 0:86284a262735 | 219 | int res; |
msinig | 0:86284a262735 | 220 | |
msinig | 0:86284a262735 | 221 | if (simPin == NULL){ |
msinig | 0:86284a262735 | 222 | ERROR("Sim Pin is required but not provided\r\n"); |
msinig | 0:86284a262735 | 223 | return RES_ERROR_STUCK; |
msinig | 0:86284a262735 | 224 | } |
msinig | 0:86284a262735 | 225 | res = lib->simInit(simPin); |
msinig | 0:86284a262735 | 226 | if (RESPOK(res) ) |
msinig | 0:86284a262735 | 227 | return RES_OK; |
msinig | 0:86284a262735 | 228 | if (lib->getDev()->sim == MDMParser::WRONG_PIN){ |
msinig | 0:86284a262735 | 229 | ERROR("Sim pin, %s ,provided is wrong\r\n", simPin); |
msinig | 0:86284a262735 | 230 | return RES_ERROR_STUCK; |
msinig | 0:86284a262735 | 231 | } |
msinig | 0:86284a262735 | 232 | return RES_ERROR; |
msinig | 0:86284a262735 | 233 | } |
msinig | 0:86284a262735 | 234 | |
msinig | 0:86284a262735 | 235 | /** Sim initialization |
msinig | 0:86284a262735 | 236 | \param lib pointer to CN library |
msinig | 0:86284a262735 | 237 | \param simPin sim pin |
msinig | 0:86284a262735 | 238 | */ |
msinig | 0:86284a262735 | 239 | CNResp simInit(CNLib* lib, char* simPin) |
msinig | 0:86284a262735 | 240 | { |
msinig | 0:86284a262735 | 241 | CNResp res = RES_ERROR; |
msinig | 0:86284a262735 | 242 | int _simWaitCounter=0; |
msinig | 0:86284a262735 | 243 | TRACE("CNLib::%s enter\r\n", __FUNCTION__); |
msinig | 0:86284a262735 | 244 | |
msinig | 0:86284a262735 | 245 | do{ |
msinig | 0:86284a262735 | 246 | if (RESPOK(lib->simInit(NULL))) |
msinig | 0:86284a262735 | 247 | break; |
msinig | 0:86284a262735 | 248 | wait_ms(10); |
msinig | 0:86284a262735 | 249 | } while(_simWaitCounter++ < SIM_WAIT_MAX_CYCLE); |
msinig | 0:86284a262735 | 250 | INFO("Sim status is %d \r\n", lib->getDev()->sim); |
msinig | 0:86284a262735 | 251 | //handle sim status |
msinig | 0:86284a262735 | 252 | switch (lib->getDev()->sim){ |
msinig | 0:86284a262735 | 253 | case MDMParser::SIM_READY: |
msinig | 0:86284a262735 | 254 | INFO("Sim has been initiated correctly\r\n"); |
msinig | 0:86284a262735 | 255 | res = RES_OK; |
msinig | 0:86284a262735 | 256 | break; |
msinig | 0:86284a262735 | 257 | case MDMParser::SIM_PIN: |
msinig | 0:86284a262735 | 258 | INFO("Sim Pin is requested\r\n"); |
msinig | 0:86284a262735 | 259 | res = simEnterPin(lib, simPin); |
msinig | 0:86284a262735 | 260 | break; |
msinig | 0:86284a262735 | 261 | case MDMParser::SIM_MISSING: |
msinig | 0:86284a262735 | 262 | ERROR("Sim has not been inserted, HALT\r\n"); |
msinig | 0:86284a262735 | 263 | res = RES_ERROR; |
msinig | 0:86284a262735 | 264 | break; |
msinig | 0:86284a262735 | 265 | case MDMParser::SIM_PUK: |
msinig | 0:86284a262735 | 266 | ERROR("Sim Puk is required, HALT\r\n"); |
msinig | 0:86284a262735 | 267 | res = RES_ERROR_STUCK; |
msinig | 0:86284a262735 | 268 | break; |
msinig | 0:86284a262735 | 269 | case MDMParser::SIM_UNKNOWN: |
msinig | 0:86284a262735 | 270 | ERROR("Sim Unknown state\r\n"); |
msinig | 0:86284a262735 | 271 | res = RES_ERROR_STUCK; |
msinig | 0:86284a262735 | 272 | break; |
msinig | 0:86284a262735 | 273 | case MDMParser::WRONG_PIN: |
msinig | 0:86284a262735 | 274 | ERROR("Wrong sim pin provided, HALT\r\n"); |
msinig | 0:86284a262735 | 275 | res = RES_ERROR_STUCK; |
msinig | 0:86284a262735 | 276 | break; |
msinig | 0:86284a262735 | 277 | } |
msinig | 0:86284a262735 | 278 | //sim has been successfully initialized |
msinig | 0:86284a262735 | 279 | if (res == RES_OK){ |
msinig | 0:86284a262735 | 280 | lib->getSimInfo(); |
msinig | 0:86284a262735 | 281 | } |
msinig | 0:86284a262735 | 282 | return res; |
msinig | 0:86284a262735 | 283 | } |