Refer to an array name from variable

Hi!

My code has several arrays and I am looking to change particular elements of particular arrays. for that reason I have incoming json, that contains all pointers to do so. However I have a problem with referring to an array. So here is the code for the idea what I am looking for:

//This is json message:
{"Array":"targetArr","Place":0,"Value":25}

const char* Array = doc["Array"];
byte Placeholder = doc["Place"];
float newValue = doc["Value"];

//Array[Placeholder] = newValue; //this is general idea of what I am looking for
targetArr[Placeholder] = newValue; //that works fine, except I have to refer to array name directly

I assume there is some syntax matters. I can solve this by using IF statement but I suppose that it is not the shortest way to code. Thanks a lot!

Try this method:

Otherwise post a MRE.

It is impossible to refer variables by it sourcecode names at runtime. After compiling all names of variables, arrays, structures etc - are stripped from the code, replaced by binary addresses in memory

In that case I'm assuming OP is using the ArduinoJSON library so the syntax for accessing into the document using strings is OK

if the arrays were also in a JSON documents, OP could use the string.

(but it's not the most effective storage unit)

I don't think so..

As far I see, OP get array name from JSON document, but than try to access an array in program code, not in JSON:

Yes - agreed. May be what I said came off the wrong way

what I'm saying is that if "targetArr" was an entry in a JSON containing all the arrays, OP could use that string to access the array

Thank you for correction :slight_smile:

Well, I have several arrays in my code that stores settings and with Json messages I send commands to the controller thus changing the values for these different arrays. So far my solution for this is like so:

if (Array == targetArr) {targetArr[Placeholder] = newValue};
if (Array == deviceArr) {deviceArr[Placeholder] = newValue};
// and so on

So my concern is to make this code shorter as this approach produces a lot of similar code lines.

As I said before, you can't refer variable by name, so your actual solution is a good option. I don't think you can make it shorter.
If you have a lot of such lines, you need to look at how to process them in a batch. Please show the full code for this.

Take some time and learn how to use data structures. They can also be arranged in arrays.

1 Like

Ok, then I'll live with that. :slight_smile: I do not think that batch will be needed - so far I have some 4 arrays that could be updated via json so not a very big deal for batch. Just wanted a bit cleaner code. I am always suspicious when something similar repeats. :slight_smile: My code is far from complete so I am still experimenting.

/*********
  reads ds18d20 on GPIO 15
  publish & receive from MQTT
*********/

#include <OneWire.h>
#include <DallasTemperature.h>
#include <WiFi.h>
#include <PubSubClientL.h>
#include <ArduinoJson.h>
#include <Preferences.h>

Preferences prefs;
// Data wire is plugged TO GPIO 15
#define ONE_WIRE_BUS 15

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// Number of temperature devices found
int numberOfDevices;

// We'll use this variable to store a found device address
DeviceAddress tempDeviceAddress; 


// Update these with values suitable for your network.
const char* ssid = "wi-fi";
const char* password = "";
const char* mqtt_server = "172.16.0.14";
const char* TOPIC = "Bruzis";
WiFiClient espClient;
PubSubClient client(espClient);
static char payload[1536];
#define MSG_BUFFER_SIZE  (1536)
char msg[MSG_BUFFER_SIZE];

unsigned long lastMsg = 0;

//SETTINGS MATRIX (14 relays)

int i;

//digital sensor ID address HEX
uint8_t T_ID_Arr[14][8] = {
  {0x28,0xCC,0x44,0xAD,0x5F,0x20,0x01,0x85},
  {0x28,0x6D,0x00,0x25,0x5F,0x20,0x01,0xDD},
  {0x28,0x16,0x43,0x10,0x5F,0x20,0x01,0xD3},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0}
};

