Help with a codec

Hi,

I need some help to add some parameters to an existing working codec.

I am already retrieving the alert flags which result in a number like so

alert_flags:2048

the details of this perameter are:

Parameter: Alerts Flags
Length: 2
Description: Bit Map of Alerts Volcano flags LSB First

I then have a table representing the bits. What I need is one additional parameter which is bit 3

How do I achieve this in the chirpstack codec? I think I need to convert to binary first?

Any help would be greatly appreciated

This guide may help you.

The node will need to upload the integer as two bytes.
Then the codec will convert the two bytes back to integer.

ok, I think I got it. if anyone can spot anything wrong, please let me know

// Decode decodes an array of bytes into an object.
//  - fPort contains the LoRaWAN fPort number
//  - bytes is an array of bytes, e.g. [225, 230, 255, 0]
//  - variables contains the device variables e.g. {"calibration": "3.5"} (both the key / value are of type string)
// The function must return an object, e.g. {"temperature": 22.5}
function Decode(fport, bytes, variables) {
  console.log(bytes)
  var decoded = {};
  var frame_id = bytes[0];
  decoded.frame_id = frame_id;
  var firmware_version_1 = bytes[1];
  decoded.firmware_version_1 = firmware_version_1;
  var firmware_version_2 = bytes[2];
  decoded.firmware_version_2 = firmware_version_2;
  var eu_rssi = bytes[3];
  decoded.eu_rssi = (256 - eu_rssi) * -1;
  var last_stored_read = ((bytes[4] << 0) & 0xFF) + ((bytes[5] << 8) & 0xFFFF) + ((bytes[6] << 16) & 0xFFFFFF) + ((bytes[7] << 24) & 0xFFFFFFFF);
  decoded.last_stored_read = last_stored_read;
  var factor = bytes[8];
  decoded.factor = factor;
  var last_dl = (bytes[10] << 8) | bytes[9];
  decoded.last_dl = last_dl; 
  var dl_interval = (bytes[12] << 8) | bytes[11];
  decoded.dl_interval = dl_interval;
  var alert_flags = (bytes[14] << 8) | bytes[13];
  decoded.alert_flags = alert_flags;
  var battery_level = (bytes[16] << 8) | bytes[15];
  decoded.battery_level = battery_level / 1000;
  var number_of_deltas = (bytes.length - 17) / 2;
  decoded.number_of_deltas = number_of_deltas;
  var water_volume = decoded.last_stored_read * decoded.factor
  decoded.water_volume = water_volume;
  
  // Call the decodeVolcanoFlags function to decode the volcano alert flags
  const volcanoFlags = decodeVolcanoFlags(bytes, 15);
  decoded = { ...decoded, ...volcanoFlags }; // Add the decoded flags to the decoded object

  return decoded;
}

// Decode the 2-byte bitmap starting from the specified offset
function decodeVolcanoFlags(bytes, offset) {
  const flags = {};

  const bitmap = (bytes[offset + 1] << 8) | bytes[offset];

  // Loop through each bit in the bitmap and extract the alert flag
  for (let i = 0; i < 16; i++) {
    const alertNumber = i + 1;
    const bitValue = (bitmap & (1 << i)) >> i;
    flags[`alert${alertNumber}`] = Boolean(bitValue);
  }

  return flags;
}

Thanks for your help

