// SPDX-License-Identifier: Apache-2.0 // Copyright Pionix GmbH and Contributors to EVerest #include "SessionInfo.hpp" namespace data { static void to_json(json& j, const SessionInfoStore::Error& e) { j = json{{"type", e.type}, {"description", e.description}, {"severity", e.severity}}; } SessionInfoStore::SessionInfoStore() : start_energy_import_wh(0), end_energy_import_wh(0), start_energy_export_wh(0), end_energy_export_wh(0), latest_total_w(0), state(State::Unknown) { this->start_time_point = date::utc_clock::now(); this->end_time_point = this->start_time_point; uk_random_delay_remaining.countdown_s = 0; uk_random_delay_remaining.current_limit_after_delay_A = 0.; uk_random_delay_remaining.current_limit_during_delay_A = 0; } bool SessionInfoStore::is_state_charging(const SessionInfoStore::State current_state) { if (current_state == State::AuthRequired || current_state == State::Charging || current_state == State::ChargingPausedEV || current_state == State::ChargingPausedEVSE) { return true; } return false; } void SessionInfoStore::reset() { std::lock_guard lock(this->session_info_mutex); this->state = State::Unknown; this->start_energy_import_wh = 0; this->end_energy_import_wh = 0; this->start_energy_export_wh = 0; this->end_energy_export_wh = 0; this->start_time_point = date::utc_clock::now(); this->latest_total_w = 0; this->permanent_fault = false; } void SessionInfoStore::update_state(const types::evse_manager::SessionEvent event) { std::lock_guard lock(this->session_info_mutex); using Event = types::evse_manager::SessionEventEnum; // using switch since some code analysis tools can detect missing cases // (when new events are added) switch (event.event) { case Event::Enabled: this->state = State::Unplugged; break; case Event::Disabled: this->state = State::Disabled; break; case Event::AuthRequired: this->state = State::AuthRequired; break; case Event::Authorized: [[fallthrough]]; case Event::PrepareCharging: [[fallthrough]]; case Event::SessionStarted: [[fallthrough]]; case Event::SessionResumed: [[fallthrough]]; case Event::TransactionStarted: this->state = State::Preparing; break; case Event::ChargingStarted: this->state = State::Charging; break; case Event::ChargingPausedEV: this->state = State::ChargingPausedEV; break; case Event::ChargingPausedEVSE: this->state = State::ChargingPausedEVSE; break; case Event::ChargingFinished: this->state = State::Finished; break; case Event::StoppingCharging: this->state = State::FinishedEV; break; case Event::TransactionFinished: { if (event.transaction_finished->reason == types::evse_manager::StopTransactionReason::Local) { this->state = State::FinishedEVSE; } else { this->state = State::Finished; } break; } case Event::PluginTimeout: this->state = State::AuthTimeout; break; case Event::ReservationStart: this->state = State::Reserved; break; case Event::ReservationEnd: [[fallthrough]]; case Event::SessionFinished: this->state = State::Unplugged; break; /// explicitly fall through all the SessionEventEnum values we are not handling case Event::Deauthorized: [[fallthrough]]; case Event::SwitchingPhases: [[fallthrough]]; default: break; } } void SessionInfoStore::set_start_energy_import_wh(int32_t start_energy_import_wh) { std::lock_guard lock(this->session_info_mutex); this->start_energy_import_wh = start_energy_import_wh; this->end_energy_import_wh = start_energy_import_wh; this->start_time_point = date::utc_clock::now(); this->end_time_point = this->start_time_point; } void SessionInfoStore::set_end_energy_import_wh(int32_t end_energy_import_wh) { std::lock_guard lock(this->session_info_mutex); this->end_energy_import_wh = end_energy_import_wh; this->end_time_point = date::utc_clock::now(); } void SessionInfoStore::set_latest_energy_import_wh(int32_t latest_energy_wh) { std::lock_guard lock(this->session_info_mutex); if (this->is_state_charging(this->state)) { this->end_time_point = date::utc_clock::now(); this->end_energy_import_wh = latest_energy_wh; } } void SessionInfoStore::set_start_energy_export_wh(int32_t start_energy_export_wh) { std::lock_guard lock(this->session_info_mutex); this->start_energy_export_wh = start_energy_export_wh; this->end_energy_export_wh = start_energy_export_wh; this->start_energy_export_wh_was_set = true; } void SessionInfoStore::set_end_energy_export_wh(int32_t end_energy_export_wh) { std::lock_guard lock(this->session_info_mutex); this->end_energy_export_wh = end_energy_export_wh; this->end_energy_export_wh_was_set = true; } void SessionInfoStore::set_latest_energy_export_wh(int32_t latest_export_energy_wh) { std::lock_guard lock(this->session_info_mutex); if (this->is_state_charging(this->state)) { this->end_energy_export_wh = latest_export_energy_wh; this->end_energy_export_wh_was_set = true; } } void SessionInfoStore::set_latest_total_w(double latest_total_w) { std::lock_guard lock(this->session_info_mutex); this->latest_total_w = latest_total_w; } void SessionInfoStore::set_uk_random_delay_remaining(const types::uk_random_delay::CountDown& cd) { std::lock_guard lock(this->session_info_mutex); this->uk_random_delay_remaining = cd; } void SessionInfoStore::set_enable_disable_source(const std::string& active_source, const std::string& active_state, const int active_priority) { std::lock_guard lock(this->session_info_mutex); this->active_enable_disable_source = active_source; this->active_enable_disable_state = active_state; this->active_enable_disable_priority = active_priority; } float SessionInfoStore::get_charged_energy_wh() const { std::lock_guard lock(this->session_info_mutex); return this->end_energy_import_wh - this->start_energy_import_wh; } float SessionInfoStore::get_discharged_energy_wh() const { std::lock_guard lock(this->session_info_mutex); if (this->start_energy_export_wh_was_set && this->end_energy_export_wh_was_set) { return this->end_energy_export_wh - this->start_energy_export_wh; } return 0.0f; // No discharged energy if export values are not set } std::chrono::seconds SessionInfoStore::get_charging_duration_s() const { std::lock_guard lock(this->session_info_mutex); return std::chrono::duration_cast(this->end_time_point - this->start_time_point); } } // namespace data