It seems (nowadays) It has been confirmed by Laird (see post below) that nowadays the fractional part of temperature readings is signed as well. From another topic:
That implies byte[4]
= 0xDB, being either decimal 219 or -37. So, when handling this as an unsigned integer, then this would yield a fractional part of 2.19, which is larger than 1?
According to Laird’s most recent RS1xx LoRa Protocol v2.7, emphasis mine:
Temperature, humidity and voltage values are represented as two or four-byte values, depending upon the range of the connected sensor. The first byte, or pair of bytes, is the fractional portion of the value. The second byte, or pair of bytes, is the integer portion of the value. For example, a temperature of 27.43 degrees C has a fractional portion of 43 and an integer portion of 27. A temperature of -15.87 C would have a fractional portion of -87 and an integer portion of -15. The following are the equations for temperature, humidity and voltage:
- Temp = Integer Portion + (Fractional Portion/100)
- Humidity = Integer Portion + (Fractional Portion/100)
- Voltage = Integer Portion + (Fractional Portion/100)
Note: Temperature and voltage use signed eight and sixteen-bit values, while humidity uses unsigned eight-bit values. However, because humidity cannot be negative, the sign bit is never set and there is no practical difference between using signed or unsigned values for humidity.
The very same document also mentions a signed integer int8_t
for the fractional part:
So, despite Laird’s comments in their (old) Node-RED library mentioned in the (old) posts above: given that example payload, I guess that for later versions the fractional part needs sign extension as well? A simple Decoder might then be:
/**
* Basic decoder for Laird RS1xx Sensors, only supporting message
* type 0x01 for RS1xx LoRa Protocol v2.7.
*/
function Decoder(bytes, port) {
var messageType = bytes[0];
// All Sensor-to-Server messages have the same options byte format.
// The options byte is always at byte index 1.
var options = bytes[1];
var decoded = {
messageType: messageType,
// Note: the Data Storage Integration stores nested objects as text
options: {
value: options,
// Show all 8 bits, ensuring leading zeroes
bits: ('00000000' + options.toString(2)).slice(-8),
sensorRequestForServerTime: (options & 1<<0) > 0,
sensorConfigurationError: (options & 1<<1) > 0,
sensorAlarmFlag: (options & 1<<2) > 0,
sensorResetFlag: (options & 1<<3) > 0,
sensorFaultFlag: (options & 1<<4) > 0
}
};
// 0x01 = Send Temp RH Data Notification
if (decoded.messageType === 0x01) {
decoded.humidity = bytes[3] + bytes[2]/100;
// Both the integer and fractional parts are signed.
// 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.
decoded.temperature = (bytes[5]<<24>>24) + (bytes[4]<<24>>24)/100;
decoded.batteryIndex = bytes[6];
decoded.batteryCapacity = {
0: '0-5%',
1: '5-20%',
2: '20-40%',
3: '40-60%',
4: '60-80%',
5: '80-100%'
}[decoded.batteryIndex] || 'Unsupported value';
decoded.alarmMsgCount = bytes[7]<<8 | bytes[8];
decoded.backlogMsgCount = bytes[9]<<8 | bytes[10];
}
return decoded;
}
For the above example payload, this would yield -14.37, not something around -17. To be sure, I’d look for some change logs on the Laird website.
@JimK, please report back here!