From a38cc531d23aac440ae282e5da5dd1a0d3e58386 Mon Sep 17 00:00:00 2001 From: Steve Karg Date: Tue, 29 Oct 2024 13:17:39 -0500 Subject: [PATCH] Added WriteProperty setter for BACnet Unsigned Integer values. (#834) --- src/bacnet/wp.c | 38 ++++++++++++++++++++++++++++++++++++++ src/bacnet/wp.h | 16 ++++++++++++++++ test/bacnet/wp/src/main.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/src/bacnet/wp.c b/src/bacnet/wp.c index 79c083ea..b8756d90 100644 --- a/src/bacnet/wp.c +++ b/src/bacnet/wp.c @@ -425,3 +425,41 @@ bool write_property_empty_string_valid( return (valid); } + +/** + * @brief Helper to decode a WriteProperty unsigned integer and set a property + * @param wp_data - #BACNET_WRITE_PROPERTY_DATA data including any + * error response. + * @param value - #BACNET_APPLICATION_DATA_VALUE data + * @param setter - function to set the property + * @param maximum - maximum value allowed for the property + * @return true if the value was decoded and set, else false + */ +bool write_property_unsigned_decode( + BACNET_WRITE_PROPERTY_DATA *wp_data, + BACNET_APPLICATION_DATA_VALUE *value, + bacnet_property_unsigned_setter setter, + BACNET_UNSIGNED_INTEGER maximum) +{ + bool status = write_property_type_valid( + wp_data, value, BACNET_APPLICATION_TAG_UNSIGNED_INT); + if (status) { + if (value->type.Unsigned_Int <= maximum) { + status = + (setter)(wp_data->object_instance, value->type.Unsigned_Int); + if (status) { + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_SUCCESS; + } else { + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + } + } else { + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + status = false; + } + } + + return status; +} diff --git a/src/bacnet/wp.h b/src/bacnet/wp.h index 6850e628..c287dc5c 100644 --- a/src/bacnet/wp.h +++ b/src/bacnet/wp.h @@ -46,6 +46,15 @@ typedef struct BACnet_Write_Property_Data { */ typedef bool (*write_property_function)(BACNET_WRITE_PROPERTY_DATA *wp_data); +/** + * @brief API for setting a BACnet Unsigned Integer property value + * @param object_instance [in] Object instance number + * @param value [in] New value to set + * @return true if successful, else false + */ +typedef bool (*bacnet_property_unsigned_setter)( + uint32_t object_instance, BACNET_UNSIGNED_INTEGER value); + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -86,6 +95,13 @@ bool write_property_empty_string_valid( const BACNET_APPLICATION_DATA_VALUE *value, size_t len_max); +BACNET_STACK_EXPORT +bool write_property_unsigned_decode( + BACNET_WRITE_PROPERTY_DATA *wp_data, + BACNET_APPLICATION_DATA_VALUE *value, + bacnet_property_unsigned_setter setter, + BACNET_UNSIGNED_INTEGER maximum); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/test/bacnet/wp/src/main.c b/test/bacnet/wp/src/main.c index 2a22d352..45dcb6f1 100644 --- a/test/bacnet/wp/src/main.c +++ b/test/bacnet/wp/src/main.c @@ -63,11 +63,28 @@ static int wp_decode_apdu( return apdu_len; } +static BACNET_UNSIGNED_INTEGER Test_Unsigned_Value; +static uint32_t Test_Object_Instance; +/** + * @brief API for setting a BACnet Unsigned Integer property value + * @param object_instance [in] Object instance number + * @param value [in] New value to set + * @return true if successful, else false + */ +static bool test_bacnet_property_unsigned_set( + uint32_t object_instance, BACNET_UNSIGNED_INTEGER value) +{ + Test_Object_Instance = object_instance; + Test_Unsigned_Value = value; + return true; +} + static void testWritePropertyTag(const BACNET_APPLICATION_DATA_VALUE *value) { BACNET_WRITE_PROPERTY_DATA wpdata = { 0 }; BACNET_WRITE_PROPERTY_DATA test_data = { 0 }; BACNET_APPLICATION_DATA_VALUE test_value = { 0 }; + BACNET_UNSIGNED_INTEGER test_unsigned_value_max = 0; uint8_t apdu[480] = { 0 }; int len = 0; int null_len = 0; @@ -125,6 +142,21 @@ static void testWritePropertyTag(const BACNET_APPLICATION_DATA_VALUE *value) case BACNET_APPLICATION_TAG_UNSIGNED_INT: zassert_equal( test_value.type.Unsigned_Int, value->type.Unsigned_Int, NULL); + test_unsigned_value_max = test_value.type.Unsigned_Int; + status = write_property_unsigned_decode( + &test_data, &test_value, test_bacnet_property_unsigned_set, + test_unsigned_value_max); + zassert_equal(status, true, NULL); + zassert_equal( + Test_Object_Instance, test_data.object_instance, NULL); + zassert_equal(Test_Unsigned_Value, value->type.Unsigned_Int, NULL); + if (test_value.type.Unsigned_Int != 0) { + test_unsigned_value_max = 0; + status = write_property_unsigned_decode( + &test_data, &test_value, test_bacnet_property_unsigned_set, + test_unsigned_value_max); + zassert_equal(status, false, NULL); + } break; case BACNET_APPLICATION_TAG_SIGNED_INT: zassert_equal( @@ -252,6 +284,7 @@ static void testWriteProperty(void) value.type.Object_Id.instance = BACNET_MAX_INSTANCE; testWritePropertyTag(&value); } + /** * @} */