Code Monkey home page Code Monkey logo

configmanager's People

Contributors

baphled avatar boneskull avatar canadaduane avatar cgmckeever avatar d42ohpaz avatar dadone89 avatar evemawrey avatar frtrillo avatar ivankravets avatar jonsilver avatar mfalkvidd avatar nrwiersma avatar per1234 avatar robertoostenveld avatar unimogman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

configmanager's Issues

Remove jQuery from Settings Example

The save_config_demo example has a settings.html file that uses a CDN-hosted jQuery to update the form and post form results back to the ESP/ConfigManager API.

Currently, requiring CDN-hosted jQuery makes for a less-than-ideal experience. In some cases, internet is not available, and it would be unfortunate if that meant additional settings could not be set between a user and their device.

change WIFI connect settings

Hi,
Given that the AP becomes no longer available after connecting the device to WIFI, is there a way to change which WIFI i'm connecting to, in a environment where there are multiple possible WIFIs to connect to?

Thanks!

no matching function for call to 'ConfigManager::addParameter(const char [5], char (*)[20], int)

Hi i'm using Platformio and would like to use your library for an ESP8266, but i can't use addParameter for strings, because i will get this error:

src/main.cpp:15:56: error: no matching function for call to 'ConfigManager::addParameter(const char [5], char (*)[20], int)'

Here is the whole error log of the compiling:

