From 8da85f6c79776bec36d065bb210979536c8ecf98 Mon Sep 17 00:00:00 2001 From: skarg Date: Wed, 25 May 2011 20:18:56 +0000 Subject: [PATCH] Moved COV object handling into Device object. Fixed COV for multiple subscriptions to same object. --- bacnet-stack/demo/handler/h_cov.c | 115 ++++++++++++++-------------- bacnet-stack/demo/object/ai.h | 2 +- bacnet-stack/demo/object/ao.h | 2 +- bacnet-stack/demo/object/av.h | 2 +- bacnet-stack/demo/object/bacfile.h | 2 +- bacnet-stack/demo/object/bi.c | 67 ++++++++-------- bacnet-stack/demo/object/bi.h | 6 +- bacnet-stack/demo/object/bo.h | 2 +- bacnet-stack/demo/object/bv.h | 2 +- bacnet-stack/demo/object/device.c | 52 +++++++++++++ bacnet-stack/demo/object/device.h | 21 ++++- bacnet-stack/demo/object/lc.h | 2 +- bacnet-stack/demo/object/lsp.h | 2 +- bacnet-stack/demo/object/ms-input.h | 2 +- bacnet-stack/demo/object/mso.h | 2 +- bacnet-stack/demo/object/trendlog.h | 2 +- 16 files changed, 180 insertions(+), 103 deletions(-) diff --git a/bacnet-stack/demo/handler/h_cov.c b/bacnet-stack/demo/handler/h_cov.c index affea5a5..1b022adc 100644 --- a/bacnet-stack/demo/handler/h_cov.c +++ b/bacnet-stack/demo/handler/h_cov.c @@ -30,6 +30,7 @@ #include "config.h" #include "txbuf.h" #include "bacdef.h" +#include "bacerror.h" #include "bacdcode.h" #include "bacaddr.h" #include "apdu.h" @@ -40,18 +41,6 @@ #include "tsm.h" /* demo objects */ #include "device.h" -#include "ai.h" -#include "ao.h" -#include "av.h" -#include "bi.h" -#include "bo.h" -#include "bv.h" -#include "lc.h" -#include "lsp.h" -#include "mso.h" -#if defined(BACFILE) -#include "bacfile.h" -#endif #include "handlers.h" /** @file h_cov.c Handles Change of Value (COV) services. */ @@ -313,7 +302,8 @@ static bool cov_list_subscribe( } static bool cov_send_request( - BACNET_COV_SUBSCRIPTION * cov_subscription) + BACNET_COV_SUBSCRIPTION * cov_subscription, + BACNET_PROPERTY_VALUE * value_list) { int len = 0; int pdu_len = 0; @@ -323,7 +313,6 @@ static bool cov_send_request( uint8_t invoke_id = 0; bool status = false; /* return value */ BACNET_COV_DATA cov_data; - BACNET_PROPERTY_VALUE value_list[2]; #if PRINT_ENABLED fprintf(stderr, "COVnotification: requested\n"); @@ -342,18 +331,7 @@ static bool cov_send_request( cov_data.monitoredObjectIdentifier.instance = cov_subscription->monitoredObjectIdentifier.instance; cov_data.timeRemaining = cov_subscription->lifetime; - /* encode the value list */ - cov_data.listOfValues = &value_list[0]; - value_list[0].next = &value_list[1]; - value_list[1].next = NULL; - switch (cov_subscription->monitoredObjectIdentifier.type) { - case OBJECT_BINARY_INPUT: - Binary_Input_Encode_Value_List(cov_subscription-> - monitoredObjectIdentifier.instance, &value_list[0]); - break; - default: - goto COV_FAILED; - } + cov_data.listOfValues = value_list; if (cov_subscription->issueConfirmedNotifications) { invoke_id = tsm_next_free_invokeID(); if (invoke_id) { @@ -410,12 +388,15 @@ static bool cov_send_request( void handler_cov_task( uint32_t elapsed_seconds) { - int index; - uint32_t lifetime_seconds; - BACNET_OBJECT_ID object_id; + int index = 0, index2 = 0; + uint32_t lifetime_seconds = 0; + uint16_t object_type = 0, object_type2 = 0; + uint32_t object_instance = 0, object_instance2 = 0; bool status = false; + BACNET_PROPERTY_VALUE value_list[2]; - + value_list[0].next = &value_list[1]; + value_list[1].next = NULL; /* existing? - match Object ID and Process ID */ for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) { if (COV_Subscriptions[index].valid) { @@ -434,24 +415,41 @@ void handler_cov_task( COV_Subscriptions[index].valid = false; } /* handle COV notifications */ - object_id.type = + object_type = COV_Subscriptions[index].monitoredObjectIdentifier.type; - object_id.instance = + object_instance = COV_Subscriptions[index].monitoredObjectIdentifier.instance; - switch (object_id.type) { - case OBJECT_BINARY_INPUT: - if (Binary_Input_Change_Of_Value(object_id.instance)) { - COV_Subscriptions[index].send_requested = true; - Binary_Input_Change_Of_Value_Clear(object_id.instance); - } - break; - default: - break; + status = Device_Encode_Value_List( + object_type, + object_instance, + &value_list[0]); + if (status) { + COV_Subscriptions[index].send_requested = true; } if (COV_Subscriptions[index].send_requested) { - status = cov_send_request(&COV_Subscriptions[index]); + cov_send_request( + &COV_Subscriptions[index], + &value_list[0]); COV_Subscriptions[index].send_requested = false; } + if (status && ((index+1) < MAX_COV_SUBCRIPTIONS)) { + /* if more than one subscription for this object instance */ + for (index2 = index+1; index2 < MAX_COV_SUBCRIPTIONS; index2++) { + object_type2 = + COV_Subscriptions[index2].monitoredObjectIdentifier.type; + object_instance2 = + COV_Subscriptions[index2].monitoredObjectIdentifier.instance; + if ((COV_Subscriptions[index].lifetime) && + (COV_Subscriptions[index].valid) && + (object_type == object_type2) && + (object_instance == object_instance2)) { + cov_send_request( + &COV_Subscriptions[index2], + &value_list[0]); + COV_Subscriptions[index2].send_requested = false; + } + } + } } } } @@ -463,22 +461,27 @@ static bool cov_subscribe( BACNET_ERROR_CODE * error_code) { bool status = false; /* return value */ + uint16_t object_type = 0; + uint32_t object_instance = 0; - switch (cov_data->monitoredObjectIdentifier.type) { - case OBJECT_BINARY_INPUT: - if (Binary_Input_Valid_Instance(cov_data-> - monitoredObjectIdentifier.instance)) { - status = - cov_list_subscribe(src, cov_data, error_class, error_code); - } else { - *error_class = ERROR_CLASS_OBJECT; - *error_code = ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED; - } - break; - default: + object_type = cov_data->monitoredObjectIdentifier.type; + object_instance = cov_data->monitoredObjectIdentifier.instance; + status = Device_Valid_Object_Id(object_type, object_instance); + if (status) { + status = Device_Value_List_Supported(object_type); + if (status) { + status = cov_list_subscribe( + src, + cov_data, + error_class, + error_code); + } else { *error_class = ERROR_CLASS_OBJECT; - *error_code = ERROR_CODE_UNKNOWN_OBJECT; - break; + *error_code = ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED; + } + } else { + *error_class = ERROR_CLASS_OBJECT; + *error_code = ERROR_CODE_UNKNOWN_OBJECT; } return status; diff --git a/bacnet-stack/demo/object/ai.h b/bacnet-stack/demo/object/ai.h index b7a51bd8..3ea8cadd 100644 --- a/bacnet-stack/demo/object/ai.h +++ b/bacnet-stack/demo/object/ai.h @@ -96,5 +96,5 @@ extern "C" { OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count, \ Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance, \ Analog_Input_Object_Name, Analog_Input_Read_Property, NULL, \ - Analog_Input_Property_Lists, NULL, NULL + Analog_Input_Property_Lists, NULL, NULL, NULL #endif diff --git a/bacnet-stack/demo/object/ao.h b/bacnet-stack/demo/object/ao.h index d4b87808..326eab06 100644 --- a/bacnet-stack/demo/object/ao.h +++ b/bacnet-stack/demo/object/ao.h @@ -105,5 +105,5 @@ extern "C" { Analog_Output_Index_To_Instance, Analog_Output_Valid_Instance, \ Analog_Output_Object_Name, Analog_Output_Read_Property, \ Analog_Output_Write_Property, Analog_Output_Property_Lists, \ - NULL, NULL + NULL, NULL, NULL #endif diff --git a/bacnet-stack/demo/object/av.h b/bacnet-stack/demo/object/av.h index 34f4c139..7de0139b 100644 --- a/bacnet-stack/demo/object/av.h +++ b/bacnet-stack/demo/object/av.h @@ -82,5 +82,5 @@ extern "C" { Analog_Value_Index_To_Instance, Analog_Value_Valid_Instance, \ Analog_Value_Object_Name, Analog_Value_Read_Property, \ Analog_Value_Write_Property, Analog_Value_Property_Lists, NULL, \ - NULL + NULL, NULL #endif diff --git a/bacnet-stack/demo/object/bacfile.h b/bacnet-stack/demo/object/bacfile.h index 70b675db..3997f7b0 100644 --- a/bacnet-stack/demo/object/bacfile.h +++ b/bacnet-stack/demo/object/bacfile.h @@ -101,5 +101,5 @@ extern "C" { #define FILE_OBJ_FUNCTIONS \ OBJECT_FILE, bacfile_init, bacfile_count, bacfile_index_to_instance, \ bacfile_valid_instance, bacfile_object_name, bacfile_read_property, \ - bacfile_write_property, BACfile_Property_Lists, NULL + bacfile_write_property, BACfile_Property_Lists, NULL, NULL #endif diff --git a/bacnet-stack/demo/object/bi.c b/bacnet-stack/demo/object/bi.c index 8fa0be1b..477858b7 100644 --- a/bacnet-stack/demo/object/bi.c +++ b/bacnet-stack/demo/object/bi.c @@ -183,7 +183,7 @@ bool Binary_Input_Out_Of_Service( return value; } -bool Binary_Input_Change_Of_Value( +static bool Binary_Input_Change_Of_Value( uint32_t object_instance) { bool status = false; @@ -197,7 +197,7 @@ bool Binary_Input_Change_Of_Value( return status; } -void Binary_Input_Change_Of_Value_Clear( +static void Binary_Input_Change_Of_Value_Clear( uint32_t object_instance) { unsigned index; @@ -210,41 +210,48 @@ void Binary_Input_Change_Of_Value_Clear( return; } +/* returns true if value has changed */ bool Binary_Input_Encode_Value_List( uint32_t object_instance, BACNET_PROPERTY_VALUE * 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.type.Enumerated = - Binary_Input_Present_Value(object_instance); - value_list->priority = BACNET_NO_PRIORITY; + bool status = false; - value_list = value_list->next; - - 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 (Binary_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); + 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.type.Enumerated = + Binary_Input_Present_Value(object_instance); + value_list->priority = BACNET_NO_PRIORITY; + value_list = value_list->next; } - value_list->priority = BACNET_NO_PRIORITY; + 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 (Binary_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->priority = BACNET_NO_PRIORITY; + } + status = Binary_Input_Change_Of_Value(object_instance); + Binary_Input_Change_Of_Value_Clear(object_instance); - return true; + return status; } bool Binary_Input_Present_Value_Set( diff --git a/bacnet-stack/demo/object/bi.h b/bacnet-stack/demo/object/bi.h index 4eb0c17d..9e231569 100644 --- a/bacnet-stack/demo/object/bi.h +++ b/bacnet-stack/demo/object/bi.h @@ -83,10 +83,6 @@ extern "C" { bool Binary_Input_Out_Of_Service( uint32_t object_instance); - bool Binary_Input_Change_Of_Value( - uint32_t object_instance); - void Binary_Input_Change_Of_Value_Clear( - uint32_t object_instance); bool Binary_Input_Encode_Value_List( uint32_t object_instance, BACNET_PROPERTY_VALUE * value_list); @@ -118,5 +114,5 @@ extern "C" { OBJECT_BINARY_INPUT, Binary_Input_Init, Binary_Input_Count, \ Binary_Input_Index_To_Instance, Binary_Input_Valid_Instance, \ Binary_Input_Object_Name, Binary_Input_Read_Property, NULL, \ - Binary_Input_Property_Lists, NULL, NULL + Binary_Input_Property_Lists, NULL, NULL, Binary_Input_Encode_Value_List #endif diff --git a/bacnet-stack/demo/object/bo.h b/bacnet-stack/demo/object/bo.h index 741cf170..6aece0ef 100644 --- a/bacnet-stack/demo/object/bo.h +++ b/bacnet-stack/demo/object/bo.h @@ -114,5 +114,5 @@ extern "C" { Binary_Output_Index_To_Instance, Binary_Output_Valid_Instance, \ Binary_Output_Object_Name, Binary_Output_Read_Property, \ Binary_Output_Write_Property, Binary_Output_Property_Lists, \ - NULL, NULL + NULL, NULL, NULL #endif diff --git a/bacnet-stack/demo/object/bv.h b/bacnet-stack/demo/object/bv.h index ace89ca2..ab8c10ee 100644 --- a/bacnet-stack/demo/object/bv.h +++ b/bacnet-stack/demo/object/bv.h @@ -76,5 +76,5 @@ extern "C" { Binary_Value_Index_To_Instance, Binary_Value_Valid_Instance, \ Binary_Value_Object_Name, Binary_Value_Read_Property, \ Binary_Value_Write_Property, Binary_Value_Property_Lists, NULL, \ - NULL + NULL, NULL #endif diff --git a/bacnet-stack/demo/object/device.c b/bacnet-stack/demo/object/device.c index 37d03a95..e9fcdc9a 100644 --- a/bacnet-stack/demo/object/device.c +++ b/bacnet-stack/demo/object/device.c @@ -1359,6 +1359,58 @@ bool Device_Write_Property( return (status); } +/** Looks up the requested Object, and fills the Property Value list. + * If the Object or Property can't be found, returns false. + * @ingroup ObjHelpers + * @param [in] The object type to be looked up. + * @param [in] The object instance number to be looked up. + * @param [out] The value list + * @return True if the object instance supports this feature and value changed. + */ +bool Device_Encode_Value_List( + BACNET_OBJECT_TYPE object_type, + uint32_t object_instance, + BACNET_PROPERTY_VALUE * value_list) +{ + bool status = false; /* Ever the pessamist! */ + struct object_functions *pObject = NULL; + + pObject = Device_Objects_Find_Functions(object_type); + if (pObject != NULL) { + if (pObject->Object_Valid_Instance && + pObject->Object_Valid_Instance(object_instance)) { + if (pObject->Object_Value_List) { + status = pObject->Object_Value_List( + object_instance, + value_list); + } + } + } + + return (status); +} + +/** Looks up the requested Object to see if the functionality is supported. + * @ingroup ObjHelpers + * @param [in] The object type to be looked up. + * @return True if the object instance supports this feature. + */ +bool Device_Value_List_Supported( + BACNET_OBJECT_TYPE object_type) +{ + bool status = false; /* Ever the pessamist! */ + struct object_functions *pObject = NULL; + + pObject = Device_Objects_Find_Functions(object_type); + if (pObject != NULL) { + if (pObject->Object_Value_List) { + status = true; + } + } + + return (status); +} + /** Initialize the Device Object. Initialize the group of object helper functions for any supported Object. Initialize each of the Device Object child Object instances. diff --git a/bacnet-stack/demo/object/device.h b/bacnet-stack/demo/object/device.h index c0e4bc1b..b911ba77 100644 --- a/bacnet-stack/demo/object/device.h +++ b/bacnet-stack/demo/object/device.h @@ -101,6 +101,17 @@ typedef unsigned ( *object_iterate_function) ( unsigned current_index); +/** Look in the table of objects of this type, and get the COV Value List. + * @ingroup ObjHelpers + * @param [in] The object instance number to be looked up. + * @param [out] The value list + * @return True if the object instance supports this feature, and has changed. + */ +typedef bool( + *object_value_list_function) ( + uint32_t object_instance, + BACNET_PROPERTY_VALUE * value_list); + /** Defines the group of object helper functions for any supported Object. * @ingroup ObjHelpers * Each Object must provide some implementation of each of these helpers @@ -122,6 +133,7 @@ typedef struct object_functions { rpm_property_lists_function Object_RPM_List; rr_info_function Object_RR_Info; object_iterate_function Object_Iterator; + object_value_list_function Object_Value_List; } object_functions_t; /* String Lengths - excluding any nul terminator */ @@ -199,6 +211,13 @@ extern "C" { BACNET_OBJECT_TYPE object_type, struct special_property_list_t *pPropertyList); + bool Device_Encode_Value_List( + BACNET_OBJECT_TYPE object_type, + uint32_t object_instance, + BACNET_PROPERTY_VALUE * value_list); + bool Device_Value_List_Supported( + BACNET_OBJECT_TYPE object_type); + uint32_t Device_Object_Instance_Number( void); bool Device_Set_Object_Instance_Number( @@ -366,7 +385,7 @@ extern "C" { OBJECT_DEVICE, NULL, Device_Count, Device_Index_To_Instance, \ Device_Valid_Object_Instance_Number, Device_Object_Name, \ Device_Read_Property_Local, Device_Write_Property_Local, \ - Device_Property_Lists, DeviceGetRRInfo, NULL + Device_Property_Lists, DeviceGetRRInfo, NULL, NULL /** @defgroup ObjFrmwk Object Framework * The modules in this section describe the BACnet-stack's framework for * BACnet-defined Objects (Device, Analog Input, etc). There are two submodules diff --git a/bacnet-stack/demo/object/lc.h b/bacnet-stack/demo/object/lc.h index 2a8943ba..ae88da10 100644 --- a/bacnet-stack/demo/object/lc.h +++ b/bacnet-stack/demo/object/lc.h @@ -81,5 +81,5 @@ extern "C" { Load_Control_Index_To_Instance, Load_Control_Valid_Instance, \ Load_Control_Object_Name, Load_Control_Read_Property, \ Load_Control_Write_Property, Load_Control_Property_Lists, NULL, \ - NULL + NULL, NULL #endif diff --git a/bacnet-stack/demo/object/lsp.h b/bacnet-stack/demo/object/lsp.h index 56e41691..ecf1c306 100644 --- a/bacnet-stack/demo/object/lsp.h +++ b/bacnet-stack/demo/object/lsp.h @@ -75,5 +75,5 @@ extern "C" { Life_Safety_Point_Valid_Instance, Life_Safety_Point_Object_Name, \ Life_Safety_Point_Read_Property, \ Life_Safety_Point_Write_Property, \ - Life_Safety_Point_Property_Lists, NULL, NULL + Life_Safety_Point_Property_Lists, NULL, NULL, NULL #endif diff --git a/bacnet-stack/demo/object/ms-input.h b/bacnet-stack/demo/object/ms-input.h index e7e97884..34545e2a 100644 --- a/bacnet-stack/demo/object/ms-input.h +++ b/bacnet-stack/demo/object/ms-input.h @@ -102,5 +102,5 @@ extern "C" { Multistate_Input_Valid_Instance, Multistate_Input_Object_Name, \ Multistate_Input_Read_Property, \ Multistate_Input_Write_Property, \ - Multistate_Input_Property_Lists, NULL, NULL + Multistate_Input_Property_Lists, NULL, NULL, NULL #endif diff --git a/bacnet-stack/demo/object/mso.h b/bacnet-stack/demo/object/mso.h index 0e971854..de29a4fe 100644 --- a/bacnet-stack/demo/object/mso.h +++ b/bacnet-stack/demo/object/mso.h @@ -77,5 +77,5 @@ extern "C" { Multistate_Output_Valid_Instance, Multistate_Output_Object_Name, \ Multistate_Output_Read_Property, \ Multistate_Output_Write_Property, \ - Multistate_Output_Property_Lists, NULL, NULL + Multistate_Output_Property_Lists, NULL, NULL, NULL #endif diff --git a/bacnet-stack/demo/object/trendlog.h b/bacnet-stack/demo/object/trendlog.h index cd0cee67..0b3247f8 100644 --- a/bacnet-stack/demo/object/trendlog.h +++ b/bacnet-stack/demo/object/trendlog.h @@ -202,5 +202,5 @@ extern "C" { Trend_Log_Index_To_Instance, Trend_Log_Valid_Instance, \ Trend_Log_Object_Name, Trend_Log_Read_Property, \ Trend_Log_Write_Property, Trend_Log_Property_Lists, \ - TrendLogGetRRInfo, NULL + TrendLogGetRRInfo, NULL, NULL #endif