Files
cariflex/tools/EVerest-main/modules/EVSE/OCPP201/error_handling.hpp
Eric F d398a6ced2 Add extracted tools: CitrineOS, OpenOCPP, ShapeShifter
- CitrineOS core extracted (CSMS OCPP 2.0.1)
- OpenOCPP extracted (firmware OCPP 1.6J/2.0.1)
- ShapeShifter library installed (pip install -e)
- ShapeShifter specification extracted
- EVerest extracted

TODO updated with progress
2026-06-08 00:38:27 -04:00

105 lines
4.4 KiB
C++

// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#ifndef OCPP201_ERROR_HANDLING_HPP
#define OCPP201_ERROR_HANDLING_HPP
#include <everest/conversions/ocpp/ocpp_conversions.hpp>
#include <ocpp/v2/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"},
{"evse_manager/MREC22ResistanceFault", "CX022"},
{"evse_manager/MREC11CableCheckFault", "CX011"},
{"evse_manager/MREC5OverVoltage", "CX005"},
};
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 Returns simplified mapping from error origin to OCPP component based on evse and connector ids
ocpp::v2::Component get_component_from_error(const Everest::error::Error& error) {
ocpp::v2::Component component;
if (!error.origin.mapping.has_value()) {
// component is ChargingStation
component.name = CHARGING_STATION_COMPONENT_NAME;
return component;
}
const auto& mapping = error.origin.mapping.value();
const auto evse_id = mapping.evse;
if (!mapping.connector.has_value()) {
// component is EVSE
ocpp::v2::EVSE evse;
evse.id = evse_id;
component.name = EVSE_COMPONENT_NAME;
component.evse = evse;
return component;
}
// component is Connector
ocpp::v2::EVSE evse;
evse.id = evse_id;
evse.connectorId = mapping.connector.value();
component.name = EVSE_COMPONENT_NAME;
component.evse = evse;
return component;
}
/// \brief Derives the EventData from the given \p error, \p cleared and \p event_id parameters
ocpp::v2::EventData get_event_data(const Everest::error::Error& error, const bool cleared, const int32_t event_id) {
ocpp::v2::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::v2::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::v2::EventNotificationEnum::HardWiredNotification;
event_data.component = get_component_from_error(error);
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