Decode unsigned long

I want to decode an unsigned long in the ttn decoder.
The unsigned long represents an unix timestamp.
The unsigned long is sent as:

payload[0] = (timestamp & 0xFF);
payload[1] = ((timestamp >> 8) & 0xFF);
payload[2] = ((timestamp >> 16) & 0xFF);
payload[3] = ((timestamp >> 24) & 0xFF);
LoRa.sendData(payload);

My decode function look like this:

function Decoder(bytes, port) {
  // Decode an uplink message from a buffer
  // (array) of bytes to an object of fields.
  var decoded = {};

  // if (port === 1) decoded.led = bytes[0];
  var time = ((payload[0] << 0) & 0xFF) + ((payload[1] << 8) & 0xFFFF) + ((payload[2] << 16) & 0xFFFFFF) + ((payload[3] << 24) & 0xFFFFFFFF);
  decoded.time = time;
  return decoded;
}

But the payload is decoded as a long, instead of unsigned long.
Any suggestions?

What does that mean? Are you saying the value is negative after decoding?

Are you sure timestamp is an unsigned type? (How are timestamp and payload declared, on what platform, what are you sending, what is the result?)

The Decoder uses JavaScript, which does not really know longs; it only knows IEEE 754 64-bit floating point. But its maximum integer is 9007199254740991, or 253 - 1, so should still fit a 32 bit unsigned value, if you indeed send that. Even more, without explicit sign extension when decoding, negative values with fewer than 4 bytes are decoded erroneously, but positive values are not.

In the compilers I used there is no need for the & 0xFF and all when assigning a too large a value to a byte. So, after having shifted. But for what I’ve read, shifting itself may be troublesome/undefined for negative values in C/C++. (Some other languages may support >>> for explicit logical, unsigned right shifting.) I guess that’s why in the TTN documentation, the & 0xFF and all are done before shifting.

As an aside: each packet already has a timestamp from the gateway (which may be a bit later than the actual measurement, but most often suffices).

2 Likes

The timestamp is defined as unsigned long in this case. The platform is an atmel1284P with an arduino bootloader.
On this platform a long is 4 bytes.

As unix time will always be positive it will make best sense to send it as unsigned long hence it is the most byte efficient solution.
I see your point about positive numbers from two’s compliment. And from testing I also see this result that only negative numbers will fail this conversion.

Regarding the & 0xFF, i use it to make the code more clear of what happens. Maybe som compiler does not need this and some does. The point is for the human eye it is clear what happens.
I’m not sure the Arduino IDE supports the >>> operation. But here sign extension is mentioned: https://www.arduino.cc/en/Reference/Bitshift

To your side comment, yes this is true that the gateway sends an timestamp. But for my application it is not the time of interest. However one of my next problems to solve is how to syncronize the time from the gateway with the end node - But thats another topic!

That’s always good, but it’s still unclear to me what problem you are/were seeing… :wink:

I had some problems not getting the right values out of the decoder. I thought is was the decoding because i got a negative number and it worked on the MCU. But after your information and the reference to two’s compliment, it was clear that the error must be somewhere else and indeed it was the value parsed to the timestamp string which was wrong.

So problem fixed and thanks for your help! :slight_smile: