Problem sending long packets with Arduino MKRGSM1400

Hello everybody

I'm working on an IoT project, specifically in the agriculture sector. In my project, I use arduino MKR 1400 GSM to read some parameters in plants like temperature, humidity and electrical conductance; and then send it to the ThingSpeak IoT plattform. Due to my the requeriments of my project, I need to read a parameter every second during 3 minutes (180 values = 1 * 60 sec * 3 minutes ), so I need to send a bulk update of mi private channel using API REST.

But for some strange reason, I only can send bulk updates when the packet size is about 256 bytes or less, but not longer. Every time I send my packet with size longer than 256 bytes, I receive an error. I don't know if this error is caused by the library (MKRGSM) or is a limitation on the GSM chip. This supposes a very serious inconvenience for me, because I need to send about 180 measurements (2,2Kbytes); and the between consecutive bulk updates must be 15 seconds or more.

Can someone tell me what could be the reason of this limitation?

This is my arduino code. (For requests with packet size of 256 bytes works fine, but with longer size not). I attach my logs.

Thank you very much.

// include the GSM library
#include <MKRGSM.h>

// PIN number if necessary
#define PINNUMBER ""

// APN information obrained from your network provider
#define GPRS_APN "?????????" // replace with your GPRS APN
#define GPRS_LOGIN "" // replace with your GPRS login
#define GPRS_PASSWORD "" // replace with your GPRS password

// initialize the library instances
GSMClient client;
GPRS gprs;
GSM gsmAccess(true);



// ThingSpeak Settings
char thingSpeakAddress[] = "api.thingspeak.com";
String writeAPIKey = "MY_API_KEY_WR"; //replace with your API Key
const int updateThingSpeakInterval = 15 * 1000; // Time interval in milliseconds to update ThingSpeak (number of seconds * 1000 = interval)

// Variable Setup
long lastConnectionTime = 0;
boolean lastConnected = false;
int failedCounter = 0;

char superstring[] = "{\"write_api_key\":\"MY_API_KEY_WR\",\"updates\":[{\"delta_t\":0,\"field8\":-1000000},{\"delta_t\":1,\"field8\":-1000000},{\"delta_t\":1,\"field8\":-1000000},{\"delta_t\":1,\"field8\":-1000000},{\"delta_t\":1,\"field8\":-1000000},{\"delta_t\":1,\"field8\":-1000000},{\"delta_t\":1,\"field8\":-9999999},{\"delta_t\":1,\"field8\":-1000000},{\"delta_t\":1,\"field8\":-9999999}]}";



void setup() {
  Serial.setTimeout(5);
  Serial.begin(57600); // opens serial port, sets data rate to 9600 bps
  StartGSM();
}



void loop() {
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // Disconnect from ThingSpeak
  if (!client.connected() && lastConnected) {
    Serial.println("...disconnected");
    Serial.println();

    client.stop();
  }

  // Update ThingSpeak
  if (!client.connected() && (millis() - lastConnectionTime > updateThingSpeakInterval)) {
    String ToThingSpeak = superstring;
    Serial.println(ToThingSpeak);
    updateThingSpeak(ToThingSpeak);
  }

  if (failedCounter > 3 ) {
    StartGSM();
  }

  lastConnected = client.connected();
}

void updateThingSpeak(String tsData)
{
  if (client.connect(thingSpeakAddress, 80))
  {
    Serial.println("[-] Enviando datos !!!! ");
    client.println("POST /channels/MY_CHANNEL/bulk_update.json HTTP/1.1");
    client.println("Host: api.thingspeak.com");
    client.println("User-Agent: mw.doc.bulk-update (Arduino ESP8266)");
    client.println("Connection: close");
    client.println("Content-Type: application/json");
    client.print("Content-Length: ");
    client.print(tsData.length());
    client.print("

                 ");

    client.print(tsData);

    lastConnectionTime = millis();

    if (client.connected()) {
      Serial.println("Connecting to ThingSpeak...");
      Serial.println();

      failedCounter = 0;
    } else {
      failedCounter++;

      Serial.println("Connection to ThingSpeak failed (" + String(failedCounter, DEC) + ")");
      Serial.println();
    }

  } else {
    failedCounter++;

    Serial.println("Connection to ThingSpeak Failed (" + String(failedCounter, DEC) + ")");
    Serial.println();

    lastConnectionTime = millis();
  }
}

void StartGSM() {
  char server[] = "api.thingspeak.com"; // the base URL
  int port = 80; // the port, 80 for HTTP

  Serial.println("Starting Arduino web client.");
  // connection state
  boolean notConnected = true;

  // Start GSM shield
  // pass the PIN of your SIM as a parameter of gsmAccess.begin()
  while (notConnected) {
    if ((gsmAccess.begin(PINNUMBER) == GSM_READY) &
        (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) {
      notConnected = false;
    } else {
      Serial.println("Not connected");
      delay(1000);
    }
  }

  Serial.println("connecting...");

  // if you get a connection, report back via serial:
  if (client.connect(server, port)) {
    Serial.println("connected");
  } else {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
  }

}

rsLogArduino.txt (8.02 KB)

Hello.

Looking at the MKRGSM library I have noticed in the GSMClient.cpp file, in the write method, that the max size packet is 256. I suposse it must be some reason of that, so I'm not sure if is not possible increase it.

Any comment would be of great help for me.

Thanks

This is the method:

size_t GSMClient::write(const uint8_t* buf, size_t size)
{
  if (_writeSync) {
    while (ready() == 0);
  } else if (ready() == 0) {
    return 0;
  }

  if (_socket == -1) {
    return 0;
  }

  size_t written = 0;
  String command;


  while (size) {
    size_t chunkSize = size;

    if (chunkSize > 256) { # <----------------------------------------------------------- !!!!
      chunkSize = 256;
    }

    command.reserve(19 + chunkSize * 2);

    command += "AT+USOWR=";
    command += _socket;
    command += ",";
    command += chunkSize;
    command += ",\"";

    for (size_t i = 0; i < chunkSize; i++) {
      byte b = buf[i + written];

      byte n1 = (b >> 4) & 0x0f;
      byte n2 = (b & 0x0f);

      command += (char)(n1 > 9 ? 'A' + n1 - 10 : '0' + n1);
      command += (char)(n2 > 9 ? 'A' + n2 - 10 : '0' + n2);
    }

    command += "\"";

    MODEM.send(command);
    if (_writeSync) {
      if (MODEM.waitForResponse(10000) != 1) {
        break;
      }
    }

    written += chunkSize;
    size -= chunkSize;
  }

  return written;
}

Hi @dmonrabal,

Could you please open an issue on Github to track this: Issues · arduino-libraries/MKRGSM · GitHub

It would be very helpful is you also provided debug output from the serial monitor when you create the issue.

you can send bulk data by making dividing your data into 256 characters and using for loop to send each chunk with client.print command

for example

data=12345678....500

newdata1=12345..250
newdata2=251...500

client.print(newdata1)
client.print(newdata2)

i hope this resolve your bulk data problem