Blynk.Air OTA minimal code

Hi there,
here is the minimal code (extracted from OTA.h) i found working to integrate .Air OTA within blynk script quickly without the need for Edgent sketch, hope that helps somebody:

#include <Update.h>
#include <HTTPClient.h>
//________________________________________________________________
String overTheAirURL = "";
BLYNK_WRITE(InternalPinOTA) {
  overTheAirURL = param.asString();
  HTTPClient http;
  http.begin(overTheAirURL);
  int httpCode = http.GET();
  if (httpCode != HTTP_CODE_OK) {return;}
  int contentLength = http.getSize();
  if (contentLength <= 0) {return; }
  bool canBegin = Update.begin(contentLength);
  if (!canBegin) { return;}
  Client& client = http.getStream();
  int written = Update.writeStream(client);
  if (written != contentLength) {return;}
  if (!Update.end()) {return;}
  if (!Update.isFinished()) {return;}
reboot();
}

void reboot()
{
#if defined(ARDUINO_ARCH_MEGAAVR)
  wdt_enable(WDT_PERIOD_8CLK_gc);
#elif defined(__AVR__)
  wdt_enable(WDTO_15MS);
#elif defined(__arm__)
  NVIC_SystemReset();
#elif defined(ESP8266) || defined(ESP32)
  ESP.restart();
#else
  #error "MCU reset procedure not implemented"
#endif
  for (;;) {}
}
//__________________________________________________________
9 Likes

I’ve just been testing this, and found that I needed to use the SSL version of the Blynk library for this to work. If I use the non-SSL version (BlynkSimpleEsp32) then the BLYNK_WRITE(InternalPinOTA) callback is never triggered during normal running of the sketch.
Oddly though, it is triggered when the device is rebooted and re-connects to Blynk and this is without any BLYNK_CONNECTED callback in my sketch.

I had tried producing my own version of a minimal sketch before, and couldn’t get past this point, but that was almost certainly because I wasn’t using the SSL library.

A couple of other points…

The original code has a Blynk.disconnect() before the http.begin(overTheAirURL) command, so that Blynk doesn’t interfere with the update process. It might be worth adding this back in?

Also, adding the firmware version line from the Edgent sketch to the top of the code can be useful…

#define BLYNK_FIRMWARE_VERSION "x.x.x"

as this allows you to use the “Lower Firmware Version” rule from the Blynk.Air screen in the web console.

Thanks for posting this, it was extreemly useful.

Pete.

4 Likes

Thanks Pete, glade to hear that it was useful.
I tested this using BlynkSimpleEsp32 (not the SSL version) and worked fine and tested it again before replying here, But failed with BlynkSimpleTinyGSM.
You are right omitting Blynk.disconnect() was no good at all.
And yes defining firmware revision is very useful. I used it at least to verify that the shipment was successful.

That’s interesting, I’ll do more testing with the non SSL library file.

Pete.

Ibrahim_Roshdy, PeteKnight, thanks for this OTA example, everything works in my project based on the BlynkSimpleEsp32.h library.

2 Likes

Note that if you added the Blynk.disconnect() line; you will need to put a Blynk.connect(); berfore each return(); in case of update failed.

2 Likes

Serg_Grn, Ibrahim_Roshdy, PeteKnight,

Hello friends.
Please help me on this topic.

As the topic instructs the code, the aim is to use the “BlynkSimpleEsp32.h library” to update via Blynk Air without using Blynk.Edgent.

I have 2 problems:

  1. I use BlynkSimpleEsp8266.h library
  2. I don’t know how to write OTA.h code or insert the code you are discussing in my code. (In what position, how to do it).

I take an example of the code used to turn on and off the D4 blue light on this Nodemcu.

#define BLYNK_TEMPLATE_ID ""
#define BLYNK_DEVICE_NAME ""
#define BLYNK_AUTH_TOKEN "X8q5lh0pfypriO7b5zAFNEiJoi1_S6zb"

#define BLYNK_FIRMWARE_VERSION        "1.1.1.1"

#define BLYNK_PRINT Serial

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <ESP8266Ping.h>


#define WIFI_SSID "HIEU VAI  THANH"                      //Enter Wifi Name
#define WIFI_PASS "passathai96"                    //Enter wifi Password


