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