Laird RS1xx - probably a question on bit shifting

Now then,

I have a Laird RS1xx It works perfectly and I can get data from it and decode it. That is until I put the temperature probe in the freezer. At that point I’m struggling to decode the signed byte to a negative number

Essentially the 5th byte is signed and the first bit of that byte goes to a 1 when the probe goes below zero.

I should have made it clear I’m using the Payload Format in my application on TTN

I’ve spent hours trying to sort this with various but shifting alas to no avail.

Any clues would be most welcome.

Have you tried changing the payload format on sensor to LPP? TNN should decode easily and makes e.g. Cayenne dashboard integration easy :slight_smile:

This type of question really calls for an example, ie payload in hex and what the temperature should be, both for above and below zero.

Ok so here is my Payload code. It’s basically an amalgam of tests. I only want one number which is the temp of the freezer.

function Decoder(bytes, port) {

var params = {
  "temperature": null,
  "temp2": null,
  "temp_dec": null,
  "temp_int": null,
  "fulltemp": null,
  "bytes": bytes
}

 {
 params.temperature = (bytes[5]<<24>>19);
 params.temp2 = (bytes[5]>>1 );
 params.temp_dec = (bytes[4]);
 params.temp_int = (bytes[5]);
 params.fulltemp = (bytes[5] + bytes[4] / 100);
}
 {
return params;
}

}

The actual temp of the Freezer is -17c currently

This is the last payload

01010000DBF20500000000

And here is the output of the conversion

{
  "bytes": "AQEAANvyBQAAAAA=",
  "fulltemp": 244.19,
  "temp2": 121,
  "temp_dec": 219,
  "temp_int": 242,
  "temperature": -448
}

Does that help at all?

jim

You’re going to need to provide either the documentation which defines the encoding, or a range of substantially distinct examples across different known temperatures.

Most plausible guess is that the 4th and 5th bytes form a little endian 2’s complement number in 200ths of a degree C.

ie, 0xf2db is -3365, if that’s in 200ths it would be -16.825 C

One of the key gotchas with multi-byte 2’s complement values in a language without unsigned types is that you have to treat the most significant byte as signed, but the remaining bytes as unsigned.

Since you asked about bit shifting:

As a rule of thumb: when decoding numbers you’ll shift a full byte (8 bits), or sometimes a nibble (4 bits), or any multiples of that. So, the 19 bits above are really unexpected, and the result is basically the same as bytes[5]<<5 along with sign extension. What were you trying to achieve there?

This basically just divides the value by 2, discarding the rightmost bit. What were you expecting here?

If you were trying to decode a single signed byte, then in JavaScript (which for bitwise operators always assumes signed 32-bits integers) you could use:

// Sign-extend a single byte to 32 bits to make JavaScript understand
// negative values, by shifting 24 bits to the left, followed by a
// sign-propagating right shift of the same number of bits.
params.temp_int = bytes[5]<<24>>24;

The above should correctly show you the integer part for both positive and negative temperatures. If you would be combining multiple bytes, the above translates to:

// Signed integers, MSB
var int8  = bytes[0]<<24>>24;
var int16 = bytes[0]<<24>>16 | bytes[1];
var int24 = bytes[0]<<24>>8 | bytes[1]<<8 | bytes[2];
var int32 = bytes[0]<<24 | bytes[1]<<16 | bytes[2]<<8 | bytes[3];

I explained much more on shifting in Payload Format / Decode for TM-901 / N1C2 sensor from KCS TraceME - #4 by arjanvanb.

As for the (unsigned) decimal/fractional part, and even a full decoder for your device, search is your friend: see Laird RS1xx payload format. Laird is using a weird encoding for this one.

Asides: for the initialization, var params = {}; really suffices, and please see How do I format my forum post? [HowTo]

Apologies the examples I put up where copied from the code I had spent much time playing with. I should have left it as the original code. I’d got to the point of trying to test how it worked by putting in numbers and seeing what came out. By the end, I’d started just randomly hacking at it.

Indeed,

params.temp_int = bytes[5]<<24>>24;

Works it actually spits out the negative temperature as it should. I’m still not clear on the bit shifting but will read up on it so I don’t waste anyones time again.

Thank you all for your responses and thank you Arjan for the actual answer and further reading.