boolean setBlynk = 0;

void setup() {
  Serial.begin(115200);
  checkConnection();
  checkInternet();
  pinMode(D4,OUTPUT);
}

boolean checkConnection() {
  Serial.print("Check connecting to ");
  Serial.println(WIFI_SSID);
  WiFi.disconnect();
  WiFi.mode(WIFI_AP_STA);
  WiFi.begin(WIFI_SSID,WIFI_PASS);

  int count=0;
  while(count < 20){
    if(WiFi.status() == WL_CONNECTED){
      Serial.print("Connected to ");
      Serial.println(WIFI_SSID);
      Serial.print("Web Server IP Address: ");
      Serial.println(WiFi.localIP());
      Serial.println("");
      return true;
    }
    delay(5000);
    Serial.print(".");
    count++;
  }
  Serial.println("Timed out........ hiddenAP = 0;");
  Serial.println("");
  return false;
}


void checkInternet(){
  Serial.println("");
  bool ret = Ping.ping("www.google.com");
  if(ret){
    if(setBlynk == 0){
            Serial.println("ket noi NEW BLYNK NEW");
            Blynk.config(BLYNK_AUTH_TOKEN);
      setBlynk = 1;
    }
      if(!Blynk.connected()){
        Serial.println("Not connected to Blynk server");
        Blynk.connect(); // try to connect to server with default timeout
      }else{
        Serial.println("Connected to Blynk server");
      }
  Serial.println("");
}
}

void loop(){
  Blynk.run();
    if(!Blynk.connected()){
      int count=0;
      while(count < 3){//5 lan chay 6s Blynk.run la 30s
        Blynk.run();//thoi gian chay 6s
        if(Blynk.connected()){
          Serial.println("!Blynk.connected(); Blynk.connected())");Serial.println("");
          delay(500);
          return;
        }
        delay(1000);
        Serial.print(".");
        count++;
      }
      Serial.println("!Blynk.connected(); internetState = 0;");Serial.println("");
      delay(500);
   }
}



BLYNK_CONNECTED() {
  // Request the latest state from the server
  Blynk.syncVirtual(V4);
}

BLYNK_WRITE(V4) {
  int stateD4 = param.asInt();
  digitalWrite(D4, stateD4);
}

Please help me insert the code to support updating via BlynkAir.
In case you are using ESP32, please write and run on it for testing, I will re-code it myself to match my esp8266.

Thank you very much.

It’s always a good idea to add the #include lines together near the top of your sketch, so those two lines would go there.

The rest of the code can go anywhere, provided it’s not inside an existing function, so the simplest place it to tag it on to the end of your sketch.

Pete.

1 Like

Hello.
I tried to add, tweak the code a bit to fit the ESP8266. As below.

#define BLYNK_TEMPLATE_ID ""
#define BLYNK_DEVICE_NAME ""
#define BLYNK_AUTH_TOKEN "X8q5lh0pfypriO7b5zAFNEiJoi1_S6zb"

#define BLYNK_FIRMWARE_VERSION        "1.1.1.2"

#define BLYNK_PRINT Serial

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <ESP8266Ping.h>

//ESP32
//#include <Update.h>
//#include <HTTPClient.h>
//ESP8266
#include <ESP8266HTTPClient.h>
#include <ESP8266httpUpdate.h>
//________________________________________________________________
String overTheAirURL = "";

#define WIFI_SSID "HIEU VAI  THANH"                      //Enter Wifi Name
#define WIFI_PASS "passathai96"                    //Enter wifi Password


boolean setBlynk = 0;

void setup() {
  Serial.begin(115200);
  checkConnection();
  checkInternet();
  pinMode(D4,OUTPUT);
}

boolean checkConnection() {
  Serial.print("Check connecting to ");
  Serial.println(WIFI_SSID);
  WiFi.disconnect();
  WiFi.mode(WIFI_AP_STA);
  WiFi.begin(WIFI_SSID,WIFI_PASS);

  int count=0;
  while(count < 20){
    if(WiFi.status() == WL_CONNECTED){
      Serial.print("Connected to ");
      Serial.println(WIFI_SSID);
      Serial.print("Web Server IP Address: ");
      Serial.println(WiFi.localIP());
      Serial.println("");
      return true;
    }
    delay(5000);
    Serial.print(".");
    count++;
  }
  Serial.println("Timed out........ hiddenAP = 0;");
  Serial.println("");
  return false;
}


