LilyGo-T-Call-SIM800 icon indicating copy to clipboard operation
LilyGo-T-Call-SIM800 copied to clipboard

ESP32 LilyGo GSM module OTA possibilities

Open krupis opened this issue 3 years ago • 69 comments

Hello. I am using this module to learn how to use GSM modules. I have been experimenting with the example codes and I have learnt the basic working principles. The big project that I am going to be working on next will involve the GSM and the GPS module.

I am very interested in how to perform a OTA over the GSM since the there will be very limited WIFI availability where my device will be used. At some point, I may want to update the firmware, fix bugs, so I the probably the easiest way to be to use the GSM and do the OTA over the GSM.

I have noticed the update_firmware under the example codes but there is nothing there. Perhaps anyone has made any progress and could share their knowledge and ideas with me? I appreciate any help! Thanks in advance

krupis avatar Apr 08 '21 06:04 krupis

see tinygsm examples on how to open a tcp connection and use it, and see esp32 https ota examples https://github.com/espressif/arduino-esp32/tree/master/libraries/Update/examples/HTTPS_OTA_Update

thomsenle avatar May 01 '21 01:05 thomsenle

see also here https://github.com/vshymanskyy/TinyGSM/issues/152

thomsenle avatar May 01 '21 01:05 thomsenle

Hi, I have the same problem. How did you solve?

gunter72 avatar May 09 '21 16:05 gunter72

I did a skectch and work fine, is any are interested I can share ti, but I dont know how to make the server to store the bin file. I did the sketch using the TTGO CALL SIM800L github GSM tiny OTA example. If someone has and server example I will apreciate it, my idea is to store the bin file on my web server.

emigbur avatar May 15 '21 15:05 emigbur

Hello. Here is the code to perform OTA over the GSM:


#include <Update.h>
#define TINY_GSM_MODEM_SIM800
// Increase RX buffer
#define TINY_GSM_RX_BUFFER 1030

const char apn[] = "omnitel";
const char user[] = "omni";
const char pass[] = "omni";



#define MODEM_RST             5
#define MODEM_PWRKEY          4
#define MODEM_POWER_ON       23
#define MODEM_TX             27
#define MODEM_RX             26
#define LED_GPIO             13
#define LED_ON               HIGH
#define LED_OFF              LOW


#define SerialAT  Serial1

#include <TinyGsmClient.h>
#include <CRC32.h>

#include "FS.h"
#include "SPIFFS.h"

#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, Serial);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif


TinyGsmClient client(modem);

const char server[] = "myesptestserver.ddns.net";
const int port = 80;
const char resource[] = "/esp.bin"; //here de bin file

uint32_t knownCRC32 = 0x6f50d767;
uint32_t knownFileSize = 1024; // In case server does not send it

void setup()
{
    SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
    // Set console baud rate
    Serial.begin(115200);

    setupModem();
    delay(10);

    if (!SPIFFS.begin(true))
    {
        Serial.println("SPIFFS Mount Failed");
        return;
    }
    SPIFFS.format();
    listDir(SPIFFS, "/", 0);

    // Set GSM module baud rate
    
    delay(3000);

    // Restart takes quite some time
    // To skip it, call init() instead of restart()
    Serial.println("Initializing modem...");
    modem.restart();

    String modemInfo = modem.getModemInfo();
    Serial.print("Modem: ");
    Serial.println(modemInfo);

    // Unlock your SIM card with a PIN
    //modem.simUnlock("1234");
}



void loop()
{
    Serial.print("Waiting for network...");
    if (!modem.waitForNetwork())
    {
        Serial.println(" fail");
        delay(10000);
        return;
    }
    Serial.println(" OK");

    Serial.print("Connecting to ");
    Serial.print(apn);
    if (!modem.gprsConnect(apn, user, pass))
    {
        Serial.println(" fail");
        delay(10000);
        return;
    }
    Serial.println(" OK");

    Serial.print("Connecting to ");
    Serial.print(server);

    // if you get a connection, report back via serial:
    if (!client.connect(server, port))
    {
        Serial.println(" fail");
        delay(10000);
        return;
    }
    Serial.println(" OK");
    
    // Make a HTTP request:
    client.print(String("GET ") + resource + " HTTP/1.0\r\n");
    client.print(String("Host: ") + server + "\r\n");
    client.print("Connection: close\r\n\r\n");

    long timeout = millis();
    while (client.available() == 0)
    {
        if (millis() - timeout > 5000L)
        {
            Serial.println(">>> Client Timeout !");
            client.stop();
            delay(10000L);
            return;
        }
    }

    Serial.println("Reading header");
    uint32_t contentLength = knownFileSize;

    File file = SPIFFS.open("/update.bin", FILE_APPEND);


    while (client.available())
    {
        String line = client.readStringUntil('\n');
        line.trim();
        //Serial.println(line);    // Uncomment this to show response header
        line.toLowerCase();
        if (line.startsWith("content-length:"))
        {
            contentLength = line.substring(line.lastIndexOf(':') + 1).toInt();
        }
        else if (line.length() == 0)
        {
            break;
        }
    }


    timeout = millis();
    uint32_t readLength = 0;
    CRC32 crc;

    unsigned long timeElapsed = millis();
    printPercent(readLength, contentLength);
    

    while (readLength < contentLength && client.connected() && millis() - timeout < 10000L)
    {
        int i = 0;
        while (client.available())
        {
                // read file data to spiffs
            if (!file.print(char(client.read())))
            {
                Serial.println("Appending file");
            }
            //Serial.print((char)c);       // Uncomment this to show data
            //crc.update(c);
            readLength++;

            if (readLength % (contentLength / 13) == 0)
            {
                printPercent(readLength, contentLength);
            }
            timeout = millis();
        }
    }

    file.close();

    printPercent(readLength, contentLength);
    timeElapsed = millis() - timeElapsed;
    Serial.println();

    client.stop();
    Serial.println("stop client");

    modem.gprsDisconnect();
    Serial.println("gprs disconnect");
    Serial.println();

    float duration = float(timeElapsed) / 1000;
  /*
    Serial.print("Tamaño de Archivo: ");
    Serial.println(contentLength);
    Serial.print("Leido:  ");
    Serial.println(readLength);
    Serial.print("Calculado. CRC32:    0x");
    Serial.println(crc.finalize(), HEX);
    Serial.print("Conocido CRC32:    0x");
    Serial.println(knownCRC32, HEX);
    Serial.print("Bajado en:       ");
    Serial.print(duration);
    Serial.println("s");

    Serial.println("Se genera una espera de 3 segundos");
    for (int i = 0; i < 3; i++)
    {
        Serial.print(String(i) + "...");
        delay(1000);
    }
  */
    //readFile(SPIFFS, "/update.bin");

    updateFromFS();

    // Do nothing forevermore
    while (true)
    {
        delay(1000);
    }
}







void appendFile(fs::FS &fs, const char *path, const char *message)
{
    Serial.printf("Appending to file: %s\n", path);

    File file = fs.open(path, FILE_APPEND);
    if (!file)
    {
        Serial.println("Failed to open file for appending");
        return;
    }
    if (file.print(message))
    {
        Serial.println("APOK");
    }
    else
    {
        Serial.println("APX");
    }
}

void readFile(fs::FS &fs, const char *path)
{
    Serial.printf("Reading file: %s\n", path);

    File file = fs.open(path);
    if (!file || file.isDirectory())
    {
        Serial.println("Failed to open file for reading");
        return;
    }

    Serial.print("Read from file: ");
    while (file.available())
    {
        Serial.write(file.read());
        delayMicroseconds(100);
    }
}

void writeFile(fs::FS &fs, const char *path, const char *message)
{
    Serial.printf("Writing file: %s\n", path);

    File file = fs.open(path, FILE_WRITE);
    if (!file)
    {
        Serial.println("Failed to open file for writing");
        return;
    }
    if (file.print(message))
    {
        Serial.println("File written");
    }
    else
    {
        Serial.println("Write failed");
    }
}

