⬆️HT Sensor Uplink Decoder

var calculateTemperature = function (rawData){return (rawData - 400) / 10};
var calculateHumidity = function(rawData){return (rawData * 100) / 256};
function decbin(byte){
    return (parseInt(byte, 16).toString(2)).padStart(8, '0');
}
function Decoder(hexData){
    var data = hexData;
    var tempHex = ("0" + data[1].toString(16)).substr(-2) + ("0" + data[2].toString(16)).substr(-2);
    var tempDec = parseInt(tempHex, 16);
    var temperatureValue = calculateTemperature(tempDec);
    var humidityValue = calculateHumidity(data[3]);
    var batteryTmp = ("0" + data[4].toString(16)).substr(-2)[0];
    var batteryVoltageCalculated = 2 + parseInt("0x" + batteryTmp, 16) * 0.1;
    var reason = data[0];
    var temperature = temperatureValue;
    var humidity = humidityValue;
    var batteryVoltage = batteryVoltageCalculated;
    var thermistorProperlyConnected = decbin(data[5])[5] == 0;
    var extT1 = ("0" + data[5].toString(16)).substr(-2)[1];
    var extT2 = ("0" + data[6].toString(16)).substr(-2);
    var extThermistorTemperature = thermistorProperlyConnected ? parseInt(`0x${extT1}${extT2}`, 16) * 0.1 : 0;

    // check if it is a keepalive
    if (reason == 1) {
        return {
            reason: 'keepalive',
            temperature: temperature,
            humidity:humidity,
            batteryVoltage: batteryVoltage,
            thermistorProperlyConnected:thermistorProperlyConnected,
            extThermistorTemperature:extThermistorTemperature

        }
    }
}

TTN V3 Decoder (JavaScript ES5):

function decodeUplink(input) {
	try{
		var bytes = input.bytes;
		var data = {};
		var calculateTemperature = function (rawData){return (rawData - 400) / 10};
		var calculateHumidity = function(rawData){return (rawData * 100) / 256};
		function decbin (number) {
		if (number < 0) {
			number = 0xFFFFFFFF + number + 1;
		}
		return parseInt(number, 10).toString(2);
		}

		function handleKeepalive(bytes, data){
			var tempHex = '0' + bytes[1].toString(16) + bytes[2].toString(16);
			var tempDec = parseInt(tempHex, 16);
			var temperatureValue = calculateTemperature(tempDec);
			var humidityValue = calculateHumidity(bytes[3]);
			var batteryTmp = ("0" + bytes[4].toString(16)).substr(-2)[0];
			var batteryVoltageCalculated = 2 + parseInt("0x" + batteryTmp, 16) * 0.1;
			var temperature = temperatureValue;
			var humidity = humidityValue;
			var batteryVoltage = batteryVoltageCalculated;
			var thermistorProperlyConnected = decbin(bytes[5])[5] == 0;

			var extT1 = ("0" + bytes[5].toString(16)).substr(-2)[1];

			var extT2 = ("0" + bytes[6].toString(16)).substr(-2);
			var extThermistorTemperature = 0;
			if(thermistorProperlyConnected){
				extThermistorTemperature = parseInt("0x"+extT1+""+extT2, 16) * 0.1;
			}

			data.sensorTemperature = Number(temperature.toFixed(2));
			data.relativeHumidity = Number(humidity.toFixed(2));
			data.batteryVoltage = Number(batteryVoltage.toFixed(2));
			data.thermistorProperlyConnected = thermistorProperlyConnected;
			data.extThermistorTemperature = extThermistorTemperature;
			return data;
		}
	
		function handleResponse(bytes, data){

		var commands = bytes.map(function(byte){
			return ("0" + byte.toString(16)).substr(-2); 
		});
		commands = commands.slice(0,-7);
		var command_len = 0;
	
		commands.map(function (command, i) {
			switch (command) {
				case '04':
					{
						command_len = 2;
						var hardwareVersion = commands[i + 1];
						var softwareVersion = commands[i + 2];
						data.deviceVersions = { hardware: Number(hardwareVersion), software: Number(softwareVersion) };
					}
				break;
				case '12':
					{
						command_len = 1;
						data.keepAliveTime = parseInt(commands[i + 1], 16);
					}
				break;
				case '19':
					{
						command_len = 1;
						var commandResponse = parseInt(commands[i + 1], 16);
						var periodInMinutes = commandResponse * 5 / 60;
						data.joinRetryPeriod =  periodInMinutes;
					}
				break;
				case '1b':
					{
						command_len = 1;
						data.uplinkType = parseInt(commands[i + 1], 16) ;
					}
				break;
				case '1d':
					{
						command_len = 2;
						var wdpC = commands[i + 1] == '00' ? false : parseInt(commands[i + 1], 16);
						var wdpUc = commands[i + 2] == '00' ? false : parseInt(commands[i + 2], 16);
						data.watchDogParams= { wdpC: wdpC, wdpUc: wdpUc } ;
					}
				break;
				default:
					break;
			}
			commands.splice(i,command_len);
		});
		return data;
		}
		if (bytes[0] == 1) {
			data = handleKeepalive(bytes, data);

		}else{
			data = handleResponse(bytes,data);
			bytes = bytes.slice(-7);
			data = handleKeepalive(bytes, data);
		}
		return {data: data};
	} catch (e) {
		throw new Error(e);
	}
}