src/main.cpp:15:56: note: candidates are:
In file included from src/main.cpp:1:0:
lib/ConfigManager/ConfigManager.h:107:10: note: template<class T> void ConfigManager::addParameter(const char*, T*)
void addParameter(const char *name, T *variable) {
^
lib/ConfigManager/ConfigManager.h:107:10: note:   template argument deduction/substitution failed:
src/main.cpp:15:56: note:   candidate expects 2 arguments, 3 provided
configManager.addParameter("name", &config.name, 20);
^
In file included from src/main.cpp:1:0:

lib/ConfigManager/ConfigManager.h:110:10: note: void ConfigManager::addParameter(const char*, char*, size_t)
void addParameter(const char *name, char *variable, size_t size) {
^
lib/ConfigManager/ConfigManager.h:110:10: note:   no known conversion for argument 2 from 'char (*)[20]' to 'char*'
*** [.pioenvs/nodemcuv2/src/main.o] Error 1

If i'm commenting out the line configManager.addParameter("name", &config.name, 20); can i compile and use your library without any problems. But then i can't use strings/chars :(

Here is my main.cpp

#include "ConfigManager.h"

struct Config {
    char name[20];
    bool enabled;
    int8 hour;
} config;

ConfigManager configManager;

void setup() {
    // Setup config manager
    configManager.setAPName("Demo");
    configManager.setAPFilename("/index.html");
    configManager.addParameter("name", &config.name, 20);
    configManager.addParameter("enabled", &config.enabled);
    configManager.addParameter("hour", &config.hour);
    configManager.begin(config);

    //
}

void loop() {
    configManager.loop();
}

Can you help find out the problem and/or are you be able to help me for this problem?

Request! Single Page web interface

Hi,

I think single page would be better for user experience since no need to remember to type .../settings.html to get to config page.

Unless, I missing something. After connect to wifi network, I type local IP (http://192.168.1.137) it still show Wifi Details page. I have to type settings.html to get to config.

I see you have AP and API mode. Why dont we just show settings page by default when we are in API mode.

I think passing mode: ap or api to json data and using this mode to hide/show wifi/settings div on single page. I have no idea how to edit the code to pass this mode to browser.

BTW, I also try to change configHTMLFile = "/index.html" and rename original settings.html to index.html hoping it will show settings page be default but it still show wifi details page which I rename it to wifi.html which is weird. It seems it doesn't matter which mode web server will start in ap mode (I set setAPFilename("/wifi.html"))

Thank you in advance,
Sam

PS: Lines with **....** were changed from example

#include "ConfigManager.h"

const char mimeHTML[] PROGMEM = "text/html";
**const char *configHTMLFile = "/index.html";**

struct Config {
  char name[255];
  bool enabled;

  char mqtt_host[255];
  char mqtt_port[10];
  char mqtt_username[255];
  char mqtt_password[255];
  char mqtt_topic[255];
} config;

struct Metadata {
  int8_t version;
} meta;

ConfigManager configManager;

void createCustomRoute(WebServer *server) {
  **server->on("/", HTTPMethod::HTTP_GET, [server](){**
    SPIFFS.begin();

    File f = SPIFFS.open(configHTMLFile, "r");
    if (!f) {
      Serial.println(F("file open failed"));
      server->send(404, FPSTR(mimeHTML), F("File not found"));
      return;
    }

    server->streamFile(f, FPSTR(mimeHTML));

    f.close();
  });
}

void setup() {
  Serial.begin(115200);
  Serial.println("");

  meta.version = 3;


  // Setup config manager
  configManager.setAPName("Demo");
  **configManager.setAPFilename("/wifi.html");**

  configManager.addParameter("name", config.name, 255);

  configManager.addParameter("mqtt_host", config.mqtt_host, 255);
  configManager.addParameter("mqtt_port", config.mqtt_port, 10);
  configManager.addParameter("mqtt_username", config.mqtt_username, 255);
  configManager.addParameter("mqtt_password", config.mqtt_password, 255);
  configManager.addParameter("mqtt_topic", config.mqtt_topic, 255);

  configManager.addParameter("enabled", &config.enabled);
  configManager.addParameter("version", &meta.version, get);

  configManager.setAPICallback(createCustomRoute);

  configManager.begin(config);
  Serial.print("ESP MODE:");
}

void loop() {
  configManager.loop();
}

Clear-text passwords exposed in GET api

The GET api passes the contents of all custom field to the client in clear text. Any custom fields which carry sensitive information, e.g. MQTT broker passwords, are therefore easy security breach targets.

I previously suggested:

  1. implement an optional flag on custom fields which requests that some sort of two-way encryption/hashing be used to store and retrieve the custom field
  2. the GET api doesn't bother decrypting these fields before sending to the client

However, I think it might be sufficient to still store password fields in clear text but send them obscured by filling the field's buffer with asterisks *.

How do you feel about that Nick?

Continued from previous discussion in issue #11

Cannot save config bool on v1.5.1

Hi there,

Merry Christmas :)
I just upgrade to v1.5.1 and try to add bool parameter and int parameter to config but it bool param won't save, int param OK.

EDIT: I found issue with main.js which is not create json data properly.
Here the code I edit. (I'm not expert in anyway so, wait for developer to come up with better solution lol)

  $.fn.serializeObject = function() {
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {
      var input = document.getElementsByName(this.name);
      var value = this.value;
      var dataType = input[0].getAttribute("data-type");
      if (dataType == "number") value = parseFloat(value);
      //The following line was added
      if (dataType == "bool") {
		  value = (value=="true" || value==1)? true:false;
      }  
      //End
      if (o[this.name]) {
        if (!o[this.name].push) {
          o[this.name] = [o[this.name]];
        }
        o[this.name].push(value || '');
      } else {
        o[this.name] = (value==null) ? '' : value; // This line was changed
      }
    });
    return o;
  };

ArduinoJson 6 incompatibility

The library should either be updated to be compatible with breaking changes in ArduinoJson 6, or the documentation augmented to advise that ArduinoJson 5 be used.
In the meantime, for anyone reading this who uses PlatformIO, you can specify explicit use of the last version of ArduinoJson 5 by adding the following to platformio.ini:

lib_deps =
    [email protected]

Lost code in ConfigParameter

There is a cb function passed, but it does not appear to be used or documented. Is this old code that was never completed or was removed? I can do a PR to clear, if so -- otherwise, with some words, I can make a PR for its use ... ?

https://github.com/nrwiersma/ConfigManager/blob/master/src/ConfigManager.h#L75
ConfigParameter.toJson

    ConfigParameter(const char *name, T *ptr, ParameterMode mode = both, std::function<void(const char*)> cb = NULL) {
        this->name = name;
        this->ptr = ptr;
        this->cb = cb;
        this->mode = mode;
    }

...
    void toJson(JsonObject *json) {
        json->set(name, *ptr);

        if (cb) {
            cb(name);
        }
    }

addParameter definitions don't appear to have the cb

    template<typename T>
    void addParameter(const char *name, T *variable) {
        parameters.push_back(new ConfigParameter<T>(name, variable));
    }
    template<typename T>
    void addParameter(const char *name, T *variable, ParameterMode mode) {
        parameters.push_back(new ConfigParameter<T>(name, variable, mode));
    }
    void addParameter(const char *name, char *variable, size_t size) {
        parameters.push_back(new ConfigStringParameter(name, variable, size));
    }
    void addParameter(const char *name, char *variable, size_t size, ParameterMode mode) {
        parameters.push_back(new ConfigStringParameter(name, variable, size, mode));
    }

Compile error - simple.ino

I get the following compile error

C:\Users\Rudy\Documents\Arduino\libraries\ConfigManager-master\examples\simple\simple.ino: In function 'void setup()':

simple:10: error: 'configManager' was not declared in this scope

 configManager.setAPName("Demo");

 ^

C:\Users\Rudy\Documents\Arduino\libraries\ConfigManager-master\examples\simple\simple.ino: In function 'void loop()':

simple:20: error: 'configManager' was not declared in this scope

 configManager.loop();

 ^

v3 tracking issue

This issue will be used to track to work on v3 of ConfigManager. The idea will evolve and be discussed here.

The ideas around this are from the collaboration between @nrwiersma and @cgmckeever.

General Idea

Split ConfigManager into roughly 3 parts:

  • Configuration Management
  • Wifi Management
  • HTTP interaction

When the Wifi and HTTP sections can we turned off or a custom class used to suit the needs of the user, however a "simple" option should remain leading to the use of ConfigManager as it exists today. This can be achieved using Abstract Classes (interfaces) around the Wifi and HTTP sections.

Questions

  • If HTTP is turned off, how does Wifi Management work. We cannot set the ssid and password?

reading and writing from struct config data

Hi,
I'm trying to read and write from the config structured data. Am I missing something in the implementation here.
Please see example code below:

`
#include <ConfigManager.h>
ConfigManager configManager;
struct Config {
char name[20];
char setting_autoupdate[1];
char setting_mqttdest[15];
bool enabled;
int8 hour;
char password[20];
} config;

struct Metadata {
int8_t version;
} meta;

setup() {
configManager.setAPFilename("/ap-index.html");
configManager.addParameter("name", config.name, 20);
configManager.addParameter("enabled", &config.enabled);
configManager.addParameter("hour", &config.hour);
configManager.addParameter("password", config.password, 20, set);
configManager.addParameter("version", &meta.version, get);
configManager.addParameter("setting_autoupdate", config.setting_autoupdate, 1);
configManager.addParameter("setting_mqttdest", config.setting_mqttdest, 15);
configManager.begin(config);

if (strlen(config.setting_autoupdate) == 0) {strncpy(config.setting_autoupdate, "0",1);};
if (strlen(config.setting_mqttdest) == 0) {strncpy(config.setting_mqttdest, "0.0.0.0",7);
Serial.println("Settings defaults as meta data empty");
} else {
Serial.println("Reading settings from meta data values");
};
configManager.save();
}

loop() {
DEBUG_PRINT("configmanager mqttdest test: " + String(config.setting_mqttdest));
}
`

The results are, on running the script it shows "Settings defaults as meta data empty", so it's set the defaults as the config.setting_mqttdest length is 0.
It should then save this value.
The loop runs and correctly then shows the value contains 0.0.0.0 as expected.

I then reload the esp8266 so the code restarts from blank.
It does the same, no values stored so it says "Settings defaults as meta data empty" and sets the default value of 0.0.0.0 again.
It never seems to write the values and is blank at each reboot.
What am I doing wrong?

So to write I am doing:
strncpy(config.setting_mqttdest, "0.0.0.0",7); configManager.save();
That is correct?
Thank you!

Retrieving config data from within the sketch loop

Is there a way that a sketch can access the config data directly? I was planning on using the library to create/update settings that the device would have access to.

Now that Ive gone through the code a couple times, I dont see a simple way to do this.

Thoughts? Or am I missing something?

Is it possible to send a Webpage from ESP32 ?

Hi,

the ConfigManager is the perfect libary for me and the projects in the future.

But one question is in my mind.

From a release before i using the ConfigManager, the ESP32 have send a simple html-site with some values, if i sebd a request to: http://ESP32IP/site .

But with the ConfigManager, there is no result when he loads the page.

Is it possible to send this page ?

Best regards

André

example REST to save and retrieve JSON

Hi,
I am new to programming. Thank you for the configmanager.

I want to save/retrieve ESP wifi config and additional parameters from my JS mobile app fetch api REST.

Uploaded simple.ino example sketch.
Tested in my windows machine, curl, this works for config wifi credentials; ESP can connect to my home AP.
Curl -X POST http://192.168.1.1 -d “ssid=my_ssid&password=my_password”

While reconnected to “Demo” AP, This way to save parameters;
curl -H "Content-Type: application/json" -X PUT http://192.168.1.1/settings -d “{here JSON for various types}"

Then this way to see response in console; (always blank)
Curl -X GET http://192.168.1.1/settings

I didn't understand well the structure for various parameter types in sketch OR a wrong syntax in curl lines.
Could you please give an example to save and retrieve a string parameter, “key”:”value”.
Both in sketch and curl statements.

Thanks

Delay restarting device to allow web server response

I found that adding a small delay before calling ESP.restart() will allow ConfigManager::handleAPPost() enough time to send the browser back its response. The use case is that I'm building a front-end that uses AJAX to call the server to reset the wifi credentials, and the device would restart before the browser got the response back.

#102

Problems with with variables in the sketch

Hi,

i use example "save_config_demo.ino" from the master branch and have little problems with the variables outside of the struct.

For the float-value in the struct i used

float nameofvariable = config.nameofstructvariable;

So, if i would print it in the serial monitor, He shows only the value 0. I think, the problem in my side.

How can i solve this ?

Another thing is the configuration on the settings site. I write the values in the masks, press "save" and the following screen prints "File not found" message.

Thank you.

configuration parameters other than int don't work

I have noticed in my own sketch but also in the example/simple.ino that the "name" (string) and "enable" (boolean) cannot be updated through a PUT call

This is immediately after uploading the sketch

mbp> curl -X GET http://192.168.1.16/settings
{"name":"","enabled":true,"hour":0}

Here I am trying to update the three config options

mbp> curl -X PUT -d '{"name":"something","enabled":false,"hour":2}' http://192.168.1.16/settings

But only the hour (int) changes.

mbp> curl -X GET http://192.168.1.16/settings
{"name":"","enabled":true,"hour":2}

The work-around that I am now using is to only use integers in the configuration.

Example sketch for fsbrowser.ino

Hi,

Could you please provide example like fsbrowser.ino https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino

I try to upload/update html file on spiffs using web browser.
I have custom route for upload

 server->on("/upload", HTTPMethod::HTTP_POST, [server](){
        server->send(200);
        handleFileUpload(server);
    });
void handleFileUpload(WebServer *server){ // upload a new file to the SPIFFS
  HTTPUpload& upload = server->upload();
  if(upload.status == UPLOAD_FILE_START){
    String filename = upload.filename;
    if(!filename.startsWith("/")) filename = "/"+filename;
    Serial.print("handleFileUpload Name: "); Serial.println(filename);
    fsUploadFile = SPIFFS.open(filename, "w");            // Open the file for writing in SPIFFS (create if it doesn't exist)
    filename = String();
  } else if(upload.status == UPLOAD_FILE_WRITE){
    if(fsUploadFile)
      fsUploadFile.write(upload.buf, upload.currentSize); // Write the received bytes to the file
  } else if(upload.status == UPLOAD_FILE_END){
    if(fsUploadFile) {                                    // If the file was successfully created
      fsUploadFile.close();                               // Close the file again
      Serial.print("handleFileUpload Size: "); Serial.println(upload.totalSize);
      server->sendHeader("Location","/success.html");      // Redirect the client to the success page
      server->send(303);
    } else {
      server->send(500, "text/plain", "500: couldn't create file");
    }
  }
}

I copied handleFileUpload for example and pass server to the function and change server.xxx to server->xxx. It did compiled just fine but it doesn't response at all, just blank page after server->send(200).

I think I have no idea how to refer to server instance.

Thank you,
sam

SPIFFS not supported on ESP32

I'm following your instructions on the readme but when I click on "Tools -> ESP8266 (!) data sketch upload" it says "SPIFFS not supported on ESP32".
How can I upload the index.html file?

AP timeout?

I have a couple of devices running firmware that includes ConfigManager, in different locations. One of them is very stable. The other seems to go offline randomly. I think I've traced this to transient conditions on the wifi network at one location. The device becomes disconnected due to router issues, tries 20 times to reconnect to the wifi, fails to connect and then launches its AP mode config pages - and sits there forever waiting for a connection until it's manually rebooted.

Could we maybe have an AP timeout? Keep a timestamp of when the last http operation happened and check it in ConfigManager::loop()? Then close down the AP and retry the wifi connection?

Also it might be nice to be able to set the number of wifi connect retries, the wait time and the AP timeout value when starting ConfigManager.

What are your thoughts Nick?

Unable to save WiFi settings to EEPROM [esp32]

Hi, I came across your library on platformio, and I'm excited at what it has to offer. After following the example in the README, I get the following output and my MCU stays in AP mode waiting to be set up.

Reading saved configuration
MAC: 7C:9E:BD:ED:28:5C
SSID: "��������������������������������"
MagicBytes mismatch - SSID: ������������������������������������������������������������������������������������������������Xvǒ�
Starting Access Point
E (2364) phy_init: store_cal_data_to_nvs_handle: store calibration data failed(0x1105)

AP Name: Desk-Buddy
AP IP address: 192.168.1.1
Webserver enabled on port: 80
[E][WebServer.cpp:617] _handleRequest(): request handler not found
Unknown URL: captive.apple.com
[E][WebServer.cpp:617] _handleRequest(): request handler not found
Unknown URL: captive.apple.com
[E][WebServer.cpp:617] _handleRequest(): request handler not found
Unknown URL: captive.apple.com
[E][WebServer.cpp:617] _handleRequest(): request handler not found
Unknown URL: captive.apple.com
Storing WiFi Settings for SSID: "---------------"
[E][EEPROM.cpp:199] commit(): error in write
EEPROM committed: false

For good measure, I did run ~/Library/Arduino15/packages/esp32/tools/esptool_py/2.6.1/esptool --chip esp32 erase_flash to make sure that my flash was clean, and I still get the above messages. I am not sure how to proceed, and could use your advice.

Thank you.

AP remains available after connecting node to wifi

I noticed this with an NodeMCU ESP8266 development board. I consider it undesired behaviour that the AP remains available, as it allows anyone to reconfigure the Thing. Let me outline the steps that allow me to reproduce.

When the Thing is not connected to my local wifi network, I see “Starting Access Point” in the serial console and can connect my laptop as follows:

Laptop Wi-Fi is connected to ESP-THING and has the IP address 192.168.1.100.

All is fine and I configure the SSID and Password of my wifi router. In the serial console I can see it connecting. The ESP-THING wifi network shortly disappears, and then reappears. With the Thing connected to my local wifi network, I can again connect to its AP as follows:

Laptop Wi-Fi is connected to ESP-THING and has the IP address 192.168.4.2.

In the latter case (i.e. with the thing connected), I can access the /index.html endpoint at 192.168.1.13 (when I connect my laptop to my router network) and at 192.168.4.1 (when I connect my laptop to the ESP-THING network).

What I do not understand is where the 192.168.4.x network comes from, as there is nothing in the code with this IP address. There is this

    IPAddress ip(192, 168, 1, 1);
    WiFi.mode(WIFI_AP);
    WiFi.softAPConfig(ip, ip, IPAddress(255, 255, 255, 0));
    WiFi.softAP(apName);

I do not find in the code where the mode is being switched, but I get the feeling that - once connected - it is in WIFI_AP_STA and not in WIFI_STA mode.

Saving config with wrong type wipes EEPROM memory

Discussed here

When putting the wrong type in a config parameter and saving, the memory allocation gets screwy and gets wiped.
Device will no longer have Wifi credentials/etc at next boot.

To recreate

config.someIntParam = random(300); // where the parameter is an int
configManager.save();

** This may be an odd type cast I came across and doesnt apply to other scenarios.

Suggestion

A better setter for parameters via ConfigManager.

This would particularly be useful since setting a string is not straightforward

strncpy(config.deviceName, "fesp-muppet", DEVICENAMELEN);

Update method

Something like:

template <typename T>
void updateParameter(name, T* value) {
    // call to the configParameter->update();
  }

void updateParameter(name, char* value) {
    // call to the configParameter->update();
  }

I had zero luck figuring out how to identify a parameter by name from the std::list<BaseParameter*> and a tripped over the same trap of Arduino not having std::unordered_map at least twice now ;)

Explicit parameter objects for the main project

I also tried having the addParameter call return the ConfigParameter object and the main project code could track/index it. That got complicated, and compiler errors in the type returns/etc

void loop() {

...

ConfigParameter = configManager.addParameter("randomNumber", &config.randomNumber, get);

Doing something bad ...

Finally .. I came up with this monster that exploits ConfigManagers use of JSON for updating ... worked, but felt icky

 template <typename T>
  void updateParameter(const char* name, T value) {
    std::list<BaseParameter*>::iterator it;
    for (it = parameters.begin(); it != parameters.end(); ++it) {
      if ((*it)->getName() == name) {
        DynamicJsonDocument doc(1024);
        JsonObject json = doc.createNestedObject();
        json[name] = value;
        (*it)->fromJson(&json);
        break;

Secure the AP with PASSWORD

Thank you for an amazing Library!

Scenario:

  • The device is now in AP mode.

Issue:

  • The AP is not secured

Request:

  • Is it possible to secure the AP with a PASSWORD?

Thanks!

add other text field to settings.html and read data ???

I want to add text fields in settings.html And read the data, type out via Serial.println (variable) after saving in the form, such as mqtt_host from the example, want to read the data to be stored at the variable
Help explain me
Thank You

What is the point of "enabled" in config examples?

I don't see this parameter being used anywhere, but it is offered in both the simple.ino and save_config_demo.ino examples:

struct Config {
  char name[255];
  bool enabled;
...

What is "enabled" intended for?

settings endpoint will only return last saved value

I am not sure if this was a design choice or bug but when saving with a PUT to /settings and then calling the GET on /settings only the last value is returned.

I was playing with these 2 functions and I do not know enough about c++ to fix but wanted to bring this up.
https://github.com/nrwiersma/ConfigManager/blob/master/src/ConfigManager.h#L82-L88
and
https://github.com/nrwiersma/ConfigManager/blob/master/src/ConfigManager.cpp#L177-L194

I confirmed with the save_config_demo example that it does this as it will only show he meta.version (I removed to test the form code)
I also confirmed it will save the values to EPROMM so it's working in that part.

EDIT: I am going to play with a solution using
https://arduinojson.org/v6/how-to/merge-json-objects/

Thanks

ESP32 Support

Hi Nick, have you considered adding ESP32 support for ConfigManager? Happy to help out once again if you have the time.

ESP32 Wifi Sucks .. connects every two tries .. Workaround thoughts

Related Issue

Appears the ESP32 really sucks ... Currently running into a Wifi connection only happens every other boot.
Workaround appears to be something like this .. but its gross ...

Thoughts? Can add some flag to enable this so it doesnt always double tap?


WiFi.begin(ssid, password[0] == '\0' ? NULL : password);
delay(1000);
WiFi.disconnect();
WiFi.begin(ssid, password[0] == '\0' ? NULL : password);

Reading saved configuration
SSID: "BI-12"
E (1003) wifi: Set status to INIT.
 
========= ABOVE DELAY/CONNECT CODE ==========

Waiting for WiFi to connect...
Connected to BI-12 with 192.168.4.3
Station Mode

Compiler warning

When im compiling the Configmanager (in VS code with platform IO), I get the folowing warning:

image

I was able to fix it by adding "const", is it possible to also change this in the library?
image

Timeout does not work

Hi, I tried to set the timeout to 300 on configmanager.h, but esp8266 doesn't reboot.

One little problem with one parameter

Hi,

my project with an esp32 and a ble - scanner is almost ready to run.

But i have one problem with one parameter. In my case, it is a problem with a char - array from the UI of the ConfigManager.
I convert it to an int with : int zahl = atoi(rssimac1); .

The BLE - Libary uses a class an in this class, i use an if - request. If the scanner scans a known MAC and the RSSI of it, the esp looks to the rssi value from the ConfigManager and decide " Yes, it is a known adress" or not.

The parameter of the mac are okay. He reads this from the configmanager. But the rssi is again zero.

A serial.print in the loop shows the correct value. That's the problem i have.
Before i used your Manage, i had the INIWifimanager. But it was not mine.
Therefore, i want to use your Libary. The code is experimental and i must clean it up.

Here is my code:

`include "ConfigManager.h"
#include <HTTPClient.h>
#include <WebServer.h>
#include <ArduinoOTA.h>
#include <SPIFFS.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include <BLEAddress.h>
#include <Ticker.h>
#include <NTPClient.h>
#include <WiFiUdp.h>

#define DEBUGGING // Einkommentieren für die Serielle Ausgabe

#ifdef DEBUGGING
#define DEBUG_B(...) Serial.begin(VA_ARGS)
#define DEBUG_P(...) Serial.println(VA_ARGS)
#define DEBUG_F(...) Serial.printf(VA_ARGS)
#else
#define DEBUG_B(...)
#define DEBUG_P(...)
#define DEBUG_F(...)
#endif

WebServer server(80);

const char *settingsHTML = (char *)"/settings.html";
const char *stylesCSS = (char *)"/styles.css";
const char *mainJS = (char *)"/main.js";

struct Config {
char tageins_name[32];
char tagzwei_name[32];
char uuideins_name[50];
char uuidzwei_name[50];
char rssi_werttageins[4];
char rssi_werttagzwei[4];
char rssi_wertibeacon[4];
char webhook_ein[40];
char webhook_aus[40];
int8_t led;
bool enabled;
} config;

struct Metadata {
int8_t version;
} meta;

ConfigManager configManager;

///////////////////////////////////////Variablen werden aus dem ConfigManager - struct extrahiert////////////////////////////////
char* mac1 = config.tageins_name;
char* mac2 = config.tagzwei_name;
char* ibeacon1 = config.uuideins_name;
char* ibeacon2 = config.uuidzwei_name;
char* rssimac1 = config.rssi_werttageins;
char* rssimac2 = config.rssi_werttagzwei;
char* rssiibeacon = config.rssi_wertibeacon;
char* WebhookEin = config.webhook_ein;
char* WebhookAus = config.webhook_aus;
int led = config.led;
int version = meta.version;
int zahl = atoi(rssimac1);

void APCallback(WebServer *server) {
server->on("/styles.css", HTTPMethod::HTTP_GET, server {
configManager.streamFile(stylesCSS, mimeCSS);
});

DebugPrintln(F("AP Mode Enabled. You can call other functions that should run after a mode is enabled ... "));
}

void APICallback(WebServer *server) {
server->on("/disconnect", HTTPMethod::HTTP_GET, server {
configManager.clearWifiSettings(false);
});

server->on("/settings.html", HTTPMethod::HTTP_GET, server {
configManager.streamFile(settingsHTML, mimeHTML);
});

// NOTE: css/js can be embedded in a single page HTML
server->on("/styles.css", HTTPMethod::HTTP_GET, server {
configManager.streamFile(stylesCSS, mimeCSS);
});

server->on("/main.js", HTTPMethod::HTTP_GET, server {
configManager.streamFile(mainJS, mimeJS);
});

server->on("/reboot", HTTPMethod::HTTP_GET, server {
ESP.restart();
});

}

String IDadresseSW = "88bdf79f-59ec-4f47-bf82-39b957c568a"; //UUID SmartWatch
int RelaisPin = 32; // Pin an dem Relais hängt
int Verzoegerung = 15; // Auschaltverzögerung wenn das Signal von BLE ibeacon fehlt
int active_low = 1; // "0" Relais schaltet bei +5V, "1" Relais beim schaltet bei 0V
int Webhook3;
int Webhook4;
int TuerAUFUUID1;
int TuerAUFSWUUID;
boolean variable = true;
int AktuelleZeit;
int LEDGruen = 18;
int LEDRot = 19;
int LEDWeiss = 23;
int Buzzer = 16;
int Hilfsschalter;
int Anwesend;
int MillisFaktor = 1000;
int Anwesendheitspause = 60;
int Schaltpause;
String Scanne;
String Scanne2;
String wsrssi;
String wsrssi2;
int i = 0;
int MACScan;
int MACAktuell;

//Variablenblock für die Speicherung der Adressen
int MACJetzt;
int MACVor1Min;
int MACVor2Min;
int MACVor3Min;
int MACVor4Min;
int MACVor5Min;
int MACVor6Min;
int MACVor7Min;
int MACVor8Min;
int MACVor9Min;
//Stringzuordnung
String MACTendenz;

const long utcOffsetInSeconds = 3600;
char daysOfTheWeek[7][12] = {"Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"};
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);

//Millis wird gesetzt
long previousMillis = 0;
long interval = 1200;

int VerzoegerungZaeler = 0;
Ticker Tic;
static BLEAddress *pServerAddress;
static BLEAddress *pServerAddress2;
static BLEAddress *pServerAddress3;
static BLEAddress *pServerAddress4;
static BLEAddress pServerAddress5;
BLEScan
pBLEScan ;
int scanTime = 1; //In seconds

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks
{
void onResult(BLEAdvertisedDevice advertisedDevice) // passiert wenn BLE Device ( beacon ) gefunden wurde
{

  Serial.print("iBeacon gefunden : ");
  Serial.println(advertisedDevice.toString().c_str()); // ibeacon Adresse anzeigen
  Serial.printf("   RSSI: %d ", advertisedDevice.getRSSI());
  Scanne = (advertisedDevice.toString().c_str());
  wsrssi = (advertisedDevice.getRSSI());

  ///////////////////////////////////////Testcode//////////////////////////////////////
    Serial.println("-------------------------------------");
    Serial.println("MAC von G-Tag 1 :");
    Serial.println(mac1);
    Serial.println("-------------------------------------");

    Serial.print("Schaltentfernung G-Tag 1 :");
    Serial.println(zahl);
    Serial.println("-------------------------------------");
    Serial.print("Webhook - Einschaltbefehl :");
    Serial.println(WebhookEin);
    Serial.println("-------------------------------------");
    delay(500);
    /////////////////////////////////////////////////////////////////////////////////////

}
};

//Scanne2 = (advertisedDevice.toString().c_str());
//wsrssi2 = (advertisedDevice.getRSSI());

/*
i++;
//Codeblock für fortlaufende Speicherung der Adresse
MACVor9Min = MACVor8Min;
MACVor8Min = MACVor7Min;
MACVor7Min = MACVor6Min;
MACVor6Min = MACVor5Min;
MACVor5Min = MACVor4Min;
MACVor4Min = MACVor3Min;
MACVor3Min = MACVor2Min;
MACVor2Min = MACVor1Min;
MACVor1Min = MACJetzt;
MACJetzt = MACAktuell;

if (advertisedDevice.haveServiceUUID())
{
Serial.printf("UUID: %s ", advertisedDevice.getServiceUUID().toString().c_str());

}
//if (advertisedDevice.getAddress().equals(*pServerAddress) & advertisedDevice.getRSSI() > MinRSSI) // ibeacon Adresse Vergleichen
//if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(cstring) & advertisedDevice.getRSSI() > MinRSSI)

/////////////////////////////////////////////////////////////////Scannen nach Handy UUID's//////////////////////////////////////////////////////////////////////////////////////////////////////////

if (advertisedDevice.getAddress().equals(*pServerAddress3) & advertisedDevice.getRSSI() > rssiibeacon)
//if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(UUID2)& advertisedDevice.getRSSI() > MinRSSI)
//if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(SWUUID)& advertisedDevice.getRSSI() > MinRSSI)

{
Serial.println(" Überwachte Adresse gefunden"); // wenn überwache Adresse gefunden wurde
digitalWrite (RelaisPin, !active_low); // Relais Einschalten
Serial.println("Erfasse Schaltung zum Aufschließen !");
TuerAUFUUID1 = 1;
Anwesend = 1;

VerzoegerungZaeler = 0; // Ausschaltverzögerung zurücksetzen
advertisedDevice.getScan()->stop(); // Scanvorgang beenden
} // Found our server

else
{
TuerAUFUUID1 = 0;
TuerAUFSWUUID = 0;
Anwesend = 0;
}

if (advertisedDevice.getAddress().equals(*pServerAddress4) & advertisedDevice.getRSSI() > rssiibeacon)
//if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(UUID2)& advertisedDevice.getRSSI() > MinRSSI)
//if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(SWUUID)& advertisedDevice.getRSSI() > MinRSSI)

{
Serial.println(" Überwachte Adresse gefunden"); // wenn überwache Adresse gefunden wurde
digitalWrite (RelaisPin, !active_low); // Relais Einschalten
Serial.println("Erfasse Schaltung zum Aufschließen !");
TuerAUFUUID1 = 1;
//TuerAUFSWUUID = 0;

VerzoegerungZaeler = 0; // Ausschaltverzögerung zurücksetzen
advertisedDevice.getScan()->stop(); // Scanvorgang beenden
} // Found our server

else
{
//TuerAUFUUID1 = 0;
//TuerAUFSWUUID = 0;
}

//////////////////////////////////////////////Scannen nach G -Tag's mittels MAC - Adresse////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////Tag One///////////////////////////////////////////////////////////////////////////////////////////////////////////
if (advertisedDevice.getAddress().equals(*pServerAddress) & advertisedDevice.getRSSI() > rssimac1) // ibeacon Adresse Vergleichen
{
Serial.println(" Überwachte MAC - Adresse Tag 1 gefunden"); // wenn überwache Adresse gefunden wurde
digitalWrite (RelaisPin, !active_low); // Relais Einschalten
Serial.println("Erfasse Schaltung zum Aufschließen von Tag 1 !");
TuerAUFUUID1 = 1;
Anwesend = 1;
VerzoegerungZaeler = 0; // Ausschaltverzögerung zurücksetzen
advertisedDevice.getScan()->stop(); // Scanvorgang beenden
}
else
{
TuerAUFUUID1 = 0;
TuerAUFSWUUID = 0;
Anwesend = 0;
}

///////////////////////////////////////////////////////////Tag Two///////////////////////////////////////////////////////////////////////////////////////////////////////////

if (advertisedDevice.getAddress().equals(*pServerAddress2) & advertisedDevice.getRSSI() > rssimac2) // ibeacon Adresse Vergleichen
{
Serial.println(" Überwachte MAC - Adresse Tag 2 gefunden"); // wenn überwache Adresse gefunden wurde
digitalWrite (RelaisPin, !active_low); // Relais Einschalten
Serial.println("Erfasse Schaltung zum Aufschließen von Tag 2 !");
TuerAUFUUID1 = 1;
Anwesend = 1;
VerzoegerungZaeler = 0; // Ausschaltverzögerung zurücksetzen
advertisedDevice.getScan()->stop(); // Scanvorgang beenden
}

else
{
// TuerAUFUUID1 = 0;
// TuerAUFSWUUID = 0;
Anwesend = 0;
}

//////////////////////////////////////////////////////Scannen nach SmartWatch UUID/////////////////////////////////////////////////////////////////////////////

if (advertisedDevice.getAddress().equals(*pServerAddress5) & advertisedDevice.getRSSI() > rssiibeacon) // ibeacon Adresse Vergleichen

{
Serial.println("Zweite überwachte Adresse gefunden"); // wenn überwache Adresse gefunden wurde
digitalWrite (RelaisPin, !active_low); // Relais Einschalten
Serial.println("Erfasse Schaltung zum Aufschließen !");
TuerAUFSWUUID = 1;
//TuerAUFUUID1 = 0;

VerzoegerungZaeler = 0; // Ausschaltverzögerung zurücksetzen
advertisedDevice.getScan()->stop(); // Scanvorgang beenden
} // Found our server

else
{

}

Serial.println("");

}
};
*/

void SekundenTic() // Wird jede Sekunde ausgefüert
{
VerzoegerungZaeler++; // Sekundenzähler
if (VerzoegerungZaeler >= Verzoegerung) digitalWrite (RelaisPin, active_low); // Wenn Verzögerungszeit erreicht wurde Auschalten
}

//#################################################################SETUP##########################################################################################################

void setup() {
Serial.begin(115200);
DEBUG_B(115200);
DEBUG_F("\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n\n", FILE, TIMESTAMP, ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10);
// spiffs();
// admin();
//Connect();
//individualButton();
// setupTime();
// espboardLed();
// onboardLed();
// bme280();
// dht22(); // Die Tabs die du nutzen möchtest, musst du Einkommentieren
// bh1750();
// setupSchaltUhr();

///////////////////////////////////////////////ConfigManager - Block///////////////////////////////////////////////////////////////////////////////////

meta.version = 3;

// Setup config manager
configManager.setAPName("BTScanner");
configManager.setAPFilename("/index.html");

// Settings variables
configManager.addParameter("tageins_name", config.tageins_name, 32);
configManager.addParameter("tagzwei_name", config.tagzwei_name, 32);
configManager.addParameter("uuideins_name", config.uuideins_name, 50);
configManager.addParameter("uuidzwei_name", config.uuidzwei_name, 50);
configManager.addParameter("rssi_werttageins", config.rssi_werttageins, 4);
configManager.addParameter("rssi_werttagzwei", config.rssi_werttagzwei, 4);
configManager.addParameter("rssi_wertibeacon", config.rssi_wertibeacon, 4);
configManager.addParameter("webhook_ein", config.webhook_ein, 40);
configManager.addParameter("webhook_aus", config.webhook_aus, 40);
configManager.addParameter("led", &config.led);
configManager.addParameter("enabled", &config.enabled);

// Meta Settings
configManager.addParameter("version", &meta.version, get);

// Init Callbacks
configManager.setAPCallback(APCallback);
configManager.setAPICallback(APICallback);

configManager.begin(config);

pinMode (LEDGruen, OUTPUT);
pinMode (LEDRot, OUTPUT);
pinMode (LEDWeiss, OUTPUT);
pinMode (Buzzer, OUTPUT);

///Hilfsschalter wird in Grundstellung geschaltet//////////////////////////////////////
Hilfsschalter = 0;

ArduinoOTA.onStart( {
//save(); //Einkommentieren wenn Werte vor dem Update gesichert werden sollen
});
ArduinoOTA.begin();
timeClient.begin();
AktuelleZeit = (timeClient.getHours() + 1);
server.begin();
DEBUG_P("HTTP Server gestartet\n\n");

///////////////////////////////////Codeblock umwandlung der Variablenwerte vom ConfigManager -> BLE-Scanner///////////////////////////////////////////
String macad1 = String(mac1);
String macad2 = String(mac2);
String ibeaconid1 = String(ibeacon1);
String ibeaconid2 = String(ibeacon2);
//String tageinsrssi = String(rssimac1);
//String tagzweirssi = String(rssimac2);
String whein = String(WebhookEin);
String whaus = String(WebhookAus);

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Serial.println("Starte BLE Scanner");

Serial.print("Metadata :");
Serial.println(version);
Serial.println("-------------------------------------");

pServerAddress = new BLEAddress(macad1.c_str());
pServerAddress2 = new BLEAddress(macad2.c_str());
pServerAddress3 = new BLEAddress(ibeaconid1.c_str());
pServerAddress4 = new BLEAddress(ibeaconid2.c_str());
pServerAddress5 = new BLEAddress(IDadresseSW.c_str());
BLEDevice::init("");

}

/*
void Startnullung() //Shelly wird ausgeschaltet - Grundstellung zum Start
{
HTTPClient http;
Serial.println("Schalte Shelly aus...");
http.begin(WebhookAus); //Specify the URL
int httpCode = http.GET(); //Make the request
}
*/

//#################################################################LOOP######################################################################################

void loop() {

configManager.loop(); // Um das der Webseitenaufbau der HTML - Datei sauber erfolgen kann, kein delay im Loop einbauen. Besser Millis !!.
server.handleClient();
timeClient.update();
//if (millis() < 0x2FFF || millis() > 0xFFFFF0FF) runtime(); // Auskommentieren falls du den Admin Tab nicht nutzen möchtest

//String tageinsrssi = String(rssimac1);
//int zahl = atoi(rssimac1);
//zahl = MACAktuell;
//String tagzweirssi = String(rssimac2);

Serial.print("MAC von G-Tag 1 :");
Serial.println(mac1);
Serial.println("-------------------------------------");
Serial.print("MAC von G-Tag 2 :");
Serial.println(mac2);
Serial.println("-------------------------------------");
Serial.print("UUID von iBeacon 1 :");
Serial.println(ibeacon1);
Serial.println("-------------------------------------");
Serial.print("UUID von iBeacon 2 :");
Serial.println(ibeacon2);
Serial.println("-------------------------------------");
Serial.print("Schaltentfernung G-Tag 1 :");
//Serial.println(zahl);
/*Serial.println("-------------------------------------");
Serial.print("Schaltentfernung G-Tag 2 :");
Serial.println(rssimac2);
Serial.println("-------------------------------------");
Serial.print("Schaltentfernung iBeacons :");
Serial.println(rssiibeacon);
*/Serial.println("-------------------------------------");
Serial.print("Webhook - Einschaltbefehl :");
Serial.println(WebhookEin);
Serial.println("-------------------------------------");
Serial.print("Webhook - Ausschaltbefehl :");
Serial.println(WebhookAus);
Serial.println("-------------------------------------");

///////////////////////////////////////////Code - Block ConfigManager//////////////////////////////////
unsigned long currentMillis = millis();

/*
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks
{
void onResult(BLEAdvertisedDevice advertisedDevice) // passiert wenn BLE Device ( beacon ) gefunden wurde
{

    Serial.print("iBeacon gefunden : ");
    Serial.print(advertisedDevice.toString().c_str()); // ibeacon Adresse anzeigen
    Serial.printf("   RSSI: %d ", advertisedDevice.getRSSI());
    Serial.println("---------------------------------");


    if (advertisedDevice.getAddress().equals(*pServerAddress)& advertisedDevice.getRSSI() > zahl)    // ibeacon Adresse Vergleichen
    {
      Serial.println(" Überwachte MAC - Adresse Tag 1 gefunden");         // wenn überwache Adresse gefunden wurde

    }
  }

};

*/

if (currentMillis - previousMillis > interval) {
previousMillis = currentMillis;

pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
Tic.attach( 1, SekundenTic);

pBLEScan->start(scanTime);

}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////HTTP - Update - Block///////////////////////////////////////////////////////////////////

if ((timeClient.getMinutes() == 30) && (timeClient.getSeconds() >= 00) and (timeClient.getSeconds() <= 05)) //Prüfe immer um halb auf Updates
{
Serial.println();
Serial.println("Prüfe auf HTTP - Update...");
// ESPUpdate();
delay(1000);
}

/////////////////////////////////////Überwachung WiFi - Verbindung////////////////////////////////////////

//Netzwerküberwachung des ESP32
if
(WiFi.status() == WL_CONNECTED) {
//digitalWrite(LEDGruen, HIGH);
}

else

{
digitalWrite(LEDGruen, HIGH);
delay(100);
digitalWrite(LEDGruen, LOW);
delay(100);
digitalWrite(LEDGruen, HIGH);
delay(100);
digitalWrite(LEDGruen, LOW);
delay(100);
digitalWrite(LEDRot, HIGH);
Serial.println("Netzwerk nicht in Reichweite !");
Serial.println("Verbindung wird aufgebaut...");
WiFi.reconnect();
delay(3000);
digitalWrite(LEDRot, LOW);
digitalWrite(LEDGruen, HIGH);
}

///////////////////////////////INFO //////////////////////////////////////////

Serial.print("Aktuelle Minute :");
Serial.println(timeClient.getMinutes());
Serial.println("XXXXXXXXXXXXXXXXXXXXX");
Serial.print("Aktuelle Sekunde :");
Serial.println(timeClient.getSeconds());

pBLEScan->clearResults(); // Buffer wird gelöscht, um Speicher frei zu geben

}`

Librery

Dear Sir

Have you tried to install this example on a clean nodemcu?
I have spent hours trying to understand the problem but you see I am lost... So I write to you.

I have uploaded the code and try to connect to the "demo" AP trough my mobile, it opens the connection manager address http://192........
and I get file not found...

I have tried to understand as much as I can but I am lost, it seems that it doesnt upload the index.html...

Can you check the code again please?

I am also curious, you say that the SSID and password is saved in the eeprom, what if after that I connect to one access point I would like to connect to another? should I reprogram again the code or is there other way to reset settings?

compile error - simple.ino

When I compile the sample - simple.ino I get a compile error !

C:\Users\peter\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0\libraries\DNSServer\src/DNSServer.h:67:13: error: cannot declare field 'DNSServer::_udp' to be of abstract type 'WiFiUDP'

 WiFiUDP _udp;

         ^

Any idea what I did wrong?
Many thanks,

Memory usage and JSON/architectural issues

Hi @nrwiersma,

Firstly thank you for taking the time to write and share this library. Unfortunately I've stopped using it for the moment as it introduced instability problems into my application, due to memory usage. So I was wondering about some of the architectural choices made with this library. Please correct me if I'm wrong with anything I say here.

I've modified your library to use server->streamFile() instead of server->send(), so the HTML file is streamed directly from flash instead of being read into a string variable before being sent. This has both improved web server performance and reduced impact on heap space, in turn reducing crashes when the HTML file is too big.

I'm also concerned about the security problems of the REST API. Since parameters may include passwords for MQTT brokers, having an open endpoint which freely shows clear text parameter values is a bit of a risk.

The library passes parameters via the REST API using JSON. This creates a large memory overhead and makes it difficult to use standard HTML forms for the PUT, as there is no JSON support built into HTML. Could we not just post server args using multipart/form-data and access each arg without the expensive transformation to and from JSON? Sure it makes it easy on the client where we have the convenience of JavaScript and Ajax, but it's expensive on the ESP8266 side.

Thanks,
Jon

Metadata adding config values

Hi,
Perhaps I'm a little confused to the point of Metadata as opposed to Config?
I'm using Config to retain the wifi settings, then was going to use the Metadata struct to contain my user parameters, is this right or not? Does it get saved, and if so do I just call:
configManager.save();
and that will store the meta and config settings?
The settings don't appear to save for the meta part of the code, is this expected behaviour and if so what is the key point of the meta part of this and examples?

My code:

`include <ConfigManager.h>
ConfigManager configManager;
struct Config {
char name[20];
bool enabled;
int8 hour;
char password[20];
} config;

struct Metadata {
int8_t version;
String setting_autoupdate;
} meta;

setup() {
configManager.setAPFilename("/ap-index.html");
configManager.addParameter("name", config.name, 20);
configManager.addParameter("enabled", &config.enabled);
configManager.addParameter("hour", &config.hour);
configManager.addParameter("password", config.password, 20, set);
configManager.addParameter("version", &meta.version, get);
configManager.addParameter("setting_autoupdate", &meta.setting_autoupdate, set);
configManager.begin(config);
};

loop() {
meta.setting_autoupdate="yes";
configManager.save();
`

Saving credentials does not work

Thanks for this great library. I am trying to get it running on an ESP32 via PlatformIO.
In the log I can see this output during boot and when I try to save my Wifi credentials.

Starting Access Point
AP Name: SolarPowerReader
AP IP address: 192.168.1.1
Webserver enabled on port: 80
dhcps: send_offer>>udp_sendto result 0
[E][WebServer.cpp:617] _handleRequest(): request handler not found
Unknown URL: www.msftconnecttest.com
--> at this point I hit save in the browser to store the credentials <--
WiFi Settings cannot be stored before ConfigManager::begin()
ets Jun 8 2016 00:22:57

The code for testing:

#include <Arduino.h>
#include "ConfigManager.h"

struct Config
{
  char name[20];
  bool enabled;
  int8_t hour;
  char password[20];
} config;
struct Metadata
{
  int8_t version;
} meta;

ConfigManager configManager;
const long interval = 30000;
// the logic should be triggered on the first run and not after the interval
unsigned long previousMillis = millis() - interval;

void setup()
{
  DEBUG_MODE = true; // will enable debugging and log to serial monitor

  Serial.begin(115200);
  Serial.println("\n\nbooting...\n\n");

  meta.version = 3;

  // Setup config manager
  configManager.setAPName("SolarPowerReader");
  configManager.setAPFilename("/index.html");
  configManager.addParameter("name", config.name, 20);
  configManager.addParameter("password", config.password, 20, set);
  configManager.addParameter("version", &meta.version, get);

  configManager.begin(config);
  // configManager.clearWifiSettings(false);
  //configManager.save();
}

void loop()
{
  configManager.loop();

  unsigned long currentMillis = millis();
  // query Modbus if interval is reached and Wifi is connected
  if (currentMillis - previousMillis >= interval && configManager.getMode() != 0)
  {
    previousMillis = currentMillis;

    Serial.println("do something");
  }
}

I think it might have to do with the EPROM. Trying to call clearWifiSettings or save did result in the same behaviour.

save-config-demo

First I want to say that I like your library. It does what it does without a lot of junk in the way. What I want is a clean way to set the WiFi connection, and to set some other parameters to eeprom. I tried another library but it was doing too much. Has it's own way to make web pages that was "simpler". I thought it only made it harder as I needed to figure out how to work with it.

The minor issue I have with ConfigManager is on a new setup the contents of the eeprom is filled into the the fields in the setup screen. I haven't looked at the code yet, but it would be better to have empty text boxes on the first load. Typing new values into the line does not get rid of the remainder of the line.

I just tried to save. I think it might have saved. But I don't know if it did. Confirmation would be nice. I guess I need to handle it myself. Hey, at least I can do it my way.

ConfigManager::begin() changes value of int in struct

Below is a simple ino that reproduces the issue.

I have a struct that defines my configuration - it has an array of a struct of char * and a single int. Both the struct and ConfigManager are members of a class I'm writing. Before I call ConfigManager::begin() my int in the struct is correctly initialized to zero. However, after calling ConfigManager::begin() the value of the int becomes -1.

I have tried erasing my flash in case there was previous data being read, but that didn't change anything. I would appreciate any help and/or advice you have on this.

For testing purposes I am using Arduino 1.8.13 and ConfigManager 2.1.0. My device is an esp32 wroom 32D.

#include <ConfigManager.h>

const int CALENDARS = 8;

struct configuration_t {
  int calendars;
};

struct metadata_t {
  int version;
};

class Config {
  public:
  Config(): manager(new ConfigManager()) {
    manager->addParameter("calendars", &config.calendars);
    manager->addParameter("version", &meta.version);
  }

  void begin() {
    Serial.printf("Config::begin(): config.calendars = %d\n", config.calendars);
    Serial.printf("Config::begin(): meta.version = %d\n", meta.version);
    manager->begin(config);
    Serial.printf("Config::begin(): config.calendars = %d\n", config.calendars);
    Serial.printf("Config::begin(): meta.version = %d\n", meta.version);
  }

  private:
  configuration_t config{};
  metadata_t meta{};
  ConfigManager * manager;
};

void setup() {
  Serial.begin(115200);

  Config * config = new Config();
  config->begin();  
}

void loop() {
}

Edit: Updated demo code to remove unnecessary code and to add config parameters as in the example code.

Saving char arrays in EEPROM

Hi! First of all thanks for this great library! Yesterday I have faced an issue when I was trying to store char arrays.

So I made a struct like this:

struct Config {
  float nilBitcoin;
  float nilEthereum;
  float zolBitcoin;
  float zolEthereum;
  char linehe1[10];
  char linehe2[10];
  char linehe3[10];
  char linehe4[10];
} config;

Floats are stored correctly, but the char arrays not. I am getting garbage when I try to load.

Solution: I have to move char arrays to the top of the struct:

struct Config {
  char linehe1[10];
  char linehe2[10];
  char linehe3[10];
  char linehe4[10];
  float nilBitcoin;
  float nilEthereum;
  float zolBitcoin;
  float zolEthereum;
} config;

Is it a bug in your library or in the ESP32 framework or my knowledge about structs and EEPROM store is need to be updated? :)

How can I make it to auto reconnect?

Im trying to make the library (or sketch) to auto reconnect wifi after it connected successfully. Because right now once its connected and if wifi stops working and works again, it won't reconnect and connexions wont work.

I've tried something like this modifiying the library but its not working:

 if ((WiFi.status() != WL_CONNECTED)) {
    delay(1000);
    yield();
    char ssid[SSID_LENGTH];
    char password[PASSWORD_LENGTH];
    EEPROM.get(MAGIC_LENGTH, ssid);
    EEPROM.get(MAGIC_LENGTH + SSID_LENGTH, password);
    Serial.print("Reconnecting");
    WiFi.begin(ssid, password);
  }

CORS errors

image
How can we set the webserver to ignore cors policy?

SSIDs with Chinese characters fail

Got everything up and running with the demo, then entered an SSID with Simplified Chinese Characters in it (喝一点儿茶)

Got the following from the serial monitor

configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:952
load:0x40078000,len:6084
load:0x40080000,len:7944
entry 0x40080310

Reading saved configuration
[E][WiFiSTA.cpp:124] begin(): SSID too long or missing!
Waiting for WiFi to connect....................
Connection timed out
Starting Access Point
ets Jun  8 2016 00:22:57```

Add ConfigManager ArduBadge (Installation Guide)

Hi!

A nice addition to the readme page can be an ArduBadge badge, see here: www.ardu-badge.com
For ConfigManager it will look like that:
arduino-library-badge
Markdown:
[![arduino-library-badge](http://www.ardu-badge.com/badge/ConfigManager.svg)](http://www.ardu-badge.com/ConfigManager)

It shows:

  1. That ConfigManager is in the "Library Manager" in the Arduino IDE
  2. The latest release version
  3. Clicking on it redirects to a custom page with explanation on how to install ConfigManager.

What do you think?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.