void checkInternet(){
  Serial.println("");
  bool ret = Ping.ping("www.google.com");
  if(ret){
    if(setBlynk == 0){
            Serial.println("ket noi NEW BLYNK NEW");
            Blynk.config(BLYNK_AUTH_TOKEN);
      setBlynk = 1;
    }
      if(!Blynk.connected()){
        Serial.println("Not connected to Blynk server");
        Blynk.connect(); // try to connect to server with default timeout
      }else{
        Serial.println("Connected to Blynk server");
      }
  Serial.println("");
}
}

void loop(){
  Blynk.run();
    if(!Blynk.connected()){
      int count=0;
      while(count < 3){//5 lan chay 6s Blynk.run la 30s
        Blynk.run();//thoi gian chay 6s
        if(Blynk.connected()){
          Serial.println("!Blynk.connected(); Blynk.connected())");Serial.println("");
          delay(500);
          return;
        }
        delay(1000);
        Serial.print(".");
        count++;
      }
      Serial.println("!Blynk.connected(); internetState = 0;");Serial.println("");
      delay(500);
   }
}



BLYNK_CONNECTED() {
  // Request the latest state from the server
  Blynk.syncVirtual(V4);
}

BLYNK_WRITE(V4) {
  int stateD4 = param.asInt();
  digitalWrite(D4, stateD4);
}

BLYNK_WRITE(InternalPinOTA) {
  overTheAirURL = param.asString();
  HTTPClient http;
  http.begin(overTheAirURL);
  int httpCode = http.GET();
  if (httpCode != HTTP_CODE_OK) {return;}
  int contentLength = http.getSize();
  if (contentLength <= 0) {return; }
  bool canBegin = Update.begin(contentLength);
  if (!canBegin) { return;}
  Client& client = http.getStream();
  int written = Update.writeStream(client);
  if (written != contentLength) {return;}
  if (!Update.end()) {return;}
  if (!Update.isFinished()) {return;}
reboot();
}

void reboot()
{
#if defined(ARDUINO_ARCH_MEGAAVR)
  wdt_enable(WDT_PERIOD_8CLK_gc);
#elif defined(__AVR__)
  wdt_enable(WDTO_15MS);
#elif defined(__arm__)
  NVIC_SystemReset();
#elif defined(ESP8266) || defined(ESP32)
  ESP.restart();
#else
  #error "MCU reset procedure not implemented"
#endif
  for (;;) {}
}
//_________

However, I still have not been able to update, the error appears as detailed image attached.

Do you have a way to test it for me?

Thank you.

Since ESP8266 core version 3.x.x the http.begin command now needs to know the transport method (WiFi) as well as the server url.

Try this…

  WiFiClient my_wifi_client;
  HTTPClient http;
  http.begin(my_wifi_client, overTheAirURL);

Pete.

1 Like

I’m sorry, I’ve revised the code as you instructed, but the update status is still the same as before.

  • Firmware Shipment Process Started 2:04:49 AM Today

  • Request sent 2:04:49 AM Today

  • New Firmware Requested 2:04:49 AM Today

  • Download Failure 2:04:49 AM Today

  • Firmware Shipment Process Started 2:04:22 AM Today

Maybe you should add some serial print commands to the sketch to see how the OTA process is progressing and where it’s failing.

You should also be 100% sure that the new .bin file is correctly compiled for the board you’re using.
I’d also swap to using a three digit version number rather than four.

Pete.

1 Like

Thank you for your response.
And here is my Serial Monitor.

