Go Down

Topic: save configuration variables esp8266 via server post method (Read 112 times) previous topic - next topic

alex_fagard

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:

Code: [Select]
/**
   Config
*/
struct Config {
  int irrigationStartHour;
  float totalRainfallCutoff;
  float bucketSize;
};

Config config;


Server:

Code: [Select]
  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 ;)


J-M-L

I don't see a key entry in your Config structure
Code: [Select]
struct Config {
  int irrigationStartHour;
  float totalRainfallCutoff;
  float bucketSize;
};

Config config;
so how can this work?
Code: [Select]
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?
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

alex_fagard

I don't see a key entry in your Config structure
Code: [Select]
struct Config {
  int irrigationStartHour;
  float totalRainfallCutoff;
  float bucketSize;
};

Config config;
so how can this work?
Code: [Select]
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:

<code>
    String key = server.arg("key");
    config.key = server.arg("val");
</code>

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.

J-M-L

so you should extract both
Code: [Select]
    String theKey = server.arg("key");
    String theValue = server.arg("val");
and then check what key you go
Code: [Select]
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
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

alex_fagard

so you should extract both
Code: [Select]
    String theKey = server.arg("key");
    String theValue = server.arg("val");
and then check what key you go
Code: [Select]
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: http://sandbox.onlinephpfunctions.com/code/c6fe70ed5f77c78b61d54b51c1c3932bc7b84dad

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

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

alex_fagard

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.

J-M-L

Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

alex_fagard

you can't use switch() on String
Yup just figured that out ;) Bunch of conditionals it is!

Juraj

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

J-M-L

Probably because in php, I can just do this: http://sandbox.onlinephpfunctions.com/code/c6fe70ed5f77c78b61d54b51c1c3932bc7b84dad

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 :)
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

alex_fagard

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 :)
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:

Code: [Select]
 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");
  });

Go Up