Merge branch 'plmn_stm_fix2' of https://github.com/jarvte/mbed-os into rollup

pull/10116/head
Martin Kojtal 2019-03-15 08:45:14 +00:00
commit 759627ff12
4 changed files with 55 additions and 123 deletions

View File

@ -34,7 +34,6 @@ enum UT_CellularState {
UT_STATE_DEVICE_READY,
UT_STATE_SIM_PIN,
UT_STATE_REGISTERING_NETWORK,
UT_STATE_MANUAL_REGISTERING_NETWORK,
UT_STATE_ATTACHING_NETWORK,
UT_STATE_MAX_FSM_STATE
};
@ -392,8 +391,8 @@ TEST_F(TestCellularStateMachine, test_run_to_state)
ut.set_plmn("12345");
ASSERT_EQ(NSAPI_ERROR_OK, ut.run_to_device_registered());
(void)ut.get_current_status(current_state, target_state);
ASSERT_EQ(UT_STATE_MANUAL_REGISTERING_NETWORK, current_state);
ASSERT_EQ(UT_STATE_MANUAL_REGISTERING_NETWORK, target_state);
ASSERT_EQ(UT_STATE_REGISTERING_NETWORK, current_state);
ASSERT_EQ(UT_STATE_REGISTERING_NETWORK, target_state);
ut.cellular_event_changed((nsapi_event_t)CellularRegistrationStatusChanged, (intptr_t)&data);
ut.reset();

View File

@ -171,7 +171,9 @@ void AT_CellularNetwork::read_reg_params_and_compare(RegistrationType type)
reg_params._status == RegisteredRoaming)) {
if (previous_registration_status == RegisteredHomeNetwork ||
previous_registration_status == RegisteredRoaming) {
call_network_cb(NSAPI_STATUS_DISCONNECTED);
if (type != C_REG) {// we are interested only if we drop from packet network
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED);
}
}
}
}
@ -268,6 +270,9 @@ nsapi_error_t AT_CellularNetwork::set_registration(const char *plmn)
tr_debug("Manual network registration to %s", plmn);
_at.cmd_start("AT+COPS=1,2,");
_at.write_string(plmn);
if (_op_act != RAT_UNKNOWN) {
_at.write_int(_op_act);
}
_at.cmd_stop_read_resp();
}

View File

