Getting Nextion HTTP OTA uploads working

::ffff:192.168.0.111 - - [10/Feb/2021 16:09:39] "GET / HTTP/1.1" 200 -
::ffff:192.168.0.111 - - [10/Feb/2021 16:10:49] "GET / HTTP/1.1" 200 -
::ffff:192.168.0.228 - - [10/Feb/2021 16:10:59] code 404, message File not found
::ffff:192.168.0.228 - - [10/Feb/2021 16:10:59] "GET /Documents/Nextion/Weather.tft HTTP/1.1" 404 -
::ffff:192.168.0.228 - - [10/Feb/2021 16:12:06] "GET /Weather.tft HTTP/1.1" 200 -
::ffff:192.168.0.228 - - [10/Feb/2021 16:13:24] "GET /Weather.tft HTTP/1.1" 200 -
::ffff:192.168.0.228 - - [10/Feb/2021 16:14:12] "GET /Weather.tft HTTP/1.1" 200 -
::ffff:192.168.0.228 - - [10/Feb/2021 16:14:43] "GET /Weather.tft HTTP/1.1" 200 -
::ffff:192.168.0.228 - - [10/Feb/2021 16:15:01] "GET /Weather.tft HTTP/1.1" 200 -
::ffff:192.168.0.228 - - [10/Feb/2021 16:15:24] "GET /Weather.tft HTTP/1.1" 200 -
::ffff:192.168.0.228 - - [10/Feb/2021 16:15:48] "GET /Weather.tft HTTP/1.1" 200 -
::ffff:192.168.0.228 - - [10/Feb/2021 16:16:29] "GET /Weather.tft HTTP/1.1" 200 -
::ffff:192.168.0.228 - - [10/Feb/2021 16:16:54] "GET /Weather.tft HTTP/1.1" 200 -

This is with PY3. Any idea why this is showing the .228 IP instead of the .111 from my sketch?

NOTE Donā€™t get confused by the IP in the CMD window it is the devices IP on the target (server) IP

Yes in fact the issue is caused by espNextUpload library , it canā€™t get nextion Baud rate.
I have to verify my library version to compare with yours .
Beware about pin used as nextion serial.
By default itā€™s not TX, RX in the library.

Ah hah! ā€œDonā€™t have toā€ have the communication right ā€œbut it helpsā€!!

Got it! Now I will see if I remove all the Serial prints if I can use the normal TX RX pins because my hope is to use a button during normal operation to call back and update the screen with the box closed. Maybe you have tried this and it doesnā€™t workā€¦

1 Like

Ok so that works.

REMOVE all Serial prints and change library to GPIOs 1 and 3 TX and RX

@Blynk_Coeur So far anything over 19200 baud doesnā€™t get past 4%ā€¦ :frowning: will have to try my ESP32. Are your TX and RX wires soldered? Iā€™m wondering it my loose pins are a problem.

Yes try with esp32 it has 2 real serial ports .
I have not soldered the wires.
But you are on the way since you get upload started.

So I got totally finished uploading at 19200 then on the data check it failed. Iā€™ll have to do some back tracking to see if it is a baud rate issue or an issue of changing the pins.

1 Like

@Blynk_Coeur Ok I got it to it to upload at 250000!!! on the ESP32. I couldnā€™t get the ESP8266 to upload at all.

Now my big problem is trying to get EasyNextion library to work with ESP32 :cry:

1 Like

@PeteKnight seems I kinda hijacked this post. Maybe you could move all this to a new post??

1 Like

Your wish is my command! :grinning:

Pete.

3 Likes

To get the ESP32 working I used the following sketch. The example sketch in the library is bad broken.

/*
python 3
cd C:\Users\David\Downloads
py -m http.server
const char* fwUrlBase = "http://192.168.0.228:8000/Weather.tft"; // python server needed

python 2
python -m SimpleHTTPServer 8000
const char* fwUrlBase = "http://192.168.0.228:8000/Documents/Nextion/Weather.tft"; // python server needed

          !! FOR 8266   Went into the library and changed the pins of TX and RX to try to use in normal operation

  ESP8266 uses Software serial RX:5, TX:4 Wemos D1 mini RX:D1, TX:D2 
  ESP32 uses Hardware serial RX:16, TX:17
  Serial pins are defined in the ESPNexUpload.cpp file
*/

#if defined ESP8266
  #include <ESP8266WiFi.h>
  #include <ESP8266WiFiMulti.h>
  #include <ESP8266HTTPClient.h>

  ESP8266WiFiMulti WiFiMulti;
