Introduction

Most IoT products work with a sim card and GSM module. So if you want to use the OTA function for future upgrades on your devices, you have to use an OTA server that supports small packet requests due to the gsm limitations making the device download a large file in several small parts. Note that this feature is only available for purchased members. For now, the free users can use this method for test purposes only, and this feature will be unavailable soon.

Using TinyGSM library for OTA

The TinyGSM library is a powerful C++/Arduino library for using many different GSM modems like SIMCOM, Quectel, u-blox, AI-Thinker, etc. According to its documents, the TinyGSM library supports the following list of GSM Modems.

  • SIMCom SIM800 series (SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868)
  • SIMCom SIM900 series (SIM900A, SIM900D, SIM908, SIM968)
  • SIMCom WCDMA/HSPA/HSPA+ Modules (SIM5360, SIM5320, SIM5300E, SIM5300E/A)
  • SIMCom LTE Modules (SIM7100E, SIM7500E, SIM7500A, SIM7600C, SIM7600E)
  • SIMCom SIM7000E/A/G CAT-M1/NB-IoT Module
  • SIMCom SIM7070/SIM7080/SIM7090 CAT-M1/NB-IoT Module
  • AI-Thinker A6, A6C, A7, A20
  • ESP8266/ESP32 (AT commands interface, similar to GSM modems)
  • Digi XBee WiFi and Cellular (using XBee command mode)
  • Neoway M590
  • u-blox 2G, 3G, 4G, and LTE Cat1 Cellular Modems (many modules including LEON-G100, LISA-U2xx, SARA-G3xx, SARA-U2xx, TOBY-L2xx, LARA-R2xx, MPCI-L2xx)
  • u-blox LTE-M/NB-IoT Modems (SARA-R4xx, SARA-N4xx, but NOT SARA-N2xx)
  • Sequans Monarch LTE Cat M1/NB1 (VZM20Q)
  • Quectel BG96
  • Quectel M95
  • Quectel MC60 (alpha)

Most GSM modems let you create several TCP socket clients together. For example, you can have a connection to your MQTT server and a connection to the OTAdrive server. Just like this:

TinyGsm modem(Serial);
// MuxChannel 0 for MQTT
TinyGsmClient gsm_mqtt_client(modem, 0);
// MuxChannel 1 for OTA
TinyGsmClient gsm_otadrive_client(modem, 1);

You should pass the gsm client to any function of the OTAdrive library to use a GSM connection instead of a Wi-Fi connection.

TinyGsm modem(Serial);
// MuxChannel 0 for MQTT
TinyGsmClient gsm_mqtt_client(modem, 0);
// MuxChannel 1 for OTA
TinyGsmClient gsm_otadrive_client(modem, 1);

...

OTADRIVE.updateFirmwareInfo(gsm_otadrive_client);
OTADRIVE.getConfigs(gsm_otadrive_client);
OTADRIVE.sendAlive(gsm_otadrive_client);
OTADRIVE.updateFirmware(gsm_otadrive_client);

The following code is a final example; you can find the project files here.

#include <otadrive_esp.h>
#include <Arduino.h>
// install TinyGSM library (v0.11.7 or newer)
#define TINY_GSM_MODEM_SIM800
#include <TinyGsmClient.h>

#define APIKEY "5ec34eab-c516-496d-8cb0-78dc4744af3b" // OTAdrive APIkey for this product
#define FW_VER "v@8.21.3"                             // this app version

TinyGsm modem(Serial);
// MuxChannel 0 for MQTT
TinyGsmClient gsm_mqtt_client(modem, 0);
// MuxChannel 1 for OTA
TinyGsmClient gsm_otadrive_client(modem, 1);

String gprs_ip;

void printInfo()
{
  Serial.printf("Example08: OTA through GSM. %s, Serial:%s, IP:%s\r\n\r\n", FW_VER, OTADRIVE.getChipId().c_str(), gprs_ip.c_str());
}

void update_prgs(size_t i, size_t total)
{
  Serial.printf("upgrade %d/%d   %d%%\r\n\r\n", i, total, ((i * 100) / total));
}

void setup()
{
  // Important Notice: Please enable log outputs. Tools->Core Debug Level->Info
  Serial.begin(115200);
  printInfo();

  // Setup WiFi
  // We dont need Wi-Fi here

  SPIFFS.begin(true);
  OTADRIVE.setInfo(APIKEY, FW_VER);
  OTADRIVE.onUpdateFirmwareProgress(update_prgs);

  // do something about power-on GSM
}

void loop()
{
  for (uint8_t tr = 0; tr < 5; tr++)
  {
    printInfo();
    delay(3000);
    if (!modem.testAT(100))
    {
      Serial.println("Testing modem RX/TX test faild\r\n");
      continue;
    }

    if (modem.getSimStatus(100) != SimStatus::SIM_READY)
    {
      Serial.println("Testing modem SIMCARD faild\r\n");
      continue;
    }
    if (!modem.isGprsConnected())
    {
      Serial.println("Testing modem internet faild. Try to connect ...\r\n");
      modem.gprsConnect("simbase", "", "");
      continue;
    }

    gprs_ip = modem.getLocalIP();
    Serial.println("Modem is ready\r\n");
  }

  if (OTADRIVE.timeTick(30))
  {
    Serial.println("Lets updaete the firmware\r\n");
    if (modem.isGprsConnected() || modem.isGprsConnected())
    {
      // auto a = OTADRIVE.updateFirmwareInfo(gsm_otadrive_client);
      // Serial.printf("info: %d, %d, %s\n", a.available, a.size, a.version.c_str());
      // auto c = OTADRIVE.getConfigs(gsm_otadrive_client);
      // Serial.printf("config %s\n", c.c_str());
      // OTADRIVE.sendAlive(gsm_otadrive_client);
      Serial.println("isGprsConnected\r\n");
      OTADRIVE.updateFirmware(gsm_otadrive_client);
    }
    else
    {
      Serial.println("Modem is not ready\r\n");
    }
  }
  else
  {
    Serial.println("Waiting\r\n");
  }
}