WiFiManager
WiFiManager copied to clipboard
Value for Checkboxes overwritten - "Advanced" example
Basic Infos
Hardware
WiFimanager Branch/Release:
- [ ] Master
- [x] Development
Esp8266/Esp32:
- [ ] ESP8266
- [x] ESP32
Hardware: ESP-12e, esp01, esp25
- [ ] ESP01
- [ ] ESP12 E/F/S (nodemcu, wemos, feather)
- [x] Other: TTGO T8
ESP Core Version: 2.4.0, staging
- [ ] 2.3.0
- [x] 2.4.0
- [ ] staging (master/dev)
Description
I've tried using the checkboxes (as in the "Advanced" example) to enable and disable things on my ESP. While doing that I figured out that once you disable a checkbox and exit the configuration or let the AP timeout, the value saved in the WiFiManagerParameter
is lost and the checkbox will not work again.
How to reproduce
- Open the "Advanced" example
- Enable the checkbox (line 30) and commented the radioboxes (lines 33f)
- Upload the sketch
- Connect to the AP
- In the
Params
, clicksave
without enabling the checkbox - Close the AP or let it timeout
- Open the AP again by pressing the button
- Try enabling the checkbox and saving
The value of the checkbox will remain empty even if it is checked
Sketch
"Advanced" example:
/**
* WiFiManager advanced demo, contains advanced configurartion options
* Implements TRIGGEN_PIN button press, press for ondemand configportal, hold for 3 seconds for reset settings.
*/
#include <WiFiManager.h> // https://github.com/tzapu/WiFiManager
#define TRIGGER_PIN 0
WiFiManager wm; // global wm instance
WiFiManagerParameter custom_field; // global param ( for non blocking w params )
void setup() {
WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP
Serial.begin(115200);
Serial.setDebugOutput(true);
delay(3000);
Serial.println("\n Starting");
pinMode(TRIGGER_PIN, INPUT);
// wm.resetSettings(); // wipe settings
// add a custom input field
int customFieldLength = 40;
// new (&custom_field) WiFiManagerParameter("customfieldid", "Custom Field Label", "Custom Field Value", customFieldLength,"placeholder=\"Custom Field Placeholder\"");
// test custom html input type(checkbox)
new (&custom_field) WiFiManagerParameter("customfieldid", "Custom Field Label", "Custom Field Value", customFieldLength,"placeholder=\"Custom Field Placeholder\" type=\"checkbox\""); // custom html type
// test custom html(radio)
// const char* custom_radio_str = "<br/><label for='customfieldid'>Custom Field Label</label><input type='radio' name='customfieldid' value='1' checked> One<br><input type='radio' name='customfieldid' value='2'> Two<br><input type='radio' name='customfieldid' value='3'> Three";
// new (&custom_field) WiFiManagerParameter(custom_radio_str); // custom html input
wm.addParameter(&custom_field);
wm.setSaveParamsCallback(saveParamCallback);
// custom menu via array or vector
//
// menu tokens, "wifi","wifinoscan","info","param","close","sep","erase","restart","exit" (sep is seperator) (if param is in menu, params will not show up in wifi page!)
// const char* menu[] = {"wifi","info","param","sep","restart","exit"};
// wm.setMenu(menu,6);
std::vector<const char *> menu = {"wifi","info","param","sep","restart","exit"};
wm.setMenu(menu);
// set dark theme
wm.setClass("invert");
//set static ip
// wm.setSTAStaticIPConfig(IPAddress(10,0,1,99), IPAddress(10,0,1,1), IPAddress(255,255,255,0)); // set static ip,gw,sn
// wm.setShowStaticFields(true); // force show static ip fields
// wm.setShowDnsFields(true); // force show dns field always
// wm.setConnectTimeout(20); // how long to try to connect for before continuing
wm.setConfigPortalTimeout(30); // auto close configportal after n seconds
// wm.setCaptivePortalEnable(false); // disable captive portal redirection
// wm.setAPClientCheck(true); // avoid timeout if client connected to softap
// wifi scan settings
// wm.setRemoveDuplicateAPs(false); // do not remove duplicate ap names (true)
// wm.setMinimumSignalQuality(20); // set min RSSI (percentage) to show in scans, null = 8%
// wm.setShowInfoErase(false); // do not show erase button on info page
// wm.setScanDispPerc(true); // show RSSI as percentage not graph icons
// wm.setBreakAfterConfig(true); // always exit configportal even if wifi save fails
bool res;
// res = wm.autoConnect(); // auto generated AP name from chipid
// res = wm.autoConnect("AutoConnectAP"); // anonymous ap
res = wm.autoConnect("AutoConnectAP","password"); // password protected ap
if(!res) {
Serial.println("Failed to connect or hit timeout");
// ESP.restart();
}
else {
//if you get here you have connected to the WiFi
Serial.println("connected...yeey :)");
}
}
void checkButton(){
// check for button press
if ( digitalRead(TRIGGER_PIN) == LOW ) {
// poor mans debounce/press-hold, code not ideal for production
delay(50);
if( digitalRead(TRIGGER_PIN) == LOW ){
Serial.println("Button Pressed");
// still holding button for 3000 ms, reset settings, code not ideaa for production
delay(3000); // reset delay hold
if( digitalRead(TRIGGER_PIN) == LOW ){
Serial.println("Button Held");
Serial.println("Erasing Config, restarting");
wm.resetSettings();
ESP.restart();
}
// start portal w delay
Serial.println("Starting config portal");
wm.setConfigPortalTimeout(120);
if (!wm.startConfigPortal("OnDemandAP","password")) {
Serial.println("failed to connect or hit timeout");
delay(3000);
// ESP.restart();
} else {
//if you get here you have connected to the WiFi
Serial.println("connected...yeey :)");
}
}
}
}
String getParam(String name){
//read parameter from server, for customhmtl input
String value;
if(wm.server->hasArg(name)) {
value = wm.server->arg(name);
}
return value;
}
void saveParamCallback(){
Serial.println("[CALLBACK] saveParamCallback fired");
Serial.println("PARAM customfieldid = " + getParam("customfieldid"));
}
void loop() {
checkButton();
// put your main code here, to run repeatedly:
}
Debug Messages
Starting
*WM: [3] allocating params bytes: 20
*WM: [2] Added Parameter: customfieldid
*WM: [1] AutoConnect
*WM: [1] No Credentials are Saved, skipping connect
*WM: [2] Starting Config Portal
*WM: [2] AccessPoint set password is VALID
*WM: [1] password
*WM: [3] WiFi station disconnect
*WM: [3] WiFi_enableSTA enable
*WM: [2] Disabling STA
*WM: [2] Enabling AP
*WM: [1] StartAP with SSID: AutoConnectAP
*WM: [1] SoftAP Configuration
*WM: [1] --------------------
*WM: [1] ssid: AutoConnectAP
*WM: [1] password: password
*WM: [1] ssid_len: 13
*WM: [1] channel: 1
*WM: [1] authmode: 3
*WM: [1] ssid_hidden:
*WM: [1] max_connection: 4
*WM: [1] country: CN
*WM: [1] beacon_interval: 100(ms)
*WM: [1] --------------------
*WM: [1] AP IP address: 192.168.4.1
*WM: [3] setupConfigPortal
*WM: [1] Starting Web Portal
*WM: [3] dns server started with ip: 192.168.4.1
*WM: [2] HTTP server started
*WM: [2] WiFi Scan completed in 2905 ms
*WM: [2] Config Portal Running, blocking, waiting for clients...
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [2] <- HTTP Root
*WM: [3] -> 192.168.4.1
*WM: [3] lastconxresulttmp: WL_IDLE_STATUS
*WM: [3] lastconxresult: WL_DISCONNECTED
*WM: [2] Scan is cached 7147 ms ago
*WM: [3] -> 192.168.4.1
*WM: [2] <- HTTP Param
*WM: [3] lastconxresulttmp: WL_IDLE_STATUS
*WM: [3] lastconxresult: WL_DISCONNECTED
*WM: [3] Sent param page
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [2] <- HTTP WiFi save
*WM: [3] Method: POST
*WM: [2] Parameters
*WM: [2] --------------------
*WM: [2] customfieldid:
*WM: [2] --------------------
[CALLBACK] saveParamCallback fired
PARAM customfieldid =
*WM: [3] Sent param save page
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [2] <- HTTP Exit
*WM: [3] configportal abort
*WM: [2] disconnect configportal
*WM: [2] restoring usermode STA
*WM: [2] wifi status: WL_DISCONNECTED
*WM: [2] wifi mode: STA
*WM: [1] config portal exiting
Failed to connect or hit timeout
Button Pressed
Starting config portal
*WM: [2] Starting Config Portal
*WM: [2] AccessPoint set password is VALID
*WM: [1] password
*WM: [3] WiFi station disconnect
*WM: [3] WiFi_enableSTA enable
*WM: [2] Disabling STA
*WM: [2] Enabling AP
*WM: [1] StartAP with SSID: OnDemandAP
*WM: [1] SoftAP Configuration
*WM: [1] --------------------
*WM: [1] ssid: OnDemandAP
*WM: [1] password: password
*WM: [1] ssid_len: 10
*WM: [1] channel: 1
*WM: [1] authmode: 3
*WM: [1] ssid_hidden:
*WM: [1] max_connection: 4
*WM: [1] country: CN
*WM: [1] beacon_interval: 100(ms)
*WM: [1] --------------------
*WM: [1] AP IP address: 192.168.4.1
*WM: [3] setupConfigPortal
*WM: [1] Starting Web Portal
*WM: [3] dns server started with ip: 192.168.4.1
*WM: [2] HTTP server started
*WM: [2] WiFi Scan completed in 3106 ms
*WM: [2] Config Portal Running, blocking, waiting for clients...
*WM: [2] Portal Timeout In 115 seconds
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [2] <- HTTP Root
*WM: [3] -> 192.168.4.1
*WM: [3] lastconxresulttmp: WL_IDLE_STATUS
*WM: [3] lastconxresult: WL_DISCONNECTED
*WM: [2] Scan is cached 8867 ms ago
*WM: [3] -> 192.168.4.1
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [2] <- HTTP Param
*WM: [3] lastconxresulttmp: WL_IDLE_STATUS
*WM: [3] lastconxresult: WL_DISCONNECTED
*WM: [3] Sent param page
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [2] <- HTTP WiFi save
*WM: [3] Method: POST
*WM: [2] Parameters
*WM: [2] --------------------
*WM: [2] customfieldid:
*WM: [2] --------------------
[CALLBACK] saveParamCallback fired
PARAM customfieldid =
*WM: [3] Sent param save page
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [3] -> connectivitycheck.platform.hicloud.com
*WM: [2] <- Request redirected to captive portal
*WM: [2] <- HTTP WiFi save
*WM: [3] Method: POST
*WM: [2] Parameters
*WM: [2] --------------------
*WM: [2] customfieldid:
*WM: [2] --------------------
[CALLBACK] saveParamCallback fired
PARAM customfieldid =
*WM: [3] Sent param save page
Any idea what could be causing this? I'm trying to understand the library atm to see if I find the issue and am possibly able to fix it.
So the issue seems to lie with this method:
void WiFiManager::doParamSave(){
// @todo use new callback for before paramsaves, is this really needed?
if ( _presavecallback != NULL) {
_presavecallback();
}
//parameters
if(_paramsCount > 0){
DEBUG_WM(DEBUG_VERBOSE,F("Parameters"));
DEBUG_WM(DEBUG_VERBOSE,FPSTR(D_HR));
for (int i = 0; i < _paramsCount; i++) {
if (_params[i] == NULL || _params[i]->_length == 0) {
DEBUG_WM(DEBUG_ERROR,"[ERROR] WiFiManagerParameter is out of scope");
break; // @todo might not be needed anymore
}
//read parameter from server
String name = (String)FPSTR(S_parampre)+(String)i;
String value;
if(server->hasArg(name)) {
value = server->arg(name);
} else {
value = server->arg(_params[i]->getID());
}
//store it in params array
value.toCharArray(_params[i]->_value, _params[i]->_length+1); // length+1 null terminated
DEBUG_WM(DEBUG_VERBOSE,(String)_params[i]->getID() + ":",value);
}
DEBUG_WM(DEBUG_VERBOSE,FPSTR(D_HR));
}
if ( _saveparamscallback != NULL) {
_saveparamscallback();
}
}
and the saveParamCallback
in the example. I added two lines to reset the value afterwards in the example:
void saveParamCallback(){
Serial.println("[CALLBACK] saveParamCallback fired");
Serial.println("PARAM customfieldid = " + getParam("customfieldid"));
String value = "Custom Field Value";
custom_field.setValue(value.c_str(), value.length());
}
I have the same problem. Someone managed to solve?
is it an issue with ids? There was a similar issue reported
iirc, this was indeed an issue with the IDs. I think #1130 fixed it. Though it's been a while so no guarantees.
I know this thread is old but i run into the same issue. I have some checkboxes with const hidden ip address but if the user don't enable the check box the value of this uncheck checkbox will be overwritten with an empty string. So I don't thing this issue is fixed.
Maybe its not important but all parameters are global.
main.cpp
const char* title_str = "<br/><label style='font-weight: bold; font-size: 25px;'>NTP Server Auswahl</label><br/>";
const char* lineBreak_str = "<br/><br />";
const char* tu_berlin_ip = "130.149.7.7";
const char* tu_dresden_ip = "141.76.32.160";
const char* t_online_ip = "194.25.134.196";
const char* custom_0_ip = "000.000.000.000";
new (&title) WiFiManagerParameter (title_str);
new (&tu_berlin_ntp_server) WiFiManagerParameter("tu_berlin_ntp_server", "TU Berlin", tu_berlin_ip, strlen(tu_berlin_ip), checkbox_unchecked, WFM_LABEL_AFTER); // custom html input for tu berlin ntp server
new (&tu_dresden_ntp_server) WiFiManagerParameter("tu_dresden_ntp_server", "TU Dresden", tu_dresden_ip, strlen(tu_dresden_ip), checkbox_unchecked, WFM_LABEL_AFTER); // custom html input for tu dresden ntp server
new (&t_online_ntp_server) WiFiManagerParameter("t_online_ntp_server", "T-Online", t_online_ip, strlen(t_online_ip),checkbox_checked, WFM_LABEL_AFTER); // custom html input for t-online ntp server
new (&lineBreak) WiFiManagerParameter (lineBreak_str);
new (&custom_0_ntp_server) WiFiManagerParameter("custom_0_ntp_server", "NTP Server IP:", NULL, strlen(custom_0_ip), "placeholder=\"000.000.000.000\"");
wm.addParameter(&title);
wm.addParameter(&tu_berlin_ntp_server);
wm.addParameter(&tu_dresden_ntp_server);
wm.addParameter(&t_online_ntp_server);
wm.addParameter(&lineBreak);
wm.addParameter(&custom_0_ntp_server);
wm.setPreSaveParamsCallback(saveParamCallback);
wm.setSaveParamsCallback(saveParamCallback);
callback function
const char* getParam(const char* name){
//read parameter from server, for customhmtl input
if (wm.server->hasArg(name)) {
String value = wm.server->arg(name);
return value.length() > 0 ? value.c_str() : nullptr;
}
else {
return nullptr;
}
}
void saveParamCallback(void) {
static char* lost_ips[3];
static int lost_len[3];
uint8_t lost_cnt = 0;
static bool preSave = true;
preSave ? Serial.println("[CALLBACK] savePreParamCallback fired") : Serial.println("[CALLBACK] saveParamCallback fired");
preSave = ! preSave;
for (uint8_t i = 0; i < wm.getParametersCount(); i++) {
const char* name = wm.getParameters()[i]->getID();
if (name) {
const char* param = getParam(name);
if (param) {
Serial.println(String(i) + " was checked");
Serial.print("PARAM[" + String(name) + "]: ");
Serial.println(param);
// hier dann die ntp client objecte erstellen
}
else {
const char* value = wm.getParameters()[i]->getValue();
int length = wm.getParameters()[i]->getValueLength();
Serial.println(String(i) + " was nullptr");
Serial.println("val: " + String(value));
Serial.println("len: " + String(length));
//wm.getParameters()[i]->setValue(value,length);
}
}
else {
Serial.println(String(i) + " has no id");
}
Serial.println();
}
}
LOG output
// const hidden ip addresses
130.149.7.7
141.76.32.160
194.25.134.196
// before the data are saved from webserver
[CALLBACK] savePreParamCallback fired
0 has no id
1 was nullptr
val: 130.149.7.7
len: 11
2 was nullptr
val: 141.76.32.160
len: 13
3 was checked
PARAM[t_online_ntp_server]: PARAM[t_online_ntp_server]:
4 has no id
5 was nullptr
val:
len: 15
// after the data are saved from webserver
[CALLBACK] saveParamCallback fired
0 has no id
1 was nullptr
val:
len: 11
2 was nullptr
val:
len: 13
3 was checked
PARAM[t_online_ntp_server]: PARAM[t_online_ntp_server]:
4 has no id
5 was nullptr
val:
len: 15