#elif defined ESP32
  #include <WiFi.h>
  #include <WiFiMulti.h>
  #include <HTTPClient.h>

  WiFiMulti WiFiMulti;
#endif

#include <ESPNexUpload.h>
#include <WiFiClient.h>
WiFiClient client;

#define NxBaud  250000
#define SrlBaud 115200

const char* fwUrlBase = "http://192.168.0.111:8000/Documents/Nextion/Weather.tft"; // python server needed
const char* ssid = "*******"; /// put your AP SSID here
const char* password = "********"; /// put your AP PASSWORD

bool updated = false;
int count = 0;

void setup() {
  Serial.begin(SrlBaud);
  Serial.println("Booting...");

  // initialize ESPNexUpload
  ESPNexUpload nextion(NxBaud);

  WiFi.begin(ssid, password);
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("Connecting to Wifi AP...");
    for ( int i = 0; i < 300; i++) {                  ///       try to connect to WiFi for max 30s
      if (WiFi.status() == WL_CONNECTED) {
        Serial.printf("it is connected after %d seconds", (i / 10));
        break;
      }
      yield();
      delay(100);
    }
  }
  if (WiFi.status() == WL_CONNECTED) {
    //if you get here you have connected to the WiFi
    Serial.println("\nconnected...yesss! :)");
    checkForUpdates() ;
  } else {
    Serial.println("TimeOut! Not Connected even after 10 Seconds trying...\n *** Something wrong happened. It did not connected... *** ");
  }
}

void loop() {
  //ArduinoOTA.handle();
}

void checkForUpdates() {
  Serial.println("http start ... ");

  HTTPClient httpClient;
  httpClient.begin( client, fwUrlBase );
  int httpCode = httpClient.GET();
  int contentLength = httpClient.getSize();

  Serial.print("httpCode ");
  Serial.println (httpCode);
  Serial.print("contentLength ");
  Serial.println (contentLength);

  if ( httpCode == 200 ) {
    // Update the nextion display
    Serial.println("File received. Update Nextion...");
    bool result;

    // initialize ESPNexUpload
    ESPNexUpload nextion(NxBaud);
   
    // Progress upload.....
    nextion.setUpdateProgressCallback([]() {
      count++;
      Serial.print(count / 8);
      Serial.println(" %");
    });

    // setup serial connection, send update command and send the expected update size
    result = nextion.prepareUpload(contentLength);

    if (!result) {
      Serial.println("Error: " + nextion.statusMessage);
    } else {
      Serial.print(F("Start upload. File size is: "));
      Serial.print(contentLength);
      Serial.println(F(" bytes"));

      // Upload the received byte Stream to the nextion
      result = nextion.upload(*httpClient.getStreamPtr());

      if (result) {
        updated = true;
        Serial.println("\nSuccesfully updated Nextion!");

      } else {
        Serial.println("\nError updating Nextion: " + nextion.statusMessage);
      }

      // end: wait(delay) for the nextion to finish the update process, send nextion reset command and end the serial connection to the nextion
      nextion.end();
    }
  } else {
    // else print http error
    Serial.println(String("HTTP error: ") + httpClient.errorToString(httpCode).c_str());
  }

  httpClient.end();
  Serial.println("Closing connection\n");
}
1 Like

Good to hear !
Now you have to ingrate to your Blynk code , tell me when you succeed !
I will try your sketch asap, because mine is limited to 57600 bauds.

Maybe first youā€™ll have to teach me how to read and write to nextion without a library :joy::rofl:

1 Like

Ok, donā€™t worry !!

ESP32 Only
Step 1 (2 to follow) not totally sure this is the best way to use 2 cores but this seems to work. Updates when V0 is pressed.

/*
python 3
cd C:\Users\David\Downloads
py -m http.server
const char* fwUrlBase = "http://192.168.0.228:8000/Weather.tft"; // python server needed

python 2
python -m SimpleHTTPServer 8000
const char* fwUrlBase = "http://192.168.0.228:8000/Documents/Nextion/Weather.tft"; // python server needed

          !! FOR 8266   Went into the library and changed the pins of TX and RX to try to use in normal operation

  ESP8266 uses Software serial RX:5, TX:4 Wemos D1 mini RX:D1, TX:D2 
  ESP32 uses Hardware serial RX:16, TX:17
  Serial pins are defined in the ESPNexUpload.cpp file
*/

#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>

