diff --git a/modules/API/API.cpp b/modules/API/API.cpp index 02cb39b10..f1447c10f 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::Unplugged), 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::Unplugged; + 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,72 @@ 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) { +void SessionInfo::update_state(const types::evse_manager::SessionEventEnum event, const std::string& error_type) { 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_type); + } else if (event == Event::Error) { + this->active_errors.push_back(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) { @@ -165,8 +195,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 +283,11 @@ 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 = ""; if (session_event.error.has_value()) { state_info = types::evse_manager::error_enum_to_string(session_event.error.value().error_code); } - session_info->update_state(event, state_info); + session_info->update_state(session_event.event, state_info); 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..70e40a792 100644 --- a/modules/API/API.hpp +++ b/modules/API/API.hpp @@ -37,8 +37,10 @@ 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 + 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 @@ -47,7 +49,22 @@ class SessionInfo { 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); + enum class State { + 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); public: SessionInfo(); @@ -58,7 +75,7 @@ class SessionInfo { 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 std::string& state_info); 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); diff --git a/modules/API/README.md b/modules/API/README.md index 1c8af8952..35d1ee17e 100644 --- a/modules/API/README.md +++ b/modules/API/README.md @@ -44,7 +44,8 @@ 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": "", } ``` @@ -64,20 +65,10 @@ 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 - - VentilationNotAvailable - - OverCurrent - - Internal - - SLAC - - HLC + +- **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. + +- **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. ### 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.