int bacapp_decode_assigned_access_rights( uint8_t * apdu, BACNET_ASSIGNED_ACCESS_RIGHTS * aar) { int len; int apdu_len = 0; if (decode_is_context_tag(&apdu[apdu_len], 0)) { len = bacapp_decode_context_device_obj_ref(&apdu[apdu_len], 0, &aar->assigned_access_rights); if (len < 0) return -1; else apdu_len += len; } else return -1; if (decode_is_context_tag(&apdu[apdu_len], 1)) { len = decode_context_boolean2(&apdu[apdu_len], 1, &aar->enable); if (len < 0) return -1; else apdu_len += len; } else return -1; return apdu_len; }
/* decode the service request only */ int whohas_decode_service_request( uint8_t * apdu, unsigned apdu_len, BACNET_WHO_HAS_DATA * data) { int len = 0; uint8_t tag_number = 0; uint32_t len_value = 0; uint32_t decoded_value = 0; /* for decoding */ uint16_t decoded_type = 0; /* for decoding */ if (apdu_len && data) { /* optional limits - must be used as a pair */ if (decode_is_context_tag(&apdu[len], 0)) { len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); len += decode_unsigned(&apdu[len], len_value, &decoded_value); if (decoded_value <= BACNET_MAX_INSTANCE) data->low_limit = decoded_value; if (!decode_is_context_tag(&apdu[len], 1)) return -1; len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); len += decode_unsigned(&apdu[len], len_value, &decoded_value); if (decoded_value <= BACNET_MAX_INSTANCE) data->high_limit = decoded_value; } else { data->low_limit = -1; data->high_limit = -1; } /* object id */ if (decode_is_context_tag(&apdu[len], 2)) { data->object_name = false; len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); len += decode_object_id(&apdu[len], &decoded_type, &data->object.identifier.instance); data->object.identifier.type = decoded_type; } /* object name */ else if (decode_is_context_tag(&apdu[len], 3)) { data->object_name = true; len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); len += decode_character_string(&apdu[len], len_value, &data->object.name); } /* missing required parameters */ else return -1; } return len; }
/* BACnetDeviceObjectPropertyReference ::= SEQUENCE { object-identifier [0] BACnetObjectIdentifier, property-identifier [1] BACnetPropertyIdentifier, property-array-index [2] Unsigned OPTIONAL, -- used only with array datatype -- if omitted with an array then -- the entire array is referenced device-identifier [3] BACnetObjectIdentifier OPTIONAL } */ int bacapp_decode_device_obj_property_ref( uint8_t * apdu, BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value) { int len; int apdu_len = 0; uint32_t enumValue; /* object-identifier [0] BACnetObjectIdentifier */ if (-1 == (len = decode_context_object_id(&apdu[apdu_len], 0, &value->objectIdentifier.type, &value->objectIdentifier.instance))) { return -1; } apdu_len += len; /* property-identifier [1] BACnetPropertyIdentifier */ if (-1 == (len = decode_context_enumerated(&apdu[apdu_len], 1, &enumValue))) { return -1; } value->propertyIdentifier = (BACNET_PROPERTY_ID) enumValue; apdu_len += len; /* property-array-index [2] Unsigned OPTIONAL */ if (decode_is_context_tag(&apdu[apdu_len], 2) && !decode_is_closing_tag(&apdu[apdu_len])) { if (-1 == (len = decode_context_unsigned(&apdu[apdu_len], 2, &value->arrayIndex))) { return -1; } apdu_len += len; } else { value->arrayIndex = BACNET_ARRAY_ALL; } /* device-identifier [3] BACnetObjectIdentifier OPTIONAL */ if (decode_is_context_tag(&apdu[apdu_len], 3) && !decode_is_closing_tag(&apdu[apdu_len])) { if (-1 == (len = decode_context_object_id(&apdu[apdu_len], 3, &value->deviceIndentifier.type, &value->deviceIndentifier.instance))) { return -1; } apdu_len += len; } else { value->deviceIndentifier.type = BACNET_NO_DEV_TYPE; value->deviceIndentifier.instance = BACNET_NO_DEV_ID; } return apdu_len; }
int bacapp_decode_device_obj_property_ref( uint8_t * apdu, BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value) { int len; int apdu_len = 0; uint32_t enumValue; if (-1 == (len = decode_context_object_id(&apdu[apdu_len], 0, &value->objectIdentifier.type, &value->objectIdentifier.instance))) { return -1; } apdu_len += len; if (-1 == (len = decode_context_enumerated(&apdu[apdu_len], 1, &enumValue))) { return -1; } value->propertyIdentifier = (BACNET_PROPERTY_ID) enumValue; apdu_len += len; if (decode_is_context_tag(&apdu[apdu_len], 2)) { if (-1 == (len = decode_context_unsigned(&apdu[apdu_len], 2, &value->arrayIndex))) { return -1; } apdu_len += len; } else { value->arrayIndex = BACNET_ARRAY_ALL; } if (decode_is_context_tag(&apdu[apdu_len], 3)) { if (-1 == (len = decode_context_object_id(&apdu[apdu_len], 3, &value->deviceIndentifier.type, &value->deviceIndentifier.instance))) { return -1; } apdu_len += len; } else { value->deviceIndentifier.type = BACNET_NO_DEV_TYPE; value->deviceIndentifier.instance = BACNET_NO_DEV_ID; } return apdu_len; }
/* decode the object portion of the service request only */ int rpm_ack_decode_object_id( uint8_t * apdu, unsigned apdu_len, BACNET_OBJECT_TYPE * object_type, uint32_t * object_instance) { unsigned len = 0; uint16_t type = 0; /* for decoding */ /* check for value pointers */ if (apdu && apdu_len && object_type && object_instance) { /* Tag 0: objectIdentifier */ if (!decode_is_context_tag(&apdu[len++], 0)) return -1; len += decode_object_id(&apdu[len], &type, object_instance); if (object_type) *object_type = (BACNET_OBJECT_TYPE) type; /* Tag 1: listOfResults */ if (!decode_is_opening_tag_number(&apdu[len], 1)) return -1; len++; /* opening tag is only one octet */ } return (int) len; }
/* decode the object portion of the service request only. Bails out if * tags are wrong or missing/incomplete */ int rpm_decode_object_id( uint8_t * apdu, unsigned apdu_len, BACNET_RPM_DATA * rpmdata) { unsigned len = 0; uint16_t type = 0; /* for decoding */ /* check for value pointers */ if (apdu && apdu_len && rpmdata) { if (apdu_len < 5) { /* Must be at least 2 tags and an object id */ rpmdata->error_code = ERROR_CODE_REJECT_MISSING_REQUIRED_PARAMETER; return BACNET_STATUS_REJECT; } /* Tag 0: Object ID */ if (!decode_is_context_tag(&apdu[len++], 0)) { rpmdata->error_code = ERROR_CODE_REJECT_INVALID_TAG; return BACNET_STATUS_REJECT; } len += decode_object_id(&apdu[len], &type, &rpmdata->object_instance); rpmdata->object_type = (BACNET_OBJECT_TYPE) type; /* Tag 1: sequence of ReadAccessSpecification */ if (!decode_is_opening_tag_number(&apdu[len], 1)) { rpmdata->error_code = ERROR_CODE_REJECT_INVALID_TAG; return BACNET_STATUS_REJECT; } len++; /* opening tag is only one octet */ } return (int) len; }
/* BACnetDeviceObjectReference ::= SEQUENCE { device-identifier [0] BACnetObjectIdentifier OPTIONAL, object-identifier [1] BACnetObjectIdentifier }*/ int bacapp_decode_device_obj_ref( uint8_t * apdu, BACNET_DEVICE_OBJECT_REFERENCE * value) { int len; int apdu_len = 0; /* device-identifier [0] BACnetObjectIdentifier OPTIONAL */ if (decode_is_context_tag(&apdu[apdu_len], 0) && !decode_is_closing_tag(&apdu[apdu_len])) { if (-1 == (len = decode_context_object_id(&apdu[apdu_len], 0, &value->deviceIndentifier.type, &value->deviceIndentifier.instance))) { return -1; } apdu_len += len; } else { value->deviceIndentifier.type = BACNET_NO_DEV_TYPE; value->deviceIndentifier.instance = BACNET_NO_DEV_ID; } /* object-identifier [1] BACnetObjectIdentifier */ if (-1 == (len = decode_context_object_id(&apdu[apdu_len], 1, &value->objectIdentifier.type, &value->objectIdentifier.instance))) { return -1; } apdu_len += len; return apdu_len; }
int bacapp_decode_device_obj_ref( uint8_t * apdu, BACNET_DEVICE_OBJECT_REFERENCE * value) { int len; int apdu_len = 0; /* Device ID is optional */ if (decode_is_context_tag(&apdu[apdu_len], 0)) { if (-1 == (len = decode_context_object_id(&apdu[apdu_len], 0, &value->deviceIndentifier.type, &value->deviceIndentifier.instance))) { return -1; } apdu_len += len; } else { value->deviceIndentifier.type = BACNET_NO_DEV_TYPE; value->deviceIndentifier.instance = BACNET_NO_DEV_ID; } if (-1 == (len = decode_context_object_id(&apdu[apdu_len], 1, &value->objectIdentifier.type, &value->objectIdentifier.instance))) { return -1; } apdu_len += len; return apdu_len; }
int rp_ack_decode_service_request( uint8_t * apdu, int apdu_len, /* total length of the apdu */ BACNET_READ_PROPERTY_DATA * rpdata) { uint8_t tag_number = 0; uint32_t len_value_type = 0; int tag_len = 0; /* length of tag decode */ int len = 0; /* total length of decodes */ uint16_t object = 0; /* object type */ uint32_t property = 0; /* for decoding */ uint32_t array_value = 0; /* for decoding */ memset(prop_name,0,100); /* FIXME: check apdu_len against the len during decode */ /* Tag 0: Object ID */ if (!decode_is_context_tag(&apdu[0], 0)) return -1; len = 1; len += decode_object_id(&apdu[len], &object, &rpdata->object_instance); rpdata->object_type = (BACNET_OBJECT_TYPE) object; /* Tag 1: Property ID */ len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); if (tag_number != 1) return -1; len += decode_enumerated(&apdu[len], len_value_type, &property); rpdata->object_property = (BACNET_PROPERTY_ID) property; if(rpdata->object_property < PROP_EGRESS_ACTIVE) strcpy_s(prop_name,100,bacnet_property_names[rpdata->object_property ].pString); /* Tag 2: Optional Array Index */ tag_len = decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); if (tag_number == 2) { len += tag_len; len += decode_unsigned(&apdu[len], len_value_type, &array_value); rpdata->array_index = array_value; } else rpdata->array_index = BACNET_ARRAY_ALL; /* Tag 3: opening context tag */ if (decode_is_opening_tag_number(&apdu[len], 3)) { /* a tag number of 3 is not extended so only one octet */ len++; /* don't decode the application tag number or its data here */ rpdata->application_data = &apdu[len]; rpdata->application_data_len = apdu_len - len - 1 /*closing tag */ ; /* len includes the data and the closing tag */ len = apdu_len; } else { return -1; } return len; }
int Lighting_Output_Decode_Lighting_Command( uint8_t * apdu, unsigned apdu_max_len, BACNET_LIGHTING_COMMAND * data) { int len = 0; int apdu_len = 0; uint8_t tag_number = 0; uint32_t len_value_type = 0; float real_value = 0.0; apdu_max_len = apdu_max_len; /* check for value pointers */ if (apdu_len && data) { /* Tag 0: operation */ if (!decode_is_context_tag(&apdu[apdu_len], 0)) return -1; len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number, &len_value_type); apdu_len += len; len = decode_enumerated(&apdu[apdu_len], len_value_type, (uint32_t *) & data->operation); apdu_len += len; /* Tag 1: level - OPTIONAL */ if (decode_is_context_tag(&apdu[apdu_len], 1)) { len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number, &len_value_type); apdu_len += len; len = decode_real(&apdu[apdu_len], &real_value); apdu_len += len; data->level = (uint8_t) real_value; /* FIXME: are we going to flag errors in decoding values here? */ } /* FIXME: finish me! */ /* Tag 2: */ } return len; }
int lso_decode_service_request( uint8_t * apdu, unsigned apdu_len, BACNET_LSO_DATA * data) { int len = 0; /* return value */ int section_length = 0; /* length returned from decoding */ uint32_t operation = 0; /* handles decoded value */ /* check for value pointers */ if (apdu_len && data) { /* Tag 0: Object ID */ if ((section_length = decode_context_unsigned(&apdu[len], 0, &data->processId)) == -1) { return -1; } len += section_length; if ((section_length = decode_context_character_string(&apdu[len], 1, &data->requestingSrc)) == -1) { return -1; } len += section_length; if ((section_length = decode_context_enumerated(&apdu[len], 2, &operation)) == -1) { return -1; } data->operation = (BACNET_LIFE_SAFETY_OPERATION) operation; len += section_length; /* ** This is an optional parameter, so dont fail if it doesnt exist */ if (decode_is_context_tag(&apdu[len], 3)) { if ((section_length = decode_context_object_id(&apdu[len], 3, &data->targetObject.type, &data->targetObject.instance)) == -1) { return -1; } len += section_length; } else { data->targetObject.type = 0; data->targetObject.instance = 0; } return len; } return 0; }
/* decode the service request only */ int rd_decode_service_request( uint8_t * apdu, unsigned apdu_len, BACNET_REINITIALIZED_STATE * state, BACNET_CHARACTER_STRING * password) { unsigned len = 0; uint8_t tag_number = 0; uint32_t len_value_type = 0; uint32_t value = 0; /* check for value pointers */ if (apdu_len) { /* Tag 0: reinitializedStateOfDevice */ if (!decode_is_context_tag(&apdu[len], 0)) return -1; len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); len += decode_enumerated(&apdu[len], len_value_type, &value); if (state) *state = (BACNET_REINITIALIZED_STATE) value; /* Tag 1: password - optional */ if (len < apdu_len) { if (!decode_is_context_tag(&apdu[len], 1)) return -1; len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); len += decode_character_string(&apdu[len], len_value_type, password); } } return (int) len; }
/* decode the service request only */ int rp_decode_service_request( uint8_t * apdu, unsigned apdu_len, BACNET_READ_PROPERTY_DATA * rpdata) { unsigned len = 0; uint8_t tag_number = 0; uint32_t len_value_type = 0; uint16_t type = 0; /* for decoding */ uint32_t property = 0; /* for decoding */ uint32_t array_value = 0; /* for decoding */ /* check for value pointers */ if (rpdata != NULL) { /* Must have at least 2 tags, an object id and a property identifier * of at least 1 byte in length to have any chance of parsing */ if (apdu_len < 7) { rpdata->error_code = ERROR_CODE_REJECT_MISSING_REQUIRED_PARAMETER; return BACNET_STATUS_REJECT; } /* Tag 0: Object ID */ if (!decode_is_context_tag(&apdu[len++], 0)) { rpdata->error_code = ERROR_CODE_REJECT_INVALID_TAG; return BACNET_STATUS_REJECT; } len += decode_object_id(&apdu[len], &type, &rpdata->object_instance); rpdata->object_type = (BACNET_OBJECT_TYPE) type; /* Tag 1: Property ID */ len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); if (tag_number != 1) { rpdata->error_code = ERROR_CODE_REJECT_INVALID_TAG; return BACNET_STATUS_REJECT; } len += decode_enumerated(&apdu[len], len_value_type, &property); rpdata->object_property = (BACNET_PROPERTY_ID) property; /* Tag 2: Optional Array Index */ if (len < apdu_len) { len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); if ((tag_number == 2) && (len < apdu_len)) { len += decode_unsigned(&apdu[len], len_value_type, &array_value); rpdata->array_index = array_value; } else { rpdata->error_code = ERROR_CODE_REJECT_INVALID_TAG; return BACNET_STATUS_REJECT; } } else rpdata->array_index = BACNET_ARRAY_ALL; } if (len < apdu_len) { /* If something left over now, we have an invalid request */ rpdata->error_code = ERROR_CODE_REJECT_TOO_MANY_ARGUMENTS; return BACNET_STATUS_REJECT; } return (int) len; }
/** * Decodes from bytes into the lighting-command structure * * @param apdu - buffer to hold the bytes * @param apdu_max_len - number of bytes in the buffer to decode * @param value - lighting command value to place the decoded values * * @return number of bytes encoded */ int lighting_command_decode( uint8_t * apdu, unsigned apdu_max_len, BACNET_LIGHTING_COMMAND * data) { int len = 0; int apdu_len = 0; uint8_t tag_number = 0; uint32_t len_value_type = 0; uint32_t unsigned_value = 0; float real_value = 0.0; unused_var(apdu_max_len); /* check for value pointers */ if (apdu_max_len && data) { /* Tag 0: operation */ if (!decode_is_context_tag(&apdu[apdu_len], 0)) return BACNET_STATUS_ERROR; len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number, &len_value_type); apdu_len += len; len = decode_enumerated(&apdu[apdu_len], len_value_type, &unsigned_value); if (len > 0) { data->operation = unsigned_value; } apdu_len += len; /* Tag 1: target-level - OPTIONAL */ if (decode_is_context_tag(&apdu[apdu_len], 1)) { len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number, &len_value_type); apdu_len += len; len = decode_real(&apdu[apdu_len], &real_value); data->target_level = real_value; apdu_len += len; data->use_target_level = true; } else { data->use_target_level = false; } /* Tag 2: ramp-rate - OPTIONAL */ if (decode_is_context_tag(&apdu[apdu_len], 2)) { len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number, &len_value_type); apdu_len += len; len = decode_real(&apdu[apdu_len], &real_value); data->ramp_rate = real_value; data->use_ramp_rate = true; } else { data->use_ramp_rate = false; } /* Tag 3: step-increment - OPTIONAL */ if (decode_is_context_tag(&apdu[apdu_len], 3)) { len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number, &len_value_type); apdu_len += len; len = decode_real(&apdu[apdu_len], &real_value); data->step_increment = real_value; data->use_step_increment = true; } else { data->use_step_increment = false; } /* Tag 4: fade-time - OPTIONAL */ if (decode_is_context_tag(&apdu[apdu_len], 4)) { len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number, &len_value_type); apdu_len += len; len = decode_unsigned(&apdu[apdu_len], len_value_type, &unsigned_value); data->fade_time = unsigned_value; data->use_fade_time = true; } else { data->use_fade_time = false; } /* Tag 5: priority - OPTIONAL */ if (decode_is_context_tag(&apdu[apdu_len], 4)) { len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number, &len_value_type); apdu_len += len; len = decode_unsigned(&apdu[apdu_len], len_value_type, &unsigned_value); data->priority = unsigned_value; data->use_priority = true; } else { data->use_priority = false; } } return len; }
bool Notification_Class_Write_Property( BACNET_WRITE_PROPERTY_DATA * wp_data) { NOTIFICATION_CLASS_INFO *CurrentNotify; NOTIFICATION_CLASS_INFO TmpNotify; BACNET_APPLICATION_DATA_VALUE value; bool status = false; int iOffset = 0; uint8_t idx = 0; int len = 0; CurrentNotify = &NC_Info[Notification_Class_Instance_To_Index(wp_data-> object_instance)]; /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } if ((wp_data->object_property != PROP_PRIORITY) && (wp_data->array_index != BACNET_ARRAY_ALL)) { /* only array properties can have array options */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; } switch (wp_data->object_property) { case PROP_PRIORITY: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, &wp_data->error_class, &wp_data->error_code); if (status) { if (wp_data->array_index == 0) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_ARRAY_INDEX; } else if (wp_data->array_index == BACNET_ARRAY_ALL) { /* FIXME: wite all array */ } else if (wp_data->array_index <= 3) { CurrentNotify->Priority[wp_data->array_index - 1] = value.type.Unsigned_Int; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_ARRAY_INDEX; } } break; case PROP_ACK_REQUIRED: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BIT_STRING, &wp_data->error_class, &wp_data->error_code); if (status) { if (value.type.Bit_String.bits_used == 3) { CurrentNotify->Ack_Required = value.type.Bit_String.value[0]; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } break; case PROP_RECIPIENT_LIST: memset(&TmpNotify, 0x00, sizeof(NOTIFICATION_CLASS_INFO)); /* decode all packed */ while (iOffset < wp_data->application_data_len) { /* Decode Valid Days */ len = bacapp_decode_application_data(&wp_data-> application_data[iOffset], wp_data->application_data_len, &value); if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_BIT_STRING)) { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } if (value.type.Bit_String.bits_used == MAX_BACNET_DAYS_OF_WEEK) /* store value */ TmpNotify.Recipient_List[idx].ValidDays = value.type.Bit_String.value[0]; else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_OTHER; return false; } iOffset += len; /* Decode From Time */ len = bacapp_decode_application_data(&wp_data-> application_data[iOffset], wp_data->application_data_len, &value); if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_TIME)) { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } /* store value */ TmpNotify.Recipient_List[idx].FromTime = value.type.Time; iOffset += len; /* Decode To Time */ len = bacapp_decode_application_data(&wp_data-> application_data[iOffset], wp_data->application_data_len, &value); if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_TIME)) { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } /* store value */ TmpNotify.Recipient_List[idx].ToTime = value.type.Time; iOffset += len; /* context tag [0] - Device */ if (decode_is_context_tag(&wp_data->application_data[iOffset], 0)) { TmpNotify.Recipient_List[idx].Recipient.RecipientType = RECIPIENT_TYPE_DEVICE; /* Decode Network Number */ len = bacapp_decode_context_data(&wp_data-> application_data[iOffset], wp_data->application_data_len, &value, PROP_RECIPIENT_LIST); if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_OBJECT_ID)) { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } /* store value */ TmpNotify.Recipient_List[idx].Recipient._. DeviceIdentifier = value.type.Object_Id.instance; iOffset += len; } /* opening tag [1] - Recipient */ else if (decode_is_opening_tag_number(&wp_data-> application_data[iOffset], 1)) { iOffset++; TmpNotify.Recipient_List[idx].Recipient.RecipientType = RECIPIENT_TYPE_ADDRESS; /* Decode Network Number */ len = bacapp_decode_application_data(&wp_data-> application_data[iOffset], wp_data->application_data_len, &value); if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_UNSIGNED_INT)) { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } /* store value */ TmpNotify.Recipient_List[idx].Recipient._.Address.net = value.type.Unsigned_Int; iOffset += len; /* Decode Address */ len = bacapp_decode_application_data(&wp_data-> application_data[iOffset], wp_data->application_data_len, &value); if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_OCTET_STRING)) { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } /* store value */ if (TmpNotify.Recipient_List[idx].Recipient._.Address. net == 0) { memcpy(TmpNotify.Recipient_List[idx].Recipient._. Address.mac, value.type.Octet_String.value, value.type.Octet_String.length); TmpNotify.Recipient_List[idx].Recipient._.Address. mac_len = value.type.Octet_String.length; } else { memcpy(TmpNotify.Recipient_List[idx].Recipient._. Address.adr, value.type.Octet_String.value, value.type.Octet_String.length); TmpNotify.Recipient_List[idx].Recipient._.Address.len = value.type.Octet_String.length; } iOffset += len; /* closing tag [1] - Recipient */ if (decode_is_closing_tag_number(&wp_data-> application_data[iOffset], 1)) iOffset++; else { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } } else { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } /* Process Identifier */ len = bacapp_decode_application_data(&wp_data-> application_data[iOffset], wp_data->application_data_len, &value); if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_UNSIGNED_INT)) { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } /* store value */ TmpNotify.Recipient_List[idx].ProcessIdentifier = value.type.Unsigned_Int; iOffset += len; /* Issue Confirmed Notifications */ len = bacapp_decode_application_data(&wp_data-> application_data[iOffset], wp_data->application_data_len, &value); if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_BOOLEAN)) { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } /* store value */ TmpNotify.Recipient_List[idx].ConfirmedNotify = value.type.Boolean; iOffset += len; /* Transitions */ len = bacapp_decode_application_data(&wp_data-> application_data[iOffset], wp_data->application_data_len, &value); if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_BIT_STRING)) { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } if (value.type.Bit_String.bits_used == MAX_BACNET_EVENT_TRANSITION) /* store value */ TmpNotify.Recipient_List[idx].Transitions = value.type.Bit_String.value[0]; else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_OTHER; return false; } iOffset += len; /* Increasing element of list */ if (++idx >= NC_MAX_RECIPIENTS) { wp_data->error_class = ERROR_CLASS_RESOURCES; wp_data->error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY; return false; } } /* Decoded all recipient list */ /* copy elements from temporary object */ for (idx = 0; idx < NC_MAX_RECIPIENTS; idx++) { BACNET_ADDRESS src = { 0 }; unsigned max_apdu = 0; int32_t DeviceID; CurrentNotify->Recipient_List[idx] = TmpNotify.Recipient_List[idx]; if (CurrentNotify->Recipient_List[idx].Recipient. RecipientType == RECIPIENT_TYPE_DEVICE) { /* copy Device_ID */ DeviceID = CurrentNotify->Recipient_List[idx].Recipient._. DeviceIdentifier; address_bind_request(DeviceID, &max_apdu, &src); } else if (CurrentNotify->Recipient_List[idx].Recipient. RecipientType == RECIPIENT_TYPE_ADDRESS) { /* copy Address */ /* src = CurrentNotify->Recipient_List[idx].Recipient._.Address; */ /* address_bind_request(BACNET_MAX_INSTANCE, &max_apdu, &src); */ } } status = true; break; default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; break; } return status; }
int bacapp_decode_access_rule( uint8_t * apdu, BACNET_ACCESS_RULE * rule) { int len; int apdu_len = 0; if (decode_is_context_tag(&apdu[apdu_len], 0)) { len = decode_context_enumerated(&apdu[apdu_len], 0, &rule->time_range_specifier); if (len < 0) return -1; else apdu_len += len; } else return -1; if (rule->time_range_specifier == TIME_RANGE_SPECIFIER_SPECIFIED) { if (decode_is_context_tag(&apdu[apdu_len], 1)) { len = bacapp_decode_context_device_obj_property_ref(&apdu[apdu_len], 1, &rule->time_range); if (len < 0) return -1; else apdu_len += len; } else return -1; } if (decode_is_context_tag(&apdu[apdu_len], 2)) { len = decode_context_enumerated(&apdu[apdu_len], 2, &rule->location_specifier); if (len < 0) return -1; else apdu_len += len; } else return -1; if (rule->location_specifier == LOCATION_SPECIFIER_SPECIFIED) { if (decode_is_context_tag(&apdu[apdu_len], 3)) { len = bacapp_decode_context_device_obj_property_ref(&apdu[apdu_len], 3, &rule->location); if (len < 0) return -1; else apdu_len += len; } else return -1; } if (decode_is_context_tag(&apdu[apdu_len], 4)) { len = decode_context_boolean2(&apdu[apdu_len], 4, &rule->enable); if (len < 0) return -1; else apdu_len += len; } else return -1; return apdu_len; }
/* FIXME: there could be various error messages returned using unique values less than zero */ int wp_decode_service_request( uint8_t * apdu, unsigned apdu_len, BACNET_WRITE_PROPERTY_DATA * wpdata) { int len = 0; int tag_len = 0; uint8_t tag_number = 0; uint32_t len_value_type = 0; uint16_t type = 0; /* for decoding */ uint32_t property = 0; /* for decoding */ uint32_t unsigned_value = 0; int i = 0; /* loop counter */ /* check for value pointers */ if (apdu_len && wpdata) { /* Tag 0: Object ID */ if (!decode_is_context_tag(&apdu[len++], 0)) return -1; len += decode_object_id(&apdu[len], &type, &wpdata->object_instance); wpdata->object_type = (BACNET_OBJECT_TYPE) type; /* Tag 1: Property ID */ len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); if (tag_number != 1) return -1; len += decode_enumerated(&apdu[len], len_value_type, &property); wpdata->object_property = (BACNET_PROPERTY_ID) property; /* Tag 2: Optional Array Index */ /* note: decode without incrementing len so we can check for opening tag */ tag_len = decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); if (tag_number == 2) { len += tag_len; len += decode_unsigned(&apdu[len], len_value_type, &unsigned_value); wpdata->array_index = unsigned_value; } else wpdata->array_index = BACNET_ARRAY_ALL; /* Tag 3: opening context tag */ if (!decode_is_opening_tag_number(&apdu[len], 3)) return -1; /* determine the length of the data blob */ wpdata->application_data_len = bacapp_data_len(&apdu[len], apdu_len - len, (BACNET_PROPERTY_ID) property); /* a tag number of 3 is not extended so only one octet */ len++; /* copy the data from the APDU */ for (i = 0; i < wpdata->application_data_len; i++) { wpdata->application_data[i] = apdu[len + i]; } /* add on the data length */ len += wpdata->application_data_len; if (!decode_is_closing_tag_number(&apdu[len], 3)) return -2; /* a tag number of 3 is not extended so only one octet */ len++; /* Tag 4: optional Priority - assumed MAX if not explicitly set */ wpdata->priority = BACNET_MAX_PRIORITY; if ((unsigned) len < apdu_len) { tag_len = decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); if (tag_number == 4) { len += tag_len; len = decode_unsigned(&apdu[len], len_value_type, &unsigned_value); if ((unsigned_value >= BACNET_MIN_PRIORITY) && (unsigned_value <= BACNET_MAX_PRIORITY)) { wpdata->priority = (uint8_t) unsigned_value; } else return -5; } } } return len; }