Feature/add create object service (#476)

Added BACnet CreateObject and DeleteObject services

* refactored codec for BACnetPropertyValue into bacapp module
* added unit tests for BACnetPropertyValue
* refactored COV and Events to use BACnetPropertyValue codec API
* added unit tests for COV
* added overrun safe decoders for tag numbers and boolean context
* added unit tests and codecs for CreateObject and DeleteObject services
* added APDU service handers and senders for CreateObject and DeleteObject services
* added command line apps bacco and bacdo for CreateObject and DeleteObject services
* added CreateObject and DeleteObject service handling in example server app and device object
* added new BACnetRejectReason, Error Class, and BACnetAbortReason enumerations and conversions

---------

Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
Steve Karg
2023-08-28 13:02:35 -05:00
committed by GitHub
parent 8184afea12
commit f61f4300be
60 changed files with 3946 additions and 942 deletions
+18 -5
View File
@@ -1196,15 +1196,24 @@ void Analog_Output_Write_Present_Value_Callback_Set(
/**
* @brief Creates a Analog Value object
* @param object_instance - object-instance number of the object
* @return true if the object-instance was created
* @return the object-instance that was created, or BACNET_MAX_INSTANCE
*/
bool Analog_Output_Create(uint32_t object_instance)
uint32_t Analog_Output_Create(uint32_t object_instance)
{
bool status = false;
struct object_data *pObject = NULL;
int index = 0;
unsigned priority = 0;
if (object_instance > BACNET_MAX_INSTANCE) {
return BACNET_MAX_INSTANCE;
} else if (object_instance == BACNET_MAX_INSTANCE) {
/* wildcard instance */
/* the Object_Identifier property of the newly created object
shall be initialized to a value that is unique within the
responding BACnet-user device. The method used to generate
the object identifier is a local matter.*/
object_instance = Keylist_Next_Empty_Key(Object_List, 1);
}
pObject = Keylist_Data(Object_List, object_instance);
if (!pObject) {
pObject = calloc(1, sizeof(struct object_data));
@@ -1227,13 +1236,17 @@ bool Analog_Output_Create(uint32_t object_instance)
/* add to list */
index = Keylist_Data_Add(Object_List, object_instance, pObject);
if (index >= 0) {
status = true;
Device_Inc_Database_Revision();
} else {
free(pObject);
return BACNET_MAX_INSTANCE;
}
} else {
return BACNET_MAX_INSTANCE;
}
}
return status;
return object_instance;
}
/**
+1 -1
View File
@@ -191,7 +191,7 @@ extern "C" {
BACNET_WRITE_PROPERTY_DATA * wp_data);
BACNET_STACK_EXPORT
bool Analog_Output_Create(
uint32_t Analog_Output_Create(
uint32_t object_instance);
BACNET_STACK_EXPORT
bool Analog_Output_Delete(
+19 -6
View File
@@ -977,16 +977,25 @@ bool bacfile_read_ack_record_data(
/**
* @brief Creates an object
* @brief Creates a File object
* @param object_instance - object-instance number of the object
* @return true if the object-instance was created
* @return the object-instance that was created, or BACNET_MAX_INSTANCE
*/
bool bacfile_create(uint32_t object_instance)
uint32_t bacfile_create(uint32_t object_instance)
{
bool status = false;
struct object_data *pObject = NULL;
int index = 0;
if (object_instance > BACNET_MAX_INSTANCE) {
return BACNET_MAX_INSTANCE;
} else if (object_instance == BACNET_MAX_INSTANCE) {
/* wildcard instance */
/* the Object_Identifier property of the newly created object
shall be initialized to a value that is unique within the
responding BACnet-user device. The method used to generate
the object identifier is a local matter.*/
object_instance = Keylist_Next_Empty_Key(Object_List, 1);
}
pObject = Keylist_Data(Object_List, object_instance);
if (!pObject) {
pObject = calloc(1, sizeof(struct object_data));
@@ -1002,13 +1011,17 @@ bool bacfile_create(uint32_t object_instance)
/* add to list */
index = Keylist_Data_Add(Object_List, object_instance, pObject);
if (index >= 0) {
status = true;
Device_Inc_Database_Revision();
} else {
free(pObject);
return BACNET_MAX_INSTANCE;
}
} else {
return BACNET_MAX_INSTANCE;
}
}
return status;
return object_instance;
}
/**
+1 -1
View File
@@ -175,7 +175,7 @@ extern "C" {
uint32_t buffer_size);
BACNET_STACK_EXPORT
bool bacfile_create(
uint32_t bacfile_create(
uint32_t object_instance);
BACNET_STACK_EXPORT
bool bacfile_delete(
+19 -6
View File
@@ -1170,16 +1170,25 @@ void Binary_Output_Write_Present_Value_Callback_Set(
}
/**
* @brief Determines a object write-enabled flag state
* @brief Creates a Binary Output object
* @param object_instance - object-instance number of the object
* @return write-enabled status flag
* @return the object-instance that was created, or BACNET_MAX_INSTANCE
*/
bool Binary_Output_Create(uint32_t object_instance)
uint32_t Binary_Output_Create(uint32_t object_instance)
{
bool status = false;
struct object_data *pObject = NULL;
int index = 0;
if (object_instance > BACNET_MAX_INSTANCE) {
return BACNET_MAX_INSTANCE;
} else if (object_instance == BACNET_MAX_INSTANCE) {
/* wildcard instance */
/* the Object_Identifier property of the newly created object
shall be initialized to a value that is unique within the
responding BACnet-user device. The method used to generate
the object identifier is a local matter.*/
object_instance = Keylist_Next_Empty_Key(Object_List, 1);
}
pObject = Keylist_Data(Object_List, object_instance);
if (!pObject) {
pObject = calloc(1, sizeof(struct object_data));
@@ -1194,13 +1203,17 @@ bool Binary_Output_Create(uint32_t object_instance)
/* add to list */
index = Keylist_Data_Add(Object_List, object_instance, pObject);
if (index >= 0) {
status = true;
Device_Inc_Database_Revision();
} else {
free(pObject);
return BACNET_MAX_INSTANCE;
}
} else {
return BACNET_MAX_INSTANCE;
}
}
return status;
return object_instance;
}
/**
+1 -1
View File
@@ -228,7 +228,7 @@ extern "C" {
BACNET_WRITE_PROPERTY_DATA * wp_data);
BACNET_STACK_EXPORT
bool Binary_Output_Create(
uint32_t Binary_Output_Create(
uint32_t object_instance);
BACNET_STACK_EXPORT
bool Binary_Output_Delete(
@@ -117,7 +117,8 @@ static object_functions_t Object_Table[] = {
Device_Property_Lists, NULL /* ReadRangeInfo */, NULL /* Iterator */,
NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */,
NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
#if (BACNET_PROTOCOL_REVISION >= 17)
{ OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count,
Network_Port_Index_To_Instance, Network_Port_Valid_Instance,
@@ -125,7 +126,8 @@ static object_functions_t Object_Table[] = {
Network_Port_Write_Property, Network_Port_Property_Lists,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
#endif
{ MAX_BACNET_OBJECT_TYPE, NULL /* Init */, NULL /* Count */,
NULL /* Index_To_Instance */, NULL /* Valid_Instance */,
@@ -134,7 +136,8 @@ static object_functions_t Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */,
NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ }
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
};
/** Glue function to let the Device object, when called by a handler,
+19 -5
View File
@@ -827,15 +827,25 @@ void Color_Write_Disable(uint32_t object_instance)
}
/**
* Creates a Color object
* @brief Creates a Color object
* @param object_instance - object-instance number of the object
* @return the object-instance that was created, or BACNET_MAX_INSTANCE
*/
bool Color_Create(uint32_t object_instance)
uint32_t Color_Create(uint32_t object_instance)
{
bool status = false;
struct object_data *pObject = NULL;
int index = 0;
if (object_instance > BACNET_MAX_INSTANCE) {
return BACNET_MAX_INSTANCE;
} else if (object_instance == BACNET_MAX_INSTANCE) {
/* wildcard instance */
/* the Object_Identifier property of the newly created object
shall be initialized to a value that is unique within the
responding BACnet-user device. The method used to generate
the object identifier is a local matter.*/
object_instance = Keylist_Next_Empty_Key(Object_List, 1);
}
pObject = Keylist_Data(Object_List, object_instance);
if (!pObject) {
pObject = calloc(1, sizeof(struct object_data));
@@ -856,13 +866,17 @@ bool Color_Create(uint32_t object_instance)
/* add to list */
index = Keylist_Data_Add(Object_List, object_instance, pObject);
if (index >= 0) {
status = true;
Device_Inc_Database_Revision();
} else {
free(pObject);
return BACNET_MAX_INSTANCE;
}
} else {
return BACNET_MAX_INSTANCE;
}
}
return status;
return object_instance;
}
/**
+1 -1
View File
@@ -119,7 +119,7 @@ BACNET_STACK_EXPORT
void Color_Write_Disable(uint32_t instance);
BACNET_STACK_EXPORT
bool Color_Create(uint32_t object_instance);
uint32_t Color_Create(uint32_t object_instance);
BACNET_STACK_EXPORT
bool Color_Delete(uint32_t object_instance);
BACNET_STACK_EXPORT
+19 -5
View File
@@ -1021,15 +1021,25 @@ void Color_Temperature_Write_Disable(uint32_t object_instance)
}
/**
* Creates a Color object
* @brief Creates a Color Temperature object
* @param object_instance - object-instance number of the object
* @return the object-instance that was created, or BACNET_MAX_INSTANCE
*/
bool Color_Temperature_Create(uint32_t object_instance)
uint32_t Color_Temperature_Create(uint32_t object_instance)
{
bool status = false;
struct object_data *pObject = NULL;
int index = 0;
if (object_instance > BACNET_MAX_INSTANCE) {
return BACNET_MAX_INSTANCE;
} else if (object_instance == BACNET_MAX_INSTANCE) {
/* wildcard instance */
/* the Object_Identifier property of the newly created object
shall be initialized to a value that is unique within the
responding BACnet-user device. The method used to generate
the object identifier is a local matter.*/
object_instance = Keylist_Next_Empty_Key(Object_List, 1);
}
pObject = Keylist_Data(Object_List, object_instance);
if (!pObject) {
pObject = calloc(1, sizeof(struct object_data));
@@ -1051,13 +1061,17 @@ bool Color_Temperature_Create(uint32_t object_instance)
/* add to list */
index = Keylist_Data_Add(Object_List, object_instance, pObject);
if (index >= 0) {
status = true;
Device_Inc_Database_Revision();
} else {
free(pObject);
return BACNET_MAX_INSTANCE;
}
} else {
return BACNET_MAX_INSTANCE;
}
}
return status;
return object_instance;
}
/**
+1 -1
View File
@@ -151,7 +151,7 @@ BACNET_STACK_EXPORT
void Color_Temperature_Write_Disable(uint32_t instance);
BACNET_STACK_EXPORT
bool Color_Temperature_Create(uint32_t object_instance);
uint32_t Color_Temperature_Create(uint32_t object_instance);
BACNET_STACK_EXPORT
bool Color_Temperature_Delete(uint32_t object_instance);
BACNET_STACK_EXPORT
+165 -39
View File
@@ -98,7 +98,8 @@ static object_functions_t My_Object_Table[] = {
Device_Property_Lists, DeviceGetRRInfo, NULL /* Iterator */,
NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */,
NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */,
NULL /* Remove_List_Element */ },
NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
#if (BACNET_PROTOCOL_REVISION >= 17)
{ OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count,
Network_Port_Index_To_Instance, Network_Port_Valid_Instance,
@@ -106,7 +107,8 @@ static object_functions_t My_Object_Table[] = {
Network_Port_Write_Property, Network_Port_Property_Lists,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
#endif
{ OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count,
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance,
@@ -115,14 +117,16 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */,
Analog_Input_Encode_Value_List, Analog_Input_Change_Of_Value,
Analog_Input_Change_Of_Value_Clear, Analog_Input_Intrinsic_Reporting,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
{ OBJECT_ANALOG_OUTPUT, Analog_Output_Init, Analog_Output_Count,
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 /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Analog_Output_Create, Analog_Output_Delete},
{ OBJECT_ANALOG_VALUE, Analog_Value_Init, Analog_Value_Count,
Analog_Value_Index_To_Instance, Analog_Value_Valid_Instance,
Analog_Value_Object_Name, Analog_Value_Read_Property,
@@ -130,7 +134,8 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */,
Analog_Value_Encode_Value_List, Analog_Value_Change_Of_Value,
Analog_Value_Change_Of_Value_Clear, Analog_Value_Intrinsic_Reporting,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
{ 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,
@@ -138,21 +143,24 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */,
Binary_Input_Encode_Value_List, Binary_Input_Change_Of_Value,
Binary_Input_Change_Of_Value_Clear, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
{ OBJECT_BINARY_OUTPUT, Binary_Output_Init, Binary_Output_Count,
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 /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Binary_Output_Create, Binary_Output_Delete},
{ OBJECT_BINARY_VALUE, Binary_Value_Init, Binary_Value_Count,
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 /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
{ OBJECT_CHARACTERSTRING_VALUE, CharacterString_Value_Init,
CharacterString_Value_Count, CharacterString_Value_Index_To_Instance,
CharacterString_Value_Valid_Instance, CharacterString_Value_Object_Name,
@@ -163,20 +171,23 @@ static object_functions_t My_Object_Table[] = {
CharacterString_Value_Change_Of_Value,
CharacterString_Value_Change_Of_Value_Clear,
NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */,
NULL /* Remove_List_Element */ },
NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
{ 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,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
{ OBJECT_INTEGER_VALUE, Integer_Value_Init, Integer_Value_Count,
Integer_Value_Index_To_Instance, Integer_Value_Valid_Instance,
Integer_Value_Object_Name, Integer_Value_Read_Property,
Integer_Value_Write_Property, Integer_Value_Property_Lists,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
#if defined(INTRINSIC_REPORTING)
{ OBJECT_NOTIFICATION_CLASS, Notification_Class_Init,
Notification_Class_Count, Notification_Class_Index_To_Instance,
@@ -186,7 +197,8 @@ static object_functions_t My_Object_Table[] = {
NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */,
NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
Notification_Class_Add_List_Element,
Notification_Class_Remove_List_Element },
Notification_Class_Remove_List_Element,
NULL /* Create */, NULL /* Delete */ },
#endif
{ OBJECT_LIFE_SAFETY_POINT, Life_Safety_Point_Init, Life_Safety_Point_Count,
Life_Safety_Point_Index_To_Instance, Life_Safety_Point_Valid_Instance,
@@ -194,21 +206,24 @@ static object_functions_t My_Object_Table[] = {
Life_Safety_Point_Write_Property, Life_Safety_Point_Property_Lists,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
{ OBJECT_LOAD_CONTROL, Load_Control_Init, Load_Control_Count,
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 /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
{ OBJECT_MULTI_STATE_INPUT, Multistate_Input_Init, Multistate_Input_Count,
Multistate_Input_Index_To_Instance, Multistate_Input_Valid_Instance,
Multistate_Input_Object_Name, Multistate_Input_Read_Property,
Multistate_Input_Write_Property, Multistate_Input_Property_Lists,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
{ OBJECT_MULTI_STATE_OUTPUT, Multistate_Output_Init,
Multistate_Output_Count, Multistate_Output_Index_To_Instance,
Multistate_Output_Valid_Instance, Multistate_Output_Object_Name,
@@ -216,7 +231,8 @@ static object_functions_t My_Object_Table[] = {
Multistate_Output_Property_Lists, NULL /* ReadRangeInfo */,
NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */,
NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Multistate_Output_Create, Multistate_Output_Delete},
{ OBJECT_MULTI_STATE_VALUE, Multistate_Value_Init, Multistate_Value_Count,
Multistate_Value_Index_To_Instance, Multistate_Value_Valid_Instance,
Multistate_Value_Object_Name, Multistate_Value_Read_Property,
@@ -224,14 +240,16 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */,
Multistate_Value_Encode_Value_List, Multistate_Value_Change_Of_Value,
Multistate_Value_Change_Of_Value_Clear, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
{ OBJECT_TRENDLOG, Trend_Log_Init, Trend_Log_Count,
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 /* Iterator */, NULL /* Value_Lists */, NULL /* COV */,
NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
#if (BACNET_PROTOCOL_REVISION >= 14)
{ OBJECT_LIGHTING_OUTPUT, Lighting_Output_Init, Lighting_Output_Count,
Lighting_Output_Index_To_Instance, Lighting_Output_Valid_Instance,
@@ -239,13 +257,15 @@ static object_functions_t My_Object_Table[] = {
Lighting_Output_Write_Property, Lighting_Output_Property_Lists,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
{ OBJECT_CHANNEL, Channel_Init, Channel_Count, Channel_Index_To_Instance,
Channel_Valid_Instance, Channel_Object_Name, Channel_Read_Property,
Channel_Write_Property, Channel_Property_Lists,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
#endif
#if (BACNET_PROTOCOL_REVISION >= 24)
{ OBJECT_COLOR, Color_Init, Color_Count, Color_Index_To_Instance,
@@ -253,14 +273,16 @@ static object_functions_t My_Object_Table[] = {
Color_Write_Property, Color_Property_Lists, NULL /* ReadRangeInfo */,
NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */,
NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Color_Create, Color_Delete},
{ OBJECT_COLOR_TEMPERATURE, Color_Temperature_Init, Color_Temperature_Count,
Color_Temperature_Index_To_Instance, Color_Temperature_Valid_Instance,
Color_Temperature_Object_Name, Color_Temperature_Read_Property,
Color_Temperature_Write_Property, Color_Temperature_Property_Lists,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Color_Temperature_Create, Color_Temperature_Delete},
#endif
#if defined(BACFILE)
{ OBJECT_FILE, bacfile_init, bacfile_count, bacfile_index_to_instance,
@@ -268,7 +290,8 @@ static object_functions_t My_Object_Table[] = {
bacfile_write_property, BACfile_Property_Lists,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
bacfile_create, bacfile_delete},
#endif
{ OBJECT_OCTETSTRING_VALUE, OctetString_Value_Init, OctetString_Value_Count,
OctetString_Value_Index_To_Instance, OctetString_Value_Valid_Instance,
@@ -276,7 +299,8 @@ static object_functions_t My_Object_Table[] = {
OctetString_Value_Write_Property, OctetString_Value_Property_Lists,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
{ OBJECT_POSITIVE_INTEGER_VALUE, PositiveInteger_Value_Init,
PositiveInteger_Value_Count, PositiveInteger_Value_Index_To_Instance,
PositiveInteger_Value_Valid_Instance, PositiveInteger_Value_Object_Name,
@@ -285,28 +309,32 @@ static object_functions_t My_Object_Table[] = {
PositiveInteger_Value_Property_Lists, NULL /* ReadRangeInfo */,
NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */,
NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
{ OBJECT_SCHEDULE, Schedule_Init, Schedule_Count,
Schedule_Index_To_Instance, Schedule_Valid_Instance,
Schedule_Object_Name, Schedule_Read_Property, Schedule_Write_Property,
Schedule_Property_Lists, NULL /* ReadRangeInfo */, NULL /* Iterator */,
NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */,
NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */,
NULL /* Remove_List_Element */ },
NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
{ OBJECT_ACCUMULATOR, Accumulator_Init, Accumulator_Count,
Accumulator_Index_To_Instance, Accumulator_Valid_Instance,
Accumulator_Object_Name, Accumulator_Read_Property,
Accumulator_Write_Property, Accumulator_Property_Lists,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ },
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
{ MAX_BACNET_OBJECT_TYPE, NULL /* Init */, NULL /* Count */,
NULL /* Index_To_Instance */, NULL /* Valid_Instance */,
NULL /* Object_Name */, NULL /* Read_Property */,
NULL /* Write_Property */, NULL /* Property_Lists */,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */ }
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ },
};
/** Glue function to let the Device object, when called by a handler,
@@ -1892,6 +1920,108 @@ void Device_COV_Clear(BACNET_OBJECT_TYPE object_type, uint32_t object_instance)
}
}
/**
* @brief Creates a child object, if supported
* @ingroup ObjHelpers
* @param data - CreateObject data, including error codes if failures
* @return true if object has been created
*/
bool Device_Create_Object(
BACNET_CREATE_OBJECT_DATA *data)
{
bool status = false;
struct object_functions *pObject = NULL;
uint32_t object_instance;
pObject = Device_Objects_Find_Functions(data->object_type);
if (pObject != NULL) {
if (!pObject->Object_Create) {
/* The device supports the object type and may have
sufficient space, but does not support the creation of the
object for some other reason.*/
data->error_class = ERROR_CLASS_OBJECT;
data->error_code = ERROR_CODE_DYNAMIC_CREATION_NOT_SUPPORTED;
} else if (pObject->Object_Valid_Instance &&
pObject->Object_Valid_Instance(data->object_instance)) {
/* The object being created already exists */
data->error_class = ERROR_CLASS_OBJECT;
data->error_code = ERROR_CODE_OBJECT_IDENTIFIER_ALREADY_EXISTS;
} else {
if (data->list_of_initial_values) {
/* FIXME: add support for writing to list of initial values */
/* A property specified by the Property_Identifier in the
List of Initial Values does not support initialization
during the CreateObject service. */
data->first_failed_element_number = 1;
data->error_class = ERROR_CLASS_PROPERTY;
data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
/* and the object shall not be created */
} else {
object_instance = pObject->Object_Create(data->object_instance);
if (object_instance == BACNET_MAX_INSTANCE) {
/* The device cannot allocate the space needed
for the new object.*/
data->error_class = ERROR_CLASS_RESOURCES;
data->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
} else {
/* required by ACK */
data->object_instance = object_instance;
status = true;
}
}
}
} else {
/* The device does not support the specified object type. */
data->error_class = ERROR_CLASS_OBJECT;
data->error_code = ERROR_CODE_UNSUPPORTED_OBJECT_TYPE;
}
return status;
}
/**
* @brief Deletes a child object, if supported
* @ingroup ObjHelpers
* @param data - DeleteObject data, including error codes if failures
* @return true if object has been deleted
*/
bool Device_Delete_Object(
BACNET_DELETE_OBJECT_DATA *data)
{
bool status = false;
struct object_functions *pObject = NULL;
pObject = Device_Objects_Find_Functions(data->object_type);
if (pObject != NULL) {
if (!pObject->Object_Delete) {
/* The device supports the object type
but does not support the deletion of the
object for some reason.*/
data->error_class = ERROR_CLASS_OBJECT;
data->error_code = ERROR_CODE_OBJECT_DELETION_NOT_PERMITTED;
} else if (pObject->Object_Valid_Instance &&
pObject->Object_Valid_Instance(data->object_instance)) {
/* The object being deleted must already exist */
status = pObject->Object_Delete(data->object_instance);
if (!status) {
/* The object exists but cannot be deleted. */
data->error_class = ERROR_CLASS_OBJECT;
data->error_code = ERROR_CODE_OBJECT_DELETION_NOT_PERMITTED;
}
} else {
/* The object to be deleted does not exist. */
data->error_class = ERROR_CLASS_OBJECT;
data->error_code = ERROR_CODE_UNKNOWN_OBJECT;
}
} else {
/* The device does not support the specified object type. */
data->error_class = ERROR_CLASS_OBJECT;
data->error_code = ERROR_CODE_UNSUPPORTED_OBJECT_TYPE;
}
return status;
}
#if defined(INTRINSIC_REPORTING)
void Device_local_reporting(void)
{
@@ -1966,17 +2096,13 @@ void Device_Init(object_functions_t *object_table)
pObject++;
}
/* create some dynamically created objects as examples */
Analog_Output_Create(1);
Binary_Output_Create(1);
Multistate_Output_Create(1);
#if (BACNET_PROTOCOL_REVISION >= 24)
Color_Create(1);
Color_Temperature_Create(1);
#endif
#if defined(BACFILE)
bacfile_create(1);
bacfile_pathname_set(1, "temp_1.txt");
#endif
pObject = Object_Table;
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
if (pObject->Object_Create) {
pObject->Object_Create(BACNET_MAX_INSTANCE);
}
pObject++;
}
}
bool DeviceGetRRInfo(BACNET_READ_RANGE_DATA *pRequest, /* Info on the request */
+11
View File
@@ -34,6 +34,8 @@
#include "bacnet/bacnet_stack_exports.h"
#include "bacnet/bacdef.h"
#include "bacnet/bacenum.h"
#include "bacnet/create_object.h"
#include "bacnet/delete_object.h"
#include "bacnet/list_element.h"
#include "bacnet/wp.h"
#include "bacnet/rd.h"
@@ -168,6 +170,8 @@ typedef struct object_functions {
object_intrinsic_reporting_function Object_Intrinsic_Reporting;
list_element_function Object_Add_List_Element;
list_element_function Object_Remove_List_Element;
create_object_function Object_Create;
delete_object_function Object_Delete;
} object_functions_t;
/* String Lengths - excluding any nul terminator */
@@ -316,6 +320,13 @@ extern "C" {
BACNET_ARRAY_INDEX array_index,
uint8_t *apdu);
BACNET_STACK_EXPORT
bool Device_Create_Object(
BACNET_CREATE_OBJECT_DATA *data);
BACNET_STACK_EXPORT
bool Device_Delete_Object(
BACNET_DELETE_OBJECT_DATA *data);
BACNET_STACK_EXPORT
unsigned Device_Count(
void);
+18 -5
View File
@@ -1152,15 +1152,24 @@ void Multistate_Output_Write_Present_Value_Callback_Set(
/**
* @brief Creates a new object and adds it to the object list
* @param object_instance - object-instance number of the object
* @return true if the object is created
* @return the object-instance that was created, or BACNET_MAX_INSTANCE
*/
bool Multistate_Output_Create(uint32_t object_instance)
uint32_t Multistate_Output_Create(uint32_t object_instance)
{
bool status = false;
struct object_data *pObject = NULL;
int index = 0;
unsigned priority = 0;
if (object_instance > BACNET_MAX_INSTANCE) {
return BACNET_MAX_INSTANCE;
} else if (object_instance == BACNET_MAX_INSTANCE) {
/* wildcard instance */
/* the Object_Identifier property of the newly created object
shall be initialized to a value that is unique within the
responding BACnet-user device. The method used to generate
the object identifier is a local matter.*/
object_instance = Keylist_Next_Empty_Key(Object_List, 1);
}
pObject = Keylist_Data(Object_List, object_instance);
if (!pObject) {
pObject = calloc(1, sizeof(struct object_data));
@@ -1178,13 +1187,17 @@ bool Multistate_Output_Create(uint32_t object_instance)
/* add to list */
index = Keylist_Data_Add(Object_List, object_instance, pObject);
if (index >= 0) {
status = true;
Device_Inc_Database_Revision();
} else {
free(pObject);
return BACNET_MAX_INSTANCE;
}
} else {
return BACNET_MAX_INSTANCE;
}
}
return status;
return object_instance;
}
/**
+1 -1
View File
@@ -174,7 +174,7 @@ extern "C" {
uint32_t value);
BACNET_STACK_EXPORT
bool Multistate_Output_Create(
uint32_t Multistate_Output_Create(
uint32_t object_instance);
BACNET_STACK_EXPORT
bool Multistate_Output_Delete(