UNPKG

prisme-flow

Version:

prisme platform flow engine

1,505 lines (1,409 loc) 58.9 kB
var baEnum = require('./bacnet-enum'); var BACNET_MAX_OBJECT = module.exports.BACNET_MAX_OBJECT = 0x3FF; var BACNET_INSTANCE_BITS = module.exports.BACNET_INSTANCE_BITS = 22; var BACNET_MAX_INSTANCE = module.exports.BACNET_MAX_INSTANCE = 0x3FFFFF; var MAX_BITSTRING_BYTES = module.exports.MAX_BITSTRING_BYTES = 15; var BACNET_ARRAY_ALL = module.exports.BACNET_ARRAY_ALL = 0xFFFFFFFF; var BACNET_NO_PRIORITY = module.exports.BACNET_NO_PRIORITY = 0; var BACNET_MIN_PRIORITY = module.exports.BACNET_MIN_PRIORITY = 1; var BACNET_MAX_PRIORITY = module.exports.BACNET_MAX_PRIORITY = 16; var encodeUnsigned = function(buffer, value, length) { buffer.buffer.writeUIntBE(value, buffer.offset, length, true); buffer.offset += length; }; var encodeBacnetUnsigned = function(buffer, value) { if (value < 0x100) { encodeUnsigned(buffer, value, 1); } else if (value < 0x10000) { encodeUnsigned(buffer, value, 2); } else if (value < 0x1000000) { encodeUnsigned(buffer, value, 3); } else { encodeUnsigned(buffer, value, 4); } }; var encodeSigned = function(buffer, value, length) { buffer.buffer.writeIntBE(value, buffer.offset, length, true); buffer.offset += length; }; var encode_bacnet_signed = function(buffer, value) { if ((value >= -128) && (value < 128)) { encodeSigned(buffer, value, 1); } else if ((value >= -32768) && (value < 32768)) { encodeSigned(buffer, value, 2); } else if ((value > -8388608) && (value < 8388608)) { encodeSigned(buffer, value, 3); } else { encodeSigned(buffer, value, 4); } }; var encodeBacnetReal = function(buffer, value) { buffer.buffer.writeFloatBE(value, buffer.offset, true); buffer.offset += 4; }; var encodeBacnetDouble = function(buffer, value) { buffer.buffer.writeDoubleBE(value, buffer.offset, true); buffer.offset += 8; }; var decode_unsigned = module.exports.decode_unsigned = function(buffer, offset, length) { return { len: length, value: buffer.readUIntBE(offset, length, true) }; }; var decode_enumerated = module.exports.decode_enumerated = function(buffer, offset, lenValue) { return decode_unsigned(buffer, offset, lenValue); }; var encodeBacnetObjectId = module.exports.encodeBacnetObjectId = function(buffer, objectType, instance) { var value = ((objectType & BACNET_MAX_OBJECT) << BACNET_INSTANCE_BITS) | (instance & BACNET_MAX_INSTANCE); encodeUnsigned(buffer, value, 4); }; var encodeTag = module.exports.encodeTag = function(buffer, tagNumber, contextSpecific, lenValueType) { var len = 1; var tmp = new Array(3); tmp[0] = 0; if (contextSpecific) { tmp[0] |= 0x8; } if (tagNumber <= 14) { tmp[0] |= (tagNumber << 4); } else { tmp[0] |= 0xF0; tmp[1] = tagNumber; len++; } if (lenValueType <= 4) { tmp[0] |= lenValueType; Buffer.from(tmp).copy(buffer.buffer, buffer.offset, 0, len); buffer.offset += len; } else { tmp[0] |= 5; if (lenValueType <= 253) { tmp[len++] = lenValueType; Buffer.from(tmp).copy(buffer.buffer, buffer.offset, 0, len); buffer.offset += len; } else if (lenValueType <= 65535) { tmp[len++] = 254; Buffer.from(tmp).copy(buffer.buffer, buffer.offset, 0, len); buffer.offset += len; encodeUnsigned(buffer, lenValueType, 2); } else { tmp[len++] = 255; Buffer.from(tmp).copy(buffer.buffer, buffer.offset, 0, len); buffer.offset += len; encodeUnsigned(buffer, lenValueType, 4); } } }; var encodeBacnetEnumerated = function(buffer, value) { encodeBacnetUnsigned(buffer, value); }; var IS_EXTENDED_tagNumber = function(x) { return (x & 0xF0) === 0xF0; }; var IS_EXTENDED_VALUE = function(x) { return (x & 0x07) === 5; }; var IS_contextSpecific = function(x) { return (x & 0x8) === 0x8; }; var IS_OPENING_TAG = function(x) { return (x & 0x07) === 6; }; var IS_CLOSING_TAG = function(x) { return (x & 0x07) === 7; }; var encodeContextReal = function(buffer, tagNumber, value) { encodeTag(buffer, tagNumber, true, 4); encodeBacnetReal(buffer, value); }; var encodeContextUnsigned = module.exports.encodeContextUnsigned = function(buffer, tagNumber, value) { var len; if (value < 0x100) { len = 1; } else if (value < 0x10000) { len = 2; } else if (value < 0x1000000) { len = 3; } else { len = 4; } encodeTag(buffer, tagNumber, true, len); encodeBacnetUnsigned(buffer, value); }; var encodeContextEnumerated = module.exports.encodeContextEnumerated = function(buffer, tagNumber, value) { var len; if (value < 0x100) { len = 1; } else if (value < 0x10000) { len = 2; } else if (value < 0x1000000) { len = 3; } else { len = 4; } encodeTag(buffer, tagNumber, true, len); encodeBacnetEnumerated(buffer, value); }; var encode_octetString = function(buffer, octetString, octetOffset, octetCount) { if (octetString) { for (var i = octetOffset; i < (octetOffset + octetCount); i++) { buffer.buffer[buffer.offset++] = octetString[i]; } } }; var encode_application_octetString = function(buffer, octetString, octetOffset, octetCount) { encodeTag(buffer, baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_OCTET_STRING, false, octetCount); encode_octetString(buffer, octetString, octetOffset, octetCount); }; var encode_application_boolean = function(buffer, booleanValue) { encodeTag(buffer, baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_BOOLEAN, false, booleanValue ? 1 : 0); }; var encode_application_real = function(buffer, value) { encodeTag(buffer, baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_REAL, false, 4); encodeBacnetReal(buffer, value); }; var encode_application_double = function(buffer, value) { encodeTag(buffer, baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_DOUBLE, false, 8); encodeBacnetDouble(buffer, value); }; var bitstring_bytes_used = function(bitString) { var len = 0; if (bitString.bits_used > 0) { var lastBit = bitString.bits_used - 1; var usedBytes = (lastBit / 8) + 1; len = Math.floor(usedBytes); } return len; }; var encode_application_object_id = module.exports.encode_application_object_id = function(buffer, object_type, instance) { var tmp = { buffer: Buffer.alloc(1472), offset: 0 }; encodeBacnetObjectId(tmp, object_type, instance); encodeTag(buffer, baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID, false, tmp.offset); tmp.buffer.copy(buffer.buffer, buffer.offset, 0, tmp.offset); buffer.offset += tmp.offset; }; var encode_application_unsigned = module.exports.encode_application_unsigned = function(buffer, value) { var tmp = { buffer: Buffer.alloc(1472), offset: 0 }; encodeBacnetUnsigned(tmp, value); encodeTag(buffer, baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT, false, tmp.offset); tmp.buffer.copy(buffer.buffer, buffer.offset, 0, tmp.offset); buffer.offset += tmp.offset; }; var encode_application_enumerated = module.exports.encode_application_enumerated = function(buffer, value) { var tmp = { buffer: Buffer.alloc(1472), offset: 0 }; encodeBacnetEnumerated(tmp, value); encodeTag(buffer, baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_ENUMERATED, false, tmp.offset); tmp.buffer.copy(buffer.buffer, buffer.offset, 0, tmp.offset); buffer.offset += tmp.offset; }; var encode_application_signed = module.exports.encode_application_signed = function(buffer, value) { var tmp = { buffer: Buffer.alloc(1472), offset: 0 }; encode_bacnet_signed(tmp, value); encodeTag(buffer, baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_SIGNED_INT, false, tmp.offset); tmp.buffer.copy(buffer.buffer, buffer.offset, 0, tmp.offset); buffer.offset += tmp.offset; }; var byte_reverse_bits = function(inByte) { var outByte = 0; if ((inByte & 1) > 0) { outByte |= 0x80; } if ((inByte & 2) > 0) { outByte |= 0x40; } if ((inByte & 4) > 0) { outByte |= 0x20; } if ((inByte & 8) > 0) { outByte |= 0x10; } if ((inByte & 16) > 0) { outByte |= 0x8; } if ((inByte & 32) > 0) { outByte |= 0x4; } if ((inByte & 64) > 0) { outByte |= 0x2; } if ((inByte & 128) > 0) { outByte |= 1; } return outByte; }; var bitstring_octet = function(bitString, octetIndex) { var octet = 0; if (bitString.value) { if (octetIndex < MAX_BITSTRING_BYTES) { octet = bitString.value[octetIndex]; } } return octet; }; var encode_bitstring = function(buffer, bitString) { if (bitString.bits_used === 0) { buffer.buffer[buffer.offset++] = 0; } else { var usedBytes = bitstring_bytes_used(bitString); var remainingUsedBits = bitString.bits_used - ((usedBytes - 1) * 8); buffer.buffer[buffer.offset++] = 8 - remainingUsedBits; for (var i = 0; i < usedBytes; i++) { buffer.buffer[buffer.offset++] = byte_reverse_bits(bitstring_octet(bitString, i)); } } }; var encode_application_bitstring = function(buffer, bitString) { var bitStringEncodedLength = 1; bitStringEncodedLength += bitstring_bytes_used(bitString); encodeTag(buffer, baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_BIT_STRING, false, bitStringEncodedLength); encode_bitstring(buffer, bitString); }; var encode_bacnet_date = function(buffer, value) { if (value === new Date(1, 1, 1)) { buffer.buffer[buffer.offset++] = 0xFF; buffer.buffer[buffer.offset++] = 0xFF; buffer.buffer[buffer.offset++] = 0xFF; buffer.buffer[buffer.offset++] = 0xFF; return; } if (value.getFullYear() >= 1900) { buffer.buffer[buffer.offset++] = (value.getFullYear() - 1900); } else if (value.getFullYear() < 0x100) { buffer.buffer[buffer.offset++] = value.getFullYear(); } else { return; } buffer.buffer[buffer.offset++] = value.getMonth(); buffer.buffer[buffer.offset++] = value.getDate(); buffer.buffer[buffer.offset++] = value.getDay(); }; var encode_application_date = module.exports.encode_application_date = function(buffer, value) { encodeTag(buffer, baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_DATE, false, 4); encode_bacnet_date(buffer, value); }; var encode_bacnet_time = function(buffer, value) { buffer.buffer[buffer.offset++] = value.getHours(); buffer.buffer[buffer.offset++] = value.getMinutes(); buffer.buffer[buffer.offset++] = value.getSeconds(); buffer.buffer[buffer.offset++] = value.getMilliseconds() / 10; }; var encode_application_time = module.exports.encode_application_time = function(buffer, value) { encodeTag(buffer, baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_TIME, false, 4); encode_bacnet_time(buffer, value); }; var bacapp_encode_datetime = function(buffer, value) { if (value !== new Date(1, 1, 1)) { encode_application_date(buffer, value); encode_application_time(buffer, value); } }; var encode_context_object_id = module.exports.encode_context_object_id = function(buffer, tagNumber, objectType, instance) { encodeTag(buffer, tagNumber, true, 4); encodeBacnetObjectId(buffer, objectType, instance); }; var encode_opening_tag = module.exports.encode_opening_tag = function(buffer, tagNumber) { var len = 1; var tmp = new Array(2); tmp[0] = 0x8; if (tagNumber <= 14) { tmp[0] |= (tagNumber << 4); } else { tmp[0] |= 0xF0; tmp[1] = tagNumber; len++; } tmp[0] |= 6; Buffer.from(tmp).copy(buffer.buffer, buffer.offset, 0, len); buffer.offset += len; }; var encode_closing_tag = module.exports.encode_closing_tag = function(buffer, tagNumber) { var len = 1; var tmp = new Array(2); tmp[0] = 0x8; if (tagNumber <= 14) { tmp[0] |= (tagNumber << 4); } else { tmp[0] |= 0xF0; tmp[1] = tagNumber; len++; } tmp[0] |= 7; Buffer.from(tmp).copy(buffer.buffer, buffer.offset, 0, len); buffer.offset += len; }; var encode_read_access_specification = module.exports.encode_read_access_specification = function(buffer, value) { encode_context_object_id(buffer, 0, value.objectIdentifier.type, value.objectIdentifier.instance); encode_opening_tag(buffer, 1); value.propertyReferences.forEach(function(p) { encodeContextEnumerated(buffer, 0, p.propertyIdentifier); if (p.propertyArrayIndex && p.propertyArrayIndex !== BACNET_ARRAY_ALL) { encodeContextUnsigned(buffer, 1, p.propertyArrayIndex); } }); encode_closing_tag(buffer, 1); }; var encodeContextBoolean = function(buffer, tagNumber, booleanValue) { encodeTag(buffer, tagNumber, true, 1); buffer.buffer.writeUInt8(booleanValue ? 1 : 0, buffer.offset, true); buffer.offset += 1; }; var encode_cov_subscription = function(buffer, value) { encode_opening_tag(buffer, 0); encode_opening_tag(buffer, 0); encode_opening_tag(buffer, 1); encode_application_unsigned(buffer, value.Recipient.net); if (value.Recipient.net === 0xFFFF) { encode_application_octetString(buffer, 0, 0, 0); } else { encode_application_octetString(buffer, value.Recipient.adr, 0, value.Recipient.adr.length); } encode_closing_tag(buffer, 1); encode_closing_tag(buffer, 0); encodeContextUnsigned(buffer, 1, value.subscriptionProcessIdentifier); encode_closing_tag(buffer, 0); encode_opening_tag(buffer, 1); encode_context_object_id(buffer, 0, value.monitoredObjectIdentifier.type, value.monitoredObjectIdentifier.instance); encodeContextEnumerated(buffer, 1, value.monitoredProperty.propertyIdentifier); if (value.monitoredProperty.propertyArrayIndex !== BACNET_ARRAY_ALL) { encodeContextUnsigned(buffer, 2, value.monitoredProperty.propertyArrayIndex); } encode_closing_tag(buffer, 1); encodeContextBoolean(buffer, 2, value.IssueConfirmedNotifications); encodeContextUnsigned(buffer, 3, value.TimeRemaining); if (value.COVIncrement > 0) { encodeContextReal(buffer, 4, value.COVIncrement); } }; var bacapp_encode_application_data = module.exports.bacapp_encode_application_data = function(buffer, value) { if (value.value === null) { buffer.Add(baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_NULL); return; } switch (value.Tag) { case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_NULL: break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_BOOLEAN: encode_application_boolean(buffer, value.Value); break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT: encode_application_unsigned(buffer, value.Value); break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_SIGNED_INT: encode_application_signed(buffer, value.Value); break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_REAL: encode_application_real(buffer, value.Value); break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_DOUBLE: encode_application_double(buffer, value.Value); break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_OCTET_STRING: encode_application_octetString(buffer, value.Value, 0, value.Value.length); break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_CHARACTER_STRING: encode_application_character_string(buffer, value.Value); break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_BIT_STRING: encode_application_bitstring(buffer, value.Value); break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_ENUMERATED: encode_application_enumerated(buffer, value.Value); break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_DATE: encode_application_date(buffer, value.Value); break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_TIME: encode_application_time(buffer, value.Value); break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_TIMESTAMP: bacapp_encode_timestamp(buffer, value.Value); break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_DATETIME: bacapp_encode_datetime(buffer, value.Value); break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID: encode_application_object_id(buffer, (value.Value).type, (value.Value).instance); break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_COV_SUBSCRIPTION: encode_cov_subscription(buffer, value.Value); break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_READ_ACCESS_RESULT: encode_read_access_result(buffer, value.Value); break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_READ_ACCESS_SPECIFICATION: encode_read_access_specification(buffer, value.Value); break; default: throw 'Unknown type'; } }; var bacapp_encode_device_obj_property_ref = function(buffer, value) { encode_context_object_id(buffer, 0, value.objectIdentifier.type, value.objectIdentifier.instance); encodeContextEnumerated(buffer, 1, value.propertyIdentifier); if (value.arrayIndex !== BACNET_ARRAY_ALL) { encodeContextUnsigned(buffer, 2, value.arrayIndex); } if (value.deviceIndentifier.type === baEnum.BacnetObjectTypes.OBJECT_DEVICE) { encode_context_object_id(buffer, 3, value.deviceIndentifier.type, value.deviceIndentifier.instance); } }; var bacapp_encode_context_device_obj_property_ref = function(buffer, tagNumber, value) { encode_opening_tag(buffer, tagNumber); bacapp_encode_device_obj_property_ref(buffer, value); encode_closing_tag(buffer, tagNumber); }; var bacapp_encode_property_state = function(buffer, value) { switch (value.Tag) { case baEnum.BacnetPropetyState.BacnetPropertyStateTypes.BOOLEAN_VALUE: encodeContextBoolean(buffer, 0, value.state === 1 ? true : false); break; case baEnum.BacnetPropetyState.BacnetPropertyStateTypes.BINARY_VALUE: encodeContextEnumerated(buffer, 1, value.state); break; case baEnum.baEnum.BacnetPropetyState.BacnetPropertyStateTypes.EVENT_TYPE: encodeContextEnumerated(buffer, 2, value.state); break; case baEnum.BacnetPropetyState.BacnetPropertyStateTypes.POLARITY: encodeContextEnumerated(buffer, 3, value.state); break; case baEnum.BacnetPropetyState.BacnetPropertyStateTypes.PROGRAM_CHANGE: encodeContextEnumerated(buffer, 4, value.state); break; case baEnum.BacnetPropetyState.BacnetPropertyStateTypes.PROGRAM_STATE: encodeContextEnumerated(buffer, 5, value.state); break; case baEnum.BacnetPropetyState.BacnetPropertyStateTypes.REASON_FOR_HALT: encodeContextEnumerated(buffer, 6, value.state); break; case baEnum.BacnetPropetyState.BacnetPropertyStateTypes.RELIABILITY: encodeContextEnumerated(buffer, 7, value.state); break; case baEnum.BacnetPropetyState.BacnetPropertyStateTypes.STATE: encodeContextEnumerated(buffer, 8, value.state); break; case baEnum.BacnetPropetyState.BacnetPropertyStateTypes.SYSTEM_STATUS: encodeContextEnumerated(buffer, 9, value.state); break; case baEnum.BacnetPropetyState.BacnetPropertyStateTypes.UNITS: encodeContextEnumerated(buffer, 10, value.state); break; case baEnum.BacnetPropetyState.BacnetPropertyStateTypes.UNSIGNED_VALUE: encodeContextUnsigned(buffer, 11, value.state); break; case baEnum.BacnetPropetyState.BacnetPropertyStateTypes.LIFE_SAFETY_MODE: encodeContextEnumerated(buffer, 12, value.state); break; case baEnum.BacnetPropetyState.BacnetPropertyStateTypes.LIFE_SAFETY_STATE: encodeContextEnumerated(buffer, 13, value.state); break; default: break; } }; var encode_context_bitstring = function(buffer, tagNumber, bitString) { var bitStringEncodedLength = 1; bitStringEncodedLength += bitstring_bytes_used(bitString); encodeTag(buffer, tagNumber, true, bitStringEncodedLength); encode_bitstring(buffer, bitString); }; var encode_context_signed = function(buffer, tagNumber, value) { var len = 0; if ((value >= -128) && (value < 128)) { len = 1; } else if ((value >= -32768) && (value < 32768)) { len = 2; } else if ((value > -8388608) && (value < 8388608)) { len = 3; } else { len = 4; } encodeTag(buffer, tagNumber, true, len); encode_bacnet_signed(buffer, value); }; var encode_context_time = function(buffer, tagNumber, value) { encodeTag(buffer, tagNumber, true, 4); encode_bacnet_time(buffer, value); }; var bacapp_encode_context_datetime = function(buffer, tagNumber, value) { if (value !== new Date(1, 1, 1)) { encode_opening_tag(buffer, tagNumber); bacapp_encode_datetime(buffer, value); encode_closing_tag(buffer, tagNumber); } }; var decode_tagNumber = function(buffer, offset) { var len = 1; var tagNumber; if (IS_EXTENDED_tagNumber(buffer[offset])) { tagNumber = buffer[offset + 1]; len++; } else { tagNumber = buffer[offset] >> 4; } return { len: len, tagNumber: tagNumber }; }; var decode_is_context_tag = module.exports.decode_is_context_tag = function(buffer, offset, tagNumber) { var result = decode_tagNumber(buffer, offset); return IS_contextSpecific(buffer[offset]) && result.tagNumber === tagNumber; }; var decode_is_opening_tag_number = module.exports.decode_is_opening_tag_number = function(buffer, offset, tagNumber) { var result = decode_tagNumber(buffer, offset); return IS_OPENING_TAG(buffer[offset]) && result.tagNumber === tagNumber; }; var decode_is_closing_tag_number = module.exports.decode_is_closing_tag_number = function(buffer, offset, tagNumber) { var result = decode_tagNumber(buffer, offset); return IS_CLOSING_TAG(buffer[offset]) && result.tagNumber === tagNumber; }; var decode_is_closing_tag = function(buffer, offset) { return (buffer[offset] & 0x07) === 7; }; var decode_is_opening_tag = function(buffer, offset) { return (buffer[offset] & 0x07) === 6; }; var decode_object_id = module.exports.decode_object_id = function(buffer, offset) { var result = decode_unsigned(buffer, offset, 4); var objectType = (result.value >> BACNET_INSTANCE_BITS) & BACNET_MAX_OBJECT; var instance = result.value & BACNET_MAX_INSTANCE; return { len: result.len, objectType: objectType, instance: instance }; }; var decode_object_id_safe = function(buffer, offset, lenValue) { if (lenValue !== 4) { return { len: 0, objectType: 0, instance: 0 }; } else { return decode_object_id(buffer, offset); } }; var decode_tag_number_and_value = module.exports.decode_tag_number_and_value = function(buffer, offset) { var value; var result = decode_tagNumber(buffer, offset); var len = result.len; if (IS_EXTENDED_VALUE(buffer[offset])) { if (buffer[offset + len] === 255) { len++; result = decode_unsigned(buffer, offset + len, 4); len += result.len; value = result.value; } else if (buffer[offset + len] === 254) { len++; result = decode_unsigned(buffer, offset + len, 2); len += result.len; value = result.value; } else { value = buffer[offset + len]; len++; } } else if (IS_OPENING_TAG(buffer[offset])) { value = 0; } else if (IS_CLOSING_TAG(buffer[offset])) { value = 0; } else { value = buffer[offset] & 0x07; } return { len: len, tagNumber: result.tagNumber, value: value }; }; var bacapp_decode_application_data = module.exports.bacapp_decode_application_data = function(buffer, offset, maxOffset, objectType, propertyId) { if (!IS_contextSpecific(buffer[offset])) { var result = decode_tag_number_and_value(buffer, offset); if (result) { var len = result.len; result = bacapp_decode_data(buffer, offset + len, maxOffset, result.tagNumber, result.value); if (!result) return; return { len: len + result.len, type: result.type, value: result.value }; } } else { return bacapp_decode_context_application_data(buffer, offset, maxOffset, objectType, propertyId); } }; var encode_read_access_result = module.exports.encode_read_access_result = function(buffer, value) { encode_context_object_id(buffer, 0, value.objectIdentifier.type, value.objectIdentifier.instance); encode_opening_tag(buffer, 1); value.values.forEach(function(item) { encodeContextEnumerated(buffer, 2, item.property.propertyIdentifier); if (item.property.propertyArrayIndex !== BACNET_ARRAY_ALL) { encodeContextUnsigned(buffer, 3, item.property.propertyArrayIndex); } if (item.value && item.value[0].Value.type === 'BacnetError') { encode_opening_tag(buffer, 5); encode_application_enumerated(buffer, item.value[0].Value.error_class); encode_application_enumerated(buffer, item.value[0].Value.error_code); encode_closing_tag(buffer, 5); } else { encode_opening_tag(buffer, 4); item.value.forEach(function(subItem) { bacapp_encode_application_data(buffer, subItem); }); encode_closing_tag(buffer, 4); } }); encode_closing_tag(buffer, 1); }; var decode_read_access_result = module.exports.decode_read_access_result = function(buffer, offset, apduLen) { var len = 0; var value = {}; if (!decode_is_context_tag(buffer, offset + len, 0)) return; len++; var result = decode_object_id(buffer, offset + len); value.objectIdentifier = { type: result.objectType, instance: result.instance }; len += result.len; if (!decode_is_opening_tag_number(buffer, offset + len, 1)) return -1; len++; var _value_list = []; while ((apduLen - len) > 0) { var new_entry = {}; if (decode_is_closing_tag_number(buffer, offset + len, 1)) { len++; break; } result = decode_tag_number_and_value(buffer, offset + len); len += result.len; if (result.tagNumber !== 2) return; result = decode_enumerated(buffer, offset + len, result.value); new_entry.propertyIdentifier = result.value; len += result.len; result = decode_tag_number_and_value(buffer, offset + len); if (result.tagNumber === 3) { len += result.len; result = decode_unsigned(buffer, offset + len, result.value); new_entry.propertyArrayIndex = result.value; len += result.len; } else { new_entry.propertyArrayIndex = BACNET_ARRAY_ALL; } result = decode_tag_number_and_value(buffer, offset + len); len += result.len; if (result.tagNumber === 4) { var localValues = []; while ((len + offset) <= buffer.length && !decode_is_closing_tag_number(buffer, offset + len, 4)) { var localResult = bacapp_decode_application_data(buffer, offset + len, apduLen + offset - 1, value.objectIdentifier.type, new_entry.propertyIdentifier); if (!localResult) return; len += localResult.len; localValues.push({value: localResult.value, type: localResult.type}); } if (!decode_is_closing_tag_number(buffer, offset + len, 4)) return; if ((localValues.count === 2) && (localValues[0].Tag === baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_DATE) && (localValues[1].Tag === baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_TIME)) { var date = localValues[0].value; var time = localValues[1].value; var bdatetime = new Date(date.year, date.month, date.day, time.hour, time.minute, time.second, time.millisecond); new_entry.value = [ {type: baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_DATETIME, value: bdatetime} ]; } else { new_entry.value = localValues; } len++; } else if (result.tagNumber === 5) { var err = {}; result = decode_tag_number_and_value(buffer, offset + len); len += result.len; result = decode_enumerated(buffer, offset + len, result.value); len += result.len; err.errorClass = result.value; result = decode_tag_number_and_value(buffer, offset + len); len += result.len; result = decode_enumerated(buffer, offset + len, result.value); len += result.len; err.error_code = result.value; if (!decode_is_closing_tag_number(buffer, offset + len, 5)) return; len++; new_entry.value = { type: baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_ERROR, value: err }; } _value_list.push(new_entry); } value.values = _value_list; return { len: len, value: value }; }; var decode_signed = function(buffer, offset, length) { return { len: length, value: buffer.readIntBE(offset, length, true) }; }; var decode_real = function(buffer, offset) { return { len: 4, value: buffer.readFloatBE(offset, true) }; }; var decode_real_safe = function(buffer, offset, lenValue) { if (lenValue !== 4) { return { len: lenValue, value: 0 }; } else { return decode_real(buffer, offset); } }; var decode_double = function(buffer, offset) { return { len: 8, value: buffer.readDoubleBE(offset, true) }; }; var decode_double_safe = function(buffer, offset, lenValue) { if (lenValue !== 8) { return { len: lenValue, value: 0 }; } else { return decode_double(buffer, offset); } }; var decode_octetString = function(buffer, offset, maxLength, octetStringOffset, octetStringLength) { var octetString = []; for (var i = octetStringOffset; i < (octetStringOffset + octetStringLength); i++) { octetString.push(buffer[offset + i]); } return { len: octetStringLength, value: octetString }; }; var decode_context_octetString = function(buffer, offset, maxLength, tagNumber, octetString, octetStringOffset) { if (decode_is_context_tag(buffer, offset, tagNumber)) { var result = decode_tag_number_and_value(buffer, offset); return { len: result.lenValue + result.len, value: Buffer.from(buffer.slice(offset, result.lenValue)) }; } else { return; } }; var multi_charset_characterstring_decode = function(buffer, offset, maxLength, encoding, length) { var nodeEncoding; switch (encoding) { case baEnum.BacnetCharacterStringEncodings.CHARACTER_UTF8: nodeEncoding = 'utf8'; break; case baEnum.BacnetCharacterStringEncodings.CHARACTER_UCS2: if ((buffer[offset] === 0xFF) && (buffer[offset + 1] === 0xFE)) { nodeEncoding = 'ucs2'; } else { return; } break; case baEnum.BacnetCharacterStringEncodings.CHARACTER_UCS4: case baEnum.BacnetCharacterStringEncodings.CHARACTER_ISO8859: case baEnum.BacnetCharacterStringEncodings.CHARACTER_MS_DBCS: case baEnum.BacnetCharacterStringEncodings.CHARACTER_JISX_0208: return; default: nodeEncoding = 'latin1'; break; } return { value: buffer.toString(nodeEncoding, offset, offset + length), len: length + 1 }; }; var decode_character_string = module.exports.decode_character_string = function(buffer, offset, maxLength, lenValue) { return multi_charset_characterstring_decode(buffer, offset + 1, maxLength, buffer[offset], lenValue - 1); }; var bitstring_set_octet = function(bitString, index, octet) { var status = false; if (index < MAX_BITSTRING_BYTES) { bitString.value[index] = octet; status = true; } return status; }; var bitstring_set_bits_used = function(bitString, bytesUsed, unusedBits) { bitString.bits_used = bytesUsed * 8; bitString.bits_used -= unusedBits; }; var decode_bitstring = function(buffer, offset, lenValue) { var len = 0; var bitString = {}; bitString.value = []; if (lenValue > 0) { var bytesUsed = lenValue - 1; if (bytesUsed <= MAX_BITSTRING_BYTES) { len = 1; for (var i = 0; i < bytesUsed; i++) { bitString.value.push(byte_reverse_bits(buffer[offset + len++])); } var unusedBits = buffer[offset] & 0x07; bitstring_set_bits_used(bitString, bytesUsed, unusedBits); } } return { len: len, value: bitString }; }; var decode_date = module.exports.decode_date = function(buffer, offset) { var date; var year = buffer[offset] + 1900; var month = buffer[offset + 1]; var day = buffer[offset + 2]; var wday = buffer[offset + 3]; if (month === 0xFF && day === 0xFF && wday === 0xFF && (year - 1900) === 0xFF) { date = new Date(1, 1, 1); } else { date = new Date(year, month, day); } return { len: 4, value: date }; }; var decode_date_safe = function(buffer, offset, lenValue) { if (lenValue !== 4) { return { len: lenValue, value: new Date(1, 1, 1) }; } else { return decode_date(buffer, offset); } }; var decode_application_date = function(buffer, offset) { var result = decode_tagNumber(buffer, offset); if (result.tagNumber === baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_DATE) { var value = decode_date(buffer, offset + 1); return { len: value.len + 1, value: value }; } else { return; } }; var decode_bacnet_time = module.exports.decode_bacnet_time = function(buffer, offset) { var value; var hour = buffer[offset + 0]; var min = buffer[offset + 1]; var sec = buffer[offset + 2]; var hundredths = buffer[offset + 3]; if (hour === 0xFF && min === 0xFF && sec === 0xFF && hundredths === 0xFF) { value = new Date(1, 1, 1); } else { if (hundredths > 100) hundredths = 0; value = new Date(1, 1, 1, hour, min, sec, hundredths * 10); } return { len: 4, value: value }; }; var decode_bacnet_time_safe = function(buffer, offset, lenValue) { if (lenValue !== 4) { return { len: lenValue, value: new Date(1, 1, 1) }; } else { return decode_bacnet_time(buffer, offset); } }; var decode_application_time = function(buffer, offset) { var result = decode_tagNumber(buffer, offset); if (result.tagNumber === baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_TIME) { var value = decode_bacnet_time(buffer, offset + 1); return { len: value.len + 1, value: value }; } else { return; } }; var decode_bacnet_datetime = function(buffer, offset) { var len = 0; var date = decode_application_date(buffer, offset + len); len += date.len; var time = decode_application_time(buffer, offset + len); len += time.len; return { len: len, value: new Date(date.year, date.month, date.day, time.hour, time.minute, time.second, time.millisecond) }; }; var bacapp_decode_data = function(buffer, offset, maxLength, tagDataType, lenValueType) { var result; var value = { len: 0, type: tagDataType }; switch (tagDataType) { case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_NULL: break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_BOOLEAN: value.value = lenValueType > 0 ? true : false; break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT: result = decode_unsigned(buffer, offset, lenValueType); value.len += result.len; value.value = result.value; break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_SIGNED_INT: result = decode_signed(buffer, offset, lenValueType); value.len += result.len; value.value = result.value; break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_REAL: result = decode_real_safe(buffer, offset, lenValueType); value.len += result.len; value.value = result.value; break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_DOUBLE: result = decode_double_safe(buffer, offset, lenValueType); value.len += result.len; value.value = result.value; break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_OCTET_STRING: result = decode_octetString(buffer, offset, maxLength, 0, lenValueType); value.len += result.len; value.value = result.value; break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_CHARACTER_STRING: result = decode_character_string(buffer, offset, maxLength, lenValueType); value.len += result.len; value.value = result.value; break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_BIT_STRING: result = decode_bitstring(buffer, offset, lenValueType); value.len += result.len; value.value = result.value; break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_ENUMERATED: result = decode_enumerated(buffer, offset, lenValueType); value.len += result.len; value.value = result.value; break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_DATE: result = decode_date_safe(buffer, offset, lenValueType); value.len += result.len; value.value = result.value; break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_TIME: result = decode_bacnet_time_safe(buffer, offset, lenValueType); value.len += result.len; value.value = result.value; break; case baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID: result = decode_object_id_safe(buffer, offset, lenValueType); value.len += result.len; value.value = {type: result.objectType, instance: result.instance}; break; default: break; } return value; }; var bacapp_context_tag_type = function(property, tagNumber) { var tag = baEnum.BacnetApplicationTags.MAX_BACNET_APPLICATION_TAG; switch (property) { case baEnum.BacnetPropertyIds.PROP_ACTUAL_SHED_LEVEL: case baEnum.BacnetPropertyIds.PROP_REQUESTED_SHED_LEVEL: case baEnum.BacnetPropertyIds.PROP_EXPECTED_SHED_LEVEL: switch (tagNumber) { case 0: case 1: tag = baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT; break; case 2: tag = baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_REAL; break; default: break; } break; case baEnum.BacnetPropertyIds.PROP_ACTION: switch (tagNumber) { case 0: case 1: tag = baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID; break; case 2: tag = baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_ENUMERATED; break; case 3: case 5: case 6: tag = baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT; break; case 7: case 8: tag = baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_BOOLEAN; break; default: break; } break; case baEnum.BacnetPropertyIds.PROP_LIST_OF_GROUP_MEMBERS: switch (tagNumber) { case 0: tag = baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID; break; default: break; } break; case baEnum.BacnetPropertyIds.PROP_EXCEPTION_SCHEDULE: switch (tagNumber) { case 1: tag = baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID; break; case 3: tag = baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT; break; default: break; } break; case baEnum.BacnetPropertyIds.PROP_LOG_DEVICE_OBJECT_PROPERTY: switch (tagNumber) { case 0: case 3: tag = baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID; break; case 1: tag = baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_ENUMERATED; break; case 2: tag = baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT; break; default: break; } break; case baEnum.BacnetPropertyIds.PROP_SUBORDINATE_LIST: switch (tagNumber) { case 0: case 1: tag = baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID; break; default: break; } break; case baEnum.BacnetPropertyIds.PROP_RECIPIENT_LIST: switch (tagNumber) { case 0: tag = baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID; break; default: break; } break; case baEnum.BacnetPropertyIds.PROP_ACTIVE_COV_SUBSCRIPTIONS: switch (tagNumber) { case 0: case 1: break; case 2: tag = baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_BOOLEAN; break; case 3: tag = baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT; break; case 4: tag = baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_REAL; break; default: break; } break; default: break; } return tag; }; var decode_device_obj_property_ref = function(buffer, offset) { var len = 0; var arrayIndex = BACNET_ARRAY_ALL; if (!decode_is_context_tag(buffer, offset + len, 0)) return; len++; var objectIdentifier = decode_object_id(buffer, offset + len); len += objectIdentifier.len; var result = decode_tag_number_and_value(buffer, offset + len); len += result.len; if (result.tagNumber !== 1) return; var propertyIdentifier = decode_enumerated(buffer, offset + len, result.value); len += propertyIdentifier.len; result = decode_tag_number_and_value(buffer, offset + len); if (result.tagNumber === 2) { len += result.len; arrayIndex = decode_unsigned(buffer, offset + len, result.value); len += arrayIndex.len; } if (decode_is_context_tag(buffer, offset + len, 3)) { if (!IS_CLOSING_TAG(buffer[offset + len])) { len++; objectIdentifier = decode_object_id(buffer, offset + len); len += objectIdentifier.len; } } return { len: len, value: { objectIdentifier: objectIdentifier, propertyIdentifier: propertyIdentifier } }; }; var decode_read_access_specification = function(buffer, offset, apduLen) { var len = 0; var value = {}; if (!decode_is_context_tag(buffer, offset + len, 0)) return; len++; var decodedValue = decode_object_id(buffer, offset + len); value.objectIdentifier = { type: decodedValue.objectType, instance: decodedValue.instance }; len += decodedValue.len; if (!decode_is_opening_tag_number(buffer, offset + len, 1)) return; len++; var property_id_and_array_index = []; while ((apduLen - len) > 1 && !decode_is_closing_tag_number(buffer, offset + len, 1)) { var p_ref = {}; if (!IS_contextSpecific(buffer[offset + len])) return; var result = decode_tag_number_and_value(buffer, offset + len); len += result.len; if (result.tagNumber !== 0) return; if ((len + result.value) >= apduLen) return; decodedValue = decode_enumerated(buffer, offset + len, result.value); p_ref.propertyIdentifier = decodedValue.value; len += decodedValue.len; p_ref.propertyArrayIndex = BACNET_ARRAY_ALL; if (IS_contextSpecific(buffer[offset + len]) && !IS_CLOSING_TAG(buffer[offset + len])) { var tmp = decode_tag_number_and_value(buffer, offset + len); if (tmp.tagNumber === 1) { len += tmp.len; if ((len + tmp.value) >= apduLen) return; decodedValue = decode_unsigned(buffer, offset + len, tmp.value); p_ref.propertyArrayIndex = decodedValue.value; len += decodedValue.len; } } property_id_and_array_index.push(p_ref); } if (!decode_is_closing_tag_number(buffer, offset + len, 1)) return; len++; value.propertyReferences = property_id_and_array_index; return { len: len, value: value }; }; var decode_cov_subscription = function(buffer, offset, apduLen) { var len = 0; var value = {}; var result; var decodedValue; value.recipient = {}; if (!decode_is_opening_tag_number(buffer, offset + len, 0)) return; len++; if (!decode_is_opening_tag_number(buffer, offset + len, 0)) return; len++; if (!decode_is_opening_tag_number(buffer, offset + len, 1)) return; len++; result = decode_tag_number_and_value(buffer, offset + len); len += result.len; if (result.tagNumber !== baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT) return; decodedValue = decode_unsigned(buffer, offset + len, result.value); len += decodedValue.len; value.recipient.net = decodedValue.value; result = decode_tag_number_and_value(buffer, offset + len); len += result.len; if (result.tagNumber !== baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_OCTET_STRING) return; decodedValue = decode_octetString(buffer, offset + len, apduLen, 0, result.value); len += decodedValue.len; value.recipient.adr = decodedValue.value; if (!decode_is_closing_tag_number(buffer, offset + len, 1)) return; len++; if (!decode_is_closing_tag_number(buffer, offset + len, 0)) return; len++; result = decode_tag_number_and_value(buffer, offset + len); len += result.len; if (result.tagNumber !== 1) return; decodedValue = decode_unsigned(buffer, offset + len, result.value); len += decodedValue.len; value.subscriptionProcessIdentifier = decodedValue.value; if (!decode_is_closing_tag_number(buffer, offset + len, 0)) return; len++; if (!decode_is_opening_tag_number(buffer, offset + len, 1)) return; len++; result = decode_tag_number_and_value(buffer, offset + len); len += result.len; if (result.tagNumber !== 0) return; decodedValue = decode_object_id(buffer, offset + len); len += decodedValue.len; value.monitoredObjectIdentifier = { type: decodedValue.objectType, instance: decodedValue.instance }; result = decode_tag_number_and_value(buffer, offset + len); len += result.len; if (result.tagNumber !== 1) return; decodedValue = decode_enumerated(buffer, offset + len, result.value); len += decodedValue.len; value.monitoredProperty = {}; value.monitoredProperty.propertyIdentifier = decodedValue.value; result = decode_tag_number_and_value(buffer, offset + len); if (result.tagNumber === 2) { len += result.len; decodedValue = decode_unsigned(buffer, offset + len, result.value); len += decodedValue.len; value.monitoredProperty.propertyArrayIndex = decodedValue.value; } else { value.monitoredProperty.propertyArrayIndex = BACNET_ARRAY_ALL; } if (!decode_is_closing_tag_number(buffer, offset + len, 1)) return; len++; result = decode_tag_number_and_value(buffer, offset + len); len += result.len; if (result.tagNumber !== 2) return; value.issueConfirmedNotifications = buffer[offset + len] > 0 ? true : false; len++; result = decode_tag_number_and_value(buffer, offset + len); len += result.len; if (result.tagNumber !== 3) return; decodedValue = decode_unsigned(buffer, offset + len, result.value); len += decodedValue.len; value.timeRemaining = decodedValue.value; if (len < apduLen && !IS_CLOSING_TAG(buffer[offset + len])) { result = decode_tag_number_and_value(buffer, offset + len); len += result.len; if (result.tagNumber !== 4) return; decodedValue = decode_real(buffer, offset + len); len += decodedValue.len; value.covIncrement = decodedValue.value; } return { len: len, value: value }; }; var decode_calendar_date = function(buffer, offset) { return { len: 4, year: buffer[offset], month: buffer[offset + 1], day: buffer[offset + 2], wday: buffer[offset + 3] }; }; var decode_calendar_date_range = function(buffer, offset) { var len = 1; var startDate = decode_date(buffer, offset + len); len += startDate.len + 1; var endDate = decode_date(buffer, offset + len); len += endDate.len + 1; return { len: len, startDate: startDate, endDate: endDate }; }; var decode_calendar_week_day = function(buffer, offset) { return { len: 3, month: buffer[offset], week: buffer[offset + 1], wday: buffer[offset + 2] }; }; var decode_calendar = function(buffer, offset, apduLen) { var len = 0; var entries = []; var decodedValue; while (len < apduLen) { var result = decode_tag_number(buffer, offset + len); len += result.len; switch (result.tagNumber) { case 0: decodedValue = decode_calendar_date(buffer, offset + len); len += decodedValue.len; entries.push(decodedValue); break; case 1: decodedValue = decode_calendar_date_range(buffer, offset + len); len += decodedValue.len; entries.push(decodedValue); break; case 2: decodedValue = decode_calendar_week_day(buffer, offset + len); len += decodedValue.len; entries.push(decodedValue); break; default: return { len: len - 1, value: entries }; } } }; var bacapp_decode_context_application_data = function(buffer, offset, max_offset, objectType, property_id) { var len = 0; var result; if (IS_contextSpecific(buffer[offset])) { if (property_id === baEnum.BacnetPropertyIds.PROP_LIST_OF_GROUP_MEMBERS) { result = decode_read_access_specification(buffer, offset, max_offset); if (!result) return; return { type: baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_READ_ACCESS_SPECIFICATION, value: result.value, len: result.len }; } else if (property_id === baEnum.BacnetPropertyIds.PROP_ACTIVE_COV_SUBSCRIPTIONS) { result = decode_cov_subscription(buffer, offset, max_offset); if (!result) return; return { type: baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_COV_SUBSCRIPTION, value: result.value, len: result.len }; } else if (objectType === baEnum.BacnetObjectTypes.OBJECT_GROUP && property_id === baEnum.acnetPropertyIds.PROP_PRESENT_VALUE) { result = decode_read_access_result(buffer, offset, max_offset); if (!result) return; return { type: baEnum.BacnetApplicationTags.BACNET_APPLICATION_TAG_READ_ACCESS_RESULT, value: result.value, len: r