1

I write to my serial device with hexadecimal represented as data = "\x35\x0d" (which is 5 and a carriage return) using this code:

    boost::asio::write(
        *serial_port,
        boost::asio::buffer(data.c_str(), data.size()), 
        boost::asio::transfer_at_least(data.size()),
        error
    );

How could I convert the string "350d" to a byte string for use in writing to my serial port? Not all of my commands will be hard coded. Thank you.

xinthose
  • 3,213
  • 3
  • 40
  • 59

2 Answers2

2

Here's some code I threw together a while back for a simple tool I was working on. This contains conversions in both directions. It's not the only way, but it's one way.

// Convert binary data to hex string
std::string to_hex( const std::vector<uint8_t> & data )
{
  std::ostringstream oss;
  oss << std::hex << std::setfill('0');
  for( uint8_t val : data )
  {
    oss << std::setw(2) << (unsigned int)val;
  }
  return oss.str();
}

// Convert hex string to binary data
std::vector<uint8_t> from_hex( const std::string & s )
{
  std::vector<uint8_t> data;
  data.reserve( s.size() / 2 );
  std::istringstream iss( s );
  iss >> std::hex;
  char block[3] = {0};
  while( iss.read( block, 2 ) )
  {
    uint8_t val = std::strtol( block, NULL, 16 );
    data.push_back( val );
  }
  return data;
}

You'll need various headers: <cstdint>, <iomanip>, <sstream>, <string>, <vector>.

paddy
  • 60,864
  • 6
  • 61
  • 103
  • thank you; I need the function to return a string though; I found sehe's answer here to be pretty good: http://stackoverflow.com/a/36627615/4056146 – xinthose Apr 15 '16 at 03:12
  • It's a bit odd to use a `std::string` for binary data, but it does work. As long as you realise you can't use C functions like `strlen` if the data contains zero values. To make this code use strings, you'd basically just switch out the vectors for strings and use `char` instead of `uint8_t`. The linked solution is a bit nicer in that it doesn't use a `stringstream`. – paddy Apr 15 '16 at 03:20
  • OK, I see. I will report back with my results at work. – xinthose Apr 15 '16 at 03:24
0

This function works for me:

std::string hex_str_to_binary(std::string hex_str) 
{
    std::string binary_str, extract_str;

    try
    {
        assert(hex_str.length() % 2 == 0);  // throw exception if string length is not even
        binary_str.reserve(hex_str.length()/2);
        for (std::string::const_iterator pos = hex_str.begin(); pos < hex_str.end(); pos += 2)
        {
            extract_str.assign(pos, pos + 2);
            binary_str.push_back(std::stoi(extract_str, nullptr, 16));
        }
    }
    catch (const std::exception &e)
    {
        std::cerr << "e.what() = " << e.what();
        throw -1;
    }

    return binary_str;
}

hex_str will look like "350d". I use lowercase letters and make sure your string has an even length and fill space with 0's. You then use this string for asio write:

    boost::asio::write(
        *serial_port,
        boost::asio::buffer(binary_str.c_str(), binary_str.size()), 
        boost::asio::transfer_at_least(binary_str.size()),
        error
    );
xinthose
  • 3,213
  • 3
  • 40
  • 59