Feature/writepropertymultiple error handler (#289)

* Added extended BACnet Error PDU handling for WPM

* Added BACnetObjectPropertyReference to bacapp module.

* Added unit testing for BACnetObjectPropertyReference

Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
Steve Karg
2022-06-03 15:47:30 -05:00
committed by GitHub
parent f147283293
commit 6a8adcce3d
14 changed files with 642 additions and 88 deletions
+136
View File
@@ -29,6 +29,7 @@
#include "bacnet/bacenum.h"
#include "bacnet/bacdcode.h"
#include "bacnet/bacdef.h"
#include "bacnet/bacerror.h"
#include "bacnet/wp.h"
#include "bacnet/wpm.h"
@@ -435,3 +436,138 @@ int wpm_error_ack_encode_apdu(
}
return len;
}
/** Decoding for WritePropertyMultiple Error
* @ingroup DSWPM
* WritePropertyMultiple-Error ::= SEQUENCE {
* error-type [0] Error,
* first-failed-write-attempt [1] BACnetObjectPropertyReference
* }
*
* @param apdu [in] The contents of the APDU buffer.
* @param apdu_size [in] The size of the APDU buffer.
* @param wp_data [out] The BACNET_WRITE_PROPERTY_DATA structure
* which will contain the response values or error.
*
* @return Count of decoded bytes.
*/
int wpm_error_ack_decode_apdu(
uint8_t *apdu, uint16_t apdu_size, BACNET_WRITE_PROPERTY_DATA *wp_data)
{
int len = 0, apdu_len = 0;
uint8_t *apdu_offset = NULL;
BACNET_ERROR_CLASS error_class = ERROR_CLASS_SERVICES;
BACNET_ERROR_CODE error_code = ERROR_CODE_SUCCESS;
BACNET_OBJECT_PROPERTY_REFERENCE value;
if (apdu) {
apdu_offset = apdu;
}
if (wp_data) {
wp_data->error_class = ERROR_CLASS_SERVICES;
wp_data->error_code = ERROR_CODE_REJECT_PARAMETER_OUT_OF_RANGE;
}
/* Context tag 0 - Error */
if (apdu_size == 0) {
return 0;
}
if (decode_is_opening_tag_number(apdu_offset, 0)) {
len = 1;
apdu_len -= len;
if (apdu) {
apdu_offset = &apdu[apdu_len];
if (apdu_size > len) {
apdu_size -= len;
} else {
return 0;
}
}
} else {
return 0;
}
len = bacerror_decode_error_class_and_code(apdu_offset, apdu_size,
&error_class, &error_code);
if (len > 0) {
if (wp_data) {
wp_data->error_class = error_class;
wp_data->error_code = error_code;
}
apdu_len += len;
if (apdu) {
apdu_offset = &apdu[apdu_len];
if (apdu_size > len) {
apdu_size -= len;
} else {
return 0;
}
}
} else {
return 0;
}
if (apdu_size == 0) {
return 0;
}
if (decode_is_closing_tag_number(apdu_offset, 0)) {
len = 1;
apdu_len -= len;
if (apdu) {
apdu_offset = &apdu[apdu_len];
if (apdu_size > len) {
apdu_size -= len;
} else {
return 0;
}
}
} else {
return 0;
}
/* Context tag 1 - BACnetObjectPropertyReference */
if (apdu_size == 0) {
return 0;
}
if (decode_is_opening_tag_number(apdu_offset, 1)) {
len = 1;
apdu_len -= len;
if (apdu) {
apdu_offset = &apdu[apdu_len];
if (apdu_size > len) {
apdu_size -= len;
} else {
return 0;
}
}
} else {
return 0;
}
len = bacapp_decode_obj_property_ref(apdu_offset, apdu_size, &value);
if (len > 0) {
if (wp_data) {
wp_data->object_instance = value.object_identifier.instance;
wp_data->object_type = value.object_identifier.type;
wp_data->object_property = value.property_identifier;
wp_data->array_index = value.property_array_index;
}
apdu_len += len;
if (apdu) {
apdu_offset = &apdu[apdu_len];
if (apdu_size > len) {
apdu_size -= len;
} else {
return 0;
}
}
} else {
return 0;
}
if (apdu_size == 0) {
return 0;
}
if (decode_is_closing_tag_number(apdu_offset, 1)) {
len = 1;
apdu_len += len;
} else {
return 0;
}
return apdu_len;
}