diff --git a/rclc_parameter/include/rclc_parameter/rclc_parameter.h b/rclc_parameter/include/rclc_parameter/rclc_parameter.h index c187e659..23618308 100644 --- a/rclc_parameter/include/rclc_parameter/rclc_parameter.h +++ b/rclc_parameter/include/rclc_parameter/rclc_parameter.h @@ -71,14 +71,17 @@ typedef struct rcl_interfaces__msg__ParameterEvent ParameterEvent; #define PARAMETER_MODIFICATION_REJECTED 4001 #define PARAMETER_TYPE_MISMATCH 4002 #define UNSUPORTED_ON_LOW_MEM 4003 +#define DISABLE_ON_CALLBACK 40004 /** - * Parameter event callback + * Parameter event callback. * This callback will allow the user to allow or reject the following events: * - Parameter value change: Internal and external parameter set on existing parameters. * - Parameter creation: External parameter set on unexisting parameter if `allow_undeclared_parameters` is set. * - Parameter delete: External parameter delete on existing parameter. * + * Parameters modifications are disabled while this callback is executed. + * *
* Attribute | Adherence * ------------------ | ------------- @@ -91,7 +94,9 @@ typedef struct rcl_interfaces__msg__ParameterEvent ParameterEvent; * \param[in] new_value Parameter new value, `NULL` for parameter removal request. * \return `true` to accept the parameter event. The operation will be rejected on `false` return. */ -typedef bool (* ModifiedParameter_Callback)(const Parameter * param, const Parameter * new_value); +typedef bool (* ModifiedParameter_Callback)( + const Parameter * old_param, + const Parameter * new_param); // Allowed RCLC parameter types typedef enum rclc_parameter_type_t @@ -142,6 +147,7 @@ typedef struct rclc_parameter_server_t ParameterEvent event_list; ModifiedParameter_Callback on_modification; + bool on_callback; bool notify_changed_over_dds; bool allow_undeclared_parameters; @@ -230,10 +236,11 @@ RCLC_PARAMETER_PUBLIC rcl_ret_t rclc_executor_add_parameter_server( rclc_executor_t * executor, rclc_parameter_server_t * parameter_server, - ModifiedParameter_Callback ModifiedParameter_Callback); + ModifiedParameter_Callback on_modification); /** * Adds a RCLC parameter to a server + * This method is disabled on user callback execution. * *
* Attribute | Adherence @@ -256,7 +263,8 @@ rclc_add_parameter( rclc_parameter_type_t type); /** - * Deletes a RCLC parameter from the server + * Deletes a RCLC parameter from the server. + * This method is disabled on user callback execution. * *
* Attribute | Adherence @@ -277,7 +285,8 @@ rclc_delete_parameter( const char * parameter_name); /** - * Sets the value of an existing a RCLC bool parameter + * Sets the value of an existing a RCLC bool parameter. + * This method is disabled on user callback execution. * *
* Attribute | Adherence @@ -300,7 +309,8 @@ rclc_parameter_set_bool( bool value); /** - * Sets the value of an existing a RCLC integer parameter + * Sets the value of an existing a RCLC integer parameter. + * This method is disabled on user callback execution. * *
* Attribute | Adherence @@ -323,7 +333,8 @@ rclc_parameter_set_int( int64_t value); /** - * Sets the value of an existing a RCLC double parameter + * Sets the value of an existing a RCLC double parameter. + * This method is disabled on user callback execution. * *
* Attribute | Adherence @@ -444,6 +455,7 @@ rclc_add_parameter_description( /** * Sets a parameter read only flag. * Read only parameters can only be modified from the `rclc_parameter_set` API. + * This method is disabled on user callback execution. * *
* Attribute | Adherence @@ -467,6 +479,7 @@ rclc_set_parameter_read_only( /** * Add constraint description for an integer parameter. * This constraint description will be returned on describe parameters requests. + * This method is disabled on user callback execution. * *
* Attribute | Adherence @@ -492,6 +505,7 @@ rclc_add_parameter_constraints_integer( /** * Add constraint description for an double parameter. * This constraint description will be returned on describe parameters requests. + * This method is disabled on user callback execution. * *
* Attribute | Adherence diff --git a/rclc_parameter/src/rclc_parameter/parameter_server.c b/rclc_parameter/src/rclc_parameter/parameter_server.c index 6d42cd96..40607a50 100644 --- a/rclc_parameter/src/rclc_parameter/parameter_server.c +++ b/rclc_parameter/src/rclc_parameter/parameter_server.c @@ -42,6 +42,10 @@ rcl_ret_t rclc_add_parameter_undeclared( rclc_parameter_server_t * parameter_server, Parameter * parameter); +rcl_ret_t rclc_parameter_execute_callback( + rclc_parameter_server_t * parameter_server, + const Parameter * old_param, const Parameter * new_param); + void rclc_parameter_server_describe_service_callback( const void * req, @@ -220,9 +224,8 @@ rclc_parameter_server_set_service_callback( switch (request->parameters.data[i].value.type) { case RCLC_PARAMETER_NOT_SET: - if (param_server->on_modification && !param_server->on_modification(parameter, NULL)) { - ret = PARAMETER_MODIFICATION_REJECTED; - } else { + ret = rclc_parameter_execute_callback(param_server, parameter, NULL); + if (ret == RCL_RET_OK) { ret = rclc_delete_parameter(param_server, parameter->name.data); } break; @@ -269,8 +272,9 @@ rclc_parameter_server_set_service_callback( if (0 == remaining_capacity) { // Check parameter server capacity rclc_parameter_set_string(message, "Parameter server is full"); - } else if (param_server->on_modification && // NOLINT - !param_server->on_modification(NULL, &request->parameters.data[i])) + + } else if (RCL_RET_OK != // NOLINT + rclc_parameter_execute_callback(param_server, NULL, &request->parameters.data[i])) { // Check server callback rclc_parameter_set_string(message, "New parameter rejected"); @@ -324,9 +328,7 @@ init_parameter_server_memory( rcl_ret_t ret = RCL_RET_OK; - static char empty_string[RCLC_PARAMETER_MAX_STRING_LENGTH]; - memset(empty_string, '\0', RCLC_PARAMETER_MAX_STRING_LENGTH); - empty_string[RCLC_PARAMETER_MAX_STRING_LENGTH - 1] = '\0'; + static char empty_string[RCLC_PARAMETER_MAX_STRING_LENGTH] = ""; size_t empty_string_capacity = RCLC_PARAMETER_MAX_STRING_LENGTH - 1; bool mem_allocs_ok = true; @@ -341,6 +343,7 @@ init_parameter_server_memory( ¶meter_server->parameter_list.data[i].name, (const char *) empty_string, empty_string_capacity); + parameter_server->parameter_list.data[i].name.size = 0; } // Init list service msgs @@ -359,6 +362,7 @@ init_parameter_server_memory( ¶meter_server->list_response.result.names.data[i], (const char *) empty_string, empty_string_capacity); + parameter_server->list_response.result.names.data[i].size = 0; } // Init Get service msgs @@ -380,6 +384,7 @@ init_parameter_server_memory( ¶meter_server->get_request.names.data[i], (const char *) empty_string, empty_string_capacity); + parameter_server->get_request.names.data[i].size = 0; } // Init Set service msgs @@ -395,9 +400,7 @@ init_parameter_server_memory( options->max_params); parameter_server->set_response.results.size = 0; - static char empty_string_reason[RCLC_SET_ERROR_MAX_STRING_LENGTH]; - memset(empty_string_reason, '\0', RCLC_SET_ERROR_MAX_STRING_LENGTH); - empty_string_reason[RCLC_SET_ERROR_MAX_STRING_LENGTH - 1] = '\0'; + static char empty_string_reason[RCLC_SET_ERROR_MAX_STRING_LENGTH] = ""; size_t string_reason_capacity = RCLC_SET_ERROR_MAX_STRING_LENGTH - 1; // Pre-init strings @@ -406,11 +409,13 @@ init_parameter_server_memory( ¶meter_server->set_request.parameters.data[i].name, (const char *) empty_string, empty_string_capacity); + parameter_server->set_request.parameters.data[i].name.size = 0; mem_allocs_ok &= rosidl_runtime_c__String__assignn( ¶meter_server->set_response.results.data[i].reason, (const char *) empty_string_reason, string_reason_capacity); + parameter_server->set_response.results.data[i].reason.size = 0; } // Init Get types service msgs @@ -432,6 +437,7 @@ init_parameter_server_memory( ¶meter_server->get_types_request.names.data[i], (const char *) empty_string, empty_string_capacity); + parameter_server->get_types_request.names.data[i].size = 0; } // Init Describe service msgs @@ -460,20 +466,24 @@ init_parameter_server_memory( ¶meter_server->describe_request.names.data[i], (const char *) empty_string, empty_string_capacity); + parameter_server->describe_request.names.data[i].size = 0; // Init describe_response members mem_allocs_ok &= rosidl_runtime_c__String__assignn( ¶meter_server->describe_response.descriptors.data[i].name, (const char *) empty_string, empty_string_capacity); + parameter_server->describe_response.descriptors.data[i].name.size = 0; mem_allocs_ok &= rosidl_runtime_c__String__assignn( ¶meter_server->describe_response.descriptors.data[i].description, (const char *) empty_string, empty_string_capacity); + parameter_server->describe_response.descriptors.data[i].description.size = 0; mem_allocs_ok &= rosidl_runtime_c__String__assignn( ¶meter_server->describe_response.descriptors.data[i].additional_constraints, (const char *) empty_string, empty_string_capacity); + parameter_server->describe_response.descriptors.data[i].additional_constraints.size = 0; mem_allocs_ok &= rcl_interfaces__msg__FloatingPointRange__Sequence__init( ¶meter_server->describe_response.descriptors.data[i].floating_point_range, rcl_interfaces__msg__ParameterDescriptor__floating_point_range__MAX_SIZE); @@ -488,14 +498,17 @@ init_parameter_server_memory( ¶meter_server->parameter_descriptors.data[i].name, (const char *) empty_string, empty_string_capacity); + parameter_server->parameter_descriptors.data[i].name.size = 0; mem_allocs_ok &= rosidl_runtime_c__String__assignn( ¶meter_server->parameter_descriptors.data[i].description, (const char *) empty_string, empty_string_capacity); + parameter_server->parameter_descriptors.data[i].description.size = 0; mem_allocs_ok &= rosidl_runtime_c__String__assignn( ¶meter_server->parameter_descriptors.data[i].additional_constraints, (const char *) empty_string, empty_string_capacity); + parameter_server->parameter_descriptors.data[i].additional_constraints.size = 0; mem_allocs_ok &= rcl_interfaces__msg__FloatingPointRange__Sequence__init( ¶meter_server->parameter_descriptors.data[i].floating_point_range, rcl_interfaces__msg__ParameterDescriptor__floating_point_range__MAX_SIZE); @@ -658,8 +671,8 @@ bool init_parameter_server_memory_low_memory( parameter_server->set_response.results.capacity = 1; parameter_server->set_response.results.data[0].reason.data = allocator.allocate( - sizeof(char) * RCLC_PARAMETER_MAX_STRING_LENGTH, allocator.state); - parameter_server->set_response.results.data[0].reason.capacity = RCLC_PARAMETER_MAX_STRING_LENGTH; + sizeof(char) * RCLC_SET_ERROR_MAX_STRING_LENGTH, allocator.state); + parameter_server->set_response.results.data[0].reason.capacity = RCLC_SET_ERROR_MAX_STRING_LENGTH; parameter_server->set_response.results.data[0].reason.size = 0; // Get parameter types: @@ -794,6 +807,7 @@ rclc_parameter_server_init_with_option( ¶meter_server->describe_service, node, "/describe_parameters", describe_ts); + parameter_server->on_callback = false; parameter_server->notify_changed_over_dds = options->notify_changed_over_dds; parameter_server->allow_undeclared_parameters = options->allow_undeclared_parameters; parameter_server->low_mem_mode = options->low_mem_mode; @@ -1106,6 +1120,10 @@ rclc_add_parameter( RCL_CHECK_FOR_NULL_WITH_MSG( parameter_name, "parameter_name is a null pointer", return RCL_RET_INVALID_ARGUMENT); + if (parameter_server->on_callback) { + return DISABLE_ON_CALLBACK; + } + size_t index = parameter_server->parameter_list.size; if (index >= parameter_server->parameter_list.capacity || @@ -1204,6 +1222,10 @@ rclc_delete_parameter( RCL_CHECK_FOR_NULL_WITH_MSG( parameter_name, "parameter_name is a null pointer", return RCL_RET_INVALID_ARGUMENT); + if (parameter_server->on_callback) { + return DISABLE_ON_CALLBACK; + } + // Find parameter size_t index = rclc_parameter_search_index(¶meter_server->parameter_list, parameter_name); @@ -1263,6 +1285,10 @@ rclc_parameter_set_bool( RCL_CHECK_FOR_NULL_WITH_MSG( parameter_name, "parameter_name is a null pointer", return RCL_RET_INVALID_ARGUMENT); + if (parameter_server->on_callback) { + return DISABLE_ON_CALLBACK; + } + Parameter * parameter = rclc_parameter_search(¶meter_server->parameter_list, parameter_name); @@ -1275,18 +1301,12 @@ rclc_parameter_set_bool( } if (parameter_server->on_modification) { - // Avoid recursive loop if called within on_modification_cb - ModifiedParameter_Callback on_modification_cb = parameter_server->on_modification; - parameter_server->on_modification = NULL; - Parameter new_parameter = *parameter; new_parameter.value.bool_value = value; - bool user_ret = on_modification_cb(parameter, &new_parameter); - - parameter_server->on_modification = on_modification_cb; - - if (!user_ret) { + if (RCL_RET_OK != + rclc_parameter_execute_callback(parameter_server, parameter, &new_parameter)) + { return PARAMETER_MODIFICATION_REJECTED; } } @@ -1312,6 +1332,10 @@ rclc_parameter_set_int( RCL_CHECK_FOR_NULL_WITH_MSG( parameter_name, "parameter_name is a null pointer", return RCL_RET_INVALID_ARGUMENT); + if (parameter_server->on_callback) { + return DISABLE_ON_CALLBACK; + } + Parameter * parameter = rclc_parameter_search(¶meter_server->parameter_list, parameter_name); @@ -1324,18 +1348,12 @@ rclc_parameter_set_int( } if (parameter_server->on_modification) { - // Avoid recursive loop if called within on_modification_cb - ModifiedParameter_Callback on_modification_cb = parameter_server->on_modification; - parameter_server->on_modification = NULL; - Parameter new_parameter = *parameter; new_parameter.value.integer_value = value; - bool user_ret = on_modification_cb(parameter, &new_parameter); - - parameter_server->on_modification = on_modification_cb; - - if (!user_ret) { + if (RCL_RET_OK != + rclc_parameter_execute_callback(parameter_server, parameter, &new_parameter)) + { return PARAMETER_MODIFICATION_REJECTED; } } @@ -1361,6 +1379,10 @@ rclc_parameter_set_double( RCL_CHECK_FOR_NULL_WITH_MSG( parameter_name, "parameter_name is a null pointer", return RCL_RET_INVALID_ARGUMENT); + if (parameter_server->on_callback) { + return DISABLE_ON_CALLBACK; + } + Parameter * parameter = rclc_parameter_search(¶meter_server->parameter_list, parameter_name); @@ -1373,18 +1395,12 @@ rclc_parameter_set_double( } if (parameter_server->on_modification) { - // Avoid recursive loop if called within on_modification_cb - ModifiedParameter_Callback on_modification_cb = parameter_server->on_modification; - parameter_server->on_modification = NULL; - Parameter new_parameter = *parameter; new_parameter.value.double_value = value; - bool user_ret = on_modification_cb(parameter, &new_parameter); - - parameter_server->on_modification = on_modification_cb; - - if (!user_ret) { + if (RCL_RET_OK != + rclc_parameter_execute_callback(parameter_server, parameter, &new_parameter)) + { return PARAMETER_MODIFICATION_REJECTED; } } @@ -1559,6 +1575,10 @@ rcl_ret_t rclc_set_parameter_read_only( rclc_parameter_server_t * parameter_server, const char * parameter_name, bool read_only) { + if (parameter_server->on_callback) { + return DISABLE_ON_CALLBACK; + } + size_t index = rclc_parameter_search_index(¶meter_server->parameter_list, parameter_name); if (index >= parameter_server->parameter_list.size) { @@ -1578,6 +1598,10 @@ rcl_ret_t rclc_add_parameter_constraints_double( const char * parameter_name, double from_value, double to_value, double step) { + if (parameter_server->on_callback) { + return DISABLE_ON_CALLBACK; + } + size_t index = rclc_parameter_search_index(¶meter_server->parameter_list, parameter_name); if (index >= parameter_server->parameter_list.size) { @@ -1603,6 +1627,10 @@ rcl_ret_t rclc_add_parameter_constraints_integer( const char * parameter_name, int64_t from_value, int64_t to_value, uint64_t step) { + if (parameter_server->on_callback) { + return DISABLE_ON_CALLBACK; + } + size_t index = rclc_parameter_search_index(¶meter_server->parameter_list, parameter_name); if (index >= parameter_server->parameter_list.size) { @@ -1623,6 +1651,21 @@ rcl_ret_t rclc_add_parameter_constraints_integer( return RCL_RET_OK; } +rcl_ret_t rclc_parameter_execute_callback( + rclc_parameter_server_t * parameter_server, + const Parameter * old_param, const Parameter * new_param) +{ + bool ret = true; + + if (parameter_server->on_modification) { + parameter_server->on_callback = true; + ret = parameter_server->on_modification(old_param, new_param); + parameter_server->on_callback = false; + } + + return ret ? RCL_RET_OK : PARAMETER_MODIFICATION_REJECTED; +} + #if __cplusplus } #endif /* if __cplusplus */