@ -48,8 +48,7 @@ CellularStateMachine::CellularStateMachine(CellularDevice &device, events::Event
_cellularDevice(device), _state(STATE_INIT), _next_state(_state), _target_state(_state),
_event_status_cb(0), _network(0), _queue(queue), _queue_thread(0), _sim_pin(0),
_retry_count(0), _event_timeout(-1), _event_id(-1), _plmn(0), _command_success(false),
_plmn_network_found(false), _is_retry(false), _cb_data(), _current_event(NSAPI_EVENT_CONNECTION_STATUS_CHANGE),
_status(0)
_is_retry(false), _cb_data(), _current_event(NSAPI_EVENT_CONNECTION_STATUS_CHANGE), _status(0)
{
#if MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY == 0
_start_time = 0;
@ -83,7 +82,6 @@ void CellularStateMachine::reset()
_state = STATE_INIT;
_event_timeout = -1;
_event_id = -1;
_plmn_network_found = false;
_is_retry = false;
_status = 0;
_target_state = STATE_INIT;
@ -161,7 +159,20 @@ bool CellularStateMachine::open_sim()
}
}
return state == CellularDevice::SimStateReady;
bool sim_ready = state == CellularDevice::SimStateReady;
if (sim_ready) {
// If plmn is set, we should it right after sim is opened so that registration is forced to correct network.
if (_plmn && strlen(_plmn)) {
_cb_data.error = _network->set_registration(_plmn);
tr_debug("STM: manual set_registration: %d, plmn: %s", _cb_data.error, _plmn);
if (_cb_data.error) {
return false;
}
}
}
return sim_ready;
}
bool CellularStateMachine::is_registered()
@ -169,7 +180,9 @@ bool CellularStateMachine::is_registered()
CellularNetwork::RegistrationStatus status;
bool is_registered = false;
for (int type = 0; type < CellularNetwork::C_MAX; type++) {
// accept only CGREG/CEREG. CREG is for circuit switch network changed. If we accept CREG attach will fail if also
// CGREG/CEREG is not registered.
for (int type = 0; type < CellularNetwork::C_REG; type++) {
if (get_network_registration((CellularNetwork::RegistrationType) type, status, is_registered)) {
if (is_registered) {
break;
@ -178,6 +191,11 @@ bool CellularStateMachine::is_registered()
}
_cb_data.status_data = status;
// in manual registering we are forcing registration to certain network so we don't accept active context or attached
// as indication that device is registered to correct network.
if (_plmn && strlen(_plmn)) {
return is_registered;
}
return is_registered || _status;
}
@ -249,61 +267,13 @@ void CellularStateMachine::report_failure(const char *msg)
const char *CellularStateMachine::get_state_string(CellularState state) const
{
#if MBED_CONF_MBED_TRACE_ENABLE
static const char *strings[STATE_MAX_FSM_STATE] = { "Init", "Power", "Device ready", "SIM pin", "Registering network", "Manual registering", "Attaching network"};
static const char *strings[STATE_MAX_FSM_STATE] = { "Init", "Power", "Device ready", "SIM pin", "Registering network", "Attaching network"};
return strings[state];
#else
return NULL;
#endif // #if MBED_CONF_MBED_TRACE_ENABLE
}
bool CellularStateMachine::is_registered_to_plmn()
{
int format;
CellularNetwork::operator_t op;
_cb_data.error = _network->get_operator_params(format, op);
if (_cb_data.error == NSAPI_ERROR_OK) {
if (format == 2) {
// great, numeric format we can do comparison for that
if (strcmp(op.op_num, _plmn) == 0) {
return true;
}
return false;
}
// format was alpha, get operator names to do the comparing
CellularNetwork::operator_names_list names_list;
_cb_data.error = _network->get_operator_names(names_list);
if (_cb_data.error == NSAPI_ERROR_OK) {
CellularNetwork::operator_names_t *op_names = names_list.get_head();
bool found_match = false;
while (op_names) {
if (format == 0) {
if (strcmp(op.op_long, op_names->alpha) == 0) {
found_match = true;
}
} else if (format == 1) {
if (strcmp(op.op_short, op_names->alpha) == 0) {
found_match = true;
}
}
if (found_match) {
if (strcmp(_plmn, op_names->numeric)) {
names_list.delete_all();
return true;
}
names_list.delete_all();
return false;
}
}
}
names_list.delete_all();
}
return false;
}
void CellularStateMachine::enter_to_state(CellularState state)
{
_next_state = state;
@ -378,6 +348,7 @@ bool CellularStateMachine::device_ready()
_event_status_cb((nsapi_event_t)CellularDeviceReady, (intptr_t)&_cb_data);
}
_cellularDevice.set_ready_cb(0);
return true;
}
@ -410,16 +381,15 @@ void CellularStateMachine::state_sim_pin()
_cellularDevice.set_timeout(TIMEOUT_SIM_PIN);
tr_info("Setup SIM (timeout %d s)", TIMEOUT_SIM_PIN / 1000);
if (open_sim()) {
bool success = false;
for (int type = 0; type < CellularNetwork::C_MAX; type++) {
_cb_data.error = _network->set_registration_urc((CellularNetwork::RegistrationType)type, true);
if (!_cb_data.error) {
if (!_cb_data.error && (type == CellularNetwork::C_EREG || type == CellularNetwork::C_GREG)) {
success = true;
}
}
if (!success) {
tr_warn("Failed to set any URC's for registration");
tr_error("Failed to set CEREG/CGREG URC's for registration");
retry_state_or_fail();
return;
}
@ -428,16 +398,13 @@ void CellularStateMachine::state_sim_pin()
tr_debug("Active context found.");
_status |= ACTIVE_PDP_CONTEXT;
}
CellularNetwork::AttachStatus status; // check if modem is already attached to a network
CellularNetwork::AttachStatus status = CellularNetwork::Detached; // check if modem is already attached to a network
if (_network->get_attach(status) == NSAPI_ERROR_OK && status == CellularNetwork::Attached) {
_status |= ATTACHED_TO_NETWORK;
tr_debug("Cellular already attached.");
}
if (_plmn) {
enter_to_state(STATE_MANUAL_REGISTERING_NETWORK);
} else {
enter_to_state(STATE_REGISTERING_NETWORK);
}
enter_to_state(STATE_REGISTERING_NETWORK);
} else {
retry_state_or_fail();
}
@ -448,44 +415,25 @@ void CellularStateMachine::state_registering()
_cellularDevice.set_timeout(TIMEOUT_NETWORK);
tr_info("Network registration (timeout %d s)", TIMEOUT_REGISTRATION / 1000);
if (is_registered()) {
_cb_data.status_data = CellularNetwork::AlreadyRegistered;
if (_cb_data.status_data != CellularNetwork::RegisteredHomeNetwork &&
_cb_data.status_data != CellularNetwork::RegisteredRoaming && _status) {
// there was already activated context or attached to network, and registration status is not registered, set to already registered.
_cb_data.status_data = CellularNetwork::AlreadyRegistered;
}
_cb_data.error = NSAPI_ERROR_OK;
_event_status_cb(_current_event, (intptr_t)&_cb_data);
// we are already registered, go to attach
enter_to_state(STATE_ATTACHING_NETWORK);
} else {
_cellularDevice.set_timeout(TIMEOUT_REGISTRATION);
if (!_command_success) {
_cb_data.error = _network->set_registration();
if (!_command_success && !_plmn) { // don't call set_registration twice for manual registration
_cb_data.error = _network->set_registration(_plmn);
_command_success = (_cb_data.error == NSAPI_ERROR_OK);
}
retry_state_or_fail();
}
}
// only used when _plmn is set
void CellularStateMachine::state_manual_registering_network()
{
_cellularDevice.set_timeout(TIMEOUT_REGISTRATION);
tr_info("Manual registration %s (timeout %d s)", _plmn, TIMEOUT_REGISTRATION / 1000);
if (!_plmn_network_found) {
if (is_registered() && is_registered_to_plmn()) {
// we have to send registration changed event as network thinks that we are not registered even we have active PDP context
_cb_data.status_data = CellularNetwork::AlreadyRegistered;
_cb_data.error = NSAPI_ERROR_OK;
_event_status_cb(_current_event, (intptr_t)&_cb_data);
_plmn_network_found = true;
enter_to_state(STATE_ATTACHING_NETWORK);
} else {
if (!_command_success) {
_cb_data.error = _network->set_registration(_plmn);
_command_success = (_cb_data.error == NSAPI_ERROR_OK);
}
retry_state_or_fail();
}
}
}
void CellularStateMachine::state_attaching()
{
_cellularDevice.set_timeout(TIMEOUT_CONNECT);
@ -523,13 +471,8 @@ void CellularStateMachine::continue_from_state(CellularState state)
nsapi_error_t CellularStateMachine::run_to_state(CellularStateMachine::CellularState state)
{
_mutex.lock();
CellularState tmp_state = state;
if (_plmn && tmp_state == STATE_REGISTERING_NETWORK) {
tmp_state = STATE_MANUAL_REGISTERING_NETWORK;
}
// call pre_event via queue so that it's in same thread and it's safe to decisions
int id = _queue.call_in(0, this, &CellularStateMachine::pre_event, tmp_state);
int id = _queue.call_in(0, this, &CellularStateMachine::pre_event, state);
if (!id) {
report_failure("Failed to call queue.");
stop();
@ -620,10 +563,6 @@ void CellularStateMachine::event()
_current_event = (nsapi_event_t)CellularRegistrationStatusChanged;
state_registering();
break;
case STATE_MANUAL_REGISTERING_NETWORK:
_current_event = (nsapi_event_t)CellularRegistrationStatusChanged;
state_manual_registering_network();
break;
case STATE_ATTACHING_NETWORK:
_current_event = (nsapi_event_t)CellularAttachNetwork;
state_attaching();
@ -694,23 +633,14 @@ bool CellularStateMachine::check_is_target_reached()
void CellularStateMachine::cellular_event_changed(nsapi_event_t ev, intptr_t ptr)
{
cell_callback_data_t *data = (cell_callback_data_t *)ptr;
if ((cellular_connection_status_t)ev == CellularRegistrationStatusChanged &&
(_state == STATE_REGISTERING_NETWORK || _state == STATE_MANUAL_REGISTERING_NETWORK)) {
if ((cellular_connection_status_t)ev == CellularRegistrationStatusChanged && _state == STATE_REGISTERING_NETWORK) {
// expect packet data so only these states are valid
if ((data->status_data == CellularNetwork::RegisteredHomeNetwork || data->status_data == CellularNetwork::RegisteredRoaming) && data->error == NSAPI_ERROR_OK) {
if (_plmn) {
if (is_registered_to_plmn()) {
if (!_plmn_network_found) {
_plmn_network_found = true;
_queue.cancel(_event_id);
_is_retry = false;
_event_id = -1;
if (!check_is_target_reached()) {
continue_from_state(STATE_ATTACHING_NETWORK);
}
}
}
} else {
CellularNetwork::registration_params_t reg_params;
nsapi_error_t err = _network->get_registration_params(reg_params);
if (err == NSAPI_ERROR_OK && (reg_params._type == CellularNetwork::C_EREG || reg_params._type == CellularNetwork::C_GREG)) {
if ((data->status_data == CellularNetwork::RegisteredHomeNetwork ||
data->status_data == CellularNetwork::RegisteredRoaming) && data->error == NSAPI_ERROR_OK) {
_queue.cancel(_event_id);
_is_retry = false;
_event_id = -1;
@ -718,6 +648,8 @@ void CellularStateMachine::cellular_event_changed(nsapi_event_t ev, intptr_t ptr
continue_from_state(STATE_ATTACHING_NETWORK);
}
}
} else {
tr_debug("creg event, discard...");
}
}
}

View File

@ -58,7 +58,6 @@ private:
STATE_DEVICE_READY,
STATE_SIM_PIN,
STATE_REGISTERING_NETWORK,
STATE_MANUAL_REGISTERING_NETWORK,
STATE_ATTACHING_NETWORK,
STATE_MAX_FSM_STATE
};
@ -146,12 +145,10 @@ private:
void state_device_ready();
void state_sim_pin();
void state_registering();
void state_manual_registering_network();
void state_attaching();
void enter_to_state(CellularState state);
void retry_state_or_fail();
void continue_from_state(CellularState state);
bool is_registered_to_plmn();
void report_failure(const char *msg);
void event();
void device_ready_cb();
@ -179,7 +176,6 @@ private:
int _event_id;
const char *_plmn;
bool _command_success;
bool _plmn_network_found;
bool _is_retry;
cell_callback_data_t _cb_data;
nsapi_event_t _current_event;