mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #10056 from jarvte/context_act_ppp_retry_logic
Cellular: retry logic for CellularContext connectpull/10215/head
commit
cf4118f4ae
|
@ -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