From c9c3f85311f6fdd173cd70aa26017738d9f3c399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teppo=20J=C3=A4rvelin?= Date: Wed, 28 Feb 2018 15:44:45 +0200 Subject: [PATCH] Changed state machine class name and implementation. --- .../at_cellularnetworktest.cpp | 4 +- .../test_at_cellularnetwork.cpp | 4 +- .../stubs/AT_CellularNetwork_stub.cpp | 2 +- ...tionUtil.cpp => CellularConnectionFSM.cpp} | 231 +++++++++++------- ...nnectionUtil.h => CellularConnectionFSM.h} | 45 ++-- .../easy_cellular/EasyCellularConnection.cpp | 69 +++--- .../easy_cellular/EasyCellularConnection.h | 8 +- .../cellular/framework/API/CellularNetwork.h | 7 +- .../framework/AT/AT_CellularNetwork.cpp | 4 +- .../framework/AT/AT_CellularNetwork.h | 2 +- features/cellular/mbed_lib.json | 6 +- 11 files changed, 226 insertions(+), 156 deletions(-) rename features/cellular/easy_cellular/{CellularConnectionUtil.cpp => CellularConnectionFSM.cpp} (66%) rename features/cellular/easy_cellular/{CellularConnectionUtil.h => CellularConnectionFSM.h} (78%) diff --git a/features/cellular/UNITTESTS/at/at_cellularnetwork/at_cellularnetworktest.cpp b/features/cellular/UNITTESTS/at/at_cellularnetwork/at_cellularnetworktest.cpp index 7317556753..48e3518296 100644 --- a/features/cellular/UNITTESTS/at/at_cellularnetwork/at_cellularnetworktest.cpp +++ b/features/cellular/UNITTESTS/at/at_cellularnetwork/at_cellularnetworktest.cpp @@ -87,9 +87,9 @@ TEST(AT_CellularNetwork, test_AT_CellularNetwork_get_rate_control) unit->test_AT_CellularNetwork_get_rate_control(); } -TEST(AT_CellularNetwork, test_AT_CellularNetwork_get_backoff_time) +TEST(AT_CellularNetwork, test_AT_CellularNetwork_get_apn_backoff_timer) { - unit->test_AT_CellularNetwork_get_backoff_time(); + unit->test_AT_CellularNetwork_get_apn_backoff_timer(); } TEST(AT_CellularNetwork, test_AT_CellularNetwork_get_ip_address) diff --git a/features/cellular/UNITTESTS/at/at_cellularnetwork/test_at_cellularnetwork.cpp b/features/cellular/UNITTESTS/at/at_cellularnetwork/test_at_cellularnetwork.cpp index 1812221ee0..c0571e36d8 100644 --- a/features/cellular/UNITTESTS/at/at_cellularnetwork/test_at_cellularnetwork.cpp +++ b/features/cellular/UNITTESTS/at/at_cellularnetwork/test_at_cellularnetwork.cpp @@ -165,7 +165,7 @@ void Test_AT_CellularNetwork::test_AT_CellularNetwork_get_rate_control() CHECK(NSAPI_ERROR_OK == cn.get_rate_control(reports, timeUnit, ur)); } -void Test_AT_CellularNetwork::test_AT_CellularNetwork_get_backoff_time() +void Test_AT_CellularNetwork::test_AT_CellularNetwork_get_apn_backoff_timer() { EventQueue que; FileHandle_stub fh1; @@ -174,7 +174,7 @@ void Test_AT_CellularNetwork::test_AT_CellularNetwork_get_backoff_time() AT_CellularNetwork cn(at); int time; ATHandler_stub::nsapi_error_value = NSAPI_ERROR_CONNECTION_LOST; - CHECK(NSAPI_ERROR_CONNECTION_LOST == cn.get_backoff_time(time)); + CHECK(NSAPI_ERROR_CONNECTION_LOST == cn.get_apn_backoff_timer(time)); } diff --git a/features/cellular/UNITTESTS/stubs/AT_CellularNetwork_stub.cpp b/features/cellular/UNITTESTS/stubs/AT_CellularNetwork_stub.cpp index 222daf746a..c18cd32b4c 100644 --- a/features/cellular/UNITTESTS/stubs/AT_CellularNetwork_stub.cpp +++ b/features/cellular/UNITTESTS/stubs/AT_CellularNetwork_stub.cpp @@ -136,7 +136,7 @@ nsapi_error_t AT_CellularNetwork::get_attach(AttachStatus &status) } -nsapi_error_t AT_CellularNetwork::get_backoff_time(int &backoffTime) +nsapi_error_t AT_CellularNetwork::get_apn_backoff_timer(int &backoffTime) { return NSAPI_ERROR_OK; } diff --git a/features/cellular/easy_cellular/CellularConnectionUtil.cpp b/features/cellular/easy_cellular/CellularConnectionFSM.cpp similarity index 66% rename from features/cellular/easy_cellular/CellularConnectionUtil.cpp rename to features/cellular/easy_cellular/CellularConnectionFSM.cpp index 887d6eb5c4..1c39e133ea 100644 --- a/features/cellular/easy_cellular/CellularConnectionUtil.cpp +++ b/features/cellular/easy_cellular/CellularConnectionFSM.cpp @@ -15,7 +15,7 @@ * limitations under the License. */ -#include "CellularConnectionUtil.h" +#include #ifdef CELLULAR_DEVICE #ifndef MBED_TRACE_MAX_LEVEL @@ -29,25 +29,49 @@ #define TIMEOUT_NETWORK (10*1000) #define TIMEOUT_REGISTRATION (180*1000) +// maximum time when retrying network register, attach and connect in seconds ( 20minutes ) +#define TIMEOUT_NETWORK_MAX (20*60) + +#define RETRY_COUNT_DEFAULT 3 + namespace mbed { static events::EventQueue at_queue(8 * EVENTS_EVENT_SIZE); static CELLULAR_DEVICE cellularDevice(at_queue); static char device_info_buf[2048]; -CellularConnectionUtil::CellularConnectionUtil() : _serial(0), _state(STATE_POWER_ON), _next_state(_state), - _status_callback(0), _network(0), _power(0), _sim(0), _queue(8 * EVENTS_EVENT_SIZE), - _queue_thread(0), _cellularDevice(&cellularDevice) +CellularConnectionFSM::CellularConnectionFSM() : + _serial(0), _state(STATE_INIT), _next_state(_state), _status_callback(0), _network(0), _power(0), _sim(0), _queue( + 8 * EVENTS_EVENT_SIZE), _queue_thread(0), _cellularDevice(&cellularDevice), _retry_count(0), _state_retry_count( + 0) { memset(_sim_pin, 0, sizeof(_sim_pin)); +#if MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY == 0 + _start_time = 0; +#else + _start_time = rand() % (MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY); +#endif // MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY + + // set initial retry values in seconds + _retry_timeout_array[0] = 1; + _retry_timeout_array[1] = 2; + _retry_timeout_array[2] = 4; + _retry_timeout_array[3] = 16; + _retry_timeout_array[4] = 32; + _retry_timeout_array[5] = 60; + _retry_timeout_array[6] = 120; + _retry_timeout_array[7] = 360; + _retry_timeout_array[8] = 600; + _retry_timeout_array[9] = TIMEOUT_NETWORK_MAX; + _retry_array_length = MAX_RETRY_ARRAY_SIZE; } -CellularConnectionUtil::~CellularConnectionUtil() +CellularConnectionFSM::~CellularConnectionFSM() { stop(); } -nsapi_error_t CellularConnectionUtil::init() +nsapi_error_t CellularConnectionFSM::init() { _power = _cellularDevice->open_power(_serial); if (!_power) { @@ -72,7 +96,7 @@ nsapi_error_t CellularConnectionUtil::init() return NSAPI_ERROR_OK; } -bool CellularConnectionUtil::open_power(FileHandle *fh) +bool CellularConnectionFSM::open_power(FileHandle *fh) { if (!_power) { _power = _cellularDevice->open_power(fh); @@ -80,7 +104,6 @@ bool CellularConnectionUtil::open_power(FileHandle *fh) return false; } } - nsapi_error_t err = _power->on(); if (err != NSAPI_ERROR_OK && err != NSAPI_ERROR_UNSUPPORTED) { tr_warn("Cellular start failed. Power off/on."); @@ -93,12 +116,12 @@ bool CellularConnectionUtil::open_power(FileHandle *fh) return true; } -void CellularConnectionUtil::set_sim_pin(const char * sim_pin) +void CellularConnectionFSM::set_sim_pin(const char * sim_pin) { strncpy(_sim_pin, sim_pin, sizeof(_sim_pin)); } -bool CellularConnectionUtil::open_sim() +bool CellularConnectionFSM::open_sim() { CellularSIM::SimState state = CellularSIM::SimStateUnknown; // wait until SIM is readable @@ -123,7 +146,7 @@ bool CellularConnectionUtil::open_sim() if (_sim->get_sim_state(state) == NSAPI_ERROR_OK && state == CellularSIM::SimStateReady) { break; } - tr_debug("SIM state: %d", state); + tr_info("SIM state: %d", state); return false; } } @@ -134,7 +157,7 @@ bool CellularConnectionUtil::open_sim() return state == CellularSIM::SimStateReady; } -void CellularConnectionUtil::device_ready() +void CellularConnectionFSM::device_ready() { CellularInformation *info = _cellularDevice->open_information(_serial); @@ -149,15 +172,7 @@ void CellularConnectionUtil::device_ready() } } -bool CellularConnectionUtil::open_network() -{ - if (!_network) { - _network = _cellularDevice->open_network(_serial); - } - return (_network != NULL); -} - -bool CellularConnectionUtil::set_network_registration(char *plmn) +bool CellularConnectionFSM::set_network_registration(char *plmn) { if (_network->set_registration(plmn) != NSAPI_ERROR_OK) { tr_error("Failed to set network registration."); @@ -166,13 +181,13 @@ bool CellularConnectionUtil::set_network_registration(char *plmn) return true; } -bool CellularConnectionUtil::get_network_registration(CellularNetwork::RegistrationType type, +bool CellularConnectionFSM::get_network_registration(CellularNetwork::RegistrationType type, CellularNetwork::RegistrationStatus &status, bool &is_registered) { is_registered = false; bool is_roaming = false; nsapi_error_t err = _network->get_registration_status(type, status); - if (err != NSAPI_ERROR_OK) { + if (err != NSAPI_ERROR_OK) { if (err != NSAPI_ERROR_UNSUPPORTED) { tr_warn("Get network registration failed (type %d)!", type); } @@ -181,19 +196,19 @@ bool CellularConnectionUtil::get_network_registration(CellularNetwork::Registrat switch (status) { case CellularNetwork::RegisteredRoaming: is_roaming = true; - // fall-through + // fall-through case CellularNetwork::RegisteredHomeNetwork: is_registered = true; break; case CellularNetwork::RegisteredSMSOnlyRoaming: is_roaming = true; - // fall-through + // fall-through case CellularNetwork::RegisteredSMSOnlyHome: tr_warn("SMS only network registration!"); break; case CellularNetwork::RegisteredCSFBNotPreferredRoaming: is_roaming = true; - // fall-through + // fall-through case CellularNetwork::RegisteredCSFBNotPreferredHome: tr_warn("Not preferred network registration!"); break; @@ -215,7 +230,7 @@ bool CellularConnectionUtil::get_network_registration(CellularNetwork::Registrat return true; } -bool CellularConnectionUtil::get_attach_network(CellularNetwork::AttachStatus &status) +bool CellularConnectionFSM::get_attach_network(CellularNetwork::AttachStatus &status) { nsapi_error_t err = _network->get_attach(status); if (err != NSAPI_ERROR_OK) { @@ -224,7 +239,7 @@ bool CellularConnectionUtil::get_attach_network(CellularNetwork::AttachStatus &s return true; } -bool CellularConnectionUtil::set_attach_network() +bool CellularConnectionFSM::set_attach_network() { nsapi_error_t attach_err = _network->set_attach(); if (attach_err != NSAPI_ERROR_OK) { @@ -233,7 +248,7 @@ bool CellularConnectionUtil::set_attach_network() return true; } -void CellularConnectionUtil::report_failure(const char* msg) +void CellularConnectionFSM::report_failure(const char* msg) { tr_error("Cellular network failed: %s", msg); if (_status_callback) { @@ -241,12 +256,12 @@ void CellularConnectionUtil::report_failure(const char* msg) } } -nsapi_error_t CellularConnectionUtil::continue_to_state(CellularState state) +nsapi_error_t CellularConnectionFSM::continue_to_state(CellularState state) { if (state < _state) { _state = state; } - if (!_queue.call_in(0, callback(this, &CellularConnectionUtil::event))) { + if (!_queue.call_in(0, callback(this, &CellularConnectionFSM::event))) { stop(); return NSAPI_ERROR_NO_MEMORY; } @@ -254,22 +269,27 @@ nsapi_error_t CellularConnectionUtil::continue_to_state(CellularState state) return NSAPI_ERROR_OK; } -void CellularConnectionUtil::event() +void CellularConnectionFSM::event() { nsapi_error_t err; int event_timeout = -1; switch (_state) { + case STATE_INIT: + event_timeout = _start_time; + tr_info("INIT state, waiting %d ms before POWER state)", _start_time); + _next_state = STATE_POWER_ON; + break; case STATE_POWER_ON: cellularDevice.set_timeout(TIMEOUT_POWER_ON); tr_info("Cellular power ON (timeout %d ms)", TIMEOUT_POWER_ON); if (open_power(_serial)) { _next_state = STATE_DEVICE_READY; + _retry_count = 0; } else { - static int retry_count; - if (++retry_count <= 10) { - tr_warn("Power ON retry %d", retry_count); - event_timeout = 1000; + if (++_retry_count <= RETRY_COUNT_DEFAULT) { + tr_warn("Power ON retry %d", _retry_count); + event_timeout = 3 * 1000; } else { report_failure("Power"); return; @@ -280,36 +300,32 @@ void CellularConnectionUtil::event() cellularDevice.set_timeout(TIMEOUT_POWER_ON); if (_power->set_at_mode() == NSAPI_ERROR_OK) { tr_info("Cellular device ready"); - _next_state = STATE_START_CELLULAR; + _next_state = STATE_SIM_PIN; + _retry_count = 0; device_ready(); } else { - static int retry_count = 0; - tr_info("Waiting for cellular device (retry %d/10, timeout %d ms)", retry_count, TIMEOUT_POWER_ON); - if (++retry_count <= 10) { - event_timeout = 1000; + tr_info("Waiting for cellular device (retry %d/%d, timeout %d ms)", _retry_count, RETRY_COUNT_DEFAULT, + TIMEOUT_POWER_ON); + if (_retry_count++ <= RETRY_COUNT_DEFAULT) { + event_timeout = 3 * 1000; } else { report_failure("Power"); return; } } break; - case STATE_START_CELLULAR: - cellularDevice.set_timeout(TIMEOUT_NETWORK); - tr_info("Start cellular (timeout %d ms)", TIMEOUT_NETWORK); - open_network(); - _next_state = STATE_SIM_PIN; - break; case STATE_SIM_PIN: cellularDevice.set_timeout(TIMEOUT_SIM_PIN); tr_info("Start cellular (timeout %d ms)", TIMEOUT_SIM_PIN); if (open_sim()) { _next_state = STATE_REGISTERING_NETWORK; + _retry_count = 0; + _state_retry_count = 0; tr_info("Check for network registration"); } else { - static int retry_count; - if (++retry_count <= 10) { - tr_warn("Waiting for SIM %d", retry_count); - event_timeout = 1000; + if (_retry_count++ <= RETRY_COUNT_DEFAULT) { + tr_warn("Waiting for SIM %d/%d", _retry_count, RETRY_COUNT_DEFAULT); + event_timeout = 3 * 1000; } else { report_failure("Entering SIM PIN"); return; @@ -322,48 +338,50 @@ void CellularConnectionUtil::event() bool is_registered; _next_state = STATE_REGISTER_NETWORK; for (int type = 0; type < CellularNetwork::C_MAX; type++) { - if (get_network_registration((CellularNetwork::RegistrationType)type, status, is_registered)) { + if (get_network_registration((CellularNetwork::RegistrationType) type, status, is_registered)) { tr_debug("get_network_registration: type=%d, status=%d", type, status); if (is_registered) { tr_info("Registered to cellular network (type %d, status %d)", type, status); - _next_state = STATE_ATTACH_NETWORK; + _next_state = STATE_ATTACHING_NETWORK; + _retry_count = 0; + _state_retry_count = 0; + event_timeout = 0; tr_info("Check cellular network attach state"); break; } else { - if (status == CellularNetwork::RegistrationDenied) { - static int backoff_timeout = 1; - tr_warn("Network registration denied (type %d)! Retry after %d seconds.", type, backoff_timeout); - event_timeout = backoff_timeout * 1000; - backoff_timeout *= 2; - break; - } else if (status != CellularNetwork::NotRegistered) { - static int retry_count; - if (++retry_count <= 180) { - tr_info("Waiting for registration %d/180 (type %d, status %d)", retry_count, type, status); - event_timeout = 1*1000; - _next_state = STATE_REGISTERING_NETWORK; - } else { - tr_info("Start cellular registration"); - _next_state = STATE_REGISTER_NETWORK; - retry_count = 0; - break; - } + if (_retry_count < 180) { + event_timeout = 1000; + _next_state = STATE_REGISTERING_NETWORK; + tr_info("Waiting for registration %d/180 (type %d, status %d)", _retry_count, type, status); } else { - // modem is not yet searching network for this technology + tr_info("Start cellular registration"); + _next_state = STATE_REGISTER_NETWORK; + _retry_count = 0; + break; } } } } + + if (_next_state == STATE_REGISTERING_NETWORK) { + _retry_count++; + } break; case STATE_REGISTER_NETWORK: cellularDevice.set_timeout(TIMEOUT_REGISTRATION); tr_info("Register to cellular network (timeout %d ms)", TIMEOUT_REGISTRATION); if (set_network_registration()) { _next_state = STATE_REGISTERING_NETWORK; + _retry_count = 0; + if (_state_retry_count > RETRY_COUNT_DEFAULT) { + report_failure("Registration retry"); + return; + } + _state_retry_count++; } else { - static int retry_count; - if (++retry_count <= 3) { - event_timeout = 1000; + if (_retry_count < _retry_array_length) { + event_timeout = _retry_timeout_array[_retry_count] * 1000; + _retry_count++; } else { report_failure("Registration"); return; @@ -376,11 +394,18 @@ void CellularConnectionUtil::event() if (get_attach_network(attach_status)) { if (attach_status == CellularNetwork::Attached) { _next_state = STATE_CONNECT_NETWORK; + _retry_count = 0; } else { _next_state = STATE_ATTACH_NETWORK; + _retry_count = 0; } } else { - event_timeout = 0; + if (_retry_count++ <= RETRY_COUNT_DEFAULT) { + event_timeout = 1 * 1000; + } else { + report_failure("Attaching"); + return; + } } break; case STATE_ATTACH_NETWORK: @@ -388,9 +413,21 @@ void CellularConnectionUtil::event() tr_info("Attach to cellular network (timeout %d ms)", TIMEOUT_NETWORK); if (set_attach_network()) { _next_state = STATE_ATTACHING_NETWORK; + _retry_count = 0; + if (_state_retry_count >= RETRY_COUNT_DEFAULT) { + report_failure("Attach retry"); + return; + } + _state_retry_count++; tr_info("Cellular network attaching"); } else { - event_timeout = 0; + if (_retry_count < _retry_array_length) { + event_timeout = _retry_timeout_array[_retry_count] * 1000; + _retry_count++; + } else { + report_failure("Attach"); + return; + } } break; case STATE_CONNECT_NETWORK: @@ -400,8 +437,13 @@ void CellularConnectionUtil::event() if (!err) { _next_state = STATE_CONNECTED; } else { - report_failure("Network connect"); - return; + if (_retry_count < _retry_array_length) { + event_timeout = _retry_timeout_array[_retry_count] * 1000; + _retry_count++; + } else { + report_failure("Network Connect"); + return; + } } break; case STATE_CONNECTED: @@ -419,7 +461,7 @@ void CellularConnectionUtil::event() } if (_next_state != _state || event_timeout >= 0) { - if (_next_state != _state) { + if (_next_state != _state) { // state exit condition tr_info("Cellular state from %d to %d", _state, _next_state); if (_status_callback) { if (!_status_callback(_state, _next_state)) { @@ -443,14 +485,14 @@ void CellularConnectionUtil::event() if (event_timeout == -1) { event_timeout = 0; } - if (!_queue.call_in(event_timeout, callback(this, &CellularConnectionUtil::event))) { + if (!_queue.call_in(event_timeout, callback(this, &CellularConnectionFSM::event))) { report_failure("Cellular event failure!"); return; } } } -nsapi_error_t CellularConnectionUtil::start_dispatch() +nsapi_error_t CellularConnectionFSM::start_dispatch() { tr_info("CellularConnectionUtil::start"); tr_info("Create cellular thread"); @@ -471,7 +513,7 @@ nsapi_error_t CellularConnectionUtil::start_dispatch() return NSAPI_ERROR_OK; } -void CellularConnectionUtil::stop() +void CellularConnectionFSM::stop() { tr_info("CellularConnectionUtil::stop"); _cellularDevice->close_power(); @@ -482,41 +524,50 @@ void CellularConnectionUtil::stop() } } -void CellularConnectionUtil::set_serial(UARTSerial *serial) +void CellularConnectionFSM::set_serial(UARTSerial *serial) { _serial = serial; } -void CellularConnectionUtil::set_callback(mbed::Callback status_callback) +void CellularConnectionFSM::set_callback(mbed::Callback status_callback) { _status_callback = status_callback; } -events::EventQueue *CellularConnectionUtil::get_queue() +events::EventQueue *CellularConnectionFSM::get_queue() { return &_queue; } -CellularNetwork* CellularConnectionUtil::get_network() +CellularNetwork* CellularConnectionFSM::get_network() { return _network; } -CellularDevice* CellularConnectionUtil::get_device() +CellularDevice* CellularConnectionFSM::get_device() { return _cellularDevice; } -CellularSIM* CellularConnectionUtil::get_sim() +CellularSIM* CellularConnectionFSM::get_sim() { return _sim; } -NetworkStack *CellularConnectionUtil::get_stack() +NetworkStack *CellularConnectionFSM::get_stack() { return _cellularDevice->get_stack(); } +void CellularConnectionFSM::set_retry_timeout_array(uint16_t timeout[], int array_len) +{ + _retry_array_length = array_len > MAX_RETRY_ARRAY_SIZE ? MAX_RETRY_ARRAY_SIZE : array_len; + + for (int i = 0; i < _retry_array_length; i++) { + _retry_timeout_array[i] = timeout[i]; + } +} + } // namespace #endif // CELLULAR_DEVICE diff --git a/features/cellular/easy_cellular/CellularConnectionUtil.h b/features/cellular/easy_cellular/CellularConnectionFSM.h similarity index 78% rename from features/cellular/easy_cellular/CellularConnectionUtil.h rename to features/cellular/easy_cellular/CellularConnectionFSM.h index e38fdf8903..14726f2089 100644 --- a/features/cellular/easy_cellular/CellularConnectionUtil.h +++ b/features/cellular/easy_cellular/CellularConnectionFSM.h @@ -38,31 +38,32 @@ namespace mbed { const int PIN_SIZE = 8; +const int MAX_RETRY_ARRAY_SIZE = 10; -/** CellularConnectionUtil class +/** CellularConnectionFSM class * - * Utility class for cellular connection + * Finite State Machine for connecting to cellular network */ -class CellularConnectionUtil +class CellularConnectionFSM { public: - CellularConnectionUtil(); - virtual ~CellularConnectionUtil(); + CellularConnectionFSM(); + virtual ~CellularConnectionFSM(); public: /** Cellular connection states */ enum CellularState { - STATE_POWER_ON = 0, - STATE_DEVICE_READY = 1, - STATE_START_CELLULAR = 2, - STATE_SIM_PIN = 3, - STATE_REGISTER_NETWORK = 4, - STATE_REGISTERING_NETWORK = 5, - STATE_ATTACH_NETWORK = 7, - STATE_ATTACHING_NETWORK = 8, - STATE_CONNECT_NETWORK = 9, - STATE_CONNECTED = 10, + STATE_INIT = 0, + STATE_POWER_ON, + STATE_DEVICE_READY, + STATE_SIM_PIN, + STATE_REGISTER_NETWORK, + STATE_REGISTERING_NETWORK, + STATE_ATTACH_NETWORK, + STATE_ATTACHING_NETWORK, + STATE_CONNECT_NETWORK, + STATE_CONNECTED, }; public: @@ -122,10 +123,17 @@ public: */ void set_sim_pin(const char *sim_pin); + /** Sets the timeout array for network rejects. After reject next item is tried and after all items are waited and + * still fails then current network event will fail. + * + * @param timeout timeout array using seconds + * @param array_len length of the array + */ + void set_retry_timeout_array(uint16_t timeout[], int array_len); + private: bool open_power(FileHandle *fh); bool open_sim(); - bool open_network(); bool get_network_registration(CellularNetwork::RegistrationType type, CellularNetwork::RegistrationStatus &status, bool &is_registered); bool set_network_registration(char *plmn = 0); bool get_attach_network(CellularNetwork::AttachStatus &status); @@ -153,6 +161,11 @@ private: rtos::Thread *_queue_thread; CellularDevice *_cellularDevice; char _sim_pin[PIN_SIZE+1]; + int _retry_count; + int _state_retry_count; + int _start_time; + uint16_t _retry_timeout_array[MAX_RETRY_ARRAY_SIZE]; + int _retry_array_length; }; } // namespace diff --git a/features/cellular/easy_cellular/EasyCellularConnection.cpp b/features/cellular/easy_cellular/EasyCellularConnection.cpp index 1b995e9081..5e21441118 100644 --- a/features/cellular/easy_cellular/EasyCellularConnection.cpp +++ b/features/cellular/easy_cellular/EasyCellularConnection.cpp @@ -22,28 +22,29 @@ #include "nsapi_ppp.h" #endif -#include "CellularConnectionUtil.h" +#include "CellularConnectionFSM.h" #include "CellularUtil.h" #include "EasyCellularConnection.h" #include "CellularLog.h" +#include "mbed_wait_api.h" #if MBED_CONF_CELLULAR_USE_APN_LOOKUP || MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP #include "APN_db.h" #endif //MBED_CONF_CELLULAR_USE_APN_LOOKUP || MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP -namespace mbed -{ +namespace mbed { bool EasyCellularConnection::cellular_status(int state, int next_state) { tr_info("cellular_status %d=>%d", state, next_state); if (_target_state == state) { - if (state == CellularConnectionUtil::STATE_CONNECTED) { + if (state == CellularConnectionFSM::STATE_CONNECTED) { _is_connected = true; } else { _is_connected = false; } + tr_info("Target state reached: %d", _target_state); MBED_ASSERT(_cellularSemaphore.release() == osOK); return false; } else { @@ -52,10 +53,10 @@ bool EasyCellularConnection::cellular_status(int state, int next_state) return true; } -EasyCellularConnection::EasyCellularConnection() : _is_connected(false), _is_initialized(false), - _target_state(CellularConnectionUtil::STATE_POWER_ON), - _cellularSerial(MDMTXD, MDMRXD, MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE), - _cellularSemaphore(0), _cellularConnectionUtil(), _credentials_err(NSAPI_ERROR_OK) +EasyCellularConnection::EasyCellularConnection() : + _is_connected(false), _is_initialized(false), _target_state(CellularConnectionFSM::STATE_POWER_ON), _cellularSerial( + MDMTXD, MDMRXD, MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE), _cellularSemaphore(0), _cellularConnectionFSM(), _credentials_err( + NSAPI_ERROR_OK) { #if MBED_CONF_CELLULAR_USE_APN_LOOKUP || MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP _credentials_set = false; @@ -65,7 +66,7 @@ EasyCellularConnection::EasyCellularConnection() : _is_connected(false), _is_in EasyCellularConnection::~EasyCellularConnection() { - _cellularConnectionUtil.stop(); + _cellularConnectionFSM.stop(); } nsapi_error_t EasyCellularConnection::init() @@ -75,13 +76,13 @@ nsapi_error_t EasyCellularConnection::init() #if defined (MDMRTS) && defined (MDMCTS) _cellularSerial.set_flow_control(SerialBase::RTSCTS, MDMRTS, MDMCTS); #endif - _cellularConnectionUtil.set_serial(&_cellularSerial); - _cellularConnectionUtil.set_callback(callback(this, &EasyCellularConnection::cellular_status)); + _cellularConnectionFSM.set_serial(&_cellularSerial); + _cellularConnectionFSM.set_callback(callback(this, &EasyCellularConnection::cellular_status)); - err = _cellularConnectionUtil.init(); + err = _cellularConnectionFSM.init(); if (err == NSAPI_ERROR_OK) { - err = _cellularConnectionUtil.start_dispatch(); + err = _cellularConnectionFSM.start_dispatch(); } _is_initialized = true; } @@ -97,7 +98,7 @@ void EasyCellularConnection::set_credentials(const char *apn, const char *uname, if (_credentials_err) { return; } - CellularNetwork * network = _cellularConnectionUtil.get_network(); + CellularNetwork * network = _cellularConnectionFSM.get_network(); if (network) { _credentials_err = network->set_credentials(apn, uname, pwd); #if MBED_CONF_CELLULAR_USE_APN_LOOKUP || MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP @@ -114,7 +115,7 @@ void EasyCellularConnection::set_credentials(const char *apn, const char *uname, void EasyCellularConnection::set_sim_pin(const char *sim_pin) { if (sim_pin) { - _cellularConnectionUtil.set_sim_pin(sim_pin); + _cellularConnectionFSM.set_sim_pin(sim_pin); } } @@ -130,7 +131,7 @@ nsapi_error_t EasyCellularConnection::connect(const char *sim_pin, const char *a } if (sim_pin) { - _cellularConnectionUtil.set_sim_pin(sim_pin); + _cellularConnectionFSM.set_sim_pin(sim_pin); } return connect(); @@ -163,16 +164,17 @@ nsapi_error_t EasyCellularConnection::connect() } #if MBED_CONF_CELLULAR_USE_APN_LOOKUP || MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP if (!_credentials_set) { - _target_state = CellularConnectionUtil::STATE_SIM_PIN; - err = _cellularConnectionUtil.continue_to_state(_target_state); + _target_state = CellularConnectionFSM::STATE_SIM_PIN; + err = _cellularConnectionFSM.continue_to_state(_target_state); if (err == NSAPI_ERROR_OK) { - int sim_wait = _cellularSemaphore.wait(6*1000); // reserve 6 seconds to access to SIM + int sim_wait = _cellularSemaphore.wait(60*1000); // reserve 60 seconds to access to SIM if (sim_wait != 1) { tr_error("NO SIM ACCESS"); err = NSAPI_ERROR_NO_CONNECTION; } else { char imsi[MAX_IMSI_LENGTH+1]; - err = _cellularConnectionUtil.get_sim()->get_imsi(imsi); + wait(1); // need to wait to access SIM in some modems + err = _cellularConnectionFSM.get_sim()->get_imsi(imsi); if (err == NSAPI_ERROR_OK) { const char *apn_config = apnconfig(imsi); if (apn_config) { @@ -180,21 +182,22 @@ nsapi_error_t EasyCellularConnection::connect() const char* uname = _APN_GET(apn_config); const char* pwd = _APN_GET(apn_config); tr_info("Looked up APN %s", apn); - err = _cellularConnectionUtil.get_network()->set_credentials(apn, uname, pwd); + err = _cellularConnectionFSM.get_network()->set_credentials(apn, uname, pwd); } } } } if (err) { + tr_info("APN lookup failed"); return err; } } #endif // MBED_CONF_CELLULAR_USE_APN_LOOKUP || MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP - _target_state = CellularConnectionUtil::STATE_CONNECTED; - err = _cellularConnectionUtil.continue_to_state(_target_state); + _target_state = CellularConnectionFSM::STATE_CONNECTED; + err = _cellularConnectionFSM.continue_to_state(_target_state); if (err == NSAPI_ERROR_OK) { - int ret_wait = _cellularSemaphore.wait(10*60*1000); // cellular network searching may take several minutes + int ret_wait = _cellularSemaphore.wait(10 * 60 * 1000); // cellular network searching may take several minutes if (ret_wait != 1) { tr_info("No cellular connection"); err = NSAPI_ERROR_NO_CONNECTION; @@ -211,10 +214,10 @@ nsapi_error_t EasyCellularConnection::disconnect() #if MBED_CONF_CELLULAR_USE_APN_LOOKUP || MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP _credentials_set = false; #endif // #if MBED_CONF_CELLULAR_USE_APN_LOOKUP || MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP - if (!_cellularConnectionUtil.get_network()) { + if (!_cellularConnectionFSM.get_network()) { return NSAPI_ERROR_NO_CONNECTION; } - return _cellularConnectionUtil.get_network()->disconnect(); + return _cellularConnectionFSM.get_network()->disconnect(); } bool EasyCellularConnection::is_connected() @@ -224,16 +227,16 @@ bool EasyCellularConnection::is_connected() const char *EasyCellularConnection::get_ip_address() { - CellularNetwork *network = _cellularConnectionUtil.get_network(); + CellularNetwork *network = _cellularConnectionFSM.get_network(); if (!network) { return NULL; } - return _cellularConnectionUtil.get_network()->get_ip_address(); + return _cellularConnectionFSM.get_network()->get_ip_address(); } const char *EasyCellularConnection::get_netmask() { - CellularNetwork *network = _cellularConnectionUtil.get_network(); + CellularNetwork *network = _cellularConnectionFSM.get_network(); if (!network) { return NULL; } @@ -243,7 +246,7 @@ const char *EasyCellularConnection::get_netmask() const char *EasyCellularConnection::get_gateway() { - CellularNetwork *network = _cellularConnectionUtil.get_network(); + CellularNetwork *network = _cellularConnectionFSM.get_network(); if (!network) { return NULL; } @@ -253,7 +256,7 @@ const char *EasyCellularConnection::get_gateway() void EasyCellularConnection::attach(mbed::Callback status_cb) { - CellularNetwork *network = _cellularConnectionUtil.get_network(); + CellularNetwork *network = _cellularConnectionFSM.get_network(); if (network) { network->attach(status_cb); } @@ -261,7 +264,7 @@ void EasyCellularConnection::attach(mbed::Callbackmodem_debug_on(on); } @@ -269,7 +272,7 @@ void EasyCellularConnection::modem_debug_on(bool on) NetworkStack *EasyCellularConnection::get_stack() { - return _cellularConnectionUtil.get_stack(); + return _cellularConnectionFSM.get_stack(); } } // namespace diff --git a/features/cellular/easy_cellular/EasyCellularConnection.h b/features/cellular/easy_cellular/EasyCellularConnection.h index 13085a1902..601c9a2047 100644 --- a/features/cellular/easy_cellular/EasyCellularConnection.h +++ b/features/cellular/easy_cellular/EasyCellularConnection.h @@ -16,9 +16,10 @@ */ #ifndef EASY_CELLULAR_CONNECTION_H + #define EASY_CELLULAR_CONNECTION_H -#include "CellularConnectionUtil.h" +#include "CellularConnectionFSM.h" #ifdef CELLULAR_DEVICE #include "netsocket/CellularBase.h" @@ -147,12 +148,11 @@ private: #if MBED_CONF_CELLULAR_USE_APN_LOOKUP || MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP bool _credentials_set; #endif // #if MBED_CONF_CELLULAR_USE_APN_LOOKUP || MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP - CellularConnectionUtil::CellularState _target_state; + CellularConnectionFSM::CellularState _target_state; UARTSerial _cellularSerial; rtos::Semaphore _cellularSemaphore; - CellularConnectionUtil _cellularConnectionUtil; - + CellularConnectionFSM _cellularConnectionFSM; nsapi_error_t _credentials_err; }; diff --git a/features/cellular/framework/API/CellularNetwork.h b/features/cellular/framework/API/CellularNetwork.h index 3136025254..672b08b9f1 100644 --- a/features/cellular/framework/API/CellularNetwork.h +++ b/features/cellular/framework/API/CellularNetwork.h @@ -264,10 +264,10 @@ public: /** Get backoff timer value * - * @param backoff_time Backoff timer value associated with PDP APN in seconds - * @return zero on success + * @param backoff_timer Backoff timer value associated with PDP APN in seconds + * @return zero on success */ - virtual nsapi_error_t get_backoff_time(int &backoff_time) = 0; + virtual nsapi_error_t get_apn_backoff_timer(int &backoff_timer) = 0; /** Sets radio access technology. * @@ -381,7 +381,6 @@ public: * @return NSAPI_ERROR_OK on success, negative error code on failure */ virtual nsapi_error_t get_operator_params(int &format, operator_t &operator_params) = 0; - }; } // namespace mbed diff --git a/features/cellular/framework/AT/AT_CellularNetwork.cpp b/features/cellular/framework/AT/AT_CellularNetwork.cpp index 7ea2da5270..5c05d35e1f 100644 --- a/features/cellular/framework/AT/AT_CellularNetwork.cpp +++ b/features/cellular/framework/AT/AT_CellularNetwork.cpp @@ -685,7 +685,7 @@ nsapi_error_t AT_CellularNetwork::get_attach(AttachStatus &status) } -nsapi_error_t AT_CellularNetwork::get_backoff_time(int &backoffTime) +nsapi_error_t AT_CellularNetwork::get_apn_backoff_timer(int &backoff_timer) { _at.lock(); @@ -697,7 +697,7 @@ nsapi_error_t AT_CellularNetwork::get_backoff_time(int &backoffTime) _at.resp_start("+CABTRDP:"); if (_at.info_resp()) { _at.skip_param(); - backoffTime = _at.read_int(); + backoff_timer = _at.read_int(); } _at.resp_stop(); } diff --git a/features/cellular/framework/AT/AT_CellularNetwork.h b/features/cellular/framework/AT/AT_CellularNetwork.h index 0df894f4b8..eaf25c7f8d 100644 --- a/features/cellular/framework/AT/AT_CellularNetwork.h +++ b/features/cellular/framework/AT/AT_CellularNetwork.h @@ -71,7 +71,7 @@ public: // CellularNetwork virtual nsapi_error_t get_rate_control(CellularNetwork::RateControlExceptionReports &reports, CellularNetwork::RateControlUplinkTimeUnit &time_unit, int &uplink_rate); - virtual nsapi_error_t get_backoff_time(int &backoff_time); + virtual nsapi_error_t get_apn_backoff_timer(int &backoff_timer); virtual void attach(Callback status_cb); diff --git a/features/cellular/mbed_lib.json b/features/cellular/mbed_lib.json index ca5945f8b4..d943abd9ba 100644 --- a/features/cellular/mbed_lib.json +++ b/features/cellular/mbed_lib.json @@ -8,6 +8,10 @@ "mux-enabled": { "help": "Use cellular modem over MUX", "value": false + }, + "random_max_start_delay": { + "help": "Maximum random delay value used in start-up sequence in milliseconds", + "value": 0 } } -} \ No newline at end of file +}