function decodeUplink(input) 
{
    var tab_bin=[];
    var output = 0;
    var data;
    
    stringHex = bytesString(input.bytes);
    
    var octetTypeProduit = parseInt(stringHex.substring(0,2),16);
    var octetTypeMessage = parseInt(stringHex.substring(2,4),16);


        function bytesString(input)
        {
            var bufferString='';
            var decToString='';

            for(var i=0; i<input.length;i++)
            {
                decToString = input[i].toString(16).padStart(2,'0')
                        
                bufferString=bufferString.concat(decToString)
                        
            }       
            return bufferString;
        }
        
        function dataOutput(octetTypeMessage)
        {
            outputTypeMessage=[productStatusDataOutput(stringHex),productConfigurationDataOutput(stringHex),smokeAlarmDataOutput(stringHex),dailyAirDataOutput(stringHex),realTimeDataOutput(stringHex)]
            return outputTypeMessage[octetTypeMessage]
        }

        function typeOfProduct(octetTypeProduit)
        {
            if(octetTypeProduit==0xBC){return "Kare + LoRa"}
        }    
        
        function typeOfMessage(octetTypeMessage)
        {
            const message_name =["Product Status","Product Configuration","Smoke Alarm","Air Quality" ,"Real Time"]
            return message_name[octetTypeMessage]
        }

        ///////////////////////////////////////////////
        // Product Status Data Message Function
        ///////////////////////////////////////////////
    

        function smokeStatus(octetSmokeStatus)
        {
            if(octetSmokeStatus===0){return "Smoke sensor ok"};
            if(octetSmokeStatus===1){return "Smoke sensor fault"};
        }

        function temperatureStatus(octetTemperatureStatus)
        {
            if(octetTemperatureStatus===0){return "T°/humidity sensor ok"};
            if(octetTemperatureStatus===1){return "T°/humidity sensor fault"};
        }

        function magnetBaseDetection(octetMagnetBaseDetection)
        {
            if(octetMagnetBaseDetection===0){return "Magnetic base not detected"};
            if(octetMagnetBaseDetection===1){return "Magnetic base detected"};
            if(octetMagnetBaseDetection===2){return "Product removed from its based just now"};
            if(octetMagnetBaseDetection===3){return "Product installed on its base just now"};
            if(octetMagnetBaseDetection===4){return "Magnetic base never detected"};
        }

        function batteryLevel(octetBatteryLevel)
        {
            if(octetBatteryLevel===0){return "High"};
            if(octetBatteryLevel===1){return "Medium"};
            if(octetBatteryLevel===2){return "Low"};
            if(octetBatteryLevel===3){return "Critical"};
        }
        
        function batteryVoltage(octetBatteryVoltage)
        {
            return {"value":((octetBatteryVoltage*5)+2000),"units":"mV"}
        }

        function productLifetime(octetProductLifetime)
        {
          {return {"value":octetProductLifetime, "unit":"month"}};
        }

        /////////////////////////////////////////////////////
        //Product Configuration Message Function
        ////////////////////////////////////////////////////

        function nfcStatus(octetNfcStatus)
        {
            if(octetNfcStatus===0){return "Discoverable"}
            else if(octetNfcStatus===1){return " No Discoverable"};
        }

        function Active(octetActive)
        {
            if(octetActive===1){return "Active"}
            else if(octetActive===0){return "Deactivate"};
        }

        function reconfigurationSource(octetReconfigurationSource)
        {
            const message_name =["NFC","Downlink","Product Start up","Reserved","Reserved","Local"]
            return message_name[octetReconfigurationSource]
        }

        function reconfigurationState(octetReconfigurationState)
        {
            const message_name =["Total Success","Partial Succes","Total fail","Reserved"]
            return message_name[octetReconfigurationState]
        }

        function pendingJoin(octetPending)
        {
            if(octetPending===0){return "No join request scheduled"};
            if(octetPending===1){return "Join request scheduled"};
        }

        function temperatureDelta(octetDelta)
        {
           return {"value" : (octetDelta * 0.1),"unit":"°C"}
        }

        function periodicTransmissionPeriod(octetPeriod)
        {
           return {"value" : octetPeriod,"unit":"min"}
        }


        

        //////////////////////////////////////////////////////////////////////
        ////// Smoke Alarm Message Function
        /////////////////////////////////////////////////////////////////////

        function alarmStatus(octetAlarmStatus)
        {
            if(octetAlarmStatus===0){return "Smoke Alarm non-activated"};
            if(octetAlarmStatus===1){return "Local smoke Alarm activated"};
            if(octetAlarmStatus===2){return "Remote smoke Alarm activated"};
        }

        function alarmHush(octetAlarmHush)
        {
            if(octetAlarmHush===0){return "Smoke alarm stopped because no smoke anymore"};
            if(octetAlarmHush===1){return "Smoke alarm stopped following central button press"};
            if(octetAlarmHush===2){return ": Smoke alarm stopped following a remote silence"};
        }

        function smokeTest(octetSmokeTest)
        {
            if(octetSmokeTest===0){return "Smoke test off"};
            if(octetSmokeTest===1){return "Local smoke test was done"};
            if(octetSmokeTest===2){return "Remote smoke test was done"};
        }

        function maintenance(octetMaintenance)
        {
            if(octetMaintenance===0){return "Maintenance not done"};
            if(octetMaintenance===1){return "Maintenance has been done"};
        }

        function periodWeek(octetWeek)
        {
            return{"value":octetWeek,"units":"week"}
        }

        ///////////////////////////////////////////////////////////////////////
        /////// Real Time Message Function
        ///////////////////////////////////////////////////////////////////////
        
        function temperature(octetTemperature)
        {
            if(octetTemperature == 1023){return "Error"}
            if(octetTemperature == 1022){return "Deconnected Sensor"}
            else{ return{"value":((octetTemperature*0.1)-30),"unit":"°C"}}
        }

        function humidity(octetHumidity)
        {
            if(octetHumidity == 255){return "Error"}
            else{ return{"value":(octetHumidity*0.5),"unit":"°C"}}
        }
        
        //////////////////////////////////////////////////////////////////////
        ////// Product message decoding
        ////////////////////////////////////////////////////////////////////

        function productStatusDataOutput(stringHex)
        {
            var data_hw_version = (parseInt(stringHex.substring(4,6),16)) & 0xFF;
            var data_sw_version = (parseInt(stringHex.substring(6,8),16)) & 0xFF;
            var data_product_lifetime = (parseInt(stringHex.substring(8,10),16)) & 0xFF;
            var data_smoke_sensor= (parseInt(stringHex.substring(10,11),16)>>3) & 0x01;
            var data_temp_hum_sensor= (parseInt(stringHex.substring(10,11),16)>>2) & 0x01;
            var data_magnetic_base_detection = (parseInt(stringHex.substring(10,12),16)>>2) & 0x07;
            var data_energy_status= (parseInt(stringHex.substring(11,12),16)) & 0x03;
            var data_battery_voltage =(parseInt(stringHex.substring(12,14),16)) & 0xFF;

            data = {"typeOfProduct": typeOfProduct(octetTypeProduit),
            "typeOfMessage": typeOfMessage(octetTypeMessage),
            "hwVersion":data_hw_version,
            "swVersion":data_sw_version*0.1,
            "rmgLifetime":productLifetime(data_product_lifetime),
            "smokeSensorStatus": smokeStatus(data_smoke_sensor),
            "tempHumSensorStatus": temperatureStatus(data_temp_hum_sensor),
            "antiTearDetectionStatus": magnetBaseDetection(data_magnetic_base_detection),
            "batteryLevel":batteryLevel(data_energy_status),
            "batteryVoltage": batteryVoltage(data_battery_voltage)
            }

            return data;
        }

        function productConfigurationDataOutput(stringHex)
        {
            var data_reconfiguration_source = (parseInt(stringHex.substring(4,5),16)>>1)&0x07;
            var data_reconfiguration_status = (parseInt(stringHex.substring(4,6),16)>>3)&0x03;
            var data_daily_air_enable= (parseInt(stringHex.substring(5,6),16)>>1)&0x01;
            var data_pending_join = (parseInt(stringHex.substring(6,7),16)>>3)&0x01;
            var data_nfc_status = (parseInt(stringHex.substring(6,7),16)>>1)&0x03;
            var data_periodic_active =(parseInt(stringHex.substring(8,9),16)>>3)&0x01;
            var data_delta_temp = (parseInt(msg.raw_message.payload_hexa.substring(8,10),16))&0x7F;
            var data_periodic_transmission_period = (parseInt(stringHex.substring(10,12),16)>>2)&0x3F;

            data = {"typeOfProduct": typeOfProduct(octetTypeProduit),
            "typeOfMessage": typeOfMessage(octetTypeMessage),
            "reconfigurationSource":reconfigurationSource(data_reconfiguration_source),
            "reconfigurationStatus":reconfigurationState(data_reconfiguration_status),
            "dailyAirEnable":Active(data_daily_air_enable),
            "pendingJoin":pendingJoin(data_pending_join),
            "nfcStatus":nfcStatus(data_nfc_status),
            "periodicData":Active(data_periodic_active),
            "deltaTemperature":temperatureDelta(data_delta_temp),
            "periodicTransmissionPeriod":periodicTransmissionPeriod(data_periodic_transmission_period)
            }
            return data;
        }

        function smokeAlarmDataOutput(stringHex)
        {
            var data_smoke_alarm = (parseInt(stringHex.substring(4,5),16) >> 2)&0x03;
            var data_smoke_hush = (parseInt(stringHex.substring(4,5),16))&0x03;
            var data_smoke_test = (parseInt(stringHex.substring(5,6),16)>>2)&0x03;
            var data_time_since_last_smoke_test = (parseInt(stringHex.substring(5,8),16)>>2)&0xFF;
            var data_maintenance = (parseInt(stringHex.substring(7,8),16)>>1)&0x01;
            var data_time_since_last_maintenance = (parseInt(stringHex.substring(7,10),16)>>1)&0xFF;
            var data_temperature = (parseInt(stringHex.substring(9,13),16)>>3)&0x3FF;
            
            data = { "typeOfProduct": typeOfProduct(octetTypeProduit),
            "typeOfMessage": typeOfMessage(octetTypeMessage),
            "smokeAlarm": alarmStatus(data_smoke_alarm),
            "smokeAlarmHush": alarmHush(data_smoke_hush),
            "smokeLocalProductTest": smokeTest(data_smoke_test),
            "timeSinceLastTest":periodWeek(data_time_since_last_smoke_test),
            "digitalMaintenanceCertificate":maintenance(data_maintenance),
            "timeSinceLastMaintenance":periodWeek(data_time_since_last_maintenance),
            "temperature":temperature(data_temperature)
            };
            return data;
        }

        function dailyAirDataOutput(stringHex)
        {
            var data_temp_mini = (parseInt(stringHex.substring(4,7),16)>>2)&0x3FF;
            var data_temp_max = (parseInt(stringHex.substring(6,9),16))&0x3FF;
            var data_temp_avg = (parseInt(stringHex.substring(9,12),16)>>2)&0x3FF;
            var data_hum_min = (parseInt(stringHex.substring(11,14),16)>>2)&0xFF;
            var data_hum_max = (parseInt(stringHex.substring(13,16),16)>>2)&0xFF;
            var data_hum_avg = (parseInt(stringHex.substring(15,18),16)>>2)&0xFF;

            data = {"typeOfProduct": typeOfProduct(octetTypeProduit),
            "typeOfMessage": typeOfMessage(octetTypeMessage),
            "temperatureMin":temperature(data_temp_mini),
            "temperatureMax":temperature(data_temp_max),
            "temperatureAvg":temperature(data_temp_avg),
            "humidityMin":humidity(data_hum_min),
            "humidityMax":humidity(data_hum_max),
            "humidityAvg":humidity(data_hum_avg),
            }
            return data;
        }

        function realTimeDataOutput(stringHex)
        {
            var data_temp = (parseInt(stringHex.substring(4,7),16)>>2)&0x3FF;
            var data_hum = (parseInt(stringHex.substring(6,9),16)>>2)&0xFF;

            data = {"typeOfProduct": typeOfProduct(octetTypeProduit),
            "typeOfMessage": typeOfMessage(octetTypeMessage),
            "temperature":temperature(data_temp),
            "humidity":humidity(data_hum),
            }

            return data;
        }
        
        data=dataOutput(octetTypeMessage);
        errors = 'null';
        warnings = 'null';
        output = {data,errors,warnings};
        return output
} // end of decoder