B4R Question OTA-update via https

peacemaker

Expert
Licensed User
Longtime User
Hi, All

I prepared and used this code for OTA ESP32: https://www.b4x.com/android/forum/threads/esp32-ota-update-from-server-via-wifi-only.149206/.
Now i need the universal variant including esp8266, but SDK are different.
But AI can help a lot to make the code, but strange that if HTTPS:// link of the .bin file is used - the server reply as 400 error. Server log is clear.

Why ?
Http:// links work OK with esp32 and esp8266. But why not https ?

[CODE lang="b4x" title="module 'espota'"]Private Sub Process_Globals
'These global variables will be declared once when the application starts.
'Public variables can be accessed from all modules.
Private bc As ByteConverter
Dim FullPath(200) As Byte
Dim tim As Timer
End Sub


Sub OTA_Update
Dim b() As Byte = others.ReplaceString(GlobalStore.Slot2, "\/", "/")
If b.Length <= 0 Then
Log("Empty URL for OTA-update")
Return
End If
Log("OTA-update downloading: ", b)
Dim URL1 As String = Main.bc.StringFromBytes(b)

espwdt.Stop
espwdt.Start(260000)
Main.timAPI.Enabled = False 'pause working with server
Dim result As Boolean = Start(URL1)
If result = False Then
Dim s As String = JoinStrings(Array As String(others.DeviceName, ": OTA-update error: ", "(", URL1 , ")"))
Log(s)
webapi.SendRelayRequest(0, s)
Else
Log("OTA update is OK, restarting")
webapi.SendRelayRequest(0, JoinStrings(Array As String(others.DeviceName, ": firmware was updated (", URL1, ")")))
End If
tim.Initialize("tim_tick", 5000)
tim.Enabled = True
End Sub

Sub tim_tick
tim.Enabled = False
others.restart(9) 'restart ESP MCU
End Sub

Sub Start(URL1 As String) As Boolean
Log("OTA starting...")
Dim b() As Byte = URL1
b = others.ReplaceString(b, "\/", "/")
If b = "" Then
Log("OTA URL is empty")
Return False
End If
bc.ArrayCopy(b, FullPath)
Return RunNative("updateFIRMWARE", Null)
End Sub


#if C
#ifdef ESP32
#include "WiFi.h"
#include "HTTPClient.h"
#include "Update.h"
#include "WiFiClientSecure.h"
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecure.h>
#endif

B4R::Object returnvalue_espota;

B4R::Object* updateFIRMWARE(B4R::Object* o)
{
char* url = (char*)b4r_espota::_fullpath->data;

bool isHttps = (strncmp(url, "https://", 8) == 0);

HTTPClient http;

if (isHttps) {
WiFiClientSecure client;
client.setInsecure(); // disable certificate check
http.begin(client, url);
} else {
WiFiClient client;
http.begin(client, url);
}

http.addHeader("User-Agent", "esp_my_project");
int httpCode = http.GET();

if (httpCode != HTTP_CODE_OK) {
::Serial.printf("[HTTP] GET failed, code: %d\n", httpCode);
http.end();
return returnvalue_espota.wrapNumber((byte)0);
}

int contentLen = http.getSize();
if (contentLen <= 0) {
::Serial.println("Error: Invalid content length");
http.end();
return returnvalue_espota.wrapNumber((byte)0);
}

if (!Update.begin(contentLen)) {
::Serial.println("Error: Update.begin() failed");
http.end();
return returnvalue_espota.wrapNumber((byte)0);
}

::Serial.printf("Downloading firmware (%d bytes)...\n", contentLen);

WiFiClient* stream = http.getStreamPtr();
size_t written = Update.writeStream(*stream);

if (written != (size_t)contentLen) {
::Serial.printf("Error: Written %u != expected %d\n", written, contentLen);
http.end();
return returnvalue_espota.wrapNumber((byte)0);
}

if (!Update.end()) {
::Serial.println("Error: Update.end() failed");
http.end();
return returnvalue_espota.wrapNumber((byte)0);
}

http.end();

if (Update.isFinished()) {
::Serial.println("OTA update successful!");
return returnvalue_espota.wrapNumber((byte)1);
} else {
::Serial.println("OTA update not finished");
return returnvalue_espota.wrapNumber((byte)0);
}
}
#End If[/CODE]

Usage like:
B4X:
GlobalStore.Put(2, "https://server.com/ota/update.bin")
espota.OTA_Update

Depending:
GlobalStore: https://www.b4x.com/android/forum/threads/module-globalstore-global-objects-storage.73863/
espwdt: https://www.b4x.com/android/forum/threads/esp32-watchdog.149346/post-1035353
 
Last edited:
Back
Top