mirror of https://github.com/ARMmbed/mbed-os.git
Cellular: retry logic for CellularContext connect
State machine has retry logic until device is attached to network. After this CellularContext does the context activation e.g. connect. There was no retry logic for context activation. Added logic to CellularContext level so it's available for at and (upcoming)ril layers.pull/10056/head
parent
2d9c4946ca
commit
c6e5595cec
|
@ -20,8 +20,8 @@
|
|||
using namespace mbed;
|
||||
|
||||
AT_CellularContext::AT_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, bool cp_req, bool nonip_req) :
|
||||
AT_CellularBase(at), _is_blocking(true), _is_connected(false),
|
||||
_current_op(OP_INVALID), _nw(0), _fh(0), _cp_req(cp_req), _nonip_req(nonip_req), _cp_in_use(false)
|
||||
AT_CellularBase(at), _is_connected(false),
|
||||
_current_op(OP_INVALID), _fh(0), _cp_req(cp_req), _nonip_req(nonip_req), _cp_in_use(false)
|
||||
{
|
||||
_stack = NULL;
|
||||
_pdp_type = DEFAULT_PDP_TYPE;
|
||||
|
@ -37,7 +37,12 @@ AT_CellularContext::AT_CellularContext(ATHandler &at, CellularDevice *device, co
|
|||
_new_context_set = false;
|
||||
_next = NULL;
|
||||
_cp_netif = NULL;
|
||||
memset(_retry_timeout_array, 0, CELLULAR_RETRY_ARRAY_SIZE);
|
||||
_retry_array_length = 0;
|
||||
_retry_count = 0;
|
||||
_is_blocking = true;
|
||||
_device = device;
|
||||
_nw = NULL;
|
||||
}
|
||||
|
||||
AT_CellularContext::~AT_CellularContext()
|
||||
|
@ -251,10 +256,6 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
|
|||
{
|
||||
}
|
||||
|
||||
void AT_CellularContext::call_network_cb(nsapi_connection_status_t status)
|
||||
{
|
||||
}
|
||||
|
||||
ControlPlane_netif *AT_CellularContext::get_cp_netif()
|
||||
{
|
||||
return NULL;
|
||||
|
@ -281,3 +282,8 @@ void AT_CellularContext::deactivate_non_ip_context()
|
|||
void AT_CellularContext::set_disconnect()
|
||||
{
|
||||
}
|
||||
|
||||
void AT_CellularContext::do_connect_with_retry()
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) , Arm Limited and affiliates.
|
||||
* Copyright (c) 2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -17,7 +17,7 @@
|
|||
|
||||
#include "CellularContext.h"
|
||||
|
||||
using namespace mbed;
|
||||
namespace mbed {
|
||||
|
||||
void CellularContext::cp_data_received()
|
||||
{
|
||||
|
@ -28,3 +28,25 @@ CellularDevice *CellularContext::get_device() const
|
|||
{
|
||||
return _device;
|
||||
}
|
||||
|
||||
void CellularContext::do_connect_with_retry()
|
||||
{
|
||||
do_connect();
|
||||
}
|
||||
|
||||
void CellularContext::do_connect()
|
||||
{
|
||||
_cb_data.error = NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
void CellularContext::call_network_cb(nsapi_connection_status_t status)
|
||||
{
|
||||
if (_connect_status != status) {
|
||||
_connect_status = status;
|
||||
if (_status_cb) {
|
||||
_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connect_status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -74,3 +74,8 @@ void CellularStateMachine::set_cellular_callback(mbed::Callback<void(nsapi_event
|
|||
void CellularStateMachine::cellular_event_changed(nsapi_event_t ev, intptr_t ptr)
|
||||
{
|
||||
}
|
||||
|
||||
void CellularStateMachine::get_retry_timeout_array(uint16_t *timeout, int &array_len) const
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "cellular/framework/API/CellularContext.h"
|
||||
#include "CellularContext.h"
|
||||
#include "ControlPlane_netif_stub.h"
|
||||
|
||||
namespace mbed {
|
||||
|
@ -186,10 +186,6 @@ public:
|
|||
{
|
||||
};
|
||||
|
||||
void call_network_cb(nsapi_connection_status_t status)
|
||||
{
|
||||
};
|
||||
|
||||
ControlPlane_netif_stub *get_cp_netif()
|
||||
{
|
||||
if (!my_cp_netif) {
|
||||
|
@ -219,6 +215,11 @@ public:
|
|||
void set_disconnect()
|
||||
{
|
||||
};
|
||||
|
||||
void do_connect_with_retry()
|
||||
{
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -314,6 +314,22 @@ protected: // Device specific implementations might need these so protected
|
|||
*/
|
||||
void cp_data_received();
|
||||
|
||||
/** Retry logic after device attached to network. Retry to find and activate pdp context or in case
|
||||
* of PPP find correct pdp context and open data channel. Retry logic is the same which is used in
|
||||
* CellularStateMachine.
|
||||
*/
|
||||
virtual void do_connect_with_retry();
|
||||
|
||||
/** Helper method to call callback function if it is provided
|
||||
*
|
||||
* @param status connection status which is parameter in callback function
|
||||
*/
|
||||
void call_network_cb(nsapi_connection_status_t status);
|
||||
|
||||
/** Find and activate pdp context or in case of PPP find correct pdp context and open data channel.
|
||||
*/
|
||||
virtual void do_connect();
|
||||
|
||||
// member variables needed in target override methods
|
||||
NetworkStack *_stack; // must be pointer because of PPP
|
||||
pdp_type_t _pdp_type;
|
||||
|
@ -332,7 +348,12 @@ protected: // Device specific implementations might need these so protected
|
|||
bool _active_high;
|
||||
|
||||
ControlPlane_netif *_cp_netif;
|
||||
uint16_t _retry_timeout_array[CELLULAR_RETRY_ARRAY_SIZE];
|
||||
int _retry_array_length;
|
||||
int _retry_count;
|
||||
CellularDevice *_device;
|
||||
CellularNetwork *_nw;
|
||||
bool _is_blocking;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -418,6 +418,16 @@ public:
|
|||
protected:
|
||||
friend class AT_CellularNetwork;
|
||||
friend class AT_CellularContext;
|
||||
friend class CellularContext;
|
||||
|
||||
/** Get the retry array from the CellularStateMachine. Array is used in retry logic.
|
||||
* Array contains seconds and retry logic uses those second to wait before trying again.
|
||||
*
|
||||
* @param timeout timeout array containing seconds for retry logic. Must have space for
|
||||
* CELLULAR_RETRY_ARRAY_SIZE (defined in CellularCommon.h)
|
||||
* @param array_len length of the timeout array on return
|
||||
*/
|
||||
void get_retry_timeout_array(uint16_t *timeout, int &array_len) const;
|
||||
|
||||
/** Cellular callback to be attached to Network and CellularStateMachine classes.
|
||||
* CellularContext calls this when in PPP mode to provide network changes.
|
||||
|
|
|
@ -48,8 +48,8 @@ using namespace mbed_cellular_util;
|
|||
using namespace mbed;
|
||||
|
||||
AT_CellularContext::AT_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, bool cp_req, bool nonip_req) :
|
||||
AT_CellularBase(at), _is_connected(false), _is_blocking(true),
|
||||
_current_op(OP_INVALID), _nw(0), _fh(0), _cp_req(cp_req), _nonip_req(nonip_req), _cp_in_use(false)
|
||||
AT_CellularBase(at), _is_connected(false), _current_op(OP_INVALID), _fh(0), _cp_req(cp_req),
|
||||
_nonip_req(nonip_req), _cp_in_use(false)
|
||||
{
|
||||
tr_info("New CellularContext %s (%p)", apn ? apn : "", this);
|
||||
_stack = NULL;
|
||||
|
@ -68,7 +68,12 @@ AT_CellularContext::AT_CellularContext(ATHandler &at, CellularDevice *device, co
|
|||
_dcd_pin = NC;
|
||||
_active_high = false;
|
||||
_cp_netif = NULL;
|
||||
memset(_retry_timeout_array, 0, CELLULAR_RETRY_ARRAY_SIZE);
|
||||
_retry_array_length = 0;
|
||||
_retry_count = 0;
|
||||
_is_blocking = true;
|
||||
_device = device;
|
||||
_nw = NULL;
|
||||
}
|
||||
|
||||
AT_CellularContext::~AT_CellularContext()
|
||||
|
@ -119,6 +124,11 @@ AT_CellularDevice *AT_CellularContext::get_device() const
|
|||
return static_cast<AT_CellularDevice *>(CellularContext::get_device());
|
||||
}
|
||||
|
||||
void AT_CellularContext::do_connect_with_retry()
|
||||
{
|
||||
CellularContext::do_connect_with_retry();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularContext::connect()
|
||||
{
|
||||
tr_info("CellularContext connect");
|
||||
|
@ -129,15 +139,15 @@ nsapi_error_t AT_CellularContext::connect()
|
|||
|
||||
nsapi_error_t err = _device->attach_to_network();
|
||||
_cb_data.error = check_operation(err, OP_CONNECT);
|
||||
|
||||
_retry_count = 0;
|
||||
if (_is_blocking) {
|
||||
if (_cb_data.error == NSAPI_ERROR_OK || _cb_data.error == NSAPI_ERROR_ALREADY) {
|
||||
do_connect();
|
||||
do_connect_with_retry();
|
||||
}
|
||||
} else {
|
||||
if (_cb_data.error == NSAPI_ERROR_ALREADY) {
|
||||
// device is already attached, to be async we must use queue to connect and give proper callbacks
|
||||
int id = _device->get_queue()->call_in(0, this, &AT_CellularContext::do_connect);
|
||||
int id = _device->get_queue()->call_in(0, this, &AT_CellularContext::do_connect_with_retry);
|
||||
if (id == 0) {
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
@ -580,8 +590,6 @@ void AT_CellularContext::do_connect()
|
|||
_cb_data.error = open_data_channel();
|
||||
_at.unlock();
|
||||
if (_cb_data.error != NSAPI_ERROR_OK) {
|
||||
tr_error("Failed to open data channel!");
|
||||
call_network_cb(NSAPI_STATUS_DISCONNECTED);
|
||||
_is_connected = false;
|
||||
} else {
|
||||
_is_context_activated = true;
|
||||
|
@ -970,7 +978,8 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
|
|||
if (_status_cb) {
|
||||
_status_cb(ev, ptr);
|
||||
}
|
||||
do_connect();
|
||||
_retry_count = 0;
|
||||
do_connect_with_retry();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1000,19 +1009,6 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
|
|||
}
|
||||
}
|
||||
|
||||
void AT_CellularContext::call_network_cb(nsapi_connection_status_t status)
|
||||
{
|
||||
if (_connect_status != status) {
|
||||
_connect_status = status;
|
||||
if (_status_cb) {
|
||||
_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connect_status);
|
||||
}
|
||||
if (_nw && _connect_status == NSAPI_STATUS_DISCONNECTED) {
|
||||
tr_info("CellularContext disconnected");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ControlPlane_netif *AT_CellularContext::get_cp_netif()
|
||||
{
|
||||
tr_error("No control plane interface available from base context!");
|
||||
|
|
|
@ -93,12 +93,6 @@ protected:
|
|||
*/
|
||||
virtual uint32_t get_timeout_for_operation(ContextOperation op) const;
|
||||
|
||||
/** Helper method to call callback function if it is provided
|
||||
*
|
||||
* @param status connection status which is parameter in callback function
|
||||
*/
|
||||
void call_network_cb(nsapi_connection_status_t status);
|
||||
|
||||
virtual nsapi_error_t activate_non_ip_context();
|
||||
virtual nsapi_error_t setup_control_plane_opt();
|
||||
virtual void deactivate_non_ip_context();
|
||||
|
@ -123,13 +117,11 @@ private:
|
|||
nsapi_error_t check_operation(nsapi_error_t err, ContextOperation op);
|
||||
AT_CellularBase::CellularProperty pdp_type_t_to_cellular_property(pdp_type_t pdp_type);
|
||||
void ciot_opt_cb(mbed::CellularNetwork::CIoT_Supported_Opt ciot_opt);
|
||||
|
||||
virtual void do_connect_with_retry();
|
||||
private:
|
||||
bool _is_connected;
|
||||
bool _is_blocking;
|
||||
ContextOperation _current_op;
|
||||
char _found_apn[MAX_APN_LENGTH];
|
||||
CellularNetwork *_nw;
|
||||
FileHandle *_fh;
|
||||
rtos::Semaphore _semaphore;
|
||||
rtos::Semaphore _cp_opt_semaphore;
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include <stdint.h>
|
||||
#include "nsapi_types.h"
|
||||
|
||||
const int CELLULAR_RETRY_ARRAY_SIZE = 10;
|
||||
|
||||
struct cell_callback_data_t {
|
||||
nsapi_error_t error; /* possible error code */
|
||||
int status_data; /* cellular_event_status related enum or other info in int format. Check cellular_event_status comments.*/
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
#include "CellularContext.h"
|
||||
#include "CellularLog.h"
|
||||
#include "ThisThread.h"
|
||||
|
||||
MBED_WEAK CellularInterface *CellularInterface::get_target_default_instance()
|
||||
{
|
||||
|
@ -66,4 +68,79 @@ CellularDevice *CellularContext::get_device() const
|
|||
return _device;
|
||||
}
|
||||
|
||||
void CellularContext::do_connect_with_retry()
|
||||
{
|
||||
do_connect();
|
||||
if (_cb_data.error == NSAPI_ERROR_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_retry_count == 0) {
|
||||
_device->get_retry_timeout_array(_retry_timeout_array, _retry_array_length);
|
||||
}
|
||||
|
||||
if (_is_blocking) {
|
||||
while (_retry_count < _retry_array_length) {
|
||||
tr_debug("SYNC do_connect failed with %d, retry after %d seconds", _cb_data.error, _retry_timeout_array[_retry_count]);
|
||||
rtos::ThisThread::sleep_for(_retry_timeout_array[_retry_count] * 1000);
|
||||
do_connect();
|
||||
if (_cb_data.error == NSAPI_ERROR_OK) {
|
||||
return;
|
||||
}
|
||||
_retry_count++;
|
||||
}
|
||||
} else {
|
||||
if (_retry_count < _retry_array_length) {
|
||||
if (_retry_count == _retry_array_length - 1) {
|
||||
// set the flag that this is the last try for ppp connect / pdp context activate
|
||||
_cb_data.final_try = true;
|
||||
}
|
||||
tr_debug("ASYNC do_connect failed with %d, retry after %d seconds", _cb_data.error, _retry_timeout_array[_retry_count]);
|
||||
int id = _device->get_queue()->call_in(_retry_timeout_array[_retry_count] * 1000, this, &CellularContext::do_connect_with_retry);
|
||||
if (id == 0) {
|
||||
tr_error("Failed call via eventqueue in do_connect_with_retry()");
|
||||
#if !NSAPI_PPP_AVAILABLE
|
||||
_cb_data.final_try = true;
|
||||
_cb_data.error = NSAPI_ERROR_NO_MEMORY;
|
||||
// in PPP mode we did not activate any context, just searched the correct _cid
|
||||
if (_status_cb) {
|
||||
_status_cb((nsapi_event_t)CellularActivatePDPContext, (intptr_t)&_cb_data);
|
||||
}
|
||||
_cb_data.final_try = false;
|
||||
_cb_data.error = NSAPI_ERROR_OK;
|
||||
#else
|
||||
call_network_cb(NSAPI_STATUS_DISCONNECTED);
|
||||
#endif // !NSAPI_PPP_AVAILABLE
|
||||
}
|
||||
_retry_count++;
|
||||
return; // don't call NSAPI_STATUS_DISCONNECTED in every failure, only the last one.
|
||||
}
|
||||
}
|
||||
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
if (_cb_data.error != NSAPI_ERROR_OK) {
|
||||
tr_error("Failed to open data channel!");
|
||||
call_network_cb(NSAPI_STATUS_DISCONNECTED);
|
||||
}
|
||||
#endif // #if NSAPI_PPP_AVAILABLE
|
||||
}
|
||||
|
||||
void CellularContext::do_connect()
|
||||
{
|
||||
_cb_data.error = NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
void CellularContext::call_network_cb(nsapi_connection_status_t status)
|
||||
{
|
||||
if (_connect_status != status) {
|
||||
_connect_status = status;
|
||||
if (_status_cb) {
|
||||
_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connect_status);
|
||||
}
|
||||
if (_nw && _connect_status == NSAPI_STATUS_DISCONNECTED) {
|
||||
tr_info("CellularContext disconnected");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mbed
|
||||
|
|
|
@ -34,7 +34,7 @@ MBED_WEAK CellularDevice *CellularDevice::get_target_default_instance()
|
|||
}
|
||||
|
||||
CellularDevice::CellularDevice(FileHandle *fh) : _network_ref_count(0), _sms_ref_count(0),
|
||||
_info_ref_count(0), _fh(fh), _queue(5 * EVENTS_EVENT_SIZE), _state_machine(0), _nw(0), _status_cb(0)
|
||||
_info_ref_count(0), _fh(fh), _queue(8 * EVENTS_EVENT_SIZE), _state_machine(0), _nw(0), _status_cb(0)
|
||||
{
|
||||
MBED_ASSERT(fh);
|
||||
set_sim_pin(NULL);
|
||||
|
@ -67,6 +67,13 @@ CellularContext *CellularDevice::get_context_list() const
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void CellularDevice::get_retry_timeout_array(uint16_t *timeout, int &array_len) const
|
||||
{
|
||||
if (_state_machine && timeout) {
|
||||
_state_machine->get_retry_timeout_array(timeout, array_len);
|
||||
}
|
||||
}
|
||||
|
||||
void CellularDevice::set_sim_pin(const char *sim_pin)
|
||||
{
|
||||
if (sim_pin) {
|
||||
|
|
|
@ -67,7 +67,7 @@ CellularStateMachine::CellularStateMachine(CellularDevice &device, events::Event
|
|||
_retry_timeout_array[7] = 128; // if around two minutes was not enough then let's wait much longer
|
||||
_retry_timeout_array[8] = 600;
|
||||
_retry_timeout_array[9] = TIMEOUT_NETWORK_MAX;
|
||||
_retry_array_length = RETRY_ARRAY_SIZE;
|
||||
_retry_array_length = CELLULAR_RETRY_ARRAY_SIZE;
|
||||
}
|
||||
|
||||
CellularStateMachine::~CellularStateMachine()
|
||||
|
@ -153,7 +153,7 @@ bool CellularStateMachine::open_sim()
|
|||
} else {
|
||||
// No sim pin provided even it's needed, stop state machine
|
||||
tr_error("PIN required but no SIM pin provided.");
|
||||
_retry_count = RETRY_ARRAY_SIZE;
|
||||
_retry_count = CELLULAR_RETRY_ARRAY_SIZE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -285,8 +285,8 @@ void CellularStateMachine::enter_to_state(CellularState state)
|
|||
|
||||
void CellularStateMachine::retry_state_or_fail()
|
||||
{
|
||||
if (++_retry_count < RETRY_ARRAY_SIZE) {
|
||||
tr_debug("%s: retry %d/%d", get_state_string(_state), _retry_count, RETRY_ARRAY_SIZE);
|
||||
if (++_retry_count < CELLULAR_RETRY_ARRAY_SIZE) {
|
||||
tr_debug("%s: retry %d/%d", get_state_string(_state), _retry_count, CELLULAR_RETRY_ARRAY_SIZE);
|
||||
_event_timeout = _retry_timeout_array[_retry_count];
|
||||
_is_retry = true;
|
||||
_cb_data.error = NSAPI_ERROR_OK;
|
||||
|
@ -686,12 +686,20 @@ void CellularStateMachine::set_retry_timeout_array(const uint16_t timeout[], int
|
|||
tr_warn("set_retry_timeout_array, timeout array null or invalid length");
|
||||
return;
|
||||
}
|
||||
_retry_array_length = array_len > RETRY_ARRAY_SIZE ? RETRY_ARRAY_SIZE : array_len;
|
||||
_retry_array_length = array_len > CELLULAR_RETRY_ARRAY_SIZE ? CELLULAR_RETRY_ARRAY_SIZE : array_len;
|
||||
|
||||
for (int i = 0; i < _retry_array_length; i++) {
|
||||
_retry_timeout_array[i] = timeout[i];
|
||||
}
|
||||
}
|
||||
|
||||
void CellularStateMachine::get_retry_timeout_array(uint16_t *timeout, int &array_len) const
|
||||
{
|
||||
for (int i = 0; i < _retry_array_length; i++) {
|
||||
timeout[i] = _retry_timeout_array[i];
|
||||
}
|
||||
array_len = _retry_array_length;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
|
|
@ -30,8 +30,6 @@ namespace mbed {
|
|||
|
||||
class CellularDevice;
|
||||
|
||||
const int RETRY_ARRAY_SIZE = 10;
|
||||
|
||||
/** CellularStateMachine class
|
||||
*
|
||||
* Finite State Machine for attaching to cellular network. Used by CellularDevice.
|
||||
|
@ -133,6 +131,7 @@ private:
|
|||
*/
|
||||
void reset();
|
||||
private:
|
||||
void get_retry_timeout_array(uint16_t *timeout, int &array_len) const;
|
||||
bool power_on();
|
||||
bool open_sim();
|
||||
bool get_network_registration(CellularNetwork::RegistrationType type, CellularNetwork::RegistrationStatus &status, bool &is_registered);
|
||||
|
@ -171,7 +170,7 @@ private:
|
|||
int _start_time;
|
||||
int _event_timeout;
|
||||
|
||||
uint16_t _retry_timeout_array[RETRY_ARRAY_SIZE];
|
||||
uint16_t _retry_timeout_array[CELLULAR_RETRY_ARRAY_SIZE];
|
||||
int _retry_array_length;
|
||||
int _event_id;
|
||||
const char *_plmn;
|
||||
|
|
Loading…
Reference in New Issue