byte relayArr [14] = {5, 19, 18, 17, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //corresponding relay pins
byte relayStatusArr[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //relay high/low status, 0 at the start
byte deviceArr[14] = {1, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //device code, 1-probe, 2-device, 0-unpopulated
byte logicArr[14] = {1,1,2,0,0,0,0,0,0,0,0,0,0,0}; //device logic, 1-up, 2-down, 0-unpopulated

//device pin matrix
byte D_relay_Arr[14][14] = {
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0},
  {0,1,1,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};

// User temperature settings
float targetArr[14];
float deltaArr[14]={1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

//float targetArrS[14]={26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
//float deltaArrS[14]={1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};


// END of declarations -------------------------------------------------------------------------------

void setup_wifi() {

   // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  randomSeed(micros());

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

// This function handles received command messages
void myMessageArrived(char* topic, byte* payload, unsigned int length) {
  // Convert the message payload from bytes to a string
  String message = "";
  for (unsigned int i=0; i< length; i++) {
    message = message + (char)payload[i];
  }
  // Print the message to the serial port
  Serial.print("Incoming message: ");
  Serial.println(message);

// extract values from incoming Json
StaticJsonDocument <256> doc;
deserializeJson(doc,payload);

String Array = doc["Array"];
byte Placeholder = doc["Place"];
float newValue = doc["Value"];

//Array[Placeholder] = newValue; does not work?!
if (Array == "targetArr") {targetArr[Placeholder] = newValue}
if (Array == "deltaArr") {deltaArr[Placeholder] = newValue}
// add some later  
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP32Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      
      // mqtt topic for incoming commands
      client.subscribe("ESP_in");
      
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

// function to print a device address
void printAddress(DeviceAddress deviceAddress) {
  for (uint8_t i = 0; i < 8; i++){
    if (deviceAddress[i] < 16) Serial.print("0");
      Serial.print(deviceAddress[i], HEX);
    }
}

// function to get a device address as String
String formatAddress(DeviceAddress deviceAddress)
{
  String Address;
  for (uint8_t i = 0; i < 8; i++)
  {
    if (deviceAddress[i] < 16) Address = Address + "0";
    Address = Address + String(deviceAddress[i], HEX);
  }
  Serial.println();
  Serial.println(Address);
  return Address;
}

void setup(){
  
  delay(1000);
  // start serial port
  Serial.begin(115200);

  prefs.begin("targetArr"); //namespace
  //bytes can be put/get in namespace directly see prefs2struct example
  //prefs.putBytes("targetArr", (byte*)(&targetArrS), sizeof(targetArrS));
  prefs.getBytes("targetArr", &targetArr, sizeof(targetArr));

  setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(myMessageArrived); //initializes incoming commands
  // Start up the library
  sensors.begin();
  
  // Grab a count of devices on the wire
  numberOfDevices = sensors.getDeviceCount();
  
  // locate devices on the bus
  Serial.print("Locating devices...");
  Serial.print("Found ");
  Serial.print(numberOfDevices, DEC);
  Serial.println(" devices.");

  // Loop through each device, print out address
  for(int i=0;i<numberOfDevices; i++){
    // Search the wire for address
    if(sensors.getAddress(tempDeviceAddress, i)){
      Serial.print("Found device ");
      Serial.print(i, DEC);
      Serial.print(" with address: ");
      printAddress(tempDeviceAddress);
      //Serial.println(tempDeviceAdress, DEC);
      Serial.println();
    } else {
      Serial.print("Found ghost device at ");
      Serial.print(i, DEC);
      Serial.print(" but could not detect address. Check power and cabling");
    }
  }

// Set up the relay outputs, and start them with LOW

 for (i = 0; i < 14; i++) {
  pinMode(relayArr[i], OUTPUT);
  digitalWrite(relayArr[i], LOW);
 }
   
}

//---------------------------------------------------
void cool (float tempC, int i)
{
    // need probe check if exists
        
    if(relayStatusArr[i] == 0 and tempC >= targetArr[i] + deltaArr[i]){
    digitalWrite(relayArr[i], 1);
    relayStatusArr[i] = 1;
    }
    if(relayStatusArr[i] == 1 and tempC <= targetArr[i]){
    digitalWrite(relayArr[i], 0);
    relayStatusArr[i] = 0;
    }

}
//---------------------------------------------------
void heat (float tempC, int i)
{
    if(relayStatusArr[i] == 0 and tempC <= targetArr[i] - deltaArr[i]){
    digitalWrite(relayArr[i], 1);
    relayStatusArr[i] = 1;
    }
    if(relayStatusArr[i] == 1 and tempC >= targetArr[i]){
    digitalWrite(relayArr[i], 0);
    relayStatusArr[i] = 0;
    }

}
//---------------------------------------------------
void PumpStatusCheck(int index)
{
  relayStatusArr[index] = 0;
  for (int a = 0; a < 14; a++) {
  if (D_relay_Arr[index][a] != 0) {
  relayStatusArr[index] |= relayStatusArr[a];
  }
  }
  digitalWrite(relayArr[index], relayStatusArr[index]);
}


void loop(){ 
  if (!client.connected()) {
    reconnect(); // maintain MQTT connection
  } 
  client.loop(); 

sensors.requestTemperatures();
    
for (i = 0; i < 14; i++) {
  if (deviceArr[i] == 1){ // detect probe mark in array
    //check if sensor exists
    float tempC = sensors.getTempC(T_ID_Arr[i]);
      if (logicArr[i] == 1) {
      heat(tempC, i);  
      }
      else if (logicArr[i] == 2){
      cool(tempC, i);
      }
  } else if (deviceArr[i] == 2){ //detect device mark in array
  PumpStatusCheck (i);
  }
}

long now = millis();
  if (now - lastMsg > 50000) {
    lastMsg = now;
    DynamicJsonDocument doc(1536); // maximum size for 14 boxes is recomended 1536 (min 1120)
    
  for (i = 0; i < 14; i++) {
  if (deviceArr[i] == 1){ // detect probe mark in array
    //check if sensor exists
    float tempC = sensors.getTempC(T_ID_Arr[i]);
    doc[String(i)]["T"]=round(tempC*10)/10;
    doc[String(i)]["R"]=digitalRead(relayArr[i]);
    doc[String(i)]["P"]=targetArr[i];
    doc[String(i)]["L"]=int(logicArr[i]);  
  } else if (deviceArr[i] == 2){ //detect device mark in array
    doc[String(i)]["R"]=digitalRead(relayArr[i]);
  }
}
delay(1000);
serializeJsonPretty(doc, payload);
client.publish("B_Status", payload);
//serializeJsonPretty(doc, Serial);
//Serial.println();

}
}

A quick glance at your code makes me think you need an array of 14 structs. Have you considered that, and how you would work with it in your code?

1 Like

To be honest I am not very familiar with array of structs. I looked at them when thought about saving settings into Preferences (memory) but found a bit complicated them at that moment so I switched to other problems. But yes, I had overall idea that putting all my separate arrays into one structure could be reasonable way to do. I have to learn them in order to get them work in my code.

Hello vilnis_r

Take a view to gain then knowledge.

Have a nice day and enjoy coding in C++.

1 Like

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