-
Notifications
You must be signed in to change notification settings - Fork 90
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Implemented on_event in OCPP201 and add documentation for how the EventDataType is derived from the EVerest Error Type * Added implementation to trigger NotifyEvent.req in case errors are received within EVerest. Added documentation about the current limitations, which includes that currently no proper mapping to Components and Variables is implemented --------- Signed-off-by: pietfried <[email protected]>
- Loading branch information
1 parent
f6ccd75
commit ba0871b
Showing
4 changed files
with
144 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,40 @@ | ||
Global Errors | ||
============= | ||
Error Handling | ||
============== | ||
|
||
The `enable_global_errors` flag for this module is true. This module is | ||
therefore able to retrieve and process all reported errors from other | ||
modules that are loaded in the same EVerest configuration. | ||
|
||
The error reporting via OCPP2.0.1 follows the Minimum Required Error Codes (MRECS): https://inl.gov/chargex/mrec/ . This proposes a unified methodology | ||
to define and classify a minimum required set of error codes and how to report them via OCPP2.0.1. | ||
|
||
StatusNotification | ||
------------------ | ||
In contrast to OCPP1.6, error information is not transmitted as part of the StatusNotification.req. | ||
A `StatusNotification.req` with status `Faulted` will be set to faulted only in case the error received is of the special type `evse_manager/Inoperative`. | ||
This indicates that the EVSE is inoperative (not ready for energy transfer). | ||
|
||
In OCPP2.0.1 errors can be reported using the `NotifyEventRequest.req` . This message is used to report all other errros received. | ||
|
||
Current Limitation | ||
------------------ | ||
|
||
In OCPP2.0.1 errors can be reported using the `NotifyEventRequest` | ||
message. The `eventData` property carries the relevant information. | ||
|
||
This format of reporting errors deviates from the mechanism used within | ||
EVerest. This data structure forces to map an error to a | ||
component-variable combination. This requires a mapping | ||
mechanism between EVerest errors and component-variable | ||
combination. | ||
|
||
Currently this module maps the Error to one of these three Components: | ||
|
||
* ChargingStation (if error.origin.mapping.evse is not set or 0) | ||
* EVSE (error.origin.mapping.evse is set and error.origin.mapping.connector is not set) | ||
* Connector (error.origin.mapping.evse is set and error.origin.mapping.connector is set) | ||
|
||
The Variable used as part of the NotifyEventRequest is constantly defined to `Problem` for now. | ||
|
||
The goal is to have a more advanced mapping of reported errors to the respective component-variable combinations in the future. | ||
|
||
The `enable_global_errors` flag for this module is enabled. This module is therefore able to retrieve and process all reported errors | ||
from other modules loaded in the same EVerest configuration. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright Pionix GmbH and Contributors to EVerest | ||
#ifndef OCPP201_ERROR_HANDLING_HPP | ||
#define OCPP201_ERROR_HANDLING_HPP | ||
|
||
#include <ocpp/v201/ocpp_types.hpp> | ||
#include <utils/error.hpp> | ||
|
||
#include <unordered_map> | ||
|
||
namespace module { | ||
const std::unordered_map<std::string, std::string> MREC_ERROR_MAP = { | ||
{"connector_lock/MREC1ConnectorLockFailure", "CX001"}, | ||
{"evse_board_support/MREC2GroundFailure", "CX002"}, | ||
{"evse_board_support/MREC3HighTemperature", "CX003"}, | ||
{"evse_board_support/MREC4OverCurrentFailure", "CX004"}, | ||
{"evse_board_support/MREC5OverVoltage", "CX005"}, | ||
{"evse_board_support/MREC6UnderVoltage", "CX006"}, | ||
{"evse_board_support/MREC8EmergencyStop", "CX008"}, | ||
{"evse_board_support/MREC10InvalidVehicleMode", "CX010"}, | ||
{"evse_board_support/MREC14PilotFault", "CX014"}, | ||
{"evse_board_support/MREC15PowerLoss", "CX015"}, | ||
{"evse_board_support/MREC17EVSEContactorFault", "CX017"}, | ||
{"evse_board_support/MREC18CableOverTempDerate", "CX018"}, | ||
{"evse_board_support/MREC19CableOverTempStop", "CX019"}, | ||
{"evse_board_support/MREC20PartialInsertion", "CX020"}, | ||
{"evse_board_support/MREC23ProximityFault", "CX023"}, | ||
{"evse_board_support/MREC24ConnectorVoltageHigh", "CX024"}, | ||
{"evse_board_support/MREC25BrokenLatch", "CX025"}, | ||
{"evse_board_support/MREC26CutCable", "CX026"}, | ||
{"evse_manager/MREC4OverCurrentFailure", "CX004"}, | ||
{"ac_rcd/MREC2GroundFailure", "CX002"}, | ||
}; | ||
|
||
const auto EVSE_MANAGER_INOPERATIVE_ERROR = "evse_manager/Inoperative"; | ||
const auto CHARGING_STATION_COMPONENT_NAME = "ChargingStation"; | ||
const auto EVSE_COMPONENT_NAME = "EVSE"; | ||
const auto CONNECTOR_COMPONENT_NAME = "Connector"; | ||
const auto PROBLEM_VARIABLE_NAME = "Problem"; | ||
|
||
/// \brief Derives the EventData from the given \p error, \p cleared and \p event_id parameters | ||
ocpp::v201::EventData get_event_data(const Everest::error::Error& error, const bool cleared, const int32_t event_id) { | ||
ocpp::v201::EventData event_data; | ||
event_data.eventId = event_id; // This can theoretically conflict with eventIds generated in libocpp (e.g. | ||
// for monitoring events), but the spec does not strictly forbid that | ||
event_data.timestamp = ocpp::DateTime(error.timestamp); | ||
event_data.trigger = ocpp::v201::EventTriggerEnum::Alerting; | ||
event_data.cause = std::nullopt; // TODO: use caused_by when available within error object | ||
event_data.actualValue = cleared ? "false" : "true"; | ||
|
||
if (MREC_ERROR_MAP.count(error.type)) { | ||
event_data.techCode = MREC_ERROR_MAP.at(error.type); | ||
} else { | ||
event_data.techCode = error.type; | ||
} | ||
|
||
event_data.techInfo = error.description; | ||
event_data.cleared = cleared; | ||
event_data.transactionId = std::nullopt; // TODO: Do we need to set this here? | ||
event_data.variableMonitoringId = std::nullopt; // We dont need to set this for HardwiredNotification | ||
event_data.eventNotificationType = ocpp::v201::EventNotificationEnum::HardWiredNotification; | ||
|
||
// TODO: choose proper component | ||
const auto evse_id = error.origin.mapping.has_value() ? error.origin.mapping.value().evse : 0; | ||
if (evse_id == 0) { | ||
// component is ChargingStation | ||
event_data.component = {CHARGING_STATION_COMPONENT_NAME}; // TODO: use origin of error for mapping to component? | ||
} else if (not error.origin.mapping.value().connector.has_value()) { | ||
// component is EVSE | ||
ocpp::v201::EVSE evse = {evse_id}; | ||
event_data.component = {EVSE_COMPONENT_NAME, std::nullopt, evse}; | ||
} else { | ||
// component is Connector | ||
ocpp::v201::EVSE evse = {evse_id, std::nullopt, error.origin.mapping.value().connector.value()}; | ||
event_data.component = {CONNECTOR_COMPONENT_NAME, std::nullopt, evse}; | ||
} | ||
event_data.variable = {PROBLEM_VARIABLE_NAME}; // TODO: use type of error for mapping to variable? | ||
return event_data; | ||
} | ||
}; // namespace module | ||
|
||
#endif // OCPP201_ERROR_HANDLING_HPP |