WiFiMulti WiFiMulti;
#include <BlynkSimpleEsp32.h>

#include <ESPNexUpload.h>
#include <WiFiClient.h>
WiFiClient client;
BlynkTimer timer;

#define NxBaud  250000
#define SrlBaud 115200

const char* fwUrlBase = "http://192.168.0.111:8000/Documents/Nextion/Weather.tft"; // python server needed
const char* ssid = "******"; /// put your AP SSID here
const char* password = "******"; /// put your AP PASSWORD
char auth[] = "******";

bool updated = false;
int count = 0;

// Dirty loop with delays, YUCK!
void loop1(void *pvParameters)
{
  while (1)
  {
    int counter;
    Serial.println(counter);
    counter ++;
    delay(3000);
  }
}

// And running blynk stuff on other loop. Note the 1ms delay, this is need so the watchdog doesn't get confused
void loop2(void *pvParameters) {
  while (1) {
     Blynk.run();
     delay(1);
  }
}

void setup() {
  xTaskCreatePinnedToCore(loop1, "loop1", 4096, NULL, 1, NULL, 0);
  xTaskCreatePinnedToCore(loop2, "loop2", 4096, NULL, 1, NULL, 1);
  
  Serial.begin(SrlBaud);
  Serial.println("Booting...");

  // initialize ESPNexUpload
  ESPNexUpload nextion(NxBaud);

  WiFi.begin(ssid, password);
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("Connecting to Wifi AP...");
    for ( int i = 0; i < 300; i++) {                  ///       try to connect to WiFi for max 30s
      if (WiFi.status() == WL_CONNECTED) {
        Serial.printf("it is connected after %d seconds", (i / 10));
        break;
      }
      yield();
      delay(100);
    }
  }
  if (WiFi.status() == WL_CONNECTED) {
    //if you get here you have connected to the WiFi
    Serial.println("\nconnected...yesss! :)");  
  } else {
    Serial.println("TimeOut! Not Connected even after 10 Seconds trying...\n *** Something wrong happened. It did not connected... *** ");
  }
  
  Blynk.config(auth);
  Blynk.connect();
}

void loop() 
{
  //empty loop
}

void checkForUpdates() {
  Serial.println("http start ... ");

  HTTPClient httpClient;
  httpClient.begin( client, fwUrlBase );
  int httpCode = httpClient.GET();
  int contentLength = httpClient.getSize();

  Serial.print("httpCode ");
  Serial.println (httpCode);
  Serial.print("contentLength ");
  Serial.println (contentLength);

  if ( httpCode == 200 ) {
    // Update the nextion display
    Serial.println("File received. Update Nextion...");
    bool result;

    // initialize ESPNexUpload
    ESPNexUpload nextion(NxBaud);
   
    // Progress upload.....
    nextion.setUpdateProgressCallback([]() {
      count++;
      Serial.print(count / 8);
      Serial.println(" %");
    });

    // setup serial connection, send update command and send the expected update size
    result = nextion.prepareUpload(contentLength);

    if (!result) {
      Serial.println("Error: " + nextion.statusMessage);
    } else {
      Serial.print(F("Start upload. File size is: "));
      Serial.print(contentLength);
      Serial.println(F(" bytes"));

      // Upload the received byte Stream to the nextion
      result = nextion.upload(*httpClient.getStreamPtr());

      if (result) {
        updated = true;
        Serial.println("\nSuccesfully updated Nextion!");

      } else {
        Serial.println("\nError updating Nextion: " + nextion.statusMessage);
      }

      // end: wait(delay) for the nextion to finish the update process, send nextion reset command and end the serial connection to the nextion
      nextion.end();
    }
  } else {
    // else print http error
    Serial.println(String("HTTP error: ") + httpClient.errorToString(httpCode).c_str());
  }

  httpClient.end();
  Serial.println("Closing connection\n");
}

BLYNK_WRITE(V0)
{
  if(param.asInt())
  {
    checkForUpdates();
    Blynk.virtualWrite(V0,0);
  }
}
1 Like

Itā€™s a good idea to run 2 cores .
Good job Dave :+1:

Again probably dodgy but to get the data to send to the display we need Serial2 but if you hit V0 to update the screen there is a conflict with ESPNexUpload. So before running update we

Serial2.end(); 

This seems to work but will do more testing. The sketch below sends data both ways. (Just some test data)

My first attempt just was in an endless boot loop. The 10ms delays in the loops helped that for some reasonā€¦

