Sending variable over CLI, returning the value

Is it possible to enter a variable name, say currentTemp, into the Serial mon and have the value of that var print? Any thing I've tried prints the response as "currentTemp" and not the value. If I Serial.print(currentTemp) in the loop it of course prints the value.
Thanks

The variable names disappear after the code is compiled. It’s only memory addresses and pointers,

If you want this behavior you’ll have to code specifically for this and keep the variables names and a reference to the variable within the code

Yes, a UART command string does not have any relation to the code running.
And even you provide the variable name in UART code string taken as the variable name from your source code - all these names are gone, not available in running code.

What you can do:

  • get the UART string, the "command"

  • decode the UART string received, e.g.
    decode "getVar name"

  • if you see "getVar" and you realize "name" as a valid name for your system variable, here as "CurrentTemp":

  • Read the internal variable CurrentTemp (as native C-code), convert the value into ASCII, send the result back via UART to host

Sending a string as "CurrentTemp" has no meaning for running C-code. Even sending UART commands does not mean the FW knows what to do. All must be coded (decoded as command, do an action, send back the result of the command).

Right, I understand what you're saying. What I was trying was this (I do this over telnet, but same-same idea...)

To make this reflective of the code, a var of interest is an int pumpGpm

Issue command "var read: pumpGpm"

catch it here

if (receive_commandTelnet(cmd)) {
	if (!process_coms(cmd)) {
		process_command(cmd, device_list, device_list_len, default_board);    
	}
}

lightly sanitize it here

bool receive_commandTelnet(String &string_bufferT) {
	if (tClient.available()) {
		string_bufferT = tClient.readString();
		string_bufferT.trim();
		string_bufferT.replace(" ", "");
		return true;
	}
	return false;
}

pass it to process_coms here

bool process_coms(const String &string_buffer) {
	if (string_buffer == "HELP") {
		polling = false;
		print_help();
		return true;
	}
	else if (string_buffer.startsWith("varread:")) {
		String varRead = string_buffer;
		varRead.remove(0, 8); 
		tClient.printlnf("varRead: %s => %s", varRead.c_str(), varRead.c_str());
	}
}

Yes, I know this doesn't work, it's just one of the attempts I've made. Just trying to indicate what I've been trying.

In this case, it returns: "varRead: pumpGpm => pumpGpm"
What I'm hoping for is: "varRead: pumpGpm => 60"

You are expecting the String named varRead to magically know the value of the variable whose name is contained in the String varRead. The ONLY way for that to happen is for YOUR code to parse and recognize the variable whose name is passed, and to explicitly read that variable, and print its value to the console. The variable name, by itself, CANNOT directly access the named variables value. ALL variable names are long gone, converted to memory addresses, by the time the code is uploaded to the board.

OK, magic aside, what I'm trying to do I've already conceded is incorrect. I am passing the exact name of a variable in a String. It's received. So, if a value can't be set directly, what is the indirect process to do this? I think you're saying to take the var name I send as a String and further process that but I'm missing the how part.

You've already been told:

are all your variables of the same type?

basically you need to do something like

int var1, var2, var3, var4, var5;

...

int* getVariableForName(const String &string_buffer) {
  if (string_buffer == "var1") return &var1;
  else
  if (string_buffer == "var2") return &var2;
  else
  if (string_buffer == "var3") return &var3;
  else
  if (string_buffer == "var4") return &var4;
  else
  if (string_buffer == "var5") return &var5;
  // name not found, return null
  return nullptr;
}

as only you know the name of the variables, they are gone at run time.

they are not.
I just tried this way quick and dirty and it did work.

else if (string_buffer.startsWith("varread:")) {
	String varRead = string_buffer;
	varRead.remove(0, 8); 
	String varLookup;
	if (varRead == "pumpGpm") { 
        varLookup = String(pumpGpm); 
    }
	tClient.printlnf("varRead: %s => %s", varRead.c_str(), varLookup.c_str());
}

I think what I was hoping to do was shortcut it and use the passed var name to retrieve a value without having to do a lengthy IF block.

@gfvalvo, thanks for adding to this... super helpful :+1:

No problem. Glad to point you back to the correct answer that was given in the very first reply to your post.

you could have all the names in an array (of struct including a representation of the type of variable and pointer to the variable) and then iterate over that array...

No need for them to be the same type. He wants a string he can send to the console:

int var1;
long var2;
char var4[16];
char var5;

...

void getVariableForName(const String &string_buffer) {
  Serial.print(string_buffer + "=");
  if (string_buffer == "var1") Serial.println(var1);
  else
  if (string_buffer == "var2") Serial.println(var2);
  else
  if (string_buffer == "var3")  Serial.println(var3);
  else
  if (string_buffer == "var4")  Serial.println(var4);
  else
  if (string_buffer == "var5")  Serial.println(var5);
  // name not found, return error
  Serial.println("not found");
}

OK yes in that case it does not matter indeed.

if you don't want the long if, you need to define the list of variables. Here is a (not very clean) way

test live @ ➜ sketch.ino - Wokwi Arduino and ESP32 Simulator

enum t_knownTypes : byte {INTEGER, CONST_CHAR_STAR, FLOAT};

struct t_var {
  const char * name;
  t_knownTypes type;
  void * varPtr;
};

int intVar = 3;
const char * someText = "Some Text";
float floatVar = 3.1415;

t_var variables[] = {
  {"intVar", INTEGER, &intVar},
  {"someText", CONST_CHAR_STAR, &someText},
  {"floatVar", FLOAT, &floatVar},
};


t_var * getInfoFor(const char * varName) {
  for (auto & v : variables)
    if (!strcmp(varName, v.name)) return &v;
  return nullptr;
}

void printVariable(const char * varName) {
  t_var * ptr = getInfoFor(varName);
  Serial.print(varName);
  Serial.print(F(" = ["));
  if (ptr) {
    switch (ptr->type) {
      case INTEGER: Serial.print(*((int*) ptr->varPtr)); break;
      case CONST_CHAR_STAR: Serial.print(*((const char **) ptr->varPtr)); break;
      case FLOAT: Serial.print(*((float*) ptr->varPtr)); break;
    }
    Serial.println(F("]"));
  } else Serial.println(F("unknown variable]"));
}

void setup() {
  Serial.begin(115200);
  printVariable("intVar");
  printVariable("someText");
  printVariable("floatVar");
  printVariable("does not exist");
}

void loop() {}

What you can do, is build an array of things to match:

char* sStack[ ] = {
  "DIV","MUL","ADD","SUB","Y^X","LOG","NLG","10X","1/X","e^X",
  "SQR","X^2","SIN","COS","TAN","ASN","ACS","ATN","DEG","RAD",
  "DEC", "RTT"};

Then get via serial or other what you are looking for, search the array, recover the array index, and do a switch/case.


void loop()
{
  if (verbose) { Serial.print(F("Enter Instruction: ")); }
  Serial.readBytes( Inst, 4);
  Operation = Inst; Operation.trim();

  for ( j= 0; j<operations; j++) {
    if (Operation.equalsIgnoreCase(sStack[j])) {
      if (verbose) { Serial << sStack[j] << " Found" << " at location " << j << "\n" ; }
      T0 = millis();
      break;
    }
  }
  
  switch (j) 

Play code

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.