Extracting bits from hex encoded binary I've been using an Adafruit Huzzah ESP8266 Breakout to read data from an OpenTherm Gateway connected to my central heating unit, and publish that to MQTT. I'm programming the ESP8266 using the Arduino IDE.

The gateway publishes messages to the ESP8266 via serial. These messages look like this: T901812F3 or B501812F3

The first letter indicates whether the message comes from the thermostat or the boiler, while the remaining characters represent four bytes, hexadecimally encoded.

These four bytes are structured as follows:



I'm trying to extract the MSG-TYPE, DATA-ID, and DATA-VALUE from the four bytes, but I'm getting weird (to me) results. I'm new to Arduino and C in general.

I'm familiar with PHP, and extracting the data using that is easy:

$decimal = hexdec(substr("B501812F3", 1));      // 1343754995
$messageType = (($decimal &amp; 0x70000000) &gt;&gt; 28); // 5
$dataId = (($decimal &amp; 0x00FF0000) &gt;&gt; 16);      // 24
$dataValue = ($decimal &amp; 0x0000FFFF);           // 4851


However when I try something similar in the Arduino IDE, and upload it an Arduino, I get a different result:

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

    parseLine("B501812F3");
}

parseLine(char* message) {
    // Extract data
    char messageType;
    unsigned long data;
    int numberExtracted = sscanf(message, "%c%08x", &amp;messageType, &amp;data);

    // Decompose a single message
    int flag = (int) ((data &amp; 0x70000000) &gt;&gt; 28);
    unsigned char openThermId = (unsigned char)((data &amp; 0x00FF0000) &gt;&gt; 16);
    unsigned short openThermPayload = (unsigned short)(data &amp; 0x0000FFFF);

    Serial.println(data);             // 4851
    Serial.println(flag);             // 0
    Serial.println(openThermId);      // 0
    Serial.println(openThermPayload); // 4851
}


I (perhaps incorrectly) assume that the effect will be the same when I upload the code to an ESP8266.

What am I missing here? I suspect it has something to do with the different max integer value on the Arduino, but I'm not really sure how to proceed.
You're best off using strtoul():

messageType = message[0];
uint32_t data = strtoul(message + 1, NULL, 16);


The trick here is that message is just an array, so you can get the first letter with message[0]. Also, since C arrays are themselves just pointers to blocks of memory, message + 1 actually points to the location in memory of message[1], so you start processing the numbers from the second character in the string, thus omitting the first letter.

strtoul() takes a third parameter which is the base to decode from - 16 in this case for hexadecimal. 

From there you can then use your bit shifting and masking to slice up your 32-bit value into your required sub values.