function decodeUplink(input) { 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=''; 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=[productStatusOutput(stringHex),coAlarmStatusOutput(stringHex),realTimeOutput(stringHex), productConfigurationOutput(stringHex)] return outputTypeMessage[octetTypeMessage] } function typeOfProduct(octetTypeProduit) { if(octetTypeProduit==0xAF){return "Air LoRa"} if(octetTypeProduit==0xAE){return "Air+ LoRa"} } function typeOfMessage(octetTypeMessage) { const message_name =["Product Status","CO Alarm Status","Real Time","Product Function Configuration"] return message_name[octetTypeMessage] } function temperature(octetTemperatureValue) { return {"value": (octetTemperatureValue*0.2).toFixed(2),"unit":"°C"} } function co2(octetCO2Value) { return {"value": octetCO2Value*20,"unit": "ppm"} } function humidity(octetHumidityValue) { return {"value": (octetHumidityValue*0.5).toFixed(2),"unit":"%RH"} } function iaqGlobalArgument(octetiaqGlobal) { const message_name =["Excellent","Good","Fair","Poor", "Bad","Not used","Not used","Error"] return message_name[octetiaqGlobal] } function batterieLevelArgument(octetHCI) { const message_name =["High","Medium","Low","Critical"] return message_name[octetHCI] } function productHwStatusArgument(octetProductHwStatus) { const message_name =["Hardware working correctly","Hardware fault detected"] return message_name[octetProductHwStatus] } function active(octetActive) { data=["Not active","Active"] return data[octetActive]; } function reconfigurationSource(octetReconfigurationSource) { if(octetReconfigurationSource==0){return "NFC"} if(octetReconfigurationSource==1){return "Applicative Downlink"} if(octetReconfigurationSource==2){return "Start-up product"} if(octetReconfigurationSource==5){return "Local"} else{return "Reserved"} } function reconfigurationState(octetReconfigurationState) { if(octetReconfigurationState==0){return "Total success"} if(octetReconfigurationState==1){return "Partial success"} if(octetReconfigurationState==2){return "Total failure"} else{return "Reserved"} } function nfcStatusConfiguration(nfcStatus) { data=["Discoverable","Not Discoverable","RFU","RFU"] return data[nfcStatus]; } function hwRevision(octetHWRevision) { switch(octetHWRevision){ case 0: data="C030A"; break; case 1: data="1"; break; } return data; } function swRevision(octetSWRevision) { switch(octetSWRevision){ case 0: data="V0.0"; break; case 10: data="V1.0"; break; } return data; } function pendingJoin(octetPendingJoin) { if(octetPendingJoin==0){return "No join request scheduled"} if(octetPendingJoin==1){return "Join request scheduled"} } function co(octetCoConcentration) { if(octetCoConcentration==1023){return "Error"} else{return {"value":parseFloat(octetCoConcentration), "unit" :"ppm"}} } function testAlarm(octetTestAlarm) { if(octetTestAlarm==0){return "Test Off"} if(octetTestAlarm==1){return "Product test is running"} } function temperature(octetTemperatureValue) { if(octetTemperatureValue>=1023){return "Error"} if(octetTemperatureValue>=1022){return "Sensor not present"} else{return {"value":parseFloat(((octetTemperatureValue / 10) - 30).toFixed(2)), "unit":"°C" }} } function humidity(octetHumidityValue) { if(octetHumidityValue>=255){return "Error"} if(octetHumidityValue>=254){return "Sensor not present"} else{return {"value":parseFloat(((octetHumidityValue *0.5)).toFixed(2)), "unit" :"%RH"}} } function deltaTemp(octetDeltaTemperature) { return {"value":parseFloat((octetDeltaTemperature*0.1 ).toFixed(2)), "unit":"°C" } } function deltaCo(octetDeltaCo) { return {"value":parseFloat(octetDeltaCo*5), "unit" :"ppm"} } function d2dPing(octetD2DPing) { if(octetD2DPing==0){return "Not compatible"} if(octetD2DPing>=1){return "Compatible"} } function period(octetPeriod) { return {"value":parseFloat(octetPeriod*10), "unit" :"min"} } function productStatusOutput(stringHex) { var hw_version = parseInt(stringHex.substring(4, 6), 16); var sw_version = parseInt(stringHex.substring(6, 8), 16); var rmg_lifetime = parseInt(stringHex.substring(8, 10), 16); var co_sensor_status = (parseInt(stringHex.substring(10, 11), 16) >> 3) & 0x01; var temp_sensor_status = (parseInt(stringHex.substring(10, 11), 16) >> 2) & 0x01; var memory_status = (parseInt(stringHex.substring(10, 11), 16) >> 1) & 0x01; var default_hush = (parseInt(stringHex.substring(10, 11), 16)) & 0x01; var battery_level = (parseInt(stringHex.substring(11, 12), 16) >> 2) & 0x03; var magnet_detection = (parseInt(stringHex.substring(11, 12), 16) >> 1) & 0x01; data = { "typeOfProduct": typeOfProduct(octetTypeProduit), "typeOfMessage": typeOfMessage(octetTypeMessage), "hwRevision": hwRevision(hw_version), "swRevision": swRevision(sw_version), "remainingProductLifetime" : {"Value":rmg_lifetime,"unit":"month"}, "coSensorStatus": productHwStatusArgument(co_sensor_status), "tempHumSensorStatus": productHwStatusArgument(temp_sensor_status), "memoryFault": productHwStatusArgument(memory_status), "hushStatus": productHwStatusArgument(default_hush), "energyStatus": batterieLevelArgument(battery_level), }; return data; } function coAlarmStatusOutput(stringHex) { var co_concentration = (parseInt(stringHex.substring(4, 7), 16) >> 2) & 0x03FF; var co_pre_alarm = (parseInt(stringHex.substring(6, 7), 16) >> 1) & 0x01; var co_alarm = (parseInt(stringHex.substring(6, 7), 16)) & 0x01; var co_alarm_hush = (parseInt(stringHex.substring(7, 8), 16) >> 3) & 0x01; var co_product_test = (parseInt(stringHex.substring(7, 8), 16) >> 1) & 0x01; var time_since_last_test = (parseInt(stringHex.substring(8, 10), 16)); data = {"typeOfProduct": typeOfProduct(octetTypeProduit), "typeOfMessage": typeOfMessage(octetTypeMessage), "coConcentration": co(co_concentration), "preAlarm":active(co_pre_alarm), "localAlarm":active(co_alarm), "coAlarmHush":active(co_alarm_hush), "productTest":testAlarm(co_product_test), "timeSinceLastTest":{"value":time_since_last_test,"unit":"week"} }; return data; } function realTimeOutput(stringHex) { var co_concentration = (parseInt(stringHex.substring(4, 8), 16) >> 6) & 0x03FF; var data_temperature = (parseInt(stringHex.substring(6, 9), 16)) & 0x3FF; var data_humidity = (parseInt(stringHex.substring(9, 11), 16)) & 0xFF; var izi_air_global = (parseInt(stringHex.substring(10, 12), 16) >> 1) & 0x07; var izi_air_src = (parseInt(stringHex.substring(11, 13), 16) >> 1) & 0x0F; data = {"typeOfProduct": typeOfProduct(octetTypeProduit), "typeOfMessage": typeOfMessage(octetTypeMessage), "coConcentration": co(co_concentration), "temperature" : temperature(data_temperature), "relativeHumidity" : humidity(data_humidity), "iaqGlobal": iaqGlobalArgument(izi_air_global), } return data; } function productConfigurationOutput(stringHex) { var config_source = (parseInt(stringHex.substring(4, 5), 16) >> 1) & 0x07; var config_state = (parseInt(stringHex.substring(4, 6), 16) >> 3) & 0x03; var periodic_on_off = (parseInt(stringHex.substring(5, 6), 16) >> 2) & 0x01; var nfc_status = (parseInt(stringHex.substring(5, 6), 16)) & 0x03; var periodic_tx_period = (parseInt(stringHex.substring(7, 8), 16)) & 0x0F; var delta_temperature = (parseInt(stringHex.substring(8, 10), 16)); var delta_co = (parseInt(stringHex.substring(10, 12), 16)); var D2D_ID = (parseInt(stringHex.substring(12, 17), 16) >> 3) & 0x1FFFF; var D2D_ping = (parseInt(stringHex.substring(16, 17), 16) >> 2) & 0x1; var pending_join = (parseInt(stringHex.substring(16, 17), 16) >> 1) & 0x01; var downlink_counter = (parseInt(stringHex.substring(18, 22), 16) >> 1) & 0xFFFF; data = {"typeOfProduct": typeOfProduct(octetTypeProduit), "typeOfMessage": typeOfMessage(octetTypeMessage), "reconfigurationSource": reconfigurationSource(config_source), "reconfigurationState": reconfigurationState(config_state), "realtimeStatus": active(periodic_on_off), "nfcStatus": nfcStatusConfiguration(nfc_status), "realtimePeriod":period(periodic_tx_period), "deltaTemperature":deltaTemp(delta_temperature), "deltaCO":deltaCo(delta_co), "d2dID":D2D_ID, "d2dPing":d2dPing(D2D_ping), "pendingJoin":pendingJoin(pending_join), "downlinkCounter":downlink_counter, }; return data; } data = dataOutput(octetTypeMessage) return data; } // end of decoder