1
\$\begingroup\$

I tried to implement OTA programming by making a web server and connecting to it and loading the bin file using my phone. It worked, so now I'm trying to do the OTA programming for my ESP32 using an external web server.

When I run the code, the ESP32 connects to WiFi but it can't download the firmware. It gives an error. When I use the link with https it shows a 303 error. When I change it to http it shows 302 error. When I delete the http from the link it shows this error "failed to parse protocol HTTPClient.cpp:251"

Here is my code. What is the problem?

#include <WiFi.h>
#include <HTTPClient.h>
#include <Update.h>
void updateFirmware(uint8_t *data, size_t len);
// location of firmware file on external web server
// change to your actual .bin location
#define HOST "www.drive.google.com/uc?export=download&id=1CGPNlpRMR9VKpC6HS3vWJtr4JCS6gB6Q"

HTTPClient client;
// Your WiFi credentials
const char* ssid = "abdc";
const char* password = "8765";
// Global variables
int totalLength;       //total size of firmware
int currentLength = 0; //current size of written firmware

void setup() {
  Serial.begin(9600);
  // Start WiFi connection
  WiFi.mode(WIFI_MODE_STA);        
  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());
  // Connect to external web server
  client.begin(HOST);
  // Get file, just to check if each reachable
  int resp = client.GET();
  Serial.print("Response: ");
  Serial.println(resp);
  // If file is reachable, start downloading
  if(resp == 200){
      // get length of document (is -1 when Server sends no Content-Length header)
      totalLength = client.getSize();
      // transfer to local variable
      int len = totalLength;
      // this is required to start firmware update process
      Update.begin(UPDATE_SIZE_UNKNOWN);
      Serial.printf("FW Size: %u\n",totalLength);
      // create buffer for read
      uint8_t buff[128] = { 0 };
      // get tcp stream
      WiFiClient * stream = client.getStreamPtr();
      // read all data from server
      Serial.println("Updating firmware...");
      while(client.connected() && (len > 0 || len == -1)) {
           // get available data size
           size_t size = stream->available();
           if(size) {
              // read up to 128 byte
              int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
              // pass to function
              updateFirmware(buff, c);
              if(len > 0) {
                 len -= c;
              }
           }
           delay(1);
      }
  }else{
    Serial.println("Cannot download firmware file. Only HTTP response 200: OK is supported. Double check firmware location #defined in HOST.");
  }
  client.end();
  
}

void loop() {}

// Function to update firmware incrementally
// Buffer is declared to be 128 so chunks of 128 bytes
// from firmware is written to device until server closes
void updateFirmware(uint8_t *data, size_t len){
  Update.write(data, len);
  currentLength += len;
  // Print dots while waiting for update to finish
  Serial.print('.');
  // if current length of written firmware is not equal to total firmware size, repeat
  if(currentLength != totalLength) return;
  Update.end(true);
  Serial.printf("\nUpdate Success, Total Size: %u\nRebooting...\n", currentLength);
  // Restart ESP32 to see changes 
  ESP.restart();
}
\$\endgroup\$
5
  • 1
    \$\begingroup\$ The problem seems to be on the web server side. 303 is a redirect. 302 means the address you are accessing has been moved. \$\endgroup\$
    – JRE
    May 2, 2022 at 10:39
  • 1
    \$\begingroup\$ If the problem is just redirects, you can enable automatic redirects with client.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); \$\endgroup\$
    – Codo
    May 2, 2022 at 11:03
  • \$\begingroup\$ use "https://". \$\endgroup\$
    – Juraj
    May 3, 2022 at 5:06
  • \$\begingroup\$ @Codo when i add the code you mentioned it gives this error : [E][ssl_client.cpp:36] _handle_error(): [start_ssl_client():216]: (-29312) SSL - The connection indicated an EOF<\r><\n>[E][WiFiClientSecure.cpp:133] connect(): start_ssl_client: -29312<\r><\n>Response: -1 \$\endgroup\$
    – salar1991
    May 5, 2022 at 9:10
  • \$\begingroup\$ Difficult to tell. I propose you increase the log level (I think it's called "Core Debug Level") and create a new question with the result. \$\endgroup\$
    – Codo
    May 5, 2022 at 10:25

1 Answer 1

3
\$\begingroup\$

Please note that using WifiClient instead of WifiClientSecure will make your device really easy to hack.

Since I don't see any SSL certificate or Root CA, I'm pretty sure all requests are done via HTTP.

Since your microcontroller will make all requests on HTTP any man-in-the-middle attack or ARP spoofing with DNS server or many other attack vectors, and an attacker could overwrite the firmware of the device.

For your issue: HTTP 303 is a redirect code, as stated by Codo. HTTP redirect codes can be found here.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.