Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
CellularConnectionFSM.cpp
00001 /* 00002 * Copyright (c) 2017, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "CellularConnectionFSM.h" 00019 00020 #ifdef CELLULAR_DEVICE 00021 00022 #ifndef MBED_TRACE_MAX_LEVEL 00023 #define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_INFO 00024 #endif 00025 #include "CellularLog.h" 00026 #include "CellularCommon.h" 00027 00028 // timeout to wait for AT responses 00029 #define TIMEOUT_POWER_ON (1*1000) 00030 #define TIMEOUT_SIM_PIN (1*1000) 00031 #define TIMEOUT_NETWORK (10*1000) 00032 #define TIMEOUT_CONNECT (60*1000) 00033 #define TIMEOUT_REGISTRATION (180*1000) 00034 00035 // maximum time when retrying network register, attach and connect in seconds ( 20minutes ) 00036 #define TIMEOUT_NETWORK_MAX (20*60) 00037 00038 #define RETRY_COUNT_DEFAULT 3 00039 00040 namespace mbed 00041 { 00042 00043 CellularConnectionFSM::CellularConnectionFSM() : 00044 _serial(0), _state(STATE_INIT), _next_state(_state), _status_callback(0), _event_status_cb(0), _network(0), _power(0), _sim(0), 00045 _queue(8 * EVENTS_EVENT_SIZE), _queue_thread(0), _cellularDevice(0), _retry_count(0), _event_timeout(-1), 00046 _at_queue(8 * EVENTS_EVENT_SIZE), _event_id(0), _plmn(0), _command_success(false), _plmn_network_found(false) 00047 { 00048 memset(_sim_pin, 0, sizeof(_sim_pin)); 00049 #if MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY == 0 00050 _start_time = 0; 00051 #else 00052 // so that not every device don't start at the exact same time (for example after power outage) 00053 _start_time = rand() % (MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY); 00054 #endif // MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY 00055 00056 // set initial retry values in seconds 00057 _retry_timeout_array[0] = 1; // double time on each retry in order to keep network happy 00058 _retry_timeout_array[1] = 2; 00059 _retry_timeout_array[2] = 4; 00060 _retry_timeout_array[3] = 8; 00061 _retry_timeout_array[4] = 16; 00062 _retry_timeout_array[5] = 32; 00063 _retry_timeout_array[6] = 64; 00064 _retry_timeout_array[7] = 128; // if around two minutes was not enough then let's wait much longer 00065 _retry_timeout_array[8] = 600; 00066 _retry_timeout_array[9] = TIMEOUT_NETWORK_MAX; 00067 _retry_array_length = MAX_RETRY_ARRAY_SIZE; 00068 } 00069 00070 CellularConnectionFSM::~CellularConnectionFSM() 00071 { 00072 stop(); 00073 } 00074 00075 void CellularConnectionFSM::stop() 00076 { 00077 _queue.cancel(_event_id); 00078 _queue.break_dispatch(); 00079 00080 if (_queue_thread) { 00081 _queue_thread->terminate(); 00082 delete _queue_thread; 00083 _queue_thread = NULL; 00084 } 00085 00086 delete _cellularDevice; 00087 _cellularDevice = NULL; 00088 // _cellularDevice closes all interfaces in destructor 00089 _power = NULL; 00090 _network = NULL; 00091 _sim = NULL; 00092 00093 _state = STATE_INIT; 00094 _next_state = _state; 00095 } 00096 00097 nsapi_error_t CellularConnectionFSM::init() 00098 { 00099 tr_info("CELLULAR_DEVICE: %s", CELLULAR_STRINGIFY(CELLULAR_DEVICE)); 00100 _cellularDevice = new CELLULAR_DEVICE(_at_queue); 00101 if (!_cellularDevice) { 00102 stop(); 00103 return NSAPI_ERROR_NO_MEMORY ; 00104 } 00105 00106 _power = _cellularDevice->open_power(_serial); 00107 if (!_power) { 00108 stop(); 00109 return NSAPI_ERROR_NO_MEMORY ; 00110 } 00111 00112 _network = _cellularDevice->open_network(_serial); 00113 if (!_network) { 00114 stop(); 00115 return NSAPI_ERROR_NO_MEMORY ; 00116 } 00117 00118 _sim = _cellularDevice->open_sim(_serial); 00119 if (!_sim) { 00120 stop(); 00121 return NSAPI_ERROR_NO_MEMORY ; 00122 } 00123 00124 _at_queue.chain(&_queue); 00125 00126 _retry_count = 0; 00127 _state = STATE_INIT; 00128 _next_state = STATE_INIT; 00129 00130 return _network->init(); 00131 } 00132 00133 bool CellularConnectionFSM::power_on() 00134 { 00135 nsapi_error_t err = _power->on(); 00136 if (err != NSAPI_ERROR_OK && err != NSAPI_ERROR_UNSUPPORTED ) { 00137 tr_warn("Cellular start failed. Power off/on."); 00138 err = _power->off(); 00139 if (err != NSAPI_ERROR_OK && err != NSAPI_ERROR_UNSUPPORTED ) { 00140 tr_error("Cellular power down failing after failed power up attempt!"); 00141 } 00142 return false; 00143 } 00144 return true; 00145 } 00146 00147 void CellularConnectionFSM::set_sim_pin(const char * sim_pin) 00148 { 00149 strncpy(_sim_pin, sim_pin, sizeof(_sim_pin)); 00150 _sim_pin[sizeof(_sim_pin)-1] = '\0'; 00151 } 00152 00153 void CellularConnectionFSM::set_plmn(const char* plmn) 00154 { 00155 _plmn = plmn; 00156 } 00157 00158 bool CellularConnectionFSM::open_sim() 00159 { 00160 CellularSIM::SimState state = CellularSIM::SimStateUnknown; 00161 // wait until SIM is readable 00162 // here you could add wait(secs) if you know start delay of your SIM 00163 if (_sim->get_sim_state(state) != NSAPI_ERROR_OK ) { 00164 tr_info("Waiting for SIM (err while reading)..."); 00165 return false; 00166 } 00167 00168 if (state == CellularSIM::SimStatePinNeeded) { 00169 if (strlen(_sim_pin)) { 00170 tr_info("SIM pin required, entering pin: %s", _sim_pin); 00171 nsapi_error_t err = _sim->set_pin(_sim_pin); 00172 if (err) { 00173 tr_error("SIM pin set failed with: %d, bailing out...", err); 00174 } 00175 } else { 00176 tr_warn("PIN required but No SIM pin provided."); 00177 } 00178 } 00179 00180 if (_event_status_cb) { 00181 _event_status_cb((nsapi_event_t)CellularSIMStatusChanged, state); 00182 } 00183 00184 return state == CellularSIM::SimStateReady; 00185 } 00186 00187 bool CellularConnectionFSM::set_network_registration() 00188 { 00189 if (_network->set_registration(_plmn) != NSAPI_ERROR_OK ) { 00190 tr_error("Failed to set network registration."); 00191 return false; 00192 } 00193 return true; 00194 } 00195 00196 bool CellularConnectionFSM::is_registered() 00197 { 00198 CellularNetwork::RegistrationStatus status; 00199 bool is_registered = false; 00200 00201 for (int type = 0; type < CellularNetwork::C_MAX; type++) { 00202 if (get_network_registration((CellularNetwork::RegistrationType) type, status, is_registered)) { 00203 tr_debug("get_network_registration: type=%d, status=%d", type, status); 00204 if (is_registered) { 00205 break; 00206 } 00207 } 00208 } 00209 00210 return is_registered; 00211 } 00212 00213 bool CellularConnectionFSM::get_network_registration(CellularNetwork::RegistrationType type, 00214 CellularNetwork::RegistrationStatus &status, bool &is_registered) 00215 { 00216 is_registered = false; 00217 bool is_roaming = false; 00218 nsapi_error_t err = _network->get_registration_status(type, status); 00219 if (err != NSAPI_ERROR_OK ) { 00220 if (err != NSAPI_ERROR_UNSUPPORTED ) { 00221 tr_warn("Get network registration failed (type %d)!", type); 00222 } 00223 return false; 00224 } 00225 switch (status) { 00226 case CellularNetwork::RegisteredRoaming: 00227 is_roaming = true; 00228 // fall-through 00229 case CellularNetwork::RegisteredHomeNetwork: 00230 is_registered = true; 00231 break; 00232 case CellularNetwork::RegisteredSMSOnlyRoaming: 00233 is_roaming = true; 00234 // fall-through 00235 case CellularNetwork::RegisteredSMSOnlyHome: 00236 tr_warn("SMS only network registration!"); 00237 break; 00238 case CellularNetwork::RegisteredCSFBNotPreferredRoaming: 00239 is_roaming = true; 00240 // fall-through 00241 case CellularNetwork::RegisteredCSFBNotPreferredHome: 00242 tr_warn("Not preferred network registration!"); 00243 break; 00244 case CellularNetwork::AttachedEmergencyOnly: 00245 tr_warn("Emergency only network registration!"); 00246 break; 00247 case CellularNetwork::RegistrationDenied: 00248 case CellularNetwork::NotRegistered: 00249 case CellularNetwork::Unknown: 00250 case CellularNetwork::SearchingNetwork: 00251 default: 00252 break; 00253 } 00254 00255 if (is_roaming) { 00256 tr_warn("Roaming cellular network!"); 00257 } 00258 00259 return true; 00260 } 00261 00262 bool CellularConnectionFSM::get_attach_network(CellularNetwork::AttachStatus &status) 00263 { 00264 nsapi_error_t err = _network->get_attach(status); 00265 if (err != NSAPI_ERROR_OK ) { 00266 return false; 00267 } 00268 return true; 00269 } 00270 00271 bool CellularConnectionFSM::set_attach_network() 00272 { 00273 nsapi_error_t attach_err = _network->set_attach(); 00274 if (attach_err != NSAPI_ERROR_OK ) { 00275 return false; 00276 } 00277 return true; 00278 } 00279 00280 void CellularConnectionFSM::report_failure(const char* msg) 00281 { 00282 tr_error("Cellular network failed: %s", msg); 00283 if (_status_callback) { 00284 _status_callback(_state, _next_state); 00285 } 00286 } 00287 00288 const char* CellularConnectionFSM::get_state_string(CellularState state) 00289 { 00290 #if MBED_CONF_MBED_TRACE_ENABLE 00291 static const char *strings[] = { "Init", "Power", "Device ready", "SIM pin", "Registering network", "Manual registering", "Attaching network", "Activating PDP Context", "Connecting network", "Connected"}; 00292 return strings[state]; 00293 #else 00294 return NULL; 00295 #endif // #if MBED_CONF_MBED_TRACE_ENABLE 00296 } 00297 00298 nsapi_error_t CellularConnectionFSM::is_automatic_registering(bool& auto_reg) 00299 { 00300 CellularNetwork::NWRegisteringMode mode; 00301 nsapi_error_t err = _network->get_network_registering_mode(mode); 00302 if (err == NSAPI_ERROR_OK ) { 00303 tr_debug("automatic registering mode: %d", mode); 00304 auto_reg = (mode == CellularNetwork::NWModeAutomatic); 00305 } 00306 return err; 00307 } 00308 00309 bool CellularConnectionFSM::is_registered_to_plmn() 00310 { 00311 int format; 00312 CellularNetwork::operator_t op; 00313 00314 nsapi_error_t err = _network->get_operator_params(format, op); 00315 if (err == NSAPI_ERROR_OK ) { 00316 if (format == 2) { 00317 // great, numeric format we can do comparison for that 00318 if (strcmp(op.op_num, _plmn) == 0) { 00319 return true; 00320 } 00321 return false; 00322 } 00323 00324 // format was alpha, get operator names to do the comparing 00325 CellularNetwork::operator_names_list names_list; 00326 nsapi_error_t err = _network->get_operator_names(names_list); 00327 if (err == NSAPI_ERROR_OK ) { 00328 CellularNetwork::operator_names_t* op_names = names_list.get_head(); 00329 bool found_match = false; 00330 while (op_names) { 00331 if (format == 0) { 00332 if (strcmp(op.op_long, op_names->alpha) == 0) { 00333 found_match = true; 00334 } 00335 } else if (format == 1) { 00336 if (strcmp(op.op_short, op_names->alpha) == 0) { 00337 found_match = true; 00338 } 00339 } 00340 00341 if (found_match) { 00342 if (strcmp(_plmn, op_names->numeric)) { 00343 names_list.delete_all(); 00344 return true; 00345 } 00346 names_list.delete_all(); 00347 return false; 00348 } 00349 } 00350 } 00351 names_list.delete_all(); 00352 } 00353 00354 return false; 00355 } 00356 00357 nsapi_error_t CellularConnectionFSM::continue_from_state(CellularState state) 00358 { 00359 tr_info("Continue state from %s to %s", get_state_string((CellularConnectionFSM::CellularState)_state), 00360 get_state_string((CellularConnectionFSM::CellularState)state)); 00361 _state = state; 00362 _next_state = state; 00363 _retry_count = 0; 00364 if (!_queue.call_in(0, callback(this, &CellularConnectionFSM::event))) { 00365 stop(); 00366 return NSAPI_ERROR_NO_MEMORY ; 00367 } 00368 00369 return NSAPI_ERROR_OK ; 00370 } 00371 00372 nsapi_error_t CellularConnectionFSM::continue_to_state(CellularState state) 00373 { 00374 MBED_ASSERT(_cellularDevice); 00375 _retry_count = 0; 00376 if (state < _state) { 00377 _state = state; 00378 } else { 00379 // update next state so that we don't continue from previous state 00380 _state = _next_state; 00381 } 00382 if (!_queue.call_in(0, callback(this, &CellularConnectionFSM::event))) { 00383 stop(); 00384 return NSAPI_ERROR_NO_MEMORY ; 00385 } 00386 00387 return NSAPI_ERROR_OK ; 00388 } 00389 00390 void CellularConnectionFSM::enter_to_state(CellularState state) 00391 { 00392 _next_state = state; 00393 _retry_count = 0; 00394 _command_success = false; 00395 } 00396 00397 void CellularConnectionFSM::retry_state_or_fail() 00398 { 00399 if (++_retry_count < MAX_RETRY_ARRAY_SIZE) { 00400 tr_debug("Retry State %s, retry %d/%d", get_state_string(_state), _retry_count, MAX_RETRY_ARRAY_SIZE); 00401 _event_timeout = _retry_timeout_array[_retry_count]; 00402 } else { 00403 report_failure(get_state_string(_state)); 00404 return; 00405 } 00406 } 00407 00408 void CellularConnectionFSM::state_init() 00409 { 00410 _event_timeout = _start_time; 00411 tr_info("Init state, waiting %d ms before POWER state)", _start_time); 00412 enter_to_state(STATE_POWER_ON); 00413 } 00414 00415 void CellularConnectionFSM::state_power_on() 00416 { 00417 _cellularDevice->set_timeout(TIMEOUT_POWER_ON); 00418 tr_info("Cellular power ON (timeout %d ms)", TIMEOUT_POWER_ON); 00419 if (power_on()) { 00420 enter_to_state(STATE_DEVICE_READY); 00421 } else { 00422 // retry to power on device 00423 retry_state_or_fail(); 00424 } 00425 } 00426 00427 bool CellularConnectionFSM::device_ready() 00428 { 00429 tr_info("Cellular device ready"); 00430 if (_event_status_cb) { 00431 _event_status_cb((nsapi_event_t)CellularDeviceReady, 0); 00432 } 00433 00434 _power->remove_device_ready_urc_cb(mbed::callback(this, &CellularConnectionFSM::ready_urc_cb)); 00435 00436 bool success = false; 00437 for (int type = 0; type < CellularNetwork::C_MAX; type++) { 00438 if (!_network->set_registration_urc((CellularNetwork::RegistrationType)type, true)) { 00439 success = true; 00440 } 00441 } 00442 if (!success) { 00443 tr_error("Failed to set any URC's for registration"); 00444 report_failure(get_state_string(_state)); 00445 return false; 00446 } 00447 00448 return true; 00449 } 00450 00451 void CellularConnectionFSM::state_device_ready() 00452 { 00453 _cellularDevice->set_timeout(TIMEOUT_POWER_ON); 00454 if (_power->set_at_mode() == NSAPI_ERROR_OK ) { 00455 if (device_ready()) { 00456 enter_to_state(STATE_SIM_PIN); 00457 } 00458 } else { 00459 if (_retry_count == 0) { 00460 (void)_power->set_device_ready_urc_cb(mbed::callback(this, &CellularConnectionFSM::ready_urc_cb)); 00461 } 00462 retry_state_or_fail(); 00463 } 00464 } 00465 00466 void CellularConnectionFSM::state_sim_pin() 00467 { 00468 _cellularDevice->set_timeout(TIMEOUT_SIM_PIN); 00469 tr_info("Sim state (timeout %d ms)", TIMEOUT_SIM_PIN); 00470 if (open_sim()) { 00471 if (_plmn) { 00472 enter_to_state(STATE_MANUAL_REGISTERING_NETWORK); 00473 } else { 00474 enter_to_state(STATE_REGISTERING_NETWORK); 00475 } 00476 } else { 00477 retry_state_or_fail(); 00478 } 00479 } 00480 00481 void CellularConnectionFSM::state_registering() 00482 { 00483 _cellularDevice->set_timeout(TIMEOUT_NETWORK); 00484 if (is_registered()) { 00485 // we are already registered, go to attach 00486 enter_to_state(STATE_ATTACHING_NETWORK); 00487 } else { 00488 bool auto_reg = false; 00489 nsapi_error_t err = is_automatic_registering(auto_reg); 00490 if (err == NSAPI_ERROR_OK && !auto_reg) { 00491 // automatic registering is not on, set registration and retry 00492 _cellularDevice->set_timeout(TIMEOUT_REGISTRATION); 00493 set_network_registration(); 00494 } 00495 retry_state_or_fail(); 00496 } 00497 } 00498 00499 // only used when _plmn is set 00500 void CellularConnectionFSM::state_manual_registering_network() 00501 { 00502 _cellularDevice->set_timeout(TIMEOUT_REGISTRATION); 00503 tr_info("state_manual_registering_network"); 00504 if (!_plmn_network_found) { 00505 if (is_registered() && is_registered_to_plmn()) { 00506 _plmn_network_found = true; 00507 enter_to_state(STATE_ATTACHING_NETWORK); 00508 } else { 00509 if (!_command_success) { 00510 _command_success = set_network_registration(); 00511 } 00512 retry_state_or_fail(); 00513 } 00514 } 00515 } 00516 00517 void CellularConnectionFSM::state_attaching() 00518 { 00519 _cellularDevice->set_timeout(TIMEOUT_CONNECT); 00520 CellularNetwork::AttachStatus attach_status; 00521 if (get_attach_network(attach_status)) { 00522 if (attach_status == CellularNetwork::Attached) { 00523 enter_to_state(STATE_ACTIVATING_PDP_CONTEXT); 00524 } else { 00525 if (!_command_success) { 00526 _command_success = set_attach_network(); 00527 } 00528 retry_state_or_fail(); 00529 } 00530 } else { 00531 retry_state_or_fail(); 00532 } 00533 } 00534 00535 void CellularConnectionFSM::state_activating_pdp_context() 00536 { 00537 _cellularDevice->set_timeout(TIMEOUT_CONNECT); 00538 tr_info("Activate PDP Context (timeout %d ms)", TIMEOUT_CONNECT); 00539 if (_network->activate_context() == NSAPI_ERROR_OK ) { 00540 // when using modems stack connect is synchronous 00541 _next_state = STATE_CONNECTING_NETWORK; 00542 } else { 00543 retry_state_or_fail(); 00544 } 00545 } 00546 00547 void CellularConnectionFSM::state_connect_to_network() 00548 { 00549 _cellularDevice->set_timeout(TIMEOUT_CONNECT); 00550 tr_info("Connect to cellular network (timeout %d ms)", TIMEOUT_CONNECT); 00551 if (_network->connect() == NSAPI_ERROR_OK ) { 00552 _cellularDevice->set_timeout(TIMEOUT_NETWORK); 00553 tr_debug("Connected to cellular network, set at timeout (timeout %d ms)", TIMEOUT_NETWORK); 00554 // when using modems stack connect is synchronous 00555 _next_state = STATE_CONNECTED; 00556 } else { 00557 retry_state_or_fail(); 00558 } 00559 } 00560 00561 void CellularConnectionFSM::state_connected() 00562 { 00563 _cellularDevice->set_timeout(TIMEOUT_NETWORK); 00564 tr_debug("Cellular ready! (timeout %d ms)", TIMEOUT_NETWORK); 00565 if (_status_callback) { 00566 _status_callback(_state, _next_state); 00567 } 00568 } 00569 00570 void CellularConnectionFSM::event() 00571 { 00572 _event_timeout = -1; 00573 switch (_state) { 00574 case STATE_INIT: 00575 state_init(); 00576 break; 00577 case STATE_POWER_ON: 00578 state_power_on(); 00579 break; 00580 case STATE_DEVICE_READY: 00581 state_device_ready(); 00582 break; 00583 case STATE_SIM_PIN: 00584 state_sim_pin(); 00585 break; 00586 case STATE_REGISTERING_NETWORK: 00587 state_registering(); 00588 break; 00589 case STATE_MANUAL_REGISTERING_NETWORK: 00590 state_manual_registering_network(); 00591 break; 00592 case STATE_ATTACHING_NETWORK: 00593 state_attaching(); 00594 break; 00595 case STATE_ACTIVATING_PDP_CONTEXT: 00596 state_activating_pdp_context(); 00597 break; 00598 case STATE_CONNECTING_NETWORK: 00599 state_connect_to_network(); 00600 break; 00601 case STATE_CONNECTED: 00602 state_connected(); 00603 break; 00604 default: 00605 MBED_ASSERT(0); 00606 break; 00607 } 00608 00609 if (_next_state != _state || _event_timeout >= 0) { 00610 if (_next_state != _state) { // state exit condition 00611 tr_info("Cellular state from %s to %s", get_state_string((CellularConnectionFSM::CellularState)_state), 00612 get_state_string((CellularConnectionFSM::CellularState)_next_state)); 00613 if (_status_callback) { 00614 if (!_status_callback(_state, _next_state)) { 00615 return; 00616 } 00617 } 00618 } else { 00619 tr_info("Cellular event in %d seconds", _event_timeout); 00620 } 00621 _state = _next_state; 00622 if (_event_timeout == -1) { 00623 _event_timeout = 0; 00624 } 00625 _event_id = _queue.call_in(_event_timeout*1000, callback(this, &CellularConnectionFSM::event)); 00626 if (!_event_id) { 00627 report_failure("Cellular event failure!"); 00628 return; 00629 } 00630 } 00631 } 00632 00633 nsapi_error_t CellularConnectionFSM::start_dispatch() 00634 { 00635 MBED_ASSERT(!_queue_thread); 00636 00637 _queue_thread = new rtos::Thread(osPriorityNormal, 2048); 00638 if (!_queue_thread) { 00639 stop(); 00640 return NSAPI_ERROR_NO_MEMORY ; 00641 } 00642 if (_queue_thread->start(callback(&_queue, &events::EventQueue::dispatch_forever)) != osOK) { 00643 stop(); 00644 return NSAPI_ERROR_NO_MEMORY ; 00645 } 00646 00647 return NSAPI_ERROR_OK ; 00648 } 00649 00650 void CellularConnectionFSM::set_serial(UARTSerial *serial) 00651 { 00652 _serial = serial; 00653 } 00654 00655 void CellularConnectionFSM::set_callback(mbed::Callback<bool(int, int)> status_callback) 00656 { 00657 _status_callback = status_callback; 00658 } 00659 00660 void CellularConnectionFSM::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb) 00661 { 00662 MBED_ASSERT(_network); 00663 _event_status_cb = status_cb; 00664 if (status_cb) { 00665 _network->attach(callback(this, &CellularConnectionFSM::network_callback)); 00666 } else { 00667 _network->attach(NULL); 00668 } 00669 } 00670 00671 void CellularConnectionFSM::network_callback(nsapi_event_t ev, intptr_t ptr) 00672 { 00673 tr_info("FSM: network_callback called with event: %d, intptr: %d, _state: %s", ev, ptr, get_state_string(_state)); 00674 if ((cellular_connection_status_t)ev == CellularRegistrationStatusChanged && 00675 (_state == STATE_REGISTERING_NETWORK || _state == STATE_MANUAL_REGISTERING_NETWORK)) { 00676 // expect packet data so only these states are valid 00677 if (ptr == CellularNetwork::RegisteredHomeNetwork || ptr == CellularNetwork::RegisteredRoaming) { 00678 if (_plmn) { 00679 if (is_registered_to_plmn()) { 00680 if (!_plmn_network_found) { 00681 _plmn_network_found = true; 00682 _queue.cancel(_event_id); 00683 continue_from_state(STATE_ATTACHING_NETWORK); 00684 } 00685 } 00686 } else { 00687 _queue.cancel(_event_id); 00688 continue_from_state(STATE_ATTACHING_NETWORK); 00689 } 00690 } 00691 } 00692 00693 if (_event_status_cb) { 00694 _event_status_cb(ev, ptr); 00695 } 00696 } 00697 00698 void CellularConnectionFSM::ready_urc_cb() 00699 { 00700 tr_debug("Device ready URC func called"); 00701 if (_state == STATE_DEVICE_READY && _power->set_at_mode() == NSAPI_ERROR_OK ) { 00702 tr_debug("State was STATE_DEVICE_READY and at mode ready, cancel state and move to next"); 00703 _queue.cancel(_event_id); 00704 if (device_ready()) { 00705 continue_from_state(STATE_SIM_PIN); 00706 } 00707 } 00708 } 00709 00710 events::EventQueue *CellularConnectionFSM::get_queue() 00711 { 00712 return &_queue; 00713 } 00714 00715 CellularNetwork* CellularConnectionFSM::get_network() 00716 { 00717 return _network; 00718 } 00719 00720 CellularDevice* CellularConnectionFSM::get_device() 00721 { 00722 return _cellularDevice; 00723 } 00724 00725 CellularSIM* CellularConnectionFSM::get_sim() 00726 { 00727 return _sim; 00728 } 00729 00730 NetworkStack *CellularConnectionFSM::get_stack() 00731 { 00732 return _cellularDevice->get_stack(); 00733 } 00734 00735 void CellularConnectionFSM::set_retry_timeout_array(uint16_t timeout[], int array_len) 00736 { 00737 _retry_array_length = array_len > MAX_RETRY_ARRAY_SIZE ? MAX_RETRY_ARRAY_SIZE : array_len; 00738 00739 for (int i = 0; i < _retry_array_length; i++) { 00740 _retry_timeout_array[i] = timeout[i]; 00741 } 00742 } 00743 00744 } // namespace 00745 00746 #endif // CELLULAR_DEVICE
Generated on Tue Jul 12 2022 18:18:29 by
