---
title: Decoder LoRaWAN – UWB anchor (TTN/Chirpstack)
description: "[decode-uwb-anchor.js](https://www.lansitec.com/wp-content/uploads/2026/08/decode-uwb-anchor.js.zip)[Download](https://www.lansitec.com/wp-content/uploads/2026/08/decode-uwb-anchor.js.zip) Below the full decoder code: ``` // UWB function decodeUplink(input) { // bytes var bytes = input.bytes; // type var type = (bytes[0] >> 4) & 0x0f; switch (type) { case 0x01: return { data: decodeRegistration(bytes) }; case 0x02:…"
url: "https://www.lansitec.com/it/docs/decoders/decoder-lorawan-uwb-anchor-ttn-chirpstack/"
updated: "2026-08-26"
category: Decoders
---

# Decoder LoRaWAN – UWB anchor (TTN/Chirpstack)

[decode-uwb-anchor.js](https://www.lansitec.com/wp-content/uploads/2026/08/decode-uwb-anchor.js.zip)[Download](https://www.lansitec.com/wp-content/uploads/2026/08/decode-uwb-anchor.js.zip)

Below the full decoder code:

```
// UWB
function decodeUplink(input) {
  // bytes
  var bytes = input.bytes;
  // type
  var type = (bytes[0] >> 4) & 0x0f;

  switch (type) {
    case 0x01:
      return { data: decodeRegistration(bytes) };

    case 0x02:
      return { data: decodeHeartbeat(bytes) };

    case 0x06:
      return { data: decodeSingleConfigurationParameter(bytes) };

    default:
      return;
  }
}

// type: 0x1 Registration
function decodeRegistration(bytes) {
  var data = {};
  data.type = "RegistrationMessage";
  data.softwareVersion = "V" + (((bytes[1] << 8) & 0xff00) | (bytes[2] & 0xff)).toString(16).toUpperCase().padStart(4, "0");
  data.hardwareVersion = "V" + (((bytes[3] << 8) & 0xff00) | (bytes[4] & 0xff)).toString(16).toUpperCase().padStart(4, "0");
  data.loraClockSyncInterval = (((bytes[9] << 8) & 0xff00) | (bytes[10] & 0xff)) + "s";
  data.loraClockSyncFreq = ((bytes[11] << 24) | (bytes[12] << 16) | (bytes[13] << 8) | bytes[14]) / 1000000;
  data.loraClockSyncSF = bytes[15];
  var loraClockSyncBWValue = bytes[16];
  if (loraClockSyncBWValue == 0) {
    data.loraClockSyncBW = "500kHz";
  } else if (loraClockSyncBWValue == 1) {
    data.loraClockSyncBW = "250kHz";
  } else if (loraClockSyncBWValue == 2) {
    data.loraClockSyncBW = "125kHz";
  }
  data.heartbeatInterval = (((bytes[17] << 8) & 0xff00) | (bytes[18] & 0xff)) * 30 + "s";

  return data;
}

// type: 0x2 Heartbeat
function decodeHeartbeat(bytes) {
  var data = {};
  data.type = "HeartbeatMessage";
  data.batteryVoltage = (bytes[5] * 0.1).toFixed(1) + "V";
  data.uwbPositioningCount = bytes[7];
  data.temperature = (((bytes[10] << 8) & 0xff00) | (bytes[11] & 0xff)) + "°C";

  return data;
}

// type: 0x6 Single Configuration Parameter
function decodeSingleConfigurationParameter(bytes) {
  var data = {};
  data.type = "ConfigurationParameterResponse";
  var parameter = [];
  let byteLength = bytes.length;
  var index = 0;
  while (index + 1 < byteLength) {
    var commandBitField = {};
    var parameterTypevalue = bytes[index + 1] & 0xff;
    commandBitField.parameterType = parameterTypevalue.toString(16).toUpperCase().padStart(2, "0");
    var commandBitFieldLength = getCommandBitFieldLength(parameterTypevalue);
    var parameterValue = getParameterValue(bytes, index, commandBitFieldLength);
    commandBitField.parameterValue = parameterValue;
    commandBitField.name = getParameterName(parameterTypevalue);
    commandBitField.parameterDefinition = getParameterDefinition(
      parameterTypevalue,
      parameterValue
    );
    index = index + commandBitFieldLength;
    parameter.push(commandBitField);
  }
  data.parameter = parameter;
  return data;
}

// getParameterValue hexString
function getParameterValue(bytes, index, length) {
  var hexString = "";
  for (var i = 2; i <= length; i++) {
    var hex = (bytes[index + i] & 0xff).toString(16).toUpperCase();
    hexString += hex.padStart(2, "0");
  }
  return hexString;
}

// getCommandBitFieldLength
function getCommandBitFieldLength(parameterType) {
  let lengths = {
    0x00: 3,
    0x01: 3,
    0x32: 2,
    0x33: 2,
    0x52: 3,
    0x53: 5,
    0x54: 2,
    0x55: 2,
    0x5E: 5,
  };
  return lengths[parameterType] ?? 0;
}

// Parameter Name
function getParameterName(parameterType) {
  let name = {
    0x00: "SoftwareVersion",
    0x01: "HBPeriod",
    0x32: "CFMMSG",
    0x33: "HBCOUNT",
    0x52: "LoRaCLKSYNCInterval",
    0x53: "LoRaCLKSYNCFrequency",
    0x54: "LoRaCLKSYNCSF",
    0x55: "LoRaCLKSYNCBW",
    0x5E: "UwbAdInterval",
  };
  return name[parameterType] ?? "No matching parameter names";
}

// Parameter Definition
function getParameterDefinition(parameterType, parameterValue) {
  var val = parseInt(parameterValue, 16);
  let name = {
    0x00: "SoftwareVersion",
    0x01: val * 30 + "s, The interval of the heartbeat message, unit: 30s",
    0x32: val + " The interval of messages that must be acknowledged",
    0x33: val + " The number of heartbeat ACK that the tracker misses",
    0x52: val + "s, LoRa clock synchronization interval, unit: 1s",
    0x53: val + " LoRa clock synchronization frequency",
    0x54: val + " LoRa clock synchronization spreading factor",
    0x55: val + " LoRa clock synchronization bandwidth",
    0x5E: val / 1000 + "s, The anchor's UWB advertises interval, unit: 1ms",
  };
  return name[parameterType] ?? "No matching parameter names";
}

// Floating point conversion
function hex2float(num) {
  num = num >>> 0;

  var sign = (num & 0x80000000) ? -1 : 1;
  var exponent = (num >>> 23) & 0xff;
  var fraction = num & 0x7fffff;

  if (exponent === 0xff) {
    return fraction === 0 ? sign * Infinity : NaN;
  }

  if (exponent === 0) {
    return fraction === 0 ? sign * 0 : sign * Math.pow(2, -126) * (fraction / 0x800000);
  }

  return sign * Math.pow(2, exponent - 127) * (1 + fraction / 0x800000);
}

function asciiToHex(str) {
  var hexString = "";
  for (let i = 0; i < str.length; i++) {
    var hex = str.charCodeAt(i).toString(16);
    hexString += hex.padStart(2, "0");
  }
  return hexString;
}

function hexStringToByteArray(hexString) {
  var byteArray = [];
  for (let i = 0; i < hexString.length; i += 2) {
    byteArray.push(parseInt(hexString.substr(i, 2), 16));
  }
  return new Uint8Array(byteArray);
}

function timestampToTime(timestamp) {
  const date = new Date(timestamp);
  const year = date.getFullYear();
  const month = (date.getMonth() + 1).toString().padStart(2, "0");
  const day = date.getDate().toString().padStart(2, "0");
  const hour = date.getHours().toString().padStart(2, "0");
  const minute = date.getMinutes().toString().padStart(2, "0");
  const second = date.getSeconds().toString().padStart(2, "0");
  return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
}
```
