Device Vendor
Thermokon Sensortechnik GmbH
Device Model
NOVOS 3 Occ Lum CO2 Temp_rH
Product Manual/Datasheet Link
https://www.thermokon.de/direct/alterra-base/mimes/get/f3f365ccac822a0b6 / https://www.thermokon.de/direct/alterra-base/mimes/get/3d63622604fadb043
LoRaWAN Class
Class A
LoRaWAN Protocol Version
LORAWAN_1_0_4
Uplink Data Examples
fPort 2: 10 00 D7 11 2D 12 03 20 40 01 5E 41 00 54 4B
fPort 2: 10 00 EC 11 37 12 04 B0 40 02 EE 41 07 54 4B
fPort 2: 10 00 C8 11 32 12 07 D0 40 13 88 41 19 54 4B
Decode Function (Optional)
// Thermokon Sensortechnik GmbH
// Payload Decoder for Thermokon LoRaWAN devices
// Template: Adaption to corresponding NS/AS necessary
// -Revision B-
// -Subject to change without further notice!
//*********************************************************
// Changelog: - Added Identifiers for addtitional features (eg. NOVOS 3 INC EPD,...)
// - Removed Identifiers which were not used
// - Changed objectnames for quick access (1-Byte) identifier
//*********************************************************
// Questions or remarks:support@thermokon.de
//Decoder Mode
var DecoderLegacyMode = false;
//Only set to "true" if former object identifier must be used
var LPP_S_TEMP_0 = 0x0010;
var LPP_S_RHUM_0 = 0x0011;
var LPP_S_CO2_0 = 0x0012;
var LPP_S_VOC_0 = 0x0013;
var LPP_S_MOISTURE_0 = 0x0014;
var LPP_S_ATM_P_0 = 0x0030;
var LPP_S_DIF_P_0 = 0x0031;
var LPP_S_FLOW_0 = 0x0032;
var LPP_S_LIGHT_0 = 0x0040;
var LPP_S_OCCU_0 = 0x0041;
var LPP_S_REED_0 = 0x0050;
var LPP_S_CONDENSATION_0 = 0x0051;
var LPP_S_VBAT_0 = 0x0054;
var LPP_S_BUTTON_0 = 0x0055;
var LPP_S_DI_0 = 0x0058;
var LPP_S_SETPOINT_0 = 0x0063;
var LPP_TEMP_1 = 0x9100;
var LPP_MOISTURE_1 = 0x9140;
var LPP_DIF_P_1 = 0x9310;
var LPP_FLOW_1 = 0x9320;
var LPP_OCCU_1 = 0x9410;
var LPP_REED_1 = 0x9500;
var LPP_BUTTON_1 = 0x9550;
var LPP_DI_1 = 0x9580;
var LPP_SETPOINT_1 = 0x9630;
var LPP_TEMP_2 = 0xA100;
var LPP_DEV_KEY = 0xC000;
var LPP_EPD_VALUE_EXT_OVERLOAD_0 = 0xC194;
var LPP_EPD_VALUE_EXT_OVERLOAD_1 = 0xC19C;
var LPP_EPD_VALUE_EXT_OVERLOAD_2 = 0xC1A4;
var LPP_EPD_VALUE_EXT_OVERLOAD_3 = 0xC1AC;
var LPP_FORCED_UPLINK = 0xC230;
function u16_to_s16(u16) {
var s16 = u16&0xFFFF;
if (0x8000 & s16){s16 = - (0x010000 - s16);}
return s16;
}
function u8_to_s8(u8) {
var s8=u8&0xFF;
if (0x80 & s8) {s8 = - (0x0100 - s8);}
return s8;
}
function DecodeLPPPayload(data) {
var obj = {};
for(i=0;i<data.length;i++){
var lpp = 0;
if(data[i] <= 0x7F) {lpp = data[i]; i++;}
else {lpp = (data[i] << 8) + data[i + 1]; i+=2;}
switch(lpp){
case LPP_S_TEMP_0:
if(DecoderLegacyMode==false)
{obj.TEMP_0 = u16_to_s16(data[i] << 8 | data[i+1]) / 10;}
else if(DecoderLegacyMode==true)
{obj.TEMP = u16_to_s16(data[i] << 8 | data[i+1]) / 10;}
i++;
break;
case LPP_S_RHUM_0:
if(DecoderLegacyMode==false)
{obj.RHUM_0 = u8_to_s8(data[i]) / 1;}
else if(DecoderLegacyMode==true)
{obj.RHUM = u8_to_s8(data[i]) / 1;}
break;
case LPP_S_CO2_0:
if(DecoderLegacyMode==false)
{obj.CO2_0 = (data[i]<<8 | data[i+1]) / 1;}
else if(DecoderLegacyMode==true)
{obj.CO2 = (data[i]<<8 | data[i+1]) / 1;}
i++;
break;
case LPP_S_VOC_0:
if(DecoderLegacyMode==false)
{obj.VOC_0 = (data[i]<<8 | data[i+1]) / 1;}
else if(DecoderLegacyMode==true)
{obj.VOC = (data[i]<<8 | data[i+1]) / 1;}
i++;
break;
case LPP_S_MOISTURE_0:
obj.MOISTURE_0 = u16_to_s16(data[i] << 8 | data[i+1]) / 1;
i++;
break;
case LPP_S_ATM_P_0:
if(DecoderLegacyMode==false)
{obj.ATM_P_0 = (data[i]<<8 | data[i+1]) / 1}
else if(DecoderLegacyMode==true)
{obj.ATM_P = (data[i]<<8 | data[i+1]) / 1;}
i++;
break;
case LPP_S_DIF_P_0:
if(DecoderLegacyMode==false)
{obj.DIF_P_0 = u16_to_s16((data[i]<<8 | data[i+1]) / 1)}
else if(DecoderLegacyMode==true)
{obj.DP = u16_to_s16((data[i]<<8 | data[i+1]) / 1)}
i++;
break;
case LPP_S_FLOW_0:
if(DecoderLegacyMode==false)
{obj.FLOW_0 = (data[i]<<8 | data[i+1]) / 1;}
else if(DecoderLegacyMode==true)
{obj.FLOW = (data[i]<<8 | data[i+1]) / 1;}
i++;
break;
case LPP_S_LIGHT_0:
if(DecoderLegacyMode==false)
{obj.LIGHT_0 = (data[i]<<8 | data[i+1]) / 1;}
else if(DecoderLegacyMode==true)
{obj.VISIBLE_LIGHT = (data[i]<<8 | data[i+1]) / 1;}
i++;
break;
case LPP_S_OCCU_0:
if(DecoderLegacyMode==false)
{obj.OCCU_0_STATE = data[i] & 0x01;
obj.OCCU_0_CNT = data[i] >> 1;}
else if(DecoderLegacyMode==true)
{obj.OCCU0_STATE = data[i] & 0x01;
obj.OCCU0_CNT = data[i] >> 1;}
break;
case LPP_S_REED_0:
if(DecoderLegacyMode==false)
{obj.REED_0_STATE = data[i] & 0x01;
obj.REED_0_CNT = data[i] >> 1;}
else if(DecoderLegacyMode==true)
{obj.REED0_STATE = data[i] & 0x01;
obj.REED0_CNT = data[i] >> 1;}
break;
case LPP_S_CONDENSATION_0:
if(DecoderLegacyMode==false)
{obj.CONDENSATION_0_STATE = (data[i] >>> 7);
obj.CONDENSATION_0_RAW = (u16_to_s16(data[i] << 8 | data[i+1]) / 1)&0x0FFF;
i++;}
else if(DecoderLegacyMode==true)
{obj.CONDENSATION_STATE = (data[i] >>> 7);
obj.CONDENSATION_RAW = (u16_to_s16(data[i] << 8 | data[i+1]) / 1)&0x0FFF;
i++;}
break;
case LPP_S_VBAT_0:
if(DecoderLegacyMode==false)
{obj.VBAT_0 = data[i] / (1.0/20);}
else if(DecoderLegacyMode==true)
{obj.VBAT = data[i] / (1.0/20);}
break;
case LPP_S_BUTTON_0:
if(data[i]>=2)
{obj.BUTTON_0_PRESSED = 1}
else
{obj.BUTTON_0_PRESSED = 0}
if (data[i] & 0x01 >= 1)
{obj.BUTTON_0_LAST_TYPE = "Long Press"}
else
{obj.BUTTON_0_LAST_TYPE = "Short Press"}
obj.BUTTON_0_CNT = data[i] >> 1;
break;
case LPP_S_DI_0:
obj.DI_0_STATE = data[i] & 0x01;
obj.DI_0_CNT = data[i] >> 1;
break;
case LPP_S_SETPOINT_0:
if(DecoderLegacyMode==false)
{obj.SETPOINT_0 = data[i] / 1;}
else if(DecoderLegacyMode==true)
{obj.SETPOINT = data[i] / 1;}
break;
case LPP_TEMP_1:
obj.TEMP_1 = u16_to_s16(data[i] << 8 | data[i+1]) / 10;
i++;
break;
case LPP_MOISTURE_1:
obj.MOISTURE_1 = (data[i] << 8 | data[i+1]) / 1;
i++;
break;
case LPP_DIF_P_1 :
obj.DIF_P_1 = u16_to_s16((data[i]<<8 | data[i+1]) / 1)
i++;
break;
case LPP_FLOW_1:
obj.FLOW_1 = (data[i]<<8 | data[i+1]) / 1;
i++;
break;
case LPP_REED_1:
if(DecoderLegacyMode==false)
{obj.REED_1_STATE = data[i] & 0x01;
obj.REED_1_CNT = data[i] >> 1;}
else if(DecoderLegacyMode==true)
{obj.REED1_STATE = data[i] & 0x01;
obj.REED1_CNT = data[i] >> 1;}
break;
case LPP_BUTTON_1:
if(data[i]>=2)
{obj.BUTTON_1_PRESSED = 1}
else
{obj.BUTTON_1_PRESSED = 0}
if (data[i] & 0x01 >= 1)
{obj.BUTTON_1_LAST_TYPE = "Long Press"}
else
{obj.BUTTON_1_LAST_TYPE = "Short Press"}
obj.BUTTON_1_CNT = data[i] >> 1;
break;
case LPP_DI_1:
obj.DI_1_STATE = data[i] & 0x01;
obj.DI_1_CNT = data[i] >> 1;
break;
case LPP_SETPOINT_1:
obj.SETPOINT_1 = (data[i] << 8 | data[i+1]) / 10;
i++;
break;
case LPP_TEMP_2:
obj.TEMP_2 = u16_to_s16(data[i] << 8 | data[i+1]) / 10;
i++;
break;
case LPP_DEV_KEY:
obj.DEV_KEY = (data[i] << 8 | data[i+1]) / 1;
i++;
break;
case LPP_EPD_VALUE_EXT_OVERLOAD_0:
obj.EPD_VALUE_EXT_OVERLOAD_0 = u16_to_s16(data[i] << 8 | data[i+1]) / 1;
i++;
break;
case LPP_EPD_VALUE_EXT_OVERLOAD_1:
obj.EPD_VALUE_EXT_OVERLOAD_1 = u16_to_s16(data[i] << 8 | data[i+1]) / 1;
i++;
break;
case LPP_EPD_VALUE_EXT_OVERLOAD_2:
obj.EPD_VALUE_EXT_OVERLOAD_2 = u16_to_s16(data[i] << 8 | data[i+1]) / 1;
i++;
break;
case LPP_EPD_VALUE_EXT_OVERLOAD_3:
obj.EPD_VALUE_EXT_OVERLOAD_3 = u16_to_s16(data[i] << 8 | data[i+1]) / 1;
i++;
break;
case LPP_FORCED_UPLINK:
obj.FORCED_UPLINK = (data[i] << 8 | data[i+1]) / 1;
i++;
break;
default: //somthing is wrong with data
i = data.length;
break;
}
}
return obj;
}
function decodeUplink(input) {
var warnings = [];
warnings.push();
var data = DecodeLPPPayload(input.bytes);
return {data,warnings};
}
BACnet Object Mapping Requirements
- Temperature → AnalogInputObject (degreesCelsius)
- Relative Humidity → AnalogInputObject (percent)
- CO2 → AnalogInputObject (partsPerMillion)
- Brightness → AnalogInputObject (lux)
- Motion Detection → BinaryInputObject (motion detected / no motion detected)
- Occupancy → BinaryInputObject (occupied / unoccupied)
- Battery Voltage → AnalogInputObject (millivolts)
Priority
⚡ Medium - Planned for near-term use
Email
luca.georg@thermokon.de
Company or organization
Thermokon Sensortechnik GmbH
Pre-submission Checklist
Device Vendor
Thermokon Sensortechnik GmbH
Device Model
NOVOS 3 Occ Lum CO2 Temp_rH
Product Manual/Datasheet Link
https://www.thermokon.de/direct/alterra-base/mimes/get/f3f365ccac822a0b6 / https://www.thermokon.de/direct/alterra-base/mimes/get/3d63622604fadb043
LoRaWAN Class
Class A
LoRaWAN Protocol Version
LORAWAN_1_0_4
Uplink Data Examples
Decode Function (Optional)
BACnet Object Mapping Requirements
Priority
⚡ Medium - Planned for near-term use
Email
luca.georg@thermokon.de
Company or organization
Thermokon Sensortechnik GmbH
Pre-submission Checklist