arduino-libraries / MKRGSM

GNU Lesser General Public License v2.1
54 stars 51 forks source link

GSMClient::write AT+ USOWR delay? #154

Open Hugocourr opened 2 years ago

Hugocourr commented 2 years ago

I was looking at the write function of GSMCLIENT and noticed something :

void GSMClient::beginWrite(bool sync)
{
  _writeSync = sync;
}

size_t GSMClient::write(uint8_t c)
{
  return write(&c, 1);
}

size_t GSMClient::write(const uint8_t *buf)
{
  return write(buf, strlen((const char*)buf));
}

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;

  command.reserve(19 + (size > 256 ? 256 : size) * 2);

  while (size) {
    size_t chunkSize = size;

    if (chunkSize > 256) {
      chunkSize = 256;
    }

    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);  //HERE
    if (_writeSync) {
      if (MODEM.waitForResponse(10000) != 1) {
        break;
      }
    }

    written += chunkSize;
    size -= chunkSize;
  }

  return written;
}

We lack a delay here i think. Because MODEM.waitforesponse won't block the code for 50 ms but just until the modem respond with "OK" (wich just means that the modem stored the data and placed it in a buffer in order to send it) for example, i had a really lenghty JSON that was sended via a http post request and between each write of a byte of data to the MODEM was about 30 ms of "delay", in the end the modem couldn't keep up and responded just with "ERROR". That leads to a state where the modem stops responding. That could be one of the reason why so much people have issues with MKRGSM that stop responding after a random period of time ie: https://github.com/arduino-libraries/MKRGSM/issues/66 https://github.com/arduino-libraries/MKRGSM/issues/30. in the SARA_U201 module page 595 we can read: After the @ prompt reception, wait for a minimum of 50 ms before sending data. image

I think we are in the case of the "Binary section" so we should wait 50ms before sending the data (to be more precise we should send the begining of the command, wait a bit more than 50ms then send the data). So i changed the code a bit:

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;

  command.reserve(19 + (size > 256 ? 256 : size) * 2);

  while (size) {
    size_t chunkSize = size;

    if (chunkSize > 256) {
      chunkSize = 256;
    }

    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);
    for (unsigned long start = millis(); (millis() - start) < 60;) {} //NEW LINE
    if (_writeSync) {
      if (MODEM.waitForResponse(50000) != 1) {
        break;
      }
    }

    written += chunkSize;
    size -= chunkSize;
  }
  return written;
}

Although i wait after sending the data, it works better for me. What do you guys think?

jmer-SM commented 2 years ago

Hi, I reckon GSMClient::write is not using Binary transfer

BR's Jordi