02:43:17.747 → Check connecting to HIEU VAI THANH
02:43:22.978 → .Connected to HIEU VALUES
02:43:22.978 → Web Server IP Address: 192.168.1.21
02:43:22.978 →
02:43:22.978 →
02:43:27.216 → call NEW BLYNK NEW
02:43:27.216 → [32313]
02:43:27.216 → ___ __ __
02:43:27.216 → / _ )/ /_ _____ / /__
02:43:27.216 → / _ / / // / _ / '/
02:43:27.216 → /
//_, /////_
02:43:27.216 → /
_/ v1.1.0 on NodeMCU
02:43:27.216 →
02:43:27.216 → #StandWithUkraine https://bit.ly/swua
02:43:27.216 →
02:43:27.216 →
02:43:27.216 → Not connected to Blynk server
02:43:27.216 → [32323] Connecting to blynk.cloud:80
02:43:27.356 → [32472] Ready (ping: 43ms).
02:43:27.499 →
02:44:48,764 → InternalPinOTA
02:44:48.764 → http://sgp1.blynk.cloud/static/fw_11910610955607970738
-838595071.bin?token=fA9zNJlWe2d8TNpqfIt6H6Mb-W3p01kE
02:44:48.950 → canBegin

update command stopped at this line of code:
bool canBegin = Update.begin(contentLength);
if (!canBegin) {Serial.println(“canBegin”);return;}

Now it’s too late in my country. so I’ll come back later. Thank you for your interest.

