Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: nRF51_Vdd TextLCD BME280
EasyCellularConnection.cpp
00001 /* 00002 * Copyright (c) 2017, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "CellularTargets.h" 00019 #ifdef CELLULAR_DEVICE 00020 00021 #if NSAPI_PPP_AVAILABLE 00022 #include "nsapi_ppp.h" 00023 #endif 00024 00025 #include "CellularConnectionFSM.h" 00026 #include "CellularUtil.h" 00027 00028 #include "EasyCellularConnection.h" 00029 #include "CellularLog.h" 00030 #include "mbed_wait_api.h" 00031 00032 #if USE_APN_LOOKUP 00033 #include "APN_db.h" 00034 #endif //USE_APN_LOOKUP 00035 00036 namespace mbed { 00037 00038 bool EasyCellularConnection::cellular_status(int state, int next_state) 00039 { 00040 tr_info("cellular_status: %s ==> %s", _cellularConnectionFSM->get_state_string((CellularConnectionFSM::CellularState)state), 00041 _cellularConnectionFSM->get_state_string((CellularConnectionFSM::CellularState)next_state)); 00042 00043 if (_target_state == state) { 00044 tr_info("Target state reached: %s", _cellularConnectionFSM->get_state_string(_target_state)); 00045 (void)_cellularSemaphore.release(); 00046 return false; // return false -> state machine is halted 00047 } 00048 00049 // only in case of an error or when connected is reached state and next_state can be the same. 00050 // Release semaphore to return application instead of waiting for semaphore to complete. 00051 if (state == next_state) { 00052 tr_error("cellular_status: state and next_state are same, release semaphore as this is an error in state machine"); 00053 _stm_error = true; 00054 (void)_cellularSemaphore.release(); 00055 return false; // return false -> state machine is halted 00056 } 00057 00058 return true; 00059 } 00060 00061 void EasyCellularConnection::network_callback(nsapi_event_t ev, intptr_t ptr) 00062 { 00063 if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE ) { 00064 if (ptr == NSAPI_STATUS_GLOBAL_UP ) { 00065 _is_connected = true; 00066 } else { 00067 _is_connected = false; 00068 } 00069 } 00070 if (_status_cb) { 00071 _status_cb(ev, ptr); 00072 } 00073 } 00074 00075 EasyCellularConnection::EasyCellularConnection(bool debug) : 00076 _is_connected(false), _is_initialized(false), _stm_error(false), 00077 _target_state(CellularConnectionFSM::STATE_POWER_ON), 00078 _cellularSerial(MDMTXD, MDMRXD, MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE), _cellularSemaphore(0), 00079 _cellularConnectionFSM(0), _credentials_err(NSAPI_ERROR_OK ), _status_cb(0) 00080 { 00081 tr_info("EasyCellularConnection()"); 00082 #if USE_APN_LOOKUP 00083 _credentials_set = false; 00084 #endif // #if USE_APN_LOOKUP 00085 modem_debug_on(debug); 00086 } 00087 00088 EasyCellularConnection::~EasyCellularConnection() 00089 { 00090 if (_cellularConnectionFSM) { 00091 _cellularConnectionFSM->set_callback(NULL); 00092 _cellularConnectionFSM->attach(NULL); 00093 delete _cellularConnectionFSM; 00094 } 00095 } 00096 00097 nsapi_error_t EasyCellularConnection::init() 00098 { 00099 nsapi_error_t err = NSAPI_ERROR_OK ; 00100 _stm_error = false; 00101 if (!_is_initialized) { 00102 #if defined (MDMRTS) && defined (MDMCTS) 00103 _cellularSerial.set_flow_control(SerialBase::RTSCTS, MDMRTS, MDMCTS); 00104 #endif 00105 _cellularConnectionFSM = new CellularConnectionFSM(); 00106 _cellularConnectionFSM->set_serial(&_cellularSerial); 00107 _cellularConnectionFSM->set_callback(callback(this, &EasyCellularConnection::cellular_status)); 00108 00109 err = _cellularConnectionFSM->init(); 00110 00111 if (err == NSAPI_ERROR_OK ) { 00112 err = _cellularConnectionFSM->start_dispatch(); 00113 _cellularConnectionFSM->attach(callback(this, &EasyCellularConnection::network_callback)); 00114 } 00115 _is_initialized = true; 00116 } 00117 00118 return err; 00119 } 00120 00121 void EasyCellularConnection::set_credentials(const char *apn, const char *uname, const char *pwd) 00122 { 00123 if (apn && strlen(apn) > 0) { 00124 _credentials_err = init(); 00125 00126 if (_credentials_err) { 00127 return; 00128 } 00129 CellularNetwork *network = _cellularConnectionFSM->get_network(); 00130 if (network) { 00131 _credentials_err = network->set_credentials(apn, uname, pwd); 00132 #if USE_APN_LOOKUP 00133 if (_credentials_err == NSAPI_ERROR_OK ) { 00134 _credentials_set = true; 00135 } 00136 #endif // #if USE_APN_LOOKUP 00137 } else { 00138 //if get_network() returns NULL it means there was not enough memory for 00139 //an AT_CellularNetwork element during CellularConnectionFSM initialization 00140 tr_error("There was not enough memory during CellularConnectionFSM initialization"); 00141 } 00142 } 00143 } 00144 00145 void EasyCellularConnection::set_sim_pin(const char *sim_pin) 00146 { 00147 if (sim_pin && strlen(sim_pin) > 0) { 00148 if (!_cellularConnectionFSM) { 00149 _credentials_err = init(); 00150 00151 if (_credentials_err) { 00152 return; 00153 } 00154 } 00155 _cellularConnectionFSM->set_sim_pin(sim_pin); 00156 } 00157 } 00158 00159 nsapi_error_t EasyCellularConnection::connect(const char *sim_pin, const char *apn, const char *uname, const char *pwd) 00160 { 00161 if (_is_connected) { 00162 return NSAPI_ERROR_IS_CONNECTED ; 00163 } 00164 00165 set_credentials(apn, uname, pwd); 00166 if (_credentials_err) { 00167 return _credentials_err; 00168 } 00169 00170 if (sim_pin) { 00171 set_sim_pin(sim_pin); 00172 } 00173 00174 return connect(); 00175 } 00176 00177 nsapi_error_t EasyCellularConnection::check_connect() 00178 { 00179 if (_is_connected) { 00180 return NSAPI_ERROR_IS_CONNECTED ; 00181 } 00182 00183 // there was an error while setting credentials but it's a void function so check error here... 00184 if (_credentials_err) { 00185 return _credentials_err; 00186 } 00187 00188 nsapi_error_t err = init(); 00189 if (err) { 00190 return err; 00191 } 00192 00193 return NSAPI_ERROR_OK ; 00194 } 00195 00196 nsapi_error_t EasyCellularConnection::connect() 00197 { 00198 nsapi_error_t err = check_connect(); 00199 if (err) { 00200 return err; 00201 } 00202 #if USE_APN_LOOKUP 00203 if (!_credentials_set) { 00204 _target_state = CellularConnectionFSM::STATE_SIM_PIN; 00205 err = _cellularConnectionFSM->continue_to_state(_target_state); 00206 if (err == NSAPI_ERROR_OK ) { 00207 int sim_wait = _cellularSemaphore.wait(60 * 1000); // reserve 60 seconds to access to SIM 00208 if (sim_wait != 1 || _stm_error) { 00209 tr_error("NO SIM ACCESS"); 00210 err = NSAPI_ERROR_NO_CONNECTION ; 00211 } else { 00212 char imsi[MAX_IMSI_LENGTH + 1]; 00213 wait(1); // need to wait to access SIM in some modems 00214 err = _cellularConnectionFSM->get_sim()->get_imsi(imsi); 00215 if (err == NSAPI_ERROR_OK ) { 00216 const char *apn_config = apnconfig(imsi); 00217 if (apn_config) { 00218 const char *apn = _APN_GET(apn_config); 00219 const char *uname = _APN_GET(apn_config); 00220 const char *pwd = _APN_GET(apn_config); 00221 tr_info("Looked up APN %s", apn); 00222 err = _cellularConnectionFSM->get_network()->set_credentials(apn, uname, pwd); 00223 } 00224 } 00225 } 00226 } 00227 if (err) { 00228 tr_error("APN lookup failed"); 00229 return err; 00230 } 00231 } 00232 #endif // USE_APN_LOOKUP 00233 00234 _target_state = CellularConnectionFSM::STATE_CONNECTED; 00235 err = _cellularConnectionFSM->continue_to_state(_target_state); 00236 if (err == NSAPI_ERROR_OK ) { 00237 int ret_wait = _cellularSemaphore.wait(10 * 60 * 1000); // cellular network searching may take several minutes 00238 if (ret_wait != 1 || _stm_error) { 00239 tr_info("No cellular connection"); 00240 err = NSAPI_ERROR_NO_CONNECTION ; 00241 } 00242 } 00243 00244 return err; 00245 } 00246 00247 nsapi_error_t EasyCellularConnection::disconnect() 00248 { 00249 _credentials_err = NSAPI_ERROR_OK ; 00250 _is_connected = false; 00251 _is_initialized = false; 00252 _stm_error = false; 00253 #if USE_APN_LOOKUP 00254 _credentials_set = false; 00255 #endif // #if USE_APN_LOOKUP 00256 00257 nsapi_error_t err = NSAPI_ERROR_OK ; 00258 if (_cellularConnectionFSM && _cellularConnectionFSM->get_network()) { 00259 err = _cellularConnectionFSM->get_network()->disconnect(); 00260 } 00261 00262 if (err == NSAPI_ERROR_OK ) { 00263 delete _cellularConnectionFSM; 00264 _cellularConnectionFSM = NULL; 00265 } 00266 00267 return err; 00268 } 00269 00270 bool EasyCellularConnection::is_connected() 00271 { 00272 return _is_connected; 00273 } 00274 00275 const char *EasyCellularConnection::get_ip_address() 00276 { 00277 if (_cellularConnectionFSM) { 00278 CellularNetwork *network = _cellularConnectionFSM->get_network(); 00279 if (!network) { 00280 return NULL; 00281 } 00282 return _cellularConnectionFSM->get_network()->get_ip_address(); 00283 } else { 00284 return NULL; 00285 } 00286 } 00287 00288 const char *EasyCellularConnection::get_netmask() 00289 { 00290 if (_cellularConnectionFSM) { 00291 CellularNetwork *network = _cellularConnectionFSM->get_network(); 00292 if (!network) { 00293 return NULL; 00294 } 00295 return network->get_netmask(); 00296 } else { 00297 return NULL; 00298 } 00299 } 00300 00301 const char *EasyCellularConnection::get_gateway() 00302 { 00303 if (_cellularConnectionFSM) { 00304 CellularNetwork *network = _cellularConnectionFSM->get_network(); 00305 if (!network) { 00306 return NULL; 00307 } 00308 return network->get_gateway(); 00309 } else { 00310 return NULL; 00311 } 00312 } 00313 00314 void EasyCellularConnection::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb) 00315 { 00316 _status_cb = status_cb; 00317 } 00318 00319 void EasyCellularConnection::modem_debug_on(bool on) 00320 { 00321 if (_cellularConnectionFSM) { 00322 CellularDevice *dev = _cellularConnectionFSM->get_device(); 00323 if (dev) { 00324 dev->modem_debug_on(on); 00325 } 00326 } 00327 } 00328 00329 void EasyCellularConnection::set_plmn(const char *plmn) 00330 { 00331 if (plmn && strlen(plmn) > 0) { 00332 if (!_cellularConnectionFSM) { 00333 _credentials_err = init(); 00334 00335 if (_credentials_err) { 00336 return; 00337 } 00338 } 00339 _cellularConnectionFSM->set_plmn(plmn); 00340 } 00341 } 00342 00343 NetworkStack *EasyCellularConnection::get_stack() 00344 { 00345 if (_cellularConnectionFSM) { 00346 return _cellularConnectionFSM->get_stack(); 00347 } else { 00348 return NULL; 00349 } 00350 } 00351 00352 CellularDevice *EasyCellularConnection::get_device() 00353 { 00354 return _cellularConnectionFSM->get_device(); 00355 } 00356 00357 UARTSerial *EasyCellularConnection::get_serial() 00358 { 00359 return &_cellularSerial; 00360 } 00361 00362 } // namespace 00363 00364 #endif // CELLULAR_DEVICE
Generated on Tue Jul 12 2022 15:15:43 by