void listDir(fs::FS &fs, const char *dirname, uint8_t levels)
{
    Serial.printf("Listing directory: %s\n", dirname);

    File root = fs.open(dirname);
    if (!root)
    {
        Serial.println("Failed to open directory");
        return;
    }
    if (!root.isDirectory())
    {
        Serial.println("Not a directory");
        return;
    }

    File file = root.openNextFile();
    while (file)
    {
        if (file.isDirectory())
        {
            Serial.print("  DIR : ");
            Serial.println(file.name());
            if (levels)
            {
                listDir(fs, file.name(), levels - 1);
            }
        }
        else
        {
            Serial.print("  FILE: ");
            Serial.print(file.name());
            Serial.print("  SIZE: ");
            Serial.println(file.size());
        }
        file = root.openNextFile();
    }
}

void deleteFile(fs::FS &fs, const char *path)
{
    Serial.printf("Deleting file: %s\n", path);
    if (fs.remove(path))
    {
        Serial.println("File deleted");
    }
    else
    {
        Serial.println("Delete failed");
    }
}

void updateFromFS()
{
    File updateBin = SPIFFS.open("/update.bin");
    if (updateBin)
    {
        if (updateBin.isDirectory())
        {
            Serial.println("Directory error");
            updateBin.close();
            return;
        }

        size_t updateSize = updateBin.size();

        if (updateSize > 0)
        {
            Serial.println("Starting update");
            performUpdate(updateBin, updateSize);
        }
        else
        {
            Serial.println("Error, archivo vacío");
        }

        updateBin.close();

        // whe finished remove the binary from sd card to indicate end of the process
        //fs.remove("/update.bin");
    }
    else
    {
        Serial.println("no such binary");
    }
}

void performUpdate(Stream &updateSource, size_t updateSize)
{
    if (Update.begin(updateSize))
    {
        size_t written = Update.writeStream(updateSource);
        if (written == updateSize)
        {
            Serial.println("Writes : " + String(written) + " successfully");
        }
        else
        {
            Serial.println("Written only : " + String(written) + "/" + String(updateSize) + ". Retry?");
        }
        if (Update.end())
        {
            Serial.println("OTA finished!");
            if (Update.isFinished())
            {
                Serial.println("Restart ESP device!");
                ESP.restart();
            }
            else
            {
                Serial.println("OTA not fiished");
            }
        }
        else
        {
            Serial.println("Error occured #: " + String(Update.getError()));
        }
    }
    else
    {
        Serial.println("Cannot beggin update");
    }
}





void printPercent(uint32_t readLength, uint32_t contentLength)
{
    // If we know the total length
    if (contentLength != -1)
    {
        Serial.print("\r ");
        Serial.print((100.0 * readLength) / contentLength);
        Serial.print('%');
    }
    else
    {
        Serial.println(readLength);
    }
}



void setupModem()
{
#ifdef MODEM_RST
    // Keep reset high
    pinMode(MODEM_RST, OUTPUT);
    digitalWrite(MODEM_RST, HIGH);
#endif

    pinMode(MODEM_PWRKEY, OUTPUT);
    pinMode(MODEM_POWER_ON, OUTPUT);

    // Turn on the Modem power first
    digitalWrite(MODEM_POWER_ON, HIGH);

    // Pull down PWRKEY for more than 1 second according to manual requirements
    digitalWrite(MODEM_PWRKEY, HIGH);
    delay(100);
    digitalWrite(MODEM_PWRKEY, LOW);
    delay(1000);
    digitalWrite(MODEM_PWRKEY, HIGH);

    // Initialize the indicator as an output
    pinMode(LED_GPIO, OUTPUT);
    digitalWrite(LED_GPIO, LED_OFF);
}

Make sure to change accordingle the following lines of code:

const char apn[] = "omnitel";
const char user[] = "omni";
const char pass[] = "omni";

and

const char server[] = "myesptestserver.ddns.net";
const int port = 80;
const char resource[] = "/esp.bin"; //here de bin file

