From 1e9347f8f3f0386fc75ca96c6dcdb8dc53b69f88 Mon Sep 17 00:00:00 2001 From: Steve Karg Date: Fri, 27 Feb 2026 10:33:10 -0600 Subject: [PATCH] Bugfix/backup restore failure timeout (#1247) * Added backup failure timeout functionality and related methods in device management * Fixed STARTBACKUP to hold at PERFORMING_A_BACKUP per spec, not IDLE. * Added error handling for reinitialization during restore process to prevent accidental delete of all objects. * Added some missing Create/Delete object functions. Formatting. * Fixed Program object type in bacnet_device.c module. --- CHANGELOG.md | 4 + src/bacnet/basic/object/device.c | 1573 ++++++++++++++++------- src/bacnet/basic/object/device.h | 12 + src/bacnet/basic/server/bacnet_device.c | 701 ++++++---- 4 files changed, 1564 insertions(+), 726 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fc6d8b1..784850fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -176,6 +176,10 @@ The git repositories are hosted at the following sites: ### Fixed +* Fixed Device Management-Backup and Restore-B Backup_Failure_Timeout + to count down and abort at BACKUP_FAILURE or RESTORE_FAILURE states, + successful STARTBACKUP to end in PERFORMING_A_BACKUP state, + and moved STARTRESTORE functionality into ENDRESTORE. (#1247) * Fixed the basic Schedule object to set the correct present-value based on the Device object date and time. (#1236) * Fixed dlenv_init() for BACnet/SC. bsc_register_as_node() was blocking diff --git a/src/bacnet/basic/object/device.c b/src/bacnet/basic/object/device.c index 916ffc2f..9fe3df57 100644 --- a/src/bacnet/basic/object/device.c +++ b/src/bacnet/basic/object/device.c @@ -52,28 +52,26 @@ #include "bacnet/basic/object/ms-input.h" #include "bacnet/basic/object/mso.h" #include "bacnet/basic/object/msv.h" +#include "bacnet/basic/object/osv.h" +#include "bacnet/basic/object/piv.h" #include "bacnet/basic/object/schedule.h" #include "bacnet/basic/object/structured_view.h" #include "bacnet/basic/object/trendlog.h" -#if defined(INTRINSIC_REPORTING) #include "bacnet/basic/object/nc.h" -#endif /* defined(INTRINSIC_REPORTING) */ #include "bacnet/basic/object/bacfile.h" #include "bacnet/basic/object/bitstring_value.h" #include "bacnet/basic/object/csv.h" #include "bacnet/basic/object/iv.h" -#include "bacnet/basic/object/osv.h" -#include "bacnet/basic/object/piv.h" -#include "bacnet/basic/object/loop.h" #include "bacnet/basic/object/time_value.h" #include "bacnet/basic/object/timer.h" +#include "bacnet/basic/object/loop.h" #include "bacnet/basic/object/channel.h" +#include "bacnet/basic/object/program.h" #include "bacnet/basic/object/lo.h" #include "bacnet/basic/object/blo.h" #include "bacnet/basic/object/netport.h" #include "bacnet/basic/object/color_object.h" #include "bacnet/basic/object/color_temperature.h" -#include "bacnet/basic/object/program.h" /* for testing */ #include "bacnet/basic/sys/debug.h" #include "bacnet/bactext.h" @@ -86,452 +84,969 @@ Routed_Device_Write_Property_Local(BACNET_WRITE_PROPERTY_DATA *wp_data); /* may be overridden by outside table */ static object_functions_t *Object_Table; -/* clang-format off */ static object_functions_t My_Object_Table[] = { - { OBJECT_DEVICE, NULL /* Init - don't init Device or it will recourse! */, - Device_Count, Device_Index_To_Instance, - Device_Valid_Object_Instance_Number, Device_Object_Name, - Device_Read_Property_Local, Device_Write_Property_Local, - Device_Property_Lists, DeviceGetRRInfo, NULL /* Iterator */, - NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, - NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, - NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, - NULL /* Timer */, Device_Writable_Property_List }, + { OBJECT_DEVICE, + NULL /* Init - don't init Device or it will recourse! */, + Device_Count, + Device_Index_To_Instance, + Device_Valid_Object_Instance_Number, + Device_Object_Name, + Device_Read_Property_Local, + Device_Write_Property_Local, + Device_Property_Lists, + DeviceGetRRInfo, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + NULL /* Create */, + NULL /* Delete */, + 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, - Network_Port_Object_Name, Network_Port_Read_Property, - Network_Port_Write_Property, Network_Port_Property_Lists, - NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, - NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - NULL /* 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, - Timer_Write_Property, Timer_Property_Lists, - 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_Writable_Property_List }, + { OBJECT_NETWORK_PORT, + Network_Port_Init, + Network_Port_Count, + Network_Port_Index_To_Instance, + Network_Port_Valid_Instance, + Network_Port_Object_Name, + Network_Port_Read_Property, + Network_Port_Write_Property, + Network_Port_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + NULL /* 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, + Timer_Write_Property, + Timer_Property_Lists, + 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_Writable_Property_List }, #endif - { OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count, - Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance, - Analog_Input_Object_Name, Analog_Input_Read_Property, - Analog_Input_Write_Property, Analog_Input_Property_Lists, - NULL /* ReadRangeInfo */, NULL /* Iterator */, - Analog_Input_Encode_Value_List, Analog_Input_Change_Of_Value, - Analog_Input_Change_Of_Value_Clear, Analog_Input_Intrinsic_Reporting, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - 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, - Analog_Output_Write_Property, Analog_Output_Property_Lists, - NULL /* ReadRangeInfo */, NULL /* Iterator */, - 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_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, - Analog_Value_Write_Property, Analog_Value_Property_Lists, - NULL /* ReadRangeInfo */, NULL /* Iterator */, - Analog_Value_Encode_Value_List, Analog_Value_Change_Of_Value, - Analog_Value_Change_Of_Value_Clear, Analog_Value_Intrinsic_Reporting, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - 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, - Binary_Input_Write_Property, Binary_Input_Property_Lists, - NULL /* ReadRangeInfo */, NULL /* Iterator */, - Binary_Input_Encode_Value_List, Binary_Input_Change_Of_Value, - Binary_Input_Change_Of_Value_Clear, NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - 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, - Binary_Output_Write_Property, Binary_Output_Property_Lists, - NULL /* ReadRangeInfo */, NULL /* Iterator */, - 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_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, - Binary_Value_Write_Property, Binary_Value_Property_Lists, - NULL /* ReadRangeInfo */, NULL /* Iterator */, - 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_Writable_Property_List }, - { OBJECT_CALENDAR, Calendar_Init, Calendar_Count, - Calendar_Index_To_Instance, Calendar_Valid_Instance, - Calendar_Object_Name, Calendar_Read_Property, - Calendar_Write_Property, Calendar_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 */, - Calendar_Create, Calendar_Delete, NULL /* Timer */, - Calendar_Writable_Property_List }, + { OBJECT_ANALOG_INPUT, + Analog_Input_Init, + Analog_Input_Count, + Analog_Input_Index_To_Instance, + Analog_Input_Valid_Instance, + Analog_Input_Object_Name, + Analog_Input_Read_Property, + Analog_Input_Write_Property, + Analog_Input_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + Analog_Input_Encode_Value_List, + Analog_Input_Change_Of_Value, + Analog_Input_Change_Of_Value_Clear, + Analog_Input_Intrinsic_Reporting, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + 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, + Analog_Output_Write_Property, + Analog_Output_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + 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_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, + Analog_Value_Write_Property, + Analog_Value_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + Analog_Value_Encode_Value_List, + Analog_Value_Change_Of_Value, + Analog_Value_Change_Of_Value_Clear, + Analog_Value_Intrinsic_Reporting, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + 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, + Binary_Input_Write_Property, + Binary_Input_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + Binary_Input_Encode_Value_List, + Binary_Input_Change_Of_Value, + Binary_Input_Change_Of_Value_Clear, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + 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, + Binary_Output_Write_Property, + Binary_Output_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + 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_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, + Binary_Value_Write_Property, + Binary_Value_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + 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_Writable_Property_List }, + { OBJECT_CALENDAR, + Calendar_Init, + Calendar_Count, + Calendar_Index_To_Instance, + Calendar_Valid_Instance, + Calendar_Object_Name, + Calendar_Read_Property, + Calendar_Write_Property, + Calendar_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 */, + 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, - BitString_Value_Valid_Instance, BitString_Value_Object_Name, - BitString_Value_Read_Property, BitString_Value_Write_Property, - BitString_Value_Property_Lists, NULL /* ReadRangeInfo */, - NULL /* Iterator */, BitString_Value_Encode_Value_List, - 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_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, - CharacterString_Value_Read_Property, - CharacterString_Value_Write_Property, - CharacterString_Value_Property_Lists, NULL /* ReadRangeInfo */, - NULL /* Iterator */, CharacterString_Value_Encode_Value_List, - CharacterString_Value_Change_Of_Value, - 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_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, - OctetString_Value_Write_Property, OctetString_Value_Property_Lists, - NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, - NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - OctetString_Value_Create, OctetString_Value_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, - PositiveInteger_Value_Read_Property, - PositiveInteger_Value_Write_Property, - PositiveInteger_Value_Property_Lists, NULL /* ReadRangeInfo */, - NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, - NULL /* COV Clear */, NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - PositiveInteger_Value_Create, PositiveInteger_Value_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, - Time_Value_Write_Property, Time_Value_Property_Lists, - NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, - NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - NULL /* 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, - Integer_Value_Write_Property, Integer_Value_Property_Lists, - NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, - NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - Integer_Value_Create, Integer_Value_Delete, NULL /* Timer */, - Integer_Value_Writable_Property_List }, + { OBJECT_BITSTRING_VALUE, + BitString_Value_Init, + BitString_Value_Count, + BitString_Value_Index_To_Instance, + BitString_Value_Valid_Instance, + BitString_Value_Object_Name, + BitString_Value_Read_Property, + BitString_Value_Write_Property, + BitString_Value_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + BitString_Value_Encode_Value_List, + 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_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, + CharacterString_Value_Read_Property, + CharacterString_Value_Write_Property, + CharacterString_Value_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + CharacterString_Value_Encode_Value_List, + CharacterString_Value_Change_Of_Value, + 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_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, + OctetString_Value_Write_Property, + OctetString_Value_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + OctetString_Value_Create, + OctetString_Value_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, + PositiveInteger_Value_Read_Property, + PositiveInteger_Value_Write_Property, + PositiveInteger_Value_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + PositiveInteger_Value_Create, + PositiveInteger_Value_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, + Time_Value_Write_Property, + Time_Value_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + Time_Value_Create, + Time_Value_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, + Integer_Value_Write_Property, + Integer_Value_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + 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, - Command_Write_Property, Command_Property_Lists, - NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, - NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - NULL /* 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, - Notification_Class_Valid_Instance, Notification_Class_Object_Name, - Notification_Class_Read_Property, Notification_Class_Write_Property, - Notification_Class_Property_Lists, NULL /* ReadRangeInfo */, - NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, - NULL /* COV Clear */, NULL /* Intrinsic Reporting */, - Notification_Class_Add_List_Element, - Notification_Class_Remove_List_Element, NULL /* Create */, - NULL /* Delete */, NULL /* Timer */, - Notification_Class_Writable_Property_List }, + { OBJECT_COMMAND, + Command_Init, + Command_Count, + Command_Index_To_Instance, + Command_Valid_Instance, + Command_Object_Name, + Command_Read_Property, + Command_Write_Property, + Command_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + NULL /* 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, + Notification_Class_Valid_Instance, + Notification_Class_Object_Name, + Notification_Class_Read_Property, + Notification_Class_Write_Property, + Notification_Class_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + Notification_Class_Add_List_Element, + Notification_Class_Remove_List_Element, + NULL /* Create */, + 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, - Life_Safety_Point_Object_Name, Life_Safety_Point_Read_Property, - Life_Safety_Point_Write_Property, Life_Safety_Point_Property_Lists, - NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, - NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - 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, - Life_Safety_Zone_Write_Property, Life_Safety_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 */, - 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, - Load_Control_Write_Property, Load_Control_Property_Lists, - NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, - NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - 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, - Multistate_Input_Write_Property, Multistate_Input_Property_Lists, - NULL /* ReadRangeInfo */, NULL /* Iterator */, - 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_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, - Multistate_Output_Read_Property, Multistate_Output_Write_Property, - Multistate_Output_Property_Lists, NULL /* ReadRangeInfo */, - NULL /* Iterator */, - 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_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, - Multistate_Value_Write_Property, Multistate_Value_Property_Lists, - NULL /* ReadRangeInfo */, NULL /* Iterator */, - Multistate_Value_Encode_Value_List, Multistate_Value_Change_Of_Value, - Multistate_Value_Change_Of_Value_Clear, NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - 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, - Trend_Log_Write_Property, Trend_Log_Property_Lists, TrendLogGetRRInfo, - NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, - NULL /* COV Clear */, NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */, NULL /* Timer */, - Trend_Log_Writable_Property_List }, + { OBJECT_LIFE_SAFETY_POINT, + Life_Safety_Point_Init, + Life_Safety_Point_Count, + Life_Safety_Point_Index_To_Instance, + Life_Safety_Point_Valid_Instance, + Life_Safety_Point_Object_Name, + Life_Safety_Point_Read_Property, + Life_Safety_Point_Write_Property, + Life_Safety_Point_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + 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, + Life_Safety_Zone_Write_Property, + Life_Safety_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 */, + 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, + Load_Control_Write_Property, + Load_Control_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + 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, + Multistate_Input_Write_Property, + Multistate_Input_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + 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_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, + Multistate_Output_Read_Property, + Multistate_Output_Write_Property, + Multistate_Output_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + 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_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, + Multistate_Value_Write_Property, + Multistate_Value_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + Multistate_Value_Encode_Value_List, + Multistate_Value_Change_Of_Value, + Multistate_Value_Change_Of_Value_Clear, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + 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, + Trend_Log_Write_Property, + Trend_Log_Property_Lists, + TrendLogGetRRInfo, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + NULL /* 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, - Lighting_Output_Object_Name, Lighting_Output_Read_Property, - Lighting_Output_Write_Property, Lighting_Output_Property_Lists, - NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, - NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - 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_Writable_Property_List }, + { OBJECT_LIGHTING_OUTPUT, + Lighting_Output_Init, + Lighting_Output_Count, + Lighting_Output_Index_To_Instance, + Lighting_Output_Valid_Instance, + Lighting_Output_Object_Name, + Lighting_Output_Read_Property, + Lighting_Output_Write_Property, + Lighting_Output_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + 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_Writable_Property_List }, #endif #if (BACNET_PROTOCOL_REVISION >= 16) - { OBJECT_BINARY_LIGHTING_OUTPUT, Binary_Lighting_Output_Init, - Binary_Lighting_Output_Count, Binary_Lighting_Output_Index_To_Instance, - Binary_Lighting_Output_Valid_Instance, - Binary_Lighting_Output_Object_Name, - Binary_Lighting_Output_Read_Property, - Binary_Lighting_Output_Write_Property, - Binary_Lighting_Output_Property_Lists, NULL /* ReadRangeInfo */, - NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, - NULL /* COV Clear */, NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - Binary_Lighting_Output_Create, Binary_Lighting_Output_Delete, - Binary_Lighting_Output_Timer, - Binary_Lighting_Output_Writable_Property_List }, + { OBJECT_BINARY_LIGHTING_OUTPUT, + Binary_Lighting_Output_Init, + Binary_Lighting_Output_Count, + Binary_Lighting_Output_Index_To_Instance, + Binary_Lighting_Output_Valid_Instance, + Binary_Lighting_Output_Object_Name, + Binary_Lighting_Output_Read_Property, + Binary_Lighting_Output_Write_Property, + Binary_Lighting_Output_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + Binary_Lighting_Output_Create, + Binary_Lighting_Output_Delete, + 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, - Color_Valid_Instance, Color_Object_Name, Color_Read_Property, - Color_Write_Property, Color_Property_Lists, NULL /* ReadRangeInfo */, - NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, - NULL /* COV Clear */, NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - 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, - Color_Temperature_Write_Property, Color_Temperature_Property_Lists, - NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, - NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - Color_Temperature_Create, Color_Temperature_Delete, - Color_Temperature_Timer, Color_Temperature_Writable_Property_List }, + { OBJECT_COLOR, + Color_Init, + Color_Count, + Color_Index_To_Instance, + Color_Valid_Instance, + Color_Object_Name, + Color_Read_Property, + Color_Write_Property, + Color_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + 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, + Color_Temperature_Write_Property, + Color_Temperature_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + Color_Temperature_Create, + Color_Temperature_Delete, + Color_Temperature_Timer, + Color_Temperature_Writable_Property_List }, #endif - { OBJECT_FILE, bacfile_init, bacfile_count, bacfile_index_to_instance, - bacfile_valid_instance, bacfile_object_name, bacfile_read_property, - bacfile_write_property, BACfile_Property_Lists, - NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, - NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - bacfile_create, bacfile_delete, NULL /* Timer */, - BACfile_Writable_Property_List }, - { OBJECT_SCHEDULE, Schedule_Init, Schedule_Count, - Schedule_Index_To_Instance, Schedule_Valid_Instance, - Schedule_Object_Name, Schedule_Read_Property, Schedule_Write_Property, - Schedule_Property_Lists, NULL /* ReadRangeInfo */, NULL /* Iterator */, - NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, - NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, - NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, - Schedule_Timer /* 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, - NULL /* Write_Property */, Structured_View_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 */, - 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, - Accumulator_Write_Property, Accumulator_Property_Lists, - NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, - NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - NULL /* 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, - Loop_Write_Property, Loop_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 */, - 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, - Program_Write_Property, Program_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 */, - Program_Create, Program_Delete, Program_Timer, - Program_Writable_Property_List }, + { OBJECT_FILE, + bacfile_init, + bacfile_count, + bacfile_index_to_instance, + bacfile_valid_instance, + bacfile_object_name, + bacfile_read_property, + bacfile_write_property, + BACfile_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + bacfile_create, + bacfile_delete, + NULL /* Timer */, + BACfile_Writable_Property_List }, + { OBJECT_SCHEDULE, + Schedule_Init, + Schedule_Count, + Schedule_Index_To_Instance, + Schedule_Valid_Instance, + Schedule_Object_Name, + Schedule_Read_Property, + Schedule_Write_Property, + Schedule_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + NULL /* Create */, + NULL /* Delete */, + Schedule_Timer /* 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, + NULL /* Write_Property */, + Structured_View_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 */, + 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, + Accumulator_Write_Property, + Accumulator_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + NULL /* 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, + Loop_Write_Property, + Loop_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 */, + 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, + Program_Write_Property, + Program_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 */, + 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 }, + { 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 }, + { 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 */, + Audit_Log_Create, + Audit_Log_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 */, - NULL /* Write_Property */, NULL /* Property_Lists */, - NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, - NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */, NULL /* Timer */, - NULL /* Writable_Property_List */ }, + { MAX_BACNET_OBJECT_TYPE, + NULL /* Init */, + NULL /* Count */, + NULL /* Index_To_Instance */, + NULL /* Valid_Instance */, + NULL /* Object_Name */, + NULL /* Read_Property */, + NULL /* Write_Property */, + NULL /* Property_Lists */, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + NULL /* Create */, + NULL /* Delete */, + NULL /* Timer */, + NULL /* Writable_Property_List */ } }; -/* clang-format on */ /* Proprietary property callback functions to enable proprietary properties while reusing the basic objects as-is. */ @@ -904,7 +1419,7 @@ static const char *Vendor_Name = BACNET_VENDOR_NAME; static uint16_t Vendor_Identifier = BACNET_VENDOR_ID; static char Model_Name[MAX_DEV_MOD_LEN + 1] = "GNU"; static char Application_Software_Version[MAX_DEV_VER_LEN + 1] = "1.0"; -static char Firmware_Version[MAX_DEV_VER_LEN + 1] = BACNET_VERSION_TEXT; +static char Firmware_Revision[MAX_DEV_VER_LEN + 1] = BACNET_VERSION_TEXT; static char Location[MAX_DEV_LOC_LEN + 1] = "USA"; static char Description[MAX_DEV_DESC_LEN + 1] = "server"; static char Serial_Number[MAX_DEV_DESC_LEN + 1] = @@ -973,7 +1488,8 @@ static BACNET_TIMESTAMP Last_Restore_Time; in the Backup_Failure_Timeout property of its Device object, device B should assume that the restore procedure has been aborted, and device B should exit restore mode.*/ -static uint16_t Backup_Failure_Timeout; +static uint16_t Backup_Failure_Timeout = 60 * 60; +static uint32_t Backup_Failure_Timeout_Milliseconds; /* This property indicates the amount of time in seconds that the device might remain unresponsive after the sending of a ReinitializeDevice-ACK at the start of a backup procedure. @@ -1088,18 +1604,44 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) break; #if defined BACNET_BACKUP_RESTORE case BACNET_REINIT_STARTBACKUP: + if (Device_Backup_State_In_Progress(Backup_State)) { + rd_data->error_class = ERROR_CLASS_DEVICE; + rd_data->error_code = ERROR_CODE_CONFIGURATION_IN_PROGRESS; + break; + } + Backup_State = BACKUP_STATE_PREPARING_FOR_BACKUP; + Device_Backup_Failure_Timeout_Restart(); Device_Start_Backup(); Reinitialize_State = rd_data->state; status = true; break; case BACNET_REINIT_STARTRESTORE: + if (Device_Backup_State_In_Progress(Backup_State)) { + rd_data->error_class = ERROR_CLASS_DEVICE; + rd_data->error_code = ERROR_CODE_CONFIGURATION_IN_PROGRESS; + break; + } + Backup_State = BACKUP_STATE_PREPARING_FOR_RESTORE; + Device_Backup_Failure_Timeout_Restart(); Device_Start_Restore(); Reinitialize_State = rd_data->state; status = true; break; - case BACNET_REINIT_ENDBACKUP: case BACNET_REINIT_ENDRESTORE: + if (Backup_State != BACKUP_STATE_PERFORMING_A_RESTORE) { + rd_data->error_class = ERROR_CLASS_DEVICE; + rd_data->error_code = ERROR_CODE_CONFIGURATION_IN_PROGRESS; + break; + } + Device_Backup_Failure_Timeout_Restart(); + Device_End_Restore(); + Reinitialize_State = rd_data->state; + status = true; + break; + case BACNET_REINIT_ENDBACKUP: case BACNET_REINIT_ABORTRESTORE: + Backup_State = BACKUP_STATE_IDLE; + Device_Backup_Failure_Timeout_Reset(); Reinitialize_State = rd_data->state; status = true; break; @@ -1417,16 +1959,16 @@ bool Device_Set_Model_Name(const char *name, size_t length) const char *Device_Firmware_Revision(void) { - return Firmware_Version; + return Firmware_Revision; } bool Device_Set_Firmware_Revision(const char *name, size_t length) { bool status = false; /*return value */ - if (length < sizeof(Firmware_Version)) { - memmove(Firmware_Version, name, length); - Firmware_Version[length] = 0; + if (length < sizeof(Firmware_Revision)) { + memmove(Firmware_Revision, name, length); + Firmware_Revision[length] = 0; status = true; } @@ -2069,8 +2611,91 @@ bool Device_Backup_And_Restore_State_Set(BACNET_BACKUP_STATE state) Backup_State = state; return true; } + +/** + * @brief Reset the backup failure timeout countdown to zero + * @note This should be called when the backup failure timeout is no longer + * needed, such as when a backup or restore operation has completed or failed. + */ +void Device_Backup_Failure_Timeout_Reset(void) +{ + Backup_Failure_Timeout_Milliseconds = 0; +} #endif +/** + * @brief Determine if a backup or restore operation is currently in progress + * @param state The current backup state to check + * @return True if a backup or restore operation is in progress, else False + */ +bool Device_Backup_State_In_Progress(BACNET_BACKUP_STATE state) +{ + if ((state != BACKUP_STATE_IDLE) && + (state != BACKUP_STATE_BACKUP_FAILURE) && + (state != BACKUP_STATE_RESTORE_FAILURE)) { + return true; + } + return false; +} + +/** + * @brief Start the backup failure timeout countdown by converting the value to + * milliseconds + * @note This should be called when starting a backup or restore operation, and + * the Backup_Failure_Timeout_Milliseconds variable should be decremented in + * the main loop or a timer interrupt to track the timeout. + */ +void Device_Backup_Failure_Timeout_Restart(void) +{ +#if defined(BACNET_BACKUP_RESTORE) + if (Device_Backup_State_In_Progress(Backup_State)) { + /* service related to backup & restore will reset the backup failure + timeout during a backup or restore operation */ + Backup_Failure_Timeout_Milliseconds = Backup_Failure_Timeout * 1000UL; + } +#endif +} + +/** + * @brief Decrement the backup failure timeout countdown by the given number of + * milliseconds, and update the backup state if the timeout has expired. + * @param milliseconds The number of milliseconds to decrement from the backup + * failure timeout countdown. + * @details If device B does not receive any messages related to the backup + * procedure from device A for the number of seconds specified in the + * Backup_Failure_Timeout property of its Device object, device B should + * assume that the backup procedure has been aborted, and device B should + * exit backup mode. A message related to the backup procedure is defined + * to be any ReadProperty, ReadPropertyMultiple, WriteProperty, + * WritePropertyMultiple, CreateObject, or AtomicReadFile request + * that directly accesses a configuration File object. + */ +void Device_Backup_Failure_Timeout_Countdown(uint32_t milliseconds) +{ +#if defined(BACNET_BACKUP_RESTORE) + if (Device_Backup_State_In_Progress(Backup_State)) { + /* service related to backup & restore will restart the backup + failure timer during a backup or restore operation */ + if (Backup_Failure_Timeout_Milliseconds > 0) { + if (milliseconds >= Backup_Failure_Timeout_Milliseconds) { + Backup_Failure_Timeout_Milliseconds = 0; + } else { + Backup_Failure_Timeout_Milliseconds -= milliseconds; + } + if (Backup_Failure_Timeout_Milliseconds == 0) { + if (Backup_State == BACKUP_STATE_PERFORMING_A_BACKUP) { + Backup_State = BACKUP_STATE_BACKUP_FAILURE; + } else if (Backup_State == BACKUP_STATE_PERFORMING_A_RESTORE) { + Backup_State = BACKUP_STATE_RESTORE_FAILURE; + } + } + } + } +#else + (void)milliseconds; +#endif +} + /** * ReadProperty handler for this object. For the given ReadProperty * data, the application_data is loaded or the error flags are set. @@ -2132,7 +2757,7 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata) encode_application_character_string(&apdu[0], &char_string); break; case PROP_FIRMWARE_REVISION: - characterstring_init_ansi(&char_string, Firmware_Version); + characterstring_init_ansi(&char_string, Firmware_Revision); apdu_len = encode_application_character_string(&apdu[0], &char_string); break; @@ -2409,6 +3034,7 @@ int Device_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata) if (!rpdata) { return 0; } + Device_Backup_Failure_Timeout_Restart(); /* initialize the default return values */ rpdata->error_class = ERROR_CLASS_OBJECT; rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT; @@ -2702,8 +3328,10 @@ bool Device_Write_Property_Local(BACNET_WRITE_PROPERTY_DATA *wp_data) status = write_property_type_valid( wp_data, &value, BACNET_APPLICATION_TAG_TIMESTAMP); if (status) { +#if defined(BACAPP_TIMESTAMP) bacapp_timestamp_copy( &Time_Of_Device_Restart, &value.type.Time_Stamp); +#endif } break; default: @@ -2816,6 +3444,7 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) bool status = false; /* Ever the pessimist! */ struct object_functions *pObject = NULL; + Device_Backup_Failure_Timeout_Restart(); /* initialize the default return values */ wp_data->error_class = ERROR_CLASS_OBJECT; wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT; @@ -3056,6 +3685,7 @@ bool Device_Create_Object(BACNET_CREATE_OBJECT_DATA *data) bool object_exists = false; bool object_supported = false; + Device_Backup_Failure_Timeout_Restart(); pObject = Device_Object_Functions_Find(data->object_type); if (pObject != NULL) { if (pObject->Object_Valid_Instance && @@ -3089,6 +3719,7 @@ bool Device_Delete_Object(BACNET_DELETE_OBJECT_DATA *data) bool status = false; struct object_functions *pObject = NULL; + Device_Backup_Failure_Timeout_Restart(); pObject = Device_Object_Functions_Find(data->object_type); if (pObject != NULL) { if (!pObject->Object_Delete) { @@ -3123,6 +3754,34 @@ bool Device_Delete_Object(BACNET_DELETE_OBJECT_DATA *data) return status; } +/** + * @brief Loops through all the objects and deletes them, + * if DeleteObject service is supported by the object type. + */ +void Device_Delete_Objects(void) +{ + struct object_functions *pObject = NULL; + uint32_t instance = 0; + unsigned count = 0; + + pObject = Object_Table; + while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) { + count = 0; + if (pObject->Object_Count) { + count = pObject->Object_Count(); + } + while (count) { + count--; + if ((pObject->Object_Delete) && + (pObject->Object_Index_To_Instance)) { + instance = pObject->Object_Index_To_Instance(count); + pObject->Object_Delete(instance); + } + } + pObject++; + } +} + /** * @brief Loop through the Device object-list property and export to * a file as BACnet CreateObject services with List of Initial Values @@ -3142,9 +3801,7 @@ void Device_Start_Backup(void) bool status = false; int32_t len = 0, offset = 0; - Backup_State = BACKUP_STATE_PREPARING_FOR_BACKUP; object_count = Device_Object_List_Count(); - Backup_State = BACKUP_STATE_PERFORMING_A_BACKUP; for (i = 0; i < object_count; i++) { /* get the object type and instance from the device object list */ status = Device_Object_List_Identifier( @@ -3170,7 +3827,18 @@ void Device_Start_Backup(void) } } } - Backup_State = BACKUP_STATE_IDLE; + Backup_State = BACKUP_STATE_PERFORMING_A_BACKUP; +#endif +} + +/** + * @brief Create files for backup and restore, if supported, and set the state + * to performing a restore + */ +void Device_Start_Restore(void) +{ +#if defined BACNET_BACKUP_RESTORE + Backup_State = BACKUP_STATE_PERFORMING_A_RESTORE; #endif } @@ -3179,7 +3847,7 @@ void Device_Start_Backup(void) * a file as BACnet CreateObject services with List of Initial Values * for every writable property */ -void Device_Start_Restore(void) +void Device_End_Restore(void) { #if defined BACNET_BACKUP_RESTORE BACNET_DATE_TIME bdateTime = { 0 }; @@ -3190,7 +3858,8 @@ void Device_Start_Restore(void) datetime_local(&bdateTime.date, &bdateTime.time, NULL, NULL); bacapp_timestamp_datetime_set(&Last_Restore_Time, &bdateTime); - Backup_State = BACKUP_STATE_PREPARING_FOR_RESTORE; + /* delete all existing objects before restore */ + Device_Delete_Objects(); /* create objects from the backup file */ file_size = bacfile_file_size(Configuration_Files[0]); while (offset < file_size) { @@ -3210,15 +3879,19 @@ void Device_Start_Restore(void) /* error creating object - keep going */ } } else { + Backup_State = BACKUP_STATE_RESTORE_FAILURE; /* error while decoding object */ break; } } else { + Backup_State = BACKUP_STATE_RESTORE_FAILURE; /* error while reading file */ break; } } - Backup_State = BACKUP_STATE_IDLE; + if (Backup_State != BACKUP_STATE_RESTORE_FAILURE) { + Backup_State = BACKUP_STATE_IDLE; + } #endif } @@ -3379,8 +4052,10 @@ void Device_Timer(uint16_t milliseconds) unsigned count = 0; uint32_t instance; + Device_Backup_Failure_Timeout_Countdown(milliseconds); pObject = Object_Table; while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) { + count = 0; if (pObject->Object_Count) { count = pObject->Object_Count(); } diff --git a/src/bacnet/basic/object/device.h b/src/bacnet/basic/object/device.h index dd4c77e0..3be24571 100644 --- a/src/bacnet/basic/object/device.h +++ b/src/bacnet/basic/object/device.h @@ -251,6 +251,12 @@ uint16_t Device_Backup_Failure_Timeout(void); BACNET_STACK_EXPORT bool Device_Backup_Failure_Timeout_Set(uint16_t timeout); BACNET_STACK_EXPORT +void Device_Backup_Failure_Timeout_Reset(void); +BACNET_STACK_EXPORT +void Device_Backup_Failure_Timeout_Restart(void); +BACNET_STACK_EXPORT +void Device_Backup_Failure_Timeout_Countdown(uint32_t milliseconds); +BACNET_STACK_EXPORT uint16_t Device_Backup_Preparation_Time(void); BACNET_STACK_EXPORT bool Device_Backup_Preparation_Time_Set(uint16_t time); @@ -266,6 +272,8 @@ BACNET_STACK_EXPORT BACNET_BACKUP_STATE Device_Backup_And_Restore_State(void); BACNET_STACK_EXPORT bool Device_Backup_And_Restore_State_Set(BACNET_BACKUP_STATE state); +BACNET_STACK_EXPORT +bool Device_Backup_State_In_Progress(BACNET_BACKUP_STATE state); BACNET_STACK_EXPORT void Device_Property_Lists( @@ -330,11 +338,15 @@ BACNET_STACK_EXPORT bool Device_Create_Object(BACNET_CREATE_OBJECT_DATA *data); BACNET_STACK_EXPORT bool Device_Delete_Object(BACNET_DELETE_OBJECT_DATA *data); +BACNET_STACK_EXPORT +void Device_Delete_Objects(void); BACNET_STACK_EXPORT void Device_Start_Backup(void); BACNET_STACK_EXPORT void Device_Start_Restore(void); +BACNET_STACK_EXPORT +void Device_End_Restore(void); BACNET_STACK_EXPORT unsigned Device_Count(void); diff --git a/src/bacnet/basic/server/bacnet_device.c b/src/bacnet/basic/server/bacnet_device.c index c682b358..4f9bbd5a 100644 --- a/src/bacnet/basic/server/bacnet_device.c +++ b/src/bacnet/basic/server/bacnet_device.c @@ -65,7 +65,6 @@ #include "bacnet/basic/object/netport.h" #include "bacnet/basic/object/color_object.h" #include "bacnet/basic/object/color_temperature.h" -#include "bacnet/basic/object/program.h" #ifdef CONFIG_BACNET_BASIC_DEVICE_OBJECT_VERSION #define BACNET_DEVICE_VERSION CONFIG_BACNET_BASIC_DEVICE_OBJECT_VERSION @@ -221,9 +220,10 @@ /* may be overridden by outside table */ static object_functions_t *Object_Table; + static object_functions_t My_Object_Table[] = { { OBJECT_DEVICE, - NULL, /* don't init - recursive! */ + NULL /* Init - don't init Device or it will recourse! */, Device_Count, Device_Index_To_Instance, Device_Valid_Object_Instance_Number, @@ -231,7 +231,7 @@ static object_functions_t My_Object_Table[] = { Device_Read_Property_Local, Device_Write_Property_Local, Device_Property_Lists, - NULL /* ReadRangeInfo */, + DeviceGetRRInfo, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, @@ -243,6 +243,52 @@ static object_functions_t My_Object_Table[] = { NULL /* Delete */, NULL /* Timer */, Device_Writable_Property_List }, +#if defined(CONFIG_BACNET_BASIC_OBJECT_NETWORK_PORT) + { OBJECT_NETWORK_PORT, + Network_Port_Init, + Network_Port_Count, + Network_Port_Index_To_Instance, + Network_Port_Valid_Instance, + Network_Port_Object_Name, + Network_Port_Read_Property, + Network_Port_Write_Property, + Network_Port_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + NULL /* Create */, + NULL /* Delete */, + NULL /* Timer */, + Network_Port_Writable_Property_List }, +#endif +#if defined(CONFIG_BACNET_BASIC_OBJECT_TIMER) + { OBJECT_TIMER, + Timer_Init, + Timer_Count, + Timer_Index_To_Instance, + Timer_Valid_Instance, + Timer_Object_Name, + Timer_Read_Property, + Timer_Write_Property, + Timer_Property_Lists, + 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_Writable_Property_List }, +#endif #if defined(CONFIG_BACNET_BASIC_OBJECT_ANALOG_INPUT) { OBJECT_ANALOG_INPUT, Analog_Input_Init, @@ -312,29 +358,6 @@ static object_functions_t My_Object_Table[] = { NULL /* Timer */, Analog_Value_Writable_Property_List }, #endif -#if defined(CONFIG_BACNET_BASIC_OBJECT_AUDIT_LOG) - { 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 */, - Audit_Log_Create, - Audit_Log_Delete, - NULL /* Timer */, - Audit_Log_Writable_Property_List }, -#endif #if defined(CONFIG_BACNET_BASIC_OBJECT_BINARY_INPUT) { OBJECT_BINARY_INPUT, Binary_Input_Init, @@ -404,98 +427,6 @@ static object_functions_t My_Object_Table[] = { NULL /* Timer */, Binary_Value_Writable_Property_List }, #endif -#if defined(CONFIG_BACNET_BASIC_OBJECT_MULTISTATE_INPUT) - { OBJECT_MULTI_STATE_INPUT, - Multistate_Input_Init, - Multistate_Input_Count, - Multistate_Input_Index_To_Instance, - Multistate_Input_Valid_Instance, - Multistate_Input_Object_Name, - Multistate_Input_Read_Property, - Multistate_Input_Write_Property, - Multistate_Input_Property_Lists, - NULL /* ReadRangeInfo */, - NULL /* Iterator */, - 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_Writable_Property_List }, -#endif -#if defined(CONFIG_BACNET_BASIC_OBJECT_MULTISTATE_OUTPUT) - { OBJECT_MULTI_STATE_OUTPUT, - Multistate_Output_Init, - Multistate_Output_Count, - Multistate_Output_Index_To_Instance, - Multistate_Output_Valid_Instance, - Multistate_Output_Object_Name, - Multistate_Output_Read_Property, - Multistate_Output_Write_Property, - Multistate_Output_Property_Lists, - NULL /* ReadRangeInfo */, - NULL /* Iterator */, - 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_Writable_Property_List }, -#endif -#if defined(CONFIG_BACNET_BASIC_OBJECT_MULTISTATE_VALUE) - { 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, - Multistate_Value_Write_Property, - Multistate_Value_Property_Lists, - NULL /* ReadRangeInfo */, - NULL /* Iterator */, - Multistate_Value_Encode_Value_List, - Multistate_Value_Change_Of_Value, - Multistate_Value_Change_Of_Value_Clear, - NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, - NULL /* Remove_List_Element */, - Multistate_Value_Create, - Multistate_Value_Delete, - NULL /* Timer */, - Multistate_Value_Writable_Property_List }, -#endif -#if defined(CONFIG_BACNET_BASIC_OBJECT_NETWORK_PORT) - { OBJECT_NETWORK_PORT, - Network_Port_Init, - Network_Port_Count, - Network_Port_Index_To_Instance, - Network_Port_Valid_Instance, - Network_Port_Object_Name, - Network_Port_Read_Property, - Network_Port_Write_Property, - Network_Port_Property_Lists, - NULL /* ReadRangeInfo */, - NULL /* Iterator */, - NULL /* Value_Lists */, - NULL /* COV */, - NULL /* COV Clear */, - NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, - NULL /* Remove_List_Element */, - NULL /* Create */, - NULL /* Delete */, - NULL /* Timer */, - Network_Port_Writable_Property_List }, -#endif #if defined(CONFIG_BACNET_BASIC_OBJECT_CALENDAR) { OBJECT_CALENDAR, Calendar_Init, @@ -519,6 +450,121 @@ static object_functions_t My_Object_Table[] = { NULL /* Timer */, Calendar_Writable_Property_List }, #endif +#if defined(CONFIG_BACNET_BASIC_OBJECT_BITSTRING_VALUE) + { OBJECT_BITSTRING_VALUE, + BitString_Value_Init, + BitString_Value_Count, + BitString_Value_Index_To_Instance, + BitString_Value_Valid_Instance, + BitString_Value_Object_Name, + BitString_Value_Read_Property, + BitString_Value_Write_Property, + BitString_Value_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + BitString_Value_Encode_Value_List, + 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_Writable_Property_List }, +#endif +#if defined(CONFIG_BACNET_BASIC_OBJECT_CHARACTERSTRING_VALUE) + { OBJECT_CHARACTERSTRING_VALUE, + CharacterString_Value_Init, + CharacterString_Value_Count, + CharacterString_Value_Index_To_Instance, + CharacterString_Value_Valid_Instance, + CharacterString_Value_Object_Name, + CharacterString_Value_Read_Property, + CharacterString_Value_Write_Property, + CharacterString_Value_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + CharacterString_Value_Encode_Value_List, + CharacterString_Value_Change_Of_Value, + 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_Writable_Property_List }, +#endif +#if defined(CONFIG_BACNET_BASIC_OBJECT_OCTETSTRING_VALUE) + { 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, + OctetString_Value_Write_Property, + OctetString_Value_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + OctetString_Value_Create, + OctetString_Value_Delete, + NULL /* Timer */, + OctetString_Value_Writable_Property_List }, +#endif +#if defined(CONFIG_BACNET_BASIC_OBJECT_POSITIVE_INTEGER_VALUE) + { OBJECT_POSITIVE_INTEGER_VALUE, + PositiveInteger_Value_Init, + PositiveInteger_Value_Count, + PositiveInteger_Value_Index_To_Instance, + PositiveInteger_Value_Valid_Instance, + PositiveInteger_Value_Object_Name, + PositiveInteger_Value_Read_Property, + PositiveInteger_Value_Write_Property, + PositiveInteger_Value_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + PositiveInteger_Value_Create, + PositiveInteger_Value_Delete, + NULL /* Timer */, + PositiveInteger_Value_Writable_Property_List }, +#endif +#if defined(CONFIG_BACNET_BASIC_OBJECT_TIME_VALUE) + { 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, + Time_Value_Write_Property, + Time_Value_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + NULL /* Value_Lists */, + NULL /* COV */, + NULL /* COV Clear */, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + Time_Value_Create, + Time_Value_Delete, + NULL /* Timer */, + Time_Value_Writable_Property_List }, +#endif #if defined(CONFIG_BACNET_BASIC_OBJECT_INTEGER_VALUE) { OBJECT_INTEGER_VALUE, Integer_Value_Init, @@ -612,6 +658,75 @@ static object_functions_t My_Object_Table[] = { Load_Control_Timer, Load_Control_Writable_Property_List }, #endif +#if defined(CONFIG_BACNET_BASIC_OBJECT_MULTISTATE_INPUT) + { OBJECT_MULTI_STATE_INPUT, + Multistate_Input_Init, + Multistate_Input_Count, + Multistate_Input_Index_To_Instance, + Multistate_Input_Valid_Instance, + Multistate_Input_Object_Name, + Multistate_Input_Read_Property, + Multistate_Input_Write_Property, + Multistate_Input_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + 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_Writable_Property_List }, +#endif +#if defined(CONFIG_BACNET_BASIC_OBJECT_MULTISTATE_OUTPUT) + { OBJECT_MULTI_STATE_OUTPUT, + Multistate_Output_Init, + Multistate_Output_Count, + Multistate_Output_Index_To_Instance, + Multistate_Output_Valid_Instance, + Multistate_Output_Object_Name, + Multistate_Output_Read_Property, + Multistate_Output_Write_Property, + Multistate_Output_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + 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_Writable_Property_List }, +#endif +#if defined(CONFIG_BACNET_BASIC_OBJECT_MULTISTATE_VALUE) + { 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, + Multistate_Value_Write_Property, + Multistate_Value_Property_Lists, + NULL /* ReadRangeInfo */, + NULL /* Iterator */, + Multistate_Value_Encode_Value_List, + Multistate_Value_Change_Of_Value, + Multistate_Value_Change_Of_Value_Clear, + NULL /* Intrinsic Reporting */, + NULL /* Add_List_Element */, + NULL /* Remove_List_Element */, + Multistate_Value_Create, + Multistate_Value_Delete, + NULL /* Timer */, + Multistate_Value_Writable_Property_List }, +#endif #if defined(CONFIG_BACNET_BASIC_OBJECT_LIGHTING_OUTPUT) { OBJECT_LIGHTING_OUTPUT, Lighting_Output_Init, @@ -773,144 +888,6 @@ static object_functions_t My_Object_Table[] = { NULL /* Timer */, NULL /* Writable_Property_List */ }, #endif -#if defined(CONFIG_BACNET_BASIC_OBJECT_BITSTRING_VALUE) - { OBJECT_BITSTRING_VALUE, - BitString_Value_Init, - BitString_Value_Count, - BitString_Value_Index_To_Instance, - BitString_Value_Valid_Instance, - BitString_Value_Object_Name, - BitString_Value_Read_Property, - BitString_Value_Write_Property, - BitString_Value_Property_Lists, - NULL /* ReadRangeInfo */, - NULL /* Iterator */, - BitString_Value_Encode_Value_List, - 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_Writable_Property_List }, -#endif -#if defined(CONFIG_BACNET_BASIC_OBJECT_CHARACTERSTRING_VALUE) - { OBJECT_CHARACTERSTRING_VALUE, - CharacterString_Value_Init, - CharacterString_Value_Count, - CharacterString_Value_Index_To_Instance, - CharacterString_Value_Valid_Instance, - CharacterString_Value_Object_Name, - CharacterString_Value_Read_Property, - CharacterString_Value_Write_Property, - CharacterString_Value_Property_Lists, - NULL /* ReadRangeInfo */, - NULL /* Iterator */, - CharacterString_Value_Encode_Value_List, - CharacterString_Value_Change_Of_Value, - 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_Writable_Property_List }, -#endif -#if defined(CONFIG_BACNET_BASIC_OBJECT_OCTETSTRING_VALUE) - { 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, - OctetString_Value_Write_Property, - OctetString_Value_Property_Lists, - NULL /* ReadRangeInfo */, - NULL /* Iterator */, - NULL /* Value_Lists */, - NULL /* COV */, - NULL /* COV Clear */, - NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, - NULL /* Remove_List_Element */, - OctetString_Value_Create, - OctetString_Value_Delete, - NULL /* Timer */, - OctetString_Value_Writable_Property_List }, -#endif -#if defined(CONFIG_BACNET_BASIC_OBJECT_POSITIVE_INTEGER_VALUE) - { OBJECT_POSITIVE_INTEGER_VALUE, - PositiveInteger_Value_Init, - PositiveInteger_Value_Count, - PositiveInteger_Value_Index_To_Instance, - PositiveInteger_Value_Valid_Instance, - PositiveInteger_Value_Object_Name, - PositiveInteger_Value_Read_Property, - PositiveInteger_Value_Write_Property, - PositiveInteger_Value_Property_Lists, - NULL /* ReadRangeInfo */, - NULL /* Iterator */, - NULL /* Value_Lists */, - NULL /* COV */, - NULL /* COV Clear */, - NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, - NULL /* Remove_List_Element */, - PositiveInteger_Value_Create, - PositiveInteger_Value_Delete, - NULL /* Timer */, - PositiveInteger_Value_Writable_Property_List }, -#endif -#if defined(CONFIG_BACNET_BASIC_OBJECT_TIME_VALUE) - { 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, - Time_Value_Write_Property, - Time_Value_Property_Lists, - NULL /* ReadRangeInfo */, - NULL /* Iterator */, - NULL /* Value_Lists */, - NULL /* COV */, - NULL /* COV Clear */, - NULL /* Intrinsic Reporting */, - NULL /* Add_List_Element */, - NULL /* Remove_List_Element */, - Time_Value_Create, - Time_Value_Delete, - NULL /* Timer */, - Time_Value_Writable_Property_List }, -#endif -#if defined(CONFIG_BACNET_BASIC_OBJECT_TIMER) - { OBJECT_TIMER, - Timer_Init, - Timer_Count, - Timer_Index_To_Instance, - Timer_Valid_Instance, - Timer_Object_Name, - Timer_Read_Property, - Timer_Write_Property, - Timer_Property_Lists, - 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_Writable_Property_List }, -#endif #if defined(CONFIG_BACNET_BASIC_OBJECT_LOOP) { OBJECT_LOOP, Loop_Init, @@ -935,7 +912,7 @@ static object_functions_t My_Object_Table[] = { Loop_Writable_Property_List }, #endif #if defined(CONFIG_BACNET_BASIC_OBJECT_PROGRAM) - { OBJECT_BITSTRING_VALUE, + { OBJECT_PROGRAM, Program_Init, Program_Count, Program_Index_To_Instance, @@ -956,6 +933,29 @@ static object_functions_t My_Object_Table[] = { Program_Delete, Program_Timer, Program_Writable_Property_List }, +#endif +#if defined(CONFIG_BACNET_BASIC_OBJECT_AUDIT_LOG) + { 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 */, + Audit_Log_Create, + Audit_Log_Delete, + NULL /* Timer */, + Audit_Log_Writable_Property_List }, #endif { MAX_BACNET_OBJECT_TYPE, @@ -1287,8 +1287,6 @@ void Device_Property_Lists( const int32_t **pOptional, const int32_t **pProprietary) { - uint32_t instance; - if (pRequired) { *pRequired = Device_Properties_Required; } @@ -1296,16 +1294,7 @@ void Device_Property_Lists( *pOptional = Device_Properties_Optional; } if (pProprietary) { - if (Property_List_Proprietary_Callback) { - instance = Device_Object_Instance_Number(); - if (Property_List_Proprietary_Callback( - OBJECT_DEVICE, instance, pProprietary)) { - } else { - *pProprietary = Device_Properties_Proprietary; - } - } else { - *pProprietary = Device_Properties_Proprietary; - } + *pProprietary = Device_Properties_Proprietary; } return; @@ -1418,7 +1407,8 @@ static BACNET_TIMESTAMP Last_Restore_Time; in the Backup_Failure_Timeout property of its Device object, device B should assume that the restore procedure has been aborted, and device B should exit restore mode.*/ -static uint16_t Backup_Failure_Timeout; +static uint16_t Backup_Failure_Timeout = 60 * 60; +static uint32_t Backup_Failure_Timeout_Milliseconds; /* This property indicates the amount of time in seconds that the device might remain unresponsive after the sending of a ReinitializeDevice-ACK at the start of a backup procedure. @@ -1529,18 +1519,44 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) break; #if defined BACNET_BACKUP_RESTORE case BACNET_REINIT_STARTBACKUP: + if (Device_Backup_State_In_Progress(Backup_State)) { + rd_data->error_class = ERROR_CLASS_DEVICE; + rd_data->error_code = ERROR_CODE_CONFIGURATION_IN_PROGRESS; + break; + } + Backup_State = BACKUP_STATE_PREPARING_FOR_BACKUP; + Device_Backup_Failure_Timeout_Restart(); Device_Start_Backup(); Reinitialize_State = rd_data->state; status = true; break; case BACNET_REINIT_STARTRESTORE: + if (Device_Backup_State_In_Progress(Backup_State)) { + rd_data->error_class = ERROR_CLASS_DEVICE; + rd_data->error_code = ERROR_CODE_CONFIGURATION_IN_PROGRESS; + break; + } + Backup_State = BACKUP_STATE_PREPARING_FOR_RESTORE; + Device_Backup_Failure_Timeout_Restart(); Device_Start_Restore(); Reinitialize_State = rd_data->state; status = true; break; - case BACNET_REINIT_ENDBACKUP: case BACNET_REINIT_ENDRESTORE: + if (Backup_State != BACKUP_STATE_PERFORMING_A_RESTORE) { + rd_data->error_class = ERROR_CLASS_DEVICE; + rd_data->error_code = ERROR_CODE_CONFIGURATION_IN_PROGRESS; + break; + } + Device_Backup_Failure_Timeout_Restart(); + Device_End_Restore(); + Reinitialize_State = rd_data->state; + status = true; + break; + case BACNET_REINIT_ENDBACKUP: case BACNET_REINIT_ABORTRESTORE: + Backup_State = BACKUP_STATE_IDLE; + Device_Backup_Failure_Timeout_Reset(); Reinitialize_State = rd_data->state; status = true; break; @@ -2453,8 +2469,91 @@ bool Device_Backup_And_Restore_State_Set(BACNET_BACKUP_STATE state) Backup_State = state; return true; } + +/** + * @brief Reset the backup failure timeout countdown to zero + * @note This should be called when the backup failure timeout is no longer + * needed, such as when a backup or restore operation has completed or failed. + */ +void Device_Backup_Failure_Timeout_Reset(void) +{ + Backup_Failure_Timeout_Milliseconds = 0; +} #endif +/** + * @brief Determine if a backup or restore operation is currently in progress + * @param state The current backup state to check + * @return True if a backup or restore operation is in progress, else False + */ +bool Device_Backup_State_In_Progress(BACNET_BACKUP_STATE state) +{ + if ((state != BACKUP_STATE_IDLE) && + (state != BACKUP_STATE_BACKUP_FAILURE) && + (state != BACKUP_STATE_RESTORE_FAILURE)) { + return true; + } + return false; +} + +/** + * @brief Start the backup failure timeout countdown by converting the value to + * milliseconds + * @note This should be called when starting a backup or restore operation, and + * the Backup_Failure_Timeout_Milliseconds variable should be decremented in + * the main loop or a timer interrupt to track the timeout. + */ +void Device_Backup_Failure_Timeout_Restart(void) +{ +#if defined(BACNET_BACKUP_RESTORE) + if (Device_Backup_State_In_Progress(Backup_State)) { + /* service related to backup & restore will reset the backup failure + timeout during a backup or restore operation */ + Backup_Failure_Timeout_Milliseconds = Backup_Failure_Timeout * 1000UL; + } +#endif +} + +/** + * @brief Decrement the backup failure timeout countdown by the given number of + * milliseconds, and update the backup state if the timeout has expired. + * @param milliseconds The number of milliseconds to decrement from the backup + * failure timeout countdown. + * @details If device B does not receive any messages related to the backup + * procedure from device A for the number of seconds specified in the + * Backup_Failure_Timeout property of its Device object, device B should + * assume that the backup procedure has been aborted, and device B should + * exit backup mode. A message related to the backup procedure is defined + * to be any ReadProperty, ReadPropertyMultiple, WriteProperty, + * WritePropertyMultiple, CreateObject, or AtomicReadFile request + * that directly accesses a configuration File object. + */ +void Device_Backup_Failure_Timeout_Countdown(uint32_t milliseconds) +{ +#if defined(BACNET_BACKUP_RESTORE) + if (Device_Backup_State_In_Progress(Backup_State)) { + /* service related to backup & restore will restart the backup + failure timer during a backup or restore operation */ + if (Backup_Failure_Timeout_Milliseconds > 0) { + if (milliseconds >= Backup_Failure_Timeout_Milliseconds) { + Backup_Failure_Timeout_Milliseconds = 0; + } else { + Backup_Failure_Timeout_Milliseconds -= milliseconds; + } + if (Backup_Failure_Timeout_Milliseconds == 0) { + if (Backup_State == BACKUP_STATE_PERFORMING_A_BACKUP) { + Backup_State = BACKUP_STATE_BACKUP_FAILURE; + } else if (Backup_State == BACKUP_STATE_PERFORMING_A_RESTORE) { + Backup_State = BACKUP_STATE_RESTORE_FAILURE; + } + } + } + } +#else + (void)milliseconds; +#endif +} + /** * ReadProperty handler for this object. For the given ReadProperty * data, the application_data is loaded or the error flags are set. @@ -2797,6 +2896,7 @@ int Device_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata) if (!rpdata) { return 0; } + Device_Backup_Failure_Timeout_Restart(); /* initialize the default return values */ rpdata->error_class = ERROR_CLASS_OBJECT; rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT; @@ -3206,6 +3306,7 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) bool status = false; /* Ever the pessimist! */ struct object_functions *pObject = NULL; + Device_Backup_Failure_Timeout_Restart(); /* initialize the default return values */ wp_data->error_class = ERROR_CLASS_OBJECT; wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT; @@ -3446,6 +3547,7 @@ bool Device_Create_Object(BACNET_CREATE_OBJECT_DATA *data) bool object_exists = false; bool object_supported = false; + Device_Backup_Failure_Timeout_Restart(); pObject = Device_Object_Functions_Find(data->object_type); if (pObject != NULL) { if (pObject->Object_Valid_Instance && @@ -3479,6 +3581,7 @@ bool Device_Delete_Object(BACNET_DELETE_OBJECT_DATA *data) bool status = false; struct object_functions *pObject = NULL; + Device_Backup_Failure_Timeout_Restart(); pObject = Device_Object_Functions_Find(data->object_type); if (pObject != NULL) { if (!pObject->Object_Delete) { @@ -3513,6 +3616,34 @@ bool Device_Delete_Object(BACNET_DELETE_OBJECT_DATA *data) return status; } +/** + * @brief Loops through all the objects and deletes them, + * if DeleteObject service is supported by the object type. + */ +void Device_Delete_Objects(void) +{ + struct object_functions *pObject = NULL; + uint32_t instance = 0; + unsigned count = 0; + + pObject = Object_Table; + while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) { + count = 0; + if (pObject->Object_Count) { + count = pObject->Object_Count(); + } + while (count) { + count--; + if ((pObject->Object_Delete) && + (pObject->Object_Index_To_Instance)) { + instance = pObject->Object_Index_To_Instance(count); + pObject->Object_Delete(instance); + } + } + pObject++; + } +} + /** * @brief Loop through the Device object-list property and export to * a file as BACnet CreateObject services with List of Initial Values @@ -3532,9 +3663,7 @@ void Device_Start_Backup(void) bool status = false; int32_t len = 0, offset = 0; - Backup_State = BACKUP_STATE_PREPARING_FOR_BACKUP; object_count = Device_Object_List_Count(); - Backup_State = BACKUP_STATE_PERFORMING_A_BACKUP; for (i = 0; i < object_count; i++) { /* get the object type and instance from the device object list */ status = Device_Object_List_Identifier( @@ -3560,7 +3689,18 @@ void Device_Start_Backup(void) } } } - Backup_State = BACKUP_STATE_IDLE; + Backup_State = BACKUP_STATE_PERFORMING_A_BACKUP; +#endif +} + +/** + * @brief Create files for backup and restore, if supported, and set the state + * to performing a restore + */ +void Device_Start_Restore(void) +{ +#if defined BACNET_BACKUP_RESTORE + Backup_State = BACKUP_STATE_PERFORMING_A_RESTORE; #endif } @@ -3569,7 +3709,7 @@ void Device_Start_Backup(void) * a file as BACnet CreateObject services with List of Initial Values * for every writable property */ -void Device_Start_Restore(void) +void Device_End_Restore(void) { #if defined BACNET_BACKUP_RESTORE BACNET_DATE_TIME bdateTime = { 0 }; @@ -3580,7 +3720,8 @@ void Device_Start_Restore(void) datetime_local(&bdateTime.date, &bdateTime.time, NULL, NULL); bacapp_timestamp_datetime_set(&Last_Restore_Time, &bdateTime); - Backup_State = BACKUP_STATE_PREPARING_FOR_RESTORE; + /* delete all existing objects before restore */ + Device_Delete_Objects(); /* create objects from the backup file */ file_size = bacfile_file_size(Configuration_Files[0]); while (offset < file_size) { @@ -3600,15 +3741,19 @@ void Device_Start_Restore(void) /* error creating object - keep going */ } } else { + Backup_State = BACKUP_STATE_RESTORE_FAILURE; /* error while decoding object */ break; } } else { + Backup_State = BACKUP_STATE_RESTORE_FAILURE; /* error while reading file */ break; } } - Backup_State = BACKUP_STATE_IDLE; + if (Backup_State != BACKUP_STATE_RESTORE_FAILURE) { + Backup_State = BACKUP_STATE_IDLE; + } #endif } @@ -3778,8 +3923,10 @@ void Device_Timer(uint16_t milliseconds) unsigned count = 0; uint32_t instance; + Device_Backup_Failure_Timeout_Countdown(milliseconds); pObject = Object_Table; while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) { + count = 0; if (pObject->Object_Count) { count = pObject->Object_Count(); }