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);
}
BelGaraath
  • 33
  • 4

2 Answers2

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 );
}
Peter Paul Kiefer
  • 1,893
  • 9
  • 11
2

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.