From 957bb9fb99548feb77090e25669c7dac8dcfc0f5 Mon Sep 17 00:00:00 2001 From: skarg Date: Wed, 11 Jan 2017 23:51:24 +0000 Subject: [PATCH] Added COV example to Analog Value object. --- bacnet-stack/demo/object/av.c | 194 ++++++++++++++++++++++++++++++ bacnet-stack/demo/object/av.h | 3 + bacnet-stack/demo/object/device.c | 6 +- 3 files changed, 200 insertions(+), 3 deletions(-) diff --git a/bacnet-stack/demo/object/av.c b/bacnet-stack/demo/object/av.c index 6c653038..01c85151 100644 --- a/bacnet-stack/demo/object/av.c +++ b/bacnet-stack/demo/object/av.c @@ -63,6 +63,7 @@ static const int Analog_Value_Properties_Required[] = { static const int Analog_Value_Properties_Optional[] = { PROP_DESCRIPTION, + PROP_COV_INCREMENT, #if defined(INTRINSIC_REPORTING) PROP_TIME_DELAY, PROP_NOTIFICATION_CLASS, @@ -109,6 +110,9 @@ void Analog_Value_Init( memset(&AV_Descr[i], 0x00, sizeof(ANALOG_VALUE_DESCR)); AV_Descr[i].Present_Value = 0.0; AV_Descr[i].Units = UNITS_NO_UNITS; + AV_Descr[i].Prior_Value = 0.0f; + AV_Descr[i].COV_Increment = 1.0f; + AV_Descr[i].Changed = false; #if defined(INTRINSIC_REPORTING) AV_Descr[i].Event_State = EVENT_STATE_NORMAL; /* notification class not connected */ @@ -175,6 +179,28 @@ unsigned Analog_Value_Instance_To_Index( return index; } +static void Analog_Value_COV_Detect(unsigned int index, + float value) +{ + float prior_value = 0.0; + float cov_increment = 0.0; + float cov_delta = 0.0; + + if (index < MAX_ANALOG_VALUES) { + prior_value = AV_Descr[index].Prior_Value; + cov_increment = AV_Descr[index].COV_Increment; + if (prior_value > value) { + cov_delta = prior_value - value; + } else { + cov_delta = value - prior_value; + } + if (cov_delta >= cov_increment) { + AV_Descr[index].Changed = true; + AV_Descr[index].Prior_Value = value; + } + } +} + /** * For a given object instance-number, sets the present-value at a given * priority 1..16. @@ -195,6 +221,7 @@ bool Analog_Value_Present_Value_Set( index = Analog_Value_Instance_To_Index(object_instance); if (index < MAX_ANALOG_VALUES) { + Analog_Value_COV_Detect(index, value); AV_Descr[index].Present_Value = value; status = true; } @@ -232,6 +259,151 @@ bool Analog_Value_Object_Name( return status; } + /** + * For a given object instance-number, determines if the COV flag + * has been triggered. + * + * @param object_instance - object-instance number of the object + * + * @return true if the COV flag is set + */ +bool Analog_Value_Change_Of_Value(uint32_t object_instance) +{ + unsigned index = 0; + bool changed = false; + + index = Analog_Value_Instance_To_Index(object_instance); + if (index < MAX_ANALOG_VALUES) { + changed = AV_Descr[index].Changed; + } + + return changed; +} + +/** + * For a given object instance-number, clears the COV flag + * + * @param object_instance - object-instance number of the object + */ +void Analog_Value_Change_Of_Value_Clear(uint32_t object_instance) +{ + unsigned index = 0; + + index = Analog_Value_Instance_To_Index(object_instance); + if (index < MAX_ANALOG_VALUES) { + AV_Descr[index].Changed = false; + } +} + +/** + * For a given object instance-number, loads the value_list with the COV data. + * + * @param object_instance - object-instance number of the object + * @param value_list - list of COV data + * + * @return true if the value list is encoded + */ +bool Analog_Value_Encode_Value_List( + uint32_t object_instance, + BACNET_PROPERTY_VALUE * value_list) +{ + bool status = false; + + if (value_list) { + value_list->propertyIdentifier = PROP_PRESENT_VALUE; + value_list->propertyArrayIndex = BACNET_ARRAY_ALL; + value_list->value.context_specific = false; + value_list->value.tag = BACNET_APPLICATION_TAG_REAL; + value_list->value.type.Real = + Analog_Value_Present_Value(object_instance); + value_list->value.next = NULL; + value_list->priority = BACNET_NO_PRIORITY; + value_list = value_list->next; + } + if (value_list) { + value_list->propertyIdentifier = PROP_STATUS_FLAGS; + value_list->propertyArrayIndex = BACNET_ARRAY_ALL; + value_list->value.context_specific = false; + value_list->value.tag = BACNET_APPLICATION_TAG_BIT_STRING; + bitstring_init(&value_list->value.type.Bit_String); + bitstring_set_bit(&value_list->value.type.Bit_String, + STATUS_FLAG_IN_ALARM, false); + bitstring_set_bit(&value_list->value.type.Bit_String, + STATUS_FLAG_FAULT, false); + bitstring_set_bit(&value_list->value.type.Bit_String, + STATUS_FLAG_OVERRIDDEN, false); + if (Analog_Value_Out_Of_Service(object_instance)) { + bitstring_set_bit(&value_list->value.type.Bit_String, + STATUS_FLAG_OUT_OF_SERVICE, true); + } else { + bitstring_set_bit(&value_list->value.type.Bit_String, + STATUS_FLAG_OUT_OF_SERVICE, false); + } + value_list->value.next = NULL; + value_list->priority = BACNET_NO_PRIORITY; + value_list->next = NULL; + status = true; + } + + return status; +} + +float Analog_Value_COV_Increment( + uint32_t object_instance) +{ + unsigned index = 0; + float value = 0; + + index = Analog_Value_Instance_To_Index(object_instance); + if (index < MAX_ANALOG_VALUES) { + value = AV_Descr[index].COV_Increment; + } + + return value; +} + +void Analog_Value_COV_Increment_Set( + uint32_t object_instance, + float value) +{ + unsigned index = 0; + + index = Analog_Value_Instance_To_Index(object_instance); + if (index < MAX_ANALOG_VALUES) { + AV_Descr[index].COV_Increment = value; + Analog_Value_COV_Detect(index, AV_Descr[index].Present_Value); + } +} + +bool Analog_Value_Out_Of_Service( + uint32_t object_instance) +{ + unsigned index = 0; + bool value = false; + + index = Analog_Value_Instance_To_Index(object_instance); + if (index < MAX_ANALOG_VALUES) { + value = AV_Descr[index].Out_Of_Service; + } + + return value; +} + +void Analog_Value_Out_Of_Service_Set( + uint32_t object_instance, + bool value) +{ + unsigned index = 0; + + index = Analog_Value_Instance_To_Index(object_instance); + if (index < MAX_ANALOG_VALUES) { + if (AV_Descr[index].Out_Of_Service != value) { + AV_Descr[index].Changed = true; + } + AV_Descr[index].Out_Of_Service = value; + } +} + /* return apdu len, or BACNET_STATUS_ERROR on error */ int Analog_Value_Read_Property( BACNET_READ_PROPERTY_DATA * rpdata) @@ -323,6 +495,11 @@ int Analog_Value_Read_Property( encode_application_enumerated(&apdu[0], CurrentAV->Units); break; + case PROP_COV_INCREMENT: + apdu_len = encode_application_real(&apdu[0], + CurrentAV->COV_Increment); + break; + #if defined(INTRINSIC_REPORTING) case PROP_TIME_DELAY: apdu_len = @@ -543,6 +720,23 @@ bool Analog_Value_Write_Property( } break; + case PROP_COV_INCREMENT: + status = + WPValidateArgType(&value, BACNET_APPLICATION_TAG_REAL, + &wp_data->error_class, &wp_data->error_code); + if (status) { + if (value.type.Real >= 0.0) { + Analog_Value_COV_Increment_Set( + wp_data->object_instance, + value.type.Real); + } else { + status = false; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + } + } + break; + #if defined(INTRINSIC_REPORTING) case PROP_TIME_DELAY: status = diff --git a/bacnet-stack/demo/object/av.h b/bacnet-stack/demo/object/av.h index 6f873158..78a5fa23 100644 --- a/bacnet-stack/demo/object/av.h +++ b/bacnet-stack/demo/object/av.h @@ -48,6 +48,9 @@ extern "C" { bool Out_Of_Service; uint16_t Units; float Present_Value; + float Prior_Value; + float COV_Increment; + bool Changed; #if defined(INTRINSIC_REPORTING) uint32_t Time_Delay; uint32_t Notification_Class; diff --git a/bacnet-stack/demo/object/device.c b/bacnet-stack/demo/object/device.c index f4b97e23..baf5c48f 100644 --- a/bacnet-stack/demo/object/device.c +++ b/bacnet-stack/demo/object/device.c @@ -154,9 +154,9 @@ static object_functions_t My_Object_Table[] = { Analog_Value_Property_Lists, NULL /* ReadRangeInfo */ , NULL /* Iterator */ , - NULL /* Value_Lists */ , - NULL /* COV */ , - NULL /* COV Clear */ , + Analog_Value_Encode_Value_List, + Analog_Value_Change_Of_Value, + Analog_Value_Change_Of_Value_Clear, Analog_Value_Intrinsic_Reporting}, {OBJECT_BINARY_INPUT, Binary_Input_Init,