Convert IP or MAC address from string to byte array (Arduino or C)

14,058

Solution 1

If you are trying to get from a string like "100.150.200.250" to a byte array like { 100, 150, 200, 250 }, you need to extract the string representation for each number and convert (parse) them into a binary representation before storing them in the byte array.

The way you are trying to do this, you are just converting the first four bytes from the string, i.e. "100.", to the binary representation of each character, which turns out to be { 49, 48, 48, 0 }. You can look that up in an ASCII table.

Also remember that, as you are storing this on a byte array, it will only support values from 0 to 255.

As you are programming on small microcontroller, I would advise against using the String class. You might run into trouble when your programs get bigger and you start using lots of strings. Try to learn how to use character arrays instead and you will avoid running into memory issues. Remember the Arduino has just 2KB of RAM!

Here is a function you can use to make that conversion using the strtoul() function:

void parseBytes(const char* str, char sep, byte* bytes, int maxBytes, int base) {
    for (int i = 0; i < maxBytes; i++) {
        bytes[i] = strtoul(str, NULL, base);  // Convert byte
        str = strchr(str, sep);               // Find next separator
        if (str == NULL || *str == '\0') {
            break;                            // No more separators, exit
        }
        str++;                                // Point to next character after separator
    }
}

You can then call it like this to convert an IP address (base 10):

const char* ipStr = "50.100.150.200";
byte ip[4];
parseBytes(ipStr, '.', ip, 4, 10);

Or like this to convert a MAC address (base 16):

const char* macStr = "90-A2-AF-DA-14-11";
byte mac[6];
parseBytes(macStr, '-', mac, 6, 16);

Solution 2

You could also use sscanf, and by the way detect invalid inputs using its return value:

byte ip[4];
if (sscanf(mString.c_str(), "%hhu.%hhu.%hhu.%hhu", ip, ip+1, ip+2, ip+3) != 4) {
  Serial.print("invalid IP: ");
  Serial.println(mString);
}

However, sscanf may not be implemented in the library for all boards, for example on esp8266 it's yet to be released in version 2.4.0.

Also, the %hhu specifier for unsigned char may be not supported in some versions, but you can use %u, read it to an unsigned long and check if the value isn't greater than 255.

Share:
14,058

Related videos on Youtube

Davide
Author by

Davide

Updated on September 16, 2022

Comments

  • Davide
    Davide over 1 year

    I would convert myString "100.200.300.400" to byte array [4]. I'm a "bit" confused, this is right or need i to use a foreach for reading a single number?

    String myString = "100.200.300.400";
    byte myByteArray[4];
    myString.getBytes(myByteArray,4);
    

    Finally I want to print to the array to serial. This should be right.

    for (i=0; i<4; i++) {
      Serial.print(myByteArray[i]);
      Serial.print("."); //delimiter
    }
    

    Were I am going wrong? I got 49,48,48,0 !

    • Eugene Sh.
      Eugene Sh. about 8 years
      49 is the Ascii for the character "1", 48 is for "0" and so on. So you are getting what would be expected.
    • David Hoelzer
      David Hoelzer about 8 years
      If you're trying to convert that to a byte array, it sounds like you just want the numbers. The problem is that you have two numbers greater than 255 and you can't store a number that large into a single byte.
    • Eugene Sh.
      Eugene Sh. about 8 years
      You need to parse this string. Look at atoi function. And the Arduino's String object has some useful methods: arduino.cc/en/Reference/StringObject
  • Davide
    Davide about 8 years
    if i have a MAC Address like "90-A2-AF-DA-14-11" could i use the same function? I think not because i don't need the byte conversion (MAC address il already hexadecimal). Wrong?
  • Luis Chavier
    Luis Chavier about 8 years
    @Davide I changed the function a bit to handle different number bases and added an example with a MAC address.