Chirpstack Decoder (JavaScript ES5)

function Decode(fPort, bytes, variables) {
    try{
        var data = {};
        var calculateTemperature = function (rawData){return (rawData - 400) / 10};
        var calculateHumidity = function(rawData){return (rawData * 100) / 256};
        function decbin (number) {
        if (number < 0) {
            number = 0xFFFFFFFF + number + 1;
        }
        return parseInt(number, 10).toString(2);
        }
        function handleKeepalive(bytes, data){
            var tempHex = '0' + bytes[1].toString(16) + bytes[2].toString(16);
            var tempDec = parseInt(tempHex, 16);
            var temperatureValue = calculateTemperature(tempDec);
            var humidityValue = calculateHumidity(bytes[3]);
            var batteryTmp = ("0" + bytes[4].toString(16)).substr(-2)[0];
            var batteryVoltageCalculated = 2 + parseInt("0x" + batteryTmp, 16) * 0.1;
            var temperature = temperatureValue;
            var humidity = humidityValue;
            var batteryVoltage = batteryVoltageCalculated;
            var thermistorProperlyConnected = decbin(bytes[5])[5] == 0;
            var extT1 = ("0" + bytes[5].toString(16)).substr(-2)[1];
            var extT2 = ("0" + bytes[6].toString(16)).substr(-2);
            var extThermistorTemperature = 0;
            if(thermistorProperlyConnected){
                extThermistorTemperature = parseInt("0x"+extT1+""+extT2, 16) * 0.1;
            }
            data.sensorTemperature = Number(temperature.toFixed(2));
            data.relativeHumidity = Number(humidity.toFixed(2));
            data.batteryVoltage = Number(batteryVoltage.toFixed(2));
            data.thermistorProperlyConnected = thermistorProperlyConnected;
            data.extThermistorTemperature = extThermistorTemperature;
            return data;
        }
    
        function handleResponse(bytes, data){
        var commands = bytes.map(function(byte){
            return ("0" + byte.toString(16)).substr(-2); 
        });
        commands = commands.slice(0,-7);
        var command_len = 0;
    
        commands.map(function (command, i) {
            switch (command) {
                case '04':
                    {
                        command_len = 2;
                        var hardwareVersion = commands[i + 1];
                        var softwareVersion = commands[i + 2];
                        data.deviceVersions = { hardware: Number(hardwareVersion), software: Number(softwareVersion) };
                    }
                break;
                case '12':
                    {
                        command_len = 1;
                        data.keepAliveTime = parseInt(commands[i + 1], 16);
                    }
                break;
                case '19':
                    {
                        command_len = 1;
                        var commandResponse = parseInt(commands[i + 1], 16);
                        var periodInMinutes = commandResponse * 5 / 60;
                        data.joinRetryPeriod =  periodInMinutes;
                    }
                break;
                case '1b':
                    {
                        command_len = 1;
                        data.uplinkType = parseInt(commands[i + 1], 16) ;
                    }
                break;
                case '1d':
                    {
                        command_len = 2;
                        var deviceKeepAlive = 5;
                        var wdpC = commands[i + 1] == '00' ? false : commands[i + 1] * deviceKeepAlive + 7;
                        var wdpUc = commands[i + 2] == '00' ? false : parseInt(commands[i + 2], 16);
                        data.watchDogParams= { wdpC: wdpC, wdpUc: wdpUc } ;
                    }
                break;
                default:
                    break;
            }
            commands.splice(i,command_len);
        });
        return data;
        }
        if (bytes[0] == 1) {
            data = handleKeepalive(bytes, data);
        }else{
            data = handleResponse(bytes,data);
            bytes = bytes.slice(-7);
            data = handleKeepalive(bytes, data);
        }
        return data;
    } catch (e) {
        console.log(e)
        throw new Error('Unhandled data');
    }
}

