2

I am trying to convert a char[12] array that contains a Mac Address into a byte[6] in order to use within the Ethernet.begin method. I have tried various methods from online, but had little success to date. The char array currently contains "A4BDC334688C" and i would like a byte array containing { A4, BD, C3, etc }.

The following is extremely close to working, with the output of the following "File Opened. A4BDC334688C A4 9D C3 34 68 6C" With BD incorecctly converting to 9D, and 8C becomming 68.

#include <SPI.h>
#include <SD.h>
#include <ArduinoJson.h>

byte ByteMacAddress[6]; // RESERVED MAC ADDRESS
StaticJsonDocument<200> doc;

int ShotCount = 0;
byte buf[40];

void setup() {
  Serial.begin(9600);

  //Initialise SD Card for Config
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
  }

  // open the file for reading:
  File ConfigFile = SD.open("Config.txt");
  if (ConfigFile) {
    Serial.println("File Opened.");
  } else {
    Serial.println("error opening Config.txt");
  }

  //Deserialize Json Config in File
  delay(5);
  DeserializationError error = deserializeJson(doc, ConfigFile);
  ConfigFile.close();
  // Test if parsing succeeds.
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.c_str());
    return;
  }

  char* SDMacAddress = doc["MacAddress"];
  Serial.println(SDMacAddress);



  char arr[12];
  strcpy(arr, SDMacAddress);

  auto getNum = [](char c){ return c > '9' ? c - 'a' + 10 : c - '0'; };
  byte *ptr = ByteMacAddress;

  for(char *idx = arr ; *idx ; ++idx, ++ptr ){
    *ptr = (getNum( *idx++ ) << 4) + getNum( *idx );
  }


  //Check converted byte values.
  for( byte b : ByteMacAddress )
    Serial.println( b, HEX );  
}


void loop(){
  //Maintain DHCP Lease
  //Ethernet.maintain();

  //GetShotCount();
  delay(500);
}
  • Have you seen the function strtol(buf, &targetvariable, BASE) like it is used in the answer to this question? You could use it do convert each byte (2 characters) individually or even - via using a union - convert the whole string at once. – chrisl Oct 17 '19 at 14:53
  • 1
    In getnum you don't consider upper case letters. Are the letters all lower case or all upper case? – chrisl Oct 17 '19 at 16:01
  • usually the binary representation of MAC address is in reverse order then the hex string – Juraj Oct 17 '19 at 17:17
  • @chrisl Thank you also for your answer, I really appreciate everyone who took time to help me. – BelGaraath Oct 18 '19 at 9:16
2

Please see the comments in the code:

// SDMacAdress is zero terminated 
// (it should be because you use strcp not strncp)
// char arr[12]; you need one extra byte for the zero
char arr[13];
strcpy(arr, SDMacAddress);

auto getNum = [](char c)
{ 
  // you forgot upercase HEX letters (A-F)
  // don't use sophisticated code
  // the best programmers produce understandable code IMHO at least ;-)
  // perhaps you copied it from the internet 
  // return c > '9' ? c - 'a' + 10 : c - '0'; 

  if ( c >= '0' && c <= '9' ) return c - '0';
  if ( c >= 'a' && c <= 'f' ) return 10 + c - 'a';
  if ( c >= 'A' && c <= 'F' ) return 10 + c - 'A';

  return 0;
};

byte *ptr = ByteMacAddress;

for(char *idx = arr ; *idx ; ++idx, ++ptr )
{
  *ptr = (getNum( *idx++ ) << 4) + getNum( *idx );
}
  • Im kicking myself for that, the uppercase was the issue. And you are correct, that is copied from the internet but I had also made the same silly mistake in my attempt. Thank you very much for your time and help. – BelGaraath Oct 18 '19 at 7:34
  • I should mention, that @chrisl had had this idea before me. I just gave you an example of how to do it. Please upvote his/her (?) comment above. I did it already. ;-) – Peter Paul Kiefer Oct 18 '19 at 8:31
  • I wish I had the rep to upvote you all, alas i am a newbie here. – BelGaraath Oct 18 '19 at 9:16
0

It is not clear why you are trying to implement it from scratch. If your input is always properly formatted you can perform the conversion in one call to sscanf

char arr[] = "A4BDC334688C";
byte ByteMacAddress[6];

sscanf(arr, "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", 
  &ByteMacAddress[0],
  &ByteMacAddress[1],      
  &ByteMacAddress[2],
  &ByteMacAddress[3],
  &ByteMacAddress[4],      
  &ByteMacAddress[5]);

Of course, you can also implement it [more elegantly] through a cycle, i.e. sscanf it one byte at a time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.