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:
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user