From d1f92cbb8f52d86c2b35903826d0645185c065a8 Mon Sep 17 00:00:00 2001 From: Steve Karg Date: Thu, 4 Apr 2024 11:33:54 -0500 Subject: [PATCH] Change time-value object present-value to not report current time. Added out-of-service property to WriteProperty. --- src/bacnet/basic/object/time_value.c | 101 +++++++++++++++------------ 1 file changed, 56 insertions(+), 45 deletions(-) diff --git a/src/bacnet/basic/object/time_value.c b/src/bacnet/basic/object/time_value.c index 7445e89a..07477029 100644 --- a/src/bacnet/basic/object/time_value.c +++ b/src/bacnet/basic/object/time_value.c @@ -3,13 +3,9 @@ * @author Steve Karg * @author Mikhail Antropov * @date June 2023 - * @brief Time Value objects used by a BACnet device object - * - * @section DESCRIPTION - * - * The Time Value object is an object with a present-value that + * @brief Time Value object is an object with a present-value that * uses an bacnet time data type. -* + * * @section LICENSE * * SPDX-License-Identifier: MIT @@ -52,7 +48,8 @@ struct object_data { /* Key List for storing the object data sorted by instance number */ static OS_Keylist Object_List; /* callback for present value writes */ -static time_value_write_present_value_callback Time_Value_Write_Present_Value_Callback; +static time_value_write_present_value_callback + Time_Value_Write_Present_Value_Callback; /* These three arrays are used by the ReadPropertyMultiple handler */ static const int Time_Value_Properties_Required[] = { PROP_OBJECT_IDENTIFIER, @@ -66,9 +63,8 @@ static const int Time_Value_Properties_Proprietary[] = { -1 }; /* standard properties that are arrays for this object, but not necessary supported in this object */ -static const int BACnetARRAY_Properties[] = { - PROP_EVENT_TIME_STAMPS, PROP_EVENT_MESSAGE_TEXTS, - PROP_EVENT_MESSAGE_TEXTS_CONFIG, +static const int BACnetARRAY_Properties[] = { PROP_EVENT_TIME_STAMPS, + PROP_EVENT_MESSAGE_TEXTS, PROP_EVENT_MESSAGE_TEXTS_CONFIG, PROP_VALUE_SOURCE_ARRAY, PROP_COMMAND_TIME_ARRAY, PROP_TAGS, -1 }; /** @@ -169,21 +165,31 @@ bool Time_Value_Present_Value(uint32_t object_instance, BACNET_TIME *value) { bool status = false; struct object_data *pObject; - BACNET_DATE date; pObject = Keylist_Data(Object_List, object_instance); if (pObject) { - if (pObject->Out_Of_Service) { - datetime_copy_time(value, &pObject->Present_Value); - status = true; - } else { - status = datetime_local(&date, value, NULL, NULL); - } + datetime_copy_time(value, &pObject->Present_Value); + status = true; } return status; } +/** + * @brief For a given object instance-number, checks the present-value for COV + * @param pObject - specific object with valid data + * @param value - floating point analog value + */ +static void Time_Value_Present_Value_COV_Detect( + struct object_data *pObject, BACNET_TIME *value) +{ + if (pObject && value) { + if (datetime_compare_time(&pObject->Present_Value, value) != 0) { + pObject->Change_Of_Value = true; + } + } +} + /** * For a given object instance-number, sets the present-value * @@ -199,11 +205,13 @@ bool Time_Value_Present_Value_Set(uint32_t object_instance, BACNET_TIME *value) pObject = Keylist_Data(Object_List, object_instance); if (pObject) { - if (datetime_compare_time(&pObject->Present_Value, value) != 0) { - pObject->Change_Of_Value = true; - datetime_copy_time(&pObject->Present_Value, value); + if (!pObject->Out_Of_Service) { + if (value) { + Time_Value_Present_Value_COV_Detect(pObject, value); + datetime_copy_time(&pObject->Present_Value, value); + status = true; + } } - status = true; } return status; @@ -228,17 +236,15 @@ static bool Time_Value_Present_Value_Write(uint32_t object_instance, { bool status = false; struct object_data *pObject; - BACNET_TIME old_value = {0}; + BACNET_TIME old_value = { 0 }; pObject = Keylist_Data(Object_List, object_instance); if (pObject) { (void)priority; if (pObject->Write_Enabled) { datetime_copy_time(&old_value, &pObject->Present_Value); - if (datetime_compare_time(&pObject->Present_Value, value) != 0) { - pObject->Change_Of_Value = true; - datetime_copy_time(&pObject->Present_Value, value); - } + Time_Value_Present_Value_COV_Detect(pObject, value); + datetime_copy_time(&pObject->Present_Value, value); if (Time_Value_Write_Present_Value_Callback) { Time_Value_Write_Present_Value_Callback( object_instance, &old_value, value); @@ -403,14 +409,11 @@ bool Time_Value_Description_Set(uint32_t object_instance, char *new_name) * @param object_property - object-property to be checked * @return true if the property is a BACnetARRAY property */ -static bool BACnetARRAY_Property( - int object_property) +static bool BACnetARRAY_Property(int object_property) { - return property_list_member( - BACnetARRAY_Properties, object_property); + return property_list_member(BACnetARRAY_Properties, object_property); } - bool Time_Value_Change_Of_Value(uint32_t object_instance) { bool status = false; @@ -543,8 +546,8 @@ int Time_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata) apdu_len = encode_application_bitstring(&apdu[0], &bit_string); break; case PROP_OUT_OF_SERVICE: - apdu_len = encode_application_boolean(&apdu[0], - Time_Value_Out_Of_Service(rpdata->object_instance)); + apdu_len = encode_application_boolean( + &apdu[0], Time_Value_Out_Of_Service(rpdata->object_instance)); break; case PROP_DESCRIPTION: characterstring_init_ansi( @@ -562,8 +565,7 @@ int Time_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata) break; } /* only array properties can have array options */ - if ((apdu_len >= 0) && - (!BACnetARRAY_Property(rpdata->object_property)) && + if ((apdu_len >= 0) && (!BACnetARRAY_Property(rpdata->object_property)) && (rpdata->array_index != BACNET_ARRAY_ALL)) { rpdata->error_class = ERROR_CLASS_PROPERTY; rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; @@ -608,23 +610,32 @@ bool Time_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) switch (wp_data->object_property) { case PROP_PRESENT_VALUE: if (Time_Value_Out_Of_Service(wp_data->object_instance)) { - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_TIME); + status = write_property_type_valid( + wp_data, &value, BACNET_APPLICATION_TAG_TIME); if (status) { - status = Time_Value_Present_Value_Write( - wp_data->object_instance, - &value.type.Time, wp_data->priority, - &wp_data->error_class, &wp_data->error_code); + status = + Time_Value_Present_Value_Write(wp_data->object_instance, + &value.type.Time, wp_data->priority, + &wp_data->error_class, &wp_data->error_code); } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } break; + case PROP_OUT_OF_SERVICE: + status = write_property_type_valid( + wp_data, &value, BACNET_APPLICATION_TAG_BOOLEAN); + if (status) { + Time_Value_Out_Of_Service_Set( + wp_data->object_instance, value.type.Boolean); + } + break; default: - if (property_lists_member( - Time_Value_Properties_Required, Time_Value_Properties_Optional, - Time_Value_Properties_Proprietary, wp_data->object_property)) { + if (property_lists_member(Time_Value_Properties_Required, + Time_Value_Properties_Optional, + Time_Value_Properties_Proprietary, + wp_data->object_property)) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } else { @@ -655,7 +666,7 @@ void Time_Value_Write_Present_Value_Callback_Set( uint8_t Time_Value_Status_Flags(uint32_t object_instance) { BACNET_BIT_STRING bit_string; - + bitstring_init(&bit_string); bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false); bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);