execute js error: js vm error: (anonymous): Line 35:3 Unexpected reserved word (and 9 more errors

is there a secret to merging

decoded = { ...decoded, ...volcanoFlags }; // Merge the decoded and volcanoFlags objects

this seems to be throwing this error:


"execute js error: js vm error: (anonymous): Line 31:18 Unexpected token . (and 11 more errors)"

I have also tried

decoded = Object.assign({}, decoded, volcanoFlags);

But that is also in error. I have checked and can’t seem to see where I am going wrong any help would be greatly apprecaited. Herewith my latest version.

by the way, this if for an Arad Water meter. I have looked everywhere but can’t find a decent codec anywhere and hence trying to get this to work


function Decode(fport, bytes, variables) {
    console.log(bytes)
    var decoded = {};
    var frame_id = bytes[0];
    decoded.frame_id = frame_id;
    var firmware_version_1 = bytes[1];
    decoded.firmware_version_1 = firmware_version_1;
    var firmware_version_2 = bytes[2];
    decoded.firmware_version_2 = firmware_version_2;
    var eu_rssi = bytes[3];
    decoded.eu_rssi = (256 - eu_rssi) * -1;
    var last_stored_read = ((bytes[4] << 0) & 0xFF) + ((bytes[5] << 8) & 0xFFFF) + ((bytes[6] << 16) & 0xFFFFFF) + ((bytes[7] << 24) & 0xFFFFFFFF);
    decoded.last_stored_read = last_stored_read;
    var factor = bytes[8];
    decoded.factor = factor;
    var last_dl = (bytes[10] << 8) | bytes[9];
    decoded.last_dl = last_dl;
    var dl_interval = (bytes[12] << 8) | bytes[11];
    decoded.dl_interval = dl_interval;
    var alert_flags = (bytes[14] << 8) | bytes[13];
    decoded.alert_flags = alert_flags;
    var battery_level = (bytes[16] << 8) | bytes[15];
    decoded.battery_level = battery_level / 1000;
    var number_of_deltas = (bytes.length - 17) / 2;
    decoded.number_of_deltas = number_of_deltas;
    var water_volume = decoded.last_stored_read * decoded.factor
    decoded.water_volume = water_volume;

    // Call the decodeVolcanoFlags function to decode the volcano alert flags
    var volcanoFlags = decodeVolcanoFlags(bytes, 15);
    decoded = { ...decoded, ...volcanoFlags }; // Merge the decoded and volcanoFlags objects

    return decoded;
}

// Decode the 2-byte bitmap starting from the specified offset
function decodeVolcanoFlags(bytes, offset) {
    var flags = {};

    var bitmap = (bytes[offset + 1] << 8) | bytes[offset];

    flags.tamper = !!(bitmap & 0x01); // Bit 0 represents alert 1
    flags.cut_wire = !!(bitmap & 0x02); // Bit 1 represents alert 2
    flags.battery = !!(bitmap & 0x04); // Bit 2 represents alert 3
    flags.leak = !!(bitmap & 0x08); // Bit 3 represents alert 4
    flags.ccw = !!(bitmap & 0x10); // Bit 4 represents alert 5
    flags.power_down = !!(bitmap & 0x20); // Bit 5 represents alert 6
    flags.field_configuration = !!(bitmap & 0x40); // Bit 6 represents alert 7
    flags.res = !!(bitmap & 0x80); // Bit 7 represents alert 8
    flags.low_temp = !!(bitmap & 0x0100); // Bit 8 represents alert 9
    flags.qmax = !!(bitmap & 0x0200); // Bit 9 represents alert 10
    flags.poor_rf = !!(bitmap & 0x0400); // Bit 10 represents alert 11
    flags.dl_active = !!(bitmap & 0x0800); // Bit 11 represents alert 12
    flags.dl_mem_err = !!(bitmap & 0x1000); // Bit 12 represents alert 13
    flags.dl_delta_of = !!(bitmap & 0x2000); // Bit 13 represents alert 14
    flags.dl_delta_size = !!(bitmap & 0x4000); // Bit 14 represents alert 15
    flags.res2 = !!(bitmap & 0x8000); // Bit 15 represents alert 16

    return flags;
}

I finally got it working …

This is the codec for Arad water meters. It works on both Gladiator and Octave ranges.

They are pricey, but solid, utilities grade meters.

function Decode(fport, bytes, variables) {
    console.log(bytes)
    var decoded = {};
    var frame_id = bytes[0];
    decoded.frame_id = frame_id;
    var firmware_version_1 = bytes[1];
    decoded.firmware_version_1 = firmware_version_1;
    var firmware_version_2 = bytes[2];
    decoded.firmware_version_2 = firmware_version_2;
    var eu_rssi = bytes[3];
    decoded.eu_rssi = (256 - eu_rssi) * -1;
    var last_stored_read = ((bytes[4] << 0) & 0xFF) + ((bytes[5] << 8) & 0xFFFF) + ((bytes[6] << 16) & 0xFFFFFF) + ((bytes[7] << 24) & 0xFFFFFFFF);
    decoded.last_stored_read = last_stored_read;
    var factor = bytes[8];
    decoded.factor = factor;
    var last_dl = (bytes[10] << 8) | bytes[9];
    decoded.last_dl = last_dl;
    var dl_interval = (bytes[12] << 8) | bytes[11];
    decoded.dl_interval = dl_interval;
    var alert_flags = (bytes[14] << 8) | bytes[13];
    decoded.alert_flags = alert_flags;
    var flags = {};
    var bitmap = (bytes[14] << 8) | bytes[13];
    flags.tamper = !!(bitmap & 0x01);
    flags.cut_wire = !!(bitmap & 0x02);
    flags.battery = !!(bitmap & 0x04);
    flags.leak = !!(bitmap & 0x08);
    flags.ccw = !!(bitmap & 0x10);
    flags.power_down = !!(bitmap & 0x20);
    flags.field_configuration = !!(bitmap & 0x40);
    flags.res = !!(bitmap & 0x80);
    flags.low_temp = !!(bitmap & 0x0100);
    flags.qmax = !!(bitmap & 0x0200);
    flags.poor_rf = !!(bitmap & 0x0400);
    flags.dl_active = !!(bitmap & 0x0800);
    flags.dl_mem_err = !!(bitmap & 0x1000);
    flags.dl_delta_of = !!(bitmap & 0x2000);
    flags.dl_delta_size = !!(bitmap & 0x4000);
    decoded.flags = flags;
    return decoded;
}
1 Like

The codec is basically JavaScript.
The codec should be in simple JavaScript.
Glad you can make it working.