diff --git a/bacnet-stack/demo/handler/h_rd.c b/bacnet-stack/demo/handler/h_rd.c index 37d07c81..0d4ddfb4 100644 --- a/bacnet-stack/demo/handler/h_rd.c +++ b/bacnet-stack/demo/handler/h_rd.c @@ -38,7 +38,12 @@ #include "reject.h" #include "rd.h" -static char *Password = "Jesus"; +static reinitialize_device_function Reinitialize_Device_Function; +void handler_reinitialize_device_function_set( + reinitialize_device_function pFunction) +{ + Reinitialize_Device_Function = pFunction; +} void handler_reinitialize_device( uint8_t * service_request, @@ -46,8 +51,7 @@ void handler_reinitialize_device( BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data) { - BACNET_REINITIALIZED_STATE state; - BACNET_CHARACTER_STRING their_password; + BACNET_REINITIALIZE_DEVICE_DATA rd_data; int len = 0; int pdu_len = 0; BACNET_NPDU_DATA npdu_data; @@ -75,15 +79,17 @@ void handler_reinitialize_device( goto RD_ABORT; } /* decode the service request only */ - len = - rd_decode_service_request(service_request, service_len, &state, - &their_password); + len = rd_decode_service_request(service_request, service_len, + &rd_data.state, + &rd_data.password); #if PRINT_ENABLED - if (len > 0) + if (len > 0) { fprintf(stderr, "ReinitializeDevice: state=%u password=%s\n", - (unsigned) state, characterstring_value(&their_password)); - else + (unsigned) rd_data.state, + characterstring_value(&rd_data.password)); + } else { fprintf(stderr, "ReinitializeDevice: Unable to decode request!\n"); + } #endif /* bad decoding or something we didn't understand - send an abort */ if (len < 0) { @@ -97,7 +103,7 @@ void handler_reinitialize_device( goto RD_ABORT; } /* check the data from the request */ - if (state >= MAX_BACNET_REINITIALIZED_STATE) { + if (rd_data.state >= MAX_BACNET_REINITIALIZED_STATE) { len = reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, REJECT_REASON_UNDEFINED_ENUMERATION); @@ -106,7 +112,8 @@ void handler_reinitialize_device( "ReinitializeDevice: Sending Reject - undefined enumeration\n"); #endif } else { - if (characterstring_ansi_same(&their_password, Password)) { + if (Reinitialize_Device_Function && + Reinitialize_Device_Function(&rd_data)) { len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, @@ -114,15 +121,11 @@ void handler_reinitialize_device( #if PRINT_ENABLED fprintf(stderr, "ReinitializeDevice: Sending Simple Ack!\n"); #endif - /* FIXME: now you can reboot, restart, quit, or something clever */ - /* Note: you can use a mix of state and password to do specific stuff */ - /* Note: if you don't do something clever like actually restart, - you probably should clear any DCC status and timeouts */ } else { len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_REINITIALIZE_DEVICE, - ERROR_CLASS_SECURITY, ERROR_CODE_PASSWORD_FAILURE); + rd_data.error_class, rd_data.error_code); #if PRINT_ENABLED fprintf(stderr, "ReinitializeDevice: Sending Error - password failure.\n"); diff --git a/bacnet-stack/demo/object/device.c b/bacnet-stack/demo/object/device.c index a45715e5..ca8df75b 100644 --- a/bacnet-stack/demo/object/device.c +++ b/bacnet-stack/demo/object/device.c @@ -339,6 +339,44 @@ static void Device_Objects_Property_List( return; } +bool Device_Reinitialize( + BACNET_REINITIALIZE_DEVICE_DATA *rd_data) +{ + bool status = false; + + if (characterstring_ansi_same(&rd_data->password, "Jesus")) { + switch (rd_data->state) { + case REINITIALIZED_STATE_COLD_START: + break; + case REINITIALIZED_STATE_WARM_START: + break; + case REINITIALIZED_STATE_START_BACKUP: + break; + case REINITIALIZED_STATE_END_BACKUP: + break; + case REINITIALIZED_STATE_START_RESTORE: + break; + case REINITIALIZED_STATE_END_RESTORE: + break; + case REINITIALIZED_STATE_ABORT_RESTORE: + break; + default: + break; + } + /* Note: you could use a mix of state + and password to multiple things */ + /* note: you probably want to restart *after* the + simple ack has been sent from the return handler + so just set a flag from here */ + status = true; + } else { + rd_data->error_class = ERROR_CLASS_SECURITY; + rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE; + } + + return status; +} + /* These three arrays are used by the ReadPropertyMultiple handler */ static const int Device_Properties_Required[] = { PROP_OBJECT_IDENTIFIER, @@ -1354,6 +1392,7 @@ void Device_Init( handler_rpm_function_set(Device_Objects_Read_Property); handler_rpm_list_set(Device_Objects_Property_List); handler_write_property_function_set(Device_Objects_Write_Property); + handler_reinitialize_device_function_set(Device_Reinitialize); pObject = &Object_Table[0]; while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) { diff --git a/bacnet-stack/include/handlers.h b/bacnet-stack/include/handlers.h index f6da3ecb..e429b6a5 100644 --- a/bacnet-stack/include/handlers.h +++ b/bacnet-stack/include/handlers.h @@ -31,6 +31,7 @@ #include "bacdef.h" #include "apdu.h" #include "bacapp.h" +#include "rd.h" #include "rp.h" #include "rpm.h" #include "wp.h" @@ -135,6 +136,8 @@ extern "C" { uint16_t service_len, BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data); + void handler_reinitialize_device_function_set( + reinitialize_device_function pFunction); void handler_device_communication_control( uint8_t * service_request, diff --git a/bacnet-stack/include/rd.h b/bacnet-stack/include/rd.h index 9aaecc57..eb893f93 100644 --- a/bacnet-stack/include/rd.h +++ b/bacnet-stack/include/rd.h @@ -37,6 +37,18 @@ #include #include +typedef struct BACnet_Reinitialize_Device_Data { + BACNET_REINITIALIZED_STATE state; + BACNET_CHARACTER_STRING password; + BACNET_ERROR_CLASS error_class; + BACNET_ERROR_CODE error_code; +} BACNET_REINITIALIZE_DEVICE_DATA; + +typedef bool ( + *reinitialize_device_function) ( + BACNET_REINITIALIZE_DEVICE_DATA *rd_data); + + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */