Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GSM: allow retry if connection fails #975

Draft
wants to merge 20 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,17 @@ class CellularDevice {
*/
virtual nsapi_error_t soft_power_off() = 0;

/** Resets the modem via AT command
*
* @remark CellularStateMachine disconnect or destruct does not reset the modem,
* but you need to do that yourself.
*
* @pre You must call shutdown to prepare the modem for reset.
*
* @return NSAPI_ERROR_OK on success
*/
virtual nsapi_error_t soft_reset() = 0;

/** Open the SIM card by setting the pin code for SIM.
*
* @param sim_pin PIN for the SIM card
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ class AT_CellularDevice : public CellularDevice {

virtual nsapi_error_t soft_power_off();

virtual nsapi_error_t soft_reset();

virtual nsapi_error_t set_pin(const char *sim_pin);

virtual nsapi_error_t get_sim_state(SimState &state);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ class GEMALTO_CINTERION : public AT_CellularDevice {

protected:
virtual nsapi_error_t init();
virtual nsapi_error_t shutdown();
virtual nsapi_error_t soft_power_off();
virtual nsapi_error_t soft_reset();

private:
static Module _module;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class GEMALTO_CINTERION_CellularStack : public AT_CellularStack {
void stopGNSS();
void PSMEnable();
void PSMDisable();
int ping(const char *host, int ttl);

protected:

Expand Down
113 changes: 85 additions & 28 deletions libraries/GSM/src/GSM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,28 @@ mbed::CellularDevice *mbed::CellularDevice::get_default_instance()

int arduino::GSMClass::begin(const char* pin, const char* apn, const char* username, const char* password, RadioAccessTechnologyType rat, uint32_t band, bool restart) {

if (restart || isCmuxEnable()) {
reset();
/* Assume module is powered ON. Uncomment this line is you are using
* Edge Control without Arduino_ConnectionHandler
* #if defined (ARDUINO_EDGE_CONTROL)
* pinMode(ON_MKR2, OUTPUT);
* digitalWrite(ON_MKR2, HIGH);
* #endif
*/

/* Ensure module is not under reset */
pinMode(MBED_CONF_GEMALTO_CINTERION_RST, OUTPUT);
digitalWrite(MBED_CONF_GEMALTO_CINTERION_RST, LOW);

/* Reset module if needed */
const bool emergencyReset = restart || isCmuxEnable();
DEBUG_INFO("Emergency reset %s", emergencyReset ? "enabled" : "disabled");
if (emergencyReset) {
hardwareReset();
}

/* Create rising edge on pin ON */
on();

if (!_context) {
_context = mbed::CellularContext::get_default_instance();
}
Expand All @@ -59,20 +77,18 @@ int arduino::GSMClass::begin(const char* pin, const char* apn, const char* usern
return 0;
}

pinMode(MBED_CONF_GEMALTO_CINTERION_ON, INPUT_PULLDOWN);

#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4)
/* This is needed to wakeup module if hw flow control is enabled */
static mbed::DigitalOut rts(MBED_CONF_GEMALTO_CINTERION_RTS, 0);
#endif

_device = _context->get_device();
_device->modem_debug_on(_at_debug);

if (!isReady()) {
DEBUG_ERROR("Cellular device not ready");
return 0;
}

DEBUG_INFO("CMUX %s", _cmuxGSMenable ? "enabled" : "disabled");
_device->set_cmux_status_flag(_cmuxGSMenable);
_device->set_retry_timeout_array(_retry_timeout, sizeof(_retry_timeout) / sizeof(_retry_timeout[0]));
_device->set_timeout(_timeout);
_device->attach(mbed::callback(this, &GSMClass::onStatusChange));
_device->init();

Expand Down Expand Up @@ -106,6 +122,10 @@ int arduino::GSMClass::begin(const char* pin, const char* apn, const char* usern
return connect_status == NSAPI_ERROR_OK ? 1 : 0;
}

void arduino::GSMClass::setTimeout(unsigned long timeout) {
_timeout = timeout;
}

void arduino::GSMClass::enableCmux() {
_cmuxGSMenable = true;
}
Expand All @@ -115,13 +135,62 @@ bool arduino::GSMClass::isCmuxEnable() {
}

void arduino::GSMClass::end() {
if(_device) {
_device->shutdown();
}
}

void arduino::GSMClass::reset() {
if(_device) {
_device->soft_reset();
}
}

void arduino::GSMClass::off() {
if(_device) {
_device->soft_power_off();
}
}

int arduino::GSMClass::ping(const char* hostname, int ttl) {

mbed::GEMALTO_CINTERION_CellularStack* stack = (mbed::GEMALTO_CINTERION_CellularStack*)_context->get_stack();
if (!stack) {
return -1;
}
return stack->ping(hostname, ttl);
}

int arduino::GSMClass::ping(const String &hostname, int ttl)
{
return ping(hostname.c_str(), ttl);
}

int arduino::GSMClass::ping(IPAddress ip, int ttl)
{
String host;
host.reserve(15);

host += ip[0];
host += '.';
host += ip[1];
host += '.';
host += ip[2];
host += '.';
host += ip[3];

return ping(host, ttl);
}

int arduino::GSMClass::disconnect() {
if (_context) {
if (!_context) {
return 0;
}

if (_context->is_connected()) {
return _context->disconnect();
}

return 0;
}

Expand Down Expand Up @@ -158,34 +227,22 @@ NetworkInterface* arduino::GSMClass::getNetwork() {
return _context;
}

void arduino::GSMClass::reset() {
void arduino::GSMClass::hardwareReset() {
/* Reset logic is inverted */
pinMode(MBED_CONF_GEMALTO_CINTERION_RST, OUTPUT);
digitalWrite(MBED_CONF_GEMALTO_CINTERION_RST, HIGH);
delay(800);
digitalWrite(MBED_CONF_GEMALTO_CINTERION_RST, LOW);
}

void arduino::GSMClass::on() {
/* Module needs a rising edge to power on */
pinMode(MBED_CONF_GEMALTO_CINTERION_ON, OUTPUT);
digitalWrite(MBED_CONF_GEMALTO_CINTERION_ON, LOW);
delay(1);
digitalWrite(MBED_CONF_GEMALTO_CINTERION_ON, HIGH);
delay(1);
}

bool arduino::GSMClass::isReady(const int timeout) {
if (!_device) {
DEBUG_ERROR("No device found");
return false;
}

const unsigned int start = millis();
while (_device->is_ready() != NSAPI_ERROR_OK) {

if (millis() - start > timeout) {
DEBUG_WARNING("Timeout waiting device ready");
return false;
}
delay(100);
}
return true;
}

arduino::GSMClass GSM;
66 changes: 42 additions & 24 deletions libraries/GSM/src/GSM.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,30 +75,47 @@ class GSMClass : public MbedSocketClass {
}
}

/* Start GSM connection.
* Configure the credentials into the device.
*
* param pin: Pointer to the pin string.
* param apn: Pointer to the apn string.
* param username: Pointer to the username string.
* param password: Pointer to the password string.
* param rat: Radio Access Technology.
*
* return: 0 in case of success, negative number in case of failure
*/
int begin(const char* pin, const char* apn, const char* username, const char* password, RadioAccessTechnologyType rat = CATNB, uint32_t band = BAND_20, bool restart = true);
/*
* Start GSM connection. Configure the credentials into the device.
*
* param pin: Pointer to the pin string.
* param apn: Pointer to the apn string.
* param username: Pointer to the username string.
* param password: Pointer to the password string.
* param rat: Radio Access Technology.
*
* return: 0 in case of success, negative number in case of failure
*/
int begin(const char* pin, const char* apn, const char* username, const char* password, RadioAccessTechnologyType rat = CATNB, uint32_t band = BAND_20, bool restart = false);

/*
* Disconnect from the network
*
* return: one value of wl_status_t enum
*/
* Disconnect from the network
*
* return: one value of wl_status_t enum
*/
int disconnect(void);

/*
* Reset internal state machine in order to be ready to reconnect again.
*/
void end(void);

unsigned long getTime();
/*
* Send AT+CFUN=1,1 command to trigger a software reset. To be called only after end();
*/
void reset();

/*
* Send AT^SMSO="fast command to power off the modem. To be called only after end();
*/
void off();

/*
* Change cellular state timeouts. Needs to be called before GSM.begin()
*/
void setTimeout(unsigned long timeout);

unsigned long getTime();
unsigned long getLocalTime();

bool setTime(unsigned long const epoch, int const timezone = 0);
Expand All @@ -108,9 +125,9 @@ class GSMClass : public MbedSocketClass {
void trace(Stream& stream);
void setTraceLevel(int trace_level, bool timestamp = false, bool at_trace = false);
#endif
int ping(const char* hostname, uint8_t ttl = 128);
int ping(const String& hostname, uint8_t ttl = 128);
int ping(IPAddress host, uint8_t ttl = 128);
int ping(const char* hostname, int ttl = 5000);
int ping(const String& hostname, int ttl = 5000);
int ping(IPAddress host, int ttl = 5000);
bool isConnected();

friend class GSMClient;
Expand All @@ -130,11 +147,12 @@ class GSMClass : public MbedSocketClass {
mbed::CellularContext* _context = nullptr;
mbed::CellularDevice* _device = nullptr;
bool _at_debug = false;
unsigned long _timeout = 1000;

/* Internal cellular state machine retries. Values are in seconds.
* This array also defines the maximum number of retries to 6
* This array also defines the maximum number of retries to CELLULAR_RETRY_ARRAY_SIZE
*/
const uint16_t _retry_timeout[6] = {1, 2, 4, 8, 16, 32};
const uint16_t _retry_timeout[CELLULAR_RETRY_ARRAY_SIZE] = {1, 2, 4, 8, 8, 8, 8, 8, 8, 8};

static constexpr int RSSI_UNKNOWN = 99;
static const char * const sim_state_str[];
Expand All @@ -149,8 +167,8 @@ class GSMClass : public MbedSocketClass {
static const char * getRegistrationStateString(const mbed::CellularNetwork::RegistrationStatus state);
void onStatusChange(nsapi_event_t ev, intptr_t in);

void reset();
bool isReady(const int timeout = 5000);
void hardwareReset();
void on();
};

}
Expand Down
20 changes: 20 additions & 0 deletions libraries/GSM/src/GSMClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,29 @@
namespace arduino {

class GSMClient : public AClient {
private:
NetworkInterface *getNetwork() {
return GSM.getNetwork();
}

public:
size_t write(uint8_t b) {
int ret = 0;
do {
ret = client->write(b);
delay(0);
} while (ret == 0 && status());
return ret;
}

size_t write(const uint8_t *buf, size_t size) {
int ret = 0;
do {
ret = client->write(buf, size);
delay(0);
} while (ret == 0 && status());
return ret;
}
};

}
Expand Down
19 changes: 19 additions & 0 deletions libraries/GSM/src/GSMSSLClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,25 @@ class GSMSSLClient : public arduino::ASslClient {
NetworkInterface *getNetwork() {
return GSM.getNetwork();
}

public:
size_t write(uint8_t b) {
int ret = 0;
do {
ret = client->write(b);
delay(0);
} while (ret == 0 && status());
return ret;
}

size_t write(const uint8_t *buf, size_t size) {
int ret = 0;
do {
ret = client->write(buf, size);
delay(0);
} while (ret == 0 && status());
return ret;
}
};

}
Expand Down
Loading