{
  "name": "ThingPark Actility Uplink Converter",
  "type": "UPLINK",
  "integrationType": "THINGPARK",
  "debugMode": false,
  "debugSettings": {
    "failuresEnabled": true,
    "allEnabled": false,
    "allEnabledUntil": 0
  },
  "configuration": {
    "scriptLang": "JS",
    "decoder": "var constants = {\n  'mTypeSpr': // MAC message type\n  {\n    0: \"Join Request\",\n    1: \"Join Accept\",\n    2: \"Unconfirmed Data Up\",\n    3: \"Unconfirmed Data Down\",\n    4: \"Confirmed Data Up\",\n    5: \"Confirmed Data Down\",\n    6: \"RFU\",\n    7: \"Proprietary\"\n  },\n  'commonMessageHeaderSpr': {\n    'type': {\n      0: \"Frame pending\",\n      3: \"Position message\",\n      4: \"Energy status message\",\n      5: \"Heartbeat message\",\n      'h7': {\n        1: \"Activity Status message\",\n        2: \"Configuration message\"\n      },\n      9: \"Shutdown message\",\n      10: \"Geolocation start message\",\n      255: \"Debug message\"\n    },\n    'status7_5': {\n      0: \"Standby\",\n      1: \"Motion tracking\",\n      2: \"Permanent tracking\",\n      3: \"Motion start/end tracking\",\n      4: \"Activity tracking\",\n      5: \"OFF\"\n    },\n    'type_position_message': {\n      0: \"GPS fix:\",\n      1: \"GPS timeout\",\n      2: \"No more used.\",\n      3: \"WIFI timeout\",\n      4: \"WIFI failure\",\n      5: \"LP-GPS data (encrypted, not described in this document)\",\n      6: \"LP-GPS data (encrypted, not described in this document)\",\n      7: \"BLE beacon scan\",\n      8: \"BLE beacon failure\",\n      9: \"WIFI BSSIDs\"\n    }\n  },\n  'param': {\n    '00': \"ul_period (sec: 60 - 86400 (min 30 for US))\",\n    '01': \"lora_period (sec: 300 - 86400)\",\n    '02': \"pw_stat_period (0, 300 - 604800)\",\n    '03': \"periodic_pos_period (sec: 0, 900 - 604800)\",\n    '04': \"rezerv04\",\n    'geoloc_sensor': {\n      0: \"WIFI only\",\n      1: \"GPS only\",\n      2: \"LP-GPS (AGPS/GPS)\",\n      3: \"Reserved (do not use)\",\n      4: \"Reserved (do not use)\",\n      5: \"Multimode (WIFI + low power-GPS + GPS) (with reset to WIFI on timeout). Superseded by mode 9.\",\n      6: \"WIFI-GPS only (WIFI then GPS if WIFI fails in one geolocation cycle)\",\n      7: \"WIFI-LPGPS only (WIFI then low power GPS if WIFI fails in one geolocation cycle)\",\n      8: \"Reserved (do not use)\",\n      9: \"WIFI-LPGPS first, the WIFI-GPS until timeout, then back to WIFI-LPGPS\",\n      10: \"BLE scan only\"\n    },\n    'geoloc_method': {\n      0: \"WIFI\",\n      1: \"GPS\",\n      2: \"LP-GPS (AGPS/GPS)\",\n      3: \"WIFI-GPS only (WIFI then GPS if WIFI fails in one geolocation cycle)\",\n      4: \"WIFI-LPGPS only (WIFI then low power GPS if WIFI fails in one geolocation cycle)\",\n      5: \"BLE scan only\"\n    },\n    '07': \"rezerv07\",\n    '08': \"motion_nb_pos (1-60)\",\n    '09': \"gps_timeout (sec: 30-300)\",\n    '0a': \"agps_timeout (sec: 30-250)\",\n    '0b': \"gps_ehpe (meter: 0-100 )\",\n    '0c': \"gps_convergence (sec: 0-300)\",\n    'config_flags': {        // 0d bit(0)==0...\n      0: \"Frame pending mechanism\",\n      1: \"Activate long button press to switch to off mode\",\n      2: \"Double short press configuration: Alert (0) vs SOS (1)\",\n      3: \"Send a configuration uplink message in response to a configuration modification downlink. Used to confirm the action.\",\n      'h4': {\n        0: \"WIFI payload with Cypher\",\n        1: \"WIFI payload without Cypher\"\n      },\n      5: \"Activate BLE advertising\",\n      6: \"First WIFI scan when geolocation starts. If disabled (0), WIFI position is replaced by a \\\"geoloc start\\\" uplink message\",\n      7: \"Led blinks when a GPS fix is received. Set to enable the feature, reset to disable. FW V1-7-3 only \\\"config_flags\\\"\",\n    },\n    'transmit_strat': {        // 0e\n      0: \"Single fixed. Single TX. Use provisioned data rate.\",\n      1: \"Single random: Single TX. Rate in [SF7..SF12].\",\n      2: \"Dual random: First TX with rate in [SF7..SF8], next TX with rate in [SF9..SF12].\",\n      3: \"Dual fixed: First TX in [SF7..SF8]. Next Use provisioned data rate. (not recommended)\",\n      4: \"Network ADR. The LoRa network controls the number of transmissions.\"\n    },\n    '0f': \"BLE_beacon_count (1-4)\",\n    '10': \"BLE_beacon_timeout (sec: 1-5)\",\n    '11': \"gps_standby_timeout (sec: 10-7200 pre V1.7-3, 0-28800 post V1.7-3)\",\n    '12': \"confirmed_ul_bitmap (0x0 â€“ 0xFFFF)\",\n    '13': \"confirmed_ul_retry (0-8)\",\n    'fd': \"BLE version\",\n    'fe': \"Firmware version\"\n  },\n  'wifi_err': {\n    0: \"WIFI connection failure\",\n    1: \"Scan failure\",\n    2: \"Antenna unavailable\",\n    3: \"WIFI not supported on this device\"\n  },\n  'ble_err': {\n    0: \"BLE is not responding\",\n    1: \"Internal error\",\n    2: \"Shared antenna not available:\",\n    3: \"Scan already on going\",\n    4: \"BLE busy (should not occur)\",\n    5: \"No beacon detected\",\n    6: \"Hardware incompatibility\"\n  },\n  'encoded': {\n    'battery': {\n      'lo': 2.8, 'hi': 4.2, 'nbits': 8, 'nresv': 2, 'step_size': 5.5            //mV Battery, WiFo time out\n    },\n    'temperature': {\n      'lo': -44, 'hi': 85, 'nbits': 8, 'nresv': 0, 'step_size': 0.5           //Â°C\n    },\n    'gps_satellite': {\n      'lo': 0, 'hi': 50, 'nbits': 8, 'nresv': 0, 'step_size': 0.2             // dBm. GPS timeout\n    },\n    'gps_age': {\n      'lo': 0, 'hi': 2040, 'nbits': 8, 'nresv': 0, 'step_size': 8             // seconds. Gps_fix, \"BLE beacon scan, WIFI_BSSID_\n    },\n    'gps_ehpe': {\n      'lo': 0, 'hi': 1000, 'nbits': 8, 'nresv': 0, 'step_size': 3.9             // meters. Gps_fix Encoded form using lo= 0, hi= 1000, nbits= 8,\n    },\n    'gps_wifi': {\n      'lo': 2.8, 'hi': 4.2, 'nbits': 8, 'nresv': 2, 'step_size': 5.5             //  mV. lo=2.8, hi=4.2, nbits=8, nresv=2. It is expressed in volt with a step of 5.5mV\n    }\n  }\n};\n\n/**\n * Start decoder\n * @type {any | undefined}\n */\nvar payLoadJson = decodeToJson(payload);\nvar result = setPayload();\nvar payload_hex;\nvar payloadByte = [];\nvar telemetryC;\nvar devEuiLink;\n\n\n/** Helper functions **/\n/**\n * Parsing metadata and payload_hex\n * @param payLoadJson\n * @returns {null|{payload: {deviceType: string, telemetry: string, deviceName: string}}}\n */\nfunction setPayload() {\n  if (payLoadJson !== null) {\n    if (payLoadJson !== null && payLoadJson.length !== 0) {\n      if (payLoadJson.hasOwnProperty('DevEUI_uplink')) {\n        devEuiLink = payLoadJson.DevEUI_uplink;\n      } else if (payLoadJson.hasOwnProperty('DevEUI_downlink_Sent')) {\n        devEuiLink = payLoadJson.DevEUI_downlink_Sent;\n      }\n      if (devEuiLink !== null && devEuiLink.length !== 0) {\n        var payloadResult = getPayload();\n        if (devEuiLink.hasOwnProperty('payload_hex')) {\n          payload_hex = devEuiLink['payload_hex'];\n          if (payload_hex !== null && payload_hex.length !== 0) {\n            payload_hex = payload_hex.trim();\n            payloadByte = hexStringToBytes(payload_hex);\n            payloadResult.telemetry = (payLoadJson.hasOwnProperty('DevEUI_uplink')) ? getTelemetryUp() : getTelemetryDown();\n          }\n        } else {\n          payloadResult.telemetry = getTelemetryDown();\n        }\n        payloadResult.deviceName = devEuiLink['DevEUI'];\n        // for the sent downLink\n        telemetryC.values['sentPayloadHex'] = \"00\";\n        return payloadResult;\n      }\n    }\n  }\n  return null;\n}\n\n/**\n * Receiving telemetry by value message_type\n * @param payload_hex\n * @param payLoadJson\n * @returns {null|Telemetry }\n */\nfunction getTelemetryUp() {\n  var message_type = payloadByte[0];\n  if (message_type > 0) {\n    telemetryC = getTelemetryCommonUp();\n  }\n  switch (message_type) {\n    case 0: // \"Frame pending\"\n      return getTelemetryFramePending();\n    case 3: // Position message\n      return getTelemetryPositionMessage();\n    case 4: // Energy status message\n      return getTelemetryEnergyStatusMessage();\n    case 5: // Heartbeat message\n      return getTelemetryHeartbeat();\n    case 7: // Activity Status message & Configuration message\n      return getTelemetryActivityStatus_Configuration();\n    case 9: // Shutdown message\n      return telemetryC;\n    case 10: // Geolocation start message\n      return telemetryC;\n    case 255: // Debugg\n      return telemetryC;\n    default: // ÐÐµÑ‚ Ñ‚Ð°ÐºÐ¸Ñ… Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ð¹\n      return null;\n  }\n}\n\nfunction getTelemetryDown() {\n  telemetryC = getTelemetryCommonDown();\n  return telemetryC;\n}\n\n/**\n * Receiving telemetry by value message_type is equal to FramePending\n * @param payLoadJson\n * @returns Json {{ts: *, values: {*}}}\n */\nfunction getTelemetryFramePending() {\n  var mSecUtc = convertDateTimeISO8601_toMsUtc(payLoadJson.DevEUI_uplink[\"Time\"]);\n  ;\n  return {\n    'ts': mSecUtc,\n    'values': {\n      'ph_type': constants.commonMessageHeaderSpr.type[0],\n      'acknowledge_token': payloadByte[1]\n    }\n  };\n}\n\n/**\n * Receiving telemetry by value message_type is equal to EnergyStatusMessage\n * @param payload_hex\n * @param payloadByte\n * @param payLoadJson\n * @returns  Json {{ts: *, values: {*}}}\n */\nfunction getTelemetryEnergyStatusMessage() {\n  var telemetryC = getTelemetryCommonUp();\n  // industrial only\n  telemetryC.values['GPS_ON (sec)'] = bytesToInt(payloadByte.subarray(5, 9));\n  telemetryC.values['GPS_Standby (sec)'] = bytesToInt(payloadByte.subarray(9, 13));\n  telemetryC.values['WIFI-SCAN (number)'] = bytesToInt(payloadByte.subarray(13, 17));\n  return telemetryC;\n}\n\n/**\n * Receiving telemetry by value message_type is equal to PositionMessage\n * @param payload_hex\n * @param payloadByte\n * @param payLoadJson\n * @returns  Json {{ts: *, values: {*}}}\n */\nfunction getTelemetryPositionMessage() {\n  var typePosMessageId = payloadByte[4] & 0xf;\n  telemetryC.values['ph_typePosMessage'] = constants.commonMessageHeaderSpr.type_position_message[typePosMessageId];\n  switch (typePosMessageId) {\n    case 0:     // 0 â€\" GPS fix\n      getPosMesGPS_fix();\n      break;\n    case 1:     // 1: GPS timeout\n      getPosMesGPS_timeout();\n      break;\n    case 2:     // \"No more used.\"\n      break;\n    case 3:     // \"WIFI timeout\"\n      getPosMesWIFI_timeout();\n      break;\n    case 4:     // \"WIFI failure\"\n      getPosMesWIFI_timeout();\n      telemetryC.values['pd_WIFI_err'] = constants.wifi_err[payloadByte[11]];\n      break;\n    case 5:     // \"LP-GPS data (encrypted, not described in this document)\n      break;\n    case 6:     // \"LP-GPS data (encrypted, not described in this document)\"\n      break;\n    case 7:     // \"BLE beacon scan\"\n      getPosMesBLE_beacon_scan();\n      break;\n    case 8:      // \"BLE beacon failure\"\n      telemetryC.values['pd_BLE_err'] = constants.ble_err[payloadByte[5]];\n      break;\n    case 9:      // \"WIFI BSSIDs\"\n      getPosMesWIFI_BSSIDs();\n      break;\n    default: // ÐÐµÑ‚ Ñ‚Ð°ÐºÐ¸Ñ… Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ð¹\n  }\n  return telemetryC;\n}\n\nfunction getPosMesGPS_fix() {\n  getAge_0_7_9();\n  var latitude = payloadByte.subarray(6, 9);\n  var longiture = payloadByte.subarray(9, 12);\n  var ehpe = encodedFunction(payloadByte[12],\n    constants.encoded.gps_ehpe['nresv'],\n    constants.encoded.gps_ehpe['step_size'],\n    constants.encoded.gps_ehpe['lo'],\n    1);\n  var encrypted = payloadByte.subarray(13, 16);\n  telemetryC.values['pd_latitude'] = convertCoordinate(latitude);\n  telemetryC.values['pd_longiture'] = convertCoordinate(longiture);\n  telemetryC.values['pd_EHPE'] = ehpe;\n  telemetryC.values['pd_encrypted'] = bytesToInt(encrypted);\n}\n\nfunction getPosMesGPS_timeout() {\n  telemetryC.values['timeout_cause'] = payloadByte[5] + '-User timeout cause';\n  var sat0 = encodedFunction(payloadByte[6],\n    constants.encoded.gps_satellite['nresv'],\n    constants.encoded.gps_satellite['step_size'],\n    constants.encoded.gps_satellite['lo'],\n    1);\n  var sat1 = encodedFunction(payloadByte[7],\n    constants.encoded.gps_satellite['nresv'],\n    constants.encoded.gps_satellite['step_size'],\n    constants.encoded.gps_satellite['lo'],\n    1);\n  var sat2 = encodedFunction(payloadByte[8],\n    constants.encoded.gps_satellite['nresv'],\n    constants.encoded.gps_satellite['step_size'],\n    constants.encoded.gps_satellite['lo'],\n    1);\n  var sat3 = encodedFunction(payloadByte[9],\n    constants.encoded.gps_satellite['nresv'],\n    constants.encoded.gps_satellite['step_size'],\n    constants.encoded.gps_satellite['lo'],\n    1);\n  telemetryC.values['C/N0'] = sat0;\n  telemetryC.values['C/N1'] = sat1;\n  telemetryC.values['C/N2'] = sat2;\n  telemetryC.values['C/N3'] = sat3;\n}\n\n/**\n * Byte 5 Byte 6 Byte 7 Byte 8 Byte 9 Byte 10\n v_bat1 v_bat2 v_bat3 v_bat4 v_bat5 v_bat6\n v_bat1: encoded voltage at the start time (T0) of the WIFI scan.\n v_bat2: encoded voltage at T0 + 0.5 second.\n v_bat3: encoded voltage at T0 + 1 second.\n v_bat4: encoded voltage at T0 + 1.5 second.\n v_bat5: encoded voltage at T0 + 2 seconds.\n v_bat6: encoded voltage at T0 + 2.5 seconds.\n Notes:\n 1- Most of time a WIFI timeout occurs due to low battery.\n 2- v_bat encoding uses lo=2.8, hi=4.2, nbits=8, nresv=2. It is expressed in volt with a step of 5.5mV\n 3- Encoded form is detailed in the Encoded form section\n */\nfunction getPosMesWIFI_timeout() {\n  var bat_1 = encodedFunction(payloadByte[5],\n    constants.encoded.gps_wifi['nresv'],\n    constants.encoded.gps_wifi['step_size'],\n    constants.encoded.gps_wifi['lo'],\n    1);\n  var bat_2 = encodedFunction(payloadByte[6],\n    constants.encoded.gps_wifi['nresv'],\n    constants.encoded.gps_wifi['step_size'],\n    constants.encoded.gps_wifi['lo'],\n    1);\n  var bat_3 = encodedFunction(payloadByte[7],\n    constants.encoded.gps_wifi['nresv'],\n    constants.encoded.gps_wifi['step_size'],\n    constants.encoded.gps_wifi['lo'],\n    1);\n  var bat_4 = encodedFunction(payloadByte[8],\n    constants.encoded.gps_wifi['nresv'],\n    constants.encoded.gps_wifi['step_size'],\n    constants.encoded.gps_wifi['lo'],\n    1);\n  var bat_5 = encodedFunction(payloadByte[9],\n    constants.encoded.gps_wifi['nresv'],\n    constants.encoded.gps_wifi['step_size'],\n    constants.encoded.gps_wifi['lo'],\n    1);\n  var bat_6 = encodedFunction(payloadByte[10],\n    constants.encoded.gps_wifi['nresv'],\n    constants.encoded.gps_wifi['step_size'],\n    constants.encoded.gps_wifi['lo'],\n    1);\n  telemetryC.values['start time (T0)'] = bat_1;\n  telemetryC.values['T0 + 0.5 sec'] = bat_2;\n  telemetryC.values['T0 + 1 sec'] = bat_3;\n  telemetryC.values['T0 + 1.5 sec'] = bat_4;\n  telemetryC.values['T0 + 2 sec'] = bat_5;\n  telemetryC.values['T0 + 2.5 sec'] = bat_6;\n}\n\n/**\n * Byte5  Byte6-11  Byte12  Byte13-18  Byte19  Byte20-25  Byte26  Byte27-33  Byte34\n * Age     MAC ADR0  RSSI0   MAC ADR1   RSSI1   MAC ADR2   RSSI2   MAC ADR3   RSSI3\n */\nfunction getPosMesBLE_beacon_scan() {\n  getAge_0_7_9();\n  var data = payload_hex.substr(6 * 2, payload_hex.length);\n  var array = data.match(/.{1,14}/g);\n  var i = 0;\n  array.forEach(function (e) {\n    var adrid = getIdRssi(e);\n    telemetryC['adr_' + i] = adrid[\"id\"];\n    telemetryC['rssi_' + i] = adrid[\"rssi\"];\n    i++;\n  });\n}\n\n/**\n * Byte5 B 6-11 Byte12 B 13-18 Byte19 B 20-25 Byte26 B 27-32 Byte 33\n Age   BSSID0 RSSI0  BSSID1  RSSI1  BSSID2  RSSI2  BSSID3  RSSI3\n\n */\nfunction getPosMesWIFI_BSSIDs() {\n  getAge_0_7_9();\n  var data = payload_hex.substr(6 * 2, payload_hex.length);\n  var array = data.match(/.{1,14}/g);\n  var i = 0;\n  array.forEach(function (e) {\n    var bssid = getIdRssi(e);\n    telemetryC['bssid_' + i] = bssid[\"id\"];\n    telemetryC['rssi_' + i] = bssid[\"rssi\"];\n    i++;\n  });\n}\n\nfunction getIdRssi(e) {\n  var bssidStr = e.substr(0, 12);\n  var id = (bssidStr.match(/.{1,2}/g)).join(':');\n  var rssiInt = parseInt(e.substr(12, e.length), 16);\n  var rssi = (parseInt(rssiInt, 16) > 127) ? (128 - rssiInt) : rssiInt;\n  return {\n    \"id\": id,\n    \"rssi\": rssi\n  }\n}\n\nfunction getAge_0_7_9() {\n  var age = encodedFunction(payloadByte[5],\n    constants.encoded.gps_age['nresv'],\n    constants.encoded.gps_age['step_size'],\n    constants.encoded.gps_age['lo'],\n    1);\n  telemetryC.values['pd_age'] = age;\n}\n\n/**\n * Receiving telemetry by value message_type is equal to Heartbeat\n * @param payload_hex\n * @param payloadByte\n * @param payLoadJson\n * @returns  Json {{ts: *, values: {*}}}\n */\nfunction getTelemetryHeartbeat() {\n  telemetryC['last_reset_cause'] = payloadByte[5];\n  if (payloadByte.length > 6) {\n    //1.7-5\n    telemetryC['fW_version'] = getVersion(payloadByte[6], payloadByte[7], payloadByte[8]);\n  }\n  return telemetryC;\n}\n\n/**\n * Receiving telemetry by value message_type is equal to ActivityStatus or Configuration\n * @param payload_hex\n * @param payloadByte\n * @param payLoadJson\n * @returns  Json {{ts: *, values: {*}}}\n */\nfunction getTelemetryActivityStatus_Configuration() {\n  var tag = payloadByte[5];\n  if (tag === 1) {         // Activity status messages byte 5 ==> tag =1; Byte 6-9 BigEndian\n    telemetryC.values['Activity_counter'] = bytesToInt(payloadByte.subarray(6, 10));\n  } else if (tag === 2) {    // Configuration messages byte 5 ==> tag =2\n    var data = payload_hex.substr(6 * 2, payload_hex.length - 6 * 2);\n    var array = data.match(/.{1,10}/g);\n    array.forEach(function (element) {\n      var id = element.substr(0, 2);\n      var param = constants.param[id];\n      var valId = parseInt(element.substr(2, element.length), 16);\n      if (id === 'fe' || id === 'fd') {\n        valId = getVersion(parseInt(element.substr(2, 4), 16),\n          parseInt(element.substr(6, 2), 16),\n          parseInt(element.substr(8, 2), 16));\n      }\n      if (id === '05') {\n        valId = constants.param.geoloc_sensor[valId];\n        telemetryC.values['geoloc_sensor'] = valId;\n      } else if (id === '06') {\n        valId = constants.param.geoloc_method[valId];\n        telemetryC.values['geoloc_method'] = valId;\n      } else if (id === '0d') {\n        if (valId > 0) {\n          var byteStr = element.substr(element.length - 2, 2);\n          telemetryC = getConfigFlags(telemetryC, byteStr, 'config_flags_bit_');\n        }\n      } else if (id === '0e') {\n        valId = constants.param.transmit_strat[valId];\n        telemetryC.values['transmit_strat'] = valId;\n      } else {\n        telemetryC.values[param] = valId;\n      }\n    });\n  }\n  return telemetryC;\n}\n\n/**\n * Receiving common telemetry by any value message_type\n * @param payloadByte\n * @param payLoadJson\n * @returns  Json {{ts: *, values: {*}}}\n */\nfunction getTelemetryCommonUp() {\n  if (payLoadJson.hasOwnProperty('DevEUI_uplink')) {\n    var byteStatus = payloadByte[1];\n    var battery = encodedFunction(payloadByte[2],\n      constants.encoded.battery['nresv'],\n      constants.encoded.battery['step_size'],\n      constants.encoded.battery['lo'],\n      100);\n    var temperature = encodedFunction(payloadByte[3],\n      constants.encoded.temperature['nresv'],\n      constants.encoded.temperature['step_size'],\n      constants.encoded.temperature['lo'],\n      1);\n    var mSecUtc = convertDateTimeISO8601_toMsUtc(devEuiLink[\"Time\"]);\n    var phTypeId = payloadByte[0];\n    var phType;\n    if (phTypeId === 7) {\n      phType = constants.commonMessageHeaderSpr.type.h7[payloadByte[5]];\n    } else {\n      phType = constants.commonMessageHeaderSpr.type[phTypeId];\n    }\n    var ack = payloadByte[4] >> 4;\n  }\n  var rez = {\n    \"ts\": mSecUtc,\n    \"values\": {\n      \"batteryVoltage\": battery,\n      \"temperature\": temperature,\n      \"ph_type\": phType,\n      \"ph_status\": constants.commonMessageHeaderSpr.status7_5[byteStatus >> 5],\n      \"ph_alert_SOS_bit4\": getBit(byteStatus, (4)),\n      \"ph_tracking/idle_state_bit3\": getBit(byteStatus, (3)),\n      \"ph_tracker_is_moving_bit2\": getBit(byteStatus, (2)),\n      \"ph_periodic_position_message_bit1\": getBit(byteStatus, (1)),\n      \"ph_POD_message_bit0\": getBit(byteStatus, (0)),\n      \"m_type\": constants.mTypeSpr[devEuiLink['MType']],\n      \"m_port\": devEuiLink['FPort'],\n      \"m_customerID\": devEuiLink['CustomerID'],\n      \"m_LrrRSSI\": devEuiLink[\"LrrRSSI\"],\n      \"m_LrrSNR\": devEuiLink[\"LrrSNR\"],\n      \"m_Lrrid\": devEuiLink[\"Lrrid\"],\n      \"ack\": ack\n    }\n  };\n  return rez;\n}\n\n/**\n * Receiving common telemetry by any value message_type\n * @param payloadByte\n * @param payLoadJson\n * @returns  Json {{ts: *, values: {*}}}\n */\nfunction getTelemetryCommonDown() {\n  var mSecUtc = convertDateTimeISO8601_toMsUtc(devEuiLink[\"Time\"]);\n  var rez = {\n    \"ts\": mSecUtc,\n    \"values\": {\n      \"m_type\": constants.mTypeSpr[devEuiLink['MType']],\n      \"m_port\": devEuiLink['FPort'],\n      \"m_customerID\": devEuiLink['CustomerID'],\n      \"m_LrrRSSI\": devEuiLink[\"LrrRSSI\"],\n      \"m_LrrSNR\": devEuiLink[\"LrrSNR\"],\n      \"m_Lrrid\": devEuiLink[\"Lrrid\"]\n    }\n  };\n  return rez;\n}\n\n/**\n * Metadata\n * @returns Headers payload: {deviceType: string, telemetry: string, deviceName: string}\n */\nfunction getPayload() {\n  return {\n    'deviceName': \"\",\n    'deviceType': \"Abeeway Micro/Industrial Tracker\",\n    'telemetry': \"\"\n  }\n}\n\n/**\n *\n * @param value\n * @param nresv\n * @param step_size\n * @param lo\n * @param divider\n * @returns {number}\n */\nfunction encodedFunction(value, nresv, step_size, lo, divider) {\n  return (((value - nresv / 2) * (step_size * 10)) / 10 + lo) / divider;\n}\n\nfunction convertCoordinate(bytes) {\n  bytes = bytesToInt(bytes);\n  bytes = bytes << 8;\n  if (bytes > 0x7FFFFFFF) {                // 2147483647\n    bytes = bytes - 0x100000000;        // 4294967296\"deviceType\": \"tracker\",\n  }\n  bytes = bytes / Math.pow(10, 7);\n  return bytes;\n}\n\n/**\n *\n * @param telemetryC\n * @param byteStr\n * @param param[ '03', '4c', '00', '99', '61', '00', '4c', '47', '38', '00' ]\n * @returns telemetryC{*} with value of config_flags\n */\nfunction getConfigFlags(telemetryC, byteStr, param) {\n  var byte = parseInt(byteStr, 16);\n  for (var i = 0; i < 8; i++) {\n    if (i === 4) {\n      telemetryC.values[param + i] = constants.param.config_flags.h4[getBit(byte, i)];\n    } else {\n      if (getBit(byte, i) > 0) {\n        telemetryC.values[param + i] = constants.param.config_flags[i];\n      }\n    }\n  }\n  return telemetryC;\n}\n\nfunction getVersion(v, v0, vsub) {\n  return \"V\" + v + \".\" + v0 + \"-\" + vsub;\n}\n\nfunction hexStringToBytes(str) {\n  var array = str.match(/.{1,2}/g);\n  var a = [];\n  array.forEach(function (element) {\n    a.push(parseInt(element, 16));\n  });\n  return new Uint8Array(a);\n}\n\nfunction convertDateTimeISO8601_toMsUtc(str) {\n  return new Date(str).getTime();\n}\n\nfunction bytesToInt(bytes) {\n  var val = 0;\n  for (var j = 0; j < bytes.length; j++) {\n    val += bytes[j];\n    if (j < bytes.length - 1) {\n      val = val << 8;\n    }\n  }\n  return val;\n}\n\nfunction decodeToJson(payload) {\n  try {\n    return JSON.parse(String.fromCharCode.apply(String, payload));\n  } catch (e) {\n    return JSON.parse(JSON.stringify(payload));\n  }\n}\n\nfunction getBit(byte, bitNumber) {\n  return ((byte & (1 << bitNumber)) != 0) ? 1 : 0;\n}\n\nreturn result;",
    "tbelDecoder": "/**\n * Decodes the incoming payload and returns a structured object containing telemetry data and attributes.\n *\n * @param {byte[]} input - The raw payload received as an array of bytes.\n * @returns {Object} output - The structured output with decoded telemetry and attributes.\n */\n\nfunction decodePayload(input) {\n    // Initialize the output object with empty attributes and telemetry for clarity.\n    var result = { attributes: {}, telemetry: {}};\n\n    // Decode serial number (SN) from the first 4 bytes of the payload.\n    // Press '?' icon in the top right corner to learn more about built in helper functions and capabilities.\n    result.attributes.sn = parseBytesToInt(input, 0, 4);\n\n    // Extract the timestamp from metadata (represented in milliseconds).\n    var timestamp = metadata.ts; // ts is the timestamp parsed from the incoming message's time, or returns the current time if it cannot be parsed.\n\n    // Initialize an object to store decoded key/value telemetry data.\n    var values = {};\n\n    // Decode battery level from the 5th byte of the payload.\n    values.battery = parseBytesToInt(input, 4, 1);\n\n    // Decode temperature from the 6th and 7th bytes of the payload (divided by 100).\n    values.temperature = parseBytesToInt(input, 5, 2) / 100.0;\n\n    // Decode saturation from the 8th byte of the payload.\n    values.saturation = parseBytesToInt(input, 7, 1);\n\n    // Combine the timestamp with values and add it to the telemetry.\n    result.telemetry = {\n        ts: timestamp,\n        values: values\n    };\n\n    // Return the fully constructed output object.\n    return result;\n    // Same logic, less code:\n    // return {\n    //     attributes: {\n    //         sn: parseBytesToInt(input, 0, 4)\n    //     },\n    //     telemetry: {\n    //         ts: convertDateToTimestamp(metadata.time),\n    //         values: {\n    //             battery: parseBytesToInt(input, 4, 1),\n    //             temperature: parseBytesToInt(input, 5, 2) / 100.0,\n    //             saturation: parseBytesToInt(input, 7, 1)\n    //         }\n    //     }\n    // };\n}\n\nvar result = decodePayload(payload);\n// Uncomment this code block to overwrite values set in the main configuration window. Useful if you extract device/asset/customer/group names from the payload;\n// result.type = 'DEVICE'; // Entity type allows you to choose type of created entity. Can be 'DEVICE' or 'ASSET'.\n// result.name = 'Temperature Sensor'; // Device or asset name (the value must be unique)\n// result.profile = 'IndustrialSensorProfile'; // Device or asset profile name.\n// result.customer = 'MyCustomer'; // If customer is not null - created entity will be assigned to customer with such name.\n// result.group = 'SensorsGroup'; // If group is not null - created entity will be added to the entity group with such name.\n\n// Return the final result object.\nreturn result;",
    "encoder": null,
    "tbelEncoder": null,
    "updateOnlyKeys": [
      "eui",
      "fPort",
      "adr",
      "spreadingFactor",
      "bandwidth",
      "devAddr",
      "frequency",
      "class"
    ],
    "type": "DEVICE",
    "name": "Device $eui",
    "profile": null,
    "label": null,
    "customer": "",
    "group": "",
    "telemetry": [
      "fCnt",
      "data",
      "rssi",
      "snr",
      "channel",
      "decoded"
    ],
    "attributes": [
      "eui",
      "fPort",
      "adr",
      "spreadingFactor",
      "bandwidth",
      "devAddr",
      "frequency",
      "class"
    ]
  },
  "additionalInfo": {
    "description": ""
  },
  "edgeTemplate": false,
  "converterVersion": 2
}