help convert String to unsigned char

I'm becoming crazy

I'm reading from an SD card a config file and than apply it.

this is the problem:

unsigned char G_addr[10][8]; //qui memorizzo fino a 10 indirizzi da 8 bytes (64bit)

....
....
....

 void applySetting(String settingName, String settingValue ) {
 if(settingName == "number_of_key") {
 number_of_key=settingValue.toInt();
 }
 if(settingName == "key1") {
 G_addr [1] = settingValue;      <--------- THIS IS THE PROBLEM
 }

I've try to use the following codes

 strcpy((char*)settingValue.c_str(), G_addr[1]); 

 strncpy (settingValue.c_str (), G_addr[1]);

 G_addr [1] = settingValue;

the code to fill G_addr use the following code

    byte address[8]; // questo array conterrà l'indirizzo locale delle chiavi
    for(int aa=0;aa<8;aa++) G_addr[G_Devices][aa]=address[aa]; // copy address

please help me !

Thanks a lot

Daniele

What are you actually trying to do? You're passing in a String named settingValue and then doing a weird assignment:

 G_addr [1] = settingValue;

What is the index of [1] supposed to do, and why are you directly assigning a String into a single element of an unsigned char array?

thank you for your answer.

I've got G_addr ( it is unsigned char ) ( see attached file )

unsigned char G_addr[10][8]; //to store 10 address 8 bytes

now I'm reading from SD card a config file saved inside ( file is config.cfg )

the structure of this file is

number_of_key=3
key1=1234567890
key2=2345678901
key3=3456789012

now reading from this file I cant load in memory the G_addr value stored in SD card

ibutton_v3.ino (10.9 KB)

 G_addr [1] = settingValue;

This will not work. G_addr[1] is a memory adress that the compiler knows about - the adress of that second element of your array. It''s ot a thing you can change.

What you probably want to so is to change the memory at that location.
Another issue is that I don't know if the strings in that array are nul-terminated. I'm guessing they aren't - you have to rely on knowing the size.

  memcpy(&G_addr[1], settingValue, sizeof(G_addr[1]));

Of course, &G_addr[1] is the same as G_addr+1, but perhaps more explicit.

The simplest solution is to quit using String anywhere in your code. There is NOTHING that the String class can do that can not be done with string functions applied to NULL terminated arrays of chars.

thank you for your answer

I've try to change G_Addr from unsigned char to String but there were new problem

look this

String G_addr[10][8]; //store 10 index da 8 bytes (64bit)
byte G_Devices; // number of key in the bus
OneWire ow(1); // inizializza il bus onewire sulla porta n°8 (se avete collegato i sensori su un'altro pin dovete modificare qui)

but this is the problem

   for (int i=0;i<G_Devices;i++) if(CheckAddress(G_addr[i],address)) {old=true;break;} // se trovo l'indirizzo imposto old a true ed esco dal for

this is the error

ibutton_v3.ino: In function 'void lookUpKeys()':
ibutton_v3:140: error: cannot convert 'String*' to 'unsigned char*' for argument '1' to 'bool CheckAddress(unsigned char*, unsigned char*)'
ibutton_v3:148: error: invalid conversion from 'byte' to 'const char*'
ibutton_v3:148: error: initializing argument 1 of 'String& String::operator=(const char*)'
ibutton_v3.ino: In function 'void applySetting(String, String, char)':
ibutton_v3:473: error: incompatible types in assignment of 'char' to 'String [8]'
ibutton_v3:476: error: incompatible types in assignment of 'String' to 'String [8]'
ibutton_v3:477: error: 'exBoolean' was not declared in this scope
ibutton_v3:480: error: incompatible types in assignment of 'String' to 'String [8]'
ibutton_v3:481: error: 'exLong' was not declared in this scope

tryng this

 void applySetting(String settingName, String settingValue , char addr) {
 if(settingName == "number_of_key") {
 number_of_key=settingValue.toInt();
 }
 if(settingName == "key1") {
   memcpy(&G_addr[1], settingValue, sizeof(8));
// G_addr [1] = addr;
 }

this is the error

ibutton_v3.ino: In function 'void applySetting(String, String, char)':
ibutton_v3:473: error: cannot convert 'String' to 'const void*' for argument '2' to 'void* memcpy(void*, const void*, size_t)'
ibutton_v3:474: error: incompatible types in assignment of 'char' to 'unsigned char [8]'
ibutton_v3:477: error: incompatible types in assignment of 'String' to 'unsigned char [8]'
ibutton_v3:478: error: 'exBoolean' was not declared in this scope
ibutton_v3:481: error: incompatible types in assignment of 'String' to 'unsigned char [8]'
ibutton_v3:482: error: 'exLong' was not declared in this scope

I've try to change G_Addr from unsigned char to String but there were new problem

That is NOT going in the right direction. Banish the stupid String class from your memory. Forget that it exists for the sole purpose of wasting memory.

Learn to use strings.

PaulS thank you for your answer

so I'm looking to cicling store in temp [1] unsigned char the character reader

 void readSDSettings(){
   
 char character;
 String settingName;
 String settingValue;
 
 unsigned char temp [1][8];
 
 myFile = SD.open("settings.txt");
 if (myFile) {
 while (myFile.available()) {
 character = myFile.read();
 while((myFile.available()) && (character != '[')){
 character = myFile.read();
 }
 character = myFile.read();
 while((myFile.available()) && (character != '=')){
 settingName = settingName + character;
 character = myFile.read();
 }
 character = myFile.read();
 while((myFile.available()) && (character != ']')){
 
       for(int aa=0;aa<8;aa++) temp[1][aa]=character[aa]; // copia l'indirizzo

//   settingValue = settingValue + character;
 character = myFile.read();
 }

so if I wanto so store inside temp the character i should cicle the reading

but this is the error

please help me before I become crazy

ibutton_v3.ino: In function 'void readSDSettings()':
ibutton_v3:434: error: invalid types 'char[int]' for array subscript
ibutton_v3.ino: In function 'void applySetting(String, String)':
ibutton_v3:477: error: incompatible types in assignment of 'String' to 'unsigned char [8]'
ibutton_v3:480: error: incompatible types in assignment of 'String' to 'unsigned char [8]'
ibutton_v3:481: error: 'exBoolean' was not declared in this scope
ibutton_v3:484: error: incompatible types in assignment of 'String' to 'unsigned char [8]'
ibutton_v3:485: error: 'exLong' was not declared in this scope

This unsigned char temp [1][8];
worries me
Explain please.

in declaration of variable I've got a unsigned char called temp [numbero of this variable ] [lenght of this variable]

I want to read from line 1 of the sd card config file the value and copy it inside the first[1] temp variable

thank you for your help

But why have a 1 x 8 array?
What is wrong with a simple 8 element vector?
I don't understand your reasoning.

I've thinked the config file in this way

number_of key=10
key1=1234567890
key2=2345678890
ecc
ecc
ecc

so if you see my sketch you can see that the first function was reading the key if never readed)

void lookUpKeys()
{
byte address[8]; // questo array conterrà l'indirizzo locale delle chiavi

while (ow.search(address)) // loop finchè trova nuovi dispositivi
{
 if (address[0] == 0x01) // identificata chiave 1-wire
 {
  if(CheckSensor(address)==1) //se il crc ok la lettura è corretta
  {
   bool old=false;
   for (int i=0;i<G_Devices;i++) if(CheckAddress(G_addr[i],address)) {old=true;break;} // se trovo l'indirizzo imposto old a true ed esco dal for
   
   
   if(!old) // se la chiave non è ancora stata usata....

   {
     
    
    for(int aa=0;aa<8;aa++) G_addr[G_Devices][aa]=address[aa]; // copia l'indirizzo
    G_Devices++; // incrementa il numero di devices memorizzati
    
    lcd.setCursor(0, 0);
    PrintAddress(address); // stampo l'indirizzo della chiave
   }
   
   
 
  PrintAddress(address); // stampo l'indirizzo della chiave  
  digitalWrite(17, HIGH);   // accende il led sulla porta 13
  delay(500);               // aspetta un po'...
  digitalWrite(17, LOW);    //..e spegne di nuovo il led sulla porta 13
  
        relayState = !relayState;
        digitalWrite(9, relayState);
        system = relayState;
  }
}

so now I want to configure the kay by sd card so I think:

   for(int aa=0;aa<8;aa++) G_addr[G_Devices][aa]=address[aa]; // copy address
    G_Devices++; // incrementa il numero di devices memorizzati

this was the way that the original code use to store G-addr

I think so

read the value from SD card and copy inside G_addr

so G_addr is lenght 8
and max 10 G_addr

so I think that if I want to copy key1 inside the first G_addr I shoud use

G_addr[1] = key1 ( from sd card file )

ibutton.ino (8.66 KB)

I simple would like to load the ten key from SD config file stored in sd card

to do this I must read the number of the kay ( why use 10 kay if I want only 4 kays ? )

and than the address of key

    fname.toCharArray(temp,8); // Convert the string to a character array
    //G_addr[1][8] = temp;
    for(int aa=0;aa<8;aa++) G_addr[G_Devices][aa]=temp[aa]; // copia l'indirizzo

now compile withour error but I don't know if this could works

I simple would like to load the ten key from SD config file stored in sd card

So, you need an array that is 10 by 8, not 1 by 8.

now compile withour error but I don't know if this could works

The snippet does NOT compile without error for me.

Ok so I need an array 10 by 8
Better if G_addr[number_of_key][8]

So in this case I can use less than 10 kay if I want

But now I've a problem

Reading each line when I found the carriege return I must write the new key in G_addr[number_of_key+1] right ?

I can think this but I can't do in C code. I think it's stupid but I can't. Please help me more.

Thank you

PaulS please correct me I rewrite the function. I think now I'm nearest than before but you help me more !

 void read_file_contents(String fname)
  {
    // This function opens the config.dat file on the SD card, reads the contents of the file and displays
    // the contents on the serial terminal.
   
    // Declare variables
    
    lcd.clear();
    
    char temp[100]; // Since the SD functions expect a character array and not a string we have to temporarily store the string in a character array.
   
    fname.toCharArray(temp,100); // Convert the string to a character array
   
    lcd.println("Reading config File");
    delay (1200);
    config_file = SD.open(temp); // Open the configuration file
    if (config_file) 
    {
      lcd.println("Reading command file");
     
      while (config_file.available()) // While the file is available read the contents
      {
        number_of_key = config_file.readStringUntil('\n'); // Read the first line where stored number of key ( so the number of cycle for)
        G_Devices = number_of_key;   
        
        for ( int cycle = 0; cycle<number_of_key ; cycle++) 
        
            for(int aa=0;aa<8;aa++) 
            address = config_file.readStringUntil('\n'); // Read the passphrase
            G_addr[G_Devices][aa]=address[aa]; // store the reading inside G_addr
   
      }
     
    // Display the information that we read from the file
  //  Serial.print("SSID = ");
  //  Serial.println(ssid);
  //  Serial.print("Passphrase = ");
  //  Serial.println(passphrase);
    }
  
    config_file.close();  // Close the file.
}

the error is

ibutton.ino: In function 'void read_file_contents(String)':
ibutton:468: error: cannot convert 'String' to 'int' in assignment
ibutton:474: error: 'address' was not declared in this scope
ibutton:475: error: 'aa' was not declared in this scope
ibutton:475: error: 'address' was not declared in this scope
ibutton:481: error: 'ssid' was not declared in this scope
ibutton:483: error: 'passphrase' was not declared in this scope

ibutton_v5.ino (11.3 KB)

fname.toCharArray(temp,100); // Convert the string to a character array

This line doesn't convert the String to a char array, it looks at the String and RETURNS the char array inside it. You are currently throwing that char array away and still trying to use the String later.

You're also missing some braces on your for loops. They aren't really optional although the code is legal without them. Without them, only the next ONE statement belongs in the for loop and the code after that is outside of it.

Reading each line when I found the carriege return I must write the new key in G_addr[number_of_key+1] right ?

NO! That is nonsense.

You have a collection of boxes. There are 10 rows and 8 columns. Why is it so difficult to understand that a letter read from the file goes in one of the boxes? Why is it so difficult to understand that you need to keep track of which row the letter will end up on? Why is it so difficult to understand that you need to keep track of which column the letter will end up in?

Keeping track of the row and column) is dirt simple.

You have a global variable called row, initialized to 0.
You have a global variable called col, initialized to 0.

Every time you read a character from the file, test it.
If it is a carriage return, increment row and set col to 0.
Otherwise, store the character in the row'th row, in the col'th column and increment col.