Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

B06:- Get variables requests #218

Merged
merged 10 commits into from
Oct 26, 2023
4 changes: 2 additions & 2 deletions config/v201/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@
"BytesPerMessageGetVariables": {
"variable_name": "BytesPerMessage",
"attributes": {
"Actual": 42
"Actual": 250
},
"instance": "GetVariables"
},
Expand All @@ -550,7 +550,7 @@
"ItemsPerMessageGetVariables": {
"variable_name": "ItemsPerMessage",
"attributes": {
"Actual": 42
"Actual": 2
},
"instance": "GetVariables"
},
Expand Down
1 change: 1 addition & 0 deletions include/ocpp/common/message_queue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
/// \brief Contains a OCPP message in json form with additional information
template <typename M> struct EnhancedMessage {
json message; ///< The OCPP message as json
size_t message_size; ///< size of the json message in bytes

Check notice on line 33 in include/ocpp/common/message_queue.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

include/ocpp/common/message_queue.hpp#L33

struct member 'EnhancedMessage::message_size' is never used.
MessageId uniqueId; ///< The unique ID of the json message
M messageType = M::InternalError; ///< The OCPP message type
MessageTypeId messageTypeId; ///< The OCPP message type ID (CALL/CALLRESULT/CALLERROR)
Expand Down
2 changes: 1 addition & 1 deletion include/ocpp/v201/charge_point.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ class ChargePoint : ocpp::ChargingStationBase {
// Functional Block B: Provisioning
void handle_boot_notification_response(CallResult<BootNotificationResponse> call_result);
void handle_set_variables_req(Call<SetVariablesRequest> call);
void handle_get_variables_req(Call<GetVariablesRequest> call);
void handle_get_variables_req(const EnhancedMessage<v201::MessageType>& message);
void handle_get_base_report_req(Call<GetBaseReportRequest> call);
void handle_get_report_req(Call<GetReportRequest> call);
void handle_set_network_profile_req(Call<SetNetworkProfileRequest> call);
Expand Down
26 changes: 15 additions & 11 deletions include/ocpp/v201/device_model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@ 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
Expand Down Expand Up @@ -92,10 +94,11 @@ class DeviceModel {
template <typename T>
T get_value(const ComponentVariable& component_variable,
const AttributeEnum& attribute_enum = AttributeEnum::Actual) {
const auto response =
this->request_value<T>(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<T>(value);
} else {
EVLOG_critical
<< "Directly requested value for ComponentVariable that doesn't exist in the device model storage: "
Expand All @@ -114,10 +117,11 @@ class DeviceModel {
template <typename T>
std::optional<T> get_optional_value(const ComponentVariable& component_variable,
const AttributeEnum& attribute_enum = AttributeEnum::Actual) {
const auto response =
this->request_value<T>(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<T>(value);
} else {
return std::nullopt;
}
Expand All @@ -135,7 +139,7 @@ class DeviceModel {
RequestDeviceModelResponse<T> 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<T>(value)};
Expand Down
29 changes: 24 additions & 5 deletions lib/ocpp/v201/charge_point.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,7 @@ void ChargePoint::handle_message(const EnhancedMessage<v201::MessageType>& messa
this->handle_set_variables_req(json_message);
break;
case MessageType::GetVariables:
this->handle_get_variables_req(json_message);
this->handle_get_variables_req(message);
break;
case MessageType::GetBaseReport:
this->handle_get_base_report_req(json_message);
Expand Down Expand Up @@ -754,9 +754,9 @@ void ChargePoint::handle_message(const EnhancedMessage<v201::MessageType>& messa

void ChargePoint::message_callback(const std::string& message) {
auto enhanced_message = this->message_queue->receive(message);
enhanced_message.message_size = message.size();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wondering if we would like to do this assignment in the queue itself so 1.6 can use it as well.

auto json_message = enhanced_message.message;
this->logging->central_system(conversions::messagetype_to_string(enhanced_message.messageType), message);

try {
if (this->registration_status == RegistrationStatusEnum::Accepted) {
this->handle_message(enhanced_message);
Expand Down Expand Up @@ -1493,11 +1493,30 @@ void ChargePoint::handle_set_variables_req(Call<SetVariablesRequest> call) {
}
}

void ChargePoint::handle_get_variables_req(Call<GetVariablesRequest> call) {
void ChargePoint::handle_get_variables_req(const EnhancedMessage<v201::MessageType>& message) {
Call<GetVariablesRequest> call = message.call_message;
const auto msg = call.msg;

// FIXME(piet): add handling for B06.FR.16
// FIXME(piet): add handling for B06.FR.17
const auto max_variables_per_message =
this->device_model->get_value<int>(ControllerComponentVariables::ItemsPerMessageGetVariables);
const auto max_bytes_per_message =
this->device_model->get_value<int>(ControllerComponentVariables::BytesPerMessageGetVariables);

// B06.FR.16
if (msg.getVariableData.size() > max_variables_per_message) {
// send a CALLERROR
const auto call_error = CallError(call.uniqueId, "OccurenceConstraintViolation", "", json({}));
this->send(call_error);
return;
}

// B06.FR.17
if (message.message_size > max_bytes_per_message) {
// send a CALLERROR
const auto call_error = CallError(call.uniqueId, "FormatViolation", "", json({}));
this->send(call_error);
return;
}

GetVariablesResponse response;

Expand Down
11 changes: 9 additions & 2 deletions lib/ocpp/v201/device_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -112,6 +113,12 @@ GetVariableStatusEnum DeviceModel::request_value(const Component& component_id,
return GetVariableStatusEnum::NotSupportedAttributeType;
}

// only internal functions can access WriteOnly variables
if (!allow_write_only and attribute_opt.value().mutability.has_value() and
attribute_opt.value().mutability.value() == MutabilityEnum::WriteOnly) {
return GetVariableStatusEnum::Rejected;
}

value = attribute_opt->value->get();
return GetVariableStatusEnum::Accepted;
}
Expand Down