Good, it’s not text! Even more, it only uses 1.5 bytes for a single count, not wasting anything at all. Many would simply have used 2 bytes per counter.
Then the following might work? Note that it uses a fixed-format decoder; not some loop that iterates over the payload and tries to determine how to interpret the next part by comparing to some known values, like in your attempt:
/**
* Decoder for Agora Opinion feedback button.
*/
function Decoder(bytes, port) {
var result = {};
result.payloadType = bytes[0];
// 1.5 bytes (3 nibbles) per count, plus 0.5 byte for battery,
// encoded in 5 bytes; rr ry yy gg gb
result.redCount = bytes[1]<<4 | bytes[2]>>4;
result.yellowCount = (bytes[2] & 0x0F)<<8 | bytes[3];
result.greenCount = bytes[4]<<4 | bytes[5]>>4;
// Unary-plus operator to cast string result of toFixed to number
result.batteryVoltage =
+((3 * 1.224) / (((bytes[5] & 0x0F) + 20) / 21)).toFixed(1);
return result;
}
To explain the bitwise operators, for the 5 bytes rr ry yy gg gb
, all in hexadecimal notation using two 4-bits nibbles for each 8-bits byte:
-
rr << 4
appends a nibble to the right, so yieldsrr0
(left shift of 4 bits; actually the result is 32 bits, so00000rr0
) -
ry >> 4
shifts the rightmost nibble out of memory, so discardsy
and yieldsr
(right shift; actually0000000r
) -
rr0 | r
yieldsrrr
(bitwise OR) -
ry & 0x0F
yieldsy
(bitwise AND) -
y << 8
yieldsy00
-
y00 | yy
yieldsyyy
Easy!