Ignore ReinitializeDevice and DeviceCommunicationControl service password (#518)

* Fix device object ReinitializeDevice service handling examples of no-password in the device. Add unit testing of device object ReinitializeDevice service.  Add API for setting ReinitializeDevice device object password.

* Fix DeviceCommunicationControl service handling example of no-password in the device.

---------

Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
Steve Karg
2023-10-18 21:32:44 -05:00
committed by GitHub
parent e143066b29
commit 0b5474d36e
12 changed files with 576 additions and 173 deletions
+51 -32
View File
@@ -74,8 +74,8 @@ static object_functions_t My_Object_Table[] = {
Device_Property_Lists, DeviceGetRRInfo, NULL /* Iterator */, Device_Property_Lists, DeviceGetRRInfo, NULL /* Iterator */,
NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */,
NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */,
NULL /* Remove_List_Element */, NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */,
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, NULL /* Timer */ },
#if (BACNET_PROTOCOL_REVISION >= 17) #if (BACNET_PROTOCOL_REVISION >= 17)
{ OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count, { OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count,
Network_Port_Index_To_Instance, Network_Port_Valid_Instance, Network_Port_Index_To_Instance, Network_Port_Valid_Instance,
@@ -93,7 +93,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */ }, NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
#if (BACNET_PROTOCOL_REVISION >= 14) #if (BACNET_PROTOCOL_REVISION >= 14)
{ OBJECT_LIGHTING_OUTPUT, Lighting_Output_Init, Lighting_Output_Count, { OBJECT_LIGHTING_OUTPUT, Lighting_Output_Init, Lighting_Output_Count,
Lighting_Output_Index_To_Instance, Lighting_Output_Valid_Instance, Lighting_Output_Index_To_Instance, Lighting_Output_Valid_Instance,
@@ -102,14 +102,14 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Lighting_Output_Create, Lighting_Output_Delete, Lighting_Output_Timer}, Lighting_Output_Create, Lighting_Output_Delete, Lighting_Output_Timer },
{ OBJECT_CHANNEL, Channel_Init, Channel_Count, Channel_Index_To_Instance, { OBJECT_CHANNEL, Channel_Init, Channel_Count, Channel_Index_To_Instance,
Channel_Valid_Instance, Channel_Object_Name, Channel_Read_Property, Channel_Valid_Instance, Channel_Object_Name, Channel_Read_Property,
Channel_Write_Property, Channel_Property_Lists, Channel_Write_Property, Channel_Property_Lists,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Channel_Create, Channel_Delete, NULL /* Timer */ }, Channel_Create, Channel_Delete, NULL /* Timer */ },
#endif #endif
#if (BACNET_PROTOCOL_REVISION >= 24) #if (BACNET_PROTOCOL_REVISION >= 24)
{ OBJECT_COLOR, Color_Init, Color_Count, Color_Index_To_Instance, { OBJECT_COLOR, Color_Init, Color_Count, Color_Index_To_Instance,
@@ -118,7 +118,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */,
NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Color_Create, Color_Delete, Color_Timer}, Color_Create, Color_Delete, Color_Timer },
{ OBJECT_COLOR_TEMPERATURE, Color_Temperature_Init, Color_Temperature_Count, { OBJECT_COLOR_TEMPERATURE, Color_Temperature_Init, Color_Temperature_Count,
Color_Temperature_Index_To_Instance, Color_Temperature_Valid_Instance, Color_Temperature_Index_To_Instance, Color_Temperature_Valid_Instance,
Color_Temperature_Object_Name, Color_Temperature_Read_Property, Color_Temperature_Object_Name, Color_Temperature_Read_Property,
@@ -127,7 +127,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Color_Temperature_Create, Color_Temperature_Delete, Color_Temperature_Create, Color_Temperature_Delete,
Color_Temperature_Timer}, Color_Temperature_Timer },
#endif #endif
{ MAX_BACNET_OBJECT_TYPE, NULL /* Init */, NULL /* Count */, { MAX_BACNET_OBJECT_TYPE, NULL /* Init */, NULL /* Count */,
NULL /* Index_To_Instance */, NULL /* Valid_Instance */, NULL /* Index_To_Instance */, NULL /* Valid_Instance */,
@@ -136,7 +136,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ } NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }
}; };
/** Glue function to let the Device object, when called by a handler, /** Glue function to let the Device object, when called by a handler,
@@ -329,6 +329,24 @@ static uint32_t Database_Revision = 0;
static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE; static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE;
static const char *Reinit_Password = "filister"; static const char *Reinit_Password = "filister";
/**
* @brief Sets the ReinitializeDevice password
*
* The password shall be a null terminated C string of up to
* 20 ASCII characters for those devices that require the password.
*
* For those devices that do not require a password, set to NULL or
* point to a zero length C string (null terminated).
*
* @param the ReinitializeDevice password; can be NULL or empty string
*/
bool Device_Reinitialize_Password_Set(const char *password)
{
Reinit_Password = password;
return true;
}
/** Commands a Device re-initialization, to a given state. /** Commands a Device re-initialization, to a given state.
* The request's password must match for the operation to succeed. * The request's password must match for the operation to succeed.
* This implementation provides a framework, but doesn't * This implementation provides a framework, but doesn't
@@ -345,6 +363,7 @@ static const char *Reinit_Password = "filister";
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
{ {
bool status = false; bool status = false;
bool password_success = false;
/* 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
@@ -352,12 +371,21 @@ 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(&rd_data->password) > 20) { if (Reinit_Password && strlen(Reinit_Password) > 0) {
rd_data->error_class = ERROR_CLASS_SERVICES; if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; rd_data->error_class = ERROR_CLASS_SERVICES;
} else if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) { rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
/* Note: you could use a mix of state and password to } else if (characterstring_ansi_same(
accomplish multiple things before restarting */ &rd_data->password, Reinit_Password)) {
password_success = true;
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
} else {
password_success = true;
}
if (password_success) {
switch (rd_data->state) { switch (rd_data->state) {
case BACNET_REINIT_COLDSTART: case BACNET_REINIT_COLDSTART:
case BACNET_REINIT_WARMSTART: case BACNET_REINIT_WARMSTART:
@@ -387,9 +415,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
break; break;
} }
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
} }
return status; return status;
@@ -1103,9 +1128,8 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
case PROP_OBJECT_LIST: case PROP_OBJECT_LIST:
count = Device_Object_List_Count(); count = Device_Object_List_Count();
apdu_len = bacnet_array_encode(rpdata->object_instance, apdu_len = bacnet_array_encode(rpdata->object_instance,
rpdata->array_index, rpdata->array_index, Device_Object_List_Element_Encode, count,
Device_Object_List_Element_Encode, apdu, apdu_max);
count, apdu, apdu_max);
if (apdu_len == BACNET_STATUS_ABORT) { if (apdu_len == BACNET_STATUS_ABORT) {
rpdata->error_code = rpdata->error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED; ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
@@ -1635,8 +1659,8 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
} }
#endif #endif
if (wp_data->object_property == PROP_OBJECT_NAME) { if (wp_data->object_property == PROP_OBJECT_NAME) {
status = Device_Write_Property_Object_Name(wp_data, status = Device_Write_Property_Object_Name(
pObject->Object_Write_Property); wp_data, pObject->Object_Write_Property);
} else { } else {
status = pObject->Object_Write_Property(wp_data); status = pObject->Object_Write_Property(wp_data);
} }
@@ -1663,8 +1687,7 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
* @return The length of the apdu encoded or #BACNET_STATUS_ERROR or * @return The length of the apdu encoded or #BACNET_STATUS_ERROR or
* #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT. * #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT.
*/ */
int Device_Add_List_Element( int Device_Add_List_Element(BACNET_LIST_ELEMENT_DATA *list_element)
BACNET_LIST_ELEMENT_DATA * list_element)
{ {
int status = BACNET_STATUS_ERROR; int status = BACNET_STATUS_ERROR;
struct object_functions *pObject = NULL; struct object_functions *pObject = NULL;
@@ -1698,8 +1721,7 @@ int Device_Add_List_Element(
* @return The length of the apdu encoded or #BACNET_STATUS_ERROR or * @return The length of the apdu encoded or #BACNET_STATUS_ERROR or
* #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT. * #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT.
*/ */
int Device_Remove_List_Element( int Device_Remove_List_Element(BACNET_LIST_ELEMENT_DATA *list_element)
BACNET_LIST_ELEMENT_DATA * list_element)
{ {
int status = BACNET_STATUS_ERROR; int status = BACNET_STATUS_ERROR;
struct object_functions *pObject = NULL; struct object_functions *pObject = NULL;
@@ -1805,8 +1827,7 @@ void Device_COV_Clear(BACNET_OBJECT_TYPE object_type, uint32_t object_instance)
* @param data - CreateObject data, including error codes if failures * @param data - CreateObject data, including error codes if failures
* @return true if object has been created * @return true if object has been created
*/ */
bool Device_Create_Object( bool Device_Create_Object(BACNET_CREATE_OBJECT_DATA *data)
BACNET_CREATE_OBJECT_DATA *data)
{ {
bool status = false; bool status = false;
struct object_functions *pObject = NULL; struct object_functions *pObject = NULL;
@@ -1865,8 +1886,7 @@ bool Device_Create_Object(
* @param data - DeleteObject data, including error codes if failures * @param data - DeleteObject data, including error codes if failures
* @return true if object has been deleted * @return true if object has been deleted
*/ */
bool Device_Delete_Object( bool Device_Delete_Object(BACNET_DELETE_OBJECT_DATA *data)
BACNET_DELETE_OBJECT_DATA *data)
{ {
bool status = false; bool status = false;
struct object_functions *pObject = NULL; struct object_functions *pObject = NULL;
@@ -1997,8 +2017,7 @@ bool DeviceGetRRInfo(BACNET_READ_RANGE_DATA *pRequest, /* Info on the request */
* @brief Updates all the object timers with elapsed milliseconds * @brief Updates all the object timers with elapsed milliseconds
* @param milliseconds - number of milliseconds elapsed * @param milliseconds - number of milliseconds elapsed
*/ */
void Device_Timer( void Device_Timer(uint16_t milliseconds)
uint16_t milliseconds)
{ {
struct object_functions *pObject; struct object_functions *pObject;
unsigned count = 0; unsigned count = 0;
+47 -24
View File
@@ -67,8 +67,8 @@ static object_functions_t My_Object_Table[] = {
Device_Property_Lists, DeviceGetRRInfo, NULL /* Iterator */, Device_Property_Lists, DeviceGetRRInfo, NULL /* Iterator */,
NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */,
NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */,
NULL /* Remove_List_Element */, NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */,
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, NULL /* Timer */ },
#if (BACNET_PROTOCOL_REVISION >= 17) #if (BACNET_PROTOCOL_REVISION >= 17)
{ OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count, { OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count,
Network_Port_Index_To_Instance, Network_Port_Valid_Instance, Network_Port_Index_To_Instance, Network_Port_Valid_Instance,
@@ -95,7 +95,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Binary_Output_Create, Binary_Output_Delete, NULL /* Timer */}, Binary_Output_Create, Binary_Output_Delete, NULL /* Timer */ },
{ MAX_BACNET_OBJECT_TYPE, NULL /* Init */, NULL /* Count */, { MAX_BACNET_OBJECT_TYPE, NULL /* Init */, NULL /* Count */,
NULL /* Index_To_Instance */, NULL /* Valid_Instance */, NULL /* Index_To_Instance */, NULL /* Valid_Instance */,
NULL /* Object_Name */, NULL /* Read_Property */, NULL /* Object_Name */, NULL /* Read_Property */,
@@ -103,7 +103,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */} NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }
}; };
/** Glue function to let the Device object, when called by a handler, /** Glue function to let the Device object, when called by a handler,
@@ -296,6 +296,24 @@ static uint32_t Database_Revision = 0;
static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE; static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE;
static const char *Reinit_Password = "raspberry"; static const char *Reinit_Password = "raspberry";
/**
* @brief Sets the ReinitializeDevice password
*
* The password shall be a null terminated C string of up to
* 20 ASCII characters for those devices that require the password.
*
* For those devices that do not require a password, set to NULL or
* point to a zero length C string (null terminated).
*
* @param the ReinitializeDevice password; can be NULL or empty string
*/
bool Device_Reinitialize_Password_Set(const char *password)
{
Reinit_Password = password;
return true;
}
/** Commands a Device re-initialization, to a given state. /** Commands a Device re-initialization, to a given state.
* The request's password must match for the operation to succeed. * The request's password must match for the operation to succeed.
* This implementation provides a framework, but doesn't * This implementation provides a framework, but doesn't
@@ -312,6 +330,7 @@ static const char *Reinit_Password = "raspberry";
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
{ {
bool status = false; bool status = false;
bool password_success = false;
/* 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
@@ -319,12 +338,21 @@ 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(&rd_data->password) > 20) { if (Reinit_Password && strlen(Reinit_Password) > 0) {
rd_data->error_class = ERROR_CLASS_SERVICES; if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; rd_data->error_class = ERROR_CLASS_SERVICES;
} else if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) { rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
/* Note: you could use a mix of state and password to } else if (characterstring_ansi_same(
accomplish multiple things before restarting */ &rd_data->password, Reinit_Password)) {
password_success = true;
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
} else {
password_success = true;
}
if (password_success) {
switch (rd_data->state) { switch (rd_data->state) {
case BACNET_REINIT_COLDSTART: case BACNET_REINIT_COLDSTART:
case BACNET_REINIT_WARMSTART: case BACNET_REINIT_WARMSTART:
@@ -1070,9 +1098,8 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
case PROP_OBJECT_LIST: case PROP_OBJECT_LIST:
count = Device_Object_List_Count(); count = Device_Object_List_Count();
apdu_len = bacnet_array_encode(rpdata->object_instance, apdu_len = bacnet_array_encode(rpdata->object_instance,
rpdata->array_index, rpdata->array_index, Device_Object_List_Element_Encode, count,
Device_Object_List_Element_Encode, apdu, apdu_max);
count, apdu, apdu_max);
if (apdu_len == BACNET_STATUS_ABORT) { if (apdu_len == BACNET_STATUS_ABORT) {
rpdata->error_code = rpdata->error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED; ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
@@ -1230,7 +1257,7 @@ int Device_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
} else { } else {
rpdata->error_class = ERROR_CLASS_OBJECT; rpdata->error_class = ERROR_CLASS_OBJECT;
rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT; rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT;
} }
} else { } else {
rpdata->error_class = ERROR_CLASS_OBJECT; rpdata->error_class = ERROR_CLASS_OBJECT;
rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT; rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT;
@@ -1602,8 +1629,8 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
} }
#endif #endif
if (wp_data->object_property == PROP_OBJECT_NAME) { if (wp_data->object_property == PROP_OBJECT_NAME) {
status = Device_Write_Property_Object_Name(wp_data, status = Device_Write_Property_Object_Name(
pObject->Object_Write_Property); wp_data, pObject->Object_Write_Property);
} else { } else {
status = pObject->Object_Write_Property(wp_data); status = pObject->Object_Write_Property(wp_data);
} }
@@ -1630,8 +1657,7 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
* @return The length of the apdu encoded or #BACNET_STATUS_ERROR or * @return The length of the apdu encoded or #BACNET_STATUS_ERROR or
* #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT. * #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT.
*/ */
int Device_Add_List_Element( int Device_Add_List_Element(BACNET_LIST_ELEMENT_DATA *list_element)
BACNET_LIST_ELEMENT_DATA * list_element)
{ {
int status = BACNET_STATUS_ERROR; int status = BACNET_STATUS_ERROR;
struct object_functions *pObject = NULL; struct object_functions *pObject = NULL;
@@ -1665,8 +1691,7 @@ int Device_Add_List_Element(
* @return The length of the apdu encoded or #BACNET_STATUS_ERROR or * @return The length of the apdu encoded or #BACNET_STATUS_ERROR or
* #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT. * #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT.
*/ */
int Device_Remove_List_Element( int Device_Remove_List_Element(BACNET_LIST_ELEMENT_DATA *list_element)
BACNET_LIST_ELEMENT_DATA * list_element)
{ {
int status = BACNET_STATUS_ERROR; int status = BACNET_STATUS_ERROR;
struct object_functions *pObject = NULL; struct object_functions *pObject = NULL;
@@ -1772,8 +1797,7 @@ void Device_COV_Clear(BACNET_OBJECT_TYPE object_type, uint32_t object_instance)
* @param data - CreateObject data, including error codes if failures * @param data - CreateObject data, including error codes if failures
* @return true if object has been created * @return true if object has been created
*/ */
bool Device_Create_Object( bool Device_Create_Object(BACNET_CREATE_OBJECT_DATA *data)
BACNET_CREATE_OBJECT_DATA *data)
{ {
bool status = false; bool status = false;
struct object_functions *pObject = NULL; struct object_functions *pObject = NULL;
@@ -1832,8 +1856,7 @@ bool Device_Create_Object(
* @param data - DeleteObject data, including error codes if failures * @param data - DeleteObject data, including error codes if failures
* @return true if object has been deleted * @return true if object has been deleted
*/ */
bool Device_Delete_Object( bool Device_Delete_Object(BACNET_DELETE_OBJECT_DATA *data)
BACNET_DELETE_OBJECT_DATA *data)
{ {
bool status = false; bool status = false;
struct object_functions *pObject = NULL; struct object_functions *pObject = NULL;
+65 -21
View File
@@ -67,12 +67,11 @@ static struct my_object_functions {
read_property_function Object_Read_Property; read_property_function Object_Read_Property;
write_property_function Object_Write_Property; write_property_function Object_Write_Property;
rpm_property_lists_function Object_RPM_List; rpm_property_lists_function Object_RPM_List;
} Object_Table[] = { } Object_Table[] = { { OBJECT_DEVICE, NULL, /* don't init - recursive! */
{ OBJECT_DEVICE, NULL, /* don't init - recursive! */ Device_Count, Device_Index_To_Instance,
Device_Count, Device_Index_To_Instance, Device_Valid_Object_Instance_Number,
Device_Valid_Object_Instance_Number, Device_Object_Name, Device_Read_Property_Local,
Device_Object_Name, Device_Read_Property_Local, Device_Write_Property_Local, Device_Property_Lists },
Device_Write_Property_Local, Device_Property_Lists },
{ OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count, { OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count,
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance, Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance,
Analog_Input_Object_Name, Analog_Input_Read_Property, NULL, Analog_Input_Object_Name, Analog_Input_Read_Property, NULL,
@@ -159,8 +158,7 @@ static int Read_Property_Common(
} }
apdu = rpdata->application_data; apdu = rpdata->application_data;
if (property_list_common(rpdata->object_property)) { if (property_list_common(rpdata->object_property)) {
apdu_len = property_list_common_encode(rpdata, apdu_len = property_list_common_encode(rpdata, Object_Instance_Number);
Object_Instance_Number);
} else if (rpdata->object_property == PROP_OBJECT_NAME) { } else if (rpdata->object_property == PROP_OBJECT_NAME) {
/* only array properties can have array options */ /* only array properties can have array options */
if (rpdata->array_index != BACNET_ARRAY_ALL) { if (rpdata->array_index != BACNET_ARRAY_ALL) {
@@ -180,9 +178,8 @@ static int Read_Property_Common(
} else if (rpdata->object_property == PROP_PROPERTY_LIST) { } else if (rpdata->object_property == PROP_PROPERTY_LIST) {
Device_Objects_Property_List( Device_Objects_Property_List(
rpdata->object_type, rpdata->object_instance, &property_list); rpdata->object_type, rpdata->object_instance, &property_list);
apdu_len = property_list_encode(rpdata, apdu_len = property_list_encode(rpdata, property_list.Required.pList,
property_list.Required.pList, property_list.Optional.pList, property_list.Optional.pList, property_list.Proprietary.pList);
property_list.Proprietary.pList);
#endif #endif
} else if (pObject->Object_Read_Property) { } else if (pObject->Object_Read_Property) {
apdu_len = pObject->Object_Read_Property(rpdata); apdu_len = pObject->Object_Read_Property(rpdata);
@@ -332,12 +329,64 @@ bool Device_Set_Object_Name(BACNET_CHARACTER_STRING *object_name)
return status; return status;
} }
/**
* @brief Sets the ReinitializeDevice password
*
* The password shall be a null terminated C string of up to
* 20 ASCII characters for those devices that require the password.
*
* For those devices that do not require a password, set to NULL or
* point to a zero length C string (null terminated).
*
* @param the ReinitializeDevice password; can be NULL or empty string
*/
bool Device_Reinitialize_Password_Set(const char *password)
{
Reinit_Password = password;
return true;
}
/**
* @brief Commands a Device re-initialization, to a given state.
* The request's password must match for the operation to succeed.
* This implementation provides a framework, but doesn't
* actually *DO* anything.
* @note You could use a mix of states and passwords to multiple outcomes.
* @note You probably want to restart *after* the simple ack has been sent
* from the return handler, so just set a local flag here.
* @ingroup ObjIntf
*
* @param rd_data [in,out] The information from the RD request.
* On failure, the error class and code will be set.
* @return True if succeeds (password is correct), else False.
*/
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
{ {
bool status = false; bool status = false;
bool password_success = false;
/* Note: you could use a mix of state and password to multiple things */ /* From 16.4.1.1.2 Password
if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) { This optional parameter shall be a CharacterString of up to
20 characters. For those devices that require the password as a
protection, the service request shall be denied if the parameter
is absent or if the password is incorrect. For those devices that
do not require a password, this parameter shall be ignored.*/
if (Reinit_Password && strlen(Reinit_Password) > 0) {
if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same(
&rd_data->password, Reinit_Password)) {
password_success = true;
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
} else {
password_success = true;
}
if (password_success) {
switch (rd_data->state) { switch (rd_data->state) {
case BACNET_REINIT_COLDSTART: case BACNET_REINIT_COLDSTART:
case BACNET_REINIT_WARMSTART: case BACNET_REINIT_WARMSTART:
@@ -367,9 +416,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
break; break;
} }
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
} }
return status; return status;
@@ -705,9 +751,8 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
case PROP_OBJECT_LIST: case PROP_OBJECT_LIST:
count = Device_Object_List_Count(); count = Device_Object_List_Count();
apdu_len = bacnet_array_encode(rpdata->object_instance, apdu_len = bacnet_array_encode(rpdata->object_instance,
rpdata->array_index, rpdata->array_index, Device_Object_List_Element_Encode, count,
Device_Object_List_Element_Encode, apdu, apdu_max);
count, apdu, apdu_max);
if (apdu_len == BACNET_STATUS_ABORT) { if (apdu_len == BACNET_STATUS_ABORT) {
rpdata->error_code = rpdata->error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED; ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
@@ -745,8 +790,7 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
encode_application_unsigned(&apdu[0], dlmstp_max_master()); encode_application_unsigned(&apdu[0], dlmstp_max_master());
break; break;
case 9600: case 9600:
apdu_len = apdu_len = encode_application_unsigned(&apdu[0], rs485_baud_rate());
encode_application_unsigned(&apdu[0], rs485_baud_rate());
break; break;
default: default:
rpdata->error_class = ERROR_CLASS_PROPERTY; rpdata->error_class = ERROR_CLASS_PROPERTY;
+62 -16
View File
@@ -67,12 +67,11 @@ static struct my_object_functions {
read_property_function Object_Read_Property; read_property_function Object_Read_Property;
write_property_function Object_Write_Property; write_property_function Object_Write_Property;
rpm_property_lists_function Object_RPM_List; rpm_property_lists_function Object_RPM_List;
} Object_Table[] = { } Object_Table[] = { { OBJECT_DEVICE, NULL, /* don't init - recursive! */
{ OBJECT_DEVICE, NULL, /* don't init - recursive! */ Device_Count, Device_Index_To_Instance,
Device_Count, Device_Index_To_Instance, Device_Valid_Object_Instance_Number,
Device_Valid_Object_Instance_Number, Device_Object_Name, Device_Read_Property_Local,
Device_Object_Name, Device_Read_Property_Local, Device_Write_Property_Local, Device_Property_Lists },
Device_Write_Property_Local, Device_Property_Lists },
{ OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count, { OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count,
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance, Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance,
Analog_Input_Object_Name, Analog_Input_Read_Property, NULL, Analog_Input_Object_Name, Analog_Input_Read_Property, NULL,
@@ -161,8 +160,7 @@ int Device_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
#if (BACNET_PROTOCOL_REVISION >= 14) #if (BACNET_PROTOCOL_REVISION >= 14)
if ((int)rpdata->object_property == PROP_PROPERTY_LIST) { if ((int)rpdata->object_property == PROP_PROPERTY_LIST) {
Device_Objects_Property_List(rpdata->object_type, Device_Objects_Property_List(rpdata->object_type,
rpdata->object_instance, rpdata->object_instance, &property_list);
&property_list);
apdu_len = property_list_encode(rpdata, apdu_len = property_list_encode(rpdata,
property_list.Required.pList, property_list.Required.pList,
property_list.Optional.pList, property_list.Optional.pList,
@@ -306,12 +304,64 @@ bool Device_Object_Name(
return status; return status;
} }
/**
* @brief Sets the ReinitializeDevice password
*
* The password shall be a null terminated C string of up to
* 20 ASCII characters for those devices that require the password.
*
* For those devices that do not require a password, set to NULL or
* point to a zero length C string (null terminated).
*
* @param the ReinitializeDevice password; can be NULL or empty string
*/
bool Device_Reinitialize_Password_Set(const char *password)
{
Reinit_Password = password;
return true;
}
/**
* @brief Commands a Device re-initialization, to a given state.
* The request's password must match for the operation to succeed.
* This implementation provides a framework, but doesn't
* actually *DO* anything.
* @note You could use a mix of states and passwords to multiple outcomes.
* @note You probably want to restart *after* the simple ack has been sent
* from the return handler, so just set a local flag here.
* @ingroup ObjIntf
*
* @param rd_data [in,out] The information from the RD request.
* On failure, the error class and code will be set.
* @return True if succeeds (password is correct), else False.
*/
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
{ {
bool status = false; bool status = false;
bool password_success = false;
/* Note: you could use a mix of state and password to multiple things */ /* From 16.4.1.1.2 Password
if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) { This optional parameter shall be a CharacterString of up to
20 characters. For those devices that require the password as a
protection, the service request shall be denied if the parameter
is absent or if the password is incorrect. For those devices that
do not require a password, this parameter shall be ignored.*/
if (Reinit_Password && strlen(Reinit_Password) > 0) {
if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same(
&rd_data->password, Reinit_Password)) {
password_success = true;
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
} else {
password_success = true;
}
if (password_success) {
switch (rd_data->state) { switch (rd_data->state) {
case BACNET_REINIT_COLDSTART: case BACNET_REINIT_COLDSTART:
case BACNET_REINIT_WARMSTART: case BACNET_REINIT_WARMSTART:
@@ -341,9 +391,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
break; break;
} }
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
} }
return status; return status;
@@ -695,9 +742,8 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
case PROP_OBJECT_LIST: case PROP_OBJECT_LIST:
count = Device_Object_List_Count(); count = Device_Object_List_Count();
apdu_len = bacnet_array_encode(rpdata->object_instance, apdu_len = bacnet_array_encode(rpdata->object_instance,
rpdata->array_index, rpdata->array_index, Device_Object_List_Element_Encode, count,
Device_Object_List_Element_Encode, apdu, apdu_max);
count, apdu, apdu_max);
if (apdu_len == BACNET_STATUS_ABORT) { if (apdu_len == BACNET_STATUS_ABORT) {
rpdata->error_code = rpdata->error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED; ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
+54 -6
View File
@@ -52,14 +52,65 @@ static uint32_t Object_Instance_Number = 12345;
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL; static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
static uint8_t Database_Revision; static uint8_t Database_Revision;
BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE; BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE;
static char Reinit_Password[16] = "filister"; static const char *Reinit_Password = "filister";
/**
* @brief Sets the ReinitializeDevice password
*
* The password shall be a null terminated C string of up to
* 20 ASCII characters for those devices that require the password.
*
* For those devices that do not require a password, set to NULL or
* point to a zero length C string (null terminated).
*
* @param the ReinitializeDevice password; can be NULL or empty string
*/
bool Device_Reinitialize_Password_Set(const char *password)
{
Reinit_Password = password;
return true;
}
/** Commands a Device re-initialization, to a given state.
* The request's password must match for the operation to succeed.
* This implementation provides a framework, but doesn't
* actually *DO* anything.
* @note You could use a mix of states and passwords to multiple outcomes.
* @note You probably want to restart *after* the simple ack has been sent
* from the return handler, so just set a local flag here.
* @ingroup ObjIntf
*
* @param rd_data [in,out] The information from the RD request.
* On failure, the error class and code will be set.
* @return True if succeeds (password is correct), else False.
*/
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
{ {
bool status = false; bool status = false;
bool password_success = false;
/* Note: you could use a mix of state and password to multiple things */ /* From 16.4.1.1.2 Password
if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) { This optional parameter shall be a CharacterString of up to
20 characters. For those devices that require the password as a
protection, the service request shall be denied if the parameter
is absent or if the password is incorrect. For those devices that
do not require a password, this parameter shall be ignored.*/
if (Reinit_Password && strlen(Reinit_Password) > 0) {
if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same(
&rd_data->password, Reinit_Password)) {
password_success = true;
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
} else {
password_success = true;
}
if (password_success) {
switch (rd_data->state) { switch (rd_data->state) {
case BACNET_REINIT_COLDSTART: case BACNET_REINIT_COLDSTART:
case BACNET_REINIT_WARMSTART: case BACNET_REINIT_WARMSTART:
@@ -89,9 +140,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
break; break;
} }
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
} }
return status; return status;
+54 -5
View File
@@ -271,12 +271,64 @@ uint32_t Device_Index_To_Instance(unsigned index)
return Object_Instance_Number; return Object_Instance_Number;
} }
/**
* @brief Sets the ReinitializeDevice password
*
* The password shall be a null terminated C string of up to
* 20 ASCII characters for those devices that require the password.
*
* For those devices that do not require a password, set to NULL or
* point to a zero length C string (null terminated).
*
* @param the ReinitializeDevice password; can be NULL or empty string
*/
bool Device_Reinitialize_Password_Set(const char *password)
{
Reinit_Password = password;
return true;
}
/**
* @brief Commands a Device re-initialization, to a given state.
* The request's password must match for the operation to succeed.
* This implementation provides a framework, but doesn't
* actually *DO* anything.
* @note You could use a mix of states and passwords to multiple outcomes.
* @note You probably want to restart *after* the simple ack has been sent
* from the return handler, so just set a local flag here.
* @ingroup ObjIntf
*
* @param rd_data [in,out] The information from the RD request.
* On failure, the error class and code will be set.
* @return True if succeeds (password is correct), else False.
*/
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
{ {
bool status = false; bool status = false;
bool password_success = false;
/* Note: you could use a mix of state and password to multiple things */ /* From 16.4.1.1.2 Password
if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) { This optional parameter shall be a CharacterString of up to
20 characters. For those devices that require the password as a
protection, the service request shall be denied if the parameter
is absent or if the password is incorrect. For those devices that
do not require a password, this parameter shall be ignored.*/
if (Reinit_Password && strlen(Reinit_Password) > 0) {
if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same(
&rd_data->password, Reinit_Password)) {
password_success = true;
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
} else {
password_success = true;
}
if (password_success) {
switch (rd_data->state) { switch (rd_data->state) {
case BACNET_REINIT_COLDSTART: case BACNET_REINIT_COLDSTART:
case BACNET_REINIT_WARMSTART: case BACNET_REINIT_WARMSTART:
@@ -306,9 +358,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
break; break;
} }
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
} }
return status; return status;
+54 -5
View File
@@ -342,12 +342,64 @@ bool Device_Set_Object_Name(BACNET_CHARACTER_STRING *object_name)
return status; return status;
} }
/**
* @brief Sets the ReinitializeDevice password
*
* The password shall be a null terminated C string of up to
* 20 ASCII characters for those devices that require the password.
*
* For those devices that do not require a password, set to NULL or
* point to a zero length C string (null terminated).
*
* @param the ReinitializeDevice password; can be NULL or empty string
*/
bool Device_Reinitialize_Password_Set(const char *password)
{
Reinit_Password = password;
return true;
}
/**
* @brief Commands a Device re-initialization, to a given state.
* The request's password must match for the operation to succeed.
* This implementation provides a framework, but doesn't
* actually *DO* anything.
* @note You could use a mix of states and passwords to multiple outcomes.
* @note You probably want to restart *after* the simple ack has been sent
* from the return handler, so just set a local flag here.
* @ingroup ObjIntf
*
* @param rd_data [in,out] The information from the RD request.
* On failure, the error class and code will be set.
* @return True if succeeds (password is correct), else False.
*/
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
{ {
bool status = false; bool status = false;
bool password_success = false;
/* Note: you could use a mix of state and password to multiple things */ /* From 16.4.1.1.2 Password
if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) { This optional parameter shall be a CharacterString of up to
20 characters. For those devices that require the password as a
protection, the service request shall be denied if the parameter
is absent or if the password is incorrect. For those devices that
do not require a password, this parameter shall be ignored.*/
if (Reinit_Password && strlen(Reinit_Password) > 0) {
if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same(
&rd_data->password, Reinit_Password)) {
password_success = true;
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
} else {
password_success = true;
}
if (password_success) {
switch (rd_data->state) { switch (rd_data->state) {
case BACNET_REINIT_COLDSTART: case BACNET_REINIT_COLDSTART:
case BACNET_REINIT_WARMSTART: case BACNET_REINIT_WARMSTART:
@@ -379,9 +431,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
break; break;
} }
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
} }
return status; return status;
+54 -5
View File
@@ -336,12 +336,64 @@ bool Device_Set_Object_Name(BACNET_CHARACTER_STRING *object_name)
return status; return status;
} }
/**
* @brief Sets the ReinitializeDevice password
*
* The password shall be a null terminated C string of up to
* 20 ASCII characters for those devices that require the password.
*
* For those devices that do not require a password, set to NULL or
* point to a zero length C string (null terminated).
*
* @param the ReinitializeDevice password; can be NULL or empty string
*/
bool Device_Reinitialize_Password_Set(const char *password)
{
Reinit_Password = password;
return true;
}
/**
* @brief Commands a Device re-initialization, to a given state.
* The request's password must match for the operation to succeed.
* This implementation provides a framework, but doesn't
* actually *DO* anything.
* @note You could use a mix of states and passwords to multiple outcomes.
* @note You probably want to restart *after* the simple ack has been sent
* from the return handler, so just set a local flag here.
* @ingroup ObjIntf
*
* @param rd_data [in,out] The information from the RD request.
* On failure, the error class and code will be set.
* @return True if succeeds (password is correct), else False.
*/
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
{ {
bool status = false; bool status = false;
bool password_success = false;
/* Note: you could use a mix of state and password to multiple things */ /* From 16.4.1.1.2 Password
if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) { This optional parameter shall be a CharacterString of up to
20 characters. For those devices that require the password as a
protection, the service request shall be denied if the parameter
is absent or if the password is incorrect. For those devices that
do not require a password, this parameter shall be ignored.*/
if (Reinit_Password && strlen(Reinit_Password) > 0) {
if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same(
&rd_data->password, Reinit_Password)) {
password_success = true;
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
} else {
password_success = true;
}
if (password_success) {
switch (rd_data->state) { switch (rd_data->state) {
case BACNET_REINIT_COLDSTART: case BACNET_REINIT_COLDSTART:
case BACNET_REINIT_WARMSTART: case BACNET_REINIT_WARMSTART:
@@ -373,9 +425,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
break; break;
} }
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
} }
return status; return status;
+66 -47
View File
@@ -98,8 +98,8 @@ static object_functions_t My_Object_Table[] = {
Device_Property_Lists, DeviceGetRRInfo, NULL /* Iterator */, Device_Property_Lists, DeviceGetRRInfo, NULL /* Iterator */,
NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */,
NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */,
NULL /* Remove_List_Element */, NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */,
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, NULL /* Timer */ },
#if (BACNET_PROTOCOL_REVISION >= 17) #if (BACNET_PROTOCOL_REVISION >= 17)
{ OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count, { OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count,
Network_Port_Index_To_Instance, Network_Port_Valid_Instance, Network_Port_Index_To_Instance, Network_Port_Valid_Instance,
@@ -108,7 +108,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */}, NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
#endif #endif
{ OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count, { OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count,
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance, Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance,
@@ -118,7 +118,7 @@ static object_functions_t My_Object_Table[] = {
Analog_Input_Encode_Value_List, Analog_Input_Change_Of_Value, Analog_Input_Encode_Value_List, Analog_Input_Change_Of_Value,
Analog_Input_Change_Of_Value_Clear, Analog_Input_Intrinsic_Reporting, Analog_Input_Change_Of_Value_Clear, Analog_Input_Intrinsic_Reporting,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */}, NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
{ OBJECT_ANALOG_OUTPUT, Analog_Output_Init, Analog_Output_Count, { OBJECT_ANALOG_OUTPUT, Analog_Output_Init, Analog_Output_Count,
Analog_Output_Index_To_Instance, Analog_Output_Valid_Instance, Analog_Output_Index_To_Instance, Analog_Output_Valid_Instance,
Analog_Output_Object_Name, Analog_Output_Read_Property, Analog_Output_Object_Name, Analog_Output_Read_Property,
@@ -126,7 +126,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Analog_Output_Create, Analog_Output_Delete, NULL /* Timer */}, Analog_Output_Create, Analog_Output_Delete, NULL /* Timer */ },
{ OBJECT_ANALOG_VALUE, Analog_Value_Init, Analog_Value_Count, { OBJECT_ANALOG_VALUE, Analog_Value_Init, Analog_Value_Count,
Analog_Value_Index_To_Instance, Analog_Value_Valid_Instance, Analog_Value_Index_To_Instance, Analog_Value_Valid_Instance,
Analog_Value_Object_Name, Analog_Value_Read_Property, Analog_Value_Object_Name, Analog_Value_Read_Property,
@@ -152,7 +152,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Binary_Output_Create, Binary_Output_Delete, NULL /* Timer */}, Binary_Output_Create, Binary_Output_Delete, NULL /* Timer */ },
{ OBJECT_BINARY_VALUE, Binary_Value_Init, Binary_Value_Count, { OBJECT_BINARY_VALUE, Binary_Value_Init, Binary_Value_Count,
Binary_Value_Index_To_Instance, Binary_Value_Valid_Instance, Binary_Value_Index_To_Instance, Binary_Value_Valid_Instance,
Binary_Value_Object_Name, Binary_Value_Read_Property, Binary_Value_Object_Name, Binary_Value_Read_Property,
@@ -171,8 +171,8 @@ static object_functions_t My_Object_Table[] = {
CharacterString_Value_Change_Of_Value, CharacterString_Value_Change_Of_Value,
CharacterString_Value_Change_Of_Value_Clear, CharacterString_Value_Change_Of_Value_Clear,
NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */,
NULL /* Remove_List_Element */, NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */,
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, NULL /* Timer */ },
{ OBJECT_COMMAND, Command_Init, Command_Count, Command_Index_To_Instance, { OBJECT_COMMAND, Command_Init, Command_Count, Command_Index_To_Instance,
Command_Valid_Instance, Command_Object_Name, Command_Read_Property, Command_Valid_Instance, Command_Object_Name, Command_Read_Property,
Command_Write_Property, Command_Property_Lists, Command_Write_Property, Command_Property_Lists,
@@ -197,8 +197,8 @@ static object_functions_t My_Object_Table[] = {
NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */,
NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
Notification_Class_Add_List_Element, Notification_Class_Add_List_Element,
Notification_Class_Remove_List_Element, Notification_Class_Remove_List_Element, NULL /* Create */,
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, NULL /* Delete */, NULL /* Timer */ },
#endif #endif
{ OBJECT_LIFE_SAFETY_POINT, Life_Safety_Point_Init, Life_Safety_Point_Count, { 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_Index_To_Instance, Life_Safety_Point_Valid_Instance,
@@ -207,7 +207,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */}, NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
{ OBJECT_LOAD_CONTROL, Load_Control_Init, Load_Control_Count, { OBJECT_LOAD_CONTROL, Load_Control_Init, Load_Control_Count,
Load_Control_Index_To_Instance, Load_Control_Valid_Instance, Load_Control_Index_To_Instance, Load_Control_Valid_Instance,
Load_Control_Object_Name, Load_Control_Read_Property, Load_Control_Object_Name, Load_Control_Read_Property,
@@ -215,7 +215,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */}, NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
{ OBJECT_MULTI_STATE_INPUT, Multistate_Input_Init, Multistate_Input_Count, { OBJECT_MULTI_STATE_INPUT, Multistate_Input_Init, Multistate_Input_Count,
Multistate_Input_Index_To_Instance, Multistate_Input_Valid_Instance, Multistate_Input_Index_To_Instance, Multistate_Input_Valid_Instance,
Multistate_Input_Object_Name, Multistate_Input_Read_Property, Multistate_Input_Object_Name, Multistate_Input_Read_Property,
@@ -223,7 +223,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */}, NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
{ OBJECT_MULTI_STATE_OUTPUT, Multistate_Output_Init, { OBJECT_MULTI_STATE_OUTPUT, Multistate_Output_Init,
Multistate_Output_Count, Multistate_Output_Index_To_Instance, Multistate_Output_Count, Multistate_Output_Index_To_Instance,
Multistate_Output_Valid_Instance, Multistate_Output_Object_Name, Multistate_Output_Valid_Instance, Multistate_Output_Object_Name,
@@ -232,7 +232,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */,
NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Multistate_Output_Create, Multistate_Output_Delete, NULL /* Timer */}, Multistate_Output_Create, Multistate_Output_Delete, NULL /* Timer */ },
{ OBJECT_MULTI_STATE_VALUE, Multistate_Value_Init, Multistate_Value_Count, { OBJECT_MULTI_STATE_VALUE, Multistate_Value_Init, Multistate_Value_Count,
Multistate_Value_Index_To_Instance, Multistate_Value_Valid_Instance, Multistate_Value_Index_To_Instance, Multistate_Value_Valid_Instance,
Multistate_Value_Object_Name, Multistate_Value_Read_Property, Multistate_Value_Object_Name, Multistate_Value_Read_Property,
@@ -241,7 +241,7 @@ static object_functions_t My_Object_Table[] = {
Multistate_Value_Encode_Value_List, Multistate_Value_Change_Of_Value, Multistate_Value_Encode_Value_List, Multistate_Value_Change_Of_Value,
Multistate_Value_Change_Of_Value_Clear, NULL /* Intrinsic Reporting */, Multistate_Value_Change_Of_Value_Clear, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */}, NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
{ OBJECT_TRENDLOG, Trend_Log_Init, Trend_Log_Count, { OBJECT_TRENDLOG, Trend_Log_Init, Trend_Log_Count,
Trend_Log_Index_To_Instance, Trend_Log_Valid_Instance, Trend_Log_Index_To_Instance, Trend_Log_Valid_Instance,
Trend_Log_Object_Name, Trend_Log_Read_Property, Trend_Log_Object_Name, Trend_Log_Read_Property,
@@ -249,7 +249,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */,
NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */}, NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
#if (BACNET_PROTOCOL_REVISION >= 14) #if (BACNET_PROTOCOL_REVISION >= 14)
{ OBJECT_LIGHTING_OUTPUT, Lighting_Output_Init, Lighting_Output_Count, { OBJECT_LIGHTING_OUTPUT, Lighting_Output_Init, Lighting_Output_Count,
Lighting_Output_Index_To_Instance, Lighting_Output_Valid_Instance, Lighting_Output_Index_To_Instance, Lighting_Output_Valid_Instance,
@@ -258,7 +258,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Lighting_Output_Create, Lighting_Output_Delete, Lighting_Output_Timer}, Lighting_Output_Create, Lighting_Output_Delete, Lighting_Output_Timer },
{ OBJECT_CHANNEL, Channel_Init, Channel_Count, Channel_Index_To_Instance, { OBJECT_CHANNEL, Channel_Init, Channel_Count, Channel_Index_To_Instance,
Channel_Valid_Instance, Channel_Object_Name, Channel_Read_Property, Channel_Valid_Instance, Channel_Object_Name, Channel_Read_Property,
Channel_Write_Property, Channel_Property_Lists, Channel_Write_Property, Channel_Property_Lists,
@@ -274,7 +274,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */,
NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Color_Create, Color_Delete, Color_Timer}, Color_Create, Color_Delete, Color_Timer },
{ OBJECT_COLOR_TEMPERATURE, Color_Temperature_Init, Color_Temperature_Count, { OBJECT_COLOR_TEMPERATURE, Color_Temperature_Init, Color_Temperature_Count,
Color_Temperature_Index_To_Instance, Color_Temperature_Valid_Instance, Color_Temperature_Index_To_Instance, Color_Temperature_Valid_Instance,
Color_Temperature_Object_Name, Color_Temperature_Read_Property, Color_Temperature_Object_Name, Color_Temperature_Read_Property,
@@ -283,7 +283,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Color_Temperature_Create, Color_Temperature_Delete, Color_Temperature_Create, Color_Temperature_Delete,
Color_Temperature_Timer}, Color_Temperature_Timer },
#endif #endif
#if defined(BACFILE) #if defined(BACFILE)
{ OBJECT_FILE, bacfile_init, bacfile_count, bacfile_index_to_instance, { OBJECT_FILE, bacfile_init, bacfile_count, bacfile_index_to_instance,
@@ -292,7 +292,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
bacfile_create, bacfile_delete, NULL /* Timer */}, bacfile_create, bacfile_delete, NULL /* Timer */ },
#endif #endif
{ OBJECT_OCTETSTRING_VALUE, OctetString_Value_Init, OctetString_Value_Count, { OBJECT_OCTETSTRING_VALUE, OctetString_Value_Init, OctetString_Value_Count,
OctetString_Value_Index_To_Instance, OctetString_Value_Valid_Instance, OctetString_Value_Index_To_Instance, OctetString_Value_Valid_Instance,
@@ -318,8 +318,8 @@ static object_functions_t My_Object_Table[] = {
Schedule_Property_Lists, NULL /* ReadRangeInfo */, NULL /* Iterator */, Schedule_Property_Lists, NULL /* ReadRangeInfo */, NULL /* Iterator */,
NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */,
NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */,
NULL /* Remove_List_Element */, NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */,
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, NULL /* Timer */ },
{ OBJECT_ACCUMULATOR, Accumulator_Init, Accumulator_Count, { OBJECT_ACCUMULATOR, Accumulator_Init, Accumulator_Count,
Accumulator_Index_To_Instance, Accumulator_Valid_Instance, Accumulator_Index_To_Instance, Accumulator_Valid_Instance,
Accumulator_Object_Name, Accumulator_Read_Property, Accumulator_Object_Name, Accumulator_Read_Property,
@@ -327,7 +327,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */}, NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
{ MAX_BACNET_OBJECT_TYPE, NULL /* Init */, NULL /* Count */, { MAX_BACNET_OBJECT_TYPE, NULL /* Init */, NULL /* Count */,
NULL /* Index_To_Instance */, NULL /* Valid_Instance */, NULL /* Index_To_Instance */, NULL /* Valid_Instance */,
NULL /* Object_Name */, NULL /* Read_Property */, NULL /* Object_Name */, NULL /* Read_Property */,
@@ -528,6 +528,24 @@ static uint32_t Database_Revision = 0;
static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE; static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE;
static const char *Reinit_Password = "filister"; static const char *Reinit_Password = "filister";
/**
* @brief Sets the ReinitializeDevice password
*
* The password shall be a null terminated C string of up to
* 20 ASCII characters for those devices that require the password.
*
* For those devices that do not require a password, set to NULL or
* point to a zero length C string (null terminated).
*
* @param the ReinitializeDevice password; can be NULL or empty string
*/
bool Device_Reinitialize_Password_Set(const char *password)
{
Reinit_Password = password;
return true;
}
/** Commands a Device re-initialization, to a given state. /** Commands a Device re-initialization, to a given state.
* The request's password must match for the operation to succeed. * The request's password must match for the operation to succeed.
* This implementation provides a framework, but doesn't * This implementation provides a framework, but doesn't
@@ -544,6 +562,7 @@ static const char *Reinit_Password = "filister";
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
{ {
bool status = false; bool status = false;
bool password_success = false;
/* 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
@@ -551,12 +570,21 @@ 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(&rd_data->password) > 20) { if (Reinit_Password && strlen(Reinit_Password) > 0) {
rd_data->error_class = ERROR_CLASS_SERVICES; if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; rd_data->error_class = ERROR_CLASS_SERVICES;
} else if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) { rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
/* Note: you could use a mix of state and password to } else if (characterstring_ansi_same(
accomplish multiple things before restarting */ &rd_data->password, Reinit_Password)) {
password_success = true;
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
} else {
password_success = true;
}
if (password_success) {
switch (rd_data->state) { switch (rd_data->state) {
case BACNET_REINIT_COLDSTART: case BACNET_REINIT_COLDSTART:
case BACNET_REINIT_WARMSTART: case BACNET_REINIT_WARMSTART:
@@ -586,9 +614,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
break; break;
} }
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
} }
return status; return status;
@@ -1306,9 +1331,8 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
case PROP_OBJECT_LIST: case PROP_OBJECT_LIST:
count = Device_Object_List_Count(); count = Device_Object_List_Count();
apdu_len = bacnet_array_encode(rpdata->object_instance, apdu_len = bacnet_array_encode(rpdata->object_instance,
rpdata->array_index, rpdata->array_index, Device_Object_List_Element_Encode, count,
Device_Object_List_Element_Encode, apdu, apdu_max);
count, apdu, apdu_max);
if (apdu_len == BACNET_STATUS_ABORT) { if (apdu_len == BACNET_STATUS_ABORT) {
rpdata->error_code = rpdata->error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED; ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
@@ -1838,8 +1862,8 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
} }
#endif #endif
if (wp_data->object_property == PROP_OBJECT_NAME) { if (wp_data->object_property == PROP_OBJECT_NAME) {
status = Device_Write_Property_Object_Name(wp_data, status = Device_Write_Property_Object_Name(
pObject->Object_Write_Property); wp_data, pObject->Object_Write_Property);
} else { } else {
status = pObject->Object_Write_Property(wp_data); status = pObject->Object_Write_Property(wp_data);
} }
@@ -1866,8 +1890,7 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
* @return The length of the apdu encoded or #BACNET_STATUS_ERROR or * @return The length of the apdu encoded or #BACNET_STATUS_ERROR or
* #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT. * #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT.
*/ */
int Device_Add_List_Element( int Device_Add_List_Element(BACNET_LIST_ELEMENT_DATA *list_element)
BACNET_LIST_ELEMENT_DATA * list_element)
{ {
int status = BACNET_STATUS_ERROR; int status = BACNET_STATUS_ERROR;
struct object_functions *pObject = NULL; struct object_functions *pObject = NULL;
@@ -1901,8 +1924,7 @@ int Device_Add_List_Element(
* @return The length of the apdu encoded or #BACNET_STATUS_ERROR or * @return The length of the apdu encoded or #BACNET_STATUS_ERROR or
* #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT. * #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT.
*/ */
int Device_Remove_List_Element( int Device_Remove_List_Element(BACNET_LIST_ELEMENT_DATA *list_element)
BACNET_LIST_ELEMENT_DATA * list_element)
{ {
int status = BACNET_STATUS_ERROR; int status = BACNET_STATUS_ERROR;
struct object_functions *pObject = NULL; struct object_functions *pObject = NULL;
@@ -2008,8 +2030,7 @@ void Device_COV_Clear(BACNET_OBJECT_TYPE object_type, uint32_t object_instance)
* @param data - CreateObject data, including error codes if failures * @param data - CreateObject data, including error codes if failures
* @return true if object has been created * @return true if object has been created
*/ */
bool Device_Create_Object( bool Device_Create_Object(BACNET_CREATE_OBJECT_DATA *data)
BACNET_CREATE_OBJECT_DATA *data)
{ {
bool status = false; bool status = false;
struct object_functions *pObject = NULL; struct object_functions *pObject = NULL;
@@ -2068,8 +2089,7 @@ bool Device_Create_Object(
* @param data - DeleteObject data, including error codes if failures * @param data - DeleteObject data, including error codes if failures
* @return true if object has been deleted * @return true if object has been deleted
*/ */
bool Device_Delete_Object( bool Device_Delete_Object(BACNET_DELETE_OBJECT_DATA *data)
BACNET_DELETE_OBJECT_DATA *data)
{ {
bool status = false; bool status = false;
struct object_functions *pObject = NULL; struct object_functions *pObject = NULL;
@@ -2236,8 +2256,7 @@ bool DeviceGetRRInfo(BACNET_READ_RANGE_DATA *pRequest, /* Info on the request */
* @brief Updates all the object timers with elapsed milliseconds * @brief Updates all the object timers with elapsed milliseconds
* @param milliseconds - number of milliseconds elapsed * @param milliseconds - number of milliseconds elapsed
*/ */
void Device_Timer( void Device_Timer(uint16_t milliseconds)
uint16_t milliseconds)
{ {
struct object_functions *pObject; struct object_functions *pObject;
unsigned count = 0; unsigned count = 0;
+3
View File
@@ -254,6 +254,9 @@ extern "C" {
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
BACNET_REINITIALIZED_STATE Device_Reinitialized_State( BACNET_REINITIALIZED_STATE Device_Reinitialized_State(
void); void);
BACNET_STACK_EXPORT
bool Device_Reinitialize_Password_Set(
const char *password);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
rr_info_function Device_Objects_RR_Info( rr_info_function Device_Objects_RR_Info(
+2 -2
View File
@@ -173,8 +173,8 @@ void handler_device_communication_control(uint8_t *service_request,
if (len > 0) if (len > 0)
goto DCC_ABORT; goto DCC_ABORT;
#endif #endif
if ((My_Password[0] == '\0') ||
if (characterstring_ansi_same(&password, My_Password)) { characterstring_ansi_same(&password, My_Password)) {
len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, service_data->invoke_id,
SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL); SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL);
+62 -8
View File
@@ -41,7 +41,8 @@ static void test_Device_Data_Sharing(void)
rpdata.application_data = &apdu[0]; rpdata.application_data = &apdu[0];
rpdata.application_data_len = sizeof(apdu); rpdata.application_data_len = sizeof(apdu);
rpdata.object_type = OBJECT_DEVICE; rpdata.object_type = OBJECT_DEVICE;
rpdata.object_instance = Device_Index_To_Instance(0);; rpdata.object_instance = Device_Index_To_Instance(0);
;
Device_Property_Lists(&pRequired, &pOptional, &pProprietary); Device_Property_Lists(&pRequired, &pOptional, &pProprietary);
while ((*pRequired) != -1) { while ((*pRequired) != -1) {
rpdata.object_property = *pRequired; rpdata.object_property = *pRequired;
@@ -49,7 +50,7 @@ static void test_Device_Data_Sharing(void)
len = Device_Read_Property(&rpdata); len = Device_Read_Property(&rpdata);
zassert_not_equal(len, BACNET_STATUS_ERROR, zassert_not_equal(len, BACNET_STATUS_ERROR,
"property '%s': failed to ReadProperty!\n", "property '%s': failed to ReadProperty!\n",
bactext_property_name(rpdata.object_property)); bactext_property_name(rpdata.object_property));
if (len > 0) { if (len > 0) {
test_len = bacapp_decode_application_data(rpdata.application_data, test_len = bacapp_decode_application_data(rpdata.application_data,
(uint8_t)rpdata.application_data_len, &value); (uint8_t)rpdata.application_data_len, &value);
@@ -85,7 +86,7 @@ static void test_Device_Data_Sharing(void)
len = Device_Read_Property(&rpdata); len = Device_Read_Property(&rpdata);
zassert_not_equal(len, BACNET_STATUS_ERROR, zassert_not_equal(len, BACNET_STATUS_ERROR,
"property '%s': failed to ReadProperty!\n", "property '%s': failed to ReadProperty!\n",
bactext_property_name(rpdata.object_property)); bactext_property_name(rpdata.object_property));
if (len > 0) { if (len > 0) {
test_len = bacapp_decode_application_data(rpdata.application_data, test_len = bacapp_decode_application_data(rpdata.application_data,
(uint8_t)rpdata.application_data_len, &value); (uint8_t)rpdata.application_data_len, &value);
@@ -127,6 +128,7 @@ static void testDevice(void)
{ {
bool status = false; bool status = false;
const char *name = "Patricia"; const char *name = "Patricia";
BACNET_REINITIALIZE_DEVICE_DATA rd_data;
status = Device_Set_Object_Instance_Number(0); status = Device_Set_Object_Instance_Number(0);
zassert_equal(Device_Object_Instance_Number(), 0, NULL); zassert_equal(Device_Object_Instance_Number(), 0, NULL);
@@ -151,22 +153,74 @@ static void testDevice(void)
Device_Set_Model_Name(name, strlen(name)); Device_Set_Model_Name(name, strlen(name));
zassert_equal(strcmp(Device_Model_Name(), name), 0, NULL); zassert_equal(strcmp(Device_Model_Name(), name), 0, NULL);
/* Reinitialize with no device password */
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_Password_Set(NULL);
status = Device_Reinitialize(&rd_data);
zassert_true(status, NULL);
zassert_equal(rd_data.error_class, ERROR_CLASS_DEVICE, "error-class=%s",
bactext_error_class_name(rd_data.error_class));
zassert_equal(rd_data.error_code, ERROR_CODE_SUCCESS, "error-code=%s",
bactext_error_code_name(rd_data.error_code));
/* Reinitialize with device valid password, service no password */
status = Device_Reinitialize_Password_Set("valid");
zassert_true(status, NULL);
status = characterstring_init_ansi(&rd_data.password, NULL);
zassert_true(status, NULL);
status = Device_Reinitialize(&rd_data);
zassert_false(status, NULL);
zassert_equal(rd_data.error_class, ERROR_CLASS_SECURITY, "error-class=%s",
bactext_error_class_name(rd_data.error_class));
zassert_equal(rd_data.error_code, ERROR_CODE_PASSWORD_FAILURE,
"error-code=%s", bactext_error_code_name(rd_data.error_code));
/* Reinitialize with device valid password, service invalid password */
status = characterstring_init_ansi(&rd_data.password, "invalid");
zassert_true(status, NULL);
status = Device_Reinitialize(&rd_data);
zassert_false(status, NULL);
zassert_equal(rd_data.error_class, ERROR_CLASS_SECURITY, "error-class=%s",
bactext_error_class_name(rd_data.error_class));
zassert_equal(rd_data.error_code, ERROR_CODE_PASSWORD_FAILURE,
"error-code=%s", bactext_error_code_name(rd_data.error_code));
/* Reinitialize with device valid password, service valid password */
characterstring_init_ansi(&rd_data.password, "valid");
status = Device_Reinitialize(&rd_data);
zassert_true(status, NULL);
/* Reinitialize with device valid password, service too long password */
characterstring_init_ansi(&rd_data.password, "abcdefghijklmnopqrstuvwxyz");
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_PARAMETER_OUT_OF_RANGE,
"error-code=%s", bactext_error_code_name(rd_data.error_code));
/* Reinitialize with device no password, unsupported state */
status = Device_Reinitialize_Password_Set(NULL);
zassert_true(status, NULL);
rd_data.state = BACNET_REINIT_MAX;
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_PARAMETER_OUT_OF_RANGE,
"error-code=%s", bactext_error_code_name(rd_data.error_code));
return; return;
} }
/** /**
* @} * @}
*/ */
#if defined(CONFIG_ZTEST_NEW_API) #if defined(CONFIG_ZTEST_NEW_API)
ZTEST_SUITE(device_tests, NULL, NULL, NULL, NULL, NULL); ZTEST_SUITE(device_tests, NULL, NULL, NULL, NULL, NULL);
#else #else
void test_main(void) void test_main(void)
{ {
ztest_test_suite(device_tests, ztest_test_suite(device_tests, ztest_unit_test(testDevice),
ztest_unit_test(testDevice), ztest_unit_test(test_Device_Data_Sharing));
ztest_unit_test(test_Device_Data_Sharing)
);
ztest_run_test_suite(device_tests); ztest_run_test_suite(device_tests);
} }