[GH-ISSUE #992] Wifimanager won't call saveConfigCallback if no connection in STA after config #846

Closed
opened 2026-02-28 01:27:19 +03:00 by kerem · 2 comments
Owner

Originally created by @pczekalski on GitHub (Jan 11, 2020).
Original GitHub issue: https://github.com/tzapu/WiFiManager/issues/992

saveConfigCallback is not called in the scenario, where you configure STA but off-line (so you do not really connect, just pre-configure it and save).

Hardware

WiFimanager Branch/Release:

  • [X ] Master
  • Development

Esp8266/Esp32:

  • ESP8266
  • [ X] ESP32

Hardware: ESP-12e, esp01, esp25

  • ESP01
  • ESP12 E/F/S (nodemcu, wemos, feather)
  • [X ] Other

ESP Core Version: 2.4.0, staging

  • 2.3.0
  • [X ] 2.4.0
  • staging (master/dev)

Description

Assuming the manager starts in AP and exposes configuration portal, if you implement it the way presented in the AutoConnectWithFSParameters, then you enter blind configuration without being able to connect in STA to the configured infrastructure AP, the flag to trigger saveConfigCallback is never set thous won't let you save custom parameters. Meanwhile, saving of the SSID and password to the infrastructure AP is being saved thus it is inconsistent.

Steps to reproduce:

  • start in AP mode (expose configuration portal)
  • connect to it, configure data for non-existing (or offline) infrastructure AP you want to connect to,
  • click save

Code

#include <FS.h>
#include <SPIFFS.h>
#include <Arduino.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <ESPAsyncWiFiManager.h>
#include <ArduinoJson.h>  //Warning - only versions prior 6 are compatible (5.11)

//#define formatSPIFFS  //Force SPIFFS format

//Local AP section
#define APPASSWORD "alamakota"

//DHT Sensor section

#define DHTPIN 16
#define DHTTYPE    DHT11
#define MQTTTopicCommon "/itsilesia/showroom/"
#define MQTTTopicTemperature "/temperature/"
#define MQTTTopicHumidity "/Humidity/"
DHT_Unified dht(DHTPIN, DHTTYPE);
uint32_t delayMS = 10000; //10s
// Extra config parameters
char mqtt_server[40];
char mqtt_port[6] = "1883";
char customDeviceId[10] = "dev0";
char mqtt_user[40];
char mqtt_pass[40];
//flag for saving data
bool shouldSaveConfig = false;
bool forceRestart = false;
//services
AsyncWebServer server(80);
DNSServer dns;

//Callbacks
void saveConfigCallback () {
  Serial.println("Should save config");
  shouldSaveConfig = true;
}

void setup() {
  Serial.begin(9600);
  dht.begin();

  Serial.println();
  Serial.println();
  if (SPIFFS.begin()) {
    Serial.println("mounted file system");
    if (SPIFFS.exists("/config.json")) {
      //file exists, reading and loading
      Serial.println("reading config file");
      File configFile = SPIFFS.open("/config.json", "r");
      if (configFile) {
        Serial.println("opened config file");
        size_t size = configFile.size();
        // Allocate a buffer to store contents of the file.
        std::unique_ptr<char[]> buf(new char[size]);

        configFile.readBytes(buf.get(), size);
        DynamicJsonBuffer jsonBuffer;
        JsonObject& json = jsonBuffer.parseObject(buf.get());
        json.printTo(Serial);
        if (json.success()) {
          Serial.println("\nparsed json");
          strcpy(mqtt_server, json["mqtt_server"]);
          strcpy(mqtt_port, json["mqtt_port"]);
          strcpy(customDeviceId, json["custom_device_id"]);
          strcpy(mqtt_user, json["mqtt_user"]);
          strcpy(mqtt_pass, json["mqtt_pass"]);
        } else {
          Serial.println("failed to load json config");
        }
      }

    }else
    {
      Serial.println("No config file");
    }
    
  } else {
    Serial.println("failed to mount FS");
    SPIFFS.format();
  }
  //Serial.println(customDeviceId);
  //Serial.println(mqtt_user);
  //Serial.println(mqtt_pass);
  // end reading config file

  AsyncWiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 40);
  AsyncWiFiManagerParameter custom_mqtt_port("port", "mqtt port", mqtt_port, 5);
  AsyncWiFiManagerParameter custom_device_id("deviceid", "device ID", customDeviceId, 10);
  AsyncWiFiManagerParameter custom_mqtt_user("user", "mqtt user", mqtt_user,40);
  AsyncWiFiManagerParameter custom_mqtt_pass("pass", "mqtt password", mqtt_pass,40);

  AsyncWiFiManager wifiManager(&server,&dns);
  wifiManager.setDebugOutput(false);
  
  wifiManager.setSaveConfigCallback(saveConfigCallback);

  wifiManager.addParameter(&custom_mqtt_server);
  wifiManager.addParameter(&custom_mqtt_port);
  wifiManager.addParameter(&custom_device_id);
  wifiManager.addParameter(&custom_mqtt_user);
  wifiManager.addParameter(&custom_mqtt_pass);
  wifiManager.setTimeout(180);
  
  if (!wifiManager.autoConnect("itSilesiaSensor", APPASSWORD)) {
    Serial.println("failed to connect and hit timeout");
    delay(3000);
    //reset and try again, or maybe put it to deep sleep
    forceRestart = true;
  
  }
  strcpy(mqtt_server, custom_mqtt_server.getValue());
  strcpy(mqtt_port, custom_mqtt_port.getValue());
  strcpy(customDeviceId, custom_device_id.getValue());
  strcpy(mqtt_user, custom_mqtt_user.getValue());
  strcpy(mqtt_pass, custom_mqtt_pass.getValue());
  
  // Work save parameters otherwise if configuring off-line!!!!
  shouldSaveConfig = true;
  // save parameters
  if (shouldSaveConfig) {
    Serial.println("saving config");
    DynamicJsonBuffer jsonBuffer;
    JsonObject& json = jsonBuffer.createObject();
    json["mqtt_server"] = mqtt_server;
    json["mqtt_port"] = mqtt_port;
    json["custom_device_id"] = customDeviceId;
    json["mqtt_user"] = mqtt_user;
    json["mqtt_pass"] = mqtt_pass;

    File configFile = SPIFFS.open("/config.json", "w");
    if (!configFile) {
      Serial.println("failed to open config file for writing");
    }

    json.printTo(Serial);
    json.printTo(configFile);
    configFile.close();
    //end save
  }
  if (forceRestart)
  {
    Serial.println("Restarting...");
    ESP.restart();
    delay(5000);
  }
  Serial.println("local ip");
  Serial.println(WiFi.localIP());
}


