Hi
I'm making a system using ESP32, Nextion and mqtt connection.
I am using the ITEAD library for Nextion. It turns out that when I load the sketch on the board and turn on the display nextion on the power and TX2 / RX2, when I click on the home button (btnInit) to open the second page (pageSecond) I have a delay, sometimes as little as 2 seconds, but sometimes large (+ 10 seconds). And I only get the message mqtt (which is retained = true) after it arrives on the second page.
I can't figure out the reason for this, I suspect it's the loop () but I don't know what to do.
bool firstConnection = false;
const char* usermqtt = "esp32/fitest01";
#include <timeObj.h>
timeObj timeMax(30 * 1000.0); //30 seconds
#include <EEPROM.h>
#include <PubSubClient.h>
#include <SPIFFS.h>
#include <WiFiClient.h>
#include <ESP_WiFiManager.h>
#include <Nextion.h>
#include <WiFi.h>
#include "ArduinoJson.h"
NexButton btnInit = NexButton(0, 2, "b0");
NexButton btnBack = NexButton(1, 3, "btnVoltar");
NexPage pageInit = NexPage(0, 0, "page0");
NexPage pageSecond = NexPage(1, 0, "page1");
NexTouch *nex_listen_list[] =
{
&btnInit,
&btnBack,
NULL
};
// SSID and PW for Config Portal
String ssid = "ESP_" + String(ESP_getChipId(), HEX);
const char* password = "your_password";
// SSID and PW for your Router
String Router_SSID;
String Router_Pass;
// Indicates whether ESP has WiFi credentials saved from previous session
bool initialConfig = false;
// Use true for dynamic DHCP IP, false to use static IP and you have to change the IP accordingly to your network
#define USE_DHCP_IP true
// Use DHCP
IPAddress stationIP = IPAddress(0, 0, 0, 0);
IPAddress gatewayIP = IPAddress(192, 168, 2, 1);
IPAddress netMask = IPAddress(255, 255, 255, 0);
IPAddress dns1IP = gatewayIP;
IPAddress dns2IP = IPAddress(8, 8, 8, 8);
#define ESP_getChipId() ((uint32_t)ESP.getEfuseMac())
#define PIN_LED 2
#define PIN D1
#define NUM_LEDS 3
bool shouldSaveConfig = false;
char placeWifi[60];
String nameOfPlace;
int numberOfPage;
const size_t JSON_SIZE = JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(9) + 4 * JSON_OBJECT_SIZE(17) + JSON_OBJECT_SIZE(18) + JSON_OBJECT_SIZE(20) + 2 * JSON_OBJECT_SIZE(21) + JSON_OBJECT_SIZE(23);
StaticJsonDocument<JSON_SIZE> docSpiffs;
const char* mqtt_server = "XXX.XXX.XXX.123";
WiFiClient wifiClient;
PubSubClient client(mqtt_server, 1883, NULL, wifiClient);
String _place;
String recivedData;
String json;
String jsonSave;
void heartBeatPrint(void)
{
static int num = 1;
if (WiFi.status() == WL_CONNECTED)
dbSerialPrint("H"); // H means connected to WiFi
else
dbSerialPrint("F"); // F means not connected to WiFi
if (num == 80)
{
dbSerialPrintln();
num = 1;
}
else if (num++ % 10 == 0)
{
dbSerialPrint(" ");
}
}
void check_status() {
// is configuration portal requested?
if (firstConnection)
{
dbSerialPrintln("\nConfiguration portal requested.");
digitalWrite(PIN_LED, HIGH); // turn the LED on by making the voltage LOW to tell us we are in configuration mode.
//Local intialization. Once its business is done, there is no need to keep it around
ESP_WiFiManager ESP_wifiManager;
ESP_wifiManager.setSaveConfigCallback(saveConfigCallback);
//Check if there is stored WiFi router/password credentials.
//If not found, device will remain in configuration mode until switched off via webserver.
dbSerialPrint("Opening configuration portal. ");
Router_SSID = ESP_wifiManager.WiFi_SSID();
if (Router_SSID != "")
{
ESP_wifiManager.setConfigPortalTimeout(120); //If no access point name has been previously entered disable timeout.
dbSerialPrintln("Got stored Credentials. Timeout 120s");
}
else
dbSerialPrintln("No stored Credentials. No timeout");
ESP_WMParameter custom_place("Place", "Place", placeWifi, 60);
ESP_wifiManager.addParameter(&custom_place);
ESP_wifiManager.setMinimumSignalQuality(-1);
// Set static IP, Gateway, Subnetmask, DNS1 and DNS2. New in v1.0.5
ESP_wifiManager.setSTAStaticIPConfig(stationIP, gatewayIP, netMask, dns1IP, dns2IP);
//it starts an access point
//and goes into a blocking loop awaiting configuration
if (!ESP_wifiManager.startConfigPortal((const char *) ssid.c_str(), password))
{
dbSerialPrintln("Not connected to WiFi but continuing anyway.");
}
else
{
//if you get here you have connected to the WiFi
dbSerialPrintln("connected...yeey :)");
dbSerialPrint("Local IP: ");
dbSerialPrintln(WiFi.localIP());
}
strcpy(placeWifi, custom_place.getValue());
digitalWrite(PIN_LED, LOW); // Turn led off as we are not in configuration mode.
dbSerialPrintln("PLACE");
dbSerialPrintln((const char*)placeWifi);
_place = String(placeWifi);
dbSerialPrintln("IN STRING: ");
dbSerialPrintln(_place);
recordPlace(10, _place);
}
static ulong checkstatus_timeout = 0;
#define HEARTBEAT_INTERVAL 10000L
// Print hearbeat every HEARTBEAT_INTERVAL (10) seconds.
if ((millis() > checkstatus_timeout) || (checkstatus_timeout == 0))
{
heartBeatPrint();
checkstatus_timeout = millis() + HEARTBEAT_INTERVAL;
}
}
void saveConfigCallback () {
dbSerialPrintln("Should save config");
shouldSaveConfig = true;
}
void callback(char* topic, unsigned char* message, unsigned int length) {
dbSerialPrint("Topic: ");
dbSerialPrint(topic);
dbSerialPrint(". Message: ");
String messageTemp;
messageTemp = "";
json = "";
for (int i = 0; i < length; i++) {
dbSerialPrint((char)message[i]);
messageTemp += (char)message[i];
}
json = messageTemp;
recordFile(json);
dbSerialPrintln("Json save in SPIFFS");
upSpiffs();
}
void setup() {
EEPROM.begin(512);
nexInit();
btnInit.attachPush(startPage2, &btnInit);
btnBack.attachPush(backPage1, &btnBack);
SPIFFS.begin();
if (!SPIFFS.exists("/infotest.json")) {
dbSerialPrintln("file error");
} else {
dbSerialPrintln("file ok");
upSpiffs();
deserializeJson(docSpiffs, jsonSave);
}
recivedData = readPlace(10);
dbSerialPrintln("Place in EEPROM:");
dbSerialPrintln(recivedData);
dbSerialPrintln("Connecting wifi...");
connectWifi();
dbSerialPrintln("Connecting mqtt...");
connectMqtt();
client.setCallback(callback);
client.setBufferSize(5044);
dbSerialPrintln("End setup()");
}
void loop() {
check_status();
if (!client.connected()) {
connectMqtt();
}
client.loop();
delay(100);
nexLoop(nex_listen_list);
switch (numberOfPage)
{
case 0:
if ((WiFi.status() == WL_CONNECTED) && (client.connected())) {
dbSerialPrintln("Connect");
}
break;
case 1:
if (timeMax.ding()) {
numberOfPage = 0;
pageInit.show();
}
dbSerialPrintln("Open second page");
break;
}
}
void recordPlace(char poss, String nome1)
{
int _size = nome1.length();
for (int i = 0; i < _size; i++)
{
EEPROM.write(poss + i, nome1[i]);
}
EEPROM.write(poss + _size, '\0'); //Add termination null character for String Data
EEPROM.commit();
}
void recordFile(String rec)
{
//Gravação do SPIFFS
File f = SPIFFS.open("/infotest.json", "w");
f.print(rec);
f.close();
}
void upSpiffs()
{
jsonSave = "";
File f = SPIFFS.open("/infotest.json.json", "r");
if (!f) {
dbSerialPrintln("Error file (upSpiffs)");
} else {
while (f.available()) {
jsonSave = f.readStringUntil('\n');
}
f.close();
dbSerialPrintln("json spiffs save");
dbSerialPrintln(jsonSave);
}
}
String readPlace(char ad)
{
int i;
char da[100]; //Max 100 Bytes
int len = 0;
unsigned char k;
k = EEPROM.read(ad);
while (k != '\0' && len < 500) //Read until null character
{
k = EEPROM.read(ad + len);
da[len] = k;
len++;
}
da[len] = '\0';
return String(da);
}
void connectWifi() {
dbSerialPrintln("\nStarting ConfigOnSwitch on " + String(ARDUINO_BOARD));
unsigned long startedAt = millis();
//Local intialization. Once its business is done, there is no need to keep it around
// Use this to default DHCP hostname to ESP8266-XXXXXX or ESP32-XXXXXX
//ESP_WiFiManager ESP_wifiManager;
// Use this to personalize DHCP hostname (RFC952 conformed)
ESP_WiFiManager ESP_wifiManager("ConfigOnSwitch");
ESP_wifiManager.setDebugOutput(true);
// Use only to erase stored WiFi Credentials
//resetSettings();
//ESP_wifiManager.resetSettings();
//set custom ip for portal
//ESP_wifiManager.setAPStaticIPConfig(IPAddress(192, 168, 100, 1), IPAddress(192, 168, 100, 1), IPAddress(255, 255, 255, 0));
ESP_wifiManager.setMinimumSignalQuality(-1);
// We can't use WiFi.SSID() in ESP32as it's only valid after connected.
// SSID and Password stored in ESP32 wifi_ap_record_t and wifi_config_t are also cleared in reboot
// Have to create a new function to store in EEPROM/SPIFFS for this purpose
Router_SSID = ESP_wifiManager.WiFi_SSID();
Router_Pass = ESP_wifiManager.WiFi_Pass();
//Remove this line if you do not want to see WiFi password printed
dbSerialPrintln("Stored: SSID = " + Router_SSID + ", Pass = " + Router_Pass);
// SSID to uppercase
ssid.toUpperCase();
if (Router_SSID == "")
{
dbSerialPrintln("Open Config Portal without Timeout: No stored Credentials.");
digitalWrite(PIN_LED, HIGH); // Turn led on as we are in configuration mode.
//it starts an access point
//and goes into a blocking loop awaiting configuration
if (!ESP_wifiManager.startConfigPortal((const char *) ssid.c_str(), password))
dbSerialPrintln("Not connected to WiFi but continuing anyway.");
else
dbSerialPrintln("WiFi connected...yeey :)");
}
digitalWrite(PIN_LED, LOW); // Turn led off as we are not in configuration mode.
#define WIFI_CONNECT_TIMEOUT 2000L
#define WHILE_LOOP_DELAY 200L
#define WHILE_LOOP_STEPS (WIFI_CONNECT_TIMEOUT / ( 3 * WHILE_LOOP_DELAY ))
startedAt = millis();
while ( (WiFi.status() != WL_CONNECTED) && (millis() - startedAt < WIFI_CONNECT_TIMEOUT ) )
{
WiFi.mode(WIFI_STA);
WiFi.persistent (true);
// We start by connecting to a WiFi network
dbSerialPrint("Connecting to ");
dbSerialPrintln(Router_SSID);
WiFi.config(stationIP, gatewayIP, netMask);
//WiFi.config(stationIP, gatewayIP, netMask, dns1IP, dns2IP);
WiFi.begin(Router_SSID.c_str(), Router_Pass.c_str());
int i = 0;
while ((!WiFi.status() || WiFi.status() >= WL_DISCONNECTED) && i++ < WHILE_LOOP_STEPS)
{
delay(WHILE_LOOP_DELAY);
}
}
dbSerialPrint("After waiting ");
dbSerialPrint((millis() - startedAt) / 1000);
dbSerialPrint(" secs more in setup(), connection result is ");
if (WiFi.status() == WL_CONNECTED)
{
dbSerialPrint("connected. Local IP: ");
dbSerialPrintln(WiFi.localIP());
}
}
void connectMqtt() {
int retries = 0;
while ((!client.connected()) && (retries < 3)) {
if (client.connect(usermqtt, "user", "p4assw0rd")) {
dbSerialPrintln("mqtt conected!");
client.subscribe("fitest01/test");
} else {
dbSerialPrint("fail mqtt, erro =");
dbSerialPrint(client.state());
retries += 1;
}
}
}
void startPage2(void *ptr)
{
pageSecond.show();
numberOfPage = 1;
timeMax.start();
}
void backPage1(void *ptr)
{
numberOfPage = 0;
pageInit.show();
}
PS: I save the information I receive via MQTT at SPIFFS, this information is a json. I also have a 30-second timer, which if I stay on the screen for more than 30 seconds without interaction, I return to the first one. This works well. The back to home screen button (btnBack) also works well.
Thank you!