From 1fd9ba6caa3fe4fcc5aef65c6439060857d7b3f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teppo=20J=C3=A4rvelin?= Date: Sat, 24 Feb 2018 15:12:53 +0200 Subject: [PATCH] APN lookup from database support. --- .../easy_cellular/CellularConnectionUtil.cpp | 46 +++++----- .../easy_cellular/CellularConnectionUtil.h | 7 ++ .../easy_cellular/EasyCellularConnection.cpp | 88 +++++++++++++------ .../easy_cellular/EasyCellularConnection.h | 1 + features/cellular/framework/API/CellularSIM.h | 9 +- .../cellular/framework/AT/AT_CellularSIM.cpp | 14 +++ .../cellular/framework/AT/AT_CellularSIM.h | 2 + 7 files changed, 121 insertions(+), 46 deletions(-) diff --git a/features/cellular/easy_cellular/CellularConnectionUtil.cpp b/features/cellular/easy_cellular/CellularConnectionUtil.cpp index 542069fb95..887d6eb5c4 100644 --- a/features/cellular/easy_cellular/CellularConnectionUtil.cpp +++ b/features/cellular/easy_cellular/CellularConnectionUtil.cpp @@ -36,7 +36,7 @@ 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), _queue(8 * EVENTS_EVENT_SIZE), + _status_callback(0), _network(0), _power(0), _sim(0), _queue(8 * EVENTS_EVENT_SIZE), _queue_thread(0), _cellularDevice(&cellularDevice) { memset(_sim_pin, 0, sizeof(_sim_pin)); @@ -60,6 +60,12 @@ nsapi_error_t CellularConnectionUtil::init() return NSAPI_ERROR_NO_MEMORY; } + _sim = _cellularDevice->open_sim(_serial); + if (!_sim) { + stop(); + return NSAPI_ERROR_NO_MEMORY; + } + at_queue.chain(&_queue); tr_info("init done..."); @@ -94,43 +100,38 @@ void CellularConnectionUtil::set_sim_pin(const char * sim_pin) bool CellularConnectionUtil::open_sim() { + CellularSIM::SimState state = CellularSIM::SimStateUnknown; + // wait until SIM is readable + // here you could add wait(secs) if you know start delay of your SIM + while (_sim->get_sim_state(state) != NSAPI_ERROR_OK || state == CellularSIM::SimStateUnknown) { + tr_info("Waiting for SIM (state %d)...", state); + return false; + } + tr_info("Initial SIM state: %d", state); + if (strlen(_sim_pin)) { nsapi_error_t err; - static CellularSIM *sim; - if (!sim) { - sim = _cellularDevice->open_sim(_serial); - } - if (!sim) { - return false; - } - CellularSIM::SimState state = CellularSIM::SimStateUnknown; - // wait until SIM is readable - // here you could add wait(secs) if you know start delay of your SIM - while (sim->get_sim_state(state) != NSAPI_ERROR_OK || state == CellularSIM::SimStateUnknown) { - tr_debug("Waiting for SIM (state %d)...", state); - return false; - } if (state == CellularSIM::SimStatePinNeeded) { tr_info("SIM pin required, entering pin: %s", _sim_pin); - err = sim->set_pin(_sim_pin); + err = _sim->set_pin(_sim_pin); if (err) { tr_error("SIM pin set failed with: %d, bailing out...", err); return false; } // here you could add wait(secs) if you know delay of changing PIN on your SIM for (int i = 0; i < MAX_SIM_READY_WAITING_TIME; i++) { - if (sim->get_sim_state(state) == NSAPI_ERROR_OK && state == CellularSIM::SimStateReady) { + if (_sim->get_sim_state(state) == NSAPI_ERROR_OK && state == CellularSIM::SimStateReady) { break; } tr_debug("SIM state: %d", state); return false; } } - return state == CellularSIM::SimStateReady; } else { - tr_info("Continue without SIM."); - return true; + tr_info("No SIM pin provided."); } + + return state == CellularSIM::SimStateReady; } void CellularConnectionUtil::device_ready() @@ -506,6 +507,11 @@ CellularDevice* CellularConnectionUtil::get_device() return _cellularDevice; } +CellularSIM* CellularConnectionUtil::get_sim() +{ + return _sim; +} + NetworkStack *CellularConnectionUtil::get_stack() { return _cellularDevice->get_stack(); diff --git a/features/cellular/easy_cellular/CellularConnectionUtil.h b/features/cellular/easy_cellular/CellularConnectionUtil.h index 2de7c6bc1d..e38fdf8903 100644 --- a/features/cellular/easy_cellular/CellularConnectionUtil.h +++ b/features/cellular/easy_cellular/CellularConnectionUtil.h @@ -28,6 +28,7 @@ #include "CellularNetwork.h" #include "CellularPower.h" +#include "CellularSIM.h" // modem type is defined as CELLULAR_DEVICE macro #define _CELLULAR_STRINGIFY(a) #a @@ -105,6 +106,11 @@ public: */ CellularDevice* get_device(); + /** Get cellular sim interface + * @return sim interface, NULL on failure + */ + CellularSIM* get_sim(); + /** Change cellular connection to the target state * @param state to continue * @return see nsapi_error_t, 0 on success @@ -142,6 +148,7 @@ private: CellularNetwork *_network; CellularPower *_power; + CellularSIM *_sim; events::EventQueue _queue; rtos::Thread *_queue_thread; CellularDevice *_cellularDevice; diff --git a/features/cellular/easy_cellular/EasyCellularConnection.cpp b/features/cellular/easy_cellular/EasyCellularConnection.cpp index 370de95378..5f0c3de514 100644 --- a/features/cellular/easy_cellular/EasyCellularConnection.cpp +++ b/features/cellular/easy_cellular/EasyCellularConnection.cpp @@ -26,9 +26,12 @@ #include "CellularUtil.h" #include "EasyCellularConnection.h" - #include "CellularLog.h" +#if MBED_CONF_APP_CELLULAR_USE_APN_LOOKUP +#include "APN_db.h" +#endif //MBED_CONF_APP_CELLULAR_USE_APN_LOOKUP + namespace mbed { bool EasyCellularConnection::cellular_status(int state, int next_state) @@ -50,7 +53,7 @@ bool EasyCellularConnection::cellular_status(int state, int next_state) } EasyCellularConnection::EasyCellularConnection() : _is_connected(false), _is_initialized(false), - _target_state(CellularConnectionUtil::STATE_POWER_ON), + _credentials_set(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) { @@ -67,7 +70,7 @@ nsapi_error_t EasyCellularConnection::init() nsapi_error_t err = NSAPI_ERROR_OK; if (!_is_initialized) { #if defined (MDMRTS) && defined (MDMCTS) - _cellularSerial.set_flow_control(SerialBase::RTSCTS, MDMRTS, MDMCTS); + _cellularSerial.set_flow_control(SerialBase::RTSCTS, MDMRTS, MDMCTS); #endif _cellularConnectionUtil.set_serial(&_cellularSerial); _cellularConnectionUtil.set_callback(callback(this, &EasyCellularConnection::cellular_status)); @@ -85,16 +88,21 @@ nsapi_error_t EasyCellularConnection::init() void EasyCellularConnection::set_credentials(const char *apn, const char *uname, const char *pwd) { - _credentials_err = init(); + if (apn && strlen(apn) > 0) { + _credentials_err = init(); - if (_credentials_err) { - return; - } - CellularNetwork * network = _cellularConnectionUtil.get_network(); - if (network) { - _credentials_err = network->set_credentials(apn, uname, pwd); - } else { - tr_error("NO Network..."); + if (_credentials_err) { + return; + } + CellularNetwork * network = _cellularConnectionUtil.get_network(); + if (network) { + _credentials_err = network->set_credentials(apn, uname, pwd); + if (_credentials_err == NSAPI_ERROR_OK) { + _credentials_set = true; + } + } else { + tr_error("NO Network..."); + } } } @@ -107,20 +115,19 @@ void EasyCellularConnection::set_sim_pin(const char *sim_pin) nsapi_error_t EasyCellularConnection::connect(const char *sim_pin, const char *apn, const char *uname, const char *pwd) { - nsapi_error_t err = check_connect(); - if (err) { - return err; + if (_is_connected) { + return NSAPI_ERROR_IS_CONNECTED; + } + + set_credentials(apn, uname, pwd); + if (_credentials_err) { + return _credentials_err; } if (sim_pin) { _cellularConnectionUtil.set_sim_pin(sim_pin); } - err = _cellularConnectionUtil.get_network()->set_credentials(apn, uname, pwd); - if (err) { - return err; - } - return connect(); } @@ -129,6 +136,12 @@ nsapi_error_t EasyCellularConnection::check_connect() if (_is_connected) { return NSAPI_ERROR_IS_CONNECTED; } + + // there was an error while setting credentials but it's a void function so check error here... + if (_credentials_err) { + return _credentials_err; + } + nsapi_error_t err = init(); if (err) { return err; @@ -139,15 +152,39 @@ nsapi_error_t EasyCellularConnection::check_connect() nsapi_error_t EasyCellularConnection::connect() { - // there was an error while setting credentials but it's a void function so check error here... - if (_credentials_err) { - return _credentials_err; - } - nsapi_error_t err = check_connect(); if (err) { return err; } +#if MBED_CONF_APP_CELLULAR_USE_APN_LOOKUP + if (!_credentials_set) { + _target_state = CellularConnectionUtil::STATE_SIM_PIN; + err = _cellularConnectionUtil.continue_to_state(_target_state); + if (err == NSAPI_ERROR_OK) { + int sim_wait = _cellularSemaphore.wait(6*1000); // reserve 6 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); + if (err == NSAPI_ERROR_OK) { + const char *apn_config = apnconfig(imsi); + if (apn_config) { + const char* apn = _APN_GET(apn_config); + 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); + } + } + } + } + if (err) { + return err; + } + } +#endif // MBED_CONF_APP_CELLULAR_USE_APN_LOOKUP _target_state = CellularConnectionUtil::STATE_CONNECTED; err = _cellularConnectionUtil.continue_to_state(_target_state); @@ -166,6 +203,7 @@ nsapi_error_t EasyCellularConnection::disconnect() { _credentials_err = NSAPI_ERROR_OK; _is_connected = false; + _credentials_set = false; if (!_cellularConnectionUtil.get_network()) { return NSAPI_ERROR_NO_CONNECTION; } diff --git a/features/cellular/easy_cellular/EasyCellularConnection.h b/features/cellular/easy_cellular/EasyCellularConnection.h index 04e1e64397..a041e89765 100644 --- a/features/cellular/easy_cellular/EasyCellularConnection.h +++ b/features/cellular/easy_cellular/EasyCellularConnection.h @@ -136,6 +136,7 @@ private: bool _is_connected; bool _is_initialized; + bool _credentials_set; CellularConnectionUtil::CellularState _target_state; UARTSerial _cellularSerial; diff --git a/features/cellular/framework/API/CellularSIM.h b/features/cellular/framework/API/CellularSIM.h index 00ca6dc58d..8a15218802 100644 --- a/features/cellular/framework/API/CellularSIM.h +++ b/features/cellular/framework/API/CellularSIM.h @@ -23,7 +23,7 @@ namespace mbed { const int MAX_SIM_READY_WAITING_TIME = 30; - +const int MAX_IMSI_LENGTH = 15; /** * Class CellularSIM * @@ -78,6 +78,13 @@ public: * @return zero on success */ virtual nsapi_error_t get_sim_state(SimState &state) = 0; + + /** Get IMSI from the sim card + * + * @param imsi preallocated char* which after successful request contains imsi + * @return zero on success + */ + virtual nsapi_error_t get_imsi(char* imsi) = 0; }; } // namespace mbed diff --git a/features/cellular/framework/AT/AT_CellularSIM.cpp b/features/cellular/framework/AT/AT_CellularSIM.cpp index e66154791d..3f1fb65461 100644 --- a/features/cellular/framework/AT/AT_CellularSIM.cpp +++ b/features/cellular/framework/AT/AT_CellularSIM.cpp @@ -114,3 +114,17 @@ nsapi_error_t AT_CellularSIM::set_pin_query(const char *sim_pin, bool query_pin) } return _at.unlock_return_error(); } + +nsapi_error_t AT_CellularSIM::get_imsi(char* imsi) +{ + _at.lock(); + _at.cmd_start("AT+CIMI"); + _at.cmd_stop(); + _at.resp_start(); + int len = _at.read_string(imsi, MAX_IMSI_LENGTH); + if (len > 0) { + imsi[len] = '\0'; + } + _at.resp_stop(); + return _at.unlock_return_error(); +} diff --git a/features/cellular/framework/AT/AT_CellularSIM.h b/features/cellular/framework/AT/AT_CellularSIM.h index 007d8b6d22..be53416820 100644 --- a/features/cellular/framework/AT/AT_CellularSIM.h +++ b/features/cellular/framework/AT/AT_CellularSIM.h @@ -43,6 +43,8 @@ public: virtual nsapi_error_t set_pin_query(const char *sim_pin, bool query_pin); virtual nsapi_error_t get_sim_state(SimState &state); + + virtual nsapi_error_t get_imsi(char* imsi); }; } // namespace mbed