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 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()
@ -48,6 +51,25 @@ CellularConnectionUtil::~CellularConnectionUtil()
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)
{
if (!_power) {
@ -69,45 +91,50 @@ bool CellularConnectionUtil::open_power(FileHandle *fh)
return true;
}
void CellularConnectionUtil::set_sim_pin(const char * sim_pin)
{
strncpy(_sim_pin, sim_pin, PIN_SIZE);
}
bool CellularConnectionUtil::open_sim()
{
#ifdef MBED_CONF_APP_CELLULAR_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) {
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);
if (strlen(_sim_pin)) {
nsapi_error_t err;
static CellularSIM *sim;
if (!sim) {
sim = _cellularDevice->open_sim(_serial);
}
if (!sim) {
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;
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", _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()
@ -143,7 +170,8 @@ bool CellularConnectionUtil::set_network_registration(char *plmn)
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;
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))) {
stop();
return NSAPI_ERROR_NO_MEMORY;
@ -235,6 +265,7 @@ void CellularConnectionUtil::event()
{
nsapi_error_t err;
int event_timeout = -1;
switch (_state) {
case STATE_POWER_ON:
cellularDevice.set_timeout(TIMEOUT_POWER_ON);
@ -376,18 +407,15 @@ void CellularConnectionUtil::event()
//network->set_credentials("internet");
err = _network->connect();
if (!err) {
_next_state = STATE_READY;
_next_state = STATE_CONNECTED;
} else {
report_failure("Network connect");
return;
}
break;
case STATE_READY:
case STATE_CONNECTED:
cellularDevice.set_timeout(TIMEOUT_NETWORK);
log_debug("Cellular ready! (timeout %d ms)", TIMEOUT_NETWORK);
if (_status_callback) {
_status_callback(_state, _next_state);
}
break;
default:
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");
_power = _cellularDevice->open_power(_serial);
if (!_power) {
log_info("Create cellular thread");
MBED_ASSERT(!_queue_thread);
_queue_thread = new Thread();
if (!_queue_thread) {
stop();
return false;
return NSAPI_ERROR_NO_MEMORY;
}
_network = _cellularDevice->open_network(_serial);
if (!_network) {
if (_queue_thread->start(callback(&_queue, &EventQueue::dispatch_forever)) != osOK) {
stop();
return false;
}
if (!_queue.call_in(0, callback(this, &CellularConnectionUtil::event))) {
stop();
return false;
return NSAPI_ERROR_NO_MEMORY;
}
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");
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()
@ -478,7 +502,7 @@ void CellularConnectionUtil::set_serial(UARTSerial *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;
}
@ -490,7 +514,7 @@ EventQueue *CellularConnectionUtil::get_queue()
CellularNetwork* CellularConnectionUtil::get_network()
{
if (_state != STATE_READY) {
if (_state != STATE_CONNECTED) {
return NULL;
}
return _network;
@ -498,11 +522,9 @@ CellularNetwork* CellularConnectionUtil::get_network()
CellularDevice* CellularConnectionUtil::get_device()
{
if (_cellularDevice) {
return _cellularDevice;
} else {
return NULL;
}
}

View File

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

View File

@ -18,7 +18,6 @@
#include "CellularConnectionUtil.h"
#include "CellularTargets.h"
#include "CellularUtil.h"
#include "CellularConnectionUtil.h"
#include "EasyCellularConnection.h"
@ -28,18 +27,29 @@
static CellularConnectionUtil cellularConnection;
static Semaphore cellularSemaphore(0);
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);
if (state == CellularConnectionUtil::STATE_READY) {
log_info("cellular_status %d=>%d", state, next_state);
if (_target_state == state) {
if (state == CellularConnectionUtil::STATE_CONNECTED) {
_is_connected = true;
} else {
_is_connected = false;
}
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()
@ -47,49 +57,81 @@ EasyCellularConnection::~EasyCellularConnection()
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)
{
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)
{
cellularConnection.set_sim_pin(sim_pin);
}
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();
}
nsapi_error_t EasyCellularConnection::connect()
{
#if defined (MDMRTS) && defined (MDMCTS)
cellularSerial.set_flow_control(SerialBase::RTSCTS, MDMRTS, MDMCTS);
#endif
cellularConnection.set_serial(&cellularSerial);
cellularConnection.set_callback(callback(cellular_status));
if (cellularConnection.start()) {
_target_state = CellularConnectionUtil::STATE_CONNECTED;
nsapi_error_t err = cellularConnection.continue_to_state(_target_state);
if (err == NSAPI_ERROR_OK) {
int ret_wait = cellularSemaphore.wait(10*60*1000); // cellular network searching may take several minutes
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()
{
return 0;
_is_connected = false;
return cellularConnection.disconnect();
}
bool EasyCellularConnection::is_connected()
{
return 0;
return _is_connected;
}
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()

View File

@ -17,6 +17,7 @@
#define EASY_CELLULAR_CONNECTION_H
#include "netsocket/CellularBase.h"
#include "CellularConnectionUtil.h"
/** ExampleCellularBase class
*
@ -30,6 +31,11 @@ public:
public:
/**
* MUST CALL, create power and start dispatcher
*/
nsapi_error_t init();
/** Set the Cellular network credentials
*
* Please check documentation of connect() for default behaviour of APN settings.
@ -112,6 +118,17 @@ protected:
* @return The underlying NetworkStack object
*/
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