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

OCPP Module / Generic OCPP interface: Add command for internal availability change request #484

Merged
merged 4 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ libcurl:
# OCPP
libocpp:
git: https://github.com/EVerest/libocpp.git
git_tag: "7865283"
git_tag: "a6cd837"
# Josev
Josev:
git: https://github.com/EVerest/ext-switchev-iso15118.git
Expand Down
15 changes: 15 additions & 0 deletions interfaces/ocpp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,21 @@ cmds:
items:
type: object
$ref: /ocpp#/SetVariableResult
change_availability:
description: >-
Allows to send a ChangeAvailabilityRequest internally (as can be done by the CSMS).
arguments:
request:
description: >-
The ChangeAvailabilityRequest as specified in OCPP2.0.1.
For OCPP 1.6:
type: object
$ref: /ocpp#/ChangeAvailabilityRequest
result:
description: >-
Response to ChangeAvailabilityRequest as specified in OCPP 2.0.1
type: object
$ref: /ocpp#/ChangeAvailabilityResponse
monitor_variables:
description: >-
Command to start monitoring the given ComponentVariable(s). Any of the provided
Expand Down
4 changes: 4 additions & 0 deletions modules/OCPP/OCPP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -747,4 +747,8 @@ void OCPP::ready() {
}
}

int32_t OCPP::get_ocpp_connector_id(int32_t evse_id, int32_t connector_id) {
return this->evse_connector_map.at(evse_id).at(connector_id);
}

} // namespace module
3 changes: 3 additions & 0 deletions modules/OCPP/OCPP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ class OCPP : public Everest::ModuleBase {
std::unique_ptr<ocpp::v16::ChargePoint> charge_point;
std::unique_ptr<Everest::SteadyTimer> charging_schedules_timer;
bool ocpp_stopped = false;

// Return the OCPP connector id from a pair of EVerest EVSE id and connector id
int32_t get_ocpp_connector_id(int32_t evse_id, int32_t connector_id);
// ev@1fce4c5e-0ab8-41bb-90f7-14277703d2ac:v1

protected:
Expand Down
69 changes: 69 additions & 0 deletions modules/OCPP/ocpp_generic/ocppImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Copyright Pionix GmbH and Contributors to EVerest

#include "ocppImpl.hpp"
#include "ocpp/v16/messages/ChangeAvailability.hpp"

namespace module {
namespace ocpp_generic {
Expand Down Expand Up @@ -54,6 +55,46 @@ types::ocpp::GetConfigurationResponse to_everest(const ocpp::v16::GetConfigurati
return _response;
}

ocpp::v16::AvailabilityStatus to_ocpp(const types::ocpp::ChangeAvailabilityStatusEnumType& status) {
switch (status) {
case types::ocpp::ChangeAvailabilityStatusEnumType::Accepted:
return ocpp::v16::AvailabilityStatus::Accepted;
case types::ocpp::ChangeAvailabilityStatusEnumType::Rejected:
return ocpp::v16::AvailabilityStatus::Rejected;
case types::ocpp::ChangeAvailabilityStatusEnumType::Scheduled:
return ocpp::v16::AvailabilityStatus::Scheduled;
}
throw std::out_of_range("unknown ChangeAvailabilityStatusEnumType");
}

types::ocpp::ChangeAvailabilityStatusEnumType to_everest(const ocpp::v16::AvailabilityStatus& status) {
switch (status) {
case ocpp::v16::AvailabilityStatus::Accepted:
return types::ocpp::ChangeAvailabilityStatusEnumType::Accepted;
case ocpp::v16::AvailabilityStatus::Rejected:
return types::ocpp::ChangeAvailabilityStatusEnumType::Rejected;
case ocpp::v16::AvailabilityStatus::Scheduled:
return types::ocpp::ChangeAvailabilityStatusEnumType::Scheduled;
}
throw std::out_of_range("unknown AvailabilityStatus");
}

ocpp::v16::AvailabilityType to_ocpp(const types::ocpp::OperationalStatusEnumType& status) {
switch (status) {
case types::ocpp::OperationalStatusEnumType::Operative:
return ocpp::v16::AvailabilityType::Operative;
case types::ocpp::OperationalStatusEnumType::Inoperative:
return ocpp::v16::AvailabilityType::Inoperative;
}
throw std::out_of_range("unknown OperationalStatusEnumType");
}

types::ocpp::ChangeAvailabilityResponse to_everest(const ocpp::v16::ChangeAvailabilityResponse& response) {
types::ocpp::ChangeAvailabilityResponse everest_response{};
everest_response.status = to_everest(response.status);
return everest_response;
}

void ocppImpl::init() {
}

Expand Down Expand Up @@ -197,6 +238,34 @@ void ocppImpl::handle_monitor_variables(std::vector<types::ocpp::ComponentVariab
});
}
}
types::ocpp::ChangeAvailabilityResponse
ocppImpl::handle_change_availability(types::ocpp::ChangeAvailabilityRequest& request) {

ocpp::v16::ChangeAvailabilityRequest ocpp_request{};
ocpp_request.type = to_ocpp(request.operational_status);
if (request.evse.has_value()) {
const auto& evse = request.evse.value();
if (!evse.connector_id.has_value()) {
return types::ocpp::ChangeAvailabilityResponse{
types::ocpp::ChangeAvailabilityStatusEnumType::Rejected,
types::ocpp::StatusInfoType{"InvalidInput",
"No connector id specified; if the whole charging station is supposed to "
"be addressed, parameter evse "
"must have no value."}};
}
try {
ocpp_request.connectorId = this->mod->get_ocpp_connector_id(evse.id, evse.connector_id.value());
} catch (const std::out_of_range&) {
return types::ocpp::ChangeAvailabilityResponse{
types::ocpp::ChangeAvailabilityStatusEnumType::Rejected,
types::ocpp::StatusInfoType{
"InvalidInput",
"Could not determine OCPP connector id from provided EVerest EVSE and Connector Ids."}};
}
}
auto response = this->mod->charge_point->on_change_availability(ocpp_request);
return to_everest(response);
}

} // namespace ocpp_generic
} // namespace module
3 changes: 3 additions & 0 deletions modules/OCPP/ocpp_generic/ocppImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

