Bugfix/read property multiple client errors (#765)

* Fixed variable data type for boolean in RPM structure.

* Fixed RPM error handling to use callback.

* Fixed bacrpm app example when not enough command line parameters are used

* Fixed empty-list EPICS printing.

* Fixed RPM-Ack processing for end of list-of-results

* Added minimal handling for segmentation-not-supported during RPM of object properties.
This commit is contained in:
Steve Karg
2024-09-21 09:26:09 -05:00
committed by GitHub
parent 869a827d55
commit 3d86873346
6 changed files with 133 additions and 31 deletions
+39 -9
View File
@@ -677,16 +677,20 @@ static void bacnet_device_object_property_add(
/**
* @brief Handle the error from a ReadProperty or ReadPropertyMultiple
* @param device_id - device instance number where data originated
* @param error_code - BACnet Error code
* @param rp_data - ReadProperty data structure
* @param device_data - Pointer to the device data structure
*/
static void Device_Error_Handler(
uint32_t device_id,
BACNET_ERROR_CODE error_code,
BACNET_READ_PROPERTY_DATA *rp_data,
BACNET_DEVICE_DATA *device_data)
{
bool status = false;
if (device_data) {
debug_printf(
"%u - %s\n", device_id, bactext_error_code_name((int)error_code));
"%u - %s\n", device_id,
bactext_error_code_name((int)rp_data->error_code));
switch (device_data->Discovery_State) {
case BACNET_DISCOVER_STATE_OBJECT_LIST_REQUEST:
/* resend request */
@@ -697,12 +701,38 @@ static void Device_Error_Handler(
BACNET_DISCOVER_STATE_OBJECT_LIST_RESPONSE;
break;
case BACNET_DISCOVER_STATE_OBJECT_GET_PROPERTY_REQUEST:
/* resend request */
if (device_data->Object_List_Index != 0) {
device_data->Object_List_Index--;
if (rp_data->error_code == ERROR_CODE_TIMEOUT) {
/* resend request */
if (device_data->Object_List_Index != 0) {
device_data->Object_List_Index--;
}
device_data->Discovery_State =
BACNET_DISCOVER_STATE_OBJECT_GET_PROPERTY_RESPONSE;
} else if (
(rp_data->error_code ==
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED) &&
(rp_data->object_property == PROP_ALL)) {
/* fallback to ReadProperty required properties */
/* FIXME: fill a property-list with properties
and use FSM to ReadProperty of each.
For now, read the object-name property */
status = bacnet_read_property_queue(
device_id, rp_data->object_type,
rp_data->object_instance, PROP_OBJECT_NAME,
BACNET_ARRAY_ALL);
if (status) {
device_data->Discovery_State =
BACNET_DISCOVER_STATE_OBJECT_GET_PROPERTY_REQUEST;
} else {
/* skip */
device_data->Discovery_State =
BACNET_DISCOVER_STATE_OBJECT_GET_PROPERTY_RESPONSE;
}
} else {
/* skip */
device_data->Discovery_State =
BACNET_DISCOVER_STATE_OBJECT_GET_PROPERTY_RESPONSE;
}
device_data->Discovery_State =
BACNET_DISCOVER_STATE_OBJECT_GET_PROPERTY_RESPONSE;
break;
default:
break;
@@ -733,7 +763,7 @@ static void bacnet_read_property_reply(
return;
}
if (rp_data->error_code != ERROR_CODE_SUCCESS) {
Device_Error_Handler(device_id, rp_data->error_code, device_data);
Device_Error_Handler(device_id, rp_data, device_data);
} else if (value) {
bacnet_device_object_property_add(
device_id, rp_data, value, device_data);
+20 -2
View File
@@ -211,15 +211,29 @@ static void bacnet_read_property_ack_process(
BACNET_ARRAY_INDEX array_index = 0;
if (rp_data) {
value = &Target_Decoded_Property_Value;
/* check for property error */
if (rp_data->error_code != ERROR_CODE_SUCCESS) {
if (bacnet_read_write_value_callback) {
bacnet_read_write_value_callback(device_id, rp_data, NULL);
}
return;
}
/* check for empty list */
if (rp_data->application_data_len == 0) {
bacapp_value_list_init(value, 1);
value->tag = BACNET_APPLICATION_TAG_EMPTYLIST;
rp_data->error_class = ERROR_CLASS_SERVICES;
rp_data->error_code = ERROR_CODE_SUCCESS;
if (bacnet_read_write_value_callback) {
bacnet_read_write_value_callback(device_id, rp_data, value);
}
return;
}
apdu = rp_data->application_data;
apdu_len = rp_data->application_data_len;
while (apdu_len) {
value = &Target_Decoded_Property_Value;
bacapp_value_list_init(value, 1);
len = bacapp_decode_known_property(
apdu, (unsigned)apdu_len, value, rp_data->object_type,
rp_data->object_property);
@@ -251,7 +265,11 @@ static void bacnet_read_property_ack_process(
}
} else {
rp_data->error_class = ERROR_CLASS_SERVICES;
rp_data->error_code = ERROR_CODE_SUCCESS;
if (len < 0) {
rp_data->error_code = ERROR_CODE_OTHER;
} else {
rp_data->error_code = ERROR_CODE_SUCCESS;
}
if (bacnet_read_write_value_callback) {
bacnet_read_write_value_callback(device_id, rp_data, NULL);
}
+6 -5
View File
@@ -103,18 +103,19 @@ int rpm_ack_decode_service_request(
decoded_len++;
apdu_len--;
apdu++;
/* note: if this is an array, there will be
more than one element to decode */
value = calloc(1, sizeof(BACNET_APPLICATION_DATA_VALUE));
rpm_property->value = value;
/* Special case for an empty array - we decode it as null */
if (apdu_len && decode_is_closing_tag_number(apdu, 4)) {
bacapp_value_list_init(value, 1);
/* Special case for an empty array or list */
if (value) {
bacapp_value_list_init(value, 1);
value->tag = BACNET_APPLICATION_TAG_EMPTYLIST;
}
decoded_len++;
apdu_len--;
apdu++;
} else {
/* one or more (array or list) elements to decode */
while (value && (apdu_len > 0)) {
len = bacapp_decode_known_property(
apdu, (unsigned)apdu_len, value,