diff --git a/modules/API/API.cpp b/modules/API/API.cpp index 02cb39b10..21fd9ae22 100644 --- a/modules/API/API.cpp +++ b/modules/API/API.cpp @@ -9,7 +9,7 @@ namespace module { static const auto NOTIFICATION_PERIOD = std::chrono::seconds(1); SessionInfo::SessionInfo() : - state("Unknown"), + state(State::Unknown), start_energy_import_wh(0), end_energy_import_wh(0), latest_total_w(0), @@ -19,9 +19,9 @@ SessionInfo::SessionInfo() : this->end_time_point = this->start_time_point; } -bool SessionInfo::is_state_charging(const std::string& current_state) { - if (current_state == "AuthRequired" || current_state == "Charging" || current_state == "ChargingPausedEV" || - current_state == "ChargingPausedEVSE") { +bool SessionInfo::is_state_charging(const SessionInfo::State current_state) { + if (current_state == State::AuthRequired || current_state == State::Charging || + current_state == State::ChargingPausedEV || current_state == State::ChargingPausedEVSE) { return true; } return false; @@ -29,8 +29,9 @@ bool SessionInfo::is_state_charging(const std::string& current_state) { void SessionInfo::reset() { std::lock_guard lock(this->session_info_mutex); - this->state = "Unknown"; - this->state_info = ""; + this->state = State::Unknown; + this->active_permanent_faults.clear(); + this->active_errors.clear(); this->start_energy_import_wh = 0; this->end_energy_import_wh = 0; this->start_energy_export_wh = 0; @@ -65,43 +66,80 @@ types::energy::ExternalLimits get_external_limits(const std::string& data, bool return external_limits; } -void SessionInfo::update_state(const std::string& event, const std::string& state_info) { +static void remove_error_from_list(std::vector& list, const std::string& error_type) { + list.erase(std::remove_if(list.begin(), list.end(), + [error_type](const module::SessionInfo::Error& err) { return err.type == error_type; }), + list.end()); +} + +void SessionInfo::update_state(const types::evse_manager::SessionEventEnum event, const SessionInfo::Error& error) { std::lock_guard lock(this->session_info_mutex); + using Event = types::evse_manager::SessionEventEnum; + + if (event == Event::Enabled) { + this->state = State::Unplugged; + } else if (event == Event::Disabled) { + this->state = State::Disabled; + } else if (event == Event::SessionStarted) { + this->state = State::Preparing; + } else if (event == Event::ReservationStart) { + this->state = State::Reserved; + } else if (event == Event::ReservationEnd) { + this->state = State::Unplugged; + } else if (event == Event::AuthRequired) { + this->state = State::AuthRequired; + } else if (event == Event::WaitingForEnergy) { + this->state = State::WaitingForEnergy; + } else if (event == Event::TransactionStarted) { + this->state = State::Preparing; + } else if (event == Event::ChargingPausedEV) { + this->state = State::ChargingPausedEV; + } else if (event == Event::ChargingPausedEVSE) { + this->state = State::ChargingPausedEVSE; + } else if (event == Event::ChargingStarted) { + this->state = State::Charging; + } else if (event == Event::ChargingResumed) { + this->state = State::Charging; + } else if (event == Event::TransactionFinished) { + this->state = State::Finished; + } else if (event == Event::SessionFinished) { + this->state = State::Unplugged; + } else if (event == Event::PermanentFault) { + this->active_permanent_faults.push_back(error); + } else if (event == Event::Error) { + this->active_errors.push_back(error); + } else if (event == Event::PermanentFaultCleared or event == Event::ErrorCleared) { + remove_error_from_list(this->active_permanent_faults, error.type); + } else if (event == Event::AllErrorsCleared) { + this->active_permanent_faults.clear(); + this->active_errors.clear(); + } +} - this->state_info = state_info; - if (event == "Enabled") { - this->state = "Unplugged"; - } else if (event == "Disabled") { - this->state = "Disabled"; - } else if (event == "SessionStarted") { - this->state = "Preparing"; - } else if (event == "ReservationStart") { - this->state = "Reserved"; - } else if (event == "ReservationEnd") { - this->state = "Unplugged"; - } else if (event == "AuthRequired") { - this->state = "AuthRequired"; - } else if (event == "WaitingForEnergy") { - this->state = "WaitingForEnergy"; - } else if (event == "TransactionStarted") { - this->state = "Preparing"; - } else if (event == "ChargingPausedEV") { - this->state = "ChargingPausedEV"; - } else if (event == "ChargingPausedEVSE") { - this->state = "ChargingPausedEVSE"; - } else if (event == "ChargingStarted") { - this->state = "Charging"; - } else if (event == "ChargingResumed") { - this->state = "Charging"; - } else if (event == "TransactionFinished") { - this->state = "Finished"; - } else if (event == "SessionFinished") { - this->state = "Unplugged"; - } else if (event == "Error") { - this->state = "Error"; - } else if (event == "PermanentFault") { - this->state = "PermanentFault"; +std::string SessionInfo::state_to_string(SessionInfo::State s) { + switch (s) { + case SessionInfo::State::Unplugged: + return "Unplugged"; + case SessionInfo::State::Disabled: + return "Disabled"; + case SessionInfo::State::Preparing: + return "Preparing"; + case SessionInfo::State::Reserved: + return "Reserved"; + case SessionInfo::State::AuthRequired: + return "AuthRequired"; + case SessionInfo::State::WaitingForEnergy: + return "WaitingForEnergy"; + case SessionInfo::State::ChargingPausedEV: + return "ChargingPausedEV"; + case SessionInfo::State::ChargingPausedEVSE: + return "ChargingPausedEVSE"; + case SessionInfo::State::Charging: + return "Charging"; + case SessionInfo::State::Finished: + return "Finished"; } + return "Unknown"; } void SessionInfo::set_start_energy_import_wh(int32_t start_energy_import_wh) { @@ -152,6 +190,10 @@ void SessionInfo::set_latest_total_w(double latest_total_w) { this->latest_total_w = latest_total_w; } +static void to_json(json& j, const SessionInfo::Error& e) { + j = json{{"type", e.type}, {"description", e.description}, {"severity", e.severity}}; +} + SessionInfo::operator std::string() { std::lock_guard lock(this->session_info_mutex); @@ -165,8 +207,9 @@ SessionInfo::operator std::string() { auto charging_duration_s = std::chrono::duration_cast(this->end_time_point - this->start_time_point); - json session_info = json::object({{"state", this->state}, - {"state_info", this->state_info}, + json session_info = json::object({{"state", state_to_string(this->state)}, + {"active_permanent_faults", this->active_permanent_faults}, + {"active_errors", this->active_errors}, {"charged_energy_wh", charged_energy_wh}, {"discharged_energy_wh", discharged_energy_wh}, {"latest_total_w", this->latest_total_w}, @@ -252,12 +295,15 @@ void API::init() { evse->subscribe_session_event( [this, var_session_info, var_logging_path, &session_info](types::evse_manager::SessionEvent session_event) { - auto event = types::evse_manager::session_event_enum_to_string(session_event.event); - std::string state_info = ""; + SessionInfo::Error error; if (session_event.error.has_value()) { - state_info = types::evse_manager::error_enum_to_string(session_event.error.value().error_code); + error.type = types::evse_manager::error_enum_to_string(session_event.error.value().error_code); + error.description = session_event.error.value().error_description; + error.severity = + types::evse_manager::error_severity_to_string(session_event.error.value().error_severity); } - session_info->update_state(event, state_info); + + session_info->update_state(session_event.event, error); if (session_event.event == types::evse_manager::SessionEventEnum::SessionStarted) { if (session_event.session_started.has_value()) { diff --git a/modules/API/API.hpp b/modules/API/API.hpp index cb2fc1ece..fafbf147f 100644 --- a/modules/API/API.hpp +++ b/modules/API/API.hpp @@ -34,31 +34,22 @@ namespace module { class LimitDecimalPlaces; class SessionInfo { -private: - std::mutex session_info_mutex; - - std::string state; ///< Latest state of the EVSE - std::string state_info; ///< Additional information of this state - int32_t start_energy_import_wh; ///< Energy reading (import) at the beginning of this charging session in Wh - int32_t end_energy_import_wh; ///< Energy reading (import) at the end of this charging session in Wh - int32_t start_energy_export_wh; ///< Energy reading (export) at the beginning of this charging session in Wh - int32_t end_energy_export_wh; ///< Energy reading (export) at the end of this charging session in Wh - std::chrono::time_point start_time_point; ///< Start of the charging session - std::chrono::time_point end_time_point; ///< End of the charging session - double latest_total_w; ///< Latest total power reading in W - - bool is_state_charging(const std::string& current_state); - public: SessionInfo(); + struct Error { + std::string type; + std::string description; + std::string severity; + }; + bool start_energy_export_wh_was_set{ false}; ///< Indicate if start export energy value (optional) has been received or not bool end_energy_export_wh_was_set{ false}; ///< Indicate if end export energy value (optional) has been received or not void reset(); - void update_state(const std::string& event, const std::string& state_info); + void update_state(const types::evse_manager::SessionEventEnum event, const SessionInfo::Error& error); void set_start_energy_import_wh(int32_t start_energy_import_wh); void set_end_energy_import_wh(int32_t end_energy_import_wh); void set_latest_energy_import_wh(int32_t latest_energy_wh); @@ -69,6 +60,37 @@ class SessionInfo { /// \brief Converts this struct into a serialized json object operator std::string(); + +private: + std::mutex session_info_mutex; + + std::vector active_permanent_faults; ///< Array of currently active permanent faults that prevent charging + std::vector active_errors; ///< Array of currently active errors that do not prevent charging + int32_t start_energy_import_wh; ///< Energy reading (import) at the beginning of this charging session in Wh + int32_t end_energy_import_wh; ///< Energy reading (import) at the end of this charging session in Wh + int32_t start_energy_export_wh; ///< Energy reading (export) at the beginning of this charging session in Wh + int32_t end_energy_export_wh; ///< Energy reading (export) at the end of this charging session in Wh + std::chrono::time_point start_time_point; ///< Start of the charging session + std::chrono::time_point end_time_point; ///< End of the charging session + double latest_total_w; ///< Latest total power reading in W + + enum class State { + Unknown, + Unplugged, + Disabled, + Preparing, + Reserved, + AuthRequired, + WaitingForEnergy, + ChargingPausedEV, + ChargingPausedEVSE, + Charging, + Finished + } state; + + bool is_state_charging(const SessionInfo::State current_state); + + std::string state_to_string(State s); }; } // namespace module // ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1 diff --git a/modules/API/README.md b/modules/API/README.md index 1c8af8952..7bef91468 100644 --- a/modules/API/README.md +++ b/modules/API/README.md @@ -44,10 +44,37 @@ This variable is published every second and contains a json object with informat "discharged_energy_wh": 0, "latest_total_w": 0.0, "state": "Unplugged", - "state_info": "" + "active_permanent_faults": [], + "active_errors": [] } ``` +Example with permanent faults being active: + +```json +{ + "active_errors": [], + "active_permanent_faults": [ + { + "description": "The control pilot voltage is out of range.", + "severity": "High", + "type": "MREC14PilotFault" + }, + { + "description": "The vehicle is in an invalid mode for charging (Reported by IEC stack)", + "severity": "High", + "type": "MREC10InvalidVehicleMode" + } + ], + "charged_energy_wh": 0, + "charging_duration_s": 0, + "datetime": "2024-01-15T14:58:15.172Z", + "discharged_energy_wh": 0, + "latest_total_w": 0, + "state": "Preparing" +} +``` + - **charged_energy_wh** contains the charged energy in Wh - **charging_duration_s** contains the duration of the current charging session in seconds - **datetime** contains a string representation of the current UTC datetime in RFC3339 format @@ -64,20 +91,44 @@ This variable is published every second and contains a json object with informat - ChargingPausedEV - ChargingPausedEVSE - Finished - - Error - - PermanentFault - -- **state_info** contains additional information for the current state, at the moment this is only set to a meaningful value in the Error state. Here it can have the following values: - - Car - - CarDiodeFault - - Relais - - RCD +- **active_permanent_faults** array of all active errors that are permanent faults (i.e. that block charging). If anything is set here it should be shown as an error to the user instead of showing the current state: + - RCD_Selftest + - RCD_DC + - RCD_AC + - VendorError + - VendorWarning + - ConnectorLockCapNotCharged + - ConnectorLockUnexpectedOpen + - ConnectorLockUnexpectedClose + - ConnectorLockFailedLock + - ConnectorLockFailedUnlock + - MREC1ConnectorLockFailure + - MREC2GroundFailure + - MREC3HighTemperature + - MREC4OverCurrentFailure + - MREC5OverVoltage + - MREC6UnderVoltage + - MREC8EmergencyStop + - MREC10InvalidVehicleMode + - MREC14PilotFault + - MREC15PowerLoss + - MREC17EVSEContactorFault + - MREC18CableOverTempDerate + - MREC19CableOverTempStop + - MREC20PartialInsertion + - MREC23ProximityFault + - MREC24ConnectorVoltageHigh + - MREC25BrokenLatch + - MREC26CutCable + - DiodeFault - VentilationNotAvailable - - OverCurrent - - Internal - - SLAC - - HLC + - BrownOut + - EnergyManagement + - PermanentFault + - PowermeterTransactionStartFailed + +- **active_errors** array of all active errors that do not block charging. This could be shown to the user but the current state should still be shown as it does not interfere with charging. The enum is the same as for active_permanent_faults. ### everest_api/evse_manager/var/limits This variable is published every second and contains a json object with information relating to the current limits of this EVSE. diff --git a/modules/EvseManager/Charger.cpp b/modules/EvseManager/Charger.cpp index c29876eb3..5b995c2ea 100644 --- a/modules/EvseManager/Charger.cpp +++ b/modules/EvseManager/Charger.cpp @@ -47,7 +47,7 @@ Charger::Charger(const std::unique_ptr& bsp, const std::unique_ hlc_use_5percent_current_session = false; // Register callbacks for errors/error clearings - error_handling->signal_error.connect([this](const types::evse_manager::ErrorEnum e, const bool prevent_charging) { + error_handling->signal_error.connect([this](const types::evse_manager::Error e, const bool prevent_charging) { std::scoped_lock lock(stateMutex); if (prevent_charging) { error_prevent_charging_flag = true; diff --git a/modules/EvseManager/ErrorHandling.cpp b/modules/EvseManager/ErrorHandling.cpp index 9ab87fa97..ab2e8f3ae 100644 --- a/modules/EvseManager/ErrorHandling.cpp +++ b/modules/EvseManager/ErrorHandling.cpp @@ -5,6 +5,18 @@ namespace module { +static types::evse_manager::Error_severity to_evse_manager_severity(Everest::error::Severity s) { + switch (s) { + case Everest::error::Severity::High: + return types::evse_manager::Error_severity::High; + case Everest::error::Severity::Medium: + return types::evse_manager::Error_severity::Medium; + case Everest::error::Severity::Low: + return types::evse_manager::Error_severity::Low; + } + return types::evse_manager::Error_severity::Low; +} + ErrorHandling::ErrorHandling(const std::unique_ptr& _r_bsp, const std::vector>& _r_hlc, const std::vector>& _r_connector_lock, @@ -20,17 +32,35 @@ ErrorHandling::ErrorHandling(const std::unique_ptr& _r_b r_bsp->subscribe_all_errors( [this](const Everest::error::Error& error) { types::evse_manager::ErrorEnum evse_error{types::evse_manager::ErrorEnum::VendorWarning}; + types::evse_manager::Error output_error; + output_error.error_description = error.description; + output_error.error_severity = to_evse_manager_severity(error.severity); + if (modify_error_bsp(error, true, evse_error)) { // signal to charger a new error has been set that prevents charging - signal_error(evse_error, true); + output_error.error_code = evse_error; + signal_error(output_error, true); } else { // signal an error that does not prevent charging - signal_error(evse_error, false); + output_error.error_code = evse_error; + signal_error(output_error, false); } }, [this](const Everest::error::Error& error) { types::evse_manager::ErrorEnum evse_error{types::evse_manager::ErrorEnum::VendorWarning}; - modify_error_bsp(error, false, evse_error); + types::evse_manager::Error output_error; + output_error.error_description = error.description; + output_error.error_severity = to_evse_manager_severity(error.severity); + + if (modify_error_bsp(error, false, evse_error)) { + // signal to charger an error has been cleared that prevents charging + output_error.error_code = evse_error; + signal_error_cleared(output_error, true); + } else { + // signal an error cleared that does not prevent charging + output_error.error_code = evse_error; + signal_error_cleared(output_error, false); + } if (active_errors.all_cleared()) { // signal to charger that all errors are cleared now @@ -47,17 +77,35 @@ ErrorHandling::ErrorHandling(const std::unique_ptr& _r_b r_connector_lock[0]->subscribe_all_errors( [this](const Everest::error::Error& error) { types::evse_manager::ErrorEnum evse_error{types::evse_manager::ErrorEnum::VendorWarning}; + types::evse_manager::Error output_error; + output_error.error_description = error.description; + output_error.error_severity = to_evse_manager_severity(error.severity); + if (modify_error_connector_lock(error, true, evse_error)) { // signal to charger a new error has been set that prevents charging - signal_error(evse_error, true); + output_error.error_code = evse_error; + signal_error(output_error, true); } else { // signal an error that does not prevent charging - signal_error(evse_error, false); + output_error.error_code = evse_error; + signal_error(output_error, false); } }, [this](const Everest::error::Error& error) { types::evse_manager::ErrorEnum evse_error{types::evse_manager::ErrorEnum::VendorWarning}; - modify_error_connector_lock(error, false, evse_error); + types::evse_manager::Error output_error; + output_error.error_description = error.description; + output_error.error_severity = to_evse_manager_severity(error.severity); + + if (modify_error_connector_lock(error, false, evse_error)) { + // signal to charger an error has been cleared that prevents charging + output_error.error_code = evse_error; + signal_error_cleared(output_error, true); + } else { + // signal an error cleared that does not prevent charging + output_error.error_code = evse_error; + signal_error_cleared(output_error, false); + } if (active_errors.all_cleared()) { // signal to charger that all errors are cleared now @@ -75,17 +123,35 @@ ErrorHandling::ErrorHandling(const std::unique_ptr& _r_b r_ac_rcd[0]->subscribe_all_errors( [this](const Everest::error::Error& error) { types::evse_manager::ErrorEnum evse_error{types::evse_manager::ErrorEnum::VendorWarning}; + types::evse_manager::Error output_error; + output_error.error_description = error.description; + output_error.error_severity = to_evse_manager_severity(error.severity); + if (modify_error_ac_rcd(error, true, evse_error)) { // signal to charger a new error has been set that prevents charging - signal_error(evse_error, true); + output_error.error_code = evse_error; + signal_error(output_error, true); } else { // signal an error that does not prevent charging - signal_error(evse_error, false); + output_error.error_code = evse_error; + signal_error(output_error, false); } }, [this](const Everest::error::Error& error) { types::evse_manager::ErrorEnum evse_error{types::evse_manager::ErrorEnum::VendorWarning}; - modify_error_ac_rcd(error, false, evse_error); + types::evse_manager::Error output_error; + output_error.error_description = error.description; + output_error.error_severity = to_evse_manager_severity(error.severity); + + if (modify_error_ac_rcd(error, false, evse_error)) { + // signal to charger an error has been cleared that prevents charging + output_error.error_code = evse_error; + signal_error_cleared(output_error, true); + } else { + // signal an error cleared that does not prevent charging + output_error.error_code = evse_error; + signal_error_cleared(output_error, false); + } if (active_errors.all_cleared()) { // signal to charger that all errors are cleared now @@ -106,7 +172,11 @@ void ErrorHandling::raise_overcurrent_error(const std::string& description) { if (modify_error_evse_manager("evse_manager/MREC4OverCurrentFailure", true, evse_error)) { // signal to charger a new error has been set - signal_error(evse_error, true); + types::evse_manager::Error output_error; + output_error.error_description = description; + output_error.error_severity = types::evse_manager::Error_severity::High; + output_error.error_code = types::evse_manager::ErrorEnum::MREC4OverCurrentFailure; + signal_error(output_error, true); }; } @@ -114,8 +184,20 @@ void ErrorHandling::clear_overcurrent_error() { // clear externally p_evse->request_clear_all_evse_manager_MREC4OverCurrentFailure(); types::evse_manager::ErrorEnum evse_error{types::evse_manager::ErrorEnum::VendorWarning}; - - modify_error_evse_manager("evse_manager/MREC4OverCurrentFailure", false, evse_error); + types::evse_manager::Error output_error; + output_error.error_description = ""; + output_error.error_severity = types::evse_manager::Error_severity::High; + output_error.error_code = types::evse_manager::ErrorEnum::MREC4OverCurrentFailure; + + if (modify_error_evse_manager("evse_manager/MREC4OverCurrentFailure", false, evse_error)) { + // signal to charger an error has been cleared that prevents charging + output_error.error_code = evse_error; + signal_error_cleared(output_error, true); + } else { + // signal an error cleared that does not prevent charging + output_error.error_code = evse_error; + signal_error_cleared(output_error, false); + } if (active_errors.all_cleared()) { // signal to charger that all errors are cleared now @@ -134,7 +216,11 @@ void ErrorHandling::raise_internal_error(const std::string& description) { if (modify_error_evse_manager("evse_manager/Internal", true, evse_error)) { // signal to charger a new error has been set - signal_error(evse_error, true); + types::evse_manager::Error output_error; + output_error.error_description = description; + output_error.error_severity = types::evse_manager::Error_severity::High; + output_error.error_code = types::evse_manager::ErrorEnum::VendorError; + signal_error(output_error, true); }; } @@ -142,8 +228,20 @@ void ErrorHandling::clear_internal_error() { // clear externally p_evse->request_clear_all_evse_manager_Internal(); types::evse_manager::ErrorEnum evse_error{types::evse_manager::ErrorEnum::VendorWarning}; - - modify_error_evse_manager("evse_manager/Internal", false, evse_error); + types::evse_manager::Error output_error; + output_error.error_description = ""; + output_error.error_severity = types::evse_manager::Error_severity::High; + output_error.error_code = types::evse_manager::ErrorEnum::VendorError; + + if (modify_error_evse_manager("evse_manager/Internal", false, evse_error)) { + // signal to charger an error has been cleared that prevents charging + output_error.error_code = evse_error; + signal_error_cleared(output_error, true); + } else { + // signal an error cleared that does not prevent charging + output_error.error_code = evse_error; + signal_error_cleared(output_error, false); + } if (active_errors.all_cleared()) { // signal to charger that all errors are cleared now @@ -162,7 +260,11 @@ void ErrorHandling::raise_powermeter_transaction_start_failed_error(const std::s if (modify_error_evse_manager("evse_manager/PowermeterTransactionStartFailed", true, evse_error)) { // signal to charger a new error has been set - signal_error(evse_error, true); + types::evse_manager::Error output_error; + output_error.error_description = description; + output_error.error_severity = types::evse_manager::Error_severity::High; + output_error.error_code = types::evse_manager::ErrorEnum::PowermeterTransactionStartFailed; + signal_error(output_error, true); }; } @@ -170,8 +272,20 @@ void ErrorHandling::clear_powermeter_transaction_start_failed_error() { // clear externally p_evse->request_clear_all_evse_manager_PowermeterTransactionStartFailed(); types::evse_manager::ErrorEnum evse_error{types::evse_manager::ErrorEnum::VendorWarning}; - - modify_error_evse_manager("evse_manager/PowermeterTransactionStartFailed", false, evse_error); + types::evse_manager::Error output_error; + output_error.error_description = ""; + output_error.error_severity = types::evse_manager::Error_severity::High; + output_error.error_code = types::evse_manager::ErrorEnum::VendorError; + + if (modify_error_evse_manager("evse_manager/PowermeterTransactionStartFailed", false, evse_error)) { + // signal to charger an error has been cleared that prevents charging + output_error.error_code = evse_error; + signal_error_cleared(output_error, true); + } else { + // signal an error cleared that does not prevent charging + output_error.error_code = evse_error; + signal_error_cleared(output_error, false); + } if (active_errors.all_cleared()) { // signal to charger that all errors are cleared now diff --git a/modules/EvseManager/ErrorHandling.hpp b/modules/EvseManager/ErrorHandling.hpp index dfc6e5b5a..ce2ff5927 100644 --- a/modules/EvseManager/ErrorHandling.hpp +++ b/modules/EvseManager/ErrorHandling.hpp @@ -110,8 +110,11 @@ class ErrorHandling { const std::vector>& r_ac_rcd, const std::unique_ptr& _p_evse); - // Signal for internal events type - sigslot::signal signal_error; + // Signal that one error has been raised. Bool argument is true if it preventing charging. + sigslot::signal signal_error; + // Signal that one error has been cleared. Bool argument is true if it was preventing charging. + sigslot::signal signal_error_cleared; + // Signal that all errors are cleared (both those preventing charging and not) sigslot::signal<> signal_all_errors_cleared; void raise_overcurrent_error(const std::string& description); diff --git a/modules/EvseManager/evse/evse_managerImpl.cpp b/modules/EvseManager/evse/evse_managerImpl.cpp index 5561a5d69..73590e2d2 100644 --- a/modules/EvseManager/evse/evse_managerImpl.cpp +++ b/modules/EvseManager/evse/evse_managerImpl.cpp @@ -97,19 +97,31 @@ void evse_managerImpl::set_session_uuid() { void evse_managerImpl::ready() { // Register callbacks for errors/permanent faults - mod->error_handling->signal_error.connect( - [this](const types::evse_manager::ErrorEnum e, const bool prevent_charging) { + mod->error_handling->signal_error.connect([this](const types::evse_manager::Error e, const bool prevent_charging) { + types::evse_manager::SessionEvent se; + + se.error = e; + se.uuid = session_uuid; + + if (prevent_charging) { + se.event = types::evse_manager::SessionEventEnum::PermanentFault; + } else { + se.event = types::evse_manager::SessionEventEnum::Error; + } + publish_session_event(se); + }); + + mod->error_handling->signal_error_cleared.connect( + [this](const types::evse_manager::Error e, const bool prevent_charging) { types::evse_manager::SessionEvent se; - types::evse_manager::Error error; - error.error_code = e; - se.error = error; + se.error = e; se.uuid = session_uuid; if (prevent_charging) { - se.event = types::evse_manager::SessionEventEnum::PermanentFault; + se.event = types::evse_manager::SessionEventEnum::PermanentFaultCleared; } else { - se.event = types::evse_manager::SessionEventEnum::Error; + se.event = types::evse_manager::SessionEventEnum::ErrorCleared; } publish_session_event(se); }); diff --git a/types/evse_manager.yaml b/types/evse_manager.yaml index 382ba58fb..9e083f739 100644 --- a/types/evse_manager.yaml +++ b/types/evse_manager.yaml @@ -128,8 +128,10 @@ types: - TransactionFinished - SessionFinished - Error + - ErrorCleared - AllErrorsCleared - PermanentFault + - PermanentFaultCleared - ReservationStart - ReservationEnd - ReplugStarted @@ -269,11 +271,23 @@ types: additionalProperties: false required: - error_code + - error_description + - error_severity properties: error_code: description: The error enum type: string $ref: /evse_manager#/ErrorEnum + error_description: + description: Description of the error (human readable) + type: string + error_severity: + description: Severity of the error + type: string + enum: + - High + - Medium + - Low vendor_error: description: The error code of the vendor type: string