/*
python 3
cd C:\Users\David\Downloads
py -m http.server
const char* fwUrlBase = "http://192.168.0.228:8000/Weather.tft"; // python server needed

python 2
python -m SimpleHTTPServer 8000
const char* fwUrlBase = "http://192.168.0.228:8000/Documents/Nextion/Weather.tft"; // python server needed

          !! FOR 8266   Went into the library and changed the pins of TX and RX to try to use in normal operation

  ESP8266 uses Software serial RX:5, TX:4 Wemos D1 mini RX:D1, TX:D2 
  ESP32 uses Hardware serial RX:16, TX:17
  Serial pins are defined in the ESPNexUpload.cpp file
*/

#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>

WiFiMulti WiFiMulti;
#include <BlynkSimpleEsp32.h>

#include <ESPNexUpload.h>
#include <WiFiClient.h>
WiFiClient client;
BlynkTimer timer;

int tempTry;
int lasttempTry;

#define NxBaud  250000
#define SrlBaud 115200
#define RXD2 16
#define TXD2 17

const char* fwUrlBase = "http://192.168.0.111:8000/Documents/Nextion/Weather.tft"; // python server needed
const char* ssid = "*****"; /// put your AP SSID here
const char* password = "*****"; /// put your AP PASSWORD
char auth[] = "*****";

bool updated = false;
int count = 0;

void tempAdd()
{
  tempTry ++;
}
// Dirty loop with delays, YUCK!
void loop1(void *pvParameters)
{
  while (1)
  {
    data_in_Nex();
    delay(10);
    data_out_Nex();
    delay(10);
  }
}

// And running blynk stuff on other loop. Note the 1ms delay, this is need so the watchdog doesn't get confused
void loop2(void *pvParameters) {
  while (1) {
     Blynk.run();
     timer.run();
     delay(10);
  }
}

void data_in_Nex()
{
  if(Serial2.available())
  {
    String data_from_Nex = "";
    delay(30);
    while(Serial2.available())
    {
      data_from_Nex += char(Serial2.read());
    }
    Serial.println(data_from_Nex);
    if(data_from_Nex == "larson"){Blynk.virtualWrite(V1, 1);}
    if(data_from_Nex == "larsoff"){Blynk.virtualWrite(V1, 0);}
  }
}

void data_out_Nex()
{
  if(tempTry != lasttempTry)             //restrict prints unless change
  {
    lasttempTry = tempTry;
    Serial2.print("page1.n1.val=" + String(tempTry));
    Serial2.write(0xff);
    Serial2.write(0xff);
    Serial2.write(0xff);
  }
  
}

void setup() {
  xTaskCreatePinnedToCore(loop1, "loop1", 4096, NULL, 1, NULL, 0);
  xTaskCreatePinnedToCore(loop2, "loop2", 4096, NULL, 1, NULL, 1);
  Serial2.begin(SrlBaud, SERIAL_8N1, RXD2, TXD2);
  Serial.begin(SrlBaud);
  Serial.println("Booting...");

  WiFi.begin(ssid, password);
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("Connecting to Wifi AP...");
    for ( int i = 0; i < 300; i++) {                  ///       try to connect to WiFi for max 30s
      if (WiFi.status() == WL_CONNECTED) {
        Serial.printf("it is connected after %d seconds", (i / 10));
        break;
      }
      yield();
      delay(100);
    }
  }
  if (WiFi.status() == WL_CONNECTED) {
    //if you get here you have connected to the WiFi
    Serial.println("\nconnected...yesss! :)");  
  } else {
    Serial.println("TimeOut! Not Connected even after 10 Seconds trying...\n *** Something wrong happened. It did not connected... *** ");
  }
  
  Blynk.config(auth);
  Blynk.connect();
  timer.setInterval(1251, tempAdd);
}

void loop() 
{
  //empty loop
}

