function decodeUplink(input) {

  var data={};   
  var 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 typeOfProduct(octetTypeProduit)
  {
    if(octetTypeProduit==0xA3){return "ATMO"};
    if(octetTypeProduit==0xA4){return "SENSE"};
    if(octetTypeProduit==0xA5){return "AERO"};
    if(octetTypeProduit==0xA6){return "PMI"};
	if(octetTypeProduit==0xA7){return "AERO CO2"};
  }    
        
  function typeOfMessage(octetTypeMessage)
  {
	var message_name =["Reserved","Real Time","Product Status","Product Configuration" ,"Keepalive","Button Press"];
	return message_name[octetTypeMessage];
  }
  
 function dataOutput(octetTypeMessage)
 {
     outputTypeMessage=["reserved",realTimeDataOutput(stringHex),productStatusDataOutput(stringHex),productConfigurationDataOutput(stringHex),keepaliveDataOutput(stringHex),buttonPressDataOutput(stringHex)]
     return outputTypeMessage[octetTypeMessage]
 }
 
 /////////////////////////////////////////////////////////
 /// Real Time functions
 ////////////////////////////////////////////////////////
 function pm(a)
 {
    if(a == 2047){return "Error"}
    else{ return{"value":a,"unit":"ug/m3"}}
 }
 
function temperature(a)
 {
    if(a == 1023){return "Error"}
    else{ return{"value":((a*0.1)-30),"unit":"°C"}}
 }

function humidity(a)
 {
    if(a == 255){return "Error"}
    else{ return{"value":(a*0.5),"unit":"%RH"}}
 }
 
 function co2(a)
 {
    if(a == 16383){return "Error"}
    else{ return{"value":a,"unit":"ppm"}}
 }
 
 function cov(a)
 {
    if(a == 16383){return "Error"}
    else{ return{"value":a,"unit":"ug/m3"}}
 }

 function formaldehyde(a)
 {
    if(a == 1023){return "Error"}
    else{ return{"value":a,"unit":"ppb"}}
 }

function luminosity(a)
 {
    if(a == 255){return "Error"}
    else{ return{"value":a*5,"unit":"lux"}}
 }

function noise(a)
 {
    if(a == 127){return "Error"}
    else{ return{"value":a,"unit":"dB"}}
 }
 
 function occupancy(a)
 {
    if(a == 255){return "Error"}
    else{ return{"value":a,"unit":"%"}}
 }
 
 function pressure(a)
 {
	if(a == 1024){return "Error"}
    else{ return{"value":a+300,"unit":"hPa"}}
 }
  
  ///////////////////////////////////////////////////////////////
  /////////////Product Status functions
  ///////////////////////////////////////////////////////////////
  
 function hwStatus(a)
 {
	if(a === 0){return "Hardware Ok"}
    if(a == 1){return "Hardware fault"}
 }
 
  function sensorStatus(a)
 {
	if(a === 0){return "Sensor Ok"}
    if(a == 1){return "Sensor fault"}
	if(a == 2){return "Sensor not populated"}
	if(a == 3){return "Sensor end of life"}
 }
 
 function joinRequest(a)
 {
	if(a === 0){return "No join request scheduled"}
    if(a == 1){return "join request scheduled"}
 }
 
 function productActivationTimeCounter(a)
 {
    if(a == 255){return "Error"}
    else{ return{"value":a,"unit":"month"}}
 }
  
  ///////////////////////////////////////////////////////////////
  /////////////Product Configuration functions
  ///////////////////////////////////////////////////////////////
  
   function reconfigurationSource(a)
 {
	if(a === 0){return "NFC"}
    if(a == 1){return "Downlink"}
	if(a == 2){return "Product Start-Up"}
	if(a == 3){return "RFU"}
 }

   function reconfigurationStatus(a)
 {
	if(a === 0){return "Total Sucess"}
  if(a == 1){return "Partial Sucess"}
	if(a == 2){return "Total Failure"}
	if(a == 3){return "RFU"}
 }  
  
   function active(a)
 {
	if(a === 0){return "Not active"}
    if(a == 1){return "Active"}
 }
  
   function ledFunction(a)
 {
	if(a === 0){return "Global air quality"}
    if(a == 1){return "CO2 Level"}
 }
   
	function nfc(a)
 {
	if(a == 0){return "Discoverable"}
    if(a == 1){return "Not discoverable"}
 }
  
  	function lora(a)
 {
	if(a == 0){return "EU68"}
    if(a > 0){return "RFU"}
 }
 
  	function measuringPeriod(a)
 {
	return{"value":a,"unit":"minutes"}
 }
 
   	function keepalivePeriod(a)
 {
	return{"value":a,"unit":"hours"}
 }
   	function co2Threshold(a)
 {
	return{"value":a*20,"unit":"ppm"}
 }
  ///////////////////////////////////////////////////////////////////////
  ////// Product message decoding
  ////////////////////////////////////////////////////////////////////


function realTimeDataOutput(stringHex)
 {
    var data_pm1 = (parseInt(stringHex.substring(4,7),16)>>1)&0x7FF;
    var data_pm2_5 = (parseInt(stringHex.substring(6,10),16)>>2)&0x7FF;
	var data_pm10 = (parseInt(stringHex.substring(9,13),16)>>3)&0x7FF;
	var data_temp = (parseInt(stringHex.substring(12,15),16)>>1)&0x3FF;
	var data_hum = (parseInt(stringHex.substring(14,17),16)>>1)&0xFF;
	var data_co2 = (parseInt(stringHex.substring(16,21),16)>>3)&0x3FFF;
	var data_cov = (parseInt(stringHex.substring(20,24),16)>>1)&0x3FFF;
	var data_formaldehyde = (parseInt(stringHex.substring(23,27),16)>>3)&0x3FF;
	var data_lum = (parseInt(stringHex.substring(33,36),16)>>3)&0xFF;
	var data_avg_noise = (parseInt(stringHex.substring(35,37),16))&0x7F;
	var data_peak_noise = (parseInt(stringHex.substring(37,39),16)>>1)&0x7F;
	var data_occupancy_rate = (parseInt(stringHex.substring(38,41),16)>>1)&0xFF;
	var data_pressure = (parseInt(stringHex.substring(40,44),16)>>3)&0x3FF;
	
	
    data = {"typeOfProduct": typeOfProduct(octetTypeProduit),
    "typeOfMessage": typeOfMessage(octetTypeMessage),
	"pm1":pm(data_pm1),
	"pm2_5":pm(data_pm2_5),
	"pm10":pm(data_pm10),
    "temperature":temperature(data_temp),
    "humidity":humidity(data_hum),
	"co2":co2(data_co2),
	"cov":cov(data_cov),
	"formaldehyde":formaldehyde(data_formaldehyde),
	"luminosity":luminosity(data_lum),
	"average noise":noise(data_avg_noise),
	"peak noise":noise(data_peak_noise),
	"occupancy rate":occupancy(data_occupancy_rate),
	"pressure":pressure(data_pressure)
    }

    return data;
 }
  
  
  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_hw_status =  (parseInt(stringHex.substring(13,14),16)>>3) & 0x01;
	  var data_pm_status =  (parseInt(stringHex.substring(13,14),16)>>1) & 0x03;
	  var data_temp_status =  (parseInt(stringHex.substring(13,15),16)>>3) & 0x03;
	  var data_formaldehyde_status =  (parseInt(stringHex.substring(14,15),16)>>1) & 0x03;
	  var data_co2_status =  (parseInt(stringHex.substring(14,16),16)>>3) & 0x03;
	  var data_cov_status =  (parseInt(stringHex.substring(15,16),16)>>1) & 0x03;
	  var data_pir_status =  (parseInt(stringHex.substring(15,17),16)>>3) & 0x03;
	  var data_micro_status =  (parseInt(stringHex.substring(16,17),16)>>1) & 0x03;
	  var data_pressure_status =  (parseInt(stringHex.substring(16,18),16)>>3) & 0x03;
	  var data_accel_status =  (parseInt(stringHex.substring(17,18),16)>>1) & 0x03;
	  var data_lum_status =  (parseInt(stringHex.substring(17,19),16)>>3) & 0x03;
	  var data_pending_join =  (parseInt(stringHex.substring(18,19),16)>>2) & 0x03;
	  var data_time_activation = (parseInt(stringHex.substring(18,21),16)>>2) & 0xFF;
	
      data = {"typeOfProduct": typeOfProduct(octetTypeProduit),
      "typeOfMessage": typeOfMessage(octetTypeMessage),
      "hwVersion":data_hw_version,
      "swVersion":data_sw_version*0.1,
	  "hardwareStatus":hwStatus(data_hw_status),
	  "pmSensorStatus":sensorStatus(data_pm_status),
	  "tempHumSensorStatus":sensorStatus(data_temp_status),
	  "formaldehydeSensorStatus":sensorStatus(data_formaldehyde_status),
	  "co2SensorStatus":sensorStatus(data_co2_status),
	  "covpmSensorStatus":sensorStatus(data_cov_status),
	  "pirSensorStatus":sensorStatus(data_pir_status),
	  "microSensorStatus":sensorStatus(data_micro_status),
	  "pressureSensorStatus":sensorStatus(data_pressure_status),
	  "accelerometerSensorStatus":sensorStatus(data_accel_status),
	  "luminositySensorStatus":sensorStatus(data_lum_status),
	  "pendingJoinStatus":joinRequest(data_pending_join),
	  "timeSinceActivation":productActivationTimeCounter(data_time_activation)
      }
      return data;
  }

  function productConfigurationDataOutput(stringHex)
  {
      var data_reconfiguration_source = (parseInt(stringHex.substring(4,5),16)>>2)&0x03;
      var data_reconfiguration_status = (parseInt(stringHex.substring(4,5),16))&0x03;
	  var data_led_enable = (parseInt(stringHex.substring(5,6),16)>>3)&0x01;
	  var data_led_function = (parseInt(stringHex.substring(5,6),16)>>1)&0x03;
	  var data_average_level_indication = (parseInt(stringHex.substring(5,6),16))&0x01;
	  var data_button_notification = (parseInt(stringHex.substring(6,7),16)>>3)&0x01;
	  var data_keepalive_enable = (parseInt(stringHex.substring(6,7),16)>>2)&0x01;
	  var data_nfc_status = (parseInt(stringHex.substring(6,7),16))&0x03;
	  var data_lora_regions = (parseInt(stringHex.substring(7,8),16))&0x07;
	  var data_measuring_period = (parseInt(stringHex.substring(8,10),16))&0xFF;
	  var data_co2_avg_threshold = (parseInt(stringHex.substring(14,16),16))&0xFF;
	  var data_co2_high_threshold = (parseInt(stringHex.substring(16,18),16))&0xFF;
	  
	  
      data = {"typeOfProduct": typeOfProduct(octetTypeProduit),
      "typeOfMessage": typeOfMessage(octetTypeMessage),
      "reconfigurationSource":reconfigurationSource(data_reconfiguration_source),
      "reconfigurationStatus":reconfigurationStatus(data_reconfiguration_status),
	  "ledEnable":active(data_led_enable),
	  "ledFunction":ledFunction(data_led_function),
	  "averageLevelIndication":active(data_average_level_indication),
	  "buttonNotification":active(data_button_notification),
	  "keepaliveEnable":active(data_keepalive_enable),
	  "nfcStatus":nfc(data_nfc_status),
	  "loraRegions":lora(data_lora_regions),
	  "measuringPeriod":measuringPeriod(data_measuring_period),
	  "co2AverageThreshold":co2Threshold(data_co2_avg_threshold),
	  "co2HighThreshold":co2Threshold(data_co2_high_threshold)
      }
      return data;
  }

  function keepaliveDataOutput(stringHex)
  {
      data = { "typeOfProduct": typeOfProduct(octetTypeProduit),
      "typeOfMessage": typeOfMessage(octetTypeMessage)
      };
      return data;
  }

  function buttonPressDataOutput(stringHex)
  {
      data = {"typeOfProduct": typeOfProduct(octetTypeProduit),
      "typeOfMessage": typeOfMessage(octetTypeMessage)
      }
      return data;
  }

  data=dataOutput(octetTypeMessage);
  
  return {data};

}