From 585b0bae5be83bc6aa2e9bb0e523cd50549877e4 Mon Sep 17 00:00:00 2001 From: skarg Date: Thu, 31 Jan 2019 14:51:46 +0000 Subject: [PATCH] Add common functions for initializing the BACnet Application Value lists. Fixes problems with receiving Unconfirmed COV Notifications with more values to store than the stack has reserved in its value list. --- bacnet-stack/demo/handler/h_ccov.c | 12 +------ bacnet-stack/demo/handler/h_cov.c | 10 ++++-- bacnet-stack/demo/handler/h_ucov.c | 12 +------ bacnet-stack/include/bacapp.h | 8 +++++ bacnet-stack/src/bacapp.c | 55 ++++++++++++++++++++++++++++++ 5 files changed, 72 insertions(+), 25 deletions(-) diff --git a/bacnet-stack/demo/handler/h_ccov.c b/bacnet-stack/demo/handler/h_ccov.c index 1f1d33cf..d7ca09f4 100644 --- a/bacnet-stack/demo/handler/h_ccov.c +++ b/bacnet-stack/demo/handler/h_ccov.c @@ -69,7 +69,6 @@ void handler_ccov_notification( BACNET_COV_DATA cov_data; BACNET_PROPERTY_VALUE property_value[MAX_COV_PROPERTIES]; BACNET_PROPERTY_VALUE *pProperty_value = NULL; - unsigned index = 0; int len = 0; int pdu_len = 0; int bytes_sent = 0; @@ -77,16 +76,7 @@ void handler_ccov_notification( /* create linked list to store data if more than one property value is expected */ - pProperty_value = &property_value[0]; - while (pProperty_value) { - index++; - if (index < MAX_COV_PROPERTIES) { - pProperty_value->next = &property_value[index]; - } else { - pProperty_value->next = NULL; - } - pProperty_value = pProperty_value->next; - } + bacapp_property_value_list_init(&property_value[0], MAX_COV_PROPERTIES); cov_data.listOfValues = &property_value[0]; /* encode the NPDU portion of the packet */ datalink_get_my_address(&my_address); diff --git a/bacnet-stack/demo/handler/h_cov.c b/bacnet-stack/demo/handler/h_cov.c index d46bb36d..48346a19 100644 --- a/bacnet-stack/demo/handler/h_cov.c +++ b/bacnet-stack/demo/handler/h_cov.c @@ -47,6 +47,10 @@ #include "device.h" #include "handlers.h" +#ifndef MAX_COV_PROPERTIES +#define MAX_COV_PROPERTIES 2 +#endif + /** @file h_cov.c Handles Change of Value (COV) services. */ typedef struct BACnet_COV_Address { @@ -616,7 +620,7 @@ bool handler_cov_fsm( uint32_t object_instance = 0; bool status = false; bool send = false; - BACNET_PROPERTY_VALUE value_list[2]; + BACNET_PROPERTY_VALUE value_list[MAX_COV_PROPERTIES]; /* states for transmitting */ static enum { COV_STATE_IDLE = 0, @@ -716,8 +720,8 @@ bool handler_cov_fsm( fprintf(stderr, "COVtask: Sending...\n"); #endif /* configure the linked list for the two properties */ - value_list[0].next = &value_list[1]; - value_list[1].next = NULL; + bacapp_property_value_list_init(&value_list[0], + MAX_COV_PROPERTIES); status = Device_Encode_Value_List(object_type, object_instance, &value_list[0]); if (status) { diff --git a/bacnet-stack/demo/handler/h_ucov.c b/bacnet-stack/demo/handler/h_ucov.c index f5c198e0..9515f074 100644 --- a/bacnet-stack/demo/handler/h_ucov.c +++ b/bacnet-stack/demo/handler/h_ucov.c @@ -66,22 +66,12 @@ void handler_ucov_notification( BACNET_PROPERTY_VALUE property_value[MAX_COV_PROPERTIES]; BACNET_PROPERTY_VALUE *pProperty_value = NULL; int len = 0; - unsigned index = 0; /* src not needed for this application */ src = src; /* create linked list to store data if more than one property value is expected */ - pProperty_value = &property_value[0]; - while (pProperty_value) { - index++; - if (index < MAX_COV_PROPERTIES) { - pProperty_value->next = &property_value[index]; - } else { - pProperty_value->next = NULL; - } - pProperty_value = pProperty_value->next; - } + bacapp_property_value_list_init(&property_value[0], MAX_COV_PROPERTIES); cov_data.listOfValues = &property_value[0]; #if PRINT_ENABLED fprintf(stderr, "UCOV: Received Notification!\n"); diff --git a/bacnet-stack/include/bacapp.h b/bacnet-stack/include/bacapp.h index f8342d38..cad7456b 100644 --- a/bacnet-stack/include/bacapp.h +++ b/bacnet-stack/include/bacapp.h @@ -134,6 +134,14 @@ typedef struct BACnet_Object_Property_Value { #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ + + void bacapp_value_list_init( + BACNET_APPLICATION_DATA_VALUE *value, + size_t count); + void bacapp_property_value_list_init( + BACNET_PROPERTY_VALUE *value, + size_t count); + int bacapp_encode_data( uint8_t * apdu, BACNET_APPLICATION_DATA_VALUE * value); diff --git a/bacnet-stack/src/bacapp.c b/bacnet-stack/src/bacapp.c index 54e51cd1..16e1222d 100644 --- a/bacnet-stack/src/bacapp.c +++ b/bacnet-stack/src/bacapp.c @@ -1555,6 +1555,61 @@ bool bacapp_parse_application_data( } #endif +/** + * Initialize an array (or single) #BACNET_APPLICATION_DATA_VALUE + * + * @param value - one or more #BACNET_APPLICATION_DATA_VALUE elements + * @param count - number of #BACNET_APPLICATION_DATA_VALUE elements + */ +void bacapp_value_list_init( + BACNET_APPLICATION_DATA_VALUE *value, + size_t count) +{ + size_t i = 0; + + if (value && count) { + for (i = 0; i < count; i++) { + value->tag = BACNET_APPLICATION_TAG_NULL; + value->context_specific = 0; + value->context_tag = 0; + if ((i+1) < count) { + value->next = value + 1; + } else { + value->next = NULL; + } + value++; + } + } +} + +/** + * Initialize an array (or single) #BACNET_PROPERTY_VALUE + * + * @param value - one or more #BACNET_PROPERTY_VALUE elements + * @param count - number of #BACNET_PROPERTY_VALUE elements + */ +void bacapp_property_value_list_init( + BACNET_PROPERTY_VALUE *value, + size_t count) +{ + size_t i = 0; + + if (value && count) { + for (i = 0; i < count; i++) { + value->propertyIdentifier = MAX_BACNET_PROPERTY_ID; + value->propertyArrayIndex = BACNET_ARRAY_ALL; + value->priority = BACNET_NO_PRIORITY; + bacapp_value_list_init(&value->value, 1); + if ((i+1) < count) { + value->next = value + 1; + } else { + value->next = NULL; + } + value++; + } + } +} + #ifdef TEST #include #include