working example?

pull/6082/head
Teppo Järvelin 2018-02-12 10:47:20 +02:00 committed by Ari Parkkila
parent fbfbdc9718
commit 1dcc6684bf
4 changed files with 184 additions and 94 deletions

View File

@ -39,8 +39,11 @@
static EventQueue at_queue(8 * EVENTS_EVENT_SIZE); static EventQueue at_queue(8 * EVENTS_EVENT_SIZE);
static CELLULAR_DEVICE cellularDevice(at_queue); static CELLULAR_DEVICE cellularDevice(at_queue);
CellularConnectionUtil::CellularConnectionUtil() : _serial(0), _state(STATE_POWER_ON), _next_state(_state), _status_callback(0), _network(0), _power(0), _queue(8 * EVENTS_EVENT_SIZE), _queue_thread(0), _cellularDevice(&cellularDevice) CellularConnectionUtil::CellularConnectionUtil() : _serial(0), _state(STATE_POWER_ON), _next_state(_state),
_status_callback(0), _network(0), _power(0), _queue(8 * EVENTS_EVENT_SIZE),
_queue_thread(0), _cellularDevice(&cellularDevice)
{ {
memset(_sim_pin, sizeof(_sim_pin), 0);
} }
CellularConnectionUtil::~CellularConnectionUtil() CellularConnectionUtil::~CellularConnectionUtil()
@ -48,6 +51,25 @@ CellularConnectionUtil::~CellularConnectionUtil()
stop(); stop();
} }
nsapi_error_t CellularConnectionUtil::init()
{
_power = _cellularDevice->open_power(_serial);
if (!_power) {
stop();
return NSAPI_ERROR_NO_MEMORY;
}
_network = _cellularDevice->open_network(_serial);
if (!_network) {
stop();
return NSAPI_ERROR_NO_MEMORY;
}
at_queue.chain(&_queue);
log_info("init done...");
return NSAPI_ERROR_OK;
}
bool CellularConnectionUtil::open_power(FileHandle *fh) bool CellularConnectionUtil::open_power(FileHandle *fh)
{ {
if (!_power) { if (!_power) {
@ -69,45 +91,50 @@ bool CellularConnectionUtil::open_power(FileHandle *fh)
return true; return true;
} }
void CellularConnectionUtil::set_sim_pin(const char * sim_pin)
{
strncpy(_sim_pin, sim_pin, PIN_SIZE);
}
bool CellularConnectionUtil::open_sim() bool CellularConnectionUtil::open_sim()
{ {
#ifdef MBED_CONF_APP_CELLULAR_SIM_PIN if (strlen(_sim_pin)) {
nsapi_error_t err; nsapi_error_t err;
static CellularSIM *sim; static CellularSIM *sim;
if (!sim) { if (!sim) {
sim = _cellularDevice->open_sim(_serial); sim = _cellularDevice->open_sim(_serial);
} }
if (!sim) { 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) {
log_debug("Waiting for SIM (state %d)...", state);
return false;
}
if (state == CellularSIM::SimStatePinNeeded) {
log_info("SIM pin required, entering pin: %s", MBED_CONF_APP_CELLULAR_SIM_PIN);
err = sim->set_pin(MBED_CONF_APP_CELLULAR_SIM_PIN);
if (err) {
log_error("SIM pin set failed with: %d, bailing out...", err);
return false; return false;
} }
// here you could add wait(secs) if you know delay of changing PIN on your SIM CellularSIM::SimState state = CellularSIM::SimStateUnknown;
for (int i = 0; i < MAX_SIM_READY_WAITING_TIME; i++) { // wait until SIM is readable
if (sim->get_sim_state(state) == NSAPI_ERROR_OK && state == CellularSIM::SimStateReady) { // here you could add wait(secs) if you know start delay of your SIM
break; while (sim->get_sim_state(state) != NSAPI_ERROR_OK || state == CellularSIM::SimStateUnknown) {
log_debug("Waiting for SIM (state %d)...", state);
return false;
}
if (state == CellularSIM::SimStatePinNeeded) {
log_info("SIM pin required, entering pin: %s", _sim_pin);
err = sim->set_pin(_sim_pin);
if (err) {
log_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) {
break;
}
log_debug("SIM state: %d", state);
return false;
} }
log_debug("SIM state: %d", state);
return false;
} }
return state == CellularSIM::SimStateReady;
} else {
log_info("Continue without SIM.");
return true;
} }
return state == CellularSIM::SimStateReady;
#else
log_info("Continue without SIM.");
return true;
#endif
} }
void CellularConnectionUtil::device_ready() void CellularConnectionUtil::device_ready()
@ -143,7 +170,8 @@ bool CellularConnectionUtil::set_network_registration(char *plmn)
return true; return true;
} }
bool CellularConnectionUtil::get_network_registration(CellularNetwork::RegistrationType type, CellularNetwork::RegistrationStatus &status, bool &is_registered) bool CellularConnectionUtil::get_network_registration(CellularNetwork::RegistrationType type,
CellularNetwork::RegistrationStatus &status, bool &is_registered)
{ {
is_registered = false; is_registered = false;
bool is_roaming = false; bool is_roaming = false;
@ -220,9 +248,11 @@ void CellularConnectionUtil::report_failure(const char* msg)
} }
} }
bool CellularConnectionUtil::continue_with_state(CellularState state) nsapi_error_t CellularConnectionUtil::continue_to_state(CellularState state)
{ {
_state = state; if (state < _state) {
_state = state;
}
if (!_queue.call_in(0, callback(this, &CellularConnectionUtil::event))) { if (!_queue.call_in(0, callback(this, &CellularConnectionUtil::event))) {
stop(); stop();
return NSAPI_ERROR_NO_MEMORY; return NSAPI_ERROR_NO_MEMORY;
@ -235,6 +265,7 @@ void CellularConnectionUtil::event()
{ {
nsapi_error_t err; nsapi_error_t err;
int event_timeout = -1; int event_timeout = -1;
switch (_state) { switch (_state) {
case STATE_POWER_ON: case STATE_POWER_ON:
cellularDevice.set_timeout(TIMEOUT_POWER_ON); cellularDevice.set_timeout(TIMEOUT_POWER_ON);
@ -376,18 +407,15 @@ void CellularConnectionUtil::event()
//network->set_credentials("internet"); //network->set_credentials("internet");
err = _network->connect(); err = _network->connect();
if (!err) { if (!err) {
_next_state = STATE_READY; _next_state = STATE_CONNECTED;
} else { } else {
report_failure("Network connect"); report_failure("Network connect");
return; return;
} }
break; break;
case STATE_READY: case STATE_CONNECTED:
cellularDevice.set_timeout(TIMEOUT_NETWORK); cellularDevice.set_timeout(TIMEOUT_NETWORK);
log_debug("Cellular ready! (timeout %d ms)", TIMEOUT_NETWORK); log_debug("Cellular ready! (timeout %d ms)", TIMEOUT_NETWORK);
if (_status_callback) {
_status_callback(_state, _next_state);
}
break; break;
default: default:
MBED_ASSERT(0); MBED_ASSERT(0);
@ -426,40 +454,36 @@ void CellularConnectionUtil::event()
} }
} }
bool CellularConnectionUtil::start(bool start_dispatch) nsapi_error_t CellularConnectionUtil::start_dispatch()
{ {
log_info("CellularConnectionUtil::start"); log_info("CellularConnectionUtil::start");
_power = _cellularDevice->open_power(_serial); log_info("Create cellular thread");
if (!_power) {
MBED_ASSERT(!_queue_thread);
_queue_thread = new Thread();
if (!_queue_thread) {
stop(); stop();
return false; return NSAPI_ERROR_NO_MEMORY;
} }
_network = _cellularDevice->open_network(_serial); if (_queue_thread->start(callback(&_queue, &EventQueue::dispatch_forever)) != osOK) {
if (!_network) {
stop(); stop();
return false; return NSAPI_ERROR_NO_MEMORY;
}
if (!_queue.call_in(0, callback(this, &CellularConnectionUtil::event))) {
stop();
return false;
} }
at_queue.chain(&_queue);
if (start_dispatch) {
log_info("Create cellular thread");
_queue_thread = new Thread();
if (!_queue_thread) {
stop();
return false;
}
if (_queue_thread->start(callback(&_queue, &EventQueue::dispatch_forever)) != osOK) {
stop();
return false;
}
}
log_info("CellularConnectionUtil::started"); log_info("CellularConnectionUtil::started");
return true; return NSAPI_ERROR_OK;
}
nsapi_error_t CellularConnectionUtil::disconnect()
{
log_info("CellularConnectionUtil::disconnect");
nsapi_error_t err = NSAPI_ERROR_OK;
if (_network) {
err = _network->disconnect();
}
return err;
} }
void CellularConnectionUtil::stop() void CellularConnectionUtil::stop()
@ -478,7 +502,7 @@ void CellularConnectionUtil::set_serial(UARTSerial *serial)
_serial = serial; _serial = serial;
} }
void CellularConnectionUtil::set_callback(mbed::Callback<int(int, int)> status_callback) void CellularConnectionUtil::set_callback(mbed::Callback<bool(int, int)> status_callback)
{ {
_status_callback = status_callback; _status_callback = status_callback;
} }
@ -490,7 +514,7 @@ EventQueue *CellularConnectionUtil::get_queue()
CellularNetwork* CellularConnectionUtil::get_network() CellularNetwork* CellularConnectionUtil::get_network()
{ {
if (_state != STATE_READY) { if (_state != STATE_CONNECTED) {
return NULL; return NULL;
} }
return _network; return _network;
@ -498,11 +522,9 @@ CellularNetwork* CellularConnectionUtil::get_network()
CellularDevice* CellularConnectionUtil::get_device() CellularDevice* CellularConnectionUtil::get_device()
{ {
if (_cellularDevice) { if (_cellularDevice) {
return _cellularDevice; return _cellularDevice;
} else { } else {
return NULL; return NULL;
} }
} }

View File

@ -31,6 +31,8 @@
#include "CellularTargets.h" #include "CellularTargets.h"
#include CELLULAR_STRINGIFY(CELLULAR_DEVICE.h) #include CELLULAR_STRINGIFY(CELLULAR_DEVICE.h)
const int PIN_SIZE = 8;
class CellularConnectionUtil class CellularConnectionUtil
{ {
public: public:
@ -44,20 +46,26 @@ public:
STATE_ATTACH_NETWORK = 7, STATE_ATTACH_NETWORK = 7,
STATE_ATTACHING_NETWORK = 8, STATE_ATTACHING_NETWORK = 8,
STATE_CONNECT_NETWORK = 9, STATE_CONNECT_NETWORK = 9,
STATE_READY = 10, STATE_CONNECTED = 10,
}; };
public: public:
CellularConnectionUtil(); CellularConnectionUtil();
virtual ~CellularConnectionUtil(); virtual ~CellularConnectionUtil();
void set_serial(UARTSerial *serial); void set_serial(UARTSerial *serial);
void set_callback(mbed::Callback<int(int, int)> status_callback); void set_callback(mbed::Callback<bool(int, int)> status_callback);
EventQueue* get_queue(); EventQueue* get_queue();
bool start(bool start_dispatch = true); nsapi_error_t start_dispatch();
nsapi_error_t init();
nsapi_error_t disconnect();
void stop(); void stop();
CellularNetwork* get_network(); CellularNetwork* get_network();
CellularDevice* get_device(); CellularDevice* get_device();
bool continue_with_state(CellularState state); nsapi_error_t continue_to_state(CellularState state);
void set_sim_pin(const char * sim_pin);
protected: protected:
bool open_power(FileHandle *fh); bool open_power(FileHandle *fh);
@ -77,13 +85,14 @@ private:
CellularState _state; CellularState _state;
CellularState _next_state; CellularState _next_state;
mbed::Callback<int(int, int)> _status_callback; mbed::Callback<bool(int, int)> _status_callback;
CellularNetwork *_network; CellularNetwork *_network;
CellularPower *_power; CellularPower *_power;
EventQueue _queue; EventQueue _queue;
Thread *_queue_thread; Thread *_queue_thread;
CellularDevice *_cellularDevice; CellularDevice *_cellularDevice;
char _sim_pin[PIN_SIZE+1];
}; };

View File

@ -18,7 +18,6 @@
#include "CellularConnectionUtil.h" #include "CellularConnectionUtil.h"
#include "CellularTargets.h" #include "CellularTargets.h"
#include "CellularUtil.h" #include "CellularUtil.h"
#include "CellularConnectionUtil.h"
#include "EasyCellularConnection.h" #include "EasyCellularConnection.h"
@ -28,18 +27,29 @@
static CellularConnectionUtil cellularConnection; static CellularConnectionUtil cellularConnection;
static Semaphore cellularSemaphore(0); static Semaphore cellularSemaphore(0);
static UARTSerial cellularSerial(MDMTXD, MDMRXD, MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE); static UARTSerial cellularSerial(MDMTXD, MDMRXD, MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE);
static int cellular_status(int state, int next_state)
bool EasyCellularConnection::cellular_status(int state, int next_state)
{ {
printf("cellular_status %d=>%d", state, next_state); log_info("cellular_status %d=>%d", state, next_state);
if (state == CellularConnectionUtil::STATE_READY) { if (_target_state == state) {
if (state == CellularConnectionUtil::STATE_CONNECTED) {
_is_connected = true;
} else {
_is_connected = false;
}
MBED_ASSERT(cellularSemaphore.release() == osOK); MBED_ASSERT(cellularSemaphore.release() == osOK);
return false;
} }
return 1; else {
_is_connected = false;
}
return true;
} }
EasyCellularConnection::EasyCellularConnection() EasyCellularConnection::EasyCellularConnection() : _is_connected(false), _target_state(CellularConnectionUtil::STATE_POWER_ON)
{ {
log_info("EasyCellularConnection start"); log_info("EasyCellularConnection()");
} }
EasyCellularConnection::~EasyCellularConnection() EasyCellularConnection::~EasyCellularConnection()
@ -47,49 +57,81 @@ EasyCellularConnection::~EasyCellularConnection()
cellularConnection.stop(); cellularConnection.stop();
} }
nsapi_error_t EasyCellularConnection::init()
{
log_init(STDIO_UART_TX, STDIO_UART_RX, MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE);
#if defined (MDMRTS) && defined (MDMCTS)
cellularSerial.set_flow_control(SerialBase::RTSCTS, MDMRTS, MDMCTS);
#endif
cellularConnection.set_serial(&cellularSerial);
cellularConnection.set_callback(callback(this, &EasyCellularConnection::cellular_status));
nsapi_error_t err = cellularConnection.init();
if (err == NSAPI_ERROR_OK) {
err = cellularConnection.start_dispatch();
}
return err;
}
void EasyCellularConnection::set_credentials(const char *apn, const char *uname, const char *pwd) void EasyCellularConnection::set_credentials(const char *apn, const char *uname, const char *pwd)
{ {
CellularNetwork * network = cellularConnection.get_network();
if (network) {
network->set_credentials(apn, uname, pwd);
} else {
log_error("NO Network...");
}
} }
void EasyCellularConnection::set_sim_pin(const char *sim_pin) void EasyCellularConnection::set_sim_pin(const char *sim_pin)
{ {
cellularConnection.set_sim_pin(sim_pin);
} }
nsapi_error_t EasyCellularConnection::connect(const char *sim_pin, const char *apn, const char *uname, const char *pwd) nsapi_error_t EasyCellularConnection::connect(const char *sim_pin, const char *apn, const char *uname, const char *pwd)
{ {
cellularConnection.set_sim_pin(sim_pin);
cellularConnection.get_network()->set_credentials(apn, uname, pwd);
return connect(); return connect();
} }
nsapi_error_t EasyCellularConnection::connect() nsapi_error_t EasyCellularConnection::connect()
{ {
#if defined (MDMRTS) && defined (MDMCTS) _target_state = CellularConnectionUtil::STATE_CONNECTED;
cellularSerial.set_flow_control(SerialBase::RTSCTS, MDMRTS, MDMCTS); nsapi_error_t err = cellularConnection.continue_to_state(_target_state);
#endif if (err == NSAPI_ERROR_OK) {
cellularConnection.set_serial(&cellularSerial);
cellularConnection.set_callback(callback(cellular_status));
if (cellularConnection.start()) {
int ret_wait = cellularSemaphore.wait(10*60*1000); // cellular network searching may take several minutes int ret_wait = cellularSemaphore.wait(10*60*1000); // cellular network searching may take several minutes
if (ret_wait != 1) { if (ret_wait != 1) {
log_error("No cellular connection"); log_info("No cellular connection");
err = NSAPI_ERROR_NO_CONNECTION;
} }
} }
return cellularConnection.get_network()?NSAPI_ERROR_OK:NSAPI_ERROR_NO_CONNECTION; return err;
} }
nsapi_error_t EasyCellularConnection::disconnect() nsapi_error_t EasyCellularConnection::disconnect()
{ {
return 0; _is_connected = false;
return cellularConnection.disconnect();
} }
bool EasyCellularConnection::is_connected() bool EasyCellularConnection::is_connected()
{ {
return 0; return _is_connected;
} }
const char *EasyCellularConnection::get_ip_address() const char *EasyCellularConnection::get_ip_address()
{ {
return cellularConnection.get_network()->get_ip_address(); CellularNetwork * network = cellularConnection.get_network();
if (network) {
return cellularConnection.get_network()->get_ip_address();
} else {
return NULL;
}
} }
const char *EasyCellularConnection::get_netmask() const char *EasyCellularConnection::get_netmask()

View File

@ -17,6 +17,7 @@
#define EASY_CELLULAR_CONNECTION_H #define EASY_CELLULAR_CONNECTION_H
#include "netsocket/CellularBase.h" #include "netsocket/CellularBase.h"
#include "CellularConnectionUtil.h"
/** ExampleCellularBase class /** ExampleCellularBase class
* *
@ -30,6 +31,11 @@ public:
public: public:
/**
* MUST CALL, create power and start dispatcher
*/
nsapi_error_t init();
/** Set the Cellular network credentials /** Set the Cellular network credentials
* *
* Please check documentation of connect() for default behaviour of APN settings. * Please check documentation of connect() for default behaviour of APN settings.
@ -112,6 +118,17 @@ protected:
* @return The underlying NetworkStack object * @return The underlying NetworkStack object
*/ */
virtual NetworkStack *get_stack(); virtual NetworkStack *get_stack();
private:
/** Callback for cellular status changes
*
* @return true to continue state machine
*/
bool cellular_status(int state, int next_state);
CellularConnectionUtil::CellularState _target_state;
bool _is_connected;
}; };
#endif // EASY_CELLULAR_CONNECTION_H #endif // EASY_CELLULAR_CONNECTION_H