For storing the bin files, you have multiple choises.

  1. Use Raspberry pi as a server ( I have created a simple apache server where I uploaded my binary file, and then I can access that server through the following sketch.

However, for testing it maybe be easier to setup Xampp on windows machine just to see whether you can get it to work. 2. Create an apache or simmilar server on your windows machine ( probably the simplest method would be to use Xampp as it does everything for you. In the xampp folder you will have htdocs folder where you can put your binary. and you can access that binary by using my sketch or your own sketch

const char server[] = "myesptestserver.ddns.net"; // ip of server or web address
const int port = 80;
const char resource[] = "/esp.bin"; // put your binary file name

Let me know if you have any more questions

krupis avatar May 15 '21 15:05 krupis

Hello. Here is the code to perform OTA over the GSM:


#include <Update.h>
#define TINY_GSM_MODEM_SIM800
// Increase RX buffer
#define TINY_GSM_RX_BUFFER 1030

const char apn[] = "omnitel";
const char user[] = "omni";
const char pass[] = "omni";



#define MODEM_RST             5
#define MODEM_PWRKEY          4
#define MODEM_POWER_ON       23
#define MODEM_TX             27
#define MODEM_RX             26
#define LED_GPIO             13
#define LED_ON               HIGH
#define LED_OFF              LOW


#define SerialAT  Serial1

#include <TinyGsmClient.h>
#include <CRC32.h>

#include "FS.h"
#include "SPIFFS.h"

#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, Serial);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif


TinyGsmClient client(modem);

const char server[] = "myesptestserver.ddns.net";
const int port = 80;
const char resource[] = "/esp.bin"; //here de bin file

uint32_t knownCRC32 = 0x6f50d767;
uint32_t knownFileSize = 1024; // In case server does not send it

void setup()
{
    SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
    // Set console baud rate
    Serial.begin(115200);

    setupModem();
    delay(10);

    if (!SPIFFS.begin(true))
    {
        Serial.println("SPIFFS Mount Failed");
        return;
    }
    SPIFFS.format();
    listDir(SPIFFS, "/", 0);

    // Set GSM module baud rate
    
    delay(3000);

    // Restart takes quite some time
    // To skip it, call init() instead of restart()
    Serial.println("Initializing modem...");
    modem.restart();

    String modemInfo = modem.getModemInfo();
    Serial.print("Modem: ");
    Serial.println(modemInfo);

    // Unlock your SIM card with a PIN
    //modem.simUnlock("1234");
}



void loop()
{
    Serial.print("Waiting for network...");
    if (!modem.waitForNetwork())
    {
        Serial.println(" fail");
        delay(10000);
        return;
    }
    Serial.println(" OK");

    Serial.print("Connecting to ");
    Serial.print(apn);
    if (!modem.gprsConnect(apn, user, pass))
    {
        Serial.println(" fail");
        delay(10000);
        return;
    }
    Serial.println(" OK");

    Serial.print("Connecting to ");
    Serial.print(server);

    // if you get a connection, report back via serial:
    if (!client.connect(server, port))
    {
        Serial.println(" fail");
        delay(10000);
        return;
    }
    Serial.println(" OK");
    
    // Make a HTTP request:
    client.print(String("GET ") + resource + " HTTP/1.0\r\n");
    client.print(String("Host: ") + server + "\r\n");
    client.print("Connection: close\r\n\r\n");

    long timeout = millis();
    while (client.available() == 0)
    {
        if (millis() - timeout > 5000L)
        {
            Serial.println(">>> Client Timeout !");
            client.stop();
            delay(10000L);
            return;
        }
    }

    Serial.println("Reading header");
    uint32_t contentLength = knownFileSize;

    File file = SPIFFS.open("/update.bin", FILE_APPEND);


    while (client.available())
    {
        String line = client.readStringUntil('\n');
        line.trim();
        //Serial.println(line);    // Uncomment this to show response header
        line.toLowerCase();
        if (line.startsWith("content-length:"))
        {
            contentLength = line.substring(line.lastIndexOf(':') + 1).toInt();
        }
        else if (line.length() == 0)
        {
            break;
        }
    }


    timeout = millis();
    uint32_t readLength = 0;
    CRC32 crc;

    unsigned long timeElapsed = millis();
    printPercent(readLength, contentLength);
    

    while (readLength < contentLength && client.connected() && millis() - timeout < 10000L)
    {
        int i = 0;
        while (client.available())
        {
                // read file data to spiffs
            if (!file.print(char(client.read())))
            {
                Serial.println("Appending file");
            }
            //Serial.print((char)c);       // Uncomment this to show data
            //crc.update(c);
            readLength++;

            if (readLength % (contentLength / 13) == 0)
            {
                printPercent(readLength, contentLength);
            }
            timeout = millis();
        }
    }

    file.close();

    printPercent(readLength, contentLength);
    timeElapsed = millis() - timeElapsed;
    Serial.println();

    client.stop();
    Serial.println("stop client");

    modem.gprsDisconnect();
    Serial.println("gprs disconnect");
    Serial.println();

    float duration = float(timeElapsed) / 1000;
  /*
    Serial.print("Tamaño de Archivo: ");
    Serial.println(contentLength);
    Serial.print("Leido:  ");
    Serial.println(readLength);
    Serial.print("Calculado. CRC32:    0x");
    Serial.println(crc.finalize(), HEX);
    Serial.print("Conocido CRC32:    0x");
    Serial.println(knownCRC32, HEX);
    Serial.print("Bajado en:       ");
    Serial.print(duration);
    Serial.println("s");

    Serial.println("Se genera una espera de 3 segundos");
    for (int i = 0; i < 3; i++)
    {
        Serial.print(String(i) + "...");
        delay(1000);
    }
  */
    //readFile(SPIFFS, "/update.bin");

    updateFromFS();

    // Do nothing forevermore
    while (true)
    {
        delay(1000);
    }
}







void appendFile(fs::FS &fs, const char *path, const char *message)
{
    Serial.printf("Appending to file: %s\n", path);

    File file = fs.open(path, FILE_APPEND);
    if (!file)
    {
        Serial.println("Failed to open file for appending");
        return;
    }
    if (file.print(message))
    {
        Serial.println("APOK");
    }
    else
    {
        Serial.println("APX");
    }
}

void readFile(fs::FS &fs, const char *path)
{
    Serial.printf("Reading file: %s\n", path);

    File file = fs.open(path);
    if (!file || file.isDirectory())
    {
        Serial.println("Failed to open file for reading");
        return;
    }

    Serial.print("Read from file: ");
    while (file.available())
    {
        Serial.write(file.read());
        delayMicroseconds(100);
    }
}

void writeFile(fs::FS &fs, const char *path, const char *message)
{
    Serial.printf("Writing file: %s\n", path);

    File file = fs.open(path, FILE_WRITE);
    if (!file)
    {
        Serial.println("Failed to open file for writing");
        return;
    }
    if (file.print(message))
    {
        Serial.println("File written");
    }
    else
    {
        Serial.println("Write failed");
    }
}

void listDir(fs::FS &fs, const char *dirname, uint8_t levels)
{
    Serial.printf("Listing directory: %s\n", dirname);

    File root = fs.open(dirname);
    if (!root)
    {
        Serial.println("Failed to open directory");
        return;
    }
    if (!root.isDirectory())
    {
        Serial.println("Not a directory");
        return;
    }

    File file = root.openNextFile();
    while (file)
    {
        if (file.isDirectory())
        {
            Serial.print("  DIR : ");
            Serial.println(file.name());
            if (levels)
            {
                listDir(fs, file.name(), levels - 1);
            }
        }
        else
        {
            Serial.print("  FILE: ");
            Serial.print(file.name());
            Serial.print("  SIZE: ");
            Serial.println(file.size());
        }
        file = root.openNextFile();
    }
}

void deleteFile(fs::FS &fs, const char *path)
{
    Serial.printf("Deleting file: %s\n", path);
    if (fs.remove(path))
    {
        Serial.println("File deleted");
    }
    else
    {
        Serial.println("Delete failed");
    }
}

void updateFromFS()
{
    File updateBin = SPIFFS.open("/update.bin");
    if (updateBin)
    {
        if (updateBin.isDirectory())
        {
            Serial.println("Directory error");
            updateBin.close();
            return;
        }

        size_t updateSize = updateBin.size();

        if (updateSize > 0)
        {
            Serial.println("Starting update");
            performUpdate(updateBin, updateSize);
        }
        else
        {
            Serial.println("Error, archivo vacío");
        }

        updateBin.close();

        // whe finished remove the binary from sd card to indicate end of the process
        //fs.remove("/update.bin");
    }
    else
    {
        Serial.println("no such binary");
    }
}

void performUpdate(Stream &updateSource, size_t updateSize)
{
    if (Update.begin(updateSize))
    {
        size_t written = Update.writeStream(updateSource);
        if (written == updateSize)
        {
            Serial.println("Writes : " + String(written) + " successfully");
        }
        else
        {
            Serial.println("Written only : " + String(written) + "/" + String(updateSize) + ". Retry?");
        }
        if (Update.end())
        {
            Serial.println("OTA finished!");
            if (Update.isFinished())
            {
                Serial.println("Restart ESP device!");
                ESP.restart();
            }
            else
            {
                Serial.println("OTA not fiished");
            }
        }
        else
        {
            Serial.println("Error occured #: " + String(Update.getError()));
        }
    }
    else
    {
        Serial.println("Cannot beggin update");
    }
}





void printPercent(uint32_t readLength, uint32_t contentLength)
{
    // If we know the total length
    if (contentLength != -1)
    {
        Serial.print("\r ");
        Serial.print((100.0 * readLength) / contentLength);
        Serial.print('%');
    }
    else
    {
        Serial.println(readLength);
    }
}



void setupModem()
{
#ifdef MODEM_RST
    // Keep reset high
    pinMode(MODEM_RST, OUTPUT);
    digitalWrite(MODEM_RST, HIGH);
#endif

    pinMode(MODEM_PWRKEY, OUTPUT);
    pinMode(MODEM_POWER_ON, OUTPUT);

    // Turn on the Modem power first
    digitalWrite(MODEM_POWER_ON, HIGH);

    // Pull down PWRKEY for more than 1 second according to manual requirements
    digitalWrite(MODEM_PWRKEY, HIGH);
    delay(100);
    digitalWrite(MODEM_PWRKEY, LOW);
    delay(1000);
    digitalWrite(MODEM_PWRKEY, HIGH);

    // Initialize the indicator as an output
    pinMode(LED_GPIO, OUTPUT);
    digitalWrite(LED_GPIO, LED_OFF);
}

Make sure to change accordingle the following lines of code:

const char apn[] = "omnitel";
const char user[] = "omni";
const char pass[] = "omni";

and

const char server[] = "myesptestserver.ddns.net";
const int port = 80;
const char resource[] = "/esp.bin"; //here de bin file

For storing the bin files, you have multiple choises.

  1. Use Raspberry pi as a server ( I have created a simple apache server where I uploaded my binary file, and then I can access that server through the following sketch.

However, for testing it maybe be easier to setup Xampp on windows machine just to see whether you can get it to work. 2. Create an apache or simmilar server on your windows machine ( probably the simplest method would be to use Xampp as it does everything for you. In the xampp folder you will have htdocs folder where you can put your binary. and you can access that binary by using my sketch or your own sketch

const char server[] = "myesptestserver.ddns.net"; // ip of server or web address
const int port = 80;
const char resource[] = "/esp.bin"; // put your binary file name

Let me know if you have any more questions

This firmware below make ota from Github. I try mix your code with this, but I yet cant:

#include <WiFi.h> #include <HTTPClient.h> #include <HTTPUpdate.h> #include <WiFiClientSecure.h> #include "cert.h"

const char * ssid = "home_wifi"; const char * password = "helloworld";

String FirmwareVer = { "2.2" }; #define URL_fw_Version "https://raw.githubusercontent.com/programmer131/ESP8266_ESP32_SelfUpdate/master/esp32_ota/bin_version.txt" #define URL_fw_Bin "https://raw.githubusercontent.com/programmer131/ESP8266_ESP32_SelfUpdate/master/esp32_ota/fw.bin"

//#define URL_fw_Version "http://cade-make.000webhostapp.com/version.txt" //#define URL_fw_Bin "http://cade-make.000webhostapp.com/firmware.bin"

void connect_wifi(); void firmwareUpdate(); int FirmwareVersionCheck();

unsigned long previousMillis = 0; // will store last time LED was updated unsigned long previousMillis_2 = 0; const long interval = 60000; const long mini_interval = 1000; void repeatedCall() { static int num=0; unsigned long currentMillis = millis(); if ((currentMillis - previousMillis) >= interval) { // save the last time you blinked the LED previousMillis = currentMillis; if (FirmwareVersionCheck()) { firmwareUpdate(); } } if ((currentMillis - previousMillis_2) >= mini_interval) { previousMillis_2 = currentMillis; Serial.print("idle loop..."); Serial.print(num++); Serial.print(" Active fw version:"); Serial.println(FirmwareVer); if(WiFi.status() == WL_CONNECTED) { Serial.println("wifi connected"); } else { connect_wifi(); } } }

struct Button { const uint8_t PIN; uint32_t numberKeyPresses; bool pressed; };

Button button_boot = { 0, 0, false }; /void IRAM_ATTR isr(void arg) { Button* s = static_cast<Button*>(arg); s->numberKeyPresses += 1; s->pressed = true; }*/

void IRAM_ATTR isr() { button_boot.numberKeyPresses += 1; button_boot.pressed = true; }

void setup() { pinMode(button_boot.PIN, INPUT); attachInterrupt(button_boot.PIN, isr, RISING); Serial.begin(115200); Serial.print("Active firmware version:"); Serial.println(FirmwareVer); pinMode(LED_BUILTIN, OUTPUT); connect_wifi(); } void loop() { if (button_boot.pressed) { //to connect wifi via Android esp touch app Serial.println("Firmware update Starting.."); firmwareUpdate(); button_boot.pressed = false; } repeatedCall(); }

void connect_wifi() { Serial.println("Waiting for WiFi"); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }

Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); }

void firmwareUpdate(void) { WiFiClientSecure client; client.setCACert(rootCACertificate); httpUpdate.setLedPin(LED_BUILTIN, LOW); t_httpUpdate_return ret = httpUpdate.update(client, URL_fw_Bin);

switch (ret) { case HTTP_UPDATE_FAILED: Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s\n", httpUpdate.getLastError(), httpUpdate.getLastErrorString().c_str()); break;

case HTTP_UPDATE_NO_UPDATES: Serial.println("HTTP_UPDATE_NO_UPDATES"); break;

case HTTP_UPDATE_OK: Serial.println("HTTP_UPDATE_OK"); break; } } int FirmwareVersionCheck(void) { String payload; int httpCode; String fwurl = ""; fwurl += URL_fw_Version; fwurl += "?"; fwurl += String(rand()); Serial.println(fwurl); WiFiClientSecure * client = new WiFiClientSecure;

if (client) { client -> setCACert(rootCACertificate);

// Add a scoping block for HTTPClient https to make sure it is destroyed before WiFiClientSecure *client is 
HTTPClient https;

if (https.begin( * client, fwurl)) 
{ // HTTPS      
  Serial.print("[HTTPS] GET...\n");
  // start connection and send HTTP header
  delay(100);
  httpCode = https.GET();
  delay(100);
  if (httpCode == HTTP_CODE_OK) // if version received
  {
    payload = https.getString(); // save received version
  } else {
    Serial.print("error in downloading version file:");
    Serial.println(httpCode);
  }
  https.end();
}
delete client;

}

if (httpCode == HTTP_CODE_OK) // if version received { payload.trim(); if (payload.equals(FirmwareVer)) { Serial.printf("\nDevice already on latest firmware version:%s\n", FirmwareVer); return 0; } else { Serial.println(payload); Serial.println("New firmware detected"); return 1; } } return 0;
}

eueduardo3 avatar May 16 '21 01:05 eueduardo3

Hello. Have you managed to get examples from Arduino IDE working? They have an example sketch that performs an OTA over the http?

From the first glance, your code looks fine. What error are you getting?

On Sun, 16 May 2021, 04:26 eueduardo3, @.***> wrote:

Hello. Here is the code to perform OTA over the GSM:

#include <Update.h>

#define TINY_GSM_MODEM_SIM800

// Increase RX buffer

#define TINY_GSM_RX_BUFFER 1030

const char apn[] = "omnitel";

const char user[] = "omni";

const char pass[] = "omni";

#define MODEM_RST 5

#define MODEM_PWRKEY 4

#define MODEM_POWER_ON 23

#define MODEM_TX 27

#define MODEM_RX 26

#define LED_GPIO 13

#define LED_ON HIGH

#define LED_OFF LOW

#define SerialAT Serial1

#include <TinyGsmClient.h>

#include <CRC32.h>

#include "FS.h"

#include "SPIFFS.h"

#ifdef DUMP_AT_COMMANDS

#include <StreamDebugger.h>

StreamDebugger debugger(SerialAT, Serial);

TinyGsm modem(debugger);

#else

TinyGsm modem(SerialAT);

#endif

TinyGsmClient client(modem);

const char server[] = "myesptestserver.ddns.net";

const int port = 80;

const char resource[] = "/esp.bin"; //here de bin file

uint32_t knownCRC32 = 0x6f50d767;

uint32_t knownFileSize = 1024; // In case server does not send it

void setup()

{

SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);

// Set console baud rate

Serial.begin(115200);



setupModem();

delay(10);



if (!SPIFFS.begin(true))

{

    Serial.println("SPIFFS Mount Failed");

    return;

}

SPIFFS.format();

listDir(SPIFFS, "/", 0);



// Set GSM module baud rate



delay(3000);



// Restart takes quite some time

// To skip it, call init() instead of restart()

Serial.println("Initializing modem...");

modem.restart();



String modemInfo = modem.getModemInfo();

Serial.print("Modem: ");

Serial.println(modemInfo);



// Unlock your SIM card with a PIN

//modem.simUnlock("1234");

}

void loop()

{

Serial.print("Waiting for network...");

if (!modem.waitForNetwork())

{

    Serial.println(" fail");

    delay(10000);

    return;

}

Serial.println(" OK");



Serial.print("Connecting to ");

Serial.print(apn);

if (!modem.gprsConnect(apn, user, pass))

{

    Serial.println(" fail");

    delay(10000);

    return;

}

Serial.println(" OK");



Serial.print("Connecting to ");

Serial.print(server);



// if you get a connection, report back via serial:

if (!client.connect(server, port))

{

    Serial.println(" fail");

    delay(10000);

    return;

}

Serial.println(" OK");



// Make a HTTP request:

client.print(String("GET ") + resource + " HTTP/1.0\r\n");

client.print(String("Host: ") + server + "\r\n");

client.print("Connection: close\r\n\r\n");



long timeout = millis();

while (client.available() == 0)

{

    if (millis() - timeout > 5000L)

    {

        Serial.println(">>> Client Timeout !");

        client.stop();

        delay(10000L);

        return;

    }

}



Serial.println("Reading header");

uint32_t contentLength = knownFileSize;



File file = SPIFFS.open("/update.bin", FILE_APPEND);





while (client.available())

{

    String line = client.readStringUntil('\n');

    line.trim();

    //Serial.println(line);    // Uncomment this to show response header

    line.toLowerCase();

    if (line.startsWith("content-length:"))

    {

        contentLength = line.substring(line.lastIndexOf(':') + 1).toInt();

    }

    else if (line.length() == 0)

    {

        break;

    }

}





timeout = millis();

uint32_t readLength = 0;

CRC32 crc;



unsigned long timeElapsed = millis();

printPercent(readLength, contentLength);





while (readLength < contentLength && client.connected() && millis() - timeout < 10000L)

{

    int i = 0;

    while (client.available())

    {

            // read file data to spiffs

        if (!file.print(char(client.read())))

        {

            Serial.println("Appending file");

        }

        //Serial.print((char)c);       // Uncomment this to show data

        //crc.update(c);

        readLength++;



        if (readLength % (contentLength / 13) == 0)

        {

            printPercent(readLength, contentLength);

        }

        timeout = millis();

    }

}



file.close();



printPercent(readLength, contentLength);

timeElapsed = millis() - timeElapsed;

Serial.println();



client.stop();

Serial.println("stop client");



modem.gprsDisconnect();

Serial.println("gprs disconnect");

Serial.println();



float duration = float(timeElapsed) / 1000;

/*

Serial.print("Tamaño de Archivo: ");

Serial.println(contentLength);

Serial.print("Leido:  ");

Serial.println(readLength);

Serial.print("Calculado. CRC32:    0x");

Serial.println(crc.finalize(), HEX);

Serial.print("Conocido CRC32:    0x");

Serial.println(knownCRC32, HEX);

Serial.print("Bajado en:       ");

Serial.print(duration);

Serial.println("s");



Serial.println("Se genera una espera de 3 segundos");

for (int i = 0; i < 3; i++)

{

    Serial.print(String(i) + "...");

    delay(1000);

}

*/

//readFile(SPIFFS, "/update.bin");



updateFromFS();



// Do nothing forevermore

while (true)

{

    delay(1000);

}

}

void appendFile(fs::FS &fs, const char *path, const char *message)

{

Serial.printf("Appending to file: %s\n", path);



File file = fs.open(path, FILE_APPEND);

if (!file)

{

    Serial.println("Failed to open file for appending");

    return;

}

if (file.print(message))

{

    Serial.println("APOK");

}

else

{

    Serial.println("APX");

}

}

void readFile(fs::FS &fs, const char *path)

{

Serial.printf("Reading file: %s\n", path);



File file = fs.open(path);

if (!file || file.isDirectory())

{

    Serial.println("Failed to open file for reading");

    return;

}



Serial.print("Read from file: ");

while (file.available())

{

    Serial.write(file.read());

    delayMicroseconds(100);

}

}

void writeFile(fs::FS &fs, const char *path, const char *message)

{

Serial.printf("Writing file: %s\n", path);



File file = fs.open(path, FILE_WRITE);

if (!file)

{

    Serial.println("Failed to open file for writing");

    return;

}

if (file.print(message))

{

    Serial.println("File written");

}

else

{

    Serial.println("Write failed");

}

}

void listDir(fs::FS &fs, const char *dirname, uint8_t levels)

{

Serial.printf("Listing directory: %s\n", dirname);



File root = fs.open(dirname);

if (!root)

{

    Serial.println("Failed to open directory");

    return;

}

if (!root.isDirectory())

{

    Serial.println("Not a directory");

    return;

}



File file = root.openNextFile();

while (file)

{

    if (file.isDirectory())

    {

        Serial.print("  DIR : ");

        Serial.println(file.name());

        if (levels)

        {

            listDir(fs, file.name(), levels - 1);

        }

    }

    else

    {

        Serial.print("  FILE: ");

        Serial.print(file.name());

        Serial.print("  SIZE: ");

        Serial.println(file.size());

    }

    file = root.openNextFile();

}

}

void deleteFile(fs::FS &fs, const char *path)

{

Serial.printf("Deleting file: %s\n", path);

if (fs.remove(path))

{

    Serial.println("File deleted");

}

else

{

    Serial.println("Delete failed");

}

}

void updateFromFS()

{

File updateBin = SPIFFS.open("/update.bin");

if (updateBin)

{

    if (updateBin.isDirectory())

    {

        Serial.println("Directory error");

        updateBin.close();

        return;

    }



    size_t updateSize = updateBin.size();



    if (updateSize > 0)

    {

        Serial.println("Starting update");

        performUpdate(updateBin, updateSize);

    }

    else

    {

        Serial.println("Error, archivo vacío");

    }



    updateBin.close();



    // whe finished remove the binary from sd card to indicate end of the process

    //fs.remove("/update.bin");

}

else

{

    Serial.println("no such binary");

}

}

void performUpdate(Stream &updateSource, size_t updateSize)

{

if (Update.begin(updateSize))

{

    size_t written = Update.writeStream(updateSource);

    if (written == updateSize)

    {

        Serial.println("Writes : " + String(written) + " successfully");

    }

    else

    {

        Serial.println("Written only : " + String(written) + "/" + String(updateSize) + ". Retry?");

    }

    if (Update.end())

    {

        Serial.println("OTA finished!");

        if (Update.isFinished())

        {

            Serial.println("Restart ESP device!");

            ESP.restart();

        }

        else

        {

            Serial.println("OTA not fiished");

        }

    }

    else

    {

        Serial.println("Error occured #: " + String(Update.getError()));

    }

}

else

{

    Serial.println("Cannot beggin update");

}

}

void printPercent(uint32_t readLength, uint32_t contentLength)

{

// If we know the total length

if (contentLength != -1)

{

    Serial.print("\r ");

    Serial.print((100.0 * readLength) / contentLength);

    Serial.print('%');

}

else

{

    Serial.println(readLength);

}

}

void setupModem()

{

#ifdef MODEM_RST

// Keep reset high

pinMode(MODEM_RST, OUTPUT);

digitalWrite(MODEM_RST, HIGH);

#endif

pinMode(MODEM_PWRKEY, OUTPUT);

pinMode(MODEM_POWER_ON, OUTPUT);



// Turn on the Modem power first

digitalWrite(MODEM_POWER_ON, HIGH);



// Pull down PWRKEY for more than 1 second according to manual requirements

digitalWrite(MODEM_PWRKEY, HIGH);

delay(100);

digitalWrite(MODEM_PWRKEY, LOW);

delay(1000);

digitalWrite(MODEM_PWRKEY, HIGH);



// Initialize the indicator as an output

pinMode(LED_GPIO, OUTPUT);

digitalWrite(LED_GPIO, LED_OFF);

}

Make sure to change accordingle the following lines of code:

const char apn[] = "omnitel";

const char user[] = "omni";

const char pass[] = "omni";

and

const char server[] = "myesptestserver.ddns.net";

const int port = 80;

const char resource[] = "/esp.bin"; //here de bin file

For storing the bin files, you have multiple choises.

  1. Use Raspberry pi as a server ( I have created a simple apache server where I uploaded my binary file, and then I can access that server through the following sketch.

However, for testing it maybe be easier to setup Xampp on windows machine just to see whether you can get it to work. 2. Create an apache or simmilar server on your windows machine ( probably the simplest method would be to use Xampp as it does everything for you. In the xampp folder you will have htdocs folder where you can put your binary. and you can access that binary by using my sketch or your own sketch

const char server[] = "myesptestserver.ddns.net"; // ip of server or web address

const int port = 80;

const char resource[] = "/esp.bin"; // put your binary file name

Let me know if you have any more questions

This firmware below make ota from Github. I try mix your code with this, but I yet cant:

#include <WiFi.h> #include <HTTPClient.h> #include <HTTPUpdate.h> #include <WiFiClientSecure.h> #include "cert.h"

const char * ssid = "home_wifi"; const char * password = "helloworld";

String FirmwareVer = { "2.2" }; #define URL_fw_Version " https://raw.githubusercontent.com/programmer131/ESP8266_ESP32_SelfUpdate/master/esp32_ota/bin_version.txt " #define URL_fw_Bin " https://raw.githubusercontent.com/programmer131/ESP8266_ESP32_SelfUpdate/master/esp32_ota/fw.bin "

//#define URL_fw_Version "http://cade-make.000webhostapp.com/version.txt" //#define URL_fw_Bin "http://cade-make.000webhostapp.com/firmware.bin"

void connect_wifi(); void firmwareUpdate(); int FirmwareVersionCheck();

unsigned long previousMillis = 0; // will store last time LED was updated unsigned long previousMillis_2 = 0; const long interval = 60000; const long mini_interval = 1000; void repeatedCall() { static int num=0; unsigned long currentMillis = millis(); if ((currentMillis - previousMillis) >= interval) { // save the last time you blinked the LED previousMillis = currentMillis; if (FirmwareVersionCheck()) { firmwareUpdate(); } } if ((currentMillis - previousMillis_2) >= mini_interval) { previousMillis_2 = currentMillis; Serial.print("idle loop..."); Serial.print(num++); Serial.print(" Active fw version:"); Serial.println(FirmwareVer); if(WiFi.status() == WL_CONNECTED) { Serial.println("wifi connected"); } else { connect_wifi(); } } }

struct Button { const uint8_t PIN; uint32_t numberKeyPresses; bool pressed; };

Button button_boot = { 0, 0, false }; /void IRAM_ATTR isr(void arg) { Button* s = static_cast<Button*>(arg); s->numberKeyPresses += 1; s->pressed = true; }*/

void IRAM_ATTR isr() { button_boot.numberKeyPresses += 1; button_boot.pressed = true; }

void setup() { pinMode(button_boot.PIN, INPUT); attachInterrupt(button_boot.PIN, isr, RISING); Serial.begin(115200); Serial.print("Active firmware version:"); Serial.println(FirmwareVer); pinMode(LED_BUILTIN, OUTPUT); connect_wifi(); } void loop() { if (button_boot.pressed) { //to connect wifi via Android esp touch app Serial.println("Firmware update Starting.."); firmwareUpdate(); button_boot.pressed = false; } repeatedCall(); }

void connect_wifi() { Serial.println("Waiting for WiFi"); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }

Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); }

void firmwareUpdate(void) { WiFiClientSecure client; client.setCACert(rootCACertificate); httpUpdate.setLedPin(LED_BUILTIN, LOW); t_httpUpdate_return ret = httpUpdate.update(client, URL_fw_Bin);

switch (ret) { case HTTP_UPDATE_FAILED: Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s\n", httpUpdate.getLastError(), httpUpdate.getLastErrorString().c_str()); break;

case HTTP_UPDATE_NO_UPDATES: Serial.println("HTTP_UPDATE_NO_UPDATES"); break;

case HTTP_UPDATE_OK: Serial.println("HTTP_UPDATE_OK"); break; } } int FirmwareVersionCheck(void) { String payload; int httpCode; String fwurl = ""; fwurl += URL_fw_Version; fwurl += "?"; fwurl += String(rand()); Serial.println(fwurl); WiFiClientSecure * client = new WiFiClientSecure;

if (client) { client -> setCACert(rootCACertificate);

// Add a scoping block for HTTPClient https to make sure it is destroyed before WiFiClientSecure *client is

HTTPClient https;

if (https.begin( * client, fwurl))

{ // HTTPS

Serial.print("[HTTPS] GET...\n");

// start connection and send HTTP header

delay(100);

httpCode = https.GET();

delay(100);

if (httpCode == HTTP_CODE_OK) // if version received

{

payload = https.getString(); // save received version

} else {

Serial.print("error in downloading version file:");

Serial.println(httpCode);

}

https.end();

}

delete client;

}

if (httpCode == HTTP_CODE_OK) // if version received { payload.trim(); if (payload.equals(FirmwareVer)) { Serial.printf("\nDevice already on latest firmware version:%s\n", FirmwareVer); return 0; } else { Serial.println(payload); Serial.println("New firmware detected"); return 1; } } return 0; }

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/Xinyuan-LilyGO/LilyGo-T-Call-SIM800/issues/132#issuecomment-841750277, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFJU62XWVDQKYUMSHUPJMODTN4NMZANCNFSM42SG5BMA .

krupis avatar May 16 '21 05:05 krupis

I tried to use your script to try to OTA a file hosted on GitHub, but I couldn't. In this example that I posted, it is okay to OTA a file through github through Wifi, but I was unable to do that using a gsm modem through the TinyGsmClient library

eueduardo3 avatar May 16 '21 20:05 eueduardo3

That is really weird. I have created an apache server using xampp and can do an OTA from there. What error are you getting? Are you using esp32 with spiffs fs partition? Do you know where your code gets stuck

On Sun, 16 May 2021, 23:38 eueduardo3, @.***> wrote:

I tried to use your script to try to OTA a file hosted on GitHub, but I couldn't. In this example that I posted, it is okay to OTA a file through github through Wifi, but I was unable to do that using a gsm modem through the TinyGsmClient library

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/Xinyuan-LilyGO/LilyGo-T-Call-SIM800/issues/132#issuecomment-841874314, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFJU62U5PEISOCCM36IP2OTTOAUNPANCNFSM42SG5BMA .

krupis avatar May 16 '21 20:05 krupis

That is really weird. I have created an apache server using xampp and can do an OTA from there. What error are you getting? Are you using esp32 with spiffs fs partition? Do you know where your code gets stuck On Sun, 16 May 2021, 23:38 eueduardo3, @.***> wrote: I tried to use your script to try to OTA a file hosted on GitHub, but I couldn't. In this example that I posted, it is okay to OTA a file through github through Wifi, but I was unable to do that using a gsm modem through the TinyGsmClient library — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub <#132 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFJU62U5PEISOCCM36IP2OTTOAUNPANCNFSM42SG5BMA .

Now it worked! Thank you very much for making your code available and helping me. I changed the server and it worked. I was using 000webhost. And it was certainly my mistake, I was not sure how to correctly make the file available for download. Switching from server to another site / server with free hosting worked. Thank you very much for your attention in trying to help me. I wish success for your projects.

eueduardo3 avatar May 20 '21 22:05 eueduardo3

I did a skectch and work fine, is any are interested I can share ti, but I dont know how to make the server to store the bin file. I did the sketch using the TTGO CALL SIM800L github GSM tiny OTA example. If someone has and server example I will apreciate it, my idea is to store the bin file on my web server.

Hi, could you share your code? I'm having lots of issues trying any other code

Thank you

gunter72 avatar Jun 24 '21 16:06 gunter72

I did a skectch and work fine, is any are interested I can share ti, but I dont know how to make the server to store the bin file. I did the sketch using the TTGO CALL SIM800L github GSM tiny OTA example. If someone has and server example I will apreciate it, my idea is to store the bin file on my web server.

Hi, could you share your code? I'm having lots of issues trying any other code

Thank you

Hey. Have you tried the OTA over GSM code that I have posted above? It would be a good start if you can get that to work, then you can modify it as you wish. Make sure you have some sort of webserver available where you going to store your binary file for the OTA. Myself, I have downloaded XAMPP on windows and store my binary files there, but there are many options available.

krupis avatar Jun 24 '21 16:06 krupis

Hi, I tried your code, but it always reaches 90% and then it gives me an error. I have a private webserver, but I also tried altervista, I always have the same problem.

gunter72 avatar Jun 24 '21 17:06 gunter72

Could this be an issue due to the size of a binary you are trying to flash? OTA has some limitations especially if its a huge binary. Have you tried to play with changing the size of OTA ? Also, you can eliminate this by trying to flash some led blink or small binary program.

Does it return you any error message?

krupis avatar Jun 24 '21 17:06 krupis

Yes, I tried with small 100k files but I have the same error. My bin is 660k

gunter72 avatar Jun 24 '21 17:06 gunter72

Yes, I tried with small 100k files but I have the same error. My bin is 660k

I see. Thats unfortunate.. What GSM are you using? Have you tried to just read the whole binary file and not do the OTA and see if you can read the whole binary? Instead of updateFromFS try to read your binary

    readFile(SPIFFS, "/update.bin");

    //updateFromFS(); // comment this out

krupis avatar Jun 24 '21 17:06 krupis

Hi krupis, thank you very much for your support. I found the problem. It was a mistake in my code. The update took place while the mqtt communication was still active. I have stopped all active clients first, then I start the update process and everything works. Thanks so much!

gunter72 avatar Jun 28 '21 08:06 gunter72

Glad you found the issue.

krupis avatar Jun 28 '21 08:06 krupis

Hello. Here is the code to perform OTA over the GSM:


#include <Update.h>
#define TINY_GSM_MODEM_SIM800
// Increase RX buffer
#define TINY_GSM_RX_BUFFER 1030

const char apn[] = "omnitel";
const char user[] = "omni";
const char pass[] = "omni";



#define MODEM_RST             5
#define MODEM_PWRKEY          4
#define MODEM_POWER_ON       23
#define MODEM_TX             27
#define MODEM_RX             26
#define LED_GPIO             13
#define LED_ON               HIGH
#define LED_OFF              LOW


#define SerialAT  Serial1

#include <TinyGsmClient.h>
#include <CRC32.h>

#include "FS.h"
#include "SPIFFS.h"

#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, Serial);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif


TinyGsmClient client(modem);

const char server[] = "myesptestserver.ddns.net";
const int port = 80;
const char resource[] = "/esp.bin"; //here de bin file

uint32_t knownCRC32 = 0x6f50d767;
uint32_t knownFileSize = 1024; // In case server does not send it

void setup()
{
    SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
    // Set console baud rate
    Serial.begin(115200);

    setupModem();
    delay(10);

    if (!SPIFFS.begin(true))
    {
        Serial.println("SPIFFS Mount Failed");
        return;
    }
    SPIFFS.format();
    listDir(SPIFFS, "/", 0);

    // Set GSM module baud rate
    
    delay(3000);

    // Restart takes quite some time
    // To skip it, call init() instead of restart()
    Serial.println("Initializing modem...");
    modem.restart();

    String modemInfo = modem.getModemInfo();
    Serial.print("Modem: ");
    Serial.println(modemInfo);

    // Unlock your SIM card with a PIN
    //modem.simUnlock("1234");
}



void loop()
{
    Serial.print("Waiting for network...");
    if (!modem.waitForNetwork())
    {
        Serial.println(" fail");
        delay(10000);
        return;
    }
    Serial.println(" OK");

    Serial.print("Connecting to ");
    Serial.print(apn);
    if (!modem.gprsConnect(apn, user, pass))
    {
        Serial.println(" fail");
        delay(10000);
        return;
    }
    Serial.println(" OK");

    Serial.print("Connecting to ");
    Serial.print(server);

    // if you get a connection, report back via serial:
    if (!client.connect(server, port))
    {
        Serial.println(" fail");
        delay(10000);
        return;
    }
    Serial.println(" OK");
    
    // Make a HTTP request:
    client.print(String("GET ") + resource + " HTTP/1.0\r\n");
    client.print(String("Host: ") + server + "\r\n");
    client.print("Connection: close\r\n\r\n");

    long timeout = millis();
    while (client.available() == 0)
    {
        if (millis() - timeout > 5000L)
        {
            Serial.println(">>> Client Timeout !");
            client.stop();
            delay(10000L);
            return;
        }
    }

    Serial.println("Reading header");
    uint32_t contentLength = knownFileSize;

    File file = SPIFFS.open("/update.bin", FILE_APPEND);


    while (client.available())
    {
        String line = client.readStringUntil('\n');
        line.trim();
        //Serial.println(line);    // Uncomment this to show response header
        line.toLowerCase();
        if (line.startsWith("content-length:"))
        {
            contentLength = line.substring(line.lastIndexOf(':') + 1).toInt();
        }
        else if (line.length() == 0)
        {
            break;
        }
    }


    timeout = millis();
    uint32_t readLength = 0;
    CRC32 crc;

    unsigned long timeElapsed = millis();
    printPercent(readLength, contentLength);
    

    while (readLength < contentLength && client.connected() && millis() - timeout < 10000L)
    {
        int i = 0;
        while (client.available())
        {
                // read file data to spiffs
            if (!file.print(char(client.read())))
            {
                Serial.println("Appending file");
            }
            //Serial.print((char)c);       // Uncomment this to show data
            //crc.update(c);
            readLength++;

            if (readLength % (contentLength / 13) == 0)
            {
                printPercent(readLength, contentLength);
            }
            timeout = millis();
        }
    }

    file.close();

    printPercent(readLength, contentLength);
    timeElapsed = millis() - timeElapsed;
    Serial.println();

    client.stop();
    Serial.println("stop client");

    modem.gprsDisconnect();
    Serial.println("gprs disconnect");
    Serial.println();

    float duration = float(timeElapsed) / 1000;
  /*
    Serial.print("Tamaño de Archivo: ");
    Serial.println(contentLength);
    Serial.print("Leido:  ");
    Serial.println(readLength);
    Serial.print("Calculado. CRC32:    0x");
    Serial.println(crc.finalize(), HEX);
    Serial.print("Conocido CRC32:    0x");
    Serial.println(knownCRC32, HEX);
    Serial.print("Bajado en:       ");
    Serial.print(duration);
    Serial.println("s");

    Serial.println("Se genera una espera de 3 segundos");
    for (int i = 0; i < 3; i++)
    {
        Serial.print(String(i) + "...");
        delay(1000);
    }
  */
    //readFile(SPIFFS, "/update.bin");

    updateFromFS();

    // Do nothing forevermore
    while (true)
    {
        delay(1000);
    }
}







void appendFile(fs::FS &fs, const char *path, const char *message)
{
    Serial.printf("Appending to file: %s\n", path);

    File file = fs.open(path, FILE_APPEND);
    if (!file)
    {
        Serial.println("Failed to open file for appending");
        return;
    }
    if (file.print(message))
    {
        Serial.println("APOK");
    }
    else
    {
        Serial.println("APX");
    }
}

void readFile(fs::FS &fs, const char *path)
{
    Serial.printf("Reading file: %s\n", path);

    File file = fs.open(path);
    if (!file || file.isDirectory())
    {
        Serial.println("Failed to open file for reading");
        return;
    }

    Serial.print("Read from file: ");
    while (file.available())
    {
        Serial.write(file.read());
        delayMicroseconds(100);
    }
}

void writeFile(fs::FS &fs, const char *path, const char *message)
{
    Serial.printf("Writing file: %s\n", path);

    File file = fs.open(path, FILE_WRITE);
    if (!file)
    {
        Serial.println("Failed to open file for writing");
        return;
    }
    if (file.print(message))
    {
        Serial.println("File written");
    }
    else
    {
        Serial.println("Write failed");
    }
}

void listDir(fs::FS &fs, const char *dirname, uint8_t levels)
{
    Serial.printf("Listing directory: %s\n", dirname);

    File root = fs.open(dirname);
    if (!root)
    {
        Serial.println("Failed to open directory");
        return;
    }
    if (!root.isDirectory())
    {
        Serial.println("Not a directory");
        return;
    }

    File file = root.openNextFile();
    while (file)
    {
        if (file.isDirectory())
        {
            Serial.print("  DIR : ");
            Serial.println(file.name());
            if (levels)
            {
                listDir(fs, file.name(), levels - 1);
            }
        }
        else
        {
            Serial.print("  FILE: ");
            Serial.print(file.name());
            Serial.print("  SIZE: ");
            Serial.println(file.size());
        }
        file = root.openNextFile();
    }
}

void deleteFile(fs::FS &fs, const char *path)
{
    Serial.printf("Deleting file: %s\n", path);
    if (fs.remove(path))
    {
        Serial.println("File deleted");
    }
    else
    {
        Serial.println("Delete failed");
    }
}

void updateFromFS()
{
    File updateBin = SPIFFS.open("/update.bin");
    if (updateBin)
    {
        if (updateBin.isDirectory())
        {
            Serial.println("Directory error");
            updateBin.close();
            return;
        }

        size_t updateSize = updateBin.size();

        if (updateSize > 0)
        {
            Serial.println("Starting update");
            performUpdate(updateBin, updateSize);
        }
        else
        {
            Serial.println("Error, archivo vacío");
        }

        updateBin.close();

        // whe finished remove the binary from sd card to indicate end of the process
        //fs.remove("/update.bin");
    }
    else
    {
        Serial.println("no such binary");
    }
}

void performUpdate(Stream &updateSource, size_t updateSize)
{
    if (Update.begin(updateSize))
    {
        size_t written = Update.writeStream(updateSource);
        if (written == updateSize)
        {
            Serial.println("Writes : " + String(written) + " successfully");
        }
        else
        {
            Serial.println("Written only : " + String(written) + "/" + String(updateSize) + ". Retry?");
        }
        if (Update.end())
        {
            Serial.println("OTA finished!");
            if (Update.isFinished())
            {
                Serial.println("Restart ESP device!");
                ESP.restart();
            }
            else
            {
                Serial.println("OTA not fiished");
            }
        }
        else
        {
            Serial.println("Error occured #: " + String(Update.getError()));
        }
    }
    else
    {
        Serial.println("Cannot beggin update");
    }
}





void printPercent(uint32_t readLength, uint32_t contentLength)
{
    // If we know the total length
    if (contentLength != -1)
    {
        Serial.print("\r ");
        Serial.print((100.0 * readLength) / contentLength);
        Serial.print('%');
    }
    else
    {
        Serial.println(readLength);
    }
}



void setupModem()
{
#ifdef MODEM_RST
    // Keep reset high
    pinMode(MODEM_RST, OUTPUT);
    digitalWrite(MODEM_RST, HIGH);
#endif

    pinMode(MODEM_PWRKEY, OUTPUT);
    pinMode(MODEM_POWER_ON, OUTPUT);

    // Turn on the Modem power first
    digitalWrite(MODEM_POWER_ON, HIGH);

    // Pull down PWRKEY for more than 1 second according to manual requirements
    digitalWrite(MODEM_PWRKEY, HIGH);
    delay(100);
    digitalWrite(MODEM_PWRKEY, LOW);
    delay(1000);
    digitalWrite(MODEM_PWRKEY, HIGH);

    // Initialize the indicator as an output
    pinMode(LED_GPIO, OUTPUT);
    digitalWrite(LED_GPIO, LED_OFF);
}

Make sure to change accordingle the following lines of code:

const char apn[] = "omnitel";
const char user[] = "omni";
const char pass[] = "omni";

and

const char server[] = "myesptestserver.ddns.net";
const int port = 80;
const char resource[] = "/esp.bin"; //here de bin file

For storing the bin files, you have multiple choises.

  1. Use Raspberry pi as a server ( I have created a simple apache server where I uploaded my binary file, and then I can access that server through the following sketch.

However, for testing it maybe be easier to setup Xampp on windows machine just to see whether you can get it to work. 2. Create an apache or simmilar server on your windows machine ( probably the simplest method would be to use Xampp as it does everything for you. In the xampp folder you will have htdocs folder where you can put your binary. and you can access that binary by using my sketch or your own sketch

const char server[] = "myesptestserver.ddns.net"; // ip of server or web address
const int port = 80;
const char resource[] = "/esp.bin"; // put your binary file name

Let me know if you have any more questions

@krupis Hi krupis, I'm ok with esp32 coding side. But I have no idea to configure xamp server and where to store the .bin file in the server. How can I do this? Can you share any reference for this? Thanks in advance.

Mohamed-ali1998 avatar Sep 04 '21 06:09 Mohamed-ali1998

@Mohamed-ali1998 Hey mate. The binary should be stored inside htdocs folder where you have installed XAMP. There should be no additionall setup required apart from starting the XAMPP services. Also, keep in mind that in order to perfrom GSM OTA, you will need to port forward the IP address. I have used some free domain service. The reason is because the GSM is not connected to your home network and will not be able to reach your local computer IP address.

krupis avatar Sep 04 '21 12:09 krupis

@krupis Hi krupis. I used our own server. That's working fine. Thank you so much.

Mohamed-ali1998 avatar Sep 21 '21 10:09 Mohamed-ali1998

@krupis Hi everyone. I tried @krupis solution but have some issues (it seems to work but...):

Setup

  1. Zorin OS 15.3
  2. Arduino IDE 1.8.15
  3. Board: DOIT ESP32 DEVKIT V1
  4. File size: 198944 byte

I use the secure version ( TinyGSMClientSecure) of TinyGSM due to our server configs..

The .bin file download stop at 99.34% (~197630) and start the update. So it failed and return Error 9 (UPDATE_ERROR_ACTIVATE). Below is the print on serial monitor

17:32:39.384 -> Reading header
17:32:40.382 -> 
 0.00%
 7.69%
 15.38%
 23.08%
 30.77%
 38.46%
 46.15%
 53.84%
 61.54%
 69.23%
 76.92%
 84.61%
 92.31%
 99.33%
17:36:54.214 -> stop client
17:36:54.580 -> gprs disconnect
17:36:54.580 -> 
17:36:54.580 -> Starting update
17:36:57.475 -> Writes : 197621 successfully
17:36:57.608 -> E (311078) esp_image: Checksum failed. Calculated 0x54 read 0xff
17:36:57.675 -> Error occured #: 9
17:36:57.675 -> END

So a help or an idea about ? Thanks and great code!

TawalMc avatar Oct 15 '21 16:10 TawalMc

@TawalMc Hello. I dont think I can help you with this issue but @gunter72 had a simillar problem.

Before you do anything else, I would try 2 things

  1. Try with small binary
  2. Isolate the rest of your code just to confirm if GSM OTA part is working. If it does, then start adding your other code bit by bit and see which part cause the issues.

krupis avatar Oct 15 '21 17:10 krupis

Nj

On Fri, Oct 15, 2021, 6:33 PM krupis @.***> wrote:

Hello. I dont think I can help you with this issue but @gunter72 https://github.com/gunter72 had a simillar problem.

Before you do anything else, I would try 2 things

  1. Try with small binary
  2. Isolate the rest of your code just to confirm if GSM OTA part is working. If it does, then start adding your other code bit by bit and see which part cause the issues.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/Xinyuan-LilyGO/LilyGo-T-Call-SIM800/issues/132#issuecomment-944475980, or unsubscribe https://github.com/notifications/unsubscribe-auth/AHXC4BBKQPEF6GYYQ3X6TMLUHBQXTANCNFSM42SG5BMA . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

TawalMc avatar Oct 15 '21 17:10 TawalMc

@TawalMc Hello. I dont think I can help you with this issue but @gunter72 had a simillar problem.

Before you do anything else, I would try 2 things

  1. Try with small binary
  2. Isolate the rest of your code just to confirm if GSM OTA part is working. If it does, then start adding your other code bit by bit and see which part cause the issues.

Thanks. I'll try them. Good

TawalMc avatar Oct 15 '21 17:10 TawalMc

@TawalMc Hello. I dont think I can help you with this issue but @gunter72 had a simillar problem. Before you do anything else, I would try 2 things

  1. Try with small binary
  2. Isolate the rest of your code just to confirm if GSM OTA part is working. If it does, then start adding your other code bit by bit and see which part cause the issues.

Thanks. I'll try them. Good

Hello, i am getting same error#9, any luck ?

KASSIMSAMJI avatar Nov 03 '21 06:11 KASSIMSAMJI

f

@TawalMc Hello. I dont think I can help you with this issue but @gunter72 had a simillar problem. Before you do anything else, I would try 2 things

  1. Try with small binary
  2. Isolate the rest of your code just to confirm if GSM OTA part is working. If it does, then start adding your other code bit by bit and see which part cause the issues.

Thanks. I'll try them. Good

Hello, i am getting same error#9, any luck ?

I get same error sometimes.Sometime it works.Could you find any solution?

ilker07 avatar Dec 28 '21 07:12 ilker07

f

@TawalMc Hello. I dont think I can help you with this issue but @gunter72 had a simillar problem. Before you do anything else, I would try 2 things

  1. Try with small binary
  2. Isolate the rest of your code just to confirm if GSM OTA part is working. If it does, then start adding your other code bit by bit and see which part cause the issues.

Thanks. I'll try them. Good

Hello, i am getting same error#9, any luck ?

I get same error sometimes.Sometime it works.Could you find any solution?

in my case the success rate was so high (2 fails out of 20) few hours after midnight, so I deduced It is due to network being hogged during the day

KASSIMSAMJI avatar Dec 28 '21 09:12 KASSIMSAMJI

in my case the success rate was so high (2 fails out of 20) few hours after midnight, so I deduced It is due to network being hogged during the day

this morning I upload the code and it updated but after that I created new bin file and it gave me error.The error is E (342241) esp_image: invalid segment length 0x2d832b6.

ilker07 avatar Dec 28 '21 10:12 ilker07

f

@TawalMc Hello. I dont think I can help you with this issue but @gunter72 had a simillar problem. Before you do anything else, I would try 2 things

  1. Try with small binary
  2. Isolate the rest of your code just to confirm if GSM OTA part is working. If it does, then start adding your other code bit by bit and see which part cause the issues.

Thanks. I'll try them. Good

Hello, i am getting same error#9, any luck ?

I get same error sometimes.Sometime it works.Could you find any solution?

in my case the success rate was so high (2 fails out of 20) few hours after midnight, so I deduced It is due to network being hogged during the day

2021-12-28

Should I change these settings?

ilker07 avatar Dec 28 '21 11:12 ilker07