void loop() {
  delay(delayMS);
  if (WiFi.status()!=WL_CONNECTED)
  {
    //reset and try again, or maybe put it to deep sleep
    ESP.restart();
  }


  // Delay between measurements.
  
  // Get temperature event and print its value.
  sensors_event_t event;
  dht.temperature().getEvent(&event);
  if (isnan(event.temperature)) {
    Serial.println(F("Error reading temperature!"));
  }
  else {
    Serial.print(F("Temperature: "));
    Serial.print(event.temperature);
    Serial.println(F("°C"));
  }
  // Get humidity event and print its value.
  dht.humidity().getEvent(&event);
  if (isnan(event.relative_humidity)) {
    Serial.println(F("Error reading humidity!"));
  }
  else {
    Serial.print(F("Humidity: "));
    Serial.print(event.relative_humidity);
    Serial.println(F("%"));
  }
}
Originally created by @pczekalski on GitHub (Jan 11, 2020). Original GitHub issue: https://github.com/tzapu/WiFiManager/issues/992 ### saveConfigCallback is not called in the scenario, where you configure STA but off-line (so you do not really connect, just pre-configure it and save). #### Hardware **WiFimanager Branch/Release:** - [X ] Master - [ ] Development **Esp8266/Esp32:** - [ ] ESP8266 - [ X] ESP32 **Hardware: ESP-12e, esp01, esp25** - [ ] ESP01 - [ ] ESP12 E/F/S (nodemcu, wemos, feather) - [X ] Other **ESP Core Version: 2.4.0, staging** - [ ] 2.3.0 - [X ] 2.4.0 - [ ] staging (master/dev) ### Description Assuming the manager starts in AP and exposes configuration portal, if you implement it the way presented in the AutoConnectWithFSParameters, then you enter blind configuration without being able to connect in STA to the configured infrastructure AP, the flag to trigger saveConfigCallback is never set thous won't let you save custom parameters. Meanwhile, saving of the SSID and password to the infrastructure AP is being saved thus it is inconsistent. Steps to reproduce: - start in AP mode (expose configuration portal) - connect to it, configure data for non-existing (or offline) infrastructure AP you want to connect to, - click save ### Code ```C++ #include <FS.h> #include <SPIFFS.h> #include <Arduino.h> #include <Adafruit_Sensor.h> #include <DHT.h> #include <DHT_U.h> #include <WiFi.h> #include <ESPAsyncWebServer.h> #include <ESPAsyncWiFiManager.h> #include <ArduinoJson.h> //Warning - only versions prior 6 are compatible (5.11) //#define formatSPIFFS //Force SPIFFS format //Local AP section #define APPASSWORD "alamakota" //DHT Sensor section #define DHTPIN 16 #define DHTTYPE DHT11 #define MQTTTopicCommon "/itsilesia/showroom/" #define MQTTTopicTemperature "/temperature/" #define MQTTTopicHumidity "/Humidity/" DHT_Unified dht(DHTPIN, DHTTYPE); uint32_t delayMS = 10000; //10s // Extra config parameters char mqtt_server[40]; char mqtt_port[6] = "1883"; char customDeviceId[10] = "dev0"; char mqtt_user[40]; char mqtt_pass[40]; //flag for saving data bool shouldSaveConfig = false; bool forceRestart = false; //services AsyncWebServer server(80); DNSServer dns; //Callbacks void saveConfigCallback () { Serial.println("Should save config"); shouldSaveConfig = true; } void setup() { Serial.begin(9600); dht.begin(); Serial.println(); Serial.println(); if (SPIFFS.begin()) { Serial.println("mounted file system"); if (SPIFFS.exists("/config.json")) { //file exists, reading and loading Serial.println("reading config file"); File configFile = SPIFFS.open("/config.json", "r"); if (configFile) { Serial.println("opened config file"); size_t size = configFile.size(); // Allocate a buffer to store contents of the file. std::unique_ptr<char[]> buf(new char[size]); configFile.readBytes(buf.get(), size); DynamicJsonBuffer jsonBuffer; JsonObject& json = jsonBuffer.parseObject(buf.get()); json.printTo(Serial); if (json.success()) { Serial.println("\nparsed json"); strcpy(mqtt_server, json["mqtt_server"]); strcpy(mqtt_port, json["mqtt_port"]); strcpy(customDeviceId, json["custom_device_id"]); strcpy(mqtt_user, json["mqtt_user"]); strcpy(mqtt_pass, json["mqtt_pass"]); } else { Serial.println("failed to load json config"); } } }else { Serial.println("No config file"); } } else { Serial.println("failed to mount FS"); SPIFFS.format(); } //Serial.println(customDeviceId); //Serial.println(mqtt_user); //Serial.println(mqtt_pass); // end reading config file AsyncWiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 40); AsyncWiFiManagerParameter custom_mqtt_port("port", "mqtt port", mqtt_port, 5); AsyncWiFiManagerParameter custom_device_id("deviceid", "device ID", customDeviceId, 10); AsyncWiFiManagerParameter custom_mqtt_user("user", "mqtt user", mqtt_user,40); AsyncWiFiManagerParameter custom_mqtt_pass("pass", "mqtt password", mqtt_pass,40); AsyncWiFiManager wifiManager(&server,&dns); wifiManager.setDebugOutput(false); wifiManager.setSaveConfigCallback(saveConfigCallback); wifiManager.addParameter(&custom_mqtt_server); wifiManager.addParameter(&custom_mqtt_port); wifiManager.addParameter(&custom_device_id); wifiManager.addParameter(&custom_mqtt_user); wifiManager.addParameter(&custom_mqtt_pass); wifiManager.setTimeout(180); if (!wifiManager.autoConnect("itSilesiaSensor", APPASSWORD)) { Serial.println("failed to connect and hit timeout"); delay(3000); //reset and try again, or maybe put it to deep sleep forceRestart = true; } strcpy(mqtt_server, custom_mqtt_server.getValue()); strcpy(mqtt_port, custom_mqtt_port.getValue()); strcpy(customDeviceId, custom_device_id.getValue()); strcpy(mqtt_user, custom_mqtt_user.getValue()); strcpy(mqtt_pass, custom_mqtt_pass.getValue()); // Work save parameters otherwise if configuring off-line!!!! shouldSaveConfig = true; // save parameters if (shouldSaveConfig) { Serial.println("saving config"); DynamicJsonBuffer jsonBuffer; JsonObject& json = jsonBuffer.createObject(); json["mqtt_server"] = mqtt_server; json["mqtt_port"] = mqtt_port; json["custom_device_id"] = customDeviceId; json["mqtt_user"] = mqtt_user; json["mqtt_pass"] = mqtt_pass; File configFile = SPIFFS.open("/config.json", "w"); if (!configFile) { Serial.println("failed to open config file for writing"); } json.printTo(Serial); json.printTo(configFile); configFile.close(); //end save } if (forceRestart) { Serial.println("Restarting..."); ESP.restart(); delay(5000); } Serial.println("local ip"); Serial.println(WiFi.localIP()); } void loop() { delay(delayMS); if (WiFi.status()!=WL_CONNECTED) { //reset and try again, or maybe put it to deep sleep ESP.restart(); } // Delay between measurements. // Get temperature event and print its value. sensors_event_t event; dht.temperature().getEvent(&event); if (isnan(event.temperature)) { Serial.println(F("Error reading temperature!")); } else { Serial.print(F("Temperature: ")); Serial.print(event.temperature); Serial.println(F("°C")); } // Get humidity event and print its value. dht.humidity().getEvent(&event); if (isnan(event.relative_humidity)) { Serial.println(F("Error reading humidity!")); } else { Serial.print(F("Humidity: ")); Serial.print(event.relative_humidity); Serial.println(F("%")); } } ```
kerem 2026-02-28 01:27:19 +03:00
Author
Owner

@tablatronix commented on GitHub (Jan 22, 2020):

yeah its not really a good callback and changed over time in its usage.

Use _shouldBreakAfterConfig it should be in the docs.

//if this is set, it will exit after config, even if connection is unsuccessful.
    void          setBreakAfterConfig(boolean shouldBreak);
<!-- gh-comment-id:577277695 --> @tablatronix commented on GitHub (Jan 22, 2020): yeah its not really a good callback and changed over time in its usage. Use _shouldBreakAfterConfig it should be in the docs. ```C++ //if this is set, it will exit after config, even if connection is unsuccessful. void setBreakAfterConfig(boolean shouldBreak); ```
Author
Owner

@tablatronix commented on GitHub (Jan 22, 2020):

I added to hotfixes readme, to clarify this

<!-- gh-comment-id:577280015 --> @tablatronix commented on GitHub (Jan 22, 2020): I added to hotfixes readme, to clarify this
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/WiFiManager#846
No description provided.