DataCake Decoder

function decodeUplink(input) {
    try {
        var bytes = input.bytes;
        var data = {};

        // Helper functions
        var calculateTemperature = function (rawData) { return (rawData - 400) / 10; };
        var calculateHumidity = function (rawData) { return (rawData * 100) / 256; };
        function decbin(number) {
            if (number < 0) {
                number = 0xFFFFFFFF + number + 1;
            }
            return parseInt(number, 10).toString(2);
        }

        function handleKeepalive(bytes, data) {
            var tempHex = '0' + bytes[1].toString(16) + bytes[2].toString(16);
            var tempDec = parseInt(tempHex, 16);
            var temperatureValue = calculateTemperature(tempDec);
            var humidityValue = calculateHumidity(bytes[3]);
            var batteryTmp = ("0" + bytes[4].toString(16)).substr(-2)[0];
            var batteryVoltageCalculated = 2 + parseInt("0x" + batteryTmp, 16) * 0.1;
            var thermistorProperlyConnected = decbin(bytes[5])[5] == 0;
            var extT1 = ("0" + bytes[5].toString(16)).substr(-2)[1];
            var extT2 = ("0" + bytes[6].toString(16)).substr(-2);
            var extThermistorTemperature = thermistorProperlyConnected ? parseInt("0x" + extT1 + extT2, 16) * 0.1 : 0;

            data.sensorTemperature = Number(temperatureValue.toFixed(2));
            data.relativeHumidity = Number(humidityValue.toFixed(2));
            data.batteryVoltage = Number(batteryVoltageCalculated.toFixed(2));
            data.thermistorProperlyConnected = thermistorProperlyConnected;
            data.extThermistorTemperature = extThermistorTemperature;
            return data;
        }

        function handleResponse(bytes, data) {
            var commands = bytes.map(function (byte) {
                return ("0" + byte.toString(16)).substr(-2);
            });
            commands = commands.slice(0, -7);
            var i = 0;

            while (i < commands.length) {
                var command = commands[i];
                switch (command) {
                    case '04':
                        data.deviceVersions = {
                            hardware: Number(commands[i + 1]),
                            software: Number(commands[i + 2])
                        };
                        i += 3;
                        break;
                    case '12':
                        data.keepAliveTime = parseInt(commands[i + 1], 16);
                        i += 2;
                        break;
                    case '19':
                        var commandResponse = parseInt(commands[i + 1], 16);
                        data.joinRetryPeriod = (commandResponse * 5) / 60;
                        i += 2;
                        break;
                    case '1b':
                        data.uplinkType = parseInt(commands[i + 1], 16);
                        i += 2;
                        break;
                    case '1d':
                        var wdpC = commands[i + 1] == '00' ? false : parseInt(commands[i + 1], 16);
                        var wdpUc = commands[i + 2] == '00' ? false : parseInt(commands[i + 2], 16);
                        data.watchDogParams = { wdpC: wdpC, wdpUc: wdpUc };
                        i += 3;
                        break;
                    default:
                        i += 1;
                        break;
                }
            }
            return data;
        }

        if (bytes[0] == 1) {
            data = handleKeepalive(bytes, data);
        } else {
            data = handleResponse(bytes, data);
            bytes = bytes.slice(-7);
            var keepaliveData = handleKeepalive(bytes, {});
            for (var key in keepaliveData) {
                data[key] = keepaliveData[key];
            }
        }
        return { data: data };
    } catch (e) {
        throw new Error(e.message);
    }
}

function Decoder(payload, port) {
    var decoded = decodeUplink({ bytes: payload, fPort: port }).data;

    // Array where we store the fields that are being sent to Datacake
    var datacakeFields = [];

    // Take each field from decoded and convert them to Datacake format
    for (var key in decoded) {
        if (decoded.hasOwnProperty(key)) {
            datacakeFields.push({ field: key.toUpperCase(), value: decoded[key] });
        }
    }

    // Forward data to Datacake
    return datacakeFields;
}

Last updated