I’ve just tested your sketch (after making the changes to the http.begin command and changing to a three digit firmware version (“1.1.2”) and it works fine…

image

Pete.

1 Like

Thank you, Peter.
I’ll check it out and see how it goes with me.
Thanks very much.

Dear Peter.
I tried to run the code again, but still the error.
I hope you can update your full code so I can test it, then I can fix it.
Thank you so much.

  • New Firmware Requested 12:30:31 AM Today

  • Download Failure 12:30:31 AM Today

  • Request sent 12:30:30 AM Today

  • Firmware Shipment Process Started 12:27:18 AM Today

  • Firmware Shipment Process Started 12:27:18 AM Today

  • Request sent 12:27:18 AM Today

  • New Firmware Requested 12:27:18 AM Today

  • Download Failure 12:27:18 AM Today

This was the sketch I used…

#define BLYNK_TEMPLATE_ID "REDACTED"
#define BLYNK_DEVICE_NAME "REDACTED"
#define BLYNK_AUTH_TOKEN "REDACTED"

#define BLYNK_FIRMWARE_VERSION "1.1.3"

#define BLYNK_PRINT Serial

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <ESP8266Ping.h>

//ESP32
//#include <Update.h>
//#include <HTTPClient.h>
//ESP8266
#include <ESP8266HTTPClient.h>
#include <ESP8266httpUpdate.h>
//________________________________________________________________
String overTheAirURL = "";

#define WIFI_SSID "REDACTED"                      //Enter Wifi Name
#define WIFI_PASS "REDACTED"                    //Enter wifi Password


boolean setBlynk = 0;

void setup() {
  Serial.begin(74880);
  checkConnection();
  checkInternet();
  pinMode(D4,OUTPUT);
}

boolean checkConnection() {
  Serial.print("Check connecting to ");
  Serial.println(WIFI_SSID);
  WiFi.disconnect();
  WiFi.mode(WIFI_AP_STA);
  WiFi.begin(WIFI_SSID,WIFI_PASS);

  int count=0;
  while(count < 20){
    if(WiFi.status() == WL_CONNECTED){
      Serial.print("Connected to ");
      Serial.println(WIFI_SSID);
      Serial.print("Web Server IP Address: ");
      Serial.println(WiFi.localIP());
      Serial.println("");
      return true;
    }
    delay(5000);
    Serial.print(".");
    count++;
  }
  Serial.println("Timed out........ hiddenAP = 0;");
  Serial.println("");
  return false;
}


void checkInternet(){
  Serial.println("");
  bool ret = Ping.ping("www.google.com");
  if(ret){
    if(setBlynk == 0){
            Serial.println("ket noi NEW BLYNK NEW");
            Blynk.config(BLYNK_AUTH_TOKEN);
      setBlynk = 1;
    }
      if(!Blynk.connected()){
        Serial.println("Not connected to Blynk server");
        Blynk.connect(); // try to connect to server with default timeout
      }else{
        Serial.println("Connected to Blynk server");
      }
  Serial.println("");
}
}

void loop(){
  Blynk.run();
    if(!Blynk.connected()){
      int count=0;
      while(count < 3){//5 lan chay 6s Blynk.run la 30s
        Blynk.run();//thoi gian chay 6s
        if(Blynk.connected()){
          Serial.println("!Blynk.connected(); Blynk.connected())");Serial.println("");
          delay(500);
          return;
        }
        delay(1000);
        Serial.print(".");
        count++;
      }
      Serial.println("!Blynk.connected(); internetState = 0;");Serial.println("");
      delay(500);
   }
}



BLYNK_CONNECTED() {
  // Request the latest state from the server
  Blynk.syncVirtual(V4);
}

BLYNK_WRITE(V4) {
  int stateD4 = param.asInt();
  digitalWrite(D4, stateD4);
}

BLYNK_WRITE(InternalPinOTA) {
 Serial.println("OTA Started"); 
  overTheAirURL = param.asString();
 Serial.print("overTheAirURL = ");  
 Serial.println(overTheAirURL);  
  WiFiClient my_wifi_client;
  HTTPClient http;
  http.begin(my_wifi_client, overTheAirURL);
  int httpCode = http.GET();
 Serial.print("httpCode = ");  
 Serial.println(httpCode);  
  if (httpCode != HTTP_CODE_OK) {return;}
  int contentLength = http.getSize();
 Serial.print("contentLength = ");  
 Serial.println(contentLength);   
  if (contentLength <= 0) {return; }
  bool canBegin = Update.begin(contentLength);
 Serial.print("canBegin = ");  
 Serial.println(canBegin);    
  if (!canBegin) { return;}
  Client& client = http.getStream();
  int written = Update.writeStream(client);
 Serial.print("written = ");  
 Serial.println(written);   
  if (written != contentLength) {return;}
  if (!Update.end()) {return;}
  if (!Update.isFinished()) {return;}
reboot();
}

void reboot()
{
 Serial.println("Rebooting after OTA Update..."); 
#if defined(ARDUINO_ARCH_MEGAAVR)
  wdt_enable(WDT_PERIOD_8CLK_gc);
#elif defined(__AVR__)
  wdt_enable(WDTO_15MS);
#elif defined(__arm__)
  NVIC_SystemReset();
#elif defined(ESP8266) || defined(ESP32)
  ESP.restart();
#else
  #error "MCU reset procedure not implemented"
#endif
  for (;;) {}
}
//_________

Pete.

1 Like

Dear PeteKnight
I used your code and edited the parameter according to my device.

#define BLYNK_TEMPLATE_ID "TMPLhFym36bS"
#define BLYNK_DEVICE_NAME "TEST SWITCH"
#define BLYNK_AUTH_TOKEN "X8q5lh0pfypriO7b5zAFNEiJoi1_S6zb"

#define BLYNK_FIRMWARE_VERSION "1.1.4"

#define BLYNK_PRINT Serial

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <ESP8266Ping.h>

//ESP32
//#include <Update.h>
//#include <HTTPClient.h>
//ESP8266
#include <ESP8266HTTPClient.h>
#include <ESP8266httpUpdate.h>
//________________________________________________________________
String overTheAirURL = "";

#define WIFI_SSID "HIEU VAI  THANH"                      //Enter Wifi Name
#define WIFI_PASS "passathai96"                    //Enter wifi Password


boolean setBlynk = 0;

void setup() {
  Serial.begin(115200);
  checkConnection();
  checkInternet();
  pinMode(D4,OUTPUT);
}

boolean checkConnection() {
  Serial.print("Check connecting to ");
  Serial.println(WIFI_SSID);
  WiFi.disconnect();
  WiFi.mode(WIFI_AP_STA);
  WiFi.begin(WIFI_SSID,WIFI_PASS);

  int count=0;
  while(count < 20){
    if(WiFi.status() == WL_CONNECTED){
      Serial.print("Connected to ");
      Serial.println(WIFI_SSID);
      Serial.print("Web Server IP Address: ");
      Serial.println(WiFi.localIP());
      Serial.println("");
      return true;
    }
    delay(5000);
    Serial.print(".");
    count++;
  }
  Serial.println("Timed out........ hiddenAP = 0;");
  Serial.println("");
  return false;
}


void checkInternet(){
  Serial.println("");
  bool ret = Ping.ping("www.google.com");
  if(ret){
    if(setBlynk == 0){
            Serial.println("ket noi NEW BLYNK NEW");
            Blynk.config(BLYNK_AUTH_TOKEN);
      setBlynk = 1;
    }
      if(!Blynk.connected()){
        Serial.println("Not connected to Blynk server");
        Blynk.connect(); // try to connect to server with default timeout
      }else{
        Serial.println("Connected to Blynk server");
      }
  Serial.println("");
}
}

void loop(){
  Blynk.run();
    if(!Blynk.connected()){
      int count=0;
      while(count < 3){//5 lan chay 6s Blynk.run la 30s
        Blynk.run();//thoi gian chay 6s
        if(Blynk.connected()){
          Serial.println("!Blynk.connected(); Blynk.connected())");Serial.println("");
          delay(500);
          return;
        }
        delay(1000);
        Serial.print(".");
        count++;
      }
      Serial.println("!Blynk.connected(); internetState = 0;");Serial.println("");
      delay(500);
   }
}



BLYNK_CONNECTED() {
  // Request the latest state from the server
  Blynk.syncVirtual(V4);
}

BLYNK_WRITE(V4) {
  int stateD4 = param.asInt();
  digitalWrite(D4, stateD4);
}

BLYNK_WRITE(InternalPinOTA) {
 Serial.println("OTA Started"); 
  overTheAirURL = param.asString();
 Serial.print("overTheAirURL = ");  
 Serial.println(overTheAirURL);  
  WiFiClient my_wifi_client;
  HTTPClient http;
  http.begin(my_wifi_client, overTheAirURL);
  int httpCode = http.GET();
 Serial.print("httpCode = ");  
 Serial.println(httpCode);  
  if (httpCode != HTTP_CODE_OK) {return;}
  int contentLength = http.getSize();
 Serial.print("contentLength = ");  
 Serial.println(contentLength);   
  if (contentLength <= 0) {return; }
  bool canBegin = Update.begin(contentLength);
 Serial.print("canBegin = ");  
 Serial.println(canBegin);    
  if (!canBegin) { return;}
  Client& client = http.getStream();
  int written = Update.writeStream(client);
 Serial.print("written = ");  
 Serial.println(written);   
  if (written != contentLength) {return;}
  if (!Update.end()) {return;}
  if (!Update.isFinished()) {return;}
ESP.restart();
}

However, the error is still the same.

16:21:10.918 -> Check connecting to HIEU VAI  THANH
16:21:16.068 -> .Connected to HIEU VAI  THANH
16:21:16.068 -> Web Server IP Address: 192.168.1.21
16:21:16.068 -> 
16:21:16.068 -> 
16:21:21.068 -> ket noi NEW BLYNK NEW
16:21:21.068 -> [32728] 
16:21:21.068 ->     ___  __          __
16:21:21.068 ->    / _ )/ /_ _____  / /__
16:21:21.068 ->   / _  / / // / _ \/  '_/
16:21:21.068 ->  /____/_/\_, /_//_/_/\_\
16:21:21.068 ->         /___/ v1.1.0 on NodeMCU
16:21:21.068 -> 
16:21:21.068 ->  #StandWithUkraine    https://bit.ly/swua
16:21:21.068 -> 
16:21:21.068 -> 
16:21:21.068 -> Not connected to Blynk server
16:21:21.068 -> [32739] Connecting to blynk.cloud:80
16:21:21.198 -> [32860] Ready (ping: 42ms).
16:21:21.328 -> 
16:22:41.060 -> OTA Started
16:22:41.060 -> overTheAirURL = http://sgp1.blynk.cloud/static/fw_2886935217758816059_-838595071.bin?token=HVQLPULctf_MpnfTM88l1gsd3rJqpITR
16:22:41.201 -> httpCode = 200
16:22:41.201 -> contentLength = 298368
16:22:41.201 -> canBegin = 0
Firmware Shipment Process Started 4:22:40 PM Today
Request sent 4:22:40 PM Today
New Firmware Requested 4:22:40 PM Today
Download Failure 4:22:40 PM Today
Firmware Shipment Process Started 4:22:05 PM Today

Do you think the problem could be caused by this command line library error?

bool canBegin = Update.begin(contentLength);

No. It works perfectly for me.

Pete.

1 Like