void checkForUpdates() {
  Serial.println("http start ... ");

  HTTPClient httpClient;
  httpClient.begin( client, fwUrlBase );
  int httpCode = httpClient.GET();
  int contentLength = httpClient.getSize();

  Serial.print("httpCode ");
  Serial.println (httpCode);
  Serial.print("contentLength ");
  Serial.println (contentLength);

  if ( httpCode == 200 ) {
    // Update the nextion display
    Serial.println("File received. Update Nextion...");
    bool result;

    // initialize ESPNexUpload
    ESPNexUpload nextion(NxBaud);
   
    // Progress upload.....
    nextion.setUpdateProgressCallback([]() {
      count++;
      Serial.print(count / 9);
      Serial.println(" %");
    });

    // setup serial connection, send update command and send the expected update size
    result = nextion.prepareUpload(contentLength);

    if (!result) {
      Serial.println("Error: " + nextion.statusMessage);
    } else {
      Serial.print(F("Start upload. File size is: "));
      Serial.print(contentLength);
      Serial.println(F(" bytes"));

      // Upload the received byte Stream to the nextion
      result = nextion.upload(*httpClient.getStreamPtr());

      if (result) {
        updated = true;
        Serial.println("\nSuccesfully updated Nextion!");

      } else {
        Serial.println("\nError updating Nextion: " + nextion.statusMessage);
      }

      // end: wait(delay) for the nextion to finish the update process, send nextion reset command and end the serial connection to the nextion
      nextion.end();
    }
  } else {
    // else print http error
    Serial.println(String("HTTP error: ") + httpClient.errorToString(httpCode).c_str());
  }

  httpClient.end();
  Serial.println("Closing connection\n");
  Serial2.begin(SrlBaud, SERIAL_8N1, RXD2, TXD2);         //Remember to reinitialize Serial2 for messages from Nextion
  delay(100);
}

BLYNK_WRITE(V0)
{
  if(param.asInt())
  { 
    Serial2.end();                        //end Serial2 so as not to conflict with ESPNexUpload
    delay(100);
    ESPNexUpload nextion(NxBaud);         // initialize ESPNexUpload
    Blynk.virtualWrite(V0,0);
    checkForUpdates();
  }
}
1 Like

So this sketch was sometimes giving errors after Nextion upload. I added a time out 10s timer to let it verify the data before restarting the serial to see if that was the problem.

1 Like

Iā€™ll try your sketch tomorrow.
The last time I tried to upload nextion file with blynk sketch I got a failure too :scream::scream:

Ya if this doesnā€™t work I will try to put flags on my send and receive loops to switch them off will updating, however the Serial2.end() should stop itā€¦

1 Like

Iā€™d be curious what you find in the data sends I had 7 in one function and 1 would mostly not write to the display, I tried 20ms delays after each write to see it that helped and it didnā€™t. Now I have 5 in one and am 2 in another, seem as if 5-6 writes per function works better.

void data_out_Nex()
{
  if(minute() != lastMinute)
  {
      lastMinute = minute();
      
      //time
      if(hour()>12)
      {
        int hourFormat = hour()-12;
        sprintf(strTime,"page0.t7.txt=\"%u:%02u PM\"",hourFormat,minute());
      }
      else
      {
        sprintf(strTime,"page0.t7.txt=\"%u:%02u AM\"",hour(),minute());
      }
      Serial2.print(strTime);
      Serial2.write(0xff); Serial2.write(0xff); Serial2.write(0xff);

      //date
      sprintf(strDate,"page0.t8.txt=\"%02u/%02u/%02d\"",day(),month(),(year()%100));
      Serial2.print(strDate);
      Serial2.write(0xff); Serial2.write(0xff); Serial2.write(0xff);

      //interior temp
      Serial2.print("page0.t0.txt=\"" + String(int_temp_BME,1) +"\"");    //comma one sets the decimal place
      Serial2.write(0xff); Serial2.write(0xff); Serial2.write(0xff);

      //exterior temp
      Serial2.print("page0.t4.txt=\"" + String(temp_BME,1) +"\"");    //comma one sets the decimal place
      Serial2.write(0xff); Serial2.write(0xff); Serial2.write(0xff); 

      //interior humidity
      Serial2.print("page0.n1.val=" + String(int_humid_BME));
      Serial2.write(0xff); Serial2.write(0xff); Serial2.write(0xff); 

      //exterior humidity
      Serial2.print("page0.n0.val=" + String(humid_BME));
      Serial2.write(0xff); Serial2.write(0xff); Serial2.write(0xff); 
  }
}

void data_out_Nex1()
{
  if(minute() != lastMinute)
  {
      lastMinute1 = minute();
      
      //mintemp
      Serial2.print("page0.t9.txt=\"" + String(minTemp,1) +"\"");    //comma one sets the decimal place
      Serial2.write(0xff); Serial2.write(0xff); Serial2.write(0xff);

      //maxtemp
      Serial2.print("page0.t3.txt=\"" + String(maxTemp,1) +"\"");    //comma one sets the decimal place
      Serial2.write(0xff); Serial2.write(0xff); Serial2.write(0xff);
  }
}
1 Like