// ev@75ac1216-19eb-4182-a85c-820f1fc2c091:v1
// insert your custom include headers here

// ev@75ac1216-19eb-4182-a85c-820f1fc2c091:v1

namespace module {
Expand All @@ -40,6 +41,8 @@ class ocppImpl : public ocppImplBase {
handle_get_variables(std::vector<types::ocpp::GetVariableRequest>& requests) override;
virtual std::vector<types::ocpp::SetVariableResult>
handle_set_variables(std::vector<types::ocpp::SetVariableRequest>& requests) override;
virtual types::ocpp::ChangeAvailabilityResponse
handle_change_availability(types::ocpp::ChangeAvailabilityRequest& request) override;
virtual void handle_monitor_variables(std::vector<types::ocpp::ComponentVariable>& component_variables) override;

// ev@d2d1847a-7b88-41dd-ad07-92785f06f5c4:v1
Expand Down
62 changes: 62 additions & 0 deletions types/ocpp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -411,3 +411,65 @@ types:
variable_monitoring_id:
description: Identifies the VariableMonitoring which triggered the event
type: integer
OperationalStatusEnumType:
description: >-
Operational status of Charging Station /EVSE / Connector
type: string
enum:
- Inoperative
- Operative
ChangeAvailabilityRequest:
description: Request type to change the availability of the Charging Station/ an EVSE / a Connector.
type: object
required:
- operational_status
properties:
operational_status:
description: Type of availability change that the Charging Station should perform.
type: string
$ref: /ocpp#/OperationalStatusEnumType
evse:
description: >-
Specify EVSE/Connector whose status is changed. When omitted, the
message refers to the Charging Station as a whole.
type: object
$ref: /ocpp#/EVSE
ChangeAvailabilityStatusEnumType:
description: >-
Status returned in response to ChangeAvailabilityRequest.
type: string
enum:
- Accepted
- Rejected
- Scheduled
StatusInfoType:
description: >-
Element providing more information about the status.
type: object
required:
- reason_code
properties:
reason_code:
description: >-
A predefined code for the reason why the status is returned in this response.
The string is case-insensitive.
type: string
additional_info:
description: >-
Additional text to provide detailed information
type: string
ChangeAvailabilityResponse:
description: Response type to request to change the availability of the Charging Station/ an EVSE / a Connector.
type: object
required:
- status
properties:
status:
description: Indicates whether the Charging Station is able to perform the availability change.
type: string
$ref: /ocpp#/ChangeAvailabilityStatusEnumType
status_info:
description: Detailed status information.
type: object
$ref: /ocpp#/StatusInfoType