TTN Smart Sensor (Pepperl-Fuchs)

Sensor

Codec Description

Codec for Pepperl-Fuchs

Codec Preview

'use strict'; function decodeUplink(input) { var hexStr = byte2HexString(input.bytes); var obj = payloadParser(hexStr); return { data: obj, warnings: [], errors: [] }; } /** * This is the function to create a payload object by decoding hex string * @param {String} hexStr * @return {Object} */ function payloadParser(hexStr) { const LoRaMessgeType = { 0: 'Unconfirmed', 1: 'Confirmed' }; const SonicBeamWidth = { 254: 'Small', 253: 'Medium', 252: 'Wide', 55: 'User-defined', }; const SonicBurstLength = { 5: 'Normal', 3: 'Short', 16: 'Very short', }; const SonicTransmittingPower = { 63: 'High', 40: 'Medium', 12: 'Low' }; const SonicSensitivity = { 63: 'Maximum', 51: 'Very high', 48: 'High', 38: 'Medium', 27: 'Low', 15: 'Minimum', }; const SonicEvaluationMethod = { 1: 'Average value' }; const SonicApplicationFilter = { 1: 'Container filling' }; const ValveStatus = { 0: 'Closed', 1: 'Open', 2: 'Undefined', 3: 'Not connected', 7: 'Not inquired' } const SensorDetails = { 0: 'Low', 1: 'High', 7: 'Not inquired', 8: 'Short circuit', 9: 'Not connected', 10: 'Invalid current level', } const ValveOpenSignal = { 1: 'Sensor 1', 2: 'Sensor 2' }; const ValveTriggerEventType = { 1: 'State change', 2: 'Valve open', 3: 'Valve closed', }; const NodeOutputLogic = { 1: 'Normally open', 2: 'Normally closed' }; const SensorStatus = { 0: 'No target detected', 1: 'Target detected', 7: 'Not inquired', 8: 'Short circuit', 9: 'Not connected', 10: 'Invalid current level', } const NodeTriggerEventType = { 1: 'State change', 2: 'Target detected', 3: 'No target detected', }; const GPSAccuracyMode = { 1: 'Eco mode', 2: 'Precision mode', }; var len; var sID; var obj = {}; obj.payload = hexStr; for (var i = 0; i < hexStr.length; i = i + 2) { len = parseInt(hexStr.substr(i, 2), 16); sID = hexStr.substr(i + 2, 4); if (sID == '0201') { // 'Temperature' obj.temp = parseFloat(hex2float(hexStr.substr(i + 6, 8)).toFixed(1)); // float } else if (sID == '0B01') { // 'Proximity' obj.proxx = parseInt(hexStr.substr(i + 6, 4), 16); // uint16 } else if (sID == '0B02') { // 'Proximity in mm' obj.proxx_mm = parseInt(hexStr.substr(i + 6, 4), 16); // uint16 } else if (sID == '0B06') { // 'Fillinglevel' obj.fillinglvl = parseInt(hexStr.substr(i + 6, 2), 16); // uint8 } else if (sID == '0B07') { // 'Amplitude' obj.amplitude = parseInt(hexStr.substr(i + 6, 2), 16); // uint8 } else if (sID == '0B08') { // 'Water Body Level' obj.water_body_level_mm = parseInt(hexStr.substr(i + 6, 4), 16); // uint16 } else if (sID == '0C01') { // 'Valve' obj.valve = parseInt(hexStr.substr(i + 6, 2), 16); // uint8 obj.valveChecksum = parseInt(hexStr.substr(i + 8, 2), 16); // uint8 } else if (sID == '0C02') { // 'Valve Status' obj.valve_status = parseInt(hexStr.substr(i + 6, 2), 16); // uint8 const valve1Status = obj.valve_status & 0x0F; const valve2Status = (obj.valve_status >> 4) & 0x0F; obj.valve_1_status = (ValveStatus[valve1Status] ? ValveStatus[valve1Status] : 'Invalid'); obj.valve_2_status = (ValveStatus[valve2Status] ? ValveStatus[valve2Status] : 'Invalid'); } else if (sID == '0C03') { // 'Sensor Details' obj.sensor_details = parseInt(hexStr.substr(i + 6, 4), 16); // uint16 const sensor1details = obj.sensor_details & 0x000F; const sensor2details = (obj.sensor_details >> 4) & 0x000F; const sensor3details = (obj.sensor_details >> 8) & 0x000F; const sensor4details = (obj.sensor_details >> 12) & 0x000F; obj.sensor_1_details = (SensorDetails[sensor1details] ? SensorDetails[sensor1details] : 'Invalid'); obj.sensor_2_details = (SensorDetails[sensor2details] ? SensorDetails[sensor2details] : 'Invalid'); obj.sensor_3_details = (SensorDetails[sensor3details] ? SensorDetails[sensor3details] : 'Invalid'); obj.sensor_4_details = (SensorDetails[sensor4details] ? SensorDetails[sensor4details] : 'Invalid'); } else if (sID == '0C04') { // 'Sensor Status' obj.sensor_status = parseInt(hexStr.substr(i + 6, 2), 16); // uint8 const sensor1Status = obj.sensor_status & 0x0F; const sensor2Status = (obj.sensor_status >> 4) & 0x0F; obj.sensor_1_status = (SensorStatus[sensor1Status] ? SensorStatus[sensor1Status] : 'Invalid'); obj.sensor_2_status = (SensorStatus[sensor2Status] ? SensorStatus[sensor2Status] : 'Invalid'); } else if (sID == '2A25') { // 'Serial Number' obj.serial_nr = hex2string(hexStr.substr(i + 6, 28)); } else if (sID == '2A26') { // 'Serial Number - 6 bytes uint' obj.serial_nr_uint = parseInt(hexStr.substr(i + 6, 12), 16); // uint24 } else if (sID == '3101') { // 'LoRa Transmission Counter' obj.lora_count = parseInt(hexStr.substr(i + 6, 4), 16); // uint16 } else if (sID == '3102') { // 'GPS Acquisition Counter' obj.gps_count = parseInt(hexStr.substr(i + 6, 4), 16); // uint16 } else if (sID == '3103') { // 'US Measurement Counter' obj.us_sensor_count = parseInt(hexStr.substr(i + 6, 8), 16); // uint32 } else if (sID == '3104') { // 'Sensor Measurement Counter' obj.sensing_count = parseInt(hexStr.substr(i + 6, 8), 16); // uint32 } else if (sID == '5001') { // 'GPS Latitude' obj.latitude = parseFloat((number2Int32(parseInt(hexStr.substr(i + 6, 8), 16)) / 1000000).toFixed(6)); } else if (sID == '5002') { // 'GPS Longitude' obj.longitude = parseFloat((number2Int32(parseInt(hexStr.substr(i + 6, 8), 16)) / 1000000).toFixed(6)); } else if (sID == '5101') { // 'Battery' if (parseInt(hexStr.substr(i + 4, 2), 16) == 1) { obj.battery_vol = parseInt(hexStr.substr(i + 6, 2), 16) / 10; // uint8 } } // Downlink ACK: Device Config else if (sID == 'F101') { obj.ble_enable = (parseInt(hexStr.substr(i + 6, 2), 16) > 0); } else if (sID == 'F102') { obj.device_name = hex2string(hexStr.substr(i + 6, 32)); } else if (sID == 'F103') { obj.reset_counter = 'done'; } else if (sID == 'F104') { obj.factory_reset = 'done'; } else if (sID == 'F105') { obj.change_password = 'done'; } else if (sID == 'F108') { obj.device_name_1 = hex2string(hexStr.substr(i + 6, 16)); } else if (sID == 'F109') { obj.device_name_2 = hex2string(hexStr.substr(i + 6, 16)); } // Downlink ACK: GPS Config else if (sID == 'F201') { obj.gps_acquisition_active = (parseInt(hexStr.substr(i + 6, 2), 16) > 0); } else if (sID == 'F202') { obj.gps_acquisition_interval = parseInt(hexStr.substr(i + 6, 8), 16); } else if (sID == 'F203') { obj.gps_next_acquisition = parseInt(hexStr.substr(i + 6, 8), 16); } else if (sID == 'F204') { const gpsAccuracyModeIndex = parseInt(hexStr.substr(i + 6, 2), 16); obj.gps_accuracy_mode = (GPSAccuracyMode[gpsAccuracyModeIndex] ? GPSAccuracyMode[gpsAccuracyModeIndex] : 'Invalid'); } else if (sID == 'F205') { const messageTypeIndex = parseInt(hexStr.substr(i + 6, 2), 16); obj.gps_message_type = (LoRaMessgeType[messageTypeIndex] ? LoRaMessgeType[messageTypeIndex] : 'Invalid'); } else if (sID == 'F206') { obj.gps_number_of_transmission = parseInt(hexStr.substr(i + 6, 2), 16); } else if (sID == 'F207') { obj.gps_localization = 'triggered'; } // Downlink ACK: LoRa Config else if (sID == 'F301') { const messageTypeIndex = parseInt(hexStr.substr(i + 6, 2), 16); obj.lora_message_type = (LoRaMessgeType[messageTypeIndex] ? LoRaMessgeType[messageTypeIndex] : 'Invalid'); } else if (sID == 'F302') { obj.lora_number_of_transmission = parseInt(hexStr.substr(i + 6, 2), 16); } else if (sID == 'F303') { const spreadingFactor = parseInt(hexStr.substr(i + 6, 2), 16); obj.lora_spreading_factor = (spreadingFactor == 255 ? 'ADR' : spreadingFactor); } else if (sID == 'F304') { obj.lora_data_transmission_active = (parseInt(hexStr.substr(i + 6, 2), 16) > 0); } else if (sID == 'F305') { obj.lora_transmission_interval = parseInt(hexStr.substr(i + 6, 8), 16); } else if (sID == 'F306') { obj.lora_next_transmission = parseInt(hexStr.substr(i + 6, 8), 16); } else if (sID == 'F307') { obj.lora_downlink_config = (parseInt(hexStr.substr(i + 6, 2), 16) > 0); } else if (sID == 'F308') { obj.lora_downlink_config_ack = (parseInt(hexStr.substr(i + 6, 2), 16) > 0); } else if (sID == 'F309') { obj.lora_sub_band = parseInt(hexStr.substr(i + 6, 2), 16); } // Downlink ACK: UltraSonic Config else if (sID == 'F401') { const SonicBeamWidthVal = parseInt(hexStr.substr(i + 6, 2), 16); obj.us_beam_width = (SonicBeamWidth[SonicBeamWidthVal] ? SonicBeamWidth[SonicBeamWidthVal] : 'Invalid'); } else if (sID == 'F402') { const SonicBurstLengthVal = parseInt(hexStr.substr(i + 6, 2), 16); obj.us_user_defined_burst_length = (SonicBurstLength[SonicBurstLengthVal] ? SonicBurstLength[SonicBurstLengthVal] : SonicBurstLengthVal); } else if (sID == 'F403') { const SonicTransmittingPowerVal = parseInt(hexStr.substr(i + 6, 2), 16); obj.us_user_defined_transmitting_power = (SonicTransmittingPower[SonicTransmittingPowerVal] ? SonicTransmittingPower[SonicTransmittingPowerVal] : SonicTransmittingPowerVal); } else if (sID == 'F404') { const SonicSensitivityVal = parseInt(hexStr.substr(i + 6, 2), 16); obj.us_user_defined_sensitivity = (SonicSensitivity[SonicSensitivityVal] ? SonicSensitivity[SonicSensitivityVal] : SonicSensitivityVal); } else if (sID == 'F405') { obj.us_full_distance = parseInt(hexStr.substr(i + 6, 4), 16); } else if (sID == 'F406') { obj.us_empty_distance = parseInt(hexStr.substr(i + 6, 4), 16); } else if (sID == 'F407') { obj.us_measurement_sequence_active = (parseInt(hexStr.substr(i + 6, 2), 16) > 0); } else if (sID == 'F408') { const evaluationMethodVal = parseInt(hexStr.substr(i + 6, 2), 16); obj.us_evaluation_method = (SonicEvaluationMethod[evaluationMethodVal] ? SonicEvaluationMethod[evaluationMethodVal] : 'Invalid'); } else if (sID == 'F409') { obj.us_measurements_per_sequence = parseInt(hexStr.substr(i + 6, 2), 16); } else if (sID == 'F40A') { obj.us_at_intervals_of = parseInt(hexStr.substr(i + 6, 4), 16); } else if (sID == 'F40B') { obj.us_application_filter_active = (parseInt(hexStr.substr(i + 6, 2), 16) > 0); } else if (sID == 'F40C') { const filterVal = parseInt(hexStr.substr(i + 6, 2), 16); obj.us_post_processing_filter = (SonicApplicationFilter[filterVal] ? SonicApplicationFilter[filterVal] : 'Invalid'); } else if (sID == 'F40D') { obj.us_additional_measurement = parseInt(hexStr.substr(i + 6, 2), 16); } else if (sID == 'F40E') { obj.water_body_level_active = parseInt(hexStr.substr(i + 6, 2), 16); } else if (sID == 'F40F') { obj.distance_to_water_body_ground = parseInt(hexStr.substr(i + 6, 4), 16); } // Downlink ACK: Device Information else if (sID == 'F501') { obj.part_number = parseInt(hexStr.substr(i + 6, 8), 16); } else if (sID == 'F502') { const major = parseInt(hexStr.substr(i + 6, 4), 16); const minor = parseInt(hexStr.substr(i + 10, 4), 16); const patch = parseInt(hexStr.substr(i + 14, 4), 16); obj.hardware_revision = major + '.' + minor + '.' + patch; } else if (sID == 'F503') { const major = parseInt(hexStr.substr(i + 6, 4), 16); const minor = parseInt(hexStr.substr(i + 10, 4), 16); const patch = parseInt(hexStr.substr(i + 14, 4), 16); obj.firmware_revision = major + '.' + minor + '.' + patch; } // Downlink ACK: Valve(UCC) Config else if (sID == 'F601') { const messageTypeIndex = parseInt(hexStr.substr(i + 6, 2), 16); obj.valve_monitoring_message_type = (LoRaMessgeType[messageTypeIndex] ? LoRaMessgeType[messageTypeIndex] : 'Invalid'); } else if (sID == 'F602') { obj.valve_monitoring_interval = parseInt(hexStr.substr(i + 6, 8), 16); } // Downlink ACK: Valve Config else if (sID == 'F701') { const openSignalIndex = parseInt(hexStr.substr(i + 6, 2), 16); obj.valve_1_open_signal = (ValveOpenSignal[openSignalIndex] ? ValveOpenSignal[openSignalIndex] : 'Invalid'); } else if (sID == 'F702') { obj.valve_1_event_driven_transmission = (parseInt(hexStr.substr(i + 6, 2), 16) > 0); } else if (sID == 'F703') { const triggerEventIndex = parseInt(hexStr.substr(i + 6, 2), 16); obj.valve_1_trigger_event = (ValveTriggerEventType[triggerEventIndex] ? ValveTriggerEventType[triggerEventIndex] : 'Invalid'); } else if (sID == 'F704') { const messageTypeIndex = parseInt(hexStr.substr(i + 6, 2), 16); obj.valve_1_message_type = (LoRaMessgeType[messageTypeIndex] ? LoRaMessgeType[messageTypeIndex] : 'Invalid'); } else if (sID == 'F705') { obj.valve_1_num_of_transmission = parseInt(hexStr.substr(i + 6, 2), 16); } else if (sID == 'F706') { obj.valve_1_monitoring_interval = parseInt(hexStr.substr(i + 6, 8), 16); } else if (sID == 'F707') { const openSignalIndex = parseInt(hexStr.substr(i + 6, 2), 16); obj.valve_2_open_signal = (ValveOpenSignal[openSignalIndex] ? ValveOpenSignal[openSignalIndex] : 'Invalid'); } else if (sID == 'F708') { obj.valve_2_event_driven_transmission = (parseInt(hexStr.substr(i + 6, 2), 16) > 0); } else if (sID == 'F709') { const triggerEventIndex = parseInt(hexStr.substr(i + 6, 2), 16); obj.valve_2_trigger_event = (ValveTriggerEventType[triggerEventIndex] ? ValveTriggerEventType[triggerEventIndex] : 'Invalid'); } else if (sID == 'F70A') { const messageTypeIndex = parseInt(hexStr.substr(i + 6, 2), 16); obj.valve_2_message_type = (LoRaMessgeType[messageTypeIndex] ? LoRaMessgeType[messageTypeIndex] : 'Invalid'); } else if (sID == 'F70B') { obj.valve_2_num_of_transmission = parseInt(hexStr.substr(i + 6, 2), 16); } else if (sID == 'F70C') { obj.valve_2_monitoring_interval = parseInt(hexStr.substr(i + 6, 8), 16); } // Downlink ACK: Node Config else if (sID == 'F801') { const outputLogicIndex = parseInt(hexStr.substr(i + 6, 2), 16); obj.sensor_1_output_logic = (NodeOutputLogic[outputLogicIndex] ? NodeOutputLogic[outputLogicIndex] : 'Invalid'); } else if (sID == 'F802') { obj.sensor_1_event_driven_transmission = (parseInt(hexStr.substr(i + 6, 2), 16) > 0); } else if (sID == 'F803') { const triggerEventIndex = parseInt(hexStr.substr(i + 6, 2), 16); obj.sensor_1_trigger_event = (NodeTriggerEventType[triggerEventIndex] ? NodeTriggerEventType[triggerEventIndex] : 'Invalid'); } else if (sID == 'F804') { const messageTypeIndex = parseInt(hexStr.substr(i + 6, 2), 16); obj.sensor_1_message_type = (LoRaMessgeType[messageTypeIndex] ? LoRaMessgeType[messageTypeIndex] : 'Invalid'); } else if (sID == 'F805') { obj.sensor_1_num_of_transmission = parseInt(hexStr.substr(i + 6, 2), 16); } else if (sID == 'F806') { obj.sensor_1_monitoring_interval = parseInt(hexStr.substr(i + 6, 8), 16); } else if (sID == 'F807') { const outputLogicIndex = parseInt(hexStr.substr(i + 6, 2), 16); obj.sensor_2_output_logic = (NodeOutputLogic[outputLogicIndex] ? NodeOutputLogic[outputLogicIndex] : 'Invalid'); } else if (sID == 'F808') { obj.sensor_2_event_driven_transmission = (parseInt(hexStr.substr(i + 6, 2), 16) > 0); } else if (sID == 'F809') { const triggerEventIndex = parseInt(hexStr.substr(i + 6, 2), 16); obj.sensor_2_trigger_event = (NodeTriggerEventType[triggerEventIndex] ? NodeTriggerEventType[triggerEventIndex] : 'Invalid'); } else if (sID == 'F80A') { const messageTypeIndex = parseInt(hexStr.substr(i + 6, 2), 16); obj.sensor_2_message_type = (LoRaMessgeType[messageTypeIndex] ? LoRaMessgeType[messageTypeIndex] : 'Invalid'); } else if (sID == 'F80B') { obj.sensor_2_num_of_transmission = parseInt(hexStr.substr(i + 6, 2), 16); } else if (sID == 'F80C') { obj.sensor_2_monitoring_interval = parseInt(hexStr.substr(i + 6, 8), 16); } i = i + (len * 2); } return obj; } function byte2HexString(bytes) { var retHexString = ''; for (var i_b = 0; i_b < bytes.length; i_b++) { retHexString = retHexString.concat(('0' + (Number(bytes[i_b]).toString(16))).slice(-2).toUpperCase()); } return retHexString; } function number2Int32(value) { if (value > 0x7FFFFFFF) { return (value - 0x100000000); } return value; } function hex2string(hexx) { var hex = hexx.toString(); var str = ''; for (var j = 0; (j < hex.length && hex.substr(j, 2) !== '00'); j += 2) str += String.fromCharCode(parseInt(hex.substr(j, 2), 16)); return str; } function hex2float(hexstring) { var bytes = []; bytes[0] = parseInt(hexstring.substr(0, 2), 16); bytes[1] = parseInt(hexstring.substr(2, 2), 16); bytes[2] = parseInt(hexstring.substr(4, 2), 16); bytes[3] = parseInt(hexstring.substr(6, 2), 16); return decodeFloat(bytes, 1, 8, 23, -126, 127, false); } function decodeFloat(bytes, signBits, exponentBits, fractionBits, eMin, eMax, littleEndian) { var binary = ''; for (var z = 0, l = bytes.length; z < l; z += 1) { var bits = bytes[z].toString(2); while (bits.length < 8) { bits = '0' + bits; } if (littleEndian) { binary = bits + binary; } else { binary += bits; } } var sign = (binary.charAt(0) === '1') ? -1 : 1; var exponent = parseInt(binary.substr(signBits, exponentBits), 2) - eMax; var significandBase = binary.substr(signBits + exponentBits, fractionBits); var significandBin = '1' + significandBase; var cnt = 0; var val = 1; var significand = 0; if (exponent == -eMax) { if (significandBase.indexOf('1') === -1) return 0; else { exponent = eMin; significandBin = '0' + significandBase; } } while (cnt < significandBin.length) { significand += val * parseInt(significandBin.charAt(cnt)); val = val / 2; cnt += 1; } return sign * significand * Math.pow(2, exponent); } 

This codec is sourced from The Things Network. All rights belong to The Things Network.

This codec is licensed under the GNU General Public License v3 (GPL v3). Modifications, if any, are clearly marked. You are free to use, modify, and distribute the codec under the terms of GPL v3.

Community Feedback