Hello All
I have a MKR GSM + CAN shield setup which reads out CAN data and sends a data string through the MKR GSM board over mobile network via TCP.
During initial bench prototyping, using SocketTest on a PC acting as the “TCP listener”, all seemed to work well under server error conditions. i.e.: when connection to the TCP listener was lost either due to:
- Loss of GSM signal
- TCP listener client was properly closed
- TCP listener was abruptly disconnected without closing properly
In above cases, the sketch would continue to run, with “client.write” commands executing but not waiting for acknowledgement.
When I moved the TCP listener service to a Windows run service on a rented server however, in case the service is stopped and the sketch is still running, all “client.xxx” commands seem to freeze the sketch. After a while the board has a few reboot attempts, which makes the CAN shield send error frames on the bus.
I want to write some error handling around this to account for the back end server/service becoming unavailable out of my control. However I don’t seem to have the handles available, as all client.xxx commands have the same behaviour, i.e. resetting (watchdog?) the MKR GSM board when the TCP listener service is stopped after initial successful connection:
client.connected
client.available
client.read
client.write
Any thoughts/leads/suggestions? I can’t share the full code, but below are the parts related to interacting with the GSM network and TCP listener service:
Parts of the connection code:
//Define GSM Parameters
#define PINNUMBER ""
#define GPRS_APN "****" // GPRS APN
#define GPRS_LOGIN "****" // GPRS login
#define GPRS_PASSWORD "****" // GPRS password
GSMClient client;
GPRS gprs;
//GSM gsmAccess(false); // Comment FOR TESTING ONLY
GSM gsmAccess(true); // FOR DEBUGGING ONLY
GSMModem modem;
const char server[] = "****"; // sever address
const int port = ****; // server port
volatile boolean GSMNotConnected = true; // GSM Connection Status
volatile boolean ServerNotConnected = true; // Server Connection Status
String IMEI = ""; // IMEI ID
byte IMEIctr = 0; // IMEI counter to init modem
volatile boolean ModemReady = false; // Status boolean for modem readiness
Modem check during setup:
// get modem IMEI
modem.begin();
IMEI = modem.getIMEI().substring(11);
while ((IMEI == NULL) && (IMEIctr <= 5)) {
IMEIctr++;
modem.begin();
IMEI = modem.getIMEI().substring(11);
}
if (IMEI != NULL) {
ModemReady = true;
}
else {
ModemReady = false;
}
// Start GSM and Server connection
if (ModemReady) {
GSMConnect();
}
Call to DataSend function from within main loop:
// Transmit data to server
if (!GSMNotConnected && !ServerNotConnected) {
DataSend();
}
DataSend function:
void DataSend() {
ServerData = ****
client.print(ServerData);
GSM connection function, called if modem is alive during startup:
void GSMConnect() {
Serial.println("GSMConnect started.");
ConnectingTimeStart = millis();
//Init GSM connection
while (GSMNotConnected && (ConnectingTime <= ConnectingTimeDuration)) { // connection time out included to retain in-car LED warning funcitonality in case connection fails
Serial.println("Inititalising GSM connection"); // TESTING ONLY
// Check GSM ready
if (gsmAccess.begin(PINNUMBER) == GSM_READY) {
delay(2000);
// Initialise GPRS
if (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY) {
GSMNotConnected = false;
Serial.println("Connected to GSM network"); // TESTING ONLY
}
}
else {
Serial.println("GSM Not Connected");
}
ConnectingTime = millis() - ConnectingTimeStart;
Serial.print("Connection Attempt Time: "); // TESTING ONLY
Serial.println(ConnectingTime); // TESTING ONLY
}
// start client connection
if (!GSMNotConnected) {
client.stop();
delay(500);
if (client.connect(server, port)) {
ServerNotConnected = false;
Serial.println("Connected to Server"); // TESTING ONLY
}
else {
ServerNotConnected = true;
Serial.println("SERVER CONNECTION FAILED"); // TESTING ONLY
}
}
}