diff --git a/include/ocpp/v201/device_model.hpp b/include/ocpp/v201/device_model.hpp index 0568ad9e5..f6051254c 100644 --- a/include/ocpp/v201/device_model.hpp +++ b/include/ocpp/v201/device_model.hpp @@ -55,9 +55,10 @@ class DeviceModel { /// \param variable_id /// \param attribute_enum /// \param value string reference to value: will be set to requested value if value is present + /// \param allow_write_only true to allow a writeOnly value to be read. /// \return GetVariableStatusEnum that indicates the result of the request - GetVariableStatusEnum request_value(const Component& component_id, const Variable& variable_id, - const AttributeEnum& attribute_enum, std::string& value); + GetVariableStatusEnum request_value_internal(const Component& component_id, const Variable& variable_id, + const AttributeEnum& attribute_enum, std::string& value, bool allow_write_only); /// \brief Iterates over the given \p component_criteria and converts this to the variable names /// (Active,Available,Enabled,Problem). If any of the variables can not be find as part of a component this function @@ -92,10 +93,11 @@ class DeviceModel { template T get_value(const ComponentVariable& component_variable, const AttributeEnum& attribute_enum = AttributeEnum::Actual) { - const auto response = - this->request_value(component_variable.component, component_variable.variable.value(), attribute_enum); - if (response.value.has_value()) { - return response.value.value(); + std::string value; + const auto response = this->request_value_internal(component_variable.component, + component_variable.variable.value(), attribute_enum,value, true); + if (response == GetVariableStatusEnum::Accepted) { + return to_specific_type(value); } else { EVLOG_critical << "Directly requested value for ComponentVariable that doesn't exist in the device model storage: " @@ -114,10 +116,11 @@ class DeviceModel { template std::optional get_optional_value(const ComponentVariable& component_variable, const AttributeEnum& attribute_enum = AttributeEnum::Actual) { - const auto response = - this->request_value(component_variable.component, component_variable.variable.value(), attribute_enum); - if (response.status == GetVariableStatusEnum::Accepted) { - return response.value.value(); + std::string value; + const auto response = this->request_value_internal(component_variable.component, + component_variable.variable.value(), attribute_enum,value, true); + if (response == GetVariableStatusEnum::Accepted) { + return to_specific_type(value); } else { return std::nullopt; } @@ -135,7 +138,7 @@ class DeviceModel { RequestDeviceModelResponse request_value(const Component& component_id, const Variable& variable_id, const AttributeEnum& attribute_enum) { std::string value; - const auto req_status = this->request_value(component_id, variable_id, attribute_enum, value); + const auto req_status = this->request_value_internal(component_id, variable_id, attribute_enum, value, false); if (req_status == GetVariableStatusEnum::Accepted) { return {GetVariableStatusEnum::Accepted, to_specific_type(value)}; @@ -163,13 +166,6 @@ class DeviceModel { /// \return Result of the requested operation SetVariableStatusEnum set_read_only_value(const Component& component_id, const Variable& variable_id, const AttributeEnum& attribute_enum, const std::string& value); - - /// @brief Gets the value of write only components - /// @param component_id - /// @param variable_id - /// @param attribute_enum - /// @return Result of the requested operation - GetVariableStatusEnum get_write_only_value(const Component& component_id, const Variable& variable_id, const AttributeEnum& attribute_enum); /// \brief Gets the VariableMetaData for the given \p component_id and \p variable_id /// \param component_id diff --git a/lib/ocpp/v201/device_model.cpp b/lib/ocpp/v201/device_model.cpp index 91b3a9765..69a26219c 100644 --- a/lib/ocpp/v201/device_model.cpp +++ b/lib/ocpp/v201/device_model.cpp @@ -92,8 +92,9 @@ bool validate_value(const VariableCharacteristics& characteristics, const std::s } } -GetVariableStatusEnum DeviceModel::request_value(const Component& component_id, const Variable& variable_id, - const AttributeEnum& attribute_enum, std::string& value) { +GetVariableStatusEnum DeviceModel::request_value_internal(const Component& component_id, const Variable& variable_id, + const AttributeEnum& attribute_enum, std::string& value, + bool allow_write_only) { const auto component_it = this->device_model.find(component_id); if (component_it == this->device_model.end()) { return GetVariableStatusEnum::UnknownComponent; @@ -112,6 +113,12 @@ GetVariableStatusEnum DeviceModel::request_value(const Component& component_id, return GetVariableStatusEnum::NotSupportedAttributeType; } + // only internal functions can access WriteOnly variables + if (attribute_opt.value().mutability.has_value() && !allow_write_only && + attribute_opt.value().mutability.value() == MutabilityEnum::WriteOnly ) { + return GetVariableStatusEnum::Rejected; + } + value = attribute_opt->value->get(); return GetVariableStatusEnum::Accepted; } @@ -173,17 +180,6 @@ SetVariableStatusEnum DeviceModel::set_read_only_value(const Component& componen throw std::invalid_argument("Not allowed to set read only value for component " + component.name.get()); } -GetVariableStatusEnum DeviceModel::get_write_only_value(const Component& component_id, const Variable& variable_id, const AttributeEnum& attribute_enum) { - - const auto attribute_opt = this->storage->get_variable_attribute(component_id, variable_id, attribute_enum); - if (attribute_opt.value().mutability.has_value() && - attribute_opt.value().mutability.value() == MutabilityEnum::WriteOnly) { - // if WriteOnly then return rejected - EVLOG_info << "====> WriteONLY ====== "; - return GetVariableStatusEnum::Rejected; - } -} - std::optional DeviceModel::get_variable_meta_data(const Component& component, const Variable& variable) { if (this->device_model.count(component) and this->device_model.at(component).count(variable)) {