WiFiManager: Char* conversion for default_value errornous when adding WiFiManagerParameter();
Basic Infos
Hardware
WiFimanager Branch/Release:
- Master
- Development (OTA)
Esp8266/Esp32:
- ESP8266
- ESP32
Hardware: ESP-12e, esp01, esp25
- ESP01
- ESP12 E/F/S (nodemcu, wemos, feather)
- Other
ESP Core Version: 2.4.0, staging
- 2.3.0
- 2.4.0
- 2.6.3
- staging (master/dev)
Description
Hi,
When we add a custom WiFiManagerParameter with a normal char* to initialize the default value it has a strange conversion error. Following code:
char mqtt_broker[12] = "192.168.1.108";
custom_mqtt_broker = WiFiManagerParameter("mqttbroker", "MQTT Broker", mqtt_broker, sizeof(mqtt_broker));
Serial.println(custom_mqtt_broker.getValue());
Serial.println(mqtt_broker);`
puts out on the Serial:
⸮⸮⸮?168.1.10
192.168.1.108
Settings in IDE
Module: NodeMcu, Wemos D1
Additional libraries:
Sketch
#include <FS.h> //this needs to be first, or it all crashes and burns...
#include <ArduinoJson.h> //https://github.com/bblanchon/ArduinoJson
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager WiFi Configuration Magic
#include <PubSubClient.h>
#include <ESP8266WiFi.h>
#define USEOTA
// enable OTA
#ifdef USEOTA
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#endif
#define TRIGGER_PIN 0 //Pin used to start AccessPoint to configure device - Just ground GPIO for 2 seconds
WiFiManager wm;
ESP8266WebServer server(80);
WiFiClient espClient;
PubSubClient client(espClient);
long lastReconnectAttempt = 0;
boolean reconnect() {
Serial.println("attempting connecting to mqtt");
if (client.connect("arduinoClient")) {
Serial.println("MQTT CONNECTED");
// Once connected, publish an announcement...
client.publish("outTopic", "hello world");
// ... and resubscribe
client.subscribe("inTopic");
}
return client.connected();
}
//############################################# CUSTOM PARAMETERS FOR THE WIFI MANAGER ##########################################
//char mqtt_server[40] = "0.0.0.0";
//char mqtt_topicIN[80] ="IOT_Device/IN";
//char mqtt_topicOUT[80] ="IOT_Device/OUT";
//char mqtt_port[6] = "1883";
char output[2] = "2";
char wifi_enc[40];
char entity_version[40];
char mqtt_port[40] = "1883";
char mqtt_broker[12] = " ";
char mqtt_pwd[40];
char session_key[40];
char entity_name[40];
char entity_type[40];
char entity_id[40];
char mqtt_retain[40];
char mqtt_qos[40];
//flag for saving data
bool shouldSaveConfig = false;
//WiFiManagerParameter custom_mqtt_server("server", "Server IP", mqtt_server, 40);
//WiFiManagerParameter custom_mqtt_port("port", "Port", mqtt_port, 6);
//WiFiManagerParameter custom_mqtt_topicIN("topicIn", "Input Topic", mqtt_topicIN, 80);
//WiFiManagerParameter custom_mqtt_topicOUT("topicOut", "Output Topic", mqtt_topicOUT, 80);
//WiFiManagerParameter custom_mqtt_messages("messages", "Messages Topic", mqtt_topicOUT, 80);
WiFiManagerParameter custom_output("output", "output", output, 2);
WiFiManagerParameter custom_mqtt_broker("mqttbroker", "MQTT Broker", mqtt_broker, 12);
WiFiManagerParameter custom_mqtt_pwd("mqttpwd", "MQTT password", mqtt_pwd, 40);
WiFiManagerParameter custom_session_key("sessionkey", "Session Key", session_key, 40);
WiFiManagerParameter custom_entity_name("entityname", "Entity Name", entity_name, 40);
WiFiManagerParameter custom_entity_type("entitytype", "Entitiy Type", entity_type, 40);
WiFiManagerParameter custom_wifi_enc("wifienc", "Wifi Enc", wifi_enc, 40);
WiFiManagerParameter custom_entity_version("entityversion", "Entity Version", entity_version, 40);
WiFiManagerParameter custom_mqtt_port("mqttport", "MQTT Port", mqtt_port, 40);
WiFiManagerParameter custom_entity_id("entityid", "Entitiy ID", entity_id, 40);
WiFiManagerParameter custom_mqtt_retain("mqttretain", "MQTT Retain", mqtt_retain, 40);
WiFiManagerParameter custom_mqtt_qos("mqttqos", "MQTT QoS", mqtt_qos, 40);
//###############################################################################################################################
//################################################### GENERAL VARIABLES #########################################################
bool blockWM = true; // Change this to false if you want your code to continue to run on the loop void even if you are not conected to any wifi.
//###############################################################################################################################
void saveConfigCallback() {
}
void saveParamCallback() {
Serial.println("****************Should save params");
shouldSaveConfig = true;
if (shouldSaveConfig) {
Serial.println("saving config");
//mqtt_broker = custom_mqtt_broker.getValue();
strcpy(mqtt_broker, custom_mqtt_broker.getValue());
DynamicJsonDocument json(1024);
//mqtt_broker = (char*) custom_mqtt_broker.getValue();
json["output"] = output;
json["mqtt_broker"] = mqtt_broker;
json["mqtt_pwd"] = mqtt_pwd;
json["session_key"] = session_key;
json["entity_name"] = entity_name;
json["entity_type"] = entity_type;
json["wifi_enc"] = wifi_enc;
json["entity_version"] = entity_version;
json["mqtt_port"] = mqtt_port;
json["entity_id"] = entity_id;
json["mqtt_retain"] = mqtt_retain;
json["mqtt_qos"] = mqtt_qos;
// json["ip"] = WiFi.localIP().toString();
// json["gateway"] = WiFi.gatewayIP().toString();
// json["subnet"] = WiFi.subnetMask().toString();
File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) {
Serial.println("failed to open config file for writing");
}
serializeJson(json, Serial);
serializeJson(json, configFile);
//json.printTo(Serial);
//json.printTo(configFile);
configFile.close();
//end save
shouldSaveConfig = false;
}
}
void handleNotFound()
{
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i = 0; i < server.args(); i++)
{
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
}
/*
This void sets the device with the WiFiManager from tzapu with custom parameters.
Needs to be called only in the setup void.
*/
void setupDeviceWM()
{
//Serial.println("pppppppppppppppppp");
//Serial.println(mqtt_broker);
// callbacks
wm.setConfigPortalBlocking(blockWM);
String ssid = "IOT_ESP_" + String(ESP.getChipId());
if (wm.autoConnect(ssid.c_str()))
{
//if you get here you have connected to the WiFi
Serial.println("Connected to wifi network!");
Serial.println(ssid);
//Serial.println(mqtt_broker);
//Serial.println(custom_mqtt_broker.getValue());
-Serial.println(WiFi.localIP());
WiFi.mode(WIFI_STA);
wm.startWebPortal();
}
else
{
Serial.println("Could not connect with WiFi!");
}
// call the code down to activate wifi so users can configure the device, event if it's connected to the local network
//wm.startConfigPortal("IOT_Device");
//
server.onNotFound(handleNotFound);
server.begin(); // declare this at the beggining of the code => ESP8266WebServer server(80);
}
void bindServerCallback() {
wm.server->on("/custom", handleRoute);
// wm.server->on("/info",handleRoute); // can override wm!
wm.server->on("/LED", HTTP_POST, handleLED); // Call the 'handleLED' function when a POST request is made to URI "/LED"
}
void handleRoute() {
Serial.println("[HTTP] handle route");
wm.server->send(200, "text/html", "<iframe name=\"dummyframe\" id=\"dummyframe\" style=\"display: none;\"></iframe><form action=\"/LED\" target=\"dummyframe\" method=\"POST\"><input type=\"submit\" value=\"Toggle LED\"></form>");
}
void handleLED() { // If a POST request is made to URI /LED
digitalWrite(atoi(output), !digitalRead(atoi(output))); // Change the state of the LED
server.sendHeader("Location", "/"); // Add a header to respond with a new location for the browser to go to the home page again
server.send(303); // Send it back to the browser with an HTTP status 303 (See Other) to redirect
}
/*
This void needs to be called in the loop void so it can handle the WM and the webportal.
*/
void loopDeviceWM()
{
wm.process();
server.handleClient();
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
}
int setupSpiffs() {
//read configuration from FS json
Serial.println("mounting FS...");
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);
DynamicJsonDocument jsonBuffer(1024);
//DynamicJsonBuffer jsonBuffer;
deserializeJson(jsonBuffer, buf.get());
//JsonObject& json = jsonBuffer.parseObject(buf.get());
serializeJson(jsonBuffer, Serial);
//json.printTo(Serial);
if (!jsonBuffer.isNull()) {
Serial.println("\nparsed json");
//Serial.println(custom_mqtt_broker.getValue());
strcpy(wifi_enc, jsonBuffer["wifi_enc"]);
strcpy(entity_version, jsonBuffer["entity_version"]);
strcpy(mqtt_port, jsonBuffer["mqtt_port"]);
strcpy(output, jsonBuffer["output"]);
strcpy(mqtt_broker, jsonBuffer["mqtt_broker"]);
strcpy(mqtt_pwd, jsonBuffer["mqtt_pwd"]);
strcpy(session_key, jsonBuffer["session_key"]);
strcpy(entity_name, jsonBuffer["entity_name"]);
strcpy(entity_type, jsonBuffer["entity_type"]);
strcpy(entity_id, jsonBuffer["entity_id"]);
strcpy(mqtt_retain, jsonBuffer["mqtt_retain"]);
strcpy(mqtt_qos, jsonBuffer["mqtt_qos"]);
//Serial.println("ooooooooooooooo");
Serial.println("loaded Json");
Serial.println("now mqtt broker is: ");
Serial.println(mqtt_broker);
return 0;
} else {
Serial.println("failed to load json config");
return 1;
}
configFile.close();
}
}
else
{
Serial.println("config json doesnt exist");
return 1;
}
} else {
Serial.println("failed to mount FS");
return 1;
}
//end read
}
void setup()
{
pinMode(atoi(output), OUTPUT);
Serial.begin(115200);
delay(3000);
//diese funktion gibt 0 zurück wenn eine config json da ist.
if(setupSpiffs() == 0){
Serial.println("SO, NOW:");
Serial.println(mqtt_broker);
custom_mqtt_broker = WiFiManagerParameter("mqttbroker", "MQTT Broker", mqtt_broker, sizeof(mqtt_broker));
}
else
{
}
//an diesem punkt sind die parameter entweder leer weil keine config existiert, oder voll weil config da war.
wm.setWebServerCallback(bindServerCallback);
wm.setSaveParamsCallback(saveParamCallback);
//wm.addParameter(&custom_output);
wm.addParameter(&custom_mqtt_broker);
//wm.addParameter(&custom_mqtt_pwd);
//wm.addParameter(&custom_session_key);
//wm.addParameter(&custom_entity_name);
//wm.addParameter(&custom_entity_type);
//wm.addParameter(&custom_wifi_enc);
//wm.addParameter(&custom_entity_version);
//wm.addParameter(&custom_mqtt_port);
//wm.addParameter(&custom_entity_id);
//wm.addParameter(&custom_mqtt_retain);
//wm.addParameter(&custom_mqtt_qos);
// Set cutom menu via menu[] or vector
// const char* menu[] = {"wifi","wifinoscan","info","param","close","sep","erase","restart","exit"};
// wm.setMenu(menu,9); // custom menu array must provide length
std::vector<const char *> menu = {"wifi", "info", "param", "update", "close", "sep", "erase", "restart", "exit"};
wm.setMenu(menu); // custom menu, pass vector
// set country
wm.setCountry("US"); // setting wifi country seems to improve OSX soft ap connectivity, may help others as well
Serial.println("Setup mode...");
//wifiManager.resetSettings();
setupDeviceWM();
pinMode(TRIGGER_PIN, INPUT);
#ifdef USEOTA
ArduinoOTA.begin();
#endif
wm.setClass("invert");
Serial.println("-------------");
Serial.println(custom_mqtt_broker.getValue());
Serial.println(String(mqtt_broker));
Serial.println(mqtt_broker);
Serial.println(session_key);
client.setServer(mqtt_broker, atoi(mqtt_port));
client.setCallback(callback);
lastReconnectAttempt = 0;
}
void loop()
{
#ifdef USEOTA
ArduinoOTA.handle();
#endif
loopDeviceWM();
if ( digitalRead(TRIGGER_PIN) == LOW ) {
delay(2000);
if ( digitalRead(TRIGGER_PIN) == LOW ) {
Serial.println("BUTTON PRESSED");
//wm.setConfigPortalTimeout(140);
// disable captive portal redirection
// wm.setCaptivePortalEnable(false);
if (!wm.startConfigPortal("OnDemandAP", "12345678")) {
Serial.println("failed to connect and hit timeout");
delay(3000);
}
}
}
if (!client.connected()) {
long now = millis();
if (now - lastReconnectAttempt > 5000) {
lastReconnectAttempt = now;
// Attempt to reconnect
if (reconnect()) {
lastReconnectAttempt = 0;
}
}
} else {
// Client connected
client.loop();
}
}```
### Debug Messages
mounted file system
reading config file
opened config file
{“output”:“2”,“mqtt_broker”:“192.168.1.108”,“mqtt_pwd”:“”,“session_key”:“”,“entity_name”:“”,“entity_type”:“”,“wifi_enc”:“”,“entity_version”:“”,“mqtt_port”:“1883”,“entity_id”:“”,“mqtt_retain”:“”,“mqtt_qos”:“”}
parsed json
loaded Json
now mqtt broker is:
192.168.1.108
SO, NOW:
192.168.1.108
*WM: [3] allocating params bytes: 20
*WM: [2] Added Parameter: mqttbroker
*WM: [1] <form action='/wifi' method='get'><button>Configure WiFi</button></form>
<form action='/param' method='get'><button>Setup</button></form>
<form action='/update' method='get'><button>Update</button></form>
<form action='/close' method='get'><button>Close</button></form>
<form action='/erase' method='get'><button class='D'>Erase</button></form>
<form action='/restart' method='get'><button>Restart</button></form>
<form action='/exit' method='get'><button>Exit</button></form>
Setup mode… *WM: [1] AutoConnect *WM: [2] esp_wifi_set_country: US *WM: [1] AutoConnect: ESP Already Connected *WM: [3] STA static IP: *WM: [2] setSTAConfig static ip not set, skipping *WM: [1] AutoConnect: SUCCESS *WM: [1] STA IP Address: 192.168.1.109 Connected to wifi network! IOT_ESP_6184038 192.168.1.109 *WM: [1] Starting Web Portal *WM: [3] dns server started with ip: *WM: [2] HTTP server started *WM: [2] WiFi Scan completed in 2182 ms
⸮⸮⸮?168.1.10 192.168.1.108 192.168.1.108
attempting connecting to mqtt
About this issue
- Original URL
- State: open
- Created 4 years ago
- Reactions: 1
- Comments: 53 (3 by maintainers)
Commits related to this issue
- #1050 prevent copy assignment of param constructor — committed to tzapu/WiFiManager by tablatronix 4 years ago
ooh
WiFiManagerParameter is missing a copy assignment operator. https://en.cppreference.com/w/cpp/language/copy_assignment
Doing this:
WiFiManagerParameter custom_mqtt_broker("mqttbroker", "MQTT Broker", mqtt_broker, 20);
is different from doing this:
custom_mqtt_broker = WiFiManagerParameter("mqttbroker", "MQTT Broker", mqtt_broker, 20);
what happens in that single line is this:
custom_mqtt_broker
, c++ generates a assignment operator where each value is copied copied, but remember… char pointers is a address, only the address get’s copied, not the string!_value
is not valid anymore, also not in the copied version because they point to the same deleted address.Hope that clarifies…
Is there any reason you want re-assign custom_mqtt_broker? Some comments are in German and although I got taught German at school 25 years ago it’s not that good anymore…
Not sure what compiler you are using but with c++11 you can do this:
WiFiManagerParameter& operator=(const WiFiManagerParameter&) = delete;
so you don’t have to set it private if you just want to prevent all users (including the class self) prevent using the copy assignment.
@dontsovcmc yes you are absolutely right, setValue does not release memory of previously allocated memory… I guess that´s why we love immutables 😃
ok - above sketch never saved changed parameters to spiff… could not work anyway… but please try this one. there is an obvious serial print saying what i expect and this is not matching up with what i get at the end of the setup - so as you can see “mqtt_broker” is alright - i can use this to connect … but custom_mqtt_broker.getValue() is not. and that also shows on the portal making it unusable.
I have no idea, your sketch still contains other stuff not needed to reproduce, hell you have 2 webservers running…
You need to let c++ decide for the size: So use ‘char mqtt_broker[] = “192.168.1.108”;’ And male sure that the length parameter for WiFiManagerParameter is large enough for a An IP address: 16 chars