Question

So I am rather new to C++, and hope for some contructive advice.

I am currently working on a telemetry system for a scientific rocket which takes data from an instrument, stores the data from a pipe from a software, and subsequently sends this data to an available serialport. The problem is that the instrument transmits data packets in XML format, e.g.:

<Sample Value="-4.80521e-012" />
<Sample Value="4.90272e-012" />
<Sample Value="3.49013e-011" />
<Sample Value="2.13785e-010" />
<Sample Value="2.38185e-010" />
<Sample Value="1.70573e-010" />
<Sample Value="1.16129e-011" />

These are stored temporarily in a buffer as created by CreateFile/WriteFile (From serial port). The probe itself cannot send other formats than XML, and I need to convert this implicitly or explicitly to 4 byte hex (due to telemetry requirements), e.g.:

2c34b73f 2c1dfc77 2bbd69d2 a9220b89 a8a0cedf 290bc781...

My question is then: Can anyone suggest a good way to do this? Should I try to remove sets of substrings from the stream, or is it an easier way to translate between XML and hex? I note again that this is to be done in C++.

Best regards,

Tarjei

Was it helpful?

Solution

The question comprises 2 steps: parse XML and convert floats to their representation in IEEE 754 as Hex value.

For parsing XML, there are several libraries out there you can simply reuse. You only have to consider if your input will always be a complete, valid XML, or only fragments that cannot stand by themselves. I am not sure it this is the case in your question.

For converting floats to IEEE 754 hex, most systems internally represent floats in IEEE 754. If this is the case for your system, you just have to find get to the representation.

You can use this (with input from this question):

std::string floatToIEEE754(float f) {
    if (!std::numeric_limits<float>::is_iec559) {
        std::cerr << "Not in IEEE 754 format!" << std::endl;
        return "";
    }

    std::stringstream ss;
    ss << std::hex << std::setw(2);
    ss << static_cast<int> (reinterpret_cast<unsigned char*>(&f)[0]);
    ss << static_cast<int> (reinterpret_cast<unsigned char*>(&f)[1]);
    ss << static_cast<int> (reinterpret_cast<unsigned char*>(&f)[2]);
    ss << static_cast<int> (reinterpret_cast<unsigned char*>(&f)[3]);

    // Or to get it as int:
    //int i;
    //ss >> i;
    //return i;

    return ss.str();
}

The weird casts are necessary to ensure compliance with the language. Strictly, C++ has undefined behaviour if you cast one pointer type to another (as in int i = *((int*)&f);). Only casts to char* are guaranteed to work.

If you have no strict requirements for the system, you can simplify the method as follows:

std::string floatToIEEE754(float f) {
    std::stringstream ss;
    // Treat bits of float as an int, and print them as hex
    ss << std::hex << *((int*) &f);
    return ss.str();
}

OTHER TIPS

If the data from the instrument is only very simple XML as in your example, you may not need a complete xml parser, but you could parse each line "manually".

For each line, extract the substring that represents the value :

<Sample Value="-4.80521e-012" />

becomes

-4.80521e-012

Then parse the extracted substring "-4.80521e-012" for example with sscanf or strtof in order to obtain a 32 bit float and finally cast that float to an unsigned long and sprintf("08x",..) it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top