Read JSON file and treat them as variables

Dear forum

My application requires some variables that I'd like to have optional. I currently have a 'secret.h' file filled with the variables, but that requires a recompile everytime I want to alter one or more of these variables.

The variables are e.g my Local IP addres, gateway, DNS, but also my SSID and password, and some API Identifiers that may change.

So I came up with the following:

  • create a (JSON) 'variables.txt' file in LittleFS
  • Read this file in the setup.

My variables file could look like this:

[
 { "name": "local_IP", "value": "192.168.1.5" },
 { "name": "Gateway", "value": "192.168.1.254" },
 { "name": "Subnet", "value": "255.255.255.0" },
 { "name": "primaryDNS", "value": "192.168.1.254" },
 { "name": "SSID", "value": "mySsid" },
 { "name": "Password", "value": "myphrase" },
 { "name": "SomeAPI", "value": "1234568ugerf5364747" }
] 

I then try and read this with the following snippet:

  if ((linelength = readFile(LittleFS, "variables.txt", variable_chars, sizeof(variable_chars))) > 0) {
    Serial.printf("Read %d characters from variables.txt\n", linelength);
    JsonDocument JSONvariables;
    DeserializationError error = deserializeJson(JSONvariables, variable_chars);
    if (error) {
      Serial.print("deserializeJson() failed: ");
      Serial.println(error.c_str());
    }
    else {
      for (JsonObject elem : JSONvariables.as<JsonArray>()) {
        const char* name1 = elem["name"]; 
        const char* value1 = elem["value"]; 
//        const char* unit1 = elem["unit"]; 
        Serial.println(name1);
        Serial.println(value1);
//        Serial.println(unit1);
        if (!strcmp(name1, "local_IP")) local_IP.fromString(value1);
        if (!strcmp(name1, "Gateway")) Gateway.fromString(value1); 
        if (!strcmp(name1, "Subnet")) Subnet.fromString(value1); 
        if (!strcmp(name1, "primaryDNS")) primaryDNS.fromString(value1); 
        if (!strcmp(name1, "SSID")) strcpy(mySSID, value1); 
        if (!strcmp(name1, "Password")) strcpy(myPassword, value1); 
      }
    }
  }
  else {
    Serial.println("No variables.txt.. aborting....");
  }

  if (!WiFi.config(local_IP, Gateway, Subnet, primaryDNS)) {
    Serial.println("STA Failed to configure");
  }
  

function readFile() just opens and returns all characters in the file.

This will work, however, it seems a bit lengthy.
What I'd like is a setup in which the Json in variables.txt is independent of my declared variables. So e.g if I add in variables.txt the Json line

{"name": "Pete", "value": "friend"}

I'd like to add a variable 'Pete' with the value "friend", without declaring Pete up front.

Hope the question is clear.

Maybe I am on the wrong track here. Your input is appreciated.

The 'name' in the Json is the actual variable used in my program. Can I somehow use the 'name' of the Json to define a variable? Maybe in a struct?

As I understand your question, not in C/C++.

At run time, all your nice variable names are long gone.

Even if you had a variable someVariable, there's no way to, say, let someone type in that text and have it directly mean the variable you previously declared.

And you appear to be asking for more: new variables entirely. How would these be used? in code that you wrote and compiled and knew not of them?

You are stuck with making some kind of data structure to hold nice names that are around at run time, like string constants or strings made on the fly, and an association of those nice names with some kind of real variable that can hold the appropriate data.

Like a dictionary or symbol table or lookup table kinda thing. Dynamically extendable.

This comes up quite a bit. If I've missed your point forgive me and tell me to read again or try to explain it differently.

C/C++ on microprocessors means quite a bit of being in your hands and knees.

a7

There are several ways you can do that, but do you know a wifimanager can eliminate all of that?

I actually do. But a wifimanager looks a bit like an overkill for my application. The FM I sometimes use also stores a JSON string in a file to read later at startup.

Did not examine its source yet. Might be of interest. Thanks for the pointer.

I use it anytime I want to make a wifi related sketch and I don't want to hardcode my credentials or wifi info. IIRC, it's only 4 lines of code.

The Json structure utilised by Filemanager (tzapu) is a lot simpler than my setup with "name" "value" pairs. Saves a lot of space in flash and RAM:

e.g.
{"ip":"192.168.1.50","gateway":"192.168.1.254","subnet":"255.255.255.0"}

Guess I can work with that.