Agoraopinion Feedback Button Payload decoder

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. :slight_smile:

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 yields rr0 (left shift of 4 bits; actually the result is 32 bits, so 00000rr0)
  • ry >> 4 shifts the rightmost nibble out of memory, so discards y and yields r (right shift; actually 0000000r)
  • rr0 | r yields rrr (bitwise OR)
  • ry & 0x0F yields y (bitwise AND)
  • y << 8 yields y00
  • y00 | yy yields yyy

Easy! :nerd_face:

1 Like