Support routed virtual device backup/restore reinitialization (#1320)
* Support routed virtual device backup restore reinitialization Allow routed virtual devices to accept ReinitializeDevice so Backup and Restore states can be handled per device. Gateway behavior remains unchanged, and DeviceCommunicationControl remains disabled for virtual devices. Virtual-device COLDSTART, WARMSTART, and ACTIVATE_CHANGES requests now return OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED instead of being acknowledged. * Cover routed device backup restore test variants Add routed-device tests for ReinitializeDevice service approval, DCC blocking, virtual-device unsupported reinitialize states, per-device Backup/Restore state, and backup timeout countdown behavior. Build device tests in four compile-time variants so BAC_ROUTING and BACNET_BACKUP_RESTORE are covered in both enabled and disabled combinations. * Keep routed device variant tests in CTest Register each optional device test build as its own CTest build/run pair so BAC_ROUTING and BACNET_BACKUP_RESTORE variants keep the existing fixture-based build-before-run behavior without changing the top-level test CMake file. Constraint: Top-level test/CMakeLists.txt remains unchanged to preserve the existing test registration convention Confidence: high Scope-risk: narrow Tested: cmake -S test -B /tmp/bacnet-stack-test-cmake-pr1320 Tested: ctest --test-dir /tmp/bacnet-stack-test-cmake-pr1320 -R '^test_device(_.*)?$' --output-on-failure -j4 Not-tested: Full repository CTest suite * Ensure Backup/Restore has real configuration-file storage Centralize reinitialize state storage so routed devices and the default device use the same access path. Enforce BACNET_BACKUP_FILE_COUNT as a positive Backup/Restore invariant, while preserving BACNET_BACKUP_RESTORE guards for no-backup builds. Constraint: BACNET_BACKUP_RESTORE performs backup and restore through Configuration_Files[0]. Rejected: Preserve BACNET_BACKUP_FILE_COUNT=0 support | it leaves only state/property handling without a usable backup file. Confidence: high Scope-risk: moderate Directive: Guard no-backup builds with BACNET_BACKUP_RESTORE, not BACNET_BACKUP_FILE_COUNT. Tested: ctest --test-dir test/build -R '^(build_device|test_device|build_device_backup_restore|test_device_backup_restore|build_device_bac_routing|test_device_bac_routing|build_device_bac_routing_backup_restore|test_device_bac_routing_backup_restore)$' --output-on-failure Tested: cmake --build build --target server gateway gateway2 bacbasic Not-tested: Runtime BACnet client backup/restore exchange --------- Signed-off-by: kimhyeongjun <hjun1.kim@samsung.com> Co-authored-by: OmX <omx@oh-my-codex.dev>
This commit is contained in:
@@ -1465,17 +1465,14 @@ static uint32_t Database_Revision = 0;
|
|||||||
/* Auto_Slave_Discovery */
|
/* Auto_Slave_Discovery */
|
||||||
/* Slave_Address_Binding */
|
/* Slave_Address_Binding */
|
||||||
/* Profile_Name */
|
/* Profile_Name */
|
||||||
static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE;
|
static BACNET_DEVICE_REINITIALIZE_DATA Reinitialize_Data = {
|
||||||
static const char *Reinit_Password = "filister";
|
.State = BACNET_REINIT_IDLE, .Password = "filister"
|
||||||
|
};
|
||||||
static write_property_function Device_Write_Property_Store_Callback;
|
static write_property_function Device_Write_Property_Store_Callback;
|
||||||
static list_element_function Device_Add_List_Element_Callback;
|
static list_element_function Device_Add_List_Element_Callback;
|
||||||
static list_element_function Device_Remove_List_Element_Callback;
|
static list_element_function Device_Remove_List_Element_Callback;
|
||||||
/* backup and restore */
|
/* backup and restore */
|
||||||
#if defined BACNET_BACKUP_RESTORE
|
#if defined BACNET_BACKUP_RESTORE
|
||||||
/* number of backup files */
|
|
||||||
#ifndef BACNET_BACKUP_FILE_COUNT
|
|
||||||
#define BACNET_BACKUP_FILE_COUNT 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* device A will read the Configuration_Files property of the Device object.
|
/* device A will read the Configuration_Files property of the Device object.
|
||||||
This property will be used to determine the files to read and in what
|
This property will be used to determine the files to read and in what
|
||||||
@@ -1520,6 +1517,140 @@ static BACNET_BACKUP_STATE Backup_State = BACKUP_STATE_IDLE;
|
|||||||
|
|
||||||
#ifdef BAC_ROUTING
|
#ifdef BAC_ROUTING
|
||||||
static bool Device_Router_Mode = false;
|
static bool Device_Router_Mode = false;
|
||||||
|
|
||||||
|
static DEVICE_OBJECT_DATA *Device_Routed_Data(void)
|
||||||
|
{
|
||||||
|
if (Device_Router_Mode) {
|
||||||
|
return Get_Routed_Device_Object(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Device_Routed_Virtual_Device(void)
|
||||||
|
{
|
||||||
|
return Device_Router_Mode && (Routed_Device_Object_Index() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static BACNET_DEVICE_REINITIALIZE_DATA *Device_Reinitialize_Data(void)
|
||||||
|
{
|
||||||
|
#if defined(BAC_ROUTING)
|
||||||
|
DEVICE_OBJECT_DATA *pDev = Device_Routed_Data();
|
||||||
|
|
||||||
|
if (pDev) {
|
||||||
|
return &pDev->Reinitialize;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return &Reinitialize_Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(BACNET_BACKUP_RESTORE)
|
||||||
|
static uint32_t *Device_Configuration_Files_Value(void)
|
||||||
|
{
|
||||||
|
#if defined(BAC_ROUTING)
|
||||||
|
DEVICE_OBJECT_DATA *pDev = Device_Routed_Data();
|
||||||
|
|
||||||
|
if (pDev) {
|
||||||
|
return pDev->Backup.Configuration_Files;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return Configuration_Files;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BACNET_TIMESTAMP *Device_Last_Restore_Time_Value(void)
|
||||||
|
{
|
||||||
|
#if defined(BAC_ROUTING)
|
||||||
|
DEVICE_OBJECT_DATA *pDev = Device_Routed_Data();
|
||||||
|
|
||||||
|
if (pDev) {
|
||||||
|
return &pDev->Backup.Last_Restore_Time;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return &Last_Restore_Time;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t *Device_Backup_Failure_Timeout_Value(void)
|
||||||
|
{
|
||||||
|
#if defined(BAC_ROUTING)
|
||||||
|
DEVICE_OBJECT_DATA *pDev = Device_Routed_Data();
|
||||||
|
|
||||||
|
if (pDev) {
|
||||||
|
return &pDev->Backup.Backup_Failure_Timeout;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return &Backup_Failure_Timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t *Device_Backup_Failure_Timeout_Milliseconds_Value(void)
|
||||||
|
{
|
||||||
|
#if defined(BAC_ROUTING)
|
||||||
|
DEVICE_OBJECT_DATA *pDev = Device_Routed_Data();
|
||||||
|
|
||||||
|
if (pDev) {
|
||||||
|
return &pDev->Backup.Backup_Failure_Timeout_Milliseconds;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return &Backup_Failure_Timeout_Milliseconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t *Device_Backup_Preparation_Time_Value(void)
|
||||||
|
{
|
||||||
|
#if defined(BAC_ROUTING)
|
||||||
|
DEVICE_OBJECT_DATA *pDev = Device_Routed_Data();
|
||||||
|
|
||||||
|
if (pDev) {
|
||||||
|
return &pDev->Backup.Backup_Preparation_Time;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return &Backup_Preparation_Time;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t *Device_Restore_Preparation_Time_Value(void)
|
||||||
|
{
|
||||||
|
#if defined(BAC_ROUTING)
|
||||||
|
DEVICE_OBJECT_DATA *pDev = Device_Routed_Data();
|
||||||
|
|
||||||
|
if (pDev) {
|
||||||
|
return &pDev->Backup.Restore_Preparation_Time;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return &Restore_Preparation_Time;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t *Device_Restore_Completion_Time_Value(void)
|
||||||
|
{
|
||||||
|
#if defined(BAC_ROUTING)
|
||||||
|
DEVICE_OBJECT_DATA *pDev = Device_Routed_Data();
|
||||||
|
|
||||||
|
if (pDev) {
|
||||||
|
return &pDev->Backup.Restore_Completion_Time;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return &Restore_Completion_Time;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BACNET_BACKUP_STATE *Device_Backup_State_Value(void)
|
||||||
|
{
|
||||||
|
#if defined(BAC_ROUTING)
|
||||||
|
DEVICE_OBJECT_DATA *pDev = Device_Routed_Data();
|
||||||
|
|
||||||
|
if (pDev) {
|
||||||
|
return &pDev->Backup.Backup_State;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return &Backup_State;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1535,7 +1666,10 @@ static bool Device_Router_Mode = false;
|
|||||||
*/
|
*/
|
||||||
bool Device_Reinitialize_Password_Set(const char *password)
|
bool Device_Reinitialize_Password_Set(const char *password)
|
||||||
{
|
{
|
||||||
Reinit_Password = password;
|
BACNET_DEVICE_REINITIALIZE_DATA *reinitialize_data =
|
||||||
|
Device_Reinitialize_Data();
|
||||||
|
|
||||||
|
reinitialize_data->Password = password;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1559,6 +1693,13 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
|
|||||||
bool password_success = false;
|
bool password_success = false;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
size_t length;
|
size_t length;
|
||||||
|
BACNET_DEVICE_REINITIALIZE_DATA *reinitialize_data =
|
||||||
|
Device_Reinitialize_Data();
|
||||||
|
BACNET_REINITIALIZED_STATE *reinitialize_state = &reinitialize_data->State;
|
||||||
|
const char *reinit_password = reinitialize_data->Password;
|
||||||
|
#if defined BACNET_BACKUP_RESTORE
|
||||||
|
BACNET_BACKUP_STATE *backup_state = Device_Backup_State_Value();
|
||||||
|
#endif
|
||||||
|
|
||||||
/* From 16.4.1.1.2 Password
|
/* From 16.4.1.1.2 Password
|
||||||
This optional parameter shall be a CharacterString of up to
|
This optional parameter shall be a CharacterString of up to
|
||||||
@@ -1566,7 +1707,7 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
|
|||||||
protection, the service request shall be denied if the parameter
|
protection, the service request shall be denied if the parameter
|
||||||
is absent or if the password is incorrect. For those devices that
|
is absent or if the password is incorrect. For those devices that
|
||||||
do not require a password, this parameter shall be ignored.*/
|
do not require a password, this parameter shall be ignored.*/
|
||||||
if (Reinit_Password && strlen(Reinit_Password) > 0) {
|
if (reinit_password && strlen(reinit_password) > 0) {
|
||||||
if (characterstring_encoding(&rd_data->password) == CHARACTER_UTF8) {
|
if (characterstring_encoding(&rd_data->password) == CHARACTER_UTF8) {
|
||||||
length = characterstring_utf8_length(&rd_data->password);
|
length = characterstring_utf8_length(&rd_data->password);
|
||||||
} else {
|
} else {
|
||||||
@@ -1576,7 +1717,7 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
|
|||||||
rd_data->error_class = ERROR_CLASS_SERVICES;
|
rd_data->error_class = ERROR_CLASS_SERVICES;
|
||||||
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
|
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
|
||||||
} else if (characterstring_ansi_same(
|
} else if (characterstring_ansi_same(
|
||||||
&rd_data->password, Reinit_Password)) {
|
&rd_data->password, reinit_password)) {
|
||||||
password_success = true;
|
password_success = true;
|
||||||
} else {
|
} else {
|
||||||
rd_data->error_class = ERROR_CLASS_SECURITY;
|
rd_data->error_class = ERROR_CLASS_SECURITY;
|
||||||
@@ -1586,13 +1727,24 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
|
|||||||
password_success = true;
|
password_success = true;
|
||||||
}
|
}
|
||||||
if (password_success) {
|
if (password_success) {
|
||||||
|
#if defined(BAC_ROUTING)
|
||||||
|
if (Device_Routed_Virtual_Device() &&
|
||||||
|
((rd_data->state == BACNET_REINIT_COLDSTART) ||
|
||||||
|
(rd_data->state == BACNET_REINIT_WARMSTART) ||
|
||||||
|
(rd_data->state == BACNET_REINIT_ACTIVATE_CHANGES))) {
|
||||||
|
rd_data->error_class = ERROR_CLASS_SERVICES;
|
||||||
|
rd_data->error_code =
|
||||||
|
ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
switch (rd_data->state) {
|
switch (rd_data->state) {
|
||||||
case BACNET_REINIT_COLDSTART:
|
case BACNET_REINIT_COLDSTART:
|
||||||
dcc_set_status_duration(COMMUNICATION_ENABLE, 0);
|
dcc_set_status_duration(COMMUNICATION_ENABLE, 0);
|
||||||
/* note: you probably want to restart *after* the
|
/* note: you probably want to restart *after* the
|
||||||
simple ack has been sent from the return handler
|
simple ack has been sent from the return handler
|
||||||
so just set a flag from here */
|
so just set a flag from here */
|
||||||
Reinitialize_State = rd_data->state;
|
*reinitialize_state = rd_data->state;
|
||||||
status = true;
|
status = true;
|
||||||
break;
|
break;
|
||||||
case BACNET_REINIT_WARMSTART:
|
case BACNET_REINIT_WARMSTART:
|
||||||
@@ -1604,50 +1756,50 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
|
|||||||
/* note: you probably want to restart *after* the
|
/* note: you probably want to restart *after* the
|
||||||
simple ack has been sent from the return handler
|
simple ack has been sent from the return handler
|
||||||
so just set a flag from here */
|
so just set a flag from here */
|
||||||
Reinitialize_State = rd_data->state;
|
*reinitialize_state = rd_data->state;
|
||||||
status = true;
|
status = true;
|
||||||
break;
|
break;
|
||||||
#if defined BACNET_BACKUP_RESTORE
|
#if defined BACNET_BACKUP_RESTORE
|
||||||
case BACNET_REINIT_STARTBACKUP:
|
case BACNET_REINIT_STARTBACKUP:
|
||||||
if (Device_Backup_State_In_Progress(Backup_State)) {
|
if (Device_Backup_State_In_Progress(*backup_state)) {
|
||||||
rd_data->error_class = ERROR_CLASS_DEVICE;
|
rd_data->error_class = ERROR_CLASS_DEVICE;
|
||||||
rd_data->error_code = ERROR_CODE_CONFIGURATION_IN_PROGRESS;
|
rd_data->error_code = ERROR_CODE_CONFIGURATION_IN_PROGRESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Backup_State = BACKUP_STATE_PREPARING_FOR_BACKUP;
|
*backup_state = BACKUP_STATE_PREPARING_FOR_BACKUP;
|
||||||
Device_Backup_Failure_Timeout_Restart();
|
Device_Backup_Failure_Timeout_Restart();
|
||||||
Device_Start_Backup();
|
Device_Start_Backup();
|
||||||
Reinitialize_State = rd_data->state;
|
*reinitialize_state = rd_data->state;
|
||||||
status = true;
|
status = true;
|
||||||
break;
|
break;
|
||||||
case BACNET_REINIT_STARTRESTORE:
|
case BACNET_REINIT_STARTRESTORE:
|
||||||
if (Device_Backup_State_In_Progress(Backup_State)) {
|
if (Device_Backup_State_In_Progress(*backup_state)) {
|
||||||
rd_data->error_class = ERROR_CLASS_DEVICE;
|
rd_data->error_class = ERROR_CLASS_DEVICE;
|
||||||
rd_data->error_code = ERROR_CODE_CONFIGURATION_IN_PROGRESS;
|
rd_data->error_code = ERROR_CODE_CONFIGURATION_IN_PROGRESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Backup_State = BACKUP_STATE_PREPARING_FOR_RESTORE;
|
*backup_state = BACKUP_STATE_PREPARING_FOR_RESTORE;
|
||||||
Device_Backup_Failure_Timeout_Restart();
|
Device_Backup_Failure_Timeout_Restart();
|
||||||
Device_Start_Restore();
|
Device_Start_Restore();
|
||||||
Reinitialize_State = rd_data->state;
|
*reinitialize_state = rd_data->state;
|
||||||
status = true;
|
status = true;
|
||||||
break;
|
break;
|
||||||
case BACNET_REINIT_ENDRESTORE:
|
case BACNET_REINIT_ENDRESTORE:
|
||||||
if (Backup_State != BACKUP_STATE_PERFORMING_A_RESTORE) {
|
if (*backup_state != BACKUP_STATE_PERFORMING_A_RESTORE) {
|
||||||
rd_data->error_class = ERROR_CLASS_DEVICE;
|
rd_data->error_class = ERROR_CLASS_DEVICE;
|
||||||
rd_data->error_code = ERROR_CODE_CONFIGURATION_IN_PROGRESS;
|
rd_data->error_code = ERROR_CODE_CONFIGURATION_IN_PROGRESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Device_Backup_Failure_Timeout_Restart();
|
Device_Backup_Failure_Timeout_Restart();
|
||||||
Device_End_Restore();
|
Device_End_Restore();
|
||||||
Reinitialize_State = rd_data->state;
|
*reinitialize_state = rd_data->state;
|
||||||
status = true;
|
status = true;
|
||||||
break;
|
break;
|
||||||
case BACNET_REINIT_ENDBACKUP:
|
case BACNET_REINIT_ENDBACKUP:
|
||||||
case BACNET_REINIT_ABORTRESTORE:
|
case BACNET_REINIT_ABORTRESTORE:
|
||||||
Backup_State = BACKUP_STATE_IDLE;
|
*backup_state = BACKUP_STATE_IDLE;
|
||||||
Device_Backup_Failure_Timeout_Reset();
|
Device_Backup_Failure_Timeout_Reset();
|
||||||
Reinitialize_State = rd_data->state;
|
*reinitialize_state = rd_data->state;
|
||||||
status = true;
|
status = true;
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
@@ -1672,7 +1824,7 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
|
|||||||
Network_Port_Changes_Pending_Activate(
|
Network_Port_Changes_Pending_Activate(
|
||||||
Network_Port_Index_To_Instance(i));
|
Network_Port_Index_To_Instance(i));
|
||||||
}
|
}
|
||||||
Reinitialize_State = rd_data->state;
|
*reinitialize_state = rd_data->state;
|
||||||
status = true;
|
status = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -1687,12 +1839,13 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
|
|||||||
|
|
||||||
BACNET_REINITIALIZED_STATE Device_Reinitialized_State(void)
|
BACNET_REINITIALIZED_STATE Device_Reinitialized_State(void)
|
||||||
{
|
{
|
||||||
return Reinitialize_State;
|
return Device_Reinitialize_Data()->State;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device_Reinitialize_State_Set(BACNET_REINITIALIZED_STATE state)
|
bool Device_Reinitialize_State_Set(BACNET_REINITIALIZED_STATE state)
|
||||||
{
|
{
|
||||||
Reinitialize_State = state;
|
Device_Reinitialize_Data()->State = state;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2467,9 +2620,11 @@ uint32_t Device_Interval_Offset(void)
|
|||||||
bool Device_Configuration_File_Set(unsigned index, uint32_t instance)
|
bool Device_Configuration_File_Set(unsigned index, uint32_t instance)
|
||||||
{
|
{
|
||||||
bool status = false;
|
bool status = false;
|
||||||
#if BACNET_BACKUP_FILE_COUNT
|
#if defined(BACNET_BACKUP_RESTORE)
|
||||||
|
uint32_t *configuration_files = Device_Configuration_Files_Value();
|
||||||
|
|
||||||
if (index < BACNET_BACKUP_FILE_COUNT) {
|
if (index < BACNET_BACKUP_FILE_COUNT) {
|
||||||
Configuration_Files[index] = instance;
|
configuration_files[index] = instance;
|
||||||
status = true;
|
status = true;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@@ -2483,10 +2638,11 @@ bool Device_Configuration_File_Set(unsigned index, uint32_t instance)
|
|||||||
uint32_t Device_Configuration_File(unsigned index)
|
uint32_t Device_Configuration_File(unsigned index)
|
||||||
{
|
{
|
||||||
uint32_t instance = BACNET_MAX_INSTANCE + 1;
|
uint32_t instance = BACNET_MAX_INSTANCE + 1;
|
||||||
|
#if defined(BACNET_BACKUP_RESTORE)
|
||||||
|
uint32_t *configuration_files = Device_Configuration_Files_Value();
|
||||||
|
|
||||||
#if BACNET_BACKUP_FILE_COUNT
|
|
||||||
if (index < BACNET_BACKUP_FILE_COUNT) {
|
if (index < BACNET_BACKUP_FILE_COUNT) {
|
||||||
instance = Configuration_Files[index];
|
instance = configuration_files[index];
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
(void)index;
|
(void)index;
|
||||||
@@ -2505,11 +2661,12 @@ uint32_t Device_Configuration_File(unsigned index)
|
|||||||
bool Device_Is_Configuration_File(uint32_t instance)
|
bool Device_Is_Configuration_File(uint32_t instance)
|
||||||
{
|
{
|
||||||
bool status = false;
|
bool status = false;
|
||||||
|
#if defined(BACNET_BACKUP_RESTORE)
|
||||||
#if BACNET_BACKUP_FILE_COUNT
|
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
uint32_t *configuration_files = Device_Configuration_Files_Value();
|
||||||
|
|
||||||
for (i = 0; i < BACNET_BACKUP_FILE_COUNT; i++) {
|
for (i = 0; i < BACNET_BACKUP_FILE_COUNT; i++) {
|
||||||
if (Configuration_Files[i] == instance) {
|
if (configuration_files[i] == instance) {
|
||||||
status = true;
|
status = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2537,10 +2694,12 @@ int Device_Configuration_File_Encode(
|
|||||||
int apdu_len = BACNET_STATUS_ERROR;
|
int apdu_len = BACNET_STATUS_ERROR;
|
||||||
|
|
||||||
(void)object_instance;
|
(void)object_instance;
|
||||||
#if BACNET_BACKUP_FILE_COUNT
|
#if defined(BACNET_BACKUP_RESTORE)
|
||||||
|
uint32_t *configuration_files = Device_Configuration_Files_Value();
|
||||||
|
|
||||||
if (array_index < BACNET_BACKUP_FILE_COUNT) {
|
if (array_index < BACNET_BACKUP_FILE_COUNT) {
|
||||||
apdu_len = encode_application_object_id(
|
apdu_len = encode_application_object_id(
|
||||||
apdu, OBJECT_FILE, Configuration_Files[array_index]);
|
apdu, OBJECT_FILE, configuration_files[array_index]);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
(void)array_index;
|
(void)array_index;
|
||||||
@@ -2620,56 +2779,67 @@ static BACNET_ERROR_CODE Device_Configuration_File_Write(
|
|||||||
|
|
||||||
uint16_t Device_Backup_Failure_Timeout(void)
|
uint16_t Device_Backup_Failure_Timeout(void)
|
||||||
{
|
{
|
||||||
return Backup_Failure_Timeout;
|
return *Device_Backup_Failure_Timeout_Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device_Backup_Failure_Timeout_Set(uint16_t timeout)
|
bool Device_Backup_Failure_Timeout_Set(uint16_t timeout)
|
||||||
{
|
{
|
||||||
Backup_Failure_Timeout = timeout;
|
uint16_t *backup_failure_timeout = Device_Backup_Failure_Timeout_Value();
|
||||||
|
|
||||||
|
*backup_failure_timeout = timeout;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t Device_Backup_Preparation_Time(void)
|
uint16_t Device_Backup_Preparation_Time(void)
|
||||||
{
|
{
|
||||||
return Backup_Preparation_Time;
|
return *Device_Backup_Preparation_Time_Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device_Backup_Preparation_Time_Set(uint16_t time)
|
bool Device_Backup_Preparation_Time_Set(uint16_t time)
|
||||||
{
|
{
|
||||||
Backup_Preparation_Time = time;
|
uint16_t *backup_preparation_time = Device_Backup_Preparation_Time_Value();
|
||||||
|
|
||||||
|
*backup_preparation_time = time;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t Device_Restore_Preparation_Time(void)
|
uint16_t Device_Restore_Preparation_Time(void)
|
||||||
{
|
{
|
||||||
return Restore_Preparation_Time;
|
return *Device_Restore_Preparation_Time_Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device_Restore_Preparation_Time_Set(uint16_t time)
|
bool Device_Restore_Preparation_Time_Set(uint16_t time)
|
||||||
{
|
{
|
||||||
Restore_Preparation_Time = time;
|
uint16_t *restore_preparation_time =
|
||||||
|
Device_Restore_Preparation_Time_Value();
|
||||||
|
|
||||||
|
*restore_preparation_time = time;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t Device_Restore_Completion_Time(void)
|
uint16_t Device_Restore_Completion_Time(void)
|
||||||
{
|
{
|
||||||
return Restore_Completion_Time;
|
return *Device_Restore_Completion_Time_Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device_Restore_Completion_Time_Set(uint16_t time)
|
bool Device_Restore_Completion_Time_Set(uint16_t time)
|
||||||
{
|
{
|
||||||
Restore_Completion_Time = time;
|
uint16_t *restore_completion_time = Device_Restore_Completion_Time_Value();
|
||||||
|
|
||||||
|
*restore_completion_time = time;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
BACNET_BACKUP_STATE Device_Backup_And_Restore_State(void)
|
BACNET_BACKUP_STATE Device_Backup_And_Restore_State(void)
|
||||||
{
|
{
|
||||||
return Backup_State;
|
return *Device_Backup_State_Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device_Backup_And_Restore_State_Set(BACNET_BACKUP_STATE state)
|
bool Device_Backup_And_Restore_State_Set(BACNET_BACKUP_STATE state)
|
||||||
{
|
{
|
||||||
Backup_State = state;
|
BACNET_BACKUP_STATE *backup_state = Device_Backup_State_Value();
|
||||||
|
|
||||||
|
*backup_state = state;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2680,7 +2850,10 @@ bool Device_Backup_And_Restore_State_Set(BACNET_BACKUP_STATE state)
|
|||||||
*/
|
*/
|
||||||
void Device_Backup_Failure_Timeout_Reset(void)
|
void Device_Backup_Failure_Timeout_Reset(void)
|
||||||
{
|
{
|
||||||
Backup_Failure_Timeout_Milliseconds = 0;
|
uint32_t *backup_failure_timeout_milliseconds =
|
||||||
|
Device_Backup_Failure_Timeout_Milliseconds_Value();
|
||||||
|
|
||||||
|
*backup_failure_timeout_milliseconds = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2709,10 +2882,15 @@ bool Device_Backup_State_In_Progress(BACNET_BACKUP_STATE state)
|
|||||||
void Device_Backup_Failure_Timeout_Restart(void)
|
void Device_Backup_Failure_Timeout_Restart(void)
|
||||||
{
|
{
|
||||||
#if defined(BACNET_BACKUP_RESTORE)
|
#if defined(BACNET_BACKUP_RESTORE)
|
||||||
if (Device_Backup_State_In_Progress(Backup_State)) {
|
BACNET_BACKUP_STATE *backup_state = Device_Backup_State_Value();
|
||||||
|
uint16_t *backup_failure_timeout = Device_Backup_Failure_Timeout_Value();
|
||||||
|
uint32_t *backup_failure_timeout_milliseconds =
|
||||||
|
Device_Backup_Failure_Timeout_Milliseconds_Value();
|
||||||
|
|
||||||
|
if (Device_Backup_State_In_Progress(*backup_state)) {
|
||||||
/* service related to backup & restore will reset the backup failure
|
/* service related to backup & restore will reset the backup failure
|
||||||
timeout during a backup or restore operation */
|
timeout during a backup or restore operation */
|
||||||
Backup_Failure_Timeout_Milliseconds = Backup_Failure_Timeout * 1000UL;
|
*backup_failure_timeout_milliseconds = *backup_failure_timeout * 1000UL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -2734,20 +2912,24 @@ void Device_Backup_Failure_Timeout_Restart(void)
|
|||||||
void Device_Backup_Failure_Timeout_Countdown(uint32_t milliseconds)
|
void Device_Backup_Failure_Timeout_Countdown(uint32_t milliseconds)
|
||||||
{
|
{
|
||||||
#if defined(BACNET_BACKUP_RESTORE)
|
#if defined(BACNET_BACKUP_RESTORE)
|
||||||
if (Device_Backup_State_In_Progress(Backup_State)) {
|
BACNET_BACKUP_STATE *backup_state = Device_Backup_State_Value();
|
||||||
|
uint32_t *backup_failure_timeout_milliseconds =
|
||||||
|
Device_Backup_Failure_Timeout_Milliseconds_Value();
|
||||||
|
|
||||||
|
if (Device_Backup_State_In_Progress(*backup_state)) {
|
||||||
/* service related to backup & restore will restart the backup
|
/* service related to backup & restore will restart the backup
|
||||||
failure timer during a backup or restore operation */
|
failure timer during a backup or restore operation */
|
||||||
if (Backup_Failure_Timeout_Milliseconds > 0) {
|
if (*backup_failure_timeout_milliseconds > 0) {
|
||||||
if (milliseconds >= Backup_Failure_Timeout_Milliseconds) {
|
if (milliseconds >= *backup_failure_timeout_milliseconds) {
|
||||||
Backup_Failure_Timeout_Milliseconds = 0;
|
*backup_failure_timeout_milliseconds = 0;
|
||||||
} else {
|
} else {
|
||||||
Backup_Failure_Timeout_Milliseconds -= milliseconds;
|
*backup_failure_timeout_milliseconds -= milliseconds;
|
||||||
}
|
}
|
||||||
if (Backup_Failure_Timeout_Milliseconds == 0) {
|
if (*backup_failure_timeout_milliseconds == 0) {
|
||||||
if (Backup_State == BACKUP_STATE_PERFORMING_A_BACKUP) {
|
if (*backup_state == BACKUP_STATE_PERFORMING_A_BACKUP) {
|
||||||
Backup_State = BACKUP_STATE_BACKUP_FAILURE;
|
*backup_state = BACKUP_STATE_BACKUP_FAILURE;
|
||||||
} else if (Backup_State == BACKUP_STATE_PERFORMING_A_RESTORE) {
|
} else if (*backup_state == BACKUP_STATE_PERFORMING_A_RESTORE) {
|
||||||
Backup_State = BACKUP_STATE_RESTORE_FAILURE;
|
*backup_state = BACKUP_STATE_RESTORE_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3888,6 +4070,8 @@ void Device_Start_Backup(void)
|
|||||||
BACNET_CREATE_OBJECT_DATA create_data = { 0 };
|
BACNET_CREATE_OBJECT_DATA create_data = { 0 };
|
||||||
bool status = false;
|
bool status = false;
|
||||||
int32_t len = 0, offset = 0;
|
int32_t len = 0, offset = 0;
|
||||||
|
BACNET_BACKUP_STATE *backup_state = Device_Backup_State_Value();
|
||||||
|
uint32_t *configuration_files = Device_Configuration_Files_Value();
|
||||||
|
|
||||||
object_count = Device_Object_List_Count();
|
object_count = Device_Object_List_Count();
|
||||||
for (i = 0; i < object_count; i++) {
|
for (i = 0; i < object_count; i++) {
|
||||||
@@ -3909,13 +4093,13 @@ void Device_Start_Backup(void)
|
|||||||
Device_Read_Property);
|
Device_Read_Property);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
(void)bacfile_write_offset(
|
(void)bacfile_write_offset(
|
||||||
Configuration_Files[0], offset, &object_apdu[0],
|
configuration_files[0], offset, &object_apdu[0],
|
||||||
(uint32_t)len);
|
(uint32_t)len);
|
||||||
offset += len;
|
offset += len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Backup_State = BACKUP_STATE_PERFORMING_A_BACKUP;
|
*backup_state = BACKUP_STATE_PERFORMING_A_BACKUP;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3926,7 +4110,9 @@ void Device_Start_Backup(void)
|
|||||||
void Device_Start_Restore(void)
|
void Device_Start_Restore(void)
|
||||||
{
|
{
|
||||||
#if defined BACNET_BACKUP_RESTORE
|
#if defined BACNET_BACKUP_RESTORE
|
||||||
Backup_State = BACKUP_STATE_PERFORMING_A_RESTORE;
|
BACNET_BACKUP_STATE *backup_state = Device_Backup_State_Value();
|
||||||
|
|
||||||
|
*backup_state = BACKUP_STATE_PERFORMING_A_RESTORE;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3943,16 +4129,19 @@ void Device_End_Restore(void)
|
|||||||
uint8_t apdu[MAX_APDU] = { 0 };
|
uint8_t apdu[MAX_APDU] = { 0 };
|
||||||
int32_t apdu_len = 0, offset = 0, file_size = 0;
|
int32_t apdu_len = 0, offset = 0, file_size = 0;
|
||||||
int decoded_len = 0;
|
int decoded_len = 0;
|
||||||
|
BACNET_BACKUP_STATE *backup_state = Device_Backup_State_Value();
|
||||||
|
BACNET_TIMESTAMP *last_restore_time = Device_Last_Restore_Time_Value();
|
||||||
|
uint32_t *configuration_files = Device_Configuration_Files_Value();
|
||||||
|
|
||||||
datetime_local(&bdateTime.date, &bdateTime.time, NULL, NULL);
|
datetime_local(&bdateTime.date, &bdateTime.time, NULL, NULL);
|
||||||
bacapp_timestamp_datetime_set(&Last_Restore_Time, &bdateTime);
|
bacapp_timestamp_datetime_set(last_restore_time, &bdateTime);
|
||||||
/* delete all existing objects before restore */
|
/* delete all existing objects before restore */
|
||||||
Device_Delete_Objects();
|
Device_Delete_Objects();
|
||||||
/* create objects from the backup file */
|
/* create objects from the backup file */
|
||||||
file_size = bacfile_file_size(Configuration_Files[0]);
|
file_size = bacfile_file_size(configuration_files[0]);
|
||||||
while (offset < file_size) {
|
while (offset < file_size) {
|
||||||
apdu_len = bacfile_read_offset(
|
apdu_len = bacfile_read_offset(
|
||||||
Configuration_Files[0], offset, &apdu[0], sizeof(apdu));
|
configuration_files[0], offset, &apdu[0], sizeof(apdu));
|
||||||
if (apdu_len > 0) {
|
if (apdu_len > 0) {
|
||||||
decoded_len = create_object_decode_service_request(
|
decoded_len = create_object_decode_service_request(
|
||||||
apdu, apdu_len, &create_data);
|
apdu, apdu_len, &create_data);
|
||||||
@@ -3967,18 +4156,18 @@ void Device_End_Restore(void)
|
|||||||
/* error creating object - keep going */
|
/* error creating object - keep going */
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Backup_State = BACKUP_STATE_RESTORE_FAILURE;
|
*backup_state = BACKUP_STATE_RESTORE_FAILURE;
|
||||||
/* error while decoding object */
|
/* error while decoding object */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Backup_State = BACKUP_STATE_RESTORE_FAILURE;
|
*backup_state = BACKUP_STATE_RESTORE_FAILURE;
|
||||||
/* error while reading file */
|
/* error while reading file */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Backup_State != BACKUP_STATE_RESTORE_FAILURE) {
|
if (*backup_state != BACKUP_STATE_RESTORE_FAILURE) {
|
||||||
Backup_State = BACKUP_STATE_IDLE;
|
*backup_state = BACKUP_STATE_IDLE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -4163,23 +4352,31 @@ void Device_Timer(uint16_t milliseconds)
|
|||||||
#ifdef BAC_ROUTING
|
#ifdef BAC_ROUTING
|
||||||
uint16_t dev_id = 0;
|
uint16_t dev_id = 0;
|
||||||
uint16_t current_dev_id = Routed_Device_Object_Index();
|
uint16_t current_dev_id = Routed_Device_Object_Index();
|
||||||
/* TODO: Multi-device Backup/Restore support
|
|
||||||
* Currently only Gateway (dev_id=0) supports Backup/Restore.
|
if (Device_Router_Mode) {
|
||||||
* Virtual devices are blocked by Routed_Device_Service_Approval().
|
for (dev_id = 0; dev_id < Get_Num_Managed_Devices(); dev_id++) {
|
||||||
* Plan to support after discussing with maintainer.
|
Set_Routed_Device_Object_Index(dev_id);
|
||||||
*
|
Device_Backup_Failure_Timeout_Countdown(milliseconds);
|
||||||
* To enable per-device Backup/Restore:
|
pObject = Object_Table;
|
||||||
* 1. Move Backup-related static variables to DEVICE_OBJECT_DATA:
|
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
|
||||||
* - Backup_State, Backup_Failure_Timeout_Milliseconds
|
count = 0;
|
||||||
* - Backup_Failure_Timeout, Configuration_Files[]
|
if (pObject->Object_Count) {
|
||||||
* - Last_Restore_Time, Backup/Restore_Preparation_Time
|
count = pObject->Object_Count();
|
||||||
* 2. Modify Routed_Device_Service_Approval() to allow RD on virtual devices
|
}
|
||||||
* 3. Call Device_Backup_Failure_Timeout_Countdown() inside the for loop
|
while (count) {
|
||||||
* for each device
|
count--;
|
||||||
*/
|
if ((pObject->Object_Timer) &&
|
||||||
Device_Backup_Failure_Timeout_Countdown(milliseconds);
|
(pObject->Object_Index_To_Instance)) {
|
||||||
for (dev_id = 0; dev_id < Get_Num_Managed_Devices(); dev_id++) {
|
instance = pObject->Object_Index_To_Instance(count);
|
||||||
Set_Routed_Device_Object_Index(dev_id);
|
pObject->Object_Timer(instance, milliseconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pObject++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Set_Routed_Device_Object_Index(current_dev_id);
|
||||||
|
} else {
|
||||||
|
Device_Backup_Failure_Timeout_Countdown(milliseconds);
|
||||||
pObject = Object_Table;
|
pObject = Object_Table;
|
||||||
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
|
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
|
||||||
count = 0;
|
count = 0;
|
||||||
@@ -4197,7 +4394,6 @@ void Device_Timer(uint16_t milliseconds)
|
|||||||
pObject++;
|
pObject++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Set_Routed_Device_Object_Index(current_dev_id);
|
|
||||||
#else
|
#else
|
||||||
Device_Backup_Failure_Timeout_Countdown(milliseconds);
|
Device_Backup_Failure_Timeout_Countdown(milliseconds);
|
||||||
pObject = Object_Table;
|
pObject = Object_Table;
|
||||||
@@ -4240,6 +4436,7 @@ void Routing_Device_Init(uint32_t first_object_instance)
|
|||||||
Device_Router_Mode = true;
|
Device_Router_Mode = true;
|
||||||
|
|
||||||
/* Initialize with our preset strings */
|
/* Initialize with our preset strings */
|
||||||
|
Routed_Device_Table_Reset();
|
||||||
Add_Routed_Device(first_object_instance, &My_Object_Name, Description);
|
Add_Routed_Device(first_object_instance, &My_Object_Name, Description);
|
||||||
|
|
||||||
/* Now substitute our routed versions of the main object functions. */
|
/* Now substitute our routed versions of the main object functions. */
|
||||||
|
|||||||
@@ -178,6 +178,34 @@ typedef struct commonBacObj_s {
|
|||||||
* This may be useful for implementations which manage multiple Devices,
|
* This may be useful for implementations which manage multiple Devices,
|
||||||
* eg, a Gateway.
|
* eg, a Gateway.
|
||||||
*/
|
*/
|
||||||
|
/* number of backup files */
|
||||||
|
#if defined(BACNET_BACKUP_RESTORE)
|
||||||
|
#ifndef BACNET_BACKUP_FILE_COUNT
|
||||||
|
#define BACNET_BACKUP_FILE_COUNT 1
|
||||||
|
#elif (BACNET_BACKUP_FILE_COUNT < 1)
|
||||||
|
#error \
|
||||||
|
"BACNET_BACKUP_FILE_COUNT must be at least 1 when BACNET_BACKUP_RESTORE is enabled"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(BAC_ROUTING) && defined(BACNET_BACKUP_RESTORE)
|
||||||
|
typedef struct bacnet_backup_restore_data_s {
|
||||||
|
BACNET_BACKUP_STATE Backup_State;
|
||||||
|
uint16_t Backup_Failure_Timeout;
|
||||||
|
uint32_t Backup_Failure_Timeout_Milliseconds;
|
||||||
|
uint32_t Configuration_Files[BACNET_BACKUP_FILE_COUNT];
|
||||||
|
BACNET_TIMESTAMP Last_Restore_Time;
|
||||||
|
uint16_t Backup_Preparation_Time;
|
||||||
|
uint16_t Restore_Preparation_Time;
|
||||||
|
uint16_t Restore_Completion_Time;
|
||||||
|
} BACNET_BACKUP_RESTORE_DATA;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct bacnet_device_reinitialize_data_s {
|
||||||
|
BACNET_REINITIALIZED_STATE State;
|
||||||
|
const char *Password;
|
||||||
|
} BACNET_DEVICE_REINITIALIZE_DATA;
|
||||||
|
|
||||||
typedef struct devObj_s {
|
typedef struct devObj_s {
|
||||||
/** The BACnet Device Address for this device; ->len depends on DLL type. */
|
/** The BACnet Device Address for this device; ->len depends on DLL type. */
|
||||||
BACNET_ADDRESS bacDevAddr;
|
BACNET_ADDRESS bacDevAddr;
|
||||||
@@ -191,6 +219,13 @@ typedef struct devObj_s {
|
|||||||
/** The upcounter that shows if the Device ID or object structure has
|
/** The upcounter that shows if the Device ID or object structure has
|
||||||
* changed. */
|
* changed. */
|
||||||
uint32_t Database_Revision;
|
uint32_t Database_Revision;
|
||||||
|
|
||||||
|
#if defined(BAC_ROUTING)
|
||||||
|
BACNET_DEVICE_REINITIALIZE_DATA Reinitialize;
|
||||||
|
#if defined(BACNET_BACKUP_RESTORE)
|
||||||
|
BACNET_BACKUP_RESTORE_DATA Backup;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
} DEVICE_OBJECT_DATA;
|
} DEVICE_OBJECT_DATA;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -502,6 +537,8 @@ uint16_t Add_Routed_Device(
|
|||||||
const BACNET_CHARACTER_STRING *Object_Name,
|
const BACNET_CHARACTER_STRING *Object_Name,
|
||||||
const char *Description);
|
const char *Description);
|
||||||
BACNET_STACK_EXPORT
|
BACNET_STACK_EXPORT
|
||||||
|
void Routed_Device_Table_Reset(void);
|
||||||
|
BACNET_STACK_EXPORT
|
||||||
DEVICE_OBJECT_DATA *Get_Routed_Device_Object(int idx);
|
DEVICE_OBJECT_DATA *Get_Routed_Device_Object(int idx);
|
||||||
BACNET_STACK_EXPORT
|
BACNET_STACK_EXPORT
|
||||||
BACNET_ADDRESS *Get_Routed_Device_Address(int idx);
|
BACNET_ADDRESS *Get_Routed_Device_Address(int idx);
|
||||||
|
|||||||
@@ -75,6 +75,14 @@ uint16_t Num_Managed_Devices = 0;
|
|||||||
*/
|
*/
|
||||||
uint16_t iCurrent_Device_Idx = 0;
|
uint16_t iCurrent_Device_Idx = 0;
|
||||||
|
|
||||||
|
/** Reset the routed Device table before rebuilding the gateway/virtual list. */
|
||||||
|
void Routed_Device_Table_Reset(void)
|
||||||
|
{
|
||||||
|
memset(&Devices[0], 0, sizeof(Devices));
|
||||||
|
Num_Managed_Devices = 0;
|
||||||
|
iCurrent_Device_Idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** Get the current routed device object index.
|
/** Get the current routed device object index.
|
||||||
* @return Index of the currently active routed device in Devices[] array
|
* @return Index of the currently active routed device in Devices[] array
|
||||||
*/
|
*/
|
||||||
@@ -150,6 +158,15 @@ uint16_t Add_Routed_Device(
|
|||||||
Routed_Device_Set_Description("No Descr", strlen("No Descr"));
|
Routed_Device_Set_Description("No Descr", strlen("No Descr"));
|
||||||
}
|
}
|
||||||
pDev->Database_Revision = 0; /* Reset/Initialize now */
|
pDev->Database_Revision = 0; /* Reset/Initialize now */
|
||||||
|
#if defined(BAC_ROUTING)
|
||||||
|
pDev->Reinitialize.State = BACNET_REINIT_IDLE;
|
||||||
|
pDev->Reinitialize.Password = "filister";
|
||||||
|
#if defined(BACNET_BACKUP_RESTORE)
|
||||||
|
memset(&pDev->Backup, 0, sizeof(pDev->Backup));
|
||||||
|
pDev->Backup.Backup_State = BACKUP_STATE_IDLE;
|
||||||
|
pDev->Backup.Backup_Failure_Timeout = 60 * 60;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
return i;
|
return i;
|
||||||
} else {
|
} else {
|
||||||
return UINT16_MAX;
|
return UINT16_MAX;
|
||||||
@@ -606,8 +623,8 @@ void Routed_Device_Inc_Database_Revision(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Check to see if the current Device supports this service.
|
/** Check to see if the current Device supports this service.
|
||||||
* Presently checks for RD and DCC and only allows them if the current
|
* Presently allows ReinitializeDevice for routed virtual devices and keeps
|
||||||
* device is the gateway device.
|
* DeviceCommunicationControl restricted to the gateway device.
|
||||||
*
|
*
|
||||||
* @param service [in] The service being requested.
|
* @param service [in] The service being requested.
|
||||||
* @param service_argument [in] An optional argument (eg, service type).
|
* @param service_argument [in] An optional argument (eg, service type).
|
||||||
@@ -629,16 +646,9 @@ int Routed_Device_Service_Approval(
|
|||||||
(void)service_argument;
|
(void)service_argument;
|
||||||
switch (service) {
|
switch (service) {
|
||||||
case SERVICE_SUPPORTED_REINITIALIZE_DEVICE:
|
case SERVICE_SUPPORTED_REINITIALIZE_DEVICE:
|
||||||
/* If not the gateway device, we don't support RD */
|
/* RD is accepted for virtual devices. Device_Reinitialize()
|
||||||
if (iCurrent_Device_Idx > 0) {
|
handles state-specific support and returns service errors for
|
||||||
if (apdu_buff != NULL) {
|
virtual-device states that have gateway/system side effects. */
|
||||||
len = reject_encode_apdu(
|
|
||||||
apdu_buff, invoke_id,
|
|
||||||
REJECT_REASON_UNRECOGNIZED_SERVICE);
|
|
||||||
} else {
|
|
||||||
len = 1; /* Non-zero return */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case SERVICE_SUPPORTED_DEVICE_COMMUNICATION_CONTROL:
|
case SERVICE_SUPPORTED_DEVICE_COMMUNICATION_CONTROL:
|
||||||
/* If not the gateway device, we don't support DCC */
|
/* If not the gateway device, we don't support DCC */
|
||||||
|
|||||||
@@ -1364,7 +1364,7 @@ static const char *Device_Location_Default = BACNET_DEVICE_LOCATION_NAME;
|
|||||||
static const char *Device_Description_Default = BACNET_DEVICE_DESCRIPTION;
|
static const char *Device_Description_Default = BACNET_DEVICE_DESCRIPTION;
|
||||||
static uint32_t Database_Revision;
|
static uint32_t Database_Revision;
|
||||||
static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE;
|
static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE;
|
||||||
static BACNET_CHARACTER_STRING Reinit_Password;
|
static const char *Reinit_Password = "filister";
|
||||||
static write_property_function Device_Write_Property_Store_Callback;
|
static write_property_function Device_Write_Property_Store_Callback;
|
||||||
static list_element_function Device_Add_List_Element_Callback;
|
static list_element_function Device_Add_List_Element_Callback;
|
||||||
static list_element_function Device_Remove_List_Element_Callback;
|
static list_element_function Device_Remove_List_Element_Callback;
|
||||||
@@ -1448,7 +1448,7 @@ static BACNET_BACKUP_STATE Backup_State = BACKUP_STATE_IDLE;
|
|||||||
*/
|
*/
|
||||||
bool Device_Reinitialize_Password_Set(const char *password)
|
bool Device_Reinitialize_Password_Set(const char *password)
|
||||||
{
|
{
|
||||||
characterstring_init_ansi(&Reinit_Password, password);
|
Reinit_Password = password;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1480,7 +1480,7 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
|
|||||||
protection, the service request shall be denied if the parameter
|
protection, the service request shall be denied if the parameter
|
||||||
is absent or if the password is incorrect. For those devices that
|
is absent or if the password is incorrect. For those devices that
|
||||||
do not require a password, this parameter shall be ignored.*/
|
do not require a password, this parameter shall be ignored.*/
|
||||||
if (characterstring_length(&Reinit_Password) > 0) {
|
if (Reinit_Password && strlen(Reinit_Password) > 0) {
|
||||||
if (characterstring_encoding(&rd_data->password) == CHARACTER_UTF8) {
|
if (characterstring_encoding(&rd_data->password) == CHARACTER_UTF8) {
|
||||||
length = characterstring_utf8_length(&rd_data->password);
|
length = characterstring_utf8_length(&rd_data->password);
|
||||||
} else {
|
} else {
|
||||||
@@ -1489,7 +1489,8 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
|
|||||||
if (length > 20) {
|
if (length > 20) {
|
||||||
rd_data->error_class = ERROR_CLASS_SERVICES;
|
rd_data->error_class = ERROR_CLASS_SERVICES;
|
||||||
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
|
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
|
||||||
} else if (characterstring_same(&rd_data->password, &Reinit_Password)) {
|
} else if (characterstring_ansi_same(
|
||||||
|
&rd_data->password, Reinit_Password)) {
|
||||||
password_success = true;
|
password_success = true;
|
||||||
} else {
|
} else {
|
||||||
rd_data->error_class = ERROR_CLASS_SECURITY;
|
rd_data->error_class = ERROR_CLASS_SECURITY;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ include_directories(
|
|||||||
${TST_DIR}/ztest/include
|
${TST_DIR}/ztest/include
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME}
|
set(TEST_DEVICE_SOURCES
|
||||||
# File(s) under test
|
# File(s) under test
|
||||||
${SRC_DIR}/bacnet/basic/object/device.c
|
${SRC_DIR}/bacnet/basic/object/device.c
|
||||||
# Support files and stubs (pathname alphabetical)
|
# Support files and stubs (pathname alphabetical)
|
||||||
@@ -140,3 +140,65 @@ add_executable(${PROJECT_NAME}
|
|||||||
${ZTST_DIR}/ztest_mock.c
|
${ZTST_DIR}/ztest_mock.c
|
||||||
${ZTST_DIR}/ztest.c
|
${ZTST_DIR}/ztest.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
function(configure_device_test_target
|
||||||
|
target_name routing_enabled backup_restore_enabled)
|
||||||
|
if(routing_enabled)
|
||||||
|
target_sources(${target_name} PRIVATE
|
||||||
|
${SRC_DIR}/bacnet/basic/object/gateway/gw_device.c
|
||||||
|
)
|
||||||
|
target_compile_definitions(${target_name} PRIVATE
|
||||||
|
BAC_ROUTING
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if(backup_restore_enabled)
|
||||||
|
target_compile_definitions(${target_name} PRIVATE
|
||||||
|
BACNET_BACKUP_RESTORE
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Register a CTest build/run pair for one device test binary.
|
||||||
|
function(
|
||||||
|
add_device_ctest
|
||||||
|
target_name
|
||||||
|
test_name)
|
||||||
|
add_test(NAME build_${test_name} COMMAND ${CMAKE_COMMAND} --build "${CMAKE_BINARY_DIR}" --config $<CONFIG> --target
|
||||||
|
${target_name})
|
||||||
|
add_test(NAME test_${test_name} COMMAND $<TARGET_FILE:${target_name}>)
|
||||||
|
set_tests_properties(test_${test_name} PROPERTIES FIXTURES_REQUIRED fixture_${test_name})
|
||||||
|
set_tests_properties(build_${test_name} PROPERTIES FIXTURES_SETUP fixture_${test_name})
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME}
|
||||||
|
${TEST_DEVICE_SOURCES}
|
||||||
|
)
|
||||||
|
configure_device_test_target(${PROJECT_NAME} OFF OFF)
|
||||||
|
|
||||||
|
# Backup/Restore-only test binary.
|
||||||
|
add_executable(${PROJECT_NAME}_backup_restore ${TEST_DEVICE_SOURCES})
|
||||||
|
configure_device_test_target(
|
||||||
|
${PROJECT_NAME}_backup_restore
|
||||||
|
OFF
|
||||||
|
ON)
|
||||||
|
|
||||||
|
# BAC_ROUTING-only test binary.
|
||||||
|
add_executable(${PROJECT_NAME}_bac_routing ${TEST_DEVICE_SOURCES})
|
||||||
|
configure_device_test_target(
|
||||||
|
${PROJECT_NAME}_bac_routing
|
||||||
|
ON
|
||||||
|
OFF)
|
||||||
|
|
||||||
|
# BAC_ROUTING with Backup/Restore test binary.
|
||||||
|
add_executable(${PROJECT_NAME}_bac_routing_backup_restore ${TEST_DEVICE_SOURCES})
|
||||||
|
configure_device_test_target(
|
||||||
|
${PROJECT_NAME}_bac_routing_backup_restore
|
||||||
|
ON
|
||||||
|
ON)
|
||||||
|
|
||||||
|
# CTest pair for the Backup/Restore-only binary.
|
||||||
|
add_device_ctest(${PROJECT_NAME}_backup_restore ${basename}_backup_restore)
|
||||||
|
# CTest pair for the BAC_ROUTING-only binary.
|
||||||
|
add_device_ctest(${PROJECT_NAME}_bac_routing ${basename}_bac_routing)
|
||||||
|
# CTest pair for the BAC_ROUTING with Backup/Restore binary.
|
||||||
|
add_device_ctest(${PROJECT_NAME}_bac_routing_backup_restore ${basename}_bac_routing_backup_restore)
|
||||||
|
|||||||
@@ -91,6 +91,49 @@ static bool Write_Property_Proprietary(BACNET_WRITE_PROPERTY_DATA *data)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(BAC_ROUTING)
|
||||||
|
/**
|
||||||
|
* @brief Verify routed virtual devices still do not expose DCC.
|
||||||
|
*/
|
||||||
|
#if defined(CONFIG_ZTEST_NEW_API)
|
||||||
|
ZTEST(device_tests, test_Routed_Device_DCC_Remains_Blocked)
|
||||||
|
#else
|
||||||
|
static void test_Routed_Device_DCC_Remains_Blocked(void)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
BACNET_CHARACTER_STRING object_name = { 0 };
|
||||||
|
uint8_t apdu[MAX_APDU] = { 0 };
|
||||||
|
uint16_t device_index = 0;
|
||||||
|
int len = 0;
|
||||||
|
bool status = false;
|
||||||
|
|
||||||
|
Device_Init(NULL);
|
||||||
|
Routing_Device_Init(1000);
|
||||||
|
status = characterstring_init_ansi(&object_name, "Virtual Device");
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
device_index = Add_Routed_Device(1001, &object_name, "Virtual Device");
|
||||||
|
zassert_equal(device_index, 1, NULL);
|
||||||
|
|
||||||
|
status = Set_Routed_Device_Object_Index(0);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
len = Routed_Device_Service_Approval(
|
||||||
|
SERVICE_SUPPORTED_DEVICE_COMMUNICATION_CONTROL, 0, NULL, 0);
|
||||||
|
zassert_equal(len, 0, NULL);
|
||||||
|
|
||||||
|
status = Set_Routed_Device_Object_Index(device_index);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
len = Routed_Device_Service_Approval(
|
||||||
|
SERVICE_SUPPORTED_DEVICE_COMMUNICATION_CONTROL, 0, NULL, 0);
|
||||||
|
zassert_not_equal(len, 0, NULL);
|
||||||
|
|
||||||
|
len = Routed_Device_Service_Approval(
|
||||||
|
SERVICE_SUPPORTED_DEVICE_COMMUNICATION_CONTROL, 0, apdu, 1);
|
||||||
|
zassert_true(len > 0, NULL);
|
||||||
|
status = Set_Routed_Device_Object_Index(0);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief ReadProperty handler for this objects proprietary properties.
|
* @brief ReadProperty handler for this objects proprietary properties.
|
||||||
* For the given ReadProperty data, the application_data is loaded
|
* For the given ReadProperty data, the application_data is loaded
|
||||||
@@ -421,6 +464,190 @@ static void testDevice(void)
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(BAC_ROUTING)
|
||||||
|
static void test_Routed_Device_Reinitialize_Unsupported_State(
|
||||||
|
BACNET_REINITIALIZED_STATE state)
|
||||||
|
{
|
||||||
|
bool status = false;
|
||||||
|
BACNET_REINITIALIZE_DEVICE_DATA rd_data = { 0 };
|
||||||
|
|
||||||
|
Device_Reinitialize_State_Set(BACNET_REINIT_IDLE);
|
||||||
|
Device_Reinitialize_Password_Set(NULL);
|
||||||
|
rd_data.error_class = ERROR_CLASS_DEVICE;
|
||||||
|
rd_data.error_code = ERROR_CODE_SUCCESS;
|
||||||
|
rd_data.state = state;
|
||||||
|
characterstring_init_ansi(&rd_data.password, NULL);
|
||||||
|
|
||||||
|
status = Device_Reinitialize(&rd_data);
|
||||||
|
zassert_false(status, NULL);
|
||||||
|
zassert_equal(
|
||||||
|
rd_data.error_class, ERROR_CLASS_SERVICES, "error-class=%s",
|
||||||
|
bactext_error_class_name(rd_data.error_class));
|
||||||
|
zassert_equal(
|
||||||
|
rd_data.error_code, ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED,
|
||||||
|
"error-code=%s", bactext_error_code_name(rd_data.error_code));
|
||||||
|
zassert_equal(Device_Reinitialized_State(), BACNET_REINIT_IDLE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_ZTEST_NEW_API)
|
||||||
|
ZTEST(device_tests, test_Routed_Device_Reinitialize)
|
||||||
|
#else
|
||||||
|
static void test_Routed_Device_Reinitialize(void)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
bool status = false;
|
||||||
|
BACNET_CHARACTER_STRING object_name = { 0 };
|
||||||
|
BACNET_REINITIALIZE_DEVICE_DATA rd_data = { 0 };
|
||||||
|
|
||||||
|
Device_Init(NULL);
|
||||||
|
Routing_Device_Init(100);
|
||||||
|
characterstring_init_ansi(&object_name, "VirtualDevice");
|
||||||
|
zassert_equal(Add_Routed_Device(101, &object_name, "Virtual"), 1, NULL);
|
||||||
|
|
||||||
|
status = Set_Routed_Device_Object_Index(0);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
zassert_equal(
|
||||||
|
Routed_Device_Service_Approval(
|
||||||
|
SERVICE_SUPPORTED_REINITIALIZE_DEVICE, 0, NULL, 0),
|
||||||
|
0, NULL);
|
||||||
|
zassert_equal(
|
||||||
|
Routed_Device_Service_Approval(
|
||||||
|
SERVICE_SUPPORTED_DEVICE_COMMUNICATION_CONTROL, 0, NULL, 0),
|
||||||
|
0, NULL);
|
||||||
|
Device_Reinitialize_State_Set(BACNET_REINIT_IDLE);
|
||||||
|
Device_Reinitialize_Password_Set(NULL);
|
||||||
|
rd_data.error_class = ERROR_CLASS_DEVICE;
|
||||||
|
rd_data.error_code = ERROR_CODE_SUCCESS;
|
||||||
|
rd_data.state = BACNET_REINIT_COLDSTART;
|
||||||
|
characterstring_init_ansi(&rd_data.password, NULL);
|
||||||
|
status = Device_Reinitialize(&rd_data);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
zassert_equal(Device_Reinitialized_State(), BACNET_REINIT_COLDSTART, NULL);
|
||||||
|
|
||||||
|
status = Set_Routed_Device_Object_Index(1);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
zassert_equal(
|
||||||
|
Routed_Device_Service_Approval(
|
||||||
|
SERVICE_SUPPORTED_REINITIALIZE_DEVICE, 0, NULL, 0),
|
||||||
|
0, NULL);
|
||||||
|
zassert_not_equal(
|
||||||
|
Routed_Device_Service_Approval(
|
||||||
|
SERVICE_SUPPORTED_DEVICE_COMMUNICATION_CONTROL, 0, NULL, 0),
|
||||||
|
0, NULL);
|
||||||
|
test_Routed_Device_Reinitialize_Unsupported_State(BACNET_REINIT_COLDSTART);
|
||||||
|
test_Routed_Device_Reinitialize_Unsupported_State(BACNET_REINIT_WARMSTART);
|
||||||
|
test_Routed_Device_Reinitialize_Unsupported_State(
|
||||||
|
BACNET_REINIT_ACTIVATE_CHANGES);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(BAC_ROUTING) && defined(BACNET_BACKUP_RESTORE)
|
||||||
|
#if defined(CONFIG_ZTEST_NEW_API)
|
||||||
|
ZTEST(device_tests, test_Routed_Device_Backup_Restore_Independence)
|
||||||
|
#else
|
||||||
|
static void test_Routed_Device_Backup_Restore_Independence(void)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
bool status = false;
|
||||||
|
BACNET_CHARACTER_STRING object_name = { 0 };
|
||||||
|
BACNET_REINITIALIZE_DEVICE_DATA rd_data = { 0 };
|
||||||
|
|
||||||
|
Device_Init(NULL);
|
||||||
|
Routing_Device_Init(200);
|
||||||
|
characterstring_init_ansi(&object_name, "VirtualDevice1");
|
||||||
|
zassert_equal(Add_Routed_Device(201, &object_name, "Virtual1"), 1, NULL);
|
||||||
|
characterstring_init_ansi(&object_name, "VirtualDevice2");
|
||||||
|
zassert_equal(Add_Routed_Device(202, &object_name, "Virtual2"), 2, NULL);
|
||||||
|
|
||||||
|
rd_data.error_class = ERROR_CLASS_DEVICE;
|
||||||
|
rd_data.error_code = ERROR_CODE_SUCCESS;
|
||||||
|
rd_data.state = BACNET_REINIT_STARTRESTORE;
|
||||||
|
characterstring_init_ansi(&rd_data.password, NULL);
|
||||||
|
|
||||||
|
Set_Routed_Device_Object_Index(1);
|
||||||
|
Device_Reinitialize_Password_Set(NULL);
|
||||||
|
status = Device_Reinitialize(&rd_data);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
zassert_equal(
|
||||||
|
Device_Backup_And_Restore_State(), BACKUP_STATE_PERFORMING_A_RESTORE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
rd_data.error_class = ERROR_CLASS_DEVICE;
|
||||||
|
rd_data.error_code = ERROR_CODE_SUCCESS;
|
||||||
|
status = Device_Reinitialize(&rd_data);
|
||||||
|
zassert_false(status, NULL);
|
||||||
|
zassert_equal(rd_data.error_class, ERROR_CLASS_DEVICE, NULL);
|
||||||
|
zassert_equal(
|
||||||
|
rd_data.error_code, ERROR_CODE_CONFIGURATION_IN_PROGRESS, NULL);
|
||||||
|
|
||||||
|
Set_Routed_Device_Object_Index(0);
|
||||||
|
zassert_equal(Device_Backup_And_Restore_State(), BACKUP_STATE_IDLE, NULL);
|
||||||
|
Set_Routed_Device_Object_Index(2);
|
||||||
|
Device_Reinitialize_Password_Set(NULL);
|
||||||
|
zassert_equal(Device_Backup_And_Restore_State(), BACKUP_STATE_IDLE, NULL);
|
||||||
|
status = Device_Reinitialize(&rd_data);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
zassert_equal(
|
||||||
|
Device_Backup_And_Restore_State(), BACKUP_STATE_PERFORMING_A_RESTORE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
Set_Routed_Device_Object_Index(1);
|
||||||
|
rd_data.error_class = ERROR_CLASS_DEVICE;
|
||||||
|
rd_data.error_code = ERROR_CODE_SUCCESS;
|
||||||
|
rd_data.state = BACNET_REINIT_ABORTRESTORE;
|
||||||
|
status = Device_Reinitialize(&rd_data);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
zassert_equal(Device_Backup_And_Restore_State(), BACKUP_STATE_IDLE, NULL);
|
||||||
|
|
||||||
|
Set_Routed_Device_Object_Index(2);
|
||||||
|
zassert_equal(
|
||||||
|
Device_Backup_And_Restore_State(), BACKUP_STATE_PERFORMING_A_RESTORE,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_ZTEST_NEW_API)
|
||||||
|
ZTEST(device_tests, test_Routed_Device_Backup_Countdown_Per_Device)
|
||||||
|
#else
|
||||||
|
static void test_Routed_Device_Backup_Countdown_Per_Device(void)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
bool status = false;
|
||||||
|
BACNET_CHARACTER_STRING object_name = { 0 };
|
||||||
|
|
||||||
|
Device_Init(NULL);
|
||||||
|
Routing_Device_Init(300);
|
||||||
|
characterstring_init_ansi(&object_name, "VirtualDevice1");
|
||||||
|
zassert_equal(Add_Routed_Device(301, &object_name, "Virtual1"), 1, NULL);
|
||||||
|
characterstring_init_ansi(&object_name, "VirtualDevice2");
|
||||||
|
zassert_equal(Add_Routed_Device(302, &object_name, "Virtual2"), 2, NULL);
|
||||||
|
|
||||||
|
status = Set_Routed_Device_Object_Index(1);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
Device_Backup_Failure_Timeout_Set(1);
|
||||||
|
Device_Backup_And_Restore_State_Set(BACKUP_STATE_PERFORMING_A_BACKUP);
|
||||||
|
Device_Backup_Failure_Timeout_Restart();
|
||||||
|
|
||||||
|
status = Set_Routed_Device_Object_Index(2);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
zassert_equal(Device_Backup_And_Restore_State(), BACKUP_STATE_IDLE, NULL);
|
||||||
|
|
||||||
|
status = Set_Routed_Device_Object_Index(1);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
Device_Timer(500);
|
||||||
|
zassert_equal(
|
||||||
|
Device_Backup_And_Restore_State(), BACKUP_STATE_PERFORMING_A_BACKUP,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
Device_Timer(500);
|
||||||
|
zassert_equal(
|
||||||
|
Device_Backup_And_Restore_State(), BACKUP_STATE_BACKUP_FAILURE, NULL);
|
||||||
|
|
||||||
|
status = Set_Routed_Device_Object_Index(2);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
zassert_equal(Device_Backup_And_Restore_State(), BACKUP_STATE_IDLE, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
@@ -430,9 +657,25 @@ ZTEST_SUITE(device_tests, NULL, NULL, NULL, NULL, NULL);
|
|||||||
#else
|
#else
|
||||||
void test_main(void)
|
void test_main(void)
|
||||||
{
|
{
|
||||||
|
#if defined(BAC_ROUTING) && defined(BACNET_BACKUP_RESTORE)
|
||||||
|
ztest_test_suite(
|
||||||
|
device_tests, ztest_unit_test(testDevice),
|
||||||
|
ztest_unit_test(test_Device_Data_Sharing),
|
||||||
|
ztest_unit_test(test_Routed_Device_DCC_Remains_Blocked),
|
||||||
|
ztest_unit_test(test_Routed_Device_Reinitialize),
|
||||||
|
ztest_unit_test(test_Routed_Device_Backup_Restore_Independence),
|
||||||
|
ztest_unit_test(test_Routed_Device_Backup_Countdown_Per_Device));
|
||||||
|
#elif defined(BAC_ROUTING)
|
||||||
|
ztest_test_suite(
|
||||||
|
device_tests, ztest_unit_test(testDevice),
|
||||||
|
ztest_unit_test(test_Device_Data_Sharing),
|
||||||
|
ztest_unit_test(test_Routed_Device_DCC_Remains_Blocked),
|
||||||
|
ztest_unit_test(test_Routed_Device_Reinitialize));
|
||||||
|
#else
|
||||||
ztest_test_suite(
|
ztest_test_suite(
|
||||||
device_tests, ztest_unit_test(testDevice),
|
device_tests, ztest_unit_test(testDevice),
|
||||||
ztest_unit_test(test_Device_Data_Sharing));
|
ztest_unit_test(test_Device_Data_Sharing));
|
||||||
|
#endif
|
||||||
|
|
||||||
ztest_run_test_suite(device_tests);
|
ztest_run_test_suite(device_tests);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user