Reading absolute values and alarm

hello,
we have a sensor for metering sending data:
00 23 19 27 78 01 02
Byte 2 = Absolute value of the counters (byte 1/4) = 23
byte 3 = Absolute value of the counters (byte 2/4) = 19
Byte 4 = Absolute value of the counters (byte 3/4) = 27
Byte 5 = Absolute value of the counters (byte 4/4) = 78
the real value of metering is 78271923

Byte 6 = 01 , the value x 1 = 78271923
if Byte 6 = 12 , the value x 10 = 782719230
if Byte 6 = 15 , the value x 1000 = 782719230000

byte 7 it’s an alarm info

how we can convert this data to have:

{ value :78271923,
alarm:02
}
can somebody help us?
thank you in advance

Hi @1swiss1, I think that you have a choice of two main approaches to your problem.

First approach, activate one of the TTN integrations (the main ones are HTTP and MQTT) and pass the raw payload to a cloud-based system and do the processing there. The JSON that will be passed over HTTP or MQTT will include the .payload_raw field and will be in base64 (ie ascii) encoding. Then you are free to use anything in the huge range of websites, programming languages, etc. to analyse the payload.

Second approach, write a small Javascript decoder and install it via the TTN web console. Note that the decoder numbers the bytes from 0, not from 1. A very minimal decoder for the x1 multiplier would look something like:

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

  decoded.value = bytes[1] << 24 | bytes[2] << 16 | bytes[3] << 8 | bytes[4];
  decoded.alarm = bytes[6];

  // add byte[5] multiplier code in here

  return decoded;
}

This will result in there being JSON .payload_fields with value and alarm in it.

I suggest that you search on the forum for decoder as there are a lot of good examples.

Close, but this expects a signed 32 bits integer, MSB. However, given the example payload, I’d guess this is unsigned, packed binary-coded decimal, LSB.

That’s not common, and a slight waste of air time. But if I interpret the example correctly, it would need something like:

// For hexadecimal payload of 0x00 23 19 27 78 01 02
var counter =                //    decimal
    (bytes[1] & 0x0F)        //          3
  + (bytes[1] >> 4) * 1e1    //         20
  + (bytes[2] & 0x0F) * 1e2  //        900
  + (bytes[2] >> 4) * 1e3    //      1,000
  + (bytes[3] & 0x0F) * 1e4  //     70,000
  + (bytes[3] >> 4) * 1e5    //    200,000
  + (bytes[4] & 0x0F) * 1e6  //  8,000,000
  + (bytes[4] >> 4) * 1e7;   // 70,000,000
                             // ---------- +
                             // 78,271,923

Or, for an array of bytes of any length (well, maximum of 6 bytes):

/**
 * Convert the array of bytes into an unsigned integer, assuming packed
 * binary-coded decimal (BCD) with an even number of nibbles, LSB.
 */
function bcdToUint(bytes) {
  return bytes.reduceRight(function(acc, byte) {
    return 100*acc + 10*(byte >> 4) + (byte & 0x0F);
  }, 0);
}

So, to wrap up:

function toMultiplier(byte) {
  switch (byte) {
    case 0x01: return 1;
    case 0x12: return 10;
    // No multiplier for 100?
    case 0x15: return 1000;
    // Or: throw an error?
    default: return 1;
  }
}

function Decoder(bytes, port) {
  // Pass array of bytes 1..4 (up to, excluding, byte 5)
  var counter = bcdToUint(bytes.slice(1, 5));
  var multiplier = toMultiplier(bytes[5]);

  return {
    // What is bytes[0]?
    whatever: bytes[0],
    value: multiplier * counter,
    alarm: bytes[6]
  };
}

@1swiss1 can you add brand and type for future readers?

1 Like