save configuration variables esp8266 via server post method

I come from a PHP background so C is very very different.

I have an ESP8266 set up as a server. I also have a jquery-based application on it.

A function I would like to have is the ability to change configuration variables from the app.

I have the following code:

Defs:

/**
   Config
*/
struct Config {
  int irrigationStartHour;
  float totalRainfallCutoff;
  float bucketSize;
};

Config config;

Server:

  server.on("/config_save", HTTP_POST, []() {
    if (server.arg("key") == "" || server.arg("val") == "") {
      return server.send(500, "text/plain", "Missing parameters.");
    }
    String key = server.arg("key");
    config.key = server.arg("val");
    saveConfig(config); // commit change
    server.send(200, "text/plain", "Done");
  }[/code

Basically, at run-time this should modify the configuration variable in local memory, and then when `saveConfig()` is called that gets committed to a file that is managed using ArduinoJson. As that part isn't really the issue here, I've only shown this code.

As you can see, I want to be able to, with one function, modify any configuration variable. I figured `config.key = server.arg("val");` would work but it doesn't and gives me: "'struct Config' has no member named 'key'".

I'm not exactly sure where to go from here. In PHP this logic would work ;)

I don’t see a key entry in your Config structure

struct Config {
  int irrigationStartHour;
  float totalRainfallCutoff;
  float bucketSize;
};

Config config;

so how can this work?config.key = server.arg("val");

You likely get a String back from server.arg (never used it as I don’t play with libraries using the String class) so you would need to parse the content to extract the irrigationStartHour, totalRainfallCutoff or bucketSize. What is this supposed to look like?

J-M-L:
I don’t see a key entry in your Config structure

struct Config {

int irrigationStartHour;
  float totalRainfallCutoff;
  float bucketSize;
};

Config config;


so how can this work?`config.key = server.arg("val");`

You likely get a String back from `server.arg` (never used it as I don’t play with libraries using the String class) so you would need to parse the content to extract the `irrigationStartHour`, `totalRainfallCutoff` or `bucketSize`. What is this supposed to look like?

Basically, key is supposed to be the irrigationStartHour or whatever other variable I want to change and it is dynamically received as a server argument. Then the value is the value that that key should be.

So If I send a post irrigationStartHour: 6

I would like it to dynamically resolve to config.irrigationStartHour = 6

Which is where I came up with:

String key = server.arg("key"); config.key = server.arg("val");

I'm not sure if this kind of logic is possible in Arduino but it is rather easy in other languages I've worked with.

I'm trying to prevent having a server function for every single configuration variable. Does it make more sense now? Maybe not my code, but at least my logic.

so you should extract both

    String theKey = server.arg("key");
    String theValue = server.arg("val");

and then check what key you go

if (theKey == "irrigationStartHour") {
  config.irrigationStartHour = theValue.intValue();
} else
if (theKey == "totalRainfallCutoff") {
  config.totalRainfallCutoff  = theValue.floatValue();
} else
if (theKey == "bucketSize") {
  config.bucketSize = theValue.floatValue();
}

or similar, totally untested

J-M-L:
so you should extract both

    String theKey = server.arg("key");

String theValue = server.arg("val");


and then check what key you go

if (theKey == "irrigationStartHour") {
  config.irrigationStartHour = theValue.intValue();
} else
if (theKey == "totalRainfallCutoff") {
  config. totalRainfallCutoff  = theValue.floatValue();
} else
if (theKey == "bucketSize") {
  config.bucketSize = theValue.floatValue();
}


or similar, totally untested

Right, that was going to be my next approach. Probably utilize a switch. But at the core of my question is I guess I find it strange that I can't dynamically do it and I have to write it out verbatim.

Probably because in php, I can just do this: PHP Sandbox - Execute PHP code online through your browser

Just find it hard to believe c doesn't have a similar methodology.

usual is to send in url or POST body
name=value&name2=value2&...

and then read server.arg("name") or server.arg("name2"). it returns the value

Juraj:
usual is to send in url or POST body
name=value&name2=value2&...

and then read server.arg("name") or server.arg("name2"). it returns the value

Not my question or issue. I've got that part covered.

you can't use switch() on String

J-M-L:
you can't use switch() on String

Yup just figured that out :wink: Bunch of conditionals it is!

the compiled sketch doesn't contain variable names. they are not available at runtime

alex_fagard:
Probably because in php, I can just do this: PHP Sandbox - Execute PHP code online through your browser

Just find it hard to believe c doesn't have a similar methodology.

Yeah, PHPis interpreted, running on top of mature operating system, with tons of memory and multi-core GHz CPUs... so all the information about variable names etc is there and you can do fancy stuff...

with C or C++ you are compiled, all information about variable names disappear and are replaced by pointers in memory... and when you are on a small micro-proc, you don't have much memory to play with and are very close to bare metal... You need to do a few more things yourself :slight_smile:

J-M-L:
Yeah, PHPis interpreted, running on top of mature operating system, with tons of memory and multi-core GHz CPUs... so all the information about variable names etc is there and you can do fancy stuff...

with C or C++ you are compiled, all information about variable names disappear and are replaced by pointers in memory... and when you are on a small micro-proc, you don't have much memory to play with and are very close to bare metal... You need to do a few more things yourself :slight_smile:

Certainty makes it hard to keep things DRY. But thank you for you input it has been enlightening.

Just had to make a couple of tweaks:

 server.on("/config_save", HTTP_POST, []() {
    if (server.arg("key") == "" || server.arg("val") == "") {
      return server.send(500, "text/plain", "Missing parameters.");
    }
    String key = server.arg("key");
    String value = server.arg("val");
    if (key == "irrigationStartHour") {
      config.irrigationStartHour = value.toInt();
    } else if (key == "totalRainfallCutoff") {
      config.totalRainfallCutoff = value.toFloat();
    } else if (key == "bucketSize") {
      config.bucketSize = value.toFloat();
    } else if (key == "irrigationControlDisabled") {
      config.irrigationControlDisabled = value.toInt();
    } else {
      return server.send(500, "text / plain", "Invalid key.");
    }
    saveConfig(config); // commit change
    server.send(200, "text / plain", "Done");
  });