passing char and returning 1-wire DeviceAddress

I am working on a config.ini parser combined with a class that manages sensors in a large data collection system. One type of sensors we are using are 1-Wire which have address of the type deviceAddress which is an array of eight uint8_t. I am using the excellent code inifile by Steve Marple to which I have added code for handling 1-Wire addresses in the form "0x12:0x34:0x56:0x78:0x90:0x12:0x34:0x56" which works well but I do not want to repeat that block of code over and over again so I am trying to figure out how to move it out into a separate function.

Here is a simplification of the inifile code I am using:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    const size_t bufferLen = 80;
    char buffer[bufferLen];
    const char *filename = "/config.ini";
// SDI, SD, and INIFILE startup code goes here and we open and read the ini file

// now we grab the 1-wire address from the ini file
    ini.getValue("S_1WIRE_1", "ADDR", buffer, bufferLen); 

// and unpack the content with a bit of error checking 
//*******   
    uint8_t addr[8];
    int len = -1;
    if (sscanf(buffer, "%x:%x:%x:%x:%x:%x:%x:%x%n", addr + 0, addr + 1, addr + 2, addr + 3, addr + 4, addr + 5, addr + 6, addr + 7, &len) < 8 || len < 15)
    {
      Serial.println("ERROR IN CONFIG.INI   malformed 1-Wire address");
      Serial.println("HALTING");
      for (;;);
//*****
// and then put the address bytes into the class object member data for the address
               
      for (uint8_t i = 0; i < 8; i++)
      {
          S_1WIRE_1.SetAddressByte(addr[i], i);
      }


I also have a class method for taking the whole address of the 1-Wire type deviceAddress
 
S_1WIRE_1.SetAddress(deviceAddress address)


What I would really like to do is to take this code between the //**** lines above and put it in a separate function to return the deviceAddress such that I could call it in a form like this (but correct)

 
S_1WIRE_1.SetAddress(AddressUnpackingFunction(buffer));


I have tried a number of approaches to build a
deviceAddress* AddressUnpackingFunction(char* buffer)

function which would include code like this to build a deviceAddress type variable to return:
1
2
3
4
5
    deviceAddress tmpAddr;
    for(uint8_t i=0;i<8;i++)
    {
      tmpAddr[i] = addr[i];
    }


or more simply something like...
1
2
3
4
5
6
7
8
9
10
11
12
deviceAddress* AddressUnpackingFunction(char* buffer)
{
    DeviceAddress addr[8];
    int len = -1;
    if (sscanf(buffer, "%x:%x:%x:%x:%x:%x:%x:%x%n", addr + 0, addr + 1, addr + 2, addr + 3, addr + 4, addr + 5, addr + 6, addr + 7, &len) < 8 || len < 15)
    {
      Serial.println("ERROR IN CONFIG.INI   malformed 1-Wire address");
      Serial.println("HALTING");
      for (;;);
    }
    return (&addr);
} 


but have failed to make it work.

I am certain there is a simple combination of pointers, dereferencing, and perhaps converting the char to a std::string that would work but it alludes me.

Could someone give me a quick kick in the butt to get this straight? THANKS!
Last edited on
In your last code excerpt, DeviceAddress addr[8]; is a local variable. The memory for it will no longer exist once AddressUnpackingFunction returns (local variables "pop" off the stack; in C++ standardese these are objects with "automatic" storage duration). You need the memory to persist after the call is done.

If you still wanted the function to return a pointer to an array, that's fine, but the array needs to be in a larger scope (e.g. in the calling function's scope). One way to do this is to pass the addr array into the function.

1
2
3
4
5
6
7
8
9
10
11
DeviceAddress* AddressUnpackingFunction(char* buffer, DeviceAddress addr[])
{
    int len = -1;
    if (sscanf(buffer, "%x:%x:%x:%x:%x:%x:%x:%x%n", addr + 0, addr + 1, addr + 2, addr + 3, addr + 4, addr + 5, addr + 6, addr + 7, &len) < 8 || len < 15)
    {
      Serial.println("ERROR IN CONFIG.INI   malformed 1-Wire address");
      Serial.println("HALTING");
      for (;;);
    }
    return addr;
}


This makes the calling code one line longer:
1
2
DeviceAddress addr[8];
S_1WIRE_1.SetAddress(AddressUnpackingFunction(buffer, addr));


But, if S_1WIRE_1.SetAddress copies the addr array's memory into its own memory that it owns, then you could call SetAddress within your function -- then, you could just have DeviceAddress addr[8] be a variable local to the function, because it will no longer be used once the function is over. But I don't have documentation for the SetAddress function.
Last edited on
Thank you Ganado for the good insights that will help me.
The address does end up in member data of the S_1WIRE_1 object. Since there are multiple of these objects and each has a section in the config.ini file, I end up making the S_1WIRE_*,SetAddress call for each of them from the config.ini parsing program. ("*" here is a wildcard digit).
Thanks again,
Pete
Topic archived. No new replies allowed.