Page cover image

Wireless Thermostat LoRaWAN

Product Datasheet

Device Profile for Tesenso IoT Cloud

Decoder/Payload Converter for Tesenso IoT Cloud

https://github.com/Tesenso-GmbH/Device-Decoder/blob/main/MClimate_Wireless_Thermostat.js
// Convert hexadecimal string to bytes array
function hexToBytes(hex) {
    var bytes = [];
    for (var i = 0; i < hex.length; i += 2) {
        bytes.push(parseInt(hex.substr(i, 2), 16));
    }
    return bytes;
}
// Decode the given input using the decodeUplink function
function decodeInput(input) {
    var bytes = hexToBytes(input);
    return decodeUplink(bytes);
}
// Function to decode the provided bytes
function decodeUplink(bytes) {
    try {
        var data = {};
        var toBool = function (value) {
        	return value + '1';
        };
        var calculateTemperature = function (rawData) { return (rawData - 400) / 10 };
        var calculateHumidity = function (rawData) { return (rawData * 100) / 256 };
        var decbin = function (number) {
            if (number < 0) {
                number = 0xFFFFFFFF + number + 1;
            }
            number = number.toString(2);
            return "00000000".substr(number.length) + number;
        }
        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 temperature = temperatureValue;
            var humidity = humidityValue;
            //var batteryVoltage = parseInt(`${decbin(bytes[4])}${decbin(bytes[5])}`, 2)/1000;
            var targetTemperature = bytes[6];
            var powerSourceStatus = bytes[7];
            var lux = parseInt('0' + bytes[8].toString(16) + bytes[9].toString(16), 16);
            var pir = toBool(bytes[10]);
            data.temperature = Number(temperature.toFixed(2));
            data.relativeHumidity = Number(humidity.toFixed(2));
            //data.batteryVoltage = Number(batteryVoltage.toFixed(3));
            data.targetTemperature = targetTemperature;
            data.powerSourceStatus = powerSourceStatus;
            data.lux = lux;
            data.pir = pir;
            return data;
        }
        function handleResponse(bytes, data) {
            var commands = bytes.map(function (byte) {
                return ("0" + byte.toString(16)).substr(-2);
            });
            commands = commands.slice(0, -11);
            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 '14':
                        {
                            command_len = 1;
                            data.childLock = toBool(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;
                    case '2f':
                        {
                            command_len = 1;
                            data.targetTemperature = parseInt(commands[i + 1], 16);
                        }
                        break;
                    case '30':
                        {
                            command_len = 1;
                            data.manualTargetTemperatureUpdate = parseInt(commands[i + 1], 16);
                        }
                        break;
                    case '32':
                        {
                            command_len = 1;
                            data.heatingStatus = parseInt(commands[i + 1], 16);
                        }
                        break;
                    case '34':
                        {
                            command_len = 1;
                            data.displayRefreshPeriod = parseInt(commands[i + 1], 16);
                        }
                        break;
                    case '36':
                        {
                            command_len = 1;
                            data.sendTargetTempDelay = parseInt(commands[i + 1], 16);
                        }
                        break;
                    case '38':
                        {
                            command_len = 1;
                            data.automaticHeatingStatus = parseInt(commands[i + 1], 16);
                        }
                        break;
                    case '3a':
                        {
                            command_len = 1;
                            data.sensorMode = parseInt(commands[i + 1], 16);
                        }
                        break;
                    case '3d':
                        {
                            command_len = 1;
                            data.pirSensorStatus = parseInt(commands[i + 1], 16);
                        }
                        break;
                    case '3f':
                        {
                            command_len = 1;
                            data.pirSensorSensitivity = parseInt(commands[i + 1], 16);
                        }
                        break;
                    case '41':
                        {
                            command_len = 1;
                            data.currentTemperatureVisibility = parseInt(commands[i + 1], 16);
                        }
                        break;
                    case '43':
                        {
                            command_len = 1;
                            data.humidityVisibility = parseInt(commands[i + 1], 16);
                        }
                        break;
                    case '45':
                        {
                            command_len = 1;
                            data.lightIntensityVisibility = parseInt(commands[i + 1], 16);
                        }
                        break;
                    case '47':
                        {
                            command_len = 1;
                            data.pirInitPeriod = parseInt(commands[i + 1], 16);
                        }
                        break;
                    case '49':
                        {
                            command_len = 1;
                            data.pirMeasurementPeriod = parseInt(commands[i + 1], 16);
                        }
                        break;
                    case '4b':
                        {
                            command_len = 1;
                            data.pirCheckPeriod = parseInt(commands[i + 1], 16);
                        }
                        break;
                    case '4d':
                        {
                            command_len = 1;
                            data.pirBlindPeriod = parseInt(commands[i + 1], 16);
                        }
                        break;
                    case 'a0':
                        {
                            command_len = 4;
                            var joinedCommands = commands[i + 1].toString() + commands[i + 2].toString() + commands[i + 3].toString() + commands[i + 4].toString();
                            fuota_address = parseInt(joinedCommands, 16);
                            fuota_address_raw = commands[i + 1].toString() + commands[i + 2].toString() + commands[i + 3].toString() + commands[i + 4].toString();
                            data.fuota = { fuota_address: fuota_address, fuota_address_raw: fuota_address_raw };
                        }
                        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(-11);
            data = handleKeepalive(bytes, data);
        }
        return data;
    } catch (e) {
        throw new Error('Unhandled data');
    }
}
// var msg = {"data":"042511120a19781b001d02182f183200360a1400340c0102a4570dee180201f600"};
return {msg: decodeInput(msg.data), metadata: metadata, msgType: msgType};

Device Labels

in manual
dataKey
dataType
dataFormat

Temperature

temperature

telemetry

float

Humidity

relativeHumidity

telemetry

float

targetTemperature

telemetry

float

powerSourceStatus

telemetry

float

Lux

lux

telemetry

float

PIR

pir

telemetry

float/string

childLock

telemetry

float

deviceVersions

telemetry

{string}

displayRefreshPeriod

telemetry

float

heatingStatus

telemetry

float

joinRetryPeriod

telemetry

float

keepAliveTime

telemetry

float

manualTargetTemperatureUpdate

telemetry

float

msg

telemetry

{string}

powerSourceStatus

telemetry

float

sendTargetTempDelay

telemetry

float

sensorTemperature

telemetry

float

targetTemperature

telemetry

float

uplinkType

telemetry

float

watchDogParams

telemetry

{string}

  • See website documentation

  • See website documentation

Last updated