Skip to content

Commit

Permalink
B06:- Get variables requests (#218)
Browse files Browse the repository at this point in the history
B06.FR.09
B06.FR.16
B06.FR.17
  • Loading branch information
SNSubramanya authored Oct 26, 2023
1 parent 6749e46 commit a133941
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 21 deletions.
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 @@ const auto STANDARD_MESSAGE_TIMEOUT = std::chrono::seconds(30);
/// \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
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();
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

0 comments on commit a133941

Please sign in to comment.