diff --git a/src/bacnet/basic/object/ai.c b/src/bacnet/basic/object/ai.c index 9fa9ac57..6a90fdd4 100644 --- a/src/bacnet/basic/object/ai.c +++ b/src/bacnet/basic/object/ai.c @@ -286,46 +286,22 @@ bool Analog_Input_Encode_Value_List( uint32_t object_instance, BACNET_PROPERTY_VALUE *value_list) { bool status = false; + bool in_alarm = false; + bool out_of_service = false; + const bool fault = false; + const bool overridden = false; + float present_value = 0.0; + unsigned index = 0; /* offset from instance lookup */ - 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_Input_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); - if (Analog_Input_Event_State(object_instance) == EVENT_STATE_NORMAL) { - bitstring_set_bit(&value_list->value.type.Bit_String, - STATUS_FLAG_IN_ALARM, false); - } else { - bitstring_set_bit(&value_list->value.type.Bit_String, - STATUS_FLAG_IN_ALARM, true); + index = Analog_Input_Instance_To_Index(object_instance); + if (index < MAX_ANALOG_INPUTS) { + if (AI_Descr[index].Event_State != EVENT_STATE_NORMAL) { + in_alarm = true; } - 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_Input_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; + out_of_service = AI_Descr[index].Out_Of_Service; + present_value = AI_Descr[index].Present_Value; + status = cov_value_list_encode_real(value_list, present_value, + in_alarm, fault, overridden, out_of_service); } return status; diff --git a/src/bacnet/basic/object/csv.c b/src/bacnet/basic/object/csv.c index 5f3eaed8..1bac65a1 100644 --- a/src/bacnet/basic/object/csv.c +++ b/src/bacnet/basic/object/csv.c @@ -50,6 +50,7 @@ static BACNET_CHARACTER_STRING Present_Value[MAX_CHARACTERSTRING_VALUES]; static bool Out_Of_Service[MAX_CHARACTERSTRING_VALUES]; static char Object_Name[MAX_CHARACTERSTRING_VALUES][64]; static char Object_Description[MAX_CHARACTERSTRING_VALUES][64]; +static bool Changed[MAX_CHARACTERSTRING_VALUES]; /* These three arrays are used by the ReadPropertyMultiple handler */ static const int Properties_Required[] = { PROP_OBJECT_IDENTIFIER, @@ -99,6 +100,7 @@ void CharacterString_Value_Init(void) snprintf(&Object_Description[i][0], sizeof(Object_Description[i]), "A Character String Value Example"); characterstring_init_ansi(&Present_Value[i], ""); + Changed[i] = false; } return; @@ -210,6 +212,9 @@ bool CharacterString_Value_Present_Value_Set( index = CharacterString_Value_Instance_To_Index(object_instance); if (index < MAX_CHARACTERSTRING_VALUES) { + if (!characterstring_same(&Present_Value[index], object_name)) { + Changed[index] = true; + } status = characterstring_copy(&Present_Value[index], object_name); } @@ -249,12 +254,75 @@ static void CharacterString_Value_Out_Of_Service_Set( index = CharacterString_Value_Instance_To_Index(object_instance); if (index < MAX_CHARACTERSTRING_VALUES) { + if (Out_Of_Service[index] != value) { + Changed[index] = true; + } Out_Of_Service[index] = value; } return; } +/** + * @brief Get the COV change flag status + * @param object_instance - object-instance number of the object + * @return the COV change flag status + */ +bool CharacterString_Value_Change_Of_Value( + uint32_t object_instance) +{ + bool changed = false; + unsigned index = 0; /* offset from instance lookup */ + + index = CharacterString_Value_Instance_To_Index(object_instance); + if (index < MAX_CHARACTERSTRING_VALUES) { + changed = Changed[index]; + } + + return changed; +} + +/** + * @brief Clear the COV change flag + * @param object_instance - object-instance number of the object + */ +void CharacterString_Value_Change_Of_Value_Clear( + uint32_t object_instance) +{ + unsigned index = 0; /* offset from instance lookup */ + + index = CharacterString_Value_Instance_To_Index(object_instance); + if (index < MAX_CHARACTERSTRING_VALUES) { + Changed[index] = false; + } +} + +/** + * @brief 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 CharacterString_Value_Encode_Value_List( + uint32_t object_instance, + BACNET_PROPERTY_VALUE * value_list) +{ + bool status = false; + const bool in_alarm = false; + const bool fault = false; + const bool overridden = false; + unsigned index = 0; /* offset from instance lookup */ + + index = CharacterString_Value_Instance_To_Index(object_instance); + if (index < MAX_CHARACTERSTRING_VALUES) { + status = cov_value_list_encode_character_string(value_list, + &Present_Value[index], in_alarm, fault, overridden, + Out_Of_Service[index]); + } + + return status; +} + /** * For a given object instance-number, return the description. * diff --git a/src/bacnet/basic/object/csv.h b/src/bacnet/basic/object/csv.h index 660ba7c9..8f0744c5 100644 --- a/src/bacnet/basic/object/csv.h +++ b/src/bacnet/basic/object/csv.h @@ -94,6 +94,17 @@ extern "C" { bool CharacterString_Value_Out_Of_Service( uint32_t object_instance); + BACNET_STACK_EXPORT + bool CharacterString_Value_Change_Of_Value( + uint32_t instance); + BACNET_STACK_EXPORT + void CharacterString_Value_Change_Of_Value_Clear( + uint32_t instance); + BACNET_STACK_EXPORT + bool CharacterString_Value_Encode_Value_List( + uint32_t object_instance, + BACNET_PROPERTY_VALUE * value_list); + BACNET_STACK_EXPORT void CharacterString_Value_Init( void); diff --git a/src/bacnet/basic/object/device.c b/src/bacnet/basic/object/device.c index 76e7ed5a..306d02f6 100644 --- a/src/bacnet/basic/object/device.c +++ b/src/bacnet/basic/object/device.c @@ -150,8 +150,10 @@ static object_functions_t My_Object_Table[] = { CharacterString_Value_Read_Property, CharacterString_Value_Write_Property, CharacterString_Value_Property_Lists, NULL /* ReadRangeInfo */, - NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, - NULL /* COV Clear */, NULL /* Intrinsic Reporting */ }, + NULL /* Iterator */, CharacterString_Value_Encode_Value_List, + CharacterString_Value_Change_Of_Value, + CharacterString_Value_Change_Of_Value_Clear, + NULL /* Intrinsic Reporting */ }, { OBJECT_COMMAND, Command_Init, Command_Count, Command_Index_To_Instance, Command_Valid_Instance, Command_Object_Name, Command_Read_Property, Command_Write_Property, Command_Property_Lists, diff --git a/src/bacnet/basic/object/msv.c b/src/bacnet/basic/object/msv.c index bb7ff673..6cc6df44 100644 --- a/src/bacnet/basic/object/msv.c +++ b/src/bacnet/basic/object/msv.c @@ -368,41 +368,19 @@ bool Multistate_Value_Encode_Value_List( uint32_t object_instance, BACNET_PROPERTY_VALUE *value_list) { bool status = false; + const bool in_alarm = false; + const bool fault = false; + const bool overridden = false; + bool out_of_service = false; + uint32_t present_value = 0.0; + unsigned index = 0; - 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_ENUMERATED; - value_list->value.next = NULL; - value_list->value.type.Enumerated = - Multistate_Value_Present_Value(object_instance); - 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; - value_list->value.next = NULL; - 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 (Multistate_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->priority = BACNET_NO_PRIORITY; - value_list->next = NULL; - status = true; + index = Multistate_Value_Instance_To_Index(object_instance); + if (index < MAX_MULTISTATE_VALUES) { + present_value = Present_Value[index]; + out_of_service = Out_Of_Service[index]; + status = cov_value_list_encode_enumerated(value_list, present_value, + in_alarm, fault, overridden, out_of_service); } return status; diff --git a/src/bacnet/cov.c b/src/bacnet/cov.c index 3beca175..cf170b70 100644 --- a/src/bacnet/cov.c +++ b/src/bacnet/cov.c @@ -925,6 +925,65 @@ bool cov_value_list_encode_unsigned( return status; } +#if defined (BACAPP_CHARACTER_STRING) +/** + * @brief Encode the Value List for CHARACTER_STRING Present-Value and + * Status-Flags + * @param value_list - #BACNET_PROPERTY_VALUE with at least 2 entries + * @param value - CHARACTER_STRING present-value + * @param in_alarm - value of in-alarm status-flags + * @param fault - value of in-alarm status-flags + * @param overridden - value of overridden status-flags + * @param out_of_service - value of out-of-service status-flags + * + * @return true if values were encoded +*/ +bool cov_value_list_encode_character_string( + BACNET_PROPERTY_VALUE * value_list, + BACNET_CHARACTER_STRING * value, + bool in_alarm, + bool fault, + bool overridden, + bool out_of_service) +{ + 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_CHARACTER_STRING; + characterstring_copy( + &value_list->value.type.Character_String, + value); + 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, in_alarm); + bitstring_set_bit(&value_list->value.type.Bit_String, + STATUS_FLAG_FAULT, fault); + bitstring_set_bit(&value_list->value.type.Bit_String, + STATUS_FLAG_OVERRIDDEN, overridden); + bitstring_set_bit(&value_list->value.type.Bit_String, + STATUS_FLAG_OUT_OF_SERVICE, out_of_service); + value_list->value.next = NULL; + value_list->priority = BACNET_NO_PRIORITY; + value_list->next = NULL; + status = true; + } + + return status; +} +#endif + #ifdef BAC_TEST #include #include diff --git a/src/bacnet/cov.h b/src/bacnet/cov.h index 4f413e73..01d38b66 100644 --- a/src/bacnet/cov.h +++ b/src/bacnet/cov.h @@ -152,6 +152,14 @@ extern "C" { bool fault, bool overridden, bool out_of_service); + BACNET_STACK_EXPORT + bool cov_value_list_encode_character_string( + BACNET_PROPERTY_VALUE * value_list, + BACNET_CHARACTER_STRING * value, + bool in_alarm, + bool fault, + bool overridden, + bool out_of_service); #ifdef BAC_TEST #include "ctest.h" diff --git a/test/bacnet/basic/object/ai/CMakeLists.txt b/test/bacnet/basic/object/ai/CMakeLists.txt index e9fc0d07..81808c43 100644 --- a/test/bacnet/basic/object/ai/CMakeLists.txt +++ b/test/bacnet/basic/object/ai/CMakeLists.txt @@ -42,9 +42,11 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bacapp.c ${SRC_DIR}/bacnet/bacdevobjpropref.c ${SRC_DIR}/bacnet/basic/sys/bigend.c + ${SRC_DIR}/bacnet/cov.c ${SRC_DIR}/bacnet/datetime.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c + ${SRC_DIR}/bacnet/memcopy.c ./stubs.c # Test and test library files ./src/main.c diff --git a/test/bacnet/basic/object/av/CMakeLists.txt b/test/bacnet/basic/object/av/CMakeLists.txt index 43a37668..60d525f2 100644 --- a/test/bacnet/basic/object/av/CMakeLists.txt +++ b/test/bacnet/basic/object/av/CMakeLists.txt @@ -42,9 +42,11 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bacstr.c ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c + ${SRC_DIR}/bacnet/cov.c ${SRC_DIR}/bacnet/datetime.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c + ${SRC_DIR}/bacnet/memcopy.c ./stubs.c # Test and test library files ./src/main.c diff --git a/test/bacnet/basic/object/bi/CMakeLists.txt b/test/bacnet/basic/object/bi/CMakeLists.txt index 6a5f6afa..04bf7355 100644 --- a/test/bacnet/basic/object/bi/CMakeLists.txt +++ b/test/bacnet/basic/object/bi/CMakeLists.txt @@ -42,9 +42,11 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bacstr.c ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c + ${SRC_DIR}/bacnet/cov.c ${SRC_DIR}/bacnet/datetime.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c + ${SRC_DIR}/bacnet/memcopy.c ./stubs.c # Test and test library files ./src/main.c diff --git a/test/bacnet/basic/object/msv/CMakeLists.txt b/test/bacnet/basic/object/msv/CMakeLists.txt index 1c7c5595..535b24f4 100644 --- a/test/bacnet/basic/object/msv/CMakeLists.txt +++ b/test/bacnet/basic/object/msv/CMakeLists.txt @@ -42,9 +42,11 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bacstr.c ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/sys/bigend.c + ${SRC_DIR}/bacnet/cov.c ${SRC_DIR}/bacnet/datetime.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/lighting.c + ${SRC_DIR}/bacnet/memcopy.c ./stubs.c # Test and test library files ./src/main.c