From 3a0878a25462d8446e7c10f7d4534bbdef995d24 Mon Sep 17 00:00:00 2001 From: Steve Karg Date: Wed, 21 Jan 2026 10:02:21 -0600 Subject: [PATCH] Add API for writable object property lists (#1206) Added a new API for writable property lists across all the basic example object types, preparing for the introduction of a Writable_Property_List property in every object in a future BACnet standard revision. The lists can be used by backup and restore feature to automatically choose the object property values in the backup that can be restored via internal WriteProperty directly from BACnet CreateObject services with List of Initial Values. Updated existing device object examples to include these writable property lists. --- CHANGELOG.md | 8 + apps/blinkt/device.c | 91 +++++- apps/gateway/Makefile | 33 +-- apps/piface/configure.sh | 2 +- apps/piface/device.c | 60 +++- apps/server-mini/Makefile | 31 +- apps/server-mini/main.c | 16 +- ports/rx62n/device.c | 5 +- src/bacnet/basic/object/acc.c | 20 ++ src/bacnet/basic/object/acc.h | 3 + src/bacnet/basic/object/access_credential.c | 23 ++ src/bacnet/basic/object/access_credential.h | 3 + src/bacnet/basic/object/access_door.c | 25 ++ src/bacnet/basic/object/access_door.h | 3 + src/bacnet/basic/object/access_point.c | 24 ++ src/bacnet/basic/object/access_point.h | 4 + src/bacnet/basic/object/access_rights.c | 44 ++- src/bacnet/basic/object/access_rights.h | 8 +- src/bacnet/basic/object/access_user.c | 24 ++ src/bacnet/basic/object/access_user.h | 4 + src/bacnet/basic/object/access_zone.c | 25 ++ src/bacnet/basic/object/access_zone.h | 4 + src/bacnet/basic/object/ai.c | 23 ++ src/bacnet/basic/object/ai.h | 3 + src/bacnet/basic/object/ao.c | 24 ++ src/bacnet/basic/object/ao.h | 3 + src/bacnet/basic/object/auditlog.c | 22 ++ src/bacnet/basic/object/auditlog.h | 3 + src/bacnet/basic/object/av.c | 65 ++++- src/bacnet/basic/object/av.h | 4 + src/bacnet/basic/object/bacfile.c | 23 ++ src/bacnet/basic/object/bacfile.h | 3 + src/bacnet/basic/object/bi.c | 23 ++ src/bacnet/basic/object/bi.h | 3 + src/bacnet/basic/object/bitstring_value.c | 23 ++ src/bacnet/basic/object/bitstring_value.h | 3 + src/bacnet/basic/object/blo.c | 23 ++ src/bacnet/basic/object/blo.h | 4 + src/bacnet/basic/object/bo.c | 24 ++ src/bacnet/basic/object/bo.h | 3 + src/bacnet/basic/object/bv.c | 48 +++- src/bacnet/basic/object/bv.h | 3 + src/bacnet/basic/object/calendar.c | 29 +- src/bacnet/basic/object/calendar.h | 4 + src/bacnet/basic/object/channel.c | 28 ++ src/bacnet/basic/object/channel.h | 4 + .../basic/object/client/device-client.c | 60 +++- src/bacnet/basic/object/color_object.c | 24 ++ src/bacnet/basic/object/color_object.h | 4 + src/bacnet/basic/object/color_temperature.c | 39 ++- src/bacnet/basic/object/color_temperature.h | 4 + src/bacnet/basic/object/command.c | 29 +- src/bacnet/basic/object/command.h | 3 + .../basic/object/credential_data_input.c | 54 +++- .../basic/object/credential_data_input.h | 4 + src/bacnet/basic/object/csv.c | 24 ++ src/bacnet/basic/object/csv.h | 3 + src/bacnet/basic/object/device.c | 264 +++++++++++++++--- src/bacnet/basic/object/device.h | 9 + src/bacnet/basic/object/iv.c | 23 ++ src/bacnet/basic/object/iv.h | 4 + src/bacnet/basic/object/lc.c | 43 ++- src/bacnet/basic/object/lc.h | 3 + src/bacnet/basic/object/lo.c | 32 +++ src/bacnet/basic/object/lo.h | 4 + src/bacnet/basic/object/loop.c | 44 +++ src/bacnet/basic/object/loop.h | 4 + src/bacnet/basic/object/lsp.c | 24 ++ src/bacnet/basic/object/lsp.h | 4 + src/bacnet/basic/object/lsz.c | 29 ++ src/bacnet/basic/object/lsz.h | 4 + src/bacnet/basic/object/ms-input.c | 23 ++ src/bacnet/basic/object/ms-input.h | 3 + src/bacnet/basic/object/mso.c | 23 ++ src/bacnet/basic/object/mso.h | 4 + src/bacnet/basic/object/msv.c | 23 ++ src/bacnet/basic/object/msv.h | 3 + src/bacnet/basic/object/nc.c | 23 ++ src/bacnet/basic/object/nc.h | 3 + src/bacnet/basic/object/netport.c | 83 ++++++ src/bacnet/basic/object/netport.h | 3 + src/bacnet/basic/object/osv.c | 58 ++-- src/bacnet/basic/object/osv.h | 4 + src/bacnet/basic/object/piv.c | 57 +++- src/bacnet/basic/object/piv.h | 4 + src/bacnet/basic/object/program.c | 23 ++ src/bacnet/basic/object/program.h | 4 + src/bacnet/basic/object/schedule.c | 41 +++ src/bacnet/basic/object/schedule.h | 3 + src/bacnet/basic/object/structured_view.c | 23 ++ src/bacnet/basic/object/structured_view.h | 4 + src/bacnet/basic/object/time_value.c | 23 ++ src/bacnet/basic/object/time_value.h | 4 + src/bacnet/basic/object/timer.c | 32 +++ src/bacnet/basic/object/timer.h | 4 + src/bacnet/basic/object/trendlog.c | 44 +++ src/bacnet/basic/object/trendlog.h | 3 + src/bacnet/basic/server/bacnet_device.c | 161 +++++++++-- src/bacnet/wp.h | 8 + .../bacnet/basic/object/device/CMakeLists.txt | 13 + 100 files changed, 2084 insertions(+), 214 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 405d022a..1cbe7f58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,14 @@ The git repositories are hosted at the following sites: ### Added +* Added a new API for writable property lists across all the basic example + object types, preparing for the introduction of a Writable_Property_List + property in every object in a future BACnet standard revision. + The lists can be used by backup and restore feature to automatically + choose the object property values in the backup that can be restored + via internal WriteProperty directly from BACnet CreateObject services with + List of Initial Values. Updated existing device objects to include + these writable property lists. (#1206) * Added post-write notifications for channel, timer, and loop objects. (#1204) * Added device WriteProperty callbacks for Timer object in example device objects implementations. (#1203) diff --git a/apps/blinkt/device.c b/apps/blinkt/device.c index cb7caaa4..cd211e85 100644 --- a/apps/blinkt/device.c +++ b/apps/blinkt/device.c @@ -63,7 +63,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, - NULL /* Timer */ }, + NULL /* Timer */, + Device_Writable_Property_List }, #if (BACNET_PROTOCOL_REVISION >= 17) { OBJECT_NETWORK_PORT, Network_Port_Init, @@ -84,7 +85,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, - NULL /* Timer */ }, + NULL /* Timer */, + Network_Port_Writable_Property_List }, #endif { OBJECT_LOAD_CONTROL, Load_Control_Init, @@ -105,7 +107,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, - NULL /* Timer */ }, + NULL /* Timer */, + Load_Control_Writable_Property_List }, #if (BACNET_PROTOCOL_REVISION >= 14) { OBJECT_LIGHTING_OUTPUT, Lighting_Output_Init, @@ -126,7 +129,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Lighting_Output_Create, Lighting_Output_Delete, - Lighting_Output_Timer }, + Lighting_Output_Timer, + Lighting_Output_Writable_Property_List }, { OBJECT_CHANNEL, Channel_Init, Channel_Count, @@ -146,7 +150,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Channel_Create, Channel_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + Channel_Writable_Property_List }, #endif #if (BACNET_PROTOCOL_REVISION >= 24) { OBJECT_COLOR, @@ -168,7 +173,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Color_Create, Color_Delete, - Color_Timer }, + Color_Timer, + Color_Writable_Property_List }, { OBJECT_COLOR_TEMPERATURE, Color_Temperature_Init, Color_Temperature_Count, @@ -188,7 +194,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Color_Temperature_Create, Color_Temperature_Delete, - Color_Temperature_Timer }, + Color_Temperature_Timer, + Color_Temperature_Writable_Property_List }, #endif { MAX_BACNET_OBJECT_TYPE, NULL /* Init */, @@ -209,7 +216,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, - NULL /* Timer */ } + NULL /* Timer */, + NULL /* Writable_Property_List */ } }; /** Glue function to let the Device object, when called by a handler, @@ -336,6 +344,31 @@ bool Device_Objects_Property_List_Member( return found; } +/** + * @brief Get the Writeable Property List for an object type + * @param object_type - object type of the object + * @param object_instance - object-instance number of the object + * @param properties - pointer to the list of writable properties + * @return The number of properties in the writable property list + */ +uint32_t Device_Objects_Writable_Property_List( + BACNET_OBJECT_TYPE object_type, + uint32_t object_instance, + const int32_t **properties) +{ + uint32_t count = 0; + struct object_functions *pObject = NULL; + + (void)object_instance; + pObject = Device_Object_Functions_Find(object_type); + if ((pObject != NULL) && (pObject->Object_Writable_Property_List != NULL)) { + pObject->Object_Writable_Property_List(object_instance, properties); + count = property_list_count(*properties); + } + + return count; +} + /* These three arrays are used by the ReadPropertyMultiple handler */ static const int Device_Properties_Required[] = { PROP_OBJECT_IDENTIFIER, @@ -384,6 +417,34 @@ static const int Device_Properties_Optional[] = { static const int Device_Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of writable properties */ + PROP_OBJECT_IDENTIFIER, + PROP_NUMBER_OF_APDU_RETRIES, + PROP_APDU_TIMEOUT, + PROP_VENDOR_IDENTIFIER, + PROP_SYSTEM_STATUS, + PROP_OBJECT_NAME, + PROP_LOCATION, + PROP_DESCRIPTION, + PROP_MODEL_NAME, +#if defined(BACNET_TIME_MASTER) + PROP_TIME_SYNCHRONIZATION_INTERVAL, + PROP_ALIGN_INTERVALS, + PROP_INTERVAL_OFFSET, +#endif + PROP_UTC_OFFSET, +#if defined(BACDL_MSTP) + PROP_MAX_INFO_FRAMES, + PROP_MAX_MASTER, +#endif + -1 +}; + /** * @brief Returns the list of required, optional, and proprietary properties * for the Device object. @@ -411,6 +472,20 @@ void Device_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Device object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Device_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /* note: you really only need to define variables for properties that are writable or that may change. The properties that are constant can be hard coded diff --git a/apps/gateway/Makefile b/apps/gateway/Makefile index 5c23dc9c..1f17e9a2 100644 --- a/apps/gateway/Makefile +++ b/apps/gateway/Makefile @@ -10,22 +10,31 @@ BACNET_OBJECT_DIR = $(BACNET_SRC_DIR)/bacnet/basic/object BACNET_OBJECT_SRC := \ $(BACNET_OBJECT_DIR)/gateway/gw_device.c \ - $(BACNET_OBJECT_DIR)/acc.c \ + $(BACNET_OBJECT_DIR)/device.c \ + $(BACNET_OBJECT_DIR)/access_credential.c \ + $(BACNET_OBJECT_DIR)/access_door.c \ + $(BACNET_OBJECT_DIR)/access_point.c \ + $(BACNET_OBJECT_DIR)/access_rights.c \ + $(BACNET_OBJECT_DIR)/access_user.c \ + $(BACNET_OBJECT_DIR)/access_zone.c \ $(BACNET_OBJECT_DIR)/ai.c \ $(BACNET_OBJECT_DIR)/ao.c \ $(BACNET_OBJECT_DIR)/av.c \ + $(BACNET_OBJECT_DIR)/acc.c \ + $(BACNET_OBJECT_DIR)/auditlog.c \ + $(BACNET_OBJECT_DIR)/bacfile.c \ $(BACNET_OBJECT_DIR)/bi.c \ $(BACNET_OBJECT_DIR)/bitstring_value.c \ - $(BACNET_OBJECT_DIR)/blo.c \ $(BACNET_OBJECT_DIR)/bo.c \ + $(BACNET_OBJECT_DIR)/blo.c \ $(BACNET_OBJECT_DIR)/bv.c \ $(BACNET_OBJECT_DIR)/calendar.c \ $(BACNET_OBJECT_DIR)/channel.c \ $(BACNET_OBJECT_DIR)/color_object.c \ $(BACNET_OBJECT_DIR)/color_temperature.c \ $(BACNET_OBJECT_DIR)/command.c \ + $(BACNET_OBJECT_DIR)/credential_data_input.c \ $(BACNET_OBJECT_DIR)/csv.c \ - $(BACNET_OBJECT_DIR)/device.c \ $(BACNET_OBJECT_DIR)/iv.c \ $(BACNET_OBJECT_DIR)/lc.c \ $(BACNET_OBJECT_DIR)/lo.c \ @@ -35,24 +44,16 @@ BACNET_OBJECT_SRC := \ $(BACNET_OBJECT_DIR)/ms-input.c \ $(BACNET_OBJECT_DIR)/mso.c \ $(BACNET_OBJECT_DIR)/msv.c \ + $(BACNET_OBJECT_DIR)/nc.c \ + $(BACNET_OBJECT_DIR)/netport.c \ $(BACNET_OBJECT_DIR)/osv.c \ $(BACNET_OBJECT_DIR)/piv.c \ $(BACNET_OBJECT_DIR)/program.c \ - $(BACNET_OBJECT_DIR)/nc.c \ - $(BACNET_OBJECT_DIR)/netport.c \ - $(BACNET_OBJECT_DIR)/time_value.c \ - $(BACNET_OBJECT_DIR)/timer.c \ - $(BACNET_OBJECT_DIR)/trendlog.c \ $(BACNET_OBJECT_DIR)/schedule.c \ $(BACNET_OBJECT_DIR)/structured_view.c \ - $(BACNET_OBJECT_DIR)/access_credential.c \ - $(BACNET_OBJECT_DIR)/access_door.c \ - $(BACNET_OBJECT_DIR)/access_point.c \ - $(BACNET_OBJECT_DIR)/access_rights.c \ - $(BACNET_OBJECT_DIR)/access_user.c \ - $(BACNET_OBJECT_DIR)/access_zone.c \ - $(BACNET_OBJECT_DIR)/credential_data_input.c \ - $(BACNET_OBJECT_DIR)/bacfile.c + $(BACNET_OBJECT_DIR)/time_value.c \ + $(BACNET_OBJECT_DIR)/timer.c \ + $(BACNET_OBJECT_DIR)/trendlog.c BACNET_BASIC_SRC = \ $(wildcard $(BACNET_SRC_DIR)/bacnet/basic/*.c) \ diff --git a/apps/piface/configure.sh b/apps/piface/configure.sh index 678e672d..75523f16 100755 --- a/apps/piface/configure.sh +++ b/apps/piface/configure.sh @@ -10,7 +10,7 @@ fi if [ ! -d "libpifacedigital" ] then - git clone https://github.com:piface/libpifacedigital.git + git clone https://github.com/piface/libpifacedigital.git fi # Build the library diff --git a/apps/piface/device.c b/apps/piface/device.c index 23eca7c7..4b1edf08 100644 --- a/apps/piface/device.c +++ b/apps/piface/device.c @@ -56,7 +56,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, - NULL /* Timer */ }, + NULL /* Timer */, + Device_Writable_Property_List }, #if (BACNET_PROTOCOL_REVISION >= 17) { OBJECT_NETWORK_PORT, Network_Port_Init, @@ -77,7 +78,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, - NULL /* Timer */ }, + NULL /* Timer */, + Network_Port_Writable_Property_List }, #endif { OBJECT_BINARY_INPUT, Binary_Input_Init, @@ -98,7 +100,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, - NULL /* Timer */ }, + NULL /* Timer */, + Binary_Input_Writable_Property_List }, { OBJECT_BINARY_LIGHTING_OUTPUT, Binary_Lighting_Output_Init, Binary_Lighting_Output_Count, @@ -118,7 +121,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Binary_Lighting_Output_Create, Binary_Lighting_Output_Delete, - Binary_Lighting_Output_Timer }, + Binary_Lighting_Output_Timer, + Binary_Lighting_Output_Writable_Property_List }, { OBJECT_BINARY_OUTPUT, Binary_Output_Init, Binary_Output_Count, @@ -138,7 +142,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Binary_Output_Create, Binary_Output_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + Binary_Output_Writable_Property_List }, { MAX_BACNET_OBJECT_TYPE, NULL /* Init */, NULL /* Count */, @@ -158,7 +163,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, - NULL /* Timer */ } + NULL /* Timer */, + NULL /* Writable_Property_List */ } }; /** Glue function to let the Device object, when called by a handler, @@ -331,6 +337,34 @@ static const int Device_Properties_Optional[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of writable properties */ + PROP_OBJECT_IDENTIFIER, + PROP_NUMBER_OF_APDU_RETRIES, + PROP_APDU_TIMEOUT, + PROP_VENDOR_IDENTIFIER, + PROP_SYSTEM_STATUS, + PROP_OBJECT_NAME, + PROP_LOCATION, + PROP_DESCRIPTION, + PROP_MODEL_NAME, +#if defined(BACNET_TIME_MASTER) + PROP_TIME_SYNCHRONIZATION_INTERVAL, + PROP_ALIGN_INTERVALS, + PROP_INTERVAL_OFFSET, +#endif + PROP_UTC_OFFSET, +#if defined(BACDL_MSTP) + PROP_MAX_INFO_FRAMES, + PROP_MAX_MASTER, +#endif + -1 +}; + static const int Device_Properties_Proprietary[] = { -1 }; void Device_Property_Lists( @@ -349,6 +383,20 @@ void Device_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Device object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Device_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /* note: you really only need to define variables for properties that are writable or that may change. The properties that are constant can be hard coded diff --git a/apps/server-mini/Makefile b/apps/server-mini/Makefile index ca3bea72..f3040e4c 100644 --- a/apps/server-mini/Makefile +++ b/apps/server-mini/Makefile @@ -9,9 +9,18 @@ SRC = main.c BACNET_OBJECT_DIR = $(BACNET_SRC_DIR)/bacnet/basic/object SRC = main.c \ $(BACNET_OBJECT_DIR)/device.c \ + $(BACNET_OBJECT_DIR)/access_credential.c \ + $(BACNET_OBJECT_DIR)/access_door.c \ + $(BACNET_OBJECT_DIR)/access_point.c \ + $(BACNET_OBJECT_DIR)/access_rights.c \ + $(BACNET_OBJECT_DIR)/access_user.c \ + $(BACNET_OBJECT_DIR)/access_zone.c \ $(BACNET_OBJECT_DIR)/ai.c \ $(BACNET_OBJECT_DIR)/ao.c \ $(BACNET_OBJECT_DIR)/av.c \ + $(BACNET_OBJECT_DIR)/acc.c \ + $(BACNET_OBJECT_DIR)/auditlog.c \ + $(BACNET_OBJECT_DIR)/bacfile.c \ $(BACNET_OBJECT_DIR)/bi.c \ $(BACNET_OBJECT_DIR)/bitstring_value.c \ $(BACNET_OBJECT_DIR)/bo.c \ @@ -22,6 +31,7 @@ SRC = main.c \ $(BACNET_OBJECT_DIR)/color_object.c \ $(BACNET_OBJECT_DIR)/color_temperature.c \ $(BACNET_OBJECT_DIR)/command.c \ + $(BACNET_OBJECT_DIR)/credential_data_input.c \ $(BACNET_OBJECT_DIR)/csv.c \ $(BACNET_OBJECT_DIR)/iv.c \ $(BACNET_OBJECT_DIR)/lc.c \ @@ -32,25 +42,16 @@ SRC = main.c \ $(BACNET_OBJECT_DIR)/ms-input.c \ $(BACNET_OBJECT_DIR)/mso.c \ $(BACNET_OBJECT_DIR)/msv.c \ - $(BACNET_OBJECT_DIR)/osv.c \ - $(BACNET_OBJECT_DIR)/piv.c \ $(BACNET_OBJECT_DIR)/nc.c \ $(BACNET_OBJECT_DIR)/netport.c \ - $(BACNET_OBJECT_DIR)/program.c \ - $(BACNET_OBJECT_DIR)/time_value.c \ - $(BACNET_OBJECT_DIR)/timer.c \ - $(BACNET_OBJECT_DIR)/trendlog.c \ + $(BACNET_OBJECT_DIR)/osv.c \ + $(BACNET_OBJECT_DIR)/piv.c \ + $(BACNET_OBJECT_DIR)/program.c \ $(BACNET_OBJECT_DIR)/schedule.c \ $(BACNET_OBJECT_DIR)/structured_view.c \ - $(BACNET_OBJECT_DIR)/access_credential.c \ - $(BACNET_OBJECT_DIR)/access_door.c \ - $(BACNET_OBJECT_DIR)/access_point.c \ - $(BACNET_OBJECT_DIR)/access_rights.c \ - $(BACNET_OBJECT_DIR)/access_user.c \ - $(BACNET_OBJECT_DIR)/access_zone.c \ - $(BACNET_OBJECT_DIR)/credential_data_input.c \ - $(BACNET_OBJECT_DIR)/acc.c \ - $(BACNET_OBJECT_DIR)/bacfile.c + $(BACNET_OBJECT_DIR)/time_value.c \ + $(BACNET_OBJECT_DIR)/timer.c \ + $(BACNET_OBJECT_DIR)/trendlog.c # TARGET_EXT is defined in apps/Makefile as .exe or nothing TARGET_BIN = ${TARGET}$(TARGET_EXT) diff --git a/apps/server-mini/main.c b/apps/server-mini/main.c index fa6e81f5..aa9ef083 100644 --- a/apps/server-mini/main.c +++ b/apps/server-mini/main.c @@ -102,7 +102,8 @@ static object_functions_t My_Object_Table[] = { NULL, NULL, NULL, - NULL }, + NULL, + Device_Writable_Property_List }, /* Analog Value (Read-Only) */ { OBJECT_ANALOG_VALUE, @@ -124,7 +125,8 @@ static object_functions_t My_Object_Table[] = { NULL, Analog_Value_Create, Analog_Value_Delete, - NULL }, + NULL, + Analog_Value_Writable_Property_List }, /* Analog Output (Commandable) */ { OBJECT_ANALOG_OUTPUT, @@ -146,7 +148,8 @@ static object_functions_t My_Object_Table[] = { NULL, Analog_Output_Create, Analog_Output_Delete, - NULL }, + NULL, + Analog_Output_Writable_Property_List }, /* Binary Output (Commandable) */ { OBJECT_BINARY_OUTPUT, @@ -168,7 +171,8 @@ static object_functions_t My_Object_Table[] = { NULL, Binary_Output_Create, Binary_Output_Delete, - NULL }, + NULL, + Binary_Output_Writable_Property_List }, /* Binary Value (Read-Only) */ { OBJECT_BINARY_VALUE, @@ -190,7 +194,8 @@ static object_functions_t My_Object_Table[] = { NULL, Binary_Value_Create, Binary_Value_Delete, - NULL }, + NULL, + Binary_Value_Writable_Property_List }, { MAX_BACNET_OBJECT_TYPE, NULL, @@ -211,6 +216,7 @@ static object_functions_t My_Object_Table[] = { NULL, NULL, NULL, + NULL, NULL } }; diff --git a/ports/rx62n/device.c b/ports/rx62n/device.c index ae6d479c..4df8da41 100644 --- a/ports/rx62n/device.c +++ b/ports/rx62n/device.c @@ -53,7 +53,7 @@ static struct my_object_functions { Device_Property_Lists }, { OBJECT_BINARY_OUTPUT, Binary_Output_Init, Binary_Output_Count, Binary_Output_Index_To_Instance, Binary_Output_Valid_Instance, - Binary_Output_Name, Binary_Output_Read_Property, + Binary_Output_Object_Name, Binary_Output_Read_Property, Binary_Output_Write_Property, Binary_Output_Property_Lists }, { MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL } }; @@ -152,7 +152,8 @@ static int Read_Property_Common( break; case PROP_OBJECT_NAME: if (pObject->Object_Name) { - pString = pObject->Object_Name(rpdata->object_instance); + pString = + pObject->Object_Name(rpdata->object_instance, &char_string); } characterstring_init_ansi(&char_string, pString); apdu_len = diff --git a/src/bacnet/basic/object/acc.c b/src/bacnet/basic/object/acc.c index c7e36b69..6cd67d89 100644 --- a/src/bacnet/basic/object/acc.c +++ b/src/bacnet/basic/object/acc.c @@ -46,6 +46,12 @@ static const int32_t Properties_Optional[] = { PROP_DESCRIPTION, -1 }; static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { PROP_PRESENT_VALUE, -1 }; + /** * Returns the list of required, optional, and proprietary properties. * Used by ReadPropertyMultiple service. @@ -75,6 +81,20 @@ void Accumulator_Property_Lists( return; } +/** + * @brief Get the list of writable properties for an Accumulator object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Accumulator_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * Determines if a given Accumulator instance is valid * diff --git a/src/bacnet/basic/object/acc.h b/src/bacnet/basic/object/acc.h index 8cd58ee0..ff0259e2 100644 --- a/src/bacnet/basic/object/acc.h +++ b/src/bacnet/basic/object/acc.h @@ -25,6 +25,9 @@ void Accumulator_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, const int32_t **pProprietary); +BACNET_STACK_EXPORT +void Accumulator_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); BACNET_STACK_EXPORT bool Accumulator_Valid_Instance(uint32_t object_instance); diff --git a/src/bacnet/basic/object/access_credential.c b/src/bacnet/basic/object/access_credential.c index 6fdb68f4..7dcb6f3a 100644 --- a/src/bacnet/basic/object/access_credential.c +++ b/src/bacnet/basic/object/access_credential.c @@ -46,6 +46,15 @@ static const int32_t Properties_Optional[] = { -1 }; static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of writable properties */ + PROP_GLOBAL_IDENTIFIER, -1 +}; + void Access_Credential_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, @@ -64,6 +73,20 @@ void Access_Credential_Property_Lists( return; } +/** + * @brief Get the list of writable properties for an Access Credential object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Access_Credential_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + void Access_Credential_Init(void) { unsigned i; diff --git a/src/bacnet/basic/object/access_credential.h b/src/bacnet/basic/object/access_credential.h index bd04b753..e0814071 100644 --- a/src/bacnet/basic/object/access_credential.h +++ b/src/bacnet/basic/object/access_credential.h @@ -64,6 +64,9 @@ void Access_Credential_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Access_Credential_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); +BACNET_STACK_EXPORT bool Access_Credential_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned Access_Credential_Count(void); diff --git a/src/bacnet/basic/object/access_door.c b/src/bacnet/basic/object/access_door.c index 261dd9ba..249781ba 100644 --- a/src/bacnet/basic/object/access_door.c +++ b/src/bacnet/basic/object/access_door.c @@ -41,6 +41,7 @@ static const int32_t Properties_Required[] = { }; static const int32_t Properties_Optional[] = { + /* unordered list of optional properties */ PROP_DOOR_STATUS, PROP_LOCK_STATUS, PROP_SECURED_STATUS, PROP_DOOR_UNLOCK_DELAY_TIME, PROP_DOOR_ALARM_STATE, -1 @@ -48,6 +49,16 @@ static const int32_t Properties_Optional[] = { static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of writable properties */ + PROP_PRESENT_VALUE, PROP_OUT_OF_SERVICE, PROP_DOOR_STATUS, + PROP_LOCK_STATUS, PROP_DOOR_ALARM_STATE, -1 +}; + void Access_Door_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, @@ -66,6 +77,20 @@ void Access_Door_Property_Lists( return; } +/** + * @brief Get the list of writable properties for an Access Door object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Access_Door_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + void Access_Door_Init(void) { unsigned i, j; diff --git a/src/bacnet/basic/object/access_door.h b/src/bacnet/basic/object/access_door.h index 1bbfe727..54ec52b5 100644 --- a/src/bacnet/basic/object/access_door.h +++ b/src/bacnet/basic/object/access_door.h @@ -46,6 +46,9 @@ void Access_Door_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Access_Door_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); +BACNET_STACK_EXPORT bool Access_Door_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned Access_Door_Count(void); diff --git a/src/bacnet/basic/object/access_point.c b/src/bacnet/basic/object/access_point.c index 0bb4b10f..6c868a58 100644 --- a/src/bacnet/basic/object/access_point.c +++ b/src/bacnet/basic/object/access_point.c @@ -48,6 +48,16 @@ static const int32_t Properties_Optional[] = { -1 }; static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of writable properties */ + PROP_OUT_OF_SERVICE, + -1, +}; + void Access_Point_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, @@ -66,6 +76,20 @@ void Access_Point_Property_Lists( return; } +/** + * @brief Get the list of writable properties for an Access Point object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Access_Point_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + void Access_Point_Init(void) { unsigned i; diff --git a/src/bacnet/basic/object/access_point.h b/src/bacnet/basic/object/access_point.h index 03dc61f6..4715ae32 100644 --- a/src/bacnet/basic/object/access_point.h +++ b/src/bacnet/basic/object/access_point.h @@ -53,6 +53,10 @@ void Access_Point_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Access_Point_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Access_Point_Valid_Instance(uint32_t object_instance); unsigned Access_Point_Count(void); BACNET_STACK_EXPORT diff --git a/src/bacnet/basic/object/access_rights.c b/src/bacnet/basic/object/access_rights.c index 71b99341..f334ca80 100644 --- a/src/bacnet/basic/object/access_rights.c +++ b/src/bacnet/basic/object/access_rights.c @@ -22,7 +22,7 @@ static bool Access_Rights_Initialized = false; -static ACCESS_RIGHTS_DESCR ar_descr[MAX_ACCESS_RIGHTSS]; +static ACCESS_RIGHTS_DESCR ar_descr[MAX_ACCESS_RIGHTS]; /* These three arrays are used by the ReadPropertyMultiple handler */ static const int32_t Properties_Required[] = { @@ -43,6 +43,15 @@ static const int32_t Properties_Optional[] = { -1 }; static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of writable properties */ + PROP_GLOBAL_IDENTIFIER, -1 +}; + void Access_Rights_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, @@ -61,6 +70,23 @@ void Access_Rights_Property_Lists( return; } +/** + * @brief Get the list of writable properties for an Access Rights object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Access_Rights_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + +/** + * @brief Initialize the Access Rights Object data + */ void Access_Rights_Init(void) { unsigned i; @@ -68,7 +94,7 @@ void Access_Rights_Init(void) if (!Access_Rights_Initialized) { Access_Rights_Initialized = true; - for (i = 0; i < MAX_ACCESS_RIGHTSS; i++) { + for (i = 0; i < MAX_ACCESS_RIGHTS; i++) { ar_descr[i].global_identifier = 0; /* set to some meaningful value */ ar_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED; @@ -87,7 +113,7 @@ void Access_Rights_Init(void) /* given instance exists */ bool Access_Rights_Valid_Instance(uint32_t object_instance) { - if (object_instance < MAX_ACCESS_RIGHTSS) { + if (object_instance < MAX_ACCESS_RIGHTS) { return true; } @@ -98,7 +124,7 @@ bool Access_Rights_Valid_Instance(uint32_t object_instance) /* more complex, and then count how many you have */ unsigned Access_Rights_Count(void) { - return MAX_ACCESS_RIGHTSS; + return MAX_ACCESS_RIGHTS; } /* we simply have 0-n object instances. Yours might be */ @@ -114,9 +140,9 @@ uint32_t Access_Rights_Index_To_Instance(unsigned index) /* that correlates to the correct instance number */ unsigned Access_Rights_Instance_To_Index(uint32_t object_instance) { - unsigned index = MAX_ACCESS_RIGHTSS; + unsigned index = MAX_ACCESS_RIGHTS; - if (object_instance < MAX_ACCESS_RIGHTSS) { + if (object_instance < MAX_ACCESS_RIGHTS) { index = object_instance; } @@ -130,7 +156,7 @@ bool Access_Rights_Object_Name( char text[32] = ""; bool status = false; - if (object_instance < MAX_ACCESS_RIGHTSS) { + if (object_instance < MAX_ACCESS_RIGHTS) { snprintf( text, sizeof(text), "ACCESS RIGHTS %lu", (unsigned long)object_instance); @@ -157,7 +183,7 @@ static int Negative_Access_Rules_Encode( BACNET_ACCESS_RULE *rule; uint32_t count; - if (object_instance < MAX_ACCESS_RIGHTSS) { + if (object_instance < MAX_ACCESS_RIGHTS) { count = ar_descr[object_instance].negative_access_rules_count; if (index < count) { rule = &ar_descr[object_instance].negative_access_rules[index]; @@ -185,7 +211,7 @@ static int Positive_Access_Rules_Encode( BACNET_ACCESS_RULE *rule; uint32_t count; - if (object_instance < MAX_ACCESS_RIGHTSS) { + if (object_instance < MAX_ACCESS_RIGHTS) { count = ar_descr[object_instance].positive_access_rules_count; if (index < count) { rule = &ar_descr[object_instance].positive_access_rules[index]; diff --git a/src/bacnet/basic/object/access_rights.h b/src/bacnet/basic/object/access_rights.h index 2eb60e18..7faaf5b7 100644 --- a/src/bacnet/basic/object/access_rights.h +++ b/src/bacnet/basic/object/access_rights.h @@ -19,8 +19,8 @@ #include "bacnet/rp.h" #include "bacnet/wp.h" -#ifndef MAX_ACCESS_RIGHTSS -#define MAX_ACCESS_RIGHTSS 4 +#ifndef MAX_ACCESS_RIGHTS +#define MAX_ACCESS_RIGHTS 4 #endif #ifndef MAX_NEGATIVE_ACCESS_RIGHTS_RULES @@ -52,6 +52,10 @@ void Access_Rights_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Access_Rights_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Access_Rights_Valid_Instance(uint32_t object_instance); unsigned Access_Rights_Count(void); BACNET_STACK_EXPORT diff --git a/src/bacnet/basic/object/access_user.c b/src/bacnet/basic/object/access_user.c index cbcab2bb..ad8d2348 100644 --- a/src/bacnet/basic/object/access_user.c +++ b/src/bacnet/basic/object/access_user.c @@ -34,6 +34,16 @@ static const int32_t Properties_Optional[] = { -1 }; static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of writable properties */ + PROP_GLOBAL_IDENTIFIER, + -1, +}; + void Access_User_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, @@ -52,6 +62,20 @@ void Access_User_Property_Lists( return; } +/** + * @brief Get the list of writable properties for an Access User object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Access_User_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + void Access_User_Init(void) { unsigned i; diff --git a/src/bacnet/basic/object/access_user.h b/src/bacnet/basic/object/access_user.h index 5ec89942..2b0e9845 100644 --- a/src/bacnet/basic/object/access_user.h +++ b/src/bacnet/basic/object/access_user.h @@ -45,6 +45,10 @@ void Access_User_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Access_User_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Access_User_Valid_Instance(uint32_t object_instance); unsigned Access_User_Count(void); BACNET_STACK_EXPORT diff --git a/src/bacnet/basic/object/access_zone.c b/src/bacnet/basic/object/access_zone.c index 6f843391..515b43b1 100644 --- a/src/bacnet/basic/object/access_zone.c +++ b/src/bacnet/basic/object/access_zone.c @@ -35,6 +35,17 @@ static const int32_t Properties_Optional[] = { -1 }; static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of writable properties */ + PROP_GLOBAL_IDENTIFIER, + PROP_RELIABILITY, + -1, +}; + void Access_Zone_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, @@ -53,6 +64,20 @@ void Access_Zone_Property_Lists( return; } +/** + * @brief Get the list of writable properties for an Access Zone object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Access_Zone_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + void Access_Zone_Init(void) { unsigned i; diff --git a/src/bacnet/basic/object/access_zone.h b/src/bacnet/basic/object/access_zone.h index 1ae467af..0f045e6e 100644 --- a/src/bacnet/basic/object/access_zone.h +++ b/src/bacnet/basic/object/access_zone.h @@ -53,6 +53,10 @@ void Access_Zone_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Access_Zone_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Access_Zone_Valid_Instance(uint32_t object_instance); unsigned Access_Zone_Count(void); BACNET_STACK_EXPORT diff --git a/src/bacnet/basic/object/ai.c b/src/bacnet/basic/object/ai.c index 9decfb12..e88ead77 100644 --- a/src/bacnet/basic/object/ai.c +++ b/src/bacnet/basic/object/ai.c @@ -62,6 +62,15 @@ static const int32_t Properties_Optional[] = { static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + -1 +}; + /** * Initialize the pointers for the required, the optional and the properitary * value properties. @@ -88,6 +97,20 @@ void Analog_Input_Property_Lists( return; } +/** + * @brief Get the list of writable properties for an Analog Input object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Analog_Input_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Gets an object from the list using an instance number as the key * @param object_instance - object-instance number of the object diff --git a/src/bacnet/basic/object/ai.h b/src/bacnet/basic/object/ai.h index f43ad4e1..07daf77a 100644 --- a/src/bacnet/basic/object/ai.h +++ b/src/bacnet/basic/object/ai.h @@ -66,6 +66,9 @@ void Analog_Input_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, const int32_t **pProprietary); +BACNET_STACK_EXPORT +void Analog_Input_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); BACNET_STACK_EXPORT bool Analog_Input_Valid_Instance(uint32_t object_instance); diff --git a/src/bacnet/basic/object/ao.c b/src/bacnet/basic/object/ao.c index d84c698b..ed4be266 100644 --- a/src/bacnet/basic/object/ao.c +++ b/src/bacnet/basic/object/ao.c @@ -84,6 +84,16 @@ static const int32_t Properties_Optional[] = { static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of writable properties */ + PROP_PRESENT_VALUE, PROP_OUT_OF_SERVICE, PROP_UNITS, PROP_COV_INCREMENT, + PROP_MIN_PRES_VALUE, PROP_MAX_PRES_VALUE, -1 +}; + /** * @brief Returns the list of required, optional, and proprietary properties. * Used by ReadPropertyMultiple service. @@ -112,6 +122,20 @@ void Analog_Output_Property_Lists( return; } +/** + * @brief Get the list of writable properties for an Analog Output object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Analog_Output_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Determines if a given Analog Output instance is valid * @param object_instance - object-instance number of the object diff --git a/src/bacnet/basic/object/ao.h b/src/bacnet/basic/object/ao.h index 5bc95640..73610e45 100644 --- a/src/bacnet/basic/object/ao.h +++ b/src/bacnet/basic/object/ao.h @@ -37,6 +37,9 @@ void Analog_Output_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Analog_Output_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); +BACNET_STACK_EXPORT bool Analog_Output_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned Analog_Output_Count(void); diff --git a/src/bacnet/basic/object/auditlog.c b/src/bacnet/basic/object/auditlog.c index dd3cdff3..609fa3f8 100644 --- a/src/bacnet/basic/object/auditlog.c +++ b/src/bacnet/basic/object/auditlog.c @@ -137,6 +137,14 @@ static const int32_t BACnetARRAY_Properties[] = { -1 }; +static const int32_t Writable_Properties[] = { + /* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ + PROP_ENABLE, PROP_BUFFER_SIZE, -1 +}; + /** * @brief Determine if the object property is a BACnetARRAY property * @param object_property - object-property to be checked @@ -176,6 +184,20 @@ void Audit_Log_Property_Lists( return; } +/** + * @brief Get the list of writable properties for an Audit Log object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Audit_Log_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Gets an object from the list using an instance number as the key * @param object_instance - object-instance number of the object diff --git a/src/bacnet/basic/object/auditlog.h b/src/bacnet/basic/object/auditlog.h index c7647868..a3894f94 100644 --- a/src/bacnet/basic/object/auditlog.h +++ b/src/bacnet/basic/object/auditlog.h @@ -42,6 +42,9 @@ void Audit_Log_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, const int32_t **pProprietary); +BACNET_STACK_EXPORT +void Audit_Log_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); BACNET_STACK_EXPORT bool Audit_Log_Valid_Instance(uint32_t object_instance); diff --git a/src/bacnet/basic/object/av.c b/src/bacnet/basic/object/av.c index 3b388773..3d4d8256 100644 --- a/src/bacnet/basic/object/av.c +++ b/src/bacnet/basic/object/av.c @@ -36,29 +36,62 @@ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_ANALOG_VALUE; static analog_value_write_present_value_callback Analog_Value_Write_Present_Value_Callback; -/* clang-format off */ /* These three arrays are used by the ReadPropertyMultiple handler */ static const int32_t Analog_Value_Properties_Required[] = { - PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE, - PROP_PRESENT_VALUE, PROP_STATUS_FLAGS, PROP_EVENT_STATE, - PROP_OUT_OF_SERVICE, PROP_UNITS, -1 + /* unordered list of required properties */ + PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE, + PROP_PRESENT_VALUE, PROP_STATUS_FLAGS, PROP_EVENT_STATE, + PROP_OUT_OF_SERVICE, PROP_UNITS, -1 }; static const int32_t Analog_Value_Properties_Optional[] = { - PROP_DESCRIPTION, PROP_RELIABILITY, PROP_COV_INCREMENT, + /* unordered list of optional properties */ + PROP_DESCRIPTION, + PROP_RELIABILITY, + PROP_COV_INCREMENT, #if defined(INTRINSIC_REPORTING) - PROP_TIME_DELAY, PROP_NOTIFICATION_CLASS, PROP_HIGH_LIMIT, - PROP_LOW_LIMIT, PROP_DEADBAND, PROP_LIMIT_ENABLE, PROP_EVENT_ENABLE, - PROP_ACKED_TRANSITIONS, PROP_NOTIFY_TYPE, PROP_EVENT_TIME_STAMPS, + PROP_TIME_DELAY, + PROP_NOTIFICATION_CLASS, + PROP_HIGH_LIMIT, + PROP_LOW_LIMIT, + PROP_DEADBAND, + PROP_LIMIT_ENABLE, + PROP_EVENT_ENABLE, + PROP_ACKED_TRANSITIONS, + PROP_NOTIFY_TYPE, + PROP_EVENT_TIME_STAMPS, PROP_EVENT_DETECTION_ENABLE, #endif -1 }; static const int32_t Analog_Value_Properties_Proprietary[] = { + /* unordered list of proprietary properties */ + -1 +}; + +/* Every object shall have a Writable Property_List property +which is a BACnetARRAY of property identifiers, +one property identifier for each property within this object +that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PRESENT_VALUE, + PROP_OUT_OF_SERVICE, + PROP_UNITS, + PROP_COV_INCREMENT, +#if defined(INTRINSIC_REPORTING) + PROP_TIME_DELAY, + PROP_NOTIFICATION_CLASS, + PROP_HIGH_LIMIT, + PROP_LOW_LIMIT, + PROP_DEADBAND, + PROP_LIMIT_ENABLE, + PROP_EVENT_ENABLE, + PROP_NOTIFY_TYPE, +#endif -1 }; -/* clang-format on */ /** * Initialize the pointers for the required, the optional and the properitary @@ -86,6 +119,20 @@ void Analog_Value_Property_Lists( return; } +/** + * @brief Get the list of writable properties for an Analog Value object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Analog_Value_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Gets an object from the list using an instance number as the key * @param object_instance - object-instance number of the object diff --git a/src/bacnet/basic/object/av.h b/src/bacnet/basic/object/av.h index a0e6eb30..c9963b8a 100644 --- a/src/bacnet/basic/object/av.h +++ b/src/bacnet/basic/object/av.h @@ -74,6 +74,10 @@ void Analog_Value_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Analog_Value_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Analog_Value_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned Analog_Value_Count(void); diff --git a/src/bacnet/basic/object/bacfile.c b/src/bacnet/basic/object/bacfile.c index 4e4aae22..0d166014 100644 --- a/src/bacnet/basic/object/bacfile.c +++ b/src/bacnet/basic/object/bacfile.c @@ -65,6 +65,15 @@ static const int32_t Properties_Optional[] = { static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of writable properties */ + PROP_ARCHIVE, PROP_FILE_SIZE, -1 +}; + /** * @brief Returns the list of required, optional, and proprietary properties. * Used by ReadPropertyMultiple service. @@ -93,6 +102,20 @@ void BACfile_Property_Lists( return; } +/** + * @brief Get the list of writable properties for an Analog Input object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void BACfile_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief duplicate a string (replacement for POSIX strdup) * @param s - string to duplicate diff --git a/src/bacnet/basic/object/bacfile.h b/src/bacnet/basic/object/bacfile.h index bb39fe0c..28592674 100644 --- a/src/bacnet/basic/object/bacfile.h +++ b/src/bacnet/basic/object/bacfile.h @@ -29,6 +29,9 @@ void BACfile_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, const int32_t **pProprietary); +BACNET_STACK_EXPORT +void BACfile_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); BACNET_STACK_EXPORT bool bacfile_object_name( diff --git a/src/bacnet/basic/object/bi.c b/src/bacnet/basic/object/bi.c index 0b214117..6557f254 100644 --- a/src/bacnet/basic/object/bi.c +++ b/src/bacnet/basic/object/bi.c @@ -97,6 +97,15 @@ static const int32_t Properties_Optional[] = { static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of writable properties */ + -1 +}; + /** * Initialize the pointers for the required, the optional and the properitary * value properties. @@ -123,6 +132,20 @@ void Binary_Input_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Binary Input object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Binary_Input_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Gets an object from the list using an instance number as the key * @param object_instance - object-instance number of the object diff --git a/src/bacnet/basic/object/bi.h b/src/bacnet/basic/object/bi.h index 8278a94c..99252530 100644 --- a/src/bacnet/basic/object/bi.h +++ b/src/bacnet/basic/object/bi.h @@ -45,6 +45,9 @@ void Binary_Input_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, const int32_t **pProprietary); +BACNET_STACK_EXPORT +void Binary_Input_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); BACNET_STACK_EXPORT bool Binary_Input_Valid_Instance(uint32_t object_instance); diff --git a/src/bacnet/basic/object/bitstring_value.c b/src/bacnet/basic/object/bitstring_value.c index 7543ab07..21dec29d 100644 --- a/src/bacnet/basic/object/bitstring_value.c +++ b/src/bacnet/basic/object/bitstring_value.c @@ -55,6 +55,15 @@ static const int32_t Properties_Optional[] = { static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PRESENT_VALUE, PROP_OUT_OF_SERVICE, -1 +}; + /** * Initialize the pointers for the required, the optional and the properitary * value properties. @@ -81,6 +90,20 @@ void BitString_Value_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a BitString Value object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void BitString_Value_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Gets an object from the list using an instance number as the key * @param object_instance - object-instance number of the object diff --git a/src/bacnet/basic/object/bitstring_value.h b/src/bacnet/basic/object/bitstring_value.h index 407b15c8..2232c1eb 100644 --- a/src/bacnet/basic/object/bitstring_value.h +++ b/src/bacnet/basic/object/bitstring_value.h @@ -42,6 +42,9 @@ void BitString_Value_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, const int32_t **pProprietary); +BACNET_STACK_EXPORT +void BitString_Value_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); BACNET_STACK_EXPORT bool BitString_Value_Valid_Instance(uint32_t object_instance); diff --git a/src/bacnet/basic/object/blo.c b/src/bacnet/basic/object/blo.c index ddc85260..77858b47 100644 --- a/src/bacnet/basic/object/blo.c +++ b/src/bacnet/basic/object/blo.c @@ -85,6 +85,15 @@ static const int32_t Properties_Optional[] = { static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + -1 +}; + /** * Returns the list of required, optional, and proprietary properties. * Used by ReadPropertyMultiple service. @@ -114,6 +123,20 @@ void Binary_Lighting_Output_Property_Lists( return; } +/** + * @brief Get list of writable properties for a Binary Lighting Output object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Binary_Lighting_Output_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * Determines if a given Lighting Output instance is valid * diff --git a/src/bacnet/basic/object/blo.h b/src/bacnet/basic/object/blo.h index 85f8fad1..29feba5f 100644 --- a/src/bacnet/basic/object/blo.h +++ b/src/bacnet/basic/object/blo.h @@ -44,6 +44,10 @@ void Binary_Lighting_Output_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Binary_Lighting_Output_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Binary_Lighting_Output_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned Binary_Lighting_Output_Count(void); diff --git a/src/bacnet/basic/object/bo.c b/src/bacnet/basic/object/bo.c index ddd379d2..f6ed6d20 100644 --- a/src/bacnet/basic/object/bo.c +++ b/src/bacnet/basic/object/bo.c @@ -82,6 +82,16 @@ static const int32_t Properties_Optional[] = { static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PRESENT_VALUE, PROP_OUT_OF_SERVICE, PROP_POLARITY, + PROP_RELINQUISH_DEFAULT, -1 +}; + /** * Returns the list of required, optional, and proprietary properties. * Used by ReadPropertyMultiple service. @@ -111,6 +121,20 @@ void Binary_Output_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Binary Output object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Binary_Output_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * Determines if a given Binary Output instance is valid * diff --git a/src/bacnet/basic/object/bo.h b/src/bacnet/basic/object/bo.h index 0511b7e6..d6016933 100644 --- a/src/bacnet/basic/object/bo.h +++ b/src/bacnet/basic/object/bo.h @@ -42,6 +42,9 @@ void Binary_Output_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, const int32_t **pProprietary); +BACNET_STACK_EXPORT +void Binary_Output_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); BACNET_STACK_EXPORT bool Binary_Output_Valid_Instance(uint32_t object_instance); diff --git a/src/bacnet/basic/object/bv.c b/src/bacnet/basic/object/bv.c index 693269db..7b65afab 100644 --- a/src/bacnet/basic/object/bv.c +++ b/src/bacnet/basic/object/bv.c @@ -67,20 +67,17 @@ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_BINARY_VALUE; static binary_value_write_present_value_callback Binary_Value_Write_Present_Value_Callback; -/* clang-format off */ /* These three arrays are used by the ReadPropertyMultiple handler */ static const int32_t Binary_Value_Properties_Required[] = { - PROP_OBJECT_IDENTIFIER, - PROP_OBJECT_NAME, - PROP_OBJECT_TYPE, - PROP_PRESENT_VALUE, - PROP_STATUS_FLAGS, - PROP_EVENT_STATE, - PROP_OUT_OF_SERVICE, - -1 + /* unordered list of optional properties */ + PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, + PROP_OBJECT_TYPE, PROP_PRESENT_VALUE, + PROP_STATUS_FLAGS, PROP_EVENT_STATE, + PROP_OUT_OF_SERVICE, -1 }; static const int32_t Binary_Value_Properties_Optional[] = { + /* unordered list of optional properties */ PROP_DESCRIPTION, PROP_RELIABILITY, PROP_ACTIVE_TEXT, @@ -98,10 +95,25 @@ static const int32_t Binary_Value_Properties_Optional[] = { -1 }; -static const int32_t Binary_Value_Properties_Proprietary[] = { +static const int32_t Binary_Value_Properties_Proprietary[] = { -1 }; + +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PRESENT_VALUE, + PROP_OUT_OF_SERVICE, +#if defined(INTRINSIC_REPORTING) && (BINARY_VALUE_INTRINSIC_REPORTING) + PROP_TIME_DELAY, + PROP_NOTIFICATION_CLASS, + PROP_ALARM_VALUE, + PROP_EVENT_ENABLE, + PROP_NOTIFY_TYPE, +#endif -1 }; -/* clang-format on */ /** * Initialize the pointers for the required, the optional and the properitary @@ -129,6 +141,20 @@ void Binary_Value_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Binary Value object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Binary_Value_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Gets an object from the list using an instance number as the key * @param object_instance - object-instance number of the object diff --git a/src/bacnet/basic/object/bv.h b/src/bacnet/basic/object/bv.h index 5be52d30..a79a678f 100644 --- a/src/bacnet/basic/object/bv.h +++ b/src/bacnet/basic/object/bv.h @@ -47,6 +47,9 @@ void Binary_Value_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, const int32_t **pProprietary); +BACNET_STACK_EXPORT +void Binary_Value_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); BACNET_STACK_EXPORT bool Binary_Value_Valid_Instance(uint32_t object_instance); diff --git a/src/bacnet/basic/object/calendar.c b/src/bacnet/basic/object/calendar.c index dcd66115..7d16a637 100644 --- a/src/bacnet/basic/object/calendar.c +++ b/src/bacnet/basic/object/calendar.c @@ -50,14 +50,27 @@ static calendar_write_present_value_callback /* These three arrays are used by the ReadPropertyMultiple handler */ static const int32_t Calendar_Properties_Required[] = { + /* unordered list of required properties */ PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE, PROP_PRESENT_VALUE, PROP_DATE_LIST, -1 }; -static const int32_t Calendar_Properties_Optional[] = { PROP_DESCRIPTION, -1 }; +static const int32_t Calendar_Properties_Optional[] = { + /* unordered list of optional properties */ + PROP_DESCRIPTION, -1 +}; static const int32_t Calendar_Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_DATE_LIST, -1 +}; + /** * Returns the list of required, optional, and proprietary properties. * Used by ReadPropertyMultiple service. @@ -87,6 +100,20 @@ void Calendar_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Calendar object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Calendar_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * Determines if a given Calendar instance is valid * diff --git a/src/bacnet/basic/object/calendar.h b/src/bacnet/basic/object/calendar.h index ae299138..5f0c390c 100644 --- a/src/bacnet/basic/object/calendar.h +++ b/src/bacnet/basic/object/calendar.h @@ -37,6 +37,10 @@ void Calendar_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Calendar_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Calendar_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned Calendar_Count(void); diff --git a/src/bacnet/basic/object/channel.c b/src/bacnet/basic/object/channel.c index 9ae373c4..ccd9b31b 100644 --- a/src/bacnet/basic/object/channel.c +++ b/src/bacnet/basic/object/channel.c @@ -79,6 +79,20 @@ static const int32_t Channel_Properties_Optional[] = { -1 }; static const int32_t Channel_Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PRESENT_VALUE, + PROP_OUT_OF_SERVICE, + PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES, + PROP_CHANNEL_NUMBER, + PROP_CONTROL_GROUPS, + -1 +}; + /** * Returns the list of required, optional, and proprietary properties. * Used by ReadPropertyMultiple service. @@ -108,6 +122,20 @@ void Channel_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Channel object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Channel_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Get a Channel object * @param object_instance [in] BACnet object instance number diff --git a/src/bacnet/basic/object/channel.h b/src/bacnet/basic/object/channel.h index 835a8722..15a1e81c 100644 --- a/src/bacnet/basic/object/channel.h +++ b/src/bacnet/basic/object/channel.h @@ -43,6 +43,10 @@ void Channel_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Channel_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Channel_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned Channel_Count(void); diff --git a/src/bacnet/basic/object/client/device-client.c b/src/bacnet/basic/object/client/device-client.c index d878bfbc..85630238 100644 --- a/src/bacnet/basic/object/client/device-client.c +++ b/src/bacnet/basic/object/client/device-client.c @@ -112,7 +112,8 @@ static object_functions_t Object_Table[] = { NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, - NULL /* Timer */ }, + NULL /* Timer */, + Device_Writable_Property_List }, #if (BACNET_PROTOCOL_REVISION >= 17) { OBJECT_NETWORK_PORT, Network_Port_Init, @@ -133,7 +134,8 @@ static object_functions_t Object_Table[] = { NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, - NULL /* Timer */ }, + NULL /* Timer */, + Network_Port_Writable_Property_List }, #endif #if defined(BACFILE) { OBJECT_FILE, @@ -155,7 +157,8 @@ static object_functions_t Object_Table[] = { NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, - NULL /* Timer */ }, + NULL /* Timer */, + BACfile_Writable_Property_List }, #endif { MAX_BACNET_OBJECT_TYPE, NULL /* Init */, @@ -176,7 +179,8 @@ static object_functions_t Object_Table[] = { NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, - NULL /* Timer */ }, + NULL /* Timer */, + NULL /* Writable_Property_List */ }, }; /** Glue function to let the Device object, when called by a handler, @@ -304,6 +308,31 @@ bool Device_Objects_Property_List_Member( return found; } +/** + * @brief Get the Writeable Property List for an object type + * @param object_type - object type of the object + * @param object_instance - object-instance number of the object + * @param properties - pointer to the list of writable properties + * @return The number of properties in the writable property list + */ +uint32_t Device_Objects_Writable_Property_List( + BACNET_OBJECT_TYPE object_type, + uint32_t object_instance, + const int32_t **properties) +{ + uint32_t count = 0; + struct object_functions *pObject = NULL; + + (void)object_instance; + pObject = Device_Object_Functions_Find(object_type); + if ((pObject != NULL) && (pObject->Object_Writable_Property_List != NULL)) { + pObject->Object_Writable_Property_List(object_instance, properties); + count = property_list_count(*properties); + } + + return count; +} + /* These three arrays are used by the ReadPropertyMultiple handler */ static const int32_t Device_Properties_Required[] = { PROP_OBJECT_IDENTIFIER, @@ -343,6 +372,15 @@ static const int32_t Device_Properties_Optional[] = { static const int32_t Device_Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of writable properties */ + -1 +}; + void Device_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, @@ -361,6 +399,20 @@ void Device_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Device object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Device_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE; static const char *Reinit_Password = "filister"; diff --git a/src/bacnet/basic/object/color_object.c b/src/bacnet/basic/object/color_object.c index 66fd63ef..66a9f3fd 100644 --- a/src/bacnet/basic/object/color_object.c +++ b/src/bacnet/basic/object/color_object.c @@ -76,6 +76,16 @@ static const int32_t Color_Properties_Optional[] = { PROP_DESCRIPTION, static const int32_t Color_Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PRESENT_VALUE, PROP_COLOR_COMMAND, PROP_DEFAULT_COLOR, + PROP_DEFAULT_FADE_TIME, PROP_TRANSITION, -1 +}; + /** * Returns the list of required, optional, and proprietary properties. * Used by ReadPropertyMultiple service. @@ -105,6 +115,20 @@ void Color_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Color object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Color_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * Determines if a given Color instance is valid * diff --git a/src/bacnet/basic/object/color_object.h b/src/bacnet/basic/object/color_object.h index 09e71099..471e5229 100644 --- a/src/bacnet/basic/object/color_object.h +++ b/src/bacnet/basic/object/color_object.h @@ -39,6 +39,10 @@ void Color_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Color_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Color_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned Color_Count(void); diff --git a/src/bacnet/basic/object/color_temperature.c b/src/bacnet/basic/object/color_temperature.c index 7bafe679..2e051d1d 100644 --- a/src/bacnet/basic/object/color_temperature.c +++ b/src/bacnet/basic/object/color_temperature.c @@ -79,6 +79,21 @@ static const int32_t Color_Temperature_Properties_Optional[] = { static const int32_t Color_Temperature_Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PRESENT_VALUE, + PROP_DEFAULT_COLOR_TEMPERATURE, + PROP_DEFAULT_FADE_TIME, + PROP_TRANSITION, + PROP_DEFAULT_RAMP_RATE, + PROP_DEFAULT_STEP_INCREMENT, + -1 +}; + /** * Returns the list of required, optional, and proprietary properties. * Used by ReadPropertyMultiple service. @@ -109,7 +124,21 @@ void Color_Temperature_Property_Lists( } /** - * Determines if a given Color instance is valid + * @brief Get the list of writable properties for an Color Temperature object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Color_Temperature_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + +/** + * Determines if a given Color Temperature instance is valid * * @param object_instance - object-instance number of the object * @@ -128,9 +157,9 @@ bool Color_Temperature_Valid_Instance(uint32_t object_instance) } /** - * Determines the number of Color objects + * Determines the number of Color Temperature objects * - * @return Number of Color objects + * @return Number of Color Temperature objects */ unsigned Color_Temperature_Count(void) { @@ -139,7 +168,7 @@ unsigned Color_Temperature_Count(void) /** * Determines the object instance-number for a given 0..N index - * of Color objects where N is Color_Temperature_Count(). + * of Color Temperature objects where N is Color_Temperature_Count(). * * @param index - 0..N where N is Color_Temperature_Count() * @@ -156,7 +185,7 @@ uint32_t Color_Temperature_Index_To_Instance(unsigned index) /** * For a given object instance-number, determines a 0..N index - * of Color objects where N is Color_Temperature_Count(). + * of Color Temperature objects where N is Color_Temperature_Count(). * * @param object_instance - object-instance number of the object * diff --git a/src/bacnet/basic/object/color_temperature.h b/src/bacnet/basic/object/color_temperature.h index 464effd5..0853b04b 100644 --- a/src/bacnet/basic/object/color_temperature.h +++ b/src/bacnet/basic/object/color_temperature.h @@ -35,6 +35,10 @@ void Color_Temperature_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Color_Temperature_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Color_Temperature_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned Color_Temperature_Count(void); diff --git a/src/bacnet/basic/object/command.c b/src/bacnet/basic/object/command.c index a632b4fa..f7dbe05b 100644 --- a/src/bacnet/basic/object/command.c +++ b/src/bacnet/basic/object/command.c @@ -33,9 +33,9 @@ static COMMAND_DESCR Command_Descr[MAX_COMMANDS]; -/* clang-format off */ /* These arrays are used by the ReadPropertyMultiple handler */ static const int32_t Command_Properties_Required[] = { + /* unordered list of required properties */ PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE, @@ -43,12 +43,21 @@ static const int32_t Command_Properties_Required[] = { PROP_IN_PROCESS, PROP_ALL_WRITES_SUCCESSFUL, PROP_ACTION, - -1 }; + -1 +}; static const int32_t Command_Properties_Optional[] = { -1 }; static const int32_t Command_Properties_Proprietary[] = { -1 }; -/* clang-format on */ + +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PRESENT_VALUE, -1 +}; /** * Returns the list of required, optional, and proprietary properties. @@ -79,6 +88,20 @@ void Command_Property_Lists( return; } +/** + * @brief Get the list of writable properties for an Command object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Command_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * Initializes the Command object data */ diff --git a/src/bacnet/basic/object/command.h b/src/bacnet/basic/object/command.h index f0300b41..d36ea3d3 100644 --- a/src/bacnet/basic/object/command.h +++ b/src/bacnet/basic/object/command.h @@ -40,6 +40,9 @@ void Command_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, const int32_t **pProprietary); +BACNET_STACK_EXPORT +void Command_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); BACNET_STACK_EXPORT bool Command_Valid_Instance(uint32_t object_instance); diff --git a/src/bacnet/basic/object/credential_data_input.c b/src/bacnet/basic/object/credential_data_input.c index 1295bbed..661c37ed 100644 --- a/src/bacnet/basic/object/credential_data_input.c +++ b/src/bacnet/basic/object/credential_data_input.c @@ -37,6 +37,25 @@ static const int32_t Properties_Optional[] = { -1 }; static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PRESENT_VALUE, PROP_RELIABILITY, -1 +}; + +/** + * @brief Returns the list of required, optional, and proprietary properties. + * Used by ReadPropertyMultiple service. + * @param pRequired - pointer to list of int terminated by -1, of + * BACnet required properties for this object. + * @param pOptional - pointer to list of int terminated by -1, of + * BACnet optional properties for this object. + * @param pProprietary - pointer to list of int terminated by -1, of + * BACnet proprietary properties for this object. + */ void Credential_Data_Input_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, @@ -55,6 +74,20 @@ void Credential_Data_Input_Property_Lists( return; } +/** + * @brief Get list of writable properties for an Credential Data Input object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Credential_Data_Input_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + void Credential_Data_Input_Init(void) { unsigned i; @@ -320,19 +353,16 @@ bool Credential_Data_Input_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } break; - case PROP_OBJECT_IDENTIFIER: - case PROP_OBJECT_NAME: - case PROP_OBJECT_TYPE: - case PROP_STATUS_FLAGS: - case PROP_OUT_OF_SERVICE: - case PROP_SUPPORTED_FORMATS: - case PROP_UPDATE_TIME: - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; - break; default: - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; + if (property_lists_member( + Properties_Required, Properties_Optional, + Properties_Proprietary, wp_data->object_property)) { + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; + } else { + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; + } break; } diff --git a/src/bacnet/basic/object/credential_data_input.h b/src/bacnet/basic/object/credential_data_input.h index e708fbab..f7b556ee 100644 --- a/src/bacnet/basic/object/credential_data_input.h +++ b/src/bacnet/basic/object/credential_data_input.h @@ -49,6 +49,10 @@ void Credential_Data_Input_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Credential_Data_Input_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Credential_Data_Input_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned Credential_Data_Input_Count(void); diff --git a/src/bacnet/basic/object/csv.c b/src/bacnet/basic/object/csv.c index 1a54902c..b1f17805 100644 --- a/src/bacnet/basic/object/csv.c +++ b/src/bacnet/basic/object/csv.c @@ -41,6 +41,15 @@ static const int32_t Properties_Optional[] = { static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PRESENT_VALUE, PROP_OUT_OF_SERVICE, -1 +}; + typedef struct characterstring_object { /* Writable out-of-service allows others to manipulate our Present Value */ bool Out_Of_Service : 1; @@ -80,6 +89,21 @@ void CharacterString_Value_Property_Lists( return; } +/** + * @brief Get the list of writable properties for an CharacterString Value + * object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void CharacterString_Value_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Set the context used with a specific object instance * @param object_instance [in] BACnet object instance number diff --git a/src/bacnet/basic/object/csv.h b/src/bacnet/basic/object/csv.h index 44e226c2..b735d1d7 100644 --- a/src/bacnet/basic/object/csv.h +++ b/src/bacnet/basic/object/csv.h @@ -25,6 +25,9 @@ void CharacterString_Value_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, const int32_t **pProprietary); +BACNET_STACK_EXPORT +void CharacterString_Value_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); BACNET_STACK_EXPORT bool CharacterString_Value_Valid_Instance(uint32_t object_instance); diff --git a/src/bacnet/basic/object/device.c b/src/bacnet/basic/object/device.c index 7b1869f4..f9624754 100644 --- a/src/bacnet/basic/object/device.c +++ b/src/bacnet/basic/object/device.c @@ -28,6 +28,13 @@ /* include the device object */ #include "bacnet/basic/object/device.h" #include "bacnet/basic/object/acc.h" +#include "bacnet/basic/object/access_credential.h" +#include "bacnet/basic/object/access_door.h" +#include "bacnet/basic/object/access_point.h" +#include "bacnet/basic/object/access_rights.h" +#include "bacnet/basic/object/access_user.h" +#include "bacnet/basic/object/access_zone.h" +#include "bacnet/basic/object/auditlog.h" #include "bacnet/basic/object/ai.h" #include "bacnet/basic/object/ao.h" #include "bacnet/basic/object/av.h" @@ -36,6 +43,7 @@ #include "bacnet/basic/object/bv.h" #include "bacnet/basic/object/calendar.h" #include "bacnet/basic/object/command.h" +#include "bacnet/basic/object/credential_data_input.h" #include "bacnet/basic/object/program.h" #include "bacnet/basic/object/lc.h" #include "bacnet/basic/object/lsp.h" @@ -86,7 +94,7 @@ static object_functions_t My_Object_Table[] = { NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, - NULL /* Timer */ }, + NULL /* Timer */, Device_Writable_Property_List }, #if (BACNET_PROTOCOL_REVISION >= 17) { OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count, Network_Port_Index_To_Instance, Network_Port_Valid_Instance, @@ -95,7 +103,8 @@ static object_functions_t My_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 /* Create */, NULL /* Delete */, NULL /* Timer */ }, + NULL /* Create */, NULL /* Delete */, NULL /* Timer */, + Network_Port_Writable_Property_List }, { OBJECT_TIMER, Timer_Init, Timer_Count, Timer_Index_To_Instance, Timer_Valid_Instance, Timer_Object_Name, Timer_Read_Property, @@ -103,7 +112,8 @@ static object_functions_t My_Object_Table[] = { NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, Timer_Add_List_Element, Timer_Remove_List_Element, - Timer_Create, Timer_Delete, Timer_Task }, + Timer_Create, Timer_Delete, Timer_Task, + Timer_Writable_Property_List }, #endif { OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count, Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance, @@ -113,7 +123,8 @@ static object_functions_t My_Object_Table[] = { 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 */, - Analog_Input_Create, Analog_Input_Delete, NULL /* Timer */ }, + Analog_Input_Create, Analog_Input_Delete, NULL /* Timer */, + Analog_Input_Writable_Property_List }, { 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, @@ -122,7 +133,8 @@ static object_functions_t My_Object_Table[] = { Analog_Output_Encode_Value_List, Analog_Output_Change_Of_Value, Analog_Output_Change_Of_Value_Clear, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - Analog_Output_Create, Analog_Output_Delete, NULL /* Timer */ }, + Analog_Output_Create, Analog_Output_Delete, NULL /* Timer */, + Analog_Output_Writable_Property_List }, { 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, @@ -131,7 +143,8 @@ static object_functions_t My_Object_Table[] = { 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 */, - Analog_Value_Create, Analog_Value_Delete, NULL /* Timer */ }, + Analog_Value_Create, Analog_Value_Delete, NULL /* Timer */, + Analog_Value_Writable_Property_List }, { 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, @@ -140,7 +153,8 @@ static object_functions_t My_Object_Table[] = { 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 */, - Binary_Input_Create, Binary_Input_Delete, NULL /* Timer */ }, + Binary_Input_Create, Binary_Input_Delete, NULL /* Timer */, + Binary_Input_Writable_Property_List }, { 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, @@ -149,7 +163,8 @@ static object_functions_t My_Object_Table[] = { Binary_Output_Encode_Value_List, Binary_Output_Change_Of_Value, Binary_Output_Change_Of_Value_Clear, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - Binary_Output_Create, Binary_Output_Delete, NULL /* Timer */ }, + Binary_Output_Create, Binary_Output_Delete, NULL /* Timer */, + Binary_Output_Writable_Property_List }, { 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, @@ -158,7 +173,8 @@ static object_functions_t My_Object_Table[] = { Binary_Value_Encode_Value_List, Binary_Value_Change_Of_Value, Binary_Value_Change_Of_Value_Clear, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - Binary_Value_Create, Binary_Value_Delete, NULL /* Timer */ }, + Binary_Value_Create, Binary_Value_Delete, NULL /* Timer */, + Binary_Value_Writable_Property_List }, { OBJECT_CALENDAR, Calendar_Init, Calendar_Count, Calendar_Index_To_Instance, Calendar_Valid_Instance, Calendar_Object_Name, Calendar_Read_Property, @@ -166,7 +182,8 @@ static object_functions_t My_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 */, - Calendar_Create, Calendar_Delete, NULL /* Timer */ }, + Calendar_Create, Calendar_Delete, NULL /* Timer */, + Calendar_Writable_Property_List }, #if (BACNET_PROTOCOL_REVISION >= 10) { OBJECT_BITSTRING_VALUE, BitString_Value_Init, BitString_Value_Count, BitString_Value_Index_To_Instance, @@ -177,7 +194,8 @@ static object_functions_t My_Object_Table[] = { BitString_Value_Change_Of_Value, BitString_Value_Change_Of_Value_Clear, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, BitString_Value_Create, - BitString_Value_Delete, NULL /* Timer */ }, + BitString_Value_Delete, NULL /* Timer */, + BitString_Value_Writable_Property_List }, { OBJECT_CHARACTERSTRING_VALUE, CharacterString_Value_Init, CharacterString_Value_Count, CharacterString_Value_Index_To_Instance, CharacterString_Value_Valid_Instance, CharacterString_Value_Object_Name, @@ -189,8 +207,8 @@ static object_functions_t My_Object_Table[] = { CharacterString_Value_Change_Of_Value_Clear, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, CharacterString_Value_Create, - CharacterString_Value_Delete, - NULL /* Timer */ }, + CharacterString_Value_Delete, NULL /* Timer */, + CharacterString_Value_Writable_Property_List }, { OBJECT_OCTETSTRING_VALUE, OctetString_Value_Init, OctetString_Value_Count, OctetString_Value_Index_To_Instance, OctetString_Value_Valid_Instance, OctetString_Value_Object_Name, OctetString_Value_Read_Property, @@ -198,7 +216,8 @@ static object_functions_t My_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 /* Create */, NULL /* Delete */, NULL /* Timer */ }, + NULL /* Create */, NULL /* Delete */, NULL /* Timer */, + OctetString_Value_Writable_Property_List }, { OBJECT_POSITIVE_INTEGER_VALUE, PositiveInteger_Value_Init, PositiveInteger_Value_Count, PositiveInteger_Value_Index_To_Instance, PositiveInteger_Value_Valid_Instance, PositiveInteger_Value_Object_Name, @@ -208,7 +227,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, + NULL /* Create */, NULL /* Delete */, NULL /* Timer */, + PositiveInteger_Value_Writable_Property_List }, { OBJECT_TIME_VALUE, Time_Value_Init, Time_Value_Count, Time_Value_Index_To_Instance, Time_Value_Valid_Instance, Time_Value_Object_Name, Time_Value_Read_Property, @@ -216,7 +236,8 @@ static object_functions_t My_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 /* Create */, NULL /* Delete */, NULL /* Timer */ }, + NULL /* Create */, NULL /* Delete */, NULL /* Timer */, + Time_Value_Writable_Property_List }, { 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, @@ -224,7 +245,8 @@ static object_functions_t My_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 */, - Integer_Value_Create, Integer_Value_Delete, NULL /* Timer */ }, + Integer_Value_Create, Integer_Value_Delete, NULL /* Timer */, + Integer_Value_Writable_Property_List }, #endif { OBJECT_COMMAND, Command_Init, Command_Count, Command_Index_To_Instance, Command_Valid_Instance, Command_Object_Name, Command_Read_Property, @@ -232,7 +254,8 @@ static object_functions_t My_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 /* Create */, NULL /* Delete */, NULL /* Timer */ }, + NULL /* Create */, NULL /* Delete */, NULL /* Timer */, + Command_Writable_Property_List }, #if defined(INTRINSIC_REPORTING) { OBJECT_NOTIFICATION_CLASS, Notification_Class_Init, Notification_Class_Count, Notification_Class_Index_To_Instance, @@ -243,7 +266,8 @@ static object_functions_t My_Object_Table[] = { NULL /* COV Clear */, NULL /* Intrinsic Reporting */, Notification_Class_Add_List_Element, Notification_Class_Remove_List_Element, NULL /* Create */, - NULL /* Delete */, NULL /* Timer */ }, + NULL /* Delete */, NULL /* Timer */, + Notification_Class_Writable_Property_List }, #endif { OBJECT_LIFE_SAFETY_POINT, Life_Safety_Point_Init, Life_Safety_Point_Count, Life_Safety_Point_Index_To_Instance, Life_Safety_Point_Valid_Instance, @@ -252,7 +276,8 @@ static object_functions_t My_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 */, - Life_Safety_Point_Create, Life_Safety_Point_Delete, NULL /* Timer */ }, + Life_Safety_Point_Create, Life_Safety_Point_Delete, NULL /* Timer */, + Life_Safety_Point_Writable_Property_List }, { OBJECT_LIFE_SAFETY_ZONE, Life_Safety_Zone_Init, Life_Safety_Zone_Count, Life_Safety_Zone_Index_To_Instance, Life_Safety_Zone_Valid_Instance, Life_Safety_Zone_Object_Name, Life_Safety_Zone_Read_Property, @@ -260,7 +285,8 @@ static object_functions_t My_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 */, - Life_Safety_Zone_Create, Life_Safety_Zone_Delete, NULL /* Timer */ }, + Life_Safety_Zone_Create, Life_Safety_Zone_Delete, NULL /* Timer */, + Life_Safety_Zone_Writable_Property_List }, { 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, @@ -268,7 +294,8 @@ static object_functions_t My_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 */, - Load_Control_Create, Load_Control_Delete, Load_Control_Timer}, + Load_Control_Create, Load_Control_Delete, Load_Control_Timer, + Load_Control_Writable_Property_List }, { 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, @@ -277,7 +304,8 @@ static object_functions_t My_Object_Table[] = { Multistate_Input_Encode_Value_List, Multistate_Input_Change_Of_Value, Multistate_Input_Change_Of_Value_Clear, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - Multistate_Input_Create, Multistate_Input_Delete, NULL /* Timer */ }, + Multistate_Input_Create, Multistate_Input_Delete, NULL /* Timer */, + Multistate_Input_Writable_Property_List }, { OBJECT_MULTI_STATE_OUTPUT, Multistate_Output_Init, Multistate_Output_Count, Multistate_Output_Index_To_Instance, Multistate_Output_Valid_Instance, Multistate_Output_Object_Name, @@ -287,7 +315,8 @@ static object_functions_t My_Object_Table[] = { Multistate_Output_Encode_Value_List, Multistate_Output_Change_Of_Value, Multistate_Output_Change_Of_Value_Clear, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - Multistate_Output_Create, Multistate_Output_Delete, NULL /* Timer */ }, + Multistate_Output_Create, Multistate_Output_Delete, NULL /* Timer */, + Multistate_Output_Writable_Property_List }, { 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, @@ -296,7 +325,8 @@ static object_functions_t My_Object_Table[] = { 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 */, - Multistate_Value_Create, Multistate_Value_Delete, NULL /* Timer */ }, + Multistate_Value_Create, Multistate_Value_Delete, NULL /* Timer */, + Multistate_Value_Writable_Property_List }, { 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, @@ -304,7 +334,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, + NULL /* Create */, NULL /* Delete */, NULL /* Timer */, + Trend_Log_Writable_Property_List }, #if (BACNET_PROTOCOL_REVISION >= 14) { OBJECT_LIGHTING_OUTPUT, Lighting_Output_Init, Lighting_Output_Count, Lighting_Output_Index_To_Instance, Lighting_Output_Valid_Instance, @@ -313,14 +344,16 @@ static object_functions_t My_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 */, - Lighting_Output_Create, Lighting_Output_Delete, Lighting_Output_Timer }, + Lighting_Output_Create, Lighting_Output_Delete, Lighting_Output_Timer, + Lighting_Output_Writable_Property_List }, { 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 */, - Channel_Create, Channel_Delete, NULL /* Timer */ }, + Channel_Create, Channel_Delete, NULL /* Timer */, + Channel_Writable_Property_List }, #endif #if (BACNET_PROTOCOL_REVISION >= 16) { OBJECT_BINARY_LIGHTING_OUTPUT, Binary_Lighting_Output_Init, @@ -334,7 +367,8 @@ static object_functions_t My_Object_Table[] = { NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, Binary_Lighting_Output_Create, Binary_Lighting_Output_Delete, - Binary_Lighting_Output_Timer }, + Binary_Lighting_Output_Timer, + Binary_Lighting_Output_Writable_Property_List }, #endif #if (BACNET_PROTOCOL_REVISION >= 24) { OBJECT_COLOR, Color_Init, Color_Count, Color_Index_To_Instance, @@ -343,7 +377,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - Color_Create, Color_Delete, Color_Timer }, + Color_Create, Color_Delete, Color_Timer, + Color_Writable_Property_List }, { 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, @@ -352,7 +387,7 @@ static object_functions_t My_Object_Table[] = { NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, Color_Temperature_Create, Color_Temperature_Delete, - Color_Temperature_Timer }, + Color_Temperature_Timer, Color_Temperature_Writable_Property_List }, #endif #if defined(BACFILE) { OBJECT_FILE, bacfile_init, bacfile_count, bacfile_index_to_instance, @@ -361,7 +396,8 @@ static object_functions_t My_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 */, - bacfile_create, bacfile_delete, NULL /* Timer */ }, + bacfile_create, bacfile_delete, NULL /* Timer */, + bacfile_Writable_Property_List }, #endif { OBJECT_SCHEDULE, Schedule_Init, Schedule_Count, Schedule_Index_To_Instance, Schedule_Valid_Instance, @@ -370,7 +406,7 @@ static object_functions_t My_Object_Table[] = { NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, - NULL /* Timer */ }, + NULL /* Timer */, Schedule_Writable_Property_List }, { OBJECT_STRUCTURED_VIEW, Structured_View_Init, Structured_View_Count, Structured_View_Index_To_Instance, Structured_View_Valid_Instance, Structured_View_Object_Name, Structured_View_Read_Property, @@ -378,7 +414,8 @@ static object_functions_t My_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 */, - Structured_View_Create, Structured_View_Delete, NULL /* Timer */ }, + Structured_View_Create, Structured_View_Delete, NULL /* Timer */, + Structured_View_Writable_Property_List }, { OBJECT_ACCUMULATOR, Accumulator_Init, Accumulator_Count, Accumulator_Index_To_Instance, Accumulator_Valid_Instance, Accumulator_Object_Name, Accumulator_Read_Property, @@ -386,7 +423,8 @@ static object_functions_t My_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 /* Create */, NULL /* Delete */, NULL /* Timer */ }, + NULL /* Create */, NULL /* Delete */, NULL /* Timer */, + Accumulator_Writable_Property_List }, { OBJECT_LOOP, Loop_Init, Loop_Count, Loop_Index_To_Instance, Loop_Valid_Instance, Loop_Object_Name, Loop_Read_Property, @@ -394,7 +432,7 @@ static object_functions_t My_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 */, - Loop_Create, Loop_Delete, Loop_Timer }, + Loop_Create, Loop_Delete, Loop_Timer, Loop_Writable_Property_List }, { OBJECT_PROGRAM, Program_Init, Program_Count, Program_Index_To_Instance, Program_Valid_Instance, Program_Object_Name, Program_Read_Property, @@ -402,7 +440,86 @@ static object_functions_t My_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 */, - Program_Create, Program_Delete, Program_Timer }, + Program_Create, Program_Delete, Program_Timer, + Program_Writable_Property_List }, +#if (BACNET_PROTOCOL_REVISION >= 9) + {OBJECT_ACCESS_CREDENTIAL, Access_Credential_Init, Access_Credential_Count, + Access_Credential_Index_To_Instance, Access_Credential_Valid_Instance, + Access_Credential_Object_Name, Access_Credential_Read_Property, + Access_Credential_Write_Property, Access_Credential_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 /* Create */, NULL /* Delete */, NULL /* Timer */, + Access_Credential_Writable_Property_List }, + {OBJECT_ACCESS_DOOR, Access_Door_Init, Access_Door_Count, + Access_Door_Index_To_Instance, Access_Door_Valid_Instance, + Access_Door_Object_Name, Access_Door_Read_Property, + Access_Door_Write_Property, Access_Door_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 /* Create */, NULL /* Delete */, NULL /* Timer */, + Access_Door_Writable_Property_List }, + {OBJECT_ACCESS_POINT, Access_Point_Init, Access_Point_Count, + Access_Point_Index_To_Instance, Access_Point_Valid_Instance, + Access_Point_Object_Name, Access_Point_Read_Property, + Access_Point_Write_Property, Access_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 /* Create */, NULL /* Delete */, NULL /* Timer */, + Access_Point_Writable_Property_List }, + {OBJECT_ACCESS_RIGHTS, Access_Rights_Init, Access_Rights_Count, + Access_Rights_Index_To_Instance, Access_Rights_Valid_Instance, + Access_Rights_Object_Name, Access_Rights_Read_Property, + Access_Rights_Write_Property, Access_Rights_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 /* Create */, NULL /* Delete */, NULL /* Timer */, + Access_Rights_Writable_Property_List }, + {OBJECT_ACCESS_USER, Access_User_Init, Access_User_Count, + Access_User_Index_To_Instance, Access_User_Valid_Instance, + Access_User_Object_Name, Access_User_Read_Property, + Access_User_Write_Property, Access_User_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 /* Create */, NULL /* Delete */, NULL /* Timer */, + Access_User_Writable_Property_List }, + {OBJECT_ACCESS_ZONE, Access_Zone_Init, Access_Zone_Count, + Access_Zone_Index_To_Instance, Access_Zone_Valid_Instance, + Access_Zone_Object_Name, Access_Zone_Read_Property, + Access_Zone_Write_Property, Access_Zone_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 /* Create */, NULL /* Delete */, NULL /* Timer */, + Access_Zone_Writable_Property_List }, + {OBJECT_CREDENTIAL_DATA_INPUT, Credential_Data_Input_Init, + Credential_Data_Input_Count, Credential_Data_Input_Index_To_Instance, + Credential_Data_Input_Valid_Instance, + Credential_Data_Input_Object_Name, Credential_Data_Input_Read_Property, + Credential_Data_Input_Write_Property, + Credential_Data_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 /* Create */, NULL /* Delete */, NULL /* Timer */, + Credential_Data_Input_Writable_Property_List }, +#endif +#if (BACNET_PROTOCOL_REVISION >= 20) + {OBJECT_AUDIT_LOG, Audit_Log_Init, Audit_Log_Count, + Audit_Log_Index_To_Instance, Audit_Log_Valid_Instance, + Audit_Log_Object_Name, Audit_Log_Read_Property, + Audit_Log_Write_Property, Audit_Log_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 /* Create */, NULL /* Delete */, NULL /* Timer */, + Audit_Log_Writable_Property_List }, +#endif { MAX_BACNET_OBJECT_TYPE, NULL /* Init */, NULL /* Count */, NULL /* Index_To_Instance */, NULL /* Valid_Instance */, NULL /* Object_Name */, NULL /* Read_Property */, @@ -410,7 +527,8 @@ static object_functions_t My_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 /* Create */, NULL /* Delete */, NULL /* Timer */ }, + NULL /* Create */, NULL /* Delete */, NULL /* Timer */, + NULL /* Writable_Property_List */ }, }; /* clang-format on */ @@ -509,6 +627,31 @@ void Device_Objects_Property_List( return; } +/** + * @brief Get the Writeable Property List for an object type + * @param object_type - object type of the object + * @param object_instance - object-instance number of the object + * @param properties - pointer to the list of writable properties + * @return The number of properties in the writable property list + */ +uint32_t Device_Objects_Writable_Property_List( + BACNET_OBJECT_TYPE object_type, + uint32_t object_instance, + const int32_t **properties) +{ + uint32_t count = 0; + struct object_functions *pObject = NULL; + + (void)object_instance; + pObject = Device_Object_Functions_Find(object_type); + if ((pObject != NULL) && (pObject->Object_Writable_Property_List != NULL)) { + pObject->Object_Writable_Property_List(object_instance, properties); + count = property_list_count(*properties); + } + + return count; +} + /* These three arrays are used by the ReadPropertyMultiple handler */ static const int32_t Device_Properties_Required[] = { /* List of Required properties in this object */ @@ -561,6 +704,37 @@ static const int32_t Device_Properties_Optional[] = { static const int32_t Device_Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of writable properties */ + PROP_OBJECT_IDENTIFIER, + PROP_OBJECT_NAME, + PROP_SYSTEM_STATUS, + PROP_VENDOR_IDENTIFIER, + PROP_MODEL_NAME, + PROP_LOCATION, + PROP_DESCRIPTION, + PROP_PROTOCOL_SERVICES_SUPPORTED, + PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED, + PROP_APDU_TIMEOUT, + PROP_NUMBER_OF_APDU_RETRIES, + PROP_UTC_OFFSET, +#if defined(BACNET_TIME_MASTER) + PROP_TIME_SYNCHRONIZATION_INTERVAL, + PROP_ALIGN_INTERVALS, + PROP_INTERVAL_OFFSET, +#endif +#if defined(BACDL_MSTP) + PROP_MAX_INFO_FRAMES, + PROP_MAX_MASTER, +#endif + PROP_TIME_OF_DEVICE_RESTART, + -1 +}; + /** * @brief Returns the list of required, optional, and proprietary properties * for the Device object. @@ -590,6 +764,20 @@ void Device_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Device object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Device_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Determine if the object property is a member of this object instance * @param object_type - object type of the object diff --git a/src/bacnet/basic/object/device.h b/src/bacnet/basic/object/device.h index f9fc24a9..cc744121 100644 --- a/src/bacnet/basic/object/device.h +++ b/src/bacnet/basic/object/device.h @@ -140,6 +140,7 @@ typedef struct object_functions { create_object_function Object_Create; delete_object_function Object_Delete; object_timer_function Object_Timer; + writable_property_list_function Object_Writable_Property_List; } object_functions_t; /* String Lengths - excluding any nul terminator */ @@ -251,10 +252,18 @@ void Device_Objects_Property_List( uint32_t object_instance, struct special_property_list_t *pPropertyList); BACNET_STACK_EXPORT +void Device_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); +BACNET_STACK_EXPORT bool Device_Objects_Property_List_Member( BACNET_OBJECT_TYPE object_type, uint32_t object_instance, BACNET_PROPERTY_ID object_property); +BACNET_STACK_EXPORT +uint32_t Device_Objects_Writable_Property_List( + BACNET_OBJECT_TYPE object_type, + uint32_t object_instance, + const int32_t **properties); /* functions to support COV */ BACNET_STACK_EXPORT diff --git a/src/bacnet/basic/object/iv.c b/src/bacnet/basic/object/iv.c index ca252d11..4ea40d71 100644 --- a/src/bacnet/basic/object/iv.c +++ b/src/bacnet/basic/object/iv.c @@ -66,6 +66,15 @@ static const int32_t Integer_Value_Properties_Optional[] = { static const int32_t Integer_Value_Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PRESENT_VALUE, PROP_COV_INCREMENT, PROP_OUT_OF_SERVICE, PROP_UNITS, -1 +}; + /** * Returns the list of required, optional, and proprietary properties. * Used by ReadPropertyMultiple service. @@ -95,6 +104,20 @@ void Integer_Value_Property_Lists( return; } +/** + * @brief Get the list of writable properties for an Integer Value object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Integer_Value_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Gets an object from the list using an instance number as the key * @param object_instance - object-instance number of the object diff --git a/src/bacnet/basic/object/iv.h b/src/bacnet/basic/object/iv.h index 82d2fba5..cf7c4c2c 100644 --- a/src/bacnet/basic/object/iv.h +++ b/src/bacnet/basic/object/iv.h @@ -35,6 +35,10 @@ void Integer_Value_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Integer_Value_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Integer_Value_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned Integer_Value_Count(void); diff --git a/src/bacnet/basic/object/lc.c b/src/bacnet/basic/object/lc.c index fa0e8ccf..4045dcd5 100644 --- a/src/bacnet/basic/object/lc.c +++ b/src/bacnet/basic/object/lc.c @@ -99,9 +99,9 @@ struct object_data { /* Key List for storing the object data sorted by instance number */ static OS_Keylist Object_List; -/* clang-format off */ /* These three arrays are used by the ReadPropertyMultiple handler */ static const int32_t Load_Control_Properties_Required[] = { + /* unordered list of required properties */ PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE, @@ -121,16 +121,29 @@ static const int32_t Load_Control_Properties_Required[] = { }; static const int32_t Load_Control_Properties_Optional[] = { - PROP_DESCRIPTION, - PROP_FULL_DUTY_BASELINE, + /* unordered list of optional properties */ + PROP_DESCRIPTION, PROP_FULL_DUTY_BASELINE, -1 +}; + +static const int32_t Load_Control_Properties_Proprietary[] = { -1 }; + +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ -1 }; -static const int32_t Load_Control_Properties_Proprietary[] = { - -1 -}; -/* clang-format on */ - +/** + * Returns the list of required, optional, and proprietary properties. + * Used by ReadPropertyMultiple service. + * + * @param pRequired - Pointer to the pointer of required values. + * @param pOptional - Pointer to the pointer of optional values. + * @param pProprietary - Pointer to the pointer of properitary values. + */ void Load_Control_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, @@ -149,6 +162,20 @@ void Load_Control_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Load Control object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Load_Control_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Gets an object from the list using an instance number as the key * @param object_instance - object-instance number of the object diff --git a/src/bacnet/basic/object/lc.h b/src/bacnet/basic/object/lc.h index b36ca4bd..f69bb542 100644 --- a/src/bacnet/basic/object/lc.h +++ b/src/bacnet/basic/object/lc.h @@ -77,6 +77,9 @@ void Load_Control_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, const int32_t **pProprietary); +BACNET_STACK_EXPORT +void Load_Control_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); BACNET_STACK_DEPRECATED("Use Load_Control_Timer() instead") BACNET_STACK_EXPORT diff --git a/src/bacnet/basic/object/lo.c b/src/bacnet/basic/object/lo.c index e6451630..a7ab5d96 100644 --- a/src/bacnet/basic/object/lo.c +++ b/src/bacnet/basic/object/lo.c @@ -115,6 +115,24 @@ static const int32_t Properties_Optional[] = { static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PRESENT_VALUE, PROP_LIGHTING_COMMAND, + PROP_OUT_OF_SERVICE, PROP_DEFAULT_FADE_TIME, + PROP_DEFAULT_RAMP_RATE, PROP_DEFAULT_STEP_INCREMENT, + PROP_TRANSITION, PROP_RELINQUISH_DEFAULT, + PROP_LAST_ON_VALUE, PROP_DEFAULT_ON_VALUE, + PROP_HIGH_END_TRIM, PROP_LOW_END_TRIM, + PROP_TRIM_FADE_TIME, PROP_BLINK_WARN_ENABLE, + PROP_EGRESS_TIME, PROP_LIGHTING_COMMAND_DEFAULT_PRIORITY, + PROP_FEEDBACK_VALUE, PROP_POWER, + PROP_INSTANTANEOUS_POWER, -1 +}; + /** * @brief compare two floating point values to 3 decimal places * @@ -156,6 +174,20 @@ void Lighting_Output_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Lighting Output object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Lighting_Output_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * Determines if a given Lighting Output instance is valid * diff --git a/src/bacnet/basic/object/lo.h b/src/bacnet/basic/object/lo.h index a3208202..319e597a 100644 --- a/src/bacnet/basic/object/lo.h +++ b/src/bacnet/basic/object/lo.h @@ -27,6 +27,10 @@ void Lighting_Output_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Lighting_Output_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Lighting_Output_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned Lighting_Output_Count(void); diff --git a/src/bacnet/basic/object/loop.c b/src/bacnet/basic/object/loop.c index c73b7eed..2a4848b1 100644 --- a/src/bacnet/basic/object/loop.c +++ b/src/bacnet/basic/object/loop.c @@ -124,6 +124,36 @@ static const int32_t *Properties_Proprietary_Extended; static write_property_function Write_Property_Proprietary_Callback; static read_property_function Read_Property_Proprietary_Callback; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + PROP_PRESENT_VALUE, + PROP_OUT_OF_SERVICE, + PROP_ACTION, + PROP_UPDATE_INTERVAL, + PROP_OUTPUT_UNITS, + PROP_CONTROLLED_VARIABLE_VALUE, + PROP_CONTROLLED_VARIABLE_UNITS, + PROP_PROPORTIONAL_CONSTANT, + PROP_PROPORTIONAL_CONSTANT_UNITS, + PROP_INTEGRAL_CONSTANT, + PROP_INTEGRAL_CONSTANT_UNITS, + PROP_DERIVATIVE_CONSTANT, + PROP_DERIVATIVE_CONSTANT_UNITS, + PROP_BIAS, + PROP_SETPOINT, + PROP_MINIMUM_OUTPUT, + PROP_MAXIMUM_OUTPUT, + PROP_PRIORITY_FOR_WRITING, + PROP_MANIPULATED_VARIABLE_REFERENCE, + PROP_CONTROLLED_VARIABLE_REFERENCE, + PROP_SETPOINT_REFERENCE, + PROP_COV_INCREMENT, + -1 +}; + /** * Returns the list of required, optional, and proprietary properties. * Used by ReadPropertyMultiple service. @@ -157,6 +187,20 @@ void Loop_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Loop object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Loop_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Determine if the property is a member of this object * @param object_property - object-property to be checked diff --git a/src/bacnet/basic/object/loop.h b/src/bacnet/basic/object/loop.h index e1f02897..c6132768 100644 --- a/src/bacnet/basic/object/loop.h +++ b/src/bacnet/basic/object/loop.h @@ -43,6 +43,10 @@ void Loop_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Loop_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT void Loop_Proprietary_Property_List_Set(const int32_t *pProprietary); BACNET_STACK_EXPORT void Loop_Read_Property_Proprietary_Callback_Set(read_property_function cb); diff --git a/src/bacnet/basic/object/lsp.c b/src/bacnet/basic/object/lsp.c index 9c8664b8..f93a7174 100644 --- a/src/bacnet/basic/object/lsp.c +++ b/src/bacnet/basic/object/lsp.c @@ -52,6 +52,16 @@ static const int32_t Life_Safety_Point_Properties_Optional[] = { -1 }; static const int32_t Life_Safety_Point_Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_MODE, PROP_PRESENT_VALUE, PROP_OUT_OF_SERVICE, + PROP_SILENCED, PROP_OPERATION_EXPECTED, -1 +}; + /** * Returns the list of required, optional, and proprietary properties. * Used by ReadPropertyMultiple service. @@ -81,6 +91,20 @@ void Life_Safety_Point_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Life Safety Point object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Life_Safety_Point_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Determines if a given object instance is valid * @param object_instance - object-instance number of the object diff --git a/src/bacnet/basic/object/lsp.h b/src/bacnet/basic/object/lsp.h index 382ce1fd..77af3d12 100644 --- a/src/bacnet/basic/object/lsp.h +++ b/src/bacnet/basic/object/lsp.h @@ -26,6 +26,10 @@ void Life_Safety_Point_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Life_Safety_Point_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Life_Safety_Point_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned Life_Safety_Point_Count(void); diff --git a/src/bacnet/basic/object/lsz.c b/src/bacnet/basic/object/lsz.c index 6a6ab0cc..a94a3400 100644 --- a/src/bacnet/basic/object/lsz.c +++ b/src/bacnet/basic/object/lsz.c @@ -63,6 +63,21 @@ static const int32_t Life_Safety_Zone_Properties_Optional[] = { -1 }; static const int32_t Life_Safety_Zone_Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_MODE, + PROP_PRESENT_VALUE, + PROP_OUT_OF_SERVICE, + PROP_SILENCED, + PROP_OPERATION_EXPECTED, + PROP_ZONE_MEMBERS, + -1 +}; + /** * Returns the list of required, optional, and proprietary properties. * Used by ReadPropertyMultiple service. @@ -92,6 +107,20 @@ void Life_Safety_Zone_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Life Safety Zone object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Life_Safety_Zone_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Determines if a given object instance is valid * @param object_instance - object-instance number of the object diff --git a/src/bacnet/basic/object/lsz.h b/src/bacnet/basic/object/lsz.h index d67c13ea..a03883b5 100644 --- a/src/bacnet/basic/object/lsz.h +++ b/src/bacnet/basic/object/lsz.h @@ -26,6 +26,10 @@ void Life_Safety_Zone_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Life_Safety_Zone_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Life_Safety_Zone_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned Life_Safety_Zone_Count(void); diff --git a/src/bacnet/basic/object/ms-input.c b/src/bacnet/basic/object/ms-input.c index a9c6f6fb..fb237395 100644 --- a/src/bacnet/basic/object/ms-input.c +++ b/src/bacnet/basic/object/ms-input.c @@ -62,6 +62,15 @@ static const int32_t Properties_Optional[] = { static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + -1 +}; + /** * Initialize the pointers for the required, the optional and the properitary * value properties. @@ -88,6 +97,20 @@ void Multistate_Input_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Multi-State Input object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Multistate_Input_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Gets an object from the list using an instance number as the key * @param object_instance - object-instance number of the object diff --git a/src/bacnet/basic/object/ms-input.h b/src/bacnet/basic/object/ms-input.h index 7c0c2505..91a9ad94 100644 --- a/src/bacnet/basic/object/ms-input.h +++ b/src/bacnet/basic/object/ms-input.h @@ -35,6 +35,9 @@ void Multistate_Input_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, const int32_t **pProprietary); +BACNET_STACK_EXPORT +void Multistate_Input_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); BACNET_STACK_EXPORT bool Multistate_Input_Valid_Instance(uint32_t object_instance); diff --git a/src/bacnet/basic/object/mso.c b/src/bacnet/basic/object/mso.c index d67fc96d..af879f05 100644 --- a/src/bacnet/basic/object/mso.c +++ b/src/bacnet/basic/object/mso.c @@ -81,6 +81,15 @@ static const int32_t Properties_Optional[] = { static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PRESENT_VALUE, PROP_OUT_OF_SERVICE, PROP_RELINQUISH_DEFAULT, -1 +}; + /** * @brief Returns the list of required, optional, and proprietary properties. * Used by ReadPropertyMultiple service. @@ -109,6 +118,20 @@ void Multistate_Output_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Multi-State Output object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Multistate_Output_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Determines if a given Multistate instance is valid * @param object_instance - object-instance number of the object diff --git a/src/bacnet/basic/object/mso.h b/src/bacnet/basic/object/mso.h index e4b64272..eb20e6a7 100644 --- a/src/bacnet/basic/object/mso.h +++ b/src/bacnet/basic/object/mso.h @@ -37,6 +37,10 @@ void Multistate_Output_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Multistate_Output_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Multistate_Output_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned Multistate_Output_Count(void); diff --git a/src/bacnet/basic/object/msv.c b/src/bacnet/basic/object/msv.c index d4d1ee6d..8b4b0291 100644 --- a/src/bacnet/basic/object/msv.c +++ b/src/bacnet/basic/object/msv.c @@ -62,6 +62,15 @@ static const int32_t Properties_Optional[] = { static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PRESENT_VALUE, PROP_OUT_OF_SERVICE, -1 +}; + /** * Initialize the pointers for the required, the optional and the properitary * value properties. @@ -88,6 +97,20 @@ void Multistate_Value_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Multi-State Value object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Multistate_Value_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Gets an object from the list using an instance number as the key * @param object_instance - object-instance number of the object diff --git a/src/bacnet/basic/object/msv.h b/src/bacnet/basic/object/msv.h index 24443957..5d5bc34e 100644 --- a/src/bacnet/basic/object/msv.h +++ b/src/bacnet/basic/object/msv.h @@ -35,6 +35,9 @@ void Multistate_Value_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, const int32_t **pProprietary); +BACNET_STACK_EXPORT +void Multistate_Value_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); BACNET_STACK_EXPORT bool Multistate_Value_Valid_Instance(uint32_t object_instance); diff --git a/src/bacnet/basic/object/nc.c b/src/bacnet/basic/object/nc.c index da490b9d..a51d4d59 100644 --- a/src/bacnet/basic/object/nc.c +++ b/src/bacnet/basic/object/nc.c @@ -50,6 +50,15 @@ static const int32_t Properties_Optional[] = { PROP_DESCRIPTION, -1 }; static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PRIORITY, PROP_ACK_REQUIRED, PROP_RECIPIENT_LIST, -1 +}; + void Notification_Class_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, @@ -67,6 +76,20 @@ void Notification_Class_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Notification Class object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Notification_Class_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + void Notification_Class_Init(void) { uint8_t NotifyIdx = 0; diff --git a/src/bacnet/basic/object/nc.h b/src/bacnet/basic/object/nc.h index 210b0fbe..a91c0397 100644 --- a/src/bacnet/basic/object/nc.h +++ b/src/bacnet/basic/object/nc.h @@ -55,6 +55,9 @@ void Notification_Class_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, const int32_t **pProprietary); +BACNET_STACK_EXPORT +void Notification_Class_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); BACNET_STACK_EXPORT void Notification_Class_Init(void); diff --git a/src/bacnet/basic/object/netport.c b/src/bacnet/basic/object/netport.c index c997670c..ca500b63 100644 --- a/src/bacnet/basic/object/netport.c +++ b/src/bacnet/basic/object/netport.c @@ -168,6 +168,10 @@ static const int32_t Ethernet_Port_Properties_Optional[] = { #endif -1 }; +static const int32_t Ethernet_Port_Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_MAC_ADDRESS, PROP_LINK_SPEED, -1 +}; static const int32_t Zigbee_Port_Properties_Optional[] = { /* unordered list of optional properties */ @@ -182,6 +186,10 @@ static const int32_t Zigbee_Port_Properties_Optional[] = { #endif -1 }; +static const int32_t Zigbee_Port_Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_MAC_ADDRESS, PROP_LINK_SPEED, -1 +}; static const int32_t MSTP_Port_Properties_Optional[] = { /* unordered list of optional properties */ @@ -198,6 +206,10 @@ static const int32_t MSTP_Port_Properties_Optional[] = { #endif -1 }; +static const int32_t MSTP_Port_Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_MAC_ADDRESS, PROP_MAX_MASTER, PROP_MAX_INFO_FRAMES, PROP_LINK_SPEED, -1 +}; static const int32_t BIP_Port_Properties_Optional[] = { /* unordered list of optional properties */ @@ -232,6 +244,17 @@ static const int32_t BIP_Port_Properties_Optional[] = { #endif -1 }; +static const int32_t BIP_Port_Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_MAC_ADDRESS, + PROP_LINK_SPEED, + PROP_FD_BBMD_ADDRESS, + PROP_FD_SUBSCRIPTION_LIFETIME, + PROP_BBMD_ACCEPT_FD_REGISTRATIONS, + PROP_BBMD_BROADCAST_DISTRIBUTION_TABLE, + PROP_BBMD_FOREIGN_DEVICE_TABLE, + -1 +}; static const int32_t BIP6_Port_Properties_Optional[] = { /* unordered list of optional properties */ @@ -269,6 +292,17 @@ static const int32_t BIP6_Port_Properties_Optional[] = { #endif -1 }; +static const int32_t BIP6_Port_Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_MAC_ADDRESS, + PROP_LINK_SPEED, + PROP_FD_BBMD_ADDRESS, + PROP_FD_SUBSCRIPTION_LIFETIME, + PROP_BBMD_ACCEPT_FD_REGISTRATIONS, + PROP_BBMD_BROADCAST_DISTRIBUTION_TABLE, + PROP_BBMD_FOREIGN_DEVICE_TABLE, + -1 +}; static const int32_t BSC_Port_Properties_Optional[] = { PROP_NETWORK_NUMBER, @@ -316,6 +350,17 @@ static const int32_t BSC_Port_Properties_Optional[] = { PROP_SC_FAILED_CONNECTION_REQUESTS, -1 }; +static const int32_t BSC_Port_Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_MAC_ADDRESS, + PROP_LINK_SPEED, + PROP_FD_BBMD_ADDRESS, + PROP_FD_SUBSCRIPTION_LIFETIME, + PROP_BBMD_ACCEPT_FD_REGISTRATIONS, + PROP_BBMD_BROADCAST_DISTRIBUTION_TABLE, + PROP_BBMD_FOREIGN_DEVICE_TABLE, + -1 +}; static const int32_t Network_Port_Properties_Proprietary[] = { -1 }; @@ -375,6 +420,44 @@ void Network_Port_Property_List( return; } +/** + * @brief Get the list of writable properties for a Network Port object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Network_Port_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + unsigned index; + + index = Network_Port_Instance_To_Index(object_instance); + if (index < BACNET_NETWORK_PORTS_MAX) { + if (index < BACNET_NETWORK_PORTS_MAX) { + switch (Object_List[index].Network_Type) { + case PORT_TYPE_MSTP: + *properties = MSTP_Port_Writable_Properties; + break; + case PORT_TYPE_BIP: + *properties = BIP_Port_Writable_Properties; + break; + case PORT_TYPE_BSC: + *properties = BSC_Port_Writable_Properties; + break; + case PORT_TYPE_BIP6: + *properties = BIP6_Port_Writable_Properties; + break; + case PORT_TYPE_ZIGBEE: + *properties = Zigbee_Port_Writable_Properties; + break; + case PORT_TYPE_ETHERNET: + default: + *properties = Ethernet_Port_Writable_Properties; + break; + } + } + } +} + /** * Returns the list of required, optional, and proprietary properties. * Used by ReadPropertyMultiple service. diff --git a/src/bacnet/basic/object/netport.h b/src/bacnet/basic/object/netport.h index 2e61e78c..212ff760 100644 --- a/src/bacnet/basic/object/netport.h +++ b/src/bacnet/basic/object/netport.h @@ -47,6 +47,9 @@ void Network_Port_Property_List( const int32_t **pRequired, const int32_t **pOptional, const int32_t **pProprietary); +BACNET_STACK_EXPORT +void Network_Port_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); BACNET_STACK_EXPORT bool Network_Port_Object_Name( diff --git a/src/bacnet/basic/object/osv.c b/src/bacnet/basic/object/osv.c index 929193cc..4680f4ef 100644 --- a/src/bacnet/basic/object/osv.c +++ b/src/bacnet/basic/object/osv.c @@ -26,16 +26,27 @@ static OCTETSTRING_VALUE_DESCR OSV_Descr[MAX_OCTETSTRING_VALUES]; /* These three arrays are used by the ReadPropertyMultiple handler */ -static const int32_t OctetString_Value_Properties_Required[] = { +static const int32_t Properties_Required[] = { + /* unordered list of required properties */ PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE, PROP_PRESENT_VALUE, PROP_STATUS_FLAGS, -1 }; -static const int32_t OctetString_Value_Properties_Optional[] = { +static const int32_t Properties_Optional[] = { + /* unordered list of optional properties */ PROP_EVENT_STATE, PROP_OUT_OF_SERVICE, PROP_DESCRIPTION, -1 }; -static const int32_t OctetString_Value_Properties_Proprietary[] = { -1 }; +static const int32_t Properties_Proprietary[] = { -1 }; + +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PRESENT_VALUE, PROP_OUT_OF_SERVICE, -1 +}; void OctetString_Value_Property_Lists( const int32_t **pRequired, @@ -43,18 +54,32 @@ void OctetString_Value_Property_Lists( const int32_t **pProprietary) { if (pRequired) { - *pRequired = OctetString_Value_Properties_Required; + *pRequired = Properties_Required; } if (pOptional) { - *pOptional = OctetString_Value_Properties_Optional; + *pOptional = Properties_Optional; } if (pProprietary) { - *pProprietary = OctetString_Value_Properties_Proprietary; + *pProprietary = Properties_Proprietary; } return; } +/** + * @brief Get the list of writable properties for an Octet String Value object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void OctetString_Value_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + void OctetString_Value_Init(void) { unsigned i; @@ -304,19 +329,16 @@ bool OctetString_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) CurrentAV->Out_Of_Service = value.type.Boolean; } break; - - case PROP_OBJECT_IDENTIFIER: - case PROP_OBJECT_NAME: - case PROP_OBJECT_TYPE: - case PROP_STATUS_FLAGS: - case PROP_EVENT_STATE: - case PROP_DESCRIPTION: - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; - break; default: - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; + if (property_lists_member( + Properties_Required, Properties_Optional, + Properties_Proprietary, wp_data->object_property)) { + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; + } else { + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; + } break; } diff --git a/src/bacnet/basic/object/osv.h b/src/bacnet/basic/object/osv.h index 1b09f9fc..1e0abcb7 100644 --- a/src/bacnet/basic/object/osv.h +++ b/src/bacnet/basic/object/osv.h @@ -32,6 +32,10 @@ void OctetString_Value_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void OctetString_Value_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool OctetString_Value_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned OctetString_Value_Count(void); diff --git a/src/bacnet/basic/object/piv.c b/src/bacnet/basic/object/piv.c index 53a005b1..d34d5071 100644 --- a/src/bacnet/basic/object/piv.c +++ b/src/bacnet/basic/object/piv.c @@ -26,7 +26,8 @@ static POSITIVEINTEGER_VALUE_DESCR PIV_Descr[MAX_POSITIVEINTEGER_VALUES]; /* These three arrays are used by the ReadPropertyMultiple handler */ -static const int32_t PositiveInteger_Value_Properties_Required[] = { +static const int32_t Properties_Required[] = { + /* unordered list of required properties */ PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE, @@ -36,30 +37,68 @@ static const int32_t PositiveInteger_Value_Properties_Required[] = { -1 }; -static const int32_t PositiveInteger_Value_Properties_Optional[] = { +static const int32_t Properties_Optional[] = { + /* unordered list of optional properties */ PROP_OUT_OF_SERVICE, -1 }; -static const int32_t PositiveInteger_Value_Properties_Proprietary[] = { -1 }; +static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PRESENT_VALUE, PROP_OUT_OF_SERVICE, PROP_UNITS, -1 +}; + +/** + * @brief Returns the list of required, optional, and proprietary properties. + * Used by ReadPropertyMultiple service. + * + * @param pRequired - pointer to list of int terminated by -1, of + * BACnet required properties for this object. + * @param pOptional - pointer to list of int terminated by -1, of + * BACnet optional properties for this object. + * @param pProprietary - pointer to list of int terminated by -1, of + * BACnet proprietary properties for this object. + */ void PositiveInteger_Value_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, const int32_t **pProprietary) { if (pRequired) { - *pRequired = PositiveInteger_Value_Properties_Required; + *pRequired = Properties_Required; } if (pOptional) { - *pOptional = PositiveInteger_Value_Properties_Optional; + *pOptional = Properties_Optional; } if (pProprietary) { - *pProprietary = PositiveInteger_Value_Properties_Proprietary; + *pProprietary = Properties_Proprietary; } return; } +/** + * @brief Get list of writable properties for a Positive Integer Value object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void PositiveInteger_Value_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + +/** + * @brief Initializes the Positive Integer Value objects + */ void PositiveInteger_Value_Init(void) { unsigned i; @@ -345,10 +384,8 @@ bool PositiveInteger_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) break; default: if (property_lists_member( - PositiveInteger_Value_Properties_Required, - PositiveInteger_Value_Properties_Optional, - PositiveInteger_Value_Properties_Proprietary, - wp_data->object_property)) { + Properties_Required, Properties_Optional, + Properties_Proprietary, wp_data->object_property)) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } else { diff --git a/src/bacnet/basic/object/piv.h b/src/bacnet/basic/object/piv.h index b6cc9c2b..52f72c5b 100644 --- a/src/bacnet/basic/object/piv.h +++ b/src/bacnet/basic/object/piv.h @@ -32,6 +32,10 @@ void PositiveInteger_Value_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void PositiveInteger_Value_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool PositiveInteger_Value_Valid_Instance(uint32_t object_instance); unsigned PositiveInteger_Value_Count(void); BACNET_STACK_EXPORT diff --git a/src/bacnet/basic/object/program.c b/src/bacnet/basic/object/program.c index 8c4e169a..cf020ac4 100644 --- a/src/bacnet/basic/object/program.c +++ b/src/bacnet/basic/object/program.c @@ -77,6 +77,15 @@ static const int32_t Properties_Optional[] = { static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PROGRAM_CHANGE, PROP_OUT_OF_SERVICE, -1 +}; + /** * Returns the list of required, optional, and proprietary properties. * Used by ReadPropertyMultiple service. @@ -106,6 +115,20 @@ void Program_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Program object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Program_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Gets an object from the list using an instance number as the key * @param object_instance - object-instance number of the object diff --git a/src/bacnet/basic/object/program.h b/src/bacnet/basic/object/program.h index 067bc956..db706596 100644 --- a/src/bacnet/basic/object/program.h +++ b/src/bacnet/basic/object/program.h @@ -26,6 +26,10 @@ void Program_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Program_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Program_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned Program_Count(void); diff --git a/src/bacnet/basic/object/schedule.c b/src/bacnet/basic/object/schedule.c index 2f83053f..bcb64cf9 100644 --- a/src/bacnet/basic/object/schedule.c +++ b/src/bacnet/basic/object/schedule.c @@ -52,6 +52,33 @@ static const int32_t Schedule_Properties_Optional[] = { static const int32_t Schedule_Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_OUT_OF_SERVICE, + PROP_WEEKLY_SCHEDULE, + PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES, + PROP_EFFECTIVE_PERIOD, +#if BACNET_EXCEPTION_SCHEDULE_SIZE + PROP_EXCEPTION_SCHEDULE, +#endif + -1 +}; + +/** + * Returns the list of required, optional, and proprietary properties. + * Used by ReadPropertyMultiple service. + * + * @param pRequired - pointer to list of int terminated by -1, of + * BACnet required properties for this object. + * @param pOptional - pointer to list of int terminated by -1, of + * BACnet optional properties for this object. + * @param pProprietary - pointer to list of int terminated by -1, of + * BACnet proprietary properties for this object. + */ void Schedule_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, @@ -68,6 +95,20 @@ void Schedule_Property_Lists( } } +/** + * @brief Get the list of writable properties for a Schedule object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Schedule_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Gets an object from the list using an instance number * @param object_instance - object-instance number of the object diff --git a/src/bacnet/basic/object/schedule.h b/src/bacnet/basic/object/schedule.h index 95954c3e..3880be65 100644 --- a/src/bacnet/basic/object/schedule.h +++ b/src/bacnet/basic/object/schedule.h @@ -67,6 +67,9 @@ void Schedule_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, const int32_t **pProprietary); +BACNET_STACK_EXPORT +void Schedule_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); BACNET_STACK_EXPORT bool Schedule_Valid_Instance(uint32_t object_instance); diff --git a/src/bacnet/basic/object/structured_view.c b/src/bacnet/basic/object/structured_view.c index 502bca90..02a1c34e 100644 --- a/src/bacnet/basic/object/structured_view.c +++ b/src/bacnet/basic/object/structured_view.c @@ -67,6 +67,15 @@ static const int32_t Properties_Optional[] = { static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + -1 +}; + /** * Returns the list of required, optional, and proprietary properties. * Used by ReadPropertyMultiple service. @@ -96,6 +105,20 @@ void Structured_View_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Structured View object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Structured_View_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * Determines if a given Structured View instance is valid * diff --git a/src/bacnet/basic/object/structured_view.h b/src/bacnet/basic/object/structured_view.h index 5be18868..fccc7b95 100644 --- a/src/bacnet/basic/object/structured_view.h +++ b/src/bacnet/basic/object/structured_view.h @@ -39,6 +39,10 @@ void Structured_View_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Structured_View_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Structured_View_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned Structured_View_Count(void); diff --git a/src/bacnet/basic/object/time_value.c b/src/bacnet/basic/object/time_value.c index 14aa2750..ed0c45a1 100644 --- a/src/bacnet/basic/object/time_value.c +++ b/src/bacnet/basic/object/time_value.c @@ -61,6 +61,15 @@ static const int32_t Time_Value_Properties_Optional[] = { static const int32_t Time_Value_Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PRESENT_VALUE, PROP_OUT_OF_SERVICE, -1 +}; + /** * Returns the list of required, optional, and proprietary properties. * Used by ReadPropertyMultiple service. @@ -90,6 +99,20 @@ void Time_Value_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Time Value object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Time_Value_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * Determines if a given Time Value instance is valid * diff --git a/src/bacnet/basic/object/time_value.h b/src/bacnet/basic/object/time_value.h index 8bc38ab8..c28a2a2c 100644 --- a/src/bacnet/basic/object/time_value.h +++ b/src/bacnet/basic/object/time_value.h @@ -36,6 +36,10 @@ void Time_Value_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Time_Value_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Time_Value_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned Time_Value_Count(void); diff --git a/src/bacnet/basic/object/timer.c b/src/bacnet/basic/object/timer.c index 77296c88..8c179e9d 100644 --- a/src/bacnet/basic/object/timer.c +++ b/src/bacnet/basic/object/timer.c @@ -97,6 +97,24 @@ static const int32_t Properties_Optional[] = { static const int32_t Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_PRESENT_VALUE, + PROP_OUT_OF_SERVICE, + PROP_DEFAULT_TIMEOUT, + PROP_MIN_PRES_VALUE, + PROP_MAX_PRES_VALUE, + PROP_RESOLUTION, + PROP_PRIORITY_FOR_WRITING, + PROP_STATE_CHANGE_VALUES, + PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES, + -1 +}; + /** * Returns the list of required, optional, and proprietary properties. * Used by ReadPropertyMultiple service. @@ -126,6 +144,20 @@ void Timer_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Timer object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Timer_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Gets an object from the list using an instance number as the key * @param object_instance - object-instance number of the object diff --git a/src/bacnet/basic/object/timer.h b/src/bacnet/basic/object/timer.h index 0971025b..8090caea 100644 --- a/src/bacnet/basic/object/timer.h +++ b/src/bacnet/basic/object/timer.h @@ -43,6 +43,10 @@ void Timer_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary); BACNET_STACK_EXPORT +void Timer_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); + +BACNET_STACK_EXPORT bool Timer_Valid_Instance(uint32_t object_instance); BACNET_STACK_EXPORT unsigned Timer_Count(void); diff --git a/src/bacnet/basic/object/trendlog.c b/src/bacnet/basic/object/trendlog.c index 2fadcdea..99ef3e23 100644 --- a/src/bacnet/basic/object/trendlog.c +++ b/src/bacnet/basic/object/trendlog.c @@ -75,6 +75,36 @@ static const int32_t Trend_Log_Properties_Optional[] = { static const int32_t Trend_Log_Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of always writable properties */ + PROP_ENABLE, + PROP_STOP_WHEN_FULL, + PROP_RECORD_COUNT, + PROP_LOGGING_TYPE, + PROP_START_TIME, + PROP_STOP_TIME, + PROP_LOG_DEVICE_OBJECT_PROPERTY, + PROP_LOG_INTERVAL, + PROP_ALIGN_INTERVALS, + PROP_INTERVAL_OFFSET, + PROP_TRIGGER, + -1 +}; + +/** + * @brief Returns the list of required, optional, and proprietary properties. + * Used by ReadPropertyMultiple service. + * @param pRequired - pointer to list of int terminated by -1, of + * BACnet required properties for this object. + * @param pOptional - pointer to list of int terminated by -1, of + * BACnet optional properties for this object. + * @param pProprietary - pointer to list of int terminated by -1, of + * BACnet proprietary properties for this object. + */ void Trend_Log_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, @@ -93,6 +123,20 @@ void Trend_Log_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Trend Log object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Trend_Log_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /* we simply have 0-n object instances. Yours might be */ /* more complex, and then you need validate that the */ /* given instance exists */ diff --git a/src/bacnet/basic/object/trendlog.h b/src/bacnet/basic/object/trendlog.h index cee60415..2a8fef3b 100644 --- a/src/bacnet/basic/object/trendlog.h +++ b/src/bacnet/basic/object/trendlog.h @@ -117,6 +117,9 @@ void Trend_Log_Property_Lists( const int32_t **pRequired, const int32_t **pOptional, const int32_t **pProprietary); +BACNET_STACK_EXPORT +void Trend_Log_Writable_Property_List( + uint32_t object_instance, const int32_t **properties); BACNET_STACK_EXPORT bool Trend_Log_Valid_Instance(uint32_t object_instance); diff --git a/src/bacnet/basic/server/bacnet_device.c b/src/bacnet/basic/server/bacnet_device.c index 8545195e..e5a218ef 100644 --- a/src/bacnet/basic/server/bacnet_device.c +++ b/src/bacnet/basic/server/bacnet_device.c @@ -235,7 +235,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, - NULL /* Timer */ }, + NULL /* Timer */, + Device_Writable_Property_List }, #if defined(CONFIG_BACNET_BASIC_OBJECT_ANALOG_INPUT) { OBJECT_ANALOG_INPUT, Analog_Input_Init, @@ -256,7 +257,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Analog_Input_Create, Analog_Input_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + Analog_Input_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_ANALOG_OUTPUT) { OBJECT_ANALOG_OUTPUT, @@ -278,7 +280,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Analog_Output_Create, Analog_Output_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + Analog_Output_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_ANALOG_VALUE) { OBJECT_ANALOG_VALUE, @@ -300,7 +303,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Analog_Value_Create, Analog_Value_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + Analog_Value_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_AUDIT_LOG) { OBJECT_AUDIT_LOG, @@ -322,7 +326,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Audit_Log_Create, Audit_Log_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + Audit_Log_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_BINARY_INPUT) { OBJECT_BINARY_INPUT, @@ -344,7 +349,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Binary_Input_Create, Binary_Input_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + Binary_Input_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_BINARY_OUTPUT) { OBJECT_BINARY_OUTPUT, @@ -366,7 +372,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Binary_Output_Create, Binary_Output_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + Binary_Output_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_BINARY_VALUE) { OBJECT_BINARY_VALUE, @@ -388,7 +395,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Binary_Value_Create, Binary_Value_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + Binary_Value_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_MULTISTATE_INPUT) { OBJECT_MULTI_STATE_INPUT, @@ -410,7 +418,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Multistate_Input_Create, Multistate_Input_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + Multistate_Input_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_MULTISTATE_OUTPUT) { OBJECT_MULTI_STATE_OUTPUT, @@ -432,7 +441,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Multistate_Output_Create, Multistate_Output_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + Multistate_Output_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_MULTISTATE_VALUE) { OBJECT_MULTI_STATE_VALUE, @@ -454,7 +464,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Multistate_Value_Create, Multistate_Value_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + Multistate_Value_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_NETWORK_PORT) { OBJECT_NETWORK_PORT, @@ -476,7 +487,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, - NULL /* Timer */ }, + NULL /* Timer */, + Network_Port_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_CALENDAR) { OBJECT_CALENDAR, @@ -498,7 +510,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Calendar_Create, Calendar_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + Calendar_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_INTEGER_VALUE) { OBJECT_INTEGER_VALUE, @@ -520,7 +533,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Integer_Value_Create, Integer_Value_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + Integer_Value_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_LIFE_SAFETY_POINT) { OBJECT_LIFE_SAFETY_POINT, @@ -542,7 +556,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Life_Safety_Point_Create, Life_Safety_Point_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + Life_Safety_Point_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_LIFE_SAFETY_ZONE) { OBJECT_LIFE_SAFETY_ZONE, @@ -564,7 +579,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Life_Safety_Zone_Create, Life_Safety_Zone_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + Life_Safety_Zone_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_LOAD_CONTROL) @@ -587,7 +603,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Load_Control_Create, Load_Control_Delete, - Load_Control_Timer }, + Load_Control_Timer, + Load_Control_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_LIGHTING_OUTPUT) { OBJECT_LIGHTING_OUTPUT, @@ -609,7 +626,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Lighting_Output_Create, Lighting_Output_Delete, - Lighting_Output_Timer }, + Lighting_Output_Timer, + Lighting_Output_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_CHANNEL) { OBJECT_CHANNEL, @@ -631,7 +649,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Channel_Create, Channel_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + Channel_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_BINARY_LIGHTING_OUTPUT) { OBJECT_BINARY_LIGHTING_OUTPUT, @@ -653,7 +672,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Binary_Lighting_Output_Create, Binary_Lighting_Output_Delete, - Binary_Lighting_Output_Timer }, + Binary_Lighting_Output_Timer, + Binary_Lighting_Output_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_COLOR) { OBJECT_COLOR, @@ -675,7 +695,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Color_Create, Color_Delete, - Color_Timer }, + Color_Timer, + Color_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_COLOR_TEMPERATURE) { OBJECT_COLOR_TEMPERATURE, @@ -697,7 +718,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Color_Temperature_Create, Color_Temperature_Delete, - Color_Temperature_Timer }, + Color_Temperature_Timer, + Color_Temperature_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_FILE) { OBJECT_FILE, @@ -719,7 +741,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, bacfile_create, bacfile_delete, - NULL /* Timer */ }, + NULL /* Timer */, + BACfile_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_STRUCTURED_VIEW) { OBJECT_STRUCTURED_VIEW, @@ -741,7 +764,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Structured_View_Create, Structured_View_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + NULL /* Writable_Property_List */ }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_BITSTRING_VALUE) { OBJECT_BITSTRING_VALUE, @@ -763,7 +787,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, BitString_Value_Create, BitString_Value_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + BitString_Value_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_CHARACTERSTRING_VALUE) { OBJECT_CHARACTERSTRING_VALUE, @@ -785,7 +810,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, CharacterString_Value_Create, CharacterString_Value_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + CharacterString_Value_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_TIME_VALUE) { OBJECT_TIME_VALUE, @@ -807,7 +833,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Time_Value_Create, Time_Value_Delete, - NULL /* Timer */ }, + NULL /* Timer */, + Time_Value_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_TIMER) { OBJECT_TIMER, @@ -829,7 +856,8 @@ static object_functions_t My_Object_Table[] = { Timer_Remove_List_Element, Timer_Create, Timer_Delete, - Timer_Task }, + Timer_Task, + Timer_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_LOOP) { OBJECT_LOOP, @@ -851,7 +879,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Loop_Create, Loop_Delete, - Loop_Timer }, + Loop_Timer, + Loop_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_PROGRAM) { OBJECT_BITSTRING_VALUE, @@ -873,7 +902,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, Program_Create, Program_Delete, - Program_Timer }, + Program_Timer, + Program_Writable_Property_List }, #endif { MAX_BACNET_OBJECT_TYPE, @@ -895,7 +925,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, - NULL /* Timer */ + NULL /* Timer */, + NULL /* Writable_Property_List */ } }; @@ -994,6 +1025,31 @@ void Device_Objects_Property_List( return; } +/** + * @brief Get the Writeable Property List for an object type + * @param object_type - object type of the object + * @param object_instance - object-instance number of the object + * @param properties - pointer to the list of writable properties + * @return The number of properties in the writable property list + */ +uint32_t Device_Objects_Writable_Property_List( + BACNET_OBJECT_TYPE object_type, + uint32_t object_instance, + const int32_t **properties) +{ + uint32_t count = 0; + struct object_functions *pObject = NULL; + + (void)object_instance; + pObject = Device_Object_Functions_Find(object_type); + if ((pObject != NULL) && (pObject->Object_Writable_Property_List != NULL)) { + pObject->Object_Writable_Property_List(object_instance, properties); + count = property_list_count(*properties); + } + + return count; +} + /* These three arrays are used by the ReadPropertyMultiple handler */ static const int32_t Device_Properties_Required[] = { /* List of Required properties in this object */ @@ -1051,6 +1107,35 @@ static const int32_t Device_Properties_Proprietary[] = { -1 }; +/* Every object shall have a Writable Property_List property + which is a BACnetARRAY of property identifiers, + one property identifier for each property within this object + that is always writable. */ +static const int32_t Writable_Properties[] = { + /* unordered list of writable properties */ + PROP_OBJECT_IDENTIFIER, + PROP_NUMBER_OF_APDU_RETRIES, + PROP_APDU_TIMEOUT, + PROP_VENDOR_IDENTIFIER, + PROP_SYSTEM_STATUS, + PROP_OBJECT_NAME, + PROP_LOCATION, + PROP_DESCRIPTION, + PROP_MODEL_NAME, +#if defined(BACNET_TIME_MASTER) + PROP_TIME_SYNCHRONIZATION_INTERVAL, + PROP_ALIGN_INTERVALS, + PROP_INTERVAL_OFFSET, +#endif + PROP_UTC_OFFSET, +#if defined(BACDL_MSTP) + PROP_MAX_INFO_FRAMES, + PROP_MAX_MASTER, +#endif + PROP_TIME_OF_DEVICE_RESTART, + -1 +}; + /** * @brief Returns the list of required, optional, and proprietary properties * for the Device object. @@ -1080,6 +1165,20 @@ void Device_Property_Lists( return; } +/** + * @brief Get the list of writable properties for a Device object + * @param object_instance - object-instance number of the object + * @param properties - Pointer to the pointer of writable properties. + */ +void Device_Writable_Property_List( + uint32_t object_instance, const int32_t **properties) +{ + (void)object_instance; + if (properties) { + *properties = Writable_Properties; + } +} + /** * @brief Determine if the object property is a member of this object instance * @param object_type - object type of the object diff --git a/src/bacnet/wp.h b/src/bacnet/wp.h index 91628af9..b1c9bbea 100644 --- a/src/bacnet/wp.h +++ b/src/bacnet/wp.h @@ -67,6 +67,14 @@ typedef bool (*write_property_member_of_object)( uint32_t object_instance, BACNET_PROPERTY_ID object_property); +/** + * @brief API to get the list of writable properties for an object instance + * @param object_instance - object-instance number of the object + * @param properties - pointer to the list of writable properties + */ +typedef void (*writable_property_list_function)( + uint32_t object_instance, const int32_t **properties); + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ diff --git a/test/bacnet/basic/object/device/CMakeLists.txt b/test/bacnet/basic/object/device/CMakeLists.txt index 01a649c6..bea848d1 100644 --- a/test/bacnet/basic/object/device/CMakeLists.txt +++ b/test/bacnet/basic/object/device/CMakeLists.txt @@ -36,7 +36,11 @@ add_executable(${PROJECT_NAME} # Support files and stubs (pathname alphabetical) ${SRC_DIR}/bacnet/abort.c ${SRC_DIR}/bacnet/access_rule.c + ${SRC_DIR}/bacnet/assigned_access_rights.c + ${SRC_DIR}/bacnet/authentication_factor.c + ${SRC_DIR}/bacnet/authentication_factor_format.c ${SRC_DIR}/bacnet/bacaction.c + ${SRC_DIR}/bacnet/bacaudit.c ${SRC_DIR}/bacnet/bacaddr.c ${SRC_DIR}/bacnet/bacapp.c ${SRC_DIR}/bacnet/bacdcode.c @@ -51,8 +55,15 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactimevalue.c ${SRC_DIR}/bacnet/basic/binding/address.c ${SRC_DIR}/bacnet/basic/object/acc.c + ${SRC_DIR}/bacnet/basic/object/access_credential.c + ${SRC_DIR}/bacnet/basic/object/access_door.c + ${SRC_DIR}/bacnet/basic/object/access_point.c + ${SRC_DIR}/bacnet/basic/object/access_rights.c + ${SRC_DIR}/bacnet/basic/object/access_user.c + ${SRC_DIR}/bacnet/basic/object/access_zone.c ${SRC_DIR}/bacnet/basic/object/ai.c ${SRC_DIR}/bacnet/basic/object/ao.c + ${SRC_DIR}/bacnet/basic/object/auditlog.c ${SRC_DIR}/bacnet/basic/object/av.c ${SRC_DIR}/bacnet/basic/object/bi.c ${SRC_DIR}/bacnet/basic/object/bitstring_value.c @@ -64,6 +75,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/basic/object/color_object.c ${SRC_DIR}/bacnet/basic/object/color_temperature.c ${SRC_DIR}/bacnet/basic/object/command.c + ${SRC_DIR}/bacnet/basic/object/credential_data_input.c ${SRC_DIR}/bacnet/basic/object/csv.c ${SRC_DIR}/bacnet/basic/object/iv.c ${SRC_DIR}/bacnet/basic/object/lc.c @@ -93,6 +105,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/datalink/bvlc6.c ${SRC_DIR}/bacnet/cov.c ${SRC_DIR}/bacnet/create_object.c + ${SRC_DIR}/bacnet/credential_authentication_factor.c ${SRC_DIR}/bacnet/datetime.c ${SRC_DIR}/bacnet/delete_object.c ${SRC_DIR}/bacnet/dcc.c