Moved COV object handling into Device object.

Fixed COV for multiple subscriptions to same object.
This commit is contained in:
skarg
2011-05-25 20:18:56 +00:00
parent 297bba14fa
commit 8da85f6c79
16 changed files with 180 additions and 103 deletions
+59 -56
View File
@@ -30,6 +30,7 @@
#include "config.h" #include "config.h"
#include "txbuf.h" #include "txbuf.h"
#include "bacdef.h" #include "bacdef.h"
#include "bacerror.h"
#include "bacdcode.h" #include "bacdcode.h"
#include "bacaddr.h" #include "bacaddr.h"
#include "apdu.h" #include "apdu.h"
@@ -40,18 +41,6 @@
#include "tsm.h" #include "tsm.h"
/* demo objects */ /* demo objects */
#include "device.h" #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" #include "handlers.h"
/** @file h_cov.c Handles Change of Value (COV) services. */ /** @file h_cov.c Handles Change of Value (COV) services. */
@@ -313,7 +302,8 @@ static bool cov_list_subscribe(
} }
static bool cov_send_request( static bool cov_send_request(
BACNET_COV_SUBSCRIPTION * cov_subscription) BACNET_COV_SUBSCRIPTION * cov_subscription,
BACNET_PROPERTY_VALUE * value_list)
{ {
int len = 0; int len = 0;
int pdu_len = 0; int pdu_len = 0;
@@ -323,7 +313,6 @@ static bool cov_send_request(
uint8_t invoke_id = 0; uint8_t invoke_id = 0;
bool status = false; /* return value */ bool status = false; /* return value */
BACNET_COV_DATA cov_data; BACNET_COV_DATA cov_data;
BACNET_PROPERTY_VALUE value_list[2];
#if PRINT_ENABLED #if PRINT_ENABLED
fprintf(stderr, "COVnotification: requested\n"); fprintf(stderr, "COVnotification: requested\n");
@@ -342,18 +331,7 @@ static bool cov_send_request(
cov_data.monitoredObjectIdentifier.instance = cov_data.monitoredObjectIdentifier.instance =
cov_subscription->monitoredObjectIdentifier.instance; cov_subscription->monitoredObjectIdentifier.instance;
cov_data.timeRemaining = cov_subscription->lifetime; cov_data.timeRemaining = cov_subscription->lifetime;
/* encode the value list */ cov_data.listOfValues = 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;
}
if (cov_subscription->issueConfirmedNotifications) { if (cov_subscription->issueConfirmedNotifications) {
invoke_id = tsm_next_free_invokeID(); invoke_id = tsm_next_free_invokeID();
if (invoke_id) { if (invoke_id) {
@@ -410,12 +388,15 @@ static bool cov_send_request(
void handler_cov_task( void handler_cov_task(
uint32_t elapsed_seconds) uint32_t elapsed_seconds)
{ {
int index; int index = 0, index2 = 0;
uint32_t lifetime_seconds; uint32_t lifetime_seconds = 0;
BACNET_OBJECT_ID object_id; uint16_t object_type = 0, object_type2 = 0;
uint32_t object_instance = 0, object_instance2 = 0;
bool status = false; 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 */ /* existing? - match Object ID and Process ID */
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) { for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) {
if (COV_Subscriptions[index].valid) { if (COV_Subscriptions[index].valid) {
@@ -434,24 +415,41 @@ void handler_cov_task(
COV_Subscriptions[index].valid = false; COV_Subscriptions[index].valid = false;
} }
/* handle COV notifications */ /* handle COV notifications */
object_id.type = object_type =
COV_Subscriptions[index].monitoredObjectIdentifier.type; COV_Subscriptions[index].monitoredObjectIdentifier.type;
object_id.instance = object_instance =
COV_Subscriptions[index].monitoredObjectIdentifier.instance; COV_Subscriptions[index].monitoredObjectIdentifier.instance;
switch (object_id.type) { status = Device_Encode_Value_List(
case OBJECT_BINARY_INPUT: object_type,
if (Binary_Input_Change_Of_Value(object_id.instance)) { object_instance,
COV_Subscriptions[index].send_requested = true; &value_list[0]);
Binary_Input_Change_Of_Value_Clear(object_id.instance); if (status) {
} COV_Subscriptions[index].send_requested = true;
break;
default:
break;
} }
if (COV_Subscriptions[index].send_requested) { 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; 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) BACNET_ERROR_CODE * error_code)
{ {
bool status = false; /* return value */ bool status = false; /* return value */
uint16_t object_type = 0;
uint32_t object_instance = 0;
switch (cov_data->monitoredObjectIdentifier.type) { object_type = cov_data->monitoredObjectIdentifier.type;
case OBJECT_BINARY_INPUT: object_instance = cov_data->monitoredObjectIdentifier.instance;
if (Binary_Input_Valid_Instance(cov_data-> status = Device_Valid_Object_Id(object_type, object_instance);
monitoredObjectIdentifier.instance)) { if (status) {
status = status = Device_Value_List_Supported(object_type);
cov_list_subscribe(src, cov_data, error_class, error_code); if (status) {
} else { status = cov_list_subscribe(
*error_class = ERROR_CLASS_OBJECT; src,
*error_code = ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED; cov_data,
} error_class,
break; error_code);
default: } else {
*error_class = ERROR_CLASS_OBJECT; *error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT; *error_code = ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED;
break; }
} else {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
} }
return status; return status;
+1 -1
View File
@@ -96,5 +96,5 @@ extern "C" {
OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count, \ OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count, \
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance, \ Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance, \
Analog_Input_Object_Name, Analog_Input_Read_Property, NULL, \ Analog_Input_Object_Name, Analog_Input_Read_Property, NULL, \
Analog_Input_Property_Lists, NULL, NULL Analog_Input_Property_Lists, NULL, NULL, NULL
#endif #endif
+1 -1
View File
@@ -105,5 +105,5 @@ extern "C" {
Analog_Output_Index_To_Instance, Analog_Output_Valid_Instance, \ Analog_Output_Index_To_Instance, Analog_Output_Valid_Instance, \
Analog_Output_Object_Name, Analog_Output_Read_Property, \ Analog_Output_Object_Name, Analog_Output_Read_Property, \
Analog_Output_Write_Property, Analog_Output_Property_Lists, \ Analog_Output_Write_Property, Analog_Output_Property_Lists, \
NULL, NULL NULL, NULL, NULL
#endif #endif
+1 -1
View File
@@ -82,5 +82,5 @@ extern "C" {
Analog_Value_Index_To_Instance, Analog_Value_Valid_Instance, \ Analog_Value_Index_To_Instance, Analog_Value_Valid_Instance, \
Analog_Value_Object_Name, Analog_Value_Read_Property, \ Analog_Value_Object_Name, Analog_Value_Read_Property, \
Analog_Value_Write_Property, Analog_Value_Property_Lists, NULL, \ Analog_Value_Write_Property, Analog_Value_Property_Lists, NULL, \
NULL NULL, NULL
#endif #endif
+1 -1
View File
@@ -101,5 +101,5 @@ extern "C" {
#define FILE_OBJ_FUNCTIONS \ #define FILE_OBJ_FUNCTIONS \
OBJECT_FILE, bacfile_init, bacfile_count, bacfile_index_to_instance, \ OBJECT_FILE, bacfile_init, bacfile_count, bacfile_index_to_instance, \
bacfile_valid_instance, bacfile_object_name, bacfile_read_property, \ 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 #endif
+37 -30
View File
@@ -183,7 +183,7 @@ bool Binary_Input_Out_Of_Service(
return value; return value;
} }
bool Binary_Input_Change_Of_Value( static bool Binary_Input_Change_Of_Value(
uint32_t object_instance) uint32_t object_instance)
{ {
bool status = false; bool status = false;
@@ -197,7 +197,7 @@ bool Binary_Input_Change_Of_Value(
return status; return status;
} }
void Binary_Input_Change_Of_Value_Clear( static void Binary_Input_Change_Of_Value_Clear(
uint32_t object_instance) uint32_t object_instance)
{ {
unsigned index; unsigned index;
@@ -210,41 +210,48 @@ void Binary_Input_Change_Of_Value_Clear(
return; return;
} }
/* returns true if value has changed */
bool Binary_Input_Encode_Value_List( bool Binary_Input_Encode_Value_List(
uint32_t object_instance, uint32_t object_instance,
BACNET_PROPERTY_VALUE * value_list) BACNET_PROPERTY_VALUE * value_list)
{ {
value_list->propertyIdentifier = PROP_PRESENT_VALUE; bool status = false;
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; if (value_list) {
value_list->propertyIdentifier = PROP_PRESENT_VALUE;
value_list->propertyIdentifier = PROP_STATUS_FLAGS; value_list->propertyArrayIndex = BACNET_ARRAY_ALL;
value_list->propertyArrayIndex = BACNET_ARRAY_ALL; value_list->value.context_specific = false;
value_list->value.context_specific = false; value_list->value.tag = BACNET_APPLICATION_TAG_ENUMERATED;
value_list->value.tag = BACNET_APPLICATION_TAG_BIT_STRING; value_list->value.type.Enumerated =
bitstring_init(&value_list->value.type.Bit_String); Binary_Input_Present_Value(object_instance);
bitstring_set_bit(&value_list->value.type.Bit_String, STATUS_FLAG_IN_ALARM, value_list->priority = BACNET_NO_PRIORITY;
false); value_list = value_list->next;
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; 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( bool Binary_Input_Present_Value_Set(
+1 -5
View File
@@ -83,10 +83,6 @@ extern "C" {
bool Binary_Input_Out_Of_Service( bool Binary_Input_Out_Of_Service(
uint32_t object_instance); 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( bool Binary_Input_Encode_Value_List(
uint32_t object_instance, uint32_t object_instance,
BACNET_PROPERTY_VALUE * value_list); BACNET_PROPERTY_VALUE * value_list);
@@ -118,5 +114,5 @@ extern "C" {
OBJECT_BINARY_INPUT, Binary_Input_Init, Binary_Input_Count, \ OBJECT_BINARY_INPUT, Binary_Input_Init, Binary_Input_Count, \
Binary_Input_Index_To_Instance, Binary_Input_Valid_Instance, \ Binary_Input_Index_To_Instance, Binary_Input_Valid_Instance, \
Binary_Input_Object_Name, Binary_Input_Read_Property, NULL, \ 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 #endif
+1 -1
View File
@@ -114,5 +114,5 @@ extern "C" {
Binary_Output_Index_To_Instance, Binary_Output_Valid_Instance, \ Binary_Output_Index_To_Instance, Binary_Output_Valid_Instance, \
Binary_Output_Object_Name, Binary_Output_Read_Property, \ Binary_Output_Object_Name, Binary_Output_Read_Property, \
Binary_Output_Write_Property, Binary_Output_Property_Lists, \ Binary_Output_Write_Property, Binary_Output_Property_Lists, \
NULL, NULL NULL, NULL, NULL
#endif #endif
+1 -1
View File
@@ -76,5 +76,5 @@ extern "C" {
Binary_Value_Index_To_Instance, Binary_Value_Valid_Instance, \ Binary_Value_Index_To_Instance, Binary_Value_Valid_Instance, \
Binary_Value_Object_Name, Binary_Value_Read_Property, \ Binary_Value_Object_Name, Binary_Value_Read_Property, \
Binary_Value_Write_Property, Binary_Value_Property_Lists, NULL, \ Binary_Value_Write_Property, Binary_Value_Property_Lists, NULL, \
NULL NULL, NULL
#endif #endif
+52
View File
@@ -1359,6 +1359,58 @@ bool Device_Write_Property(
return (status); 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 Device Object.
Initialize the group of object helper functions for any supported Object. Initialize the group of object helper functions for any supported Object.
Initialize each of the Device Object child Object instances. Initialize each of the Device Object child Object instances.
+20 -1
View File
@@ -101,6 +101,17 @@ typedef unsigned (
*object_iterate_function) ( *object_iterate_function) (
unsigned current_index); 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. /** Defines the group of object helper functions for any supported Object.
* @ingroup ObjHelpers * @ingroup ObjHelpers
* Each Object must provide some implementation of each of these helpers * 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; rpm_property_lists_function Object_RPM_List;
rr_info_function Object_RR_Info; rr_info_function Object_RR_Info;
object_iterate_function Object_Iterator; object_iterate_function Object_Iterator;
object_value_list_function Object_Value_List;
} object_functions_t; } object_functions_t;
/* String Lengths - excluding any nul terminator */ /* String Lengths - excluding any nul terminator */
@@ -199,6 +211,13 @@ extern "C" {
BACNET_OBJECT_TYPE object_type, BACNET_OBJECT_TYPE object_type,
struct special_property_list_t *pPropertyList); 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( uint32_t Device_Object_Instance_Number(
void); void);
bool Device_Set_Object_Instance_Number( bool Device_Set_Object_Instance_Number(
@@ -366,7 +385,7 @@ extern "C" {
OBJECT_DEVICE, NULL, Device_Count, Device_Index_To_Instance, \ OBJECT_DEVICE, NULL, Device_Count, Device_Index_To_Instance, \
Device_Valid_Object_Instance_Number, Device_Object_Name, \ Device_Valid_Object_Instance_Number, Device_Object_Name, \
Device_Read_Property_Local, Device_Write_Property_Local, \ Device_Read_Property_Local, Device_Write_Property_Local, \
Device_Property_Lists, DeviceGetRRInfo, NULL Device_Property_Lists, DeviceGetRRInfo, NULL, NULL
/** @defgroup ObjFrmwk Object Framework /** @defgroup ObjFrmwk Object Framework
* The modules in this section describe the BACnet-stack's framework for * The modules in this section describe the BACnet-stack's framework for
* BACnet-defined Objects (Device, Analog Input, etc). There are two submodules * BACnet-defined Objects (Device, Analog Input, etc). There are two submodules
+1 -1
View File
@@ -81,5 +81,5 @@ extern "C" {
Load_Control_Index_To_Instance, Load_Control_Valid_Instance, \ Load_Control_Index_To_Instance, Load_Control_Valid_Instance, \
Load_Control_Object_Name, Load_Control_Read_Property, \ Load_Control_Object_Name, Load_Control_Read_Property, \
Load_Control_Write_Property, Load_Control_Property_Lists, NULL, \ Load_Control_Write_Property, Load_Control_Property_Lists, NULL, \
NULL NULL, NULL
#endif #endif
+1 -1
View File
@@ -75,5 +75,5 @@ extern "C" {
Life_Safety_Point_Valid_Instance, Life_Safety_Point_Object_Name, \ Life_Safety_Point_Valid_Instance, Life_Safety_Point_Object_Name, \
Life_Safety_Point_Read_Property, \ Life_Safety_Point_Read_Property, \
Life_Safety_Point_Write_Property, \ Life_Safety_Point_Write_Property, \
Life_Safety_Point_Property_Lists, NULL, NULL Life_Safety_Point_Property_Lists, NULL, NULL, NULL
#endif #endif
+1 -1
View File
@@ -102,5 +102,5 @@ extern "C" {
Multistate_Input_Valid_Instance, Multistate_Input_Object_Name, \ Multistate_Input_Valid_Instance, Multistate_Input_Object_Name, \
Multistate_Input_Read_Property, \ Multistate_Input_Read_Property, \
Multistate_Input_Write_Property, \ Multistate_Input_Write_Property, \
Multistate_Input_Property_Lists, NULL, NULL Multistate_Input_Property_Lists, NULL, NULL, NULL
#endif #endif
+1 -1
View File
@@ -77,5 +77,5 @@ extern "C" {
Multistate_Output_Valid_Instance, Multistate_Output_Object_Name, \ Multistate_Output_Valid_Instance, Multistate_Output_Object_Name, \
Multistate_Output_Read_Property, \ Multistate_Output_Read_Property, \
Multistate_Output_Write_Property, \ Multistate_Output_Write_Property, \
Multistate_Output_Property_Lists, NULL, NULL Multistate_Output_Property_Lists, NULL, NULL, NULL
#endif #endif
+1 -1
View File
@@ -202,5 +202,5 @@ extern "C" {
Trend_Log_Index_To_Instance, Trend_Log_Valid_Instance, \ Trend_Log_Index_To_Instance, Trend_Log_Valid_Instance, \
Trend_Log_Object_Name, Trend_Log_Read_Property, \ Trend_Log_Object_Name, Trend_Log_Read_Property, \
Trend_Log_Write_Property, Trend_Log_Property_Lists, \ Trend_Log_Write_Property, Trend_Log_Property_Lists, \
TrendLogGetRRInfo, NULL TrendLogGetRRInfo, NULL, NULL
#endif #endif