From b7a727df7ba4a5b61f8d5d75eedd2b172484b03b Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Tue, 1 Oct 2024 19:28:35 +0200 Subject: [PATCH 01/22] Add simple EvAPI and extend EvManager with simplistic SoC calculation Signed-off-by: Kai-Uwe Hermann --- config/config-sil.yaml | 6 + interfaces/ev_manager.yaml | 24 ++ modules/CMakeLists.txt | 1 + modules/EvAPI/CMakeLists.txt | 21 ++ modules/EvAPI/EvAPI.cpp | 210 ++++++++++++++++++ modules/EvAPI/EvAPI.hpp | 144 ++++++++++++ modules/EvAPI/README.md | 2 + modules/EvAPI/main/emptyImpl.cpp | 16 ++ modules/EvAPI/main/emptyImpl.hpp | 60 +++++ modules/EvAPI/manifest.yaml | 22 ++ modules/EvManager/CMakeLists.txt | 1 + modules/EvManager/EvManager.cpp | 2 + modules/EvManager/EvManager.hpp | 7 +- .../EvManager/ev_manager/ev_managerImpl.cpp | 16 ++ .../EvManager/ev_manager/ev_managerImpl.hpp | 60 +++++ modules/EvManager/main/car_simulation.cpp | 68 ++++++ modules/EvManager/main/car_simulation.hpp | 25 ++- modules/EvManager/main/car_simulatorImpl.cpp | 7 +- modules/EvManager/main/simulation_data.hpp | 3 + modules/EvManager/manifest.yaml | 7 + modules/simulation/JsYetiSimulator/index.js | 4 + 21 files changed, 702 insertions(+), 4 deletions(-) create mode 100644 interfaces/ev_manager.yaml create mode 100644 modules/EvAPI/CMakeLists.txt create mode 100644 modules/EvAPI/EvAPI.cpp create mode 100644 modules/EvAPI/EvAPI.hpp create mode 100644 modules/EvAPI/README.md create mode 100644 modules/EvAPI/main/emptyImpl.cpp create mode 100644 modules/EvAPI/main/emptyImpl.hpp create mode 100644 modules/EvAPI/manifest.yaml create mode 100644 modules/EvManager/ev_manager/ev_managerImpl.cpp create mode 100644 modules/EvManager/ev_manager/ev_managerImpl.hpp diff --git a/config/config-sil.yaml b/config/config-sil.yaml index eb6b994b7..0ab5e13d8 100644 --- a/config/config-sil.yaml +++ b/config/config-sil.yaml @@ -10,6 +10,12 @@ active_modules: - module_id: error_history implementation_id: error_history module: API + ev_api: + connections: + ev_manager: + - implementation_id: ev_manager + module_id: ev_manager + module: EvAPI error_history: module: ErrorHistory config_implementation: diff --git a/interfaces/ev_manager.yaml b/interfaces/ev_manager.yaml new file mode 100644 index 000000000..7ed3b0ba0 --- /dev/null +++ b/interfaces/ev_manager.yaml @@ -0,0 +1,24 @@ +description: >- + This interface defines the ev manager. An ev manager represents the + charging logic of the ev side +cmds: {} +vars: + session_event: + description: Emits all events related to sessions + type: object + $ref: /evse_manager#/SessionEvent + ev_info: + description: More details about the EV if available + type: object + $ref: /evse_manager#/EVInfo + bsp_event: + description: >- + Events from CP/Relais + type: object + $ref: /board_support_common#/BspEvent + car_manufacturer: + description: Car manufacturer (if known) + type: string + $ref: /evse_manager#/CarManufacturer +errors: + - reference: /errors/evse_manager \ No newline at end of file diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 859a06da0..83b1b3715 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -2,6 +2,7 @@ ev_add_module(API) ev_add_module(Auth) ev_add_module(EnergyManager) ev_add_module(EnergyNode) +ev_add_module(EvAPI) ev_add_module(EvManager) ev_add_module(ErrorHistory) ev_add_module(Evse15118D20) diff --git a/modules/EvAPI/CMakeLists.txt b/modules/EvAPI/CMakeLists.txt new file mode 100644 index 000000000..06aa45c75 --- /dev/null +++ b/modules/EvAPI/CMakeLists.txt @@ -0,0 +1,21 @@ +# +# AUTO GENERATED - MARKED REGIONS WILL BE KEPT +# template version 3 +# + +# module setup: +# - ${MODULE_NAME}: module name +ev_setup_cpp_module() + +# ev@bcc62523-e22b-41d7-ba2f-825b493a3c97:v1 +# insert your custom targets and additional config variables here +# ev@bcc62523-e22b-41d7-ba2f-825b493a3c97:v1 + +target_sources(${MODULE_NAME} + PRIVATE + "main/emptyImpl.cpp" +) + +# ev@c55432ab-152c-45a9-9d2e-7281d50c69c3:v1 +# insert other things like install cmds etc here +# ev@c55432ab-152c-45a9-9d2e-7281d50c69c3:v1 diff --git a/modules/EvAPI/EvAPI.cpp b/modules/EvAPI/EvAPI.cpp new file mode 100644 index 000000000..838a3bda3 --- /dev/null +++ b/modules/EvAPI/EvAPI.cpp @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2020 - 2022 Pionix GmbH and Contributors to EVerest +#include "EvAPI.hpp" +#include +#include + +namespace module { + +static const auto NOTIFICATION_PERIOD = std::chrono::seconds(1); + +SessionInfo::SessionInfo() : + 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("Unknown") { + this->start_time_point = date::utc_clock::now(); + this->end_time_point = this->start_time_point; +} + +void SessionInfo::reset() { + std::lock_guard lock(this->session_info_mutex); + this->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; +} + +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 std::string& event) { + std::lock_guard lock(this->session_info_mutex); + this->state = event; +} + +void SessionInfo::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 SessionInfo::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 SessionInfo::set_latest_energy_import_wh(int32_t latest_energy_wh) { +} + +void SessionInfo::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 SessionInfo::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 SessionInfo::set_latest_energy_export_wh(int32_t latest_export_energy_wh) { + std::lock_guard lock(this->session_info_mutex); +} + +void SessionInfo::set_latest_total_w(double latest_total_w) { + std::lock_guard lock(this->session_info_mutex); + this->latest_total_w = latest_total_w; +} + +void SessionInfo::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; +} + +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); + + auto charged_energy_wh = this->end_energy_import_wh - this->start_energy_import_wh; + int32_t discharged_energy_wh{0}; + if ((this->start_energy_export_wh_was_set == true) && (this->end_energy_export_wh_was_set == true)) { + discharged_energy_wh = this->end_energy_export_wh - this->start_energy_export_wh; + } + auto now = date::utc_clock::now(); + + auto charging_duration_s = + std::chrono::duration_cast(this->end_time_point - this->start_time_point); + + json session_info = json::object({ + {"state", this->state}, + {"permanent_fault", this->permanent_fault}, + {"charged_energy_wh", charged_energy_wh}, + {"discharged_energy_wh", discharged_energy_wh}, + {"latest_total_w", this->latest_total_w}, + {"charging_duration_s", charging_duration_s.count()}, + {"datetime", Everest::Date::to_rfc3339(now)}, + + }); + + json active_disable_enable = json::object({{"source", this->active_enable_disable_source}, + {"state", this->active_enable_disable_state}, + {"priority", this->active_enable_disable_priority}}); + session_info["active_enable_disable_source"] = active_disable_enable; + + return session_info.dump(); +} + +void EvAPI::init() { + invoke_init(*p_main); + + std::vector connectors; + std::string var_connectors = this->api_base + "connectors"; + + for (auto& ev : this->r_ev_manager) { + auto& session_info = this->info.emplace_back(std::make_unique()); + auto& hw_caps = this->hw_capabilities_str.emplace_back(""); + std::string ev_base = this->api_base + ev->module_id; + connectors.push_back(ev->module_id); + + // API variables + std::string var_base = ev_base + "/var/"; + + std::string var_ev_info = var_base + "ev_info"; + ev->subscribe_ev_info([this, &ev, var_ev_info](types::evse_manager::EVInfo ev_info) { + json ev_info_json = ev_info; + this->mqtt.publish(var_ev_info, ev_info_json.dump()); + }); + + std::string var_session_info = var_base + "session_info"; + ev->subscribe_bsp_event([this, var_session_info, &session_info](const auto& bsp_event) { + session_info->update_state(types::board_support_common::event_to_string(bsp_event.event)); + this->mqtt.publish(var_session_info, *session_info); + }); + + std::string var_datetime = var_base + "datetime"; + std::string var_logging_path = var_base + "logging_path"; + this->api_threads.push_back(std::thread([this, var_datetime, var_session_info, &session_info]() { + auto next_tick = std::chrono::steady_clock::now(); + while (this->running) { + std::string datetime_str = Everest::Date::to_rfc3339(date::utc_clock::now()); + this->mqtt.publish(var_datetime, datetime_str); + this->mqtt.publish(var_session_info, *session_info); + + next_tick += NOTIFICATION_PERIOD; + std::this_thread::sleep_until(next_tick); + } + })); + + // API commands + std::string cmd_base = ev_base + "/cmd/"; + } + + this->api_threads.push_back(std::thread([this, var_connectors, connectors]() { + auto next_tick = std::chrono::steady_clock::now(); + while (this->running) { + json connectors_array = connectors; + this->mqtt.publish(var_connectors, connectors_array.dump()); + + next_tick += NOTIFICATION_PERIOD; + std::this_thread::sleep_until(next_tick); + } + })); +} + +void EvAPI::ready() { + invoke_ready(*p_main); + + std::string var_active_errors = this->api_base + "errors/var/active_errors"; + this->api_threads.push_back(std::thread([this, var_active_errors]() { + auto next_tick = std::chrono::steady_clock::now(); + while (this->running) { + std::string datetime_str = Everest::Date::to_rfc3339(date::utc_clock::now()); + + if (not r_error_history.empty()) { + // request active errors + types::error_history::FilterArguments filter; + filter.state_filter = types::error_history::State::Active; + auto active_errors = r_error_history.at(0)->call_get_errors(filter); + json errors_json = json(active_errors); + + // publish + this->mqtt.publish(var_active_errors, errors_json.dump()); + } + next_tick += NOTIFICATION_PERIOD; + std::this_thread::sleep_until(next_tick); + } + })); +} + +} // namespace module diff --git a/modules/EvAPI/EvAPI.hpp b/modules/EvAPI/EvAPI.hpp new file mode 100644 index 000000000..0df7b9fc9 --- /dev/null +++ b/modules/EvAPI/EvAPI.hpp @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Pionix GmbH and Contributors to EVerest +#ifndef EVAPI_HPP +#define EVAPI_HPP + +// +// AUTO GENERATED - MARKED REGIONS WILL BE KEPT +// template version 2 +// + +#include "ld-ev.hpp" + +// headers for provided interface implementations +#include + +// headers for required interface implementations +#include +#include + +// ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1 +// insert your custom include headers here +#include +#include +#include +#include +#include + +#include +#include + +namespace module { + +class LimitDecimalPlaces; + +class SessionInfo { +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); + 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); + void set_start_energy_export_wh(int32_t start_energy_export_wh); + void set_end_energy_export_wh(int32_t end_energy_export_wh); + void set_latest_energy_export_wh(int32_t latest_export_energy_wh); + void set_latest_total_w(double latest_total_w); + void set_enable_disable_source(const std::string& active_source, const std::string& active_state, + const int active_priority); + void set_permanent_fault(bool f) { + permanent_fault = f; + } + + /// \brief Converts this struct into a serialized json object + operator std::string(); + +private: + std::mutex session_info_mutex; + 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 + + std::string state = "Unknown"; + + std::string active_enable_disable_source{"Unspecified"}; + std::string active_enable_disable_state{"Enabled"}; + int active_enable_disable_priority{0}; + bool permanent_fault{false}; +}; +} // namespace module +// ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1 + +namespace module { + +struct Conf {}; + +class EvAPI : public Everest::ModuleBase { +public: + EvAPI() = delete; + EvAPI(const ModuleInfo& info, Everest::MqttProvider& mqtt_provider, std::unique_ptr p_main, + std::vector> r_ev_manager, + std::vector> r_error_history, Conf& config) : + ModuleBase(info), + mqtt(mqtt_provider), + p_main(std::move(p_main)), + r_ev_manager(std::move(r_ev_manager)), + r_error_history(std::move(r_error_history)), + config(config){}; + + Everest::MqttProvider& mqtt; + const std::unique_ptr p_main; + const std::vector> r_ev_manager; + const std::vector> r_error_history; + const Conf& config; + + // ev@1fce4c5e-0ab8-41bb-90f7-14277703d2ac:v1 + // insert your public definitions here + // ev@1fce4c5e-0ab8-41bb-90f7-14277703d2ac:v1 + +protected: + // ev@4714b2ab-a24f-4b95-ab81-36439e1478de:v1 + // insert your protected definitions here + // ev@4714b2ab-a24f-4b95-ab81-36439e1478de:v1 + +private: + friend class LdEverest; + void init(); + void ready(); + + // ev@211cfdbe-f69a-4cd6-a4ec-f8aaa3d1b6c8:v1 + // insert your private definitions here + std::vector api_threads; + bool running = true; + + std::list> info; + std::list hw_capabilities_str; + std::string selected_protocol; + + const std::string api_base = "everest_api/"; + // ev@211cfdbe-f69a-4cd6-a4ec-f8aaa3d1b6c8:v1 +}; + +// ev@087e516b-124c-48df-94fb-109508c7cda9:v1 +// insert other definitions here +// ev@087e516b-124c-48df-94fb-109508c7cda9:v1 + +} // namespace module + +#endif // EVAPI_HPP diff --git a/modules/EvAPI/README.md b/modules/EvAPI/README.md new file mode 100644 index 000000000..f0058c20e --- /dev/null +++ b/modules/EvAPI/README.md @@ -0,0 +1,2 @@ +# EvAPI module documentation +This module is responsible for providing a simple MQTT based API to EVerest internals exposing EvManager related functionality \ No newline at end of file diff --git a/modules/EvAPI/main/emptyImpl.cpp b/modules/EvAPI/main/emptyImpl.cpp new file mode 100644 index 000000000..ffebed0ca --- /dev/null +++ b/modules/EvAPI/main/emptyImpl.cpp @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2020 - 2022 Pionix GmbH and Contributors to EVerest + +#include "emptyImpl.hpp" + +namespace module { +namespace main { + +void emptyImpl::init() { +} + +void emptyImpl::ready() { +} + +} // namespace main +} // namespace module diff --git a/modules/EvAPI/main/emptyImpl.hpp b/modules/EvAPI/main/emptyImpl.hpp new file mode 100644 index 000000000..92bbe5944 --- /dev/null +++ b/modules/EvAPI/main/emptyImpl.hpp @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Pionix GmbH and Contributors to EVerest +#ifndef MAIN_EMPTY_IMPL_HPP +#define MAIN_EMPTY_IMPL_HPP + +// +// AUTO GENERATED - MARKED REGIONS WILL BE KEPT +// template version 3 +// + +#include + +#include "../EvAPI.hpp" + +// ev@75ac1216-19eb-4182-a85c-820f1fc2c091:v1 +// insert your custom include headers here +// ev@75ac1216-19eb-4182-a85c-820f1fc2c091:v1 + +namespace module { +namespace main { + +struct Conf {}; + +class emptyImpl : public emptyImplBase { +public: + emptyImpl() = delete; + emptyImpl(Everest::ModuleAdapter* ev, const Everest::PtrContainer& mod, Conf& config) : + emptyImplBase(ev, "main"), mod(mod), config(config){}; + + // ev@8ea32d28-373f-4c90-ae5e-b4fcc74e2a61:v1 + // insert your public definitions here + // ev@8ea32d28-373f-4c90-ae5e-b4fcc74e2a61:v1 + +protected: + // no commands defined for this interface + + // ev@d2d1847a-7b88-41dd-ad07-92785f06f5c4:v1 + // insert your protected definitions here + // ev@d2d1847a-7b88-41dd-ad07-92785f06f5c4:v1 + +private: + const Everest::PtrContainer& mod; + const Conf& config; + + virtual void init() override; + virtual void ready() override; + + // ev@3370e4dd-95f4-47a9-aaec-ea76f34a66c9:v1 + // insert your private definitions here + // ev@3370e4dd-95f4-47a9-aaec-ea76f34a66c9:v1 +}; + +// ev@3d7da0ad-02c2-493d-9920-0bbbd56b9876:v1 +// insert other definitions here +// ev@3d7da0ad-02c2-493d-9920-0bbbd56b9876:v1 + +} // namespace main +} // namespace module + +#endif // MAIN_EMPTY_IMPL_HPP diff --git a/modules/EvAPI/manifest.yaml b/modules/EvAPI/manifest.yaml new file mode 100644 index 000000000..2c22fe3ae --- /dev/null +++ b/modules/EvAPI/manifest.yaml @@ -0,0 +1,22 @@ +description: >- + The EVerest Ev API module, exposing some internal functionality on an external + MQTT connection. +config: {} +provides: + main: + description: EVerest API + interface: empty +requires: + ev_manager: + interface: ev_manager + min_connections: 1 + max_connections: 128 + error_history: + interface: error_history + min_connections: 0 + max_connections: 1 +enable_external_mqtt: true +metadata: + license: https://opensource.org/licenses/Apache-2.0 + authors: + - Kai-Uwe Hermann diff --git a/modules/EvManager/CMakeLists.txt b/modules/EvManager/CMakeLists.txt index d5aea153d..0c5dd492c 100644 --- a/modules/EvManager/CMakeLists.txt +++ b/modules/EvManager/CMakeLists.txt @@ -19,6 +19,7 @@ target_sources(${MODULE_NAME} target_sources(${MODULE_NAME} PRIVATE "main/car_simulatorImpl.cpp" + "ev_manager/ev_managerImpl.cpp" ) # ev@c55432ab-152c-45a9-9d2e-7281d50c69c3:v1 diff --git a/modules/EvManager/EvManager.cpp b/modules/EvManager/EvManager.cpp index 69769d3a9..d0d4eac28 100644 --- a/modules/EvManager/EvManager.cpp +++ b/modules/EvManager/EvManager.cpp @@ -7,10 +7,12 @@ namespace module { void EvManager::init() { invoke_init(*p_main); + invoke_init(*p_ev_manager); } void EvManager::ready() { invoke_ready(*p_main); + invoke_ready(*p_ev_manager); } } // namespace module diff --git a/modules/EvManager/EvManager.hpp b/modules/EvManager/EvManager.hpp index 41c6dc877..05a2598d6 100644 --- a/modules/EvManager/EvManager.hpp +++ b/modules/EvManager/EvManager.hpp @@ -12,6 +12,7 @@ // headers for provided interface implementations #include +#include // headers for required interface implementations #include @@ -44,18 +45,21 @@ struct Conf { int dc_discharge_v2g_minimal_soc; double max_current; bool three_phases; + int soc; }; class EvManager : public Everest::ModuleBase { public: EvManager() = delete; EvManager(const ModuleInfo& info, Everest::MqttProvider& mqtt_provider, - std::unique_ptr p_main, std::unique_ptr r_ev_board_support, + std::unique_ptr p_main, std::unique_ptr p_ev_manager, + std::unique_ptr r_ev_board_support, std::vector> r_ev, std::vector> r_slac, std::vector> r_powermeter, Conf& config) : ModuleBase(info), mqtt(mqtt_provider), p_main(std::move(p_main)), + p_ev_manager(std::move(p_ev_manager)), r_ev_board_support(std::move(r_ev_board_support)), r_ev(std::move(r_ev)), r_slac(std::move(r_slac)), @@ -64,6 +68,7 @@ class EvManager : public Everest::ModuleBase { Everest::MqttProvider& mqtt; const std::unique_ptr p_main; + const std::unique_ptr p_ev_manager; const std::unique_ptr r_ev_board_support; const std::vector> r_ev; const std::vector> r_slac; diff --git a/modules/EvManager/ev_manager/ev_managerImpl.cpp b/modules/EvManager/ev_manager/ev_managerImpl.cpp new file mode 100644 index 000000000..6080eecc3 --- /dev/null +++ b/modules/EvManager/ev_manager/ev_managerImpl.cpp @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Pionix GmbH and Contributors to EVerest + +#include "ev_managerImpl.hpp" + +namespace module { +namespace ev_manager { + +void ev_managerImpl::init() { +} + +void ev_managerImpl::ready() { +} + +} // namespace ev_manager +} // namespace module diff --git a/modules/EvManager/ev_manager/ev_managerImpl.hpp b/modules/EvManager/ev_manager/ev_managerImpl.hpp new file mode 100644 index 000000000..a11065e36 --- /dev/null +++ b/modules/EvManager/ev_manager/ev_managerImpl.hpp @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Pionix GmbH and Contributors to EVerest +#ifndef EV_MANAGER_EV_MANAGER_IMPL_HPP +#define EV_MANAGER_EV_MANAGER_IMPL_HPP + +// +// AUTO GENERATED - MARKED REGIONS WILL BE KEPT +// template version 3 +// + +#include + +#include "../EvManager.hpp" + +// ev@75ac1216-19eb-4182-a85c-820f1fc2c091:v1 +// insert your custom include headers here +// ev@75ac1216-19eb-4182-a85c-820f1fc2c091:v1 + +namespace module { +namespace ev_manager { + +struct Conf {}; + +class ev_managerImpl : public ev_managerImplBase { +public: + ev_managerImpl() = delete; + ev_managerImpl(Everest::ModuleAdapter* ev, const Everest::PtrContainer& mod, Conf& config) : + ev_managerImplBase(ev, "ev_manager"), mod(mod), config(config){}; + + // ev@8ea32d28-373f-4c90-ae5e-b4fcc74e2a61:v1 + // insert your public definitions here + // ev@8ea32d28-373f-4c90-ae5e-b4fcc74e2a61:v1 + +protected: + // no commands defined for this interface + + // ev@d2d1847a-7b88-41dd-ad07-92785f06f5c4:v1 + // insert your protected definitions here + // ev@d2d1847a-7b88-41dd-ad07-92785f06f5c4:v1 + +private: + const Everest::PtrContainer& mod; + const Conf& config; + + virtual void init() override; + virtual void ready() override; + + // ev@3370e4dd-95f4-47a9-aaec-ea76f34a66c9:v1 + // insert your private definitions here + // ev@3370e4dd-95f4-47a9-aaec-ea76f34a66c9:v1 +}; + +// ev@3d7da0ad-02c2-493d-9920-0bbbd56b9876:v1 +// insert other definitions here +// ev@3d7da0ad-02c2-493d-9920-0bbbd56b9876:v1 + +} // namespace ev_manager +} // namespace module + +#endif // EV_MANAGER_EV_MANAGER_IMPL_HPP diff --git a/modules/EvManager/main/car_simulation.cpp b/modules/EvManager/main/car_simulation.cpp index a0de3f33b..057c1ee9a 100644 --- a/modules/EvManager/main/car_simulation.cpp +++ b/modules/EvManager/main/car_simulation.cpp @@ -92,8 +92,53 @@ void CarSimulation::state_machine() { sim_data.state = SimState::UNPLUGGED; break; } + + if (not state_has_changed and + (sim_data.state == SimState::CHARGING_REGULATED or sim_data.state == SimState::CHARGING_FIXED or + sim_data.state == SimState::ISO_CHARGING_REGULATED)) { + simulate_soc(); + } + timepoint_last_update = std::chrono::steady_clock::now(); }; +void CarSimulation::simulate_soc() { + double ms = + std::chrono::duration_cast(std::chrono::steady_clock::now() - timepoint_last_update) + .count(); + double factor = (1.0 / 60.0 / 60.0 / 1000.0) * ms; + double power = 0.0; + types::evse_manager::EVInfo ev_info; + if (charge_ac) { + charge_v = 230.0; + if (charge_three_phase) { + power = charge_a * charge_v * 3.0; + } else { + power = charge_a * charge_v; + } + ev_info.target_current = charge_a; + ev_info.target_voltage = 0; + } else { + power = config.dc_target_current * config.dc_target_voltage; + ev_info.target_current = config.dc_target_current; + ev_info.target_voltage = config.dc_target_voltage; + } + + if (sim_data.battery_charge_wh > sim_data.battery_capacity_wh) { + sim_data.battery_charge_wh = sim_data.battery_capacity_wh; + } else { + sim_data.battery_charge_wh += power * factor; + } + + ev_info.soc = (sim_data.battery_charge_wh / sim_data.battery_capacity_wh) * 100.0; + if (ev_info.soc > 100.0) { + ev_info.soc = 100.0; + } + ev_info.battery_capacity = sim_data.battery_capacity_wh; + ev_info.battery_full_soc = 100; + + p_ev_manager->publish_ev_info(ev_info); +} + bool CarSimulation::sleep(const CmdArguments& arguments, size_t loop_interval_ms) { if (not sim_data.sleep_ticks_left.has_value()) { const auto sleep_time = std::stold(arguments[0]); @@ -122,10 +167,15 @@ bool CarSimulation::iso_wait_pwm_is_running(const CmdArguments& arguments) { bool CarSimulation::draw_power_regulated(const CmdArguments& arguments) { r_ev_board_support->call_set_ac_max_current(std::stod(arguments[0])); + charge_a = std::stod(arguments[0]); if (arguments[1] == constants::THREE_PHASES) { r_ev_board_support->call_set_three_phases(true); + charge_ac = true; + charge_three_phase = true; } else { r_ev_board_support->call_set_three_phases(false); + charge_ac = true; + charge_three_phase = false; } sim_data.state = SimState::CHARGING_REGULATED; return true; @@ -133,10 +183,15 @@ bool CarSimulation::draw_power_regulated(const CmdArguments& arguments) { bool CarSimulation::draw_power_fixed(const CmdArguments& arguments) { r_ev_board_support->call_set_ac_max_current(std::stod(arguments[0])); + charge_a = std::stod(arguments[0]); if (arguments[1] == constants::THREE_PHASES) { r_ev_board_support->call_set_three_phases(true); + charge_ac = true; + charge_three_phase = true; } else { r_ev_board_support->call_set_three_phases(false); + charge_ac = true; + charge_three_phase = false; } sim_data.state = SimState::CHARGING_FIXED; return true; @@ -200,6 +255,8 @@ bool CarSimulation::iso_dc_power_on(const CmdArguments& arguments) { if (sim_data.dc_power_on) { sim_data.state = SimState::ISO_CHARGING_REGULATED; r_ev_board_support->call_allow_power_on(true); + charge_ac = false; + charge_three_phase = false; return true; } return false; @@ -211,11 +268,17 @@ bool CarSimulation::iso_start_v2g_session(const CmdArguments& arguments, bool th if (energy_mode == constants::AC) { if (three_phases == false) { r_ev[0]->call_start_charging(types::iso15118_ev::EnergyTransferMode::AC_single_phase_core); + charge_ac = true; + charge_three_phase = false; } else { r_ev[0]->call_start_charging(types::iso15118_ev::EnergyTransferMode::AC_three_phase_core); + charge_ac = true; + charge_three_phase = true; } } else if (energy_mode == constants::DC) { r_ev[0]->call_start_charging(types::iso15118_ev::EnergyTransferMode::DC_extended); + charge_ac = false; + charge_three_phase = false; } else { return false; } @@ -224,10 +287,15 @@ bool CarSimulation::iso_start_v2g_session(const CmdArguments& arguments, bool th bool CarSimulation::iso_draw_power_regulated(const CmdArguments& arguments) { r_ev_board_support->call_set_ac_max_current(std::stod(arguments[0])); + charge_a = std::stod(arguments[0]); if (arguments[1] == constants::THREE_PHASES) { r_ev_board_support->call_set_three_phases(true); + charge_ac = true; + charge_three_phase = true; } else { r_ev_board_support->call_set_three_phases(false); + charge_ac = true; + charge_three_phase = false; } sim_data.state = SimState::ISO_CHARGING_REGULATED; return true; diff --git a/modules/EvManager/main/car_simulation.hpp b/modules/EvManager/main/car_simulation.hpp index 120ff3a10..8ee4e8261 100644 --- a/modules/EvManager/main/car_simulation.hpp +++ b/modules/EvManager/main/car_simulation.hpp @@ -5,8 +5,10 @@ #include "simulation_data.hpp" +#include "../EvManager.hpp" #include #include +#include #include #include @@ -16,12 +18,22 @@ class CarSimulation { public: CarSimulation(const std::unique_ptr& r_ev_board_support_, const std::vector>& r_ev_, - const std::vector>& r_slac_) : - r_ev_board_support(r_ev_board_support_), r_ev(r_ev_), r_slac(r_slac_){}; + const std::vector>& r_slac_, + const std::unique_ptr& p_ev_manager_, const module::Conf& config_) : + r_ev_board_support(r_ev_board_support_), + r_ev(r_ev_), + r_slac(r_slac_), + p_ev_manager(p_ev_manager_), + config(config_) { + timepoint_last_update = std::chrono::steady_clock::now(); + }; ~CarSimulation() = default; void reset() { sim_data = SimulationData(); + sim_data.battery_capacity_wh = config.dc_energy_capacity; + double soc = config.soc; + sim_data.battery_charge_wh = config.dc_energy_capacity * (soc / 100.0); } const SimState& get_state() const { @@ -98,8 +110,17 @@ class CarSimulation { private: SimulationData sim_data; + const module::Conf& config; + std::chrono::time_point timepoint_last_update; + double charge_a{0}; + double charge_v{0}; + bool charge_ac{false}; + bool charge_three_phase{false}; const std::unique_ptr& r_ev_board_support; const std::vector>& r_ev; const std::vector>& r_slac; + const std::unique_ptr& p_ev_manager; + + void simulate_soc(); }; diff --git a/modules/EvManager/main/car_simulatorImpl.cpp b/modules/EvManager/main/car_simulatorImpl.cpp index 3a13c2702..85afb02e7 100644 --- a/modules/EvManager/main/car_simulatorImpl.cpp +++ b/modules/EvManager/main/car_simulatorImpl.cpp @@ -13,7 +13,8 @@ void car_simulatorImpl::init() { register_all_commands(); subscribe_to_variables_on_init(); - car_simulation = std::make_unique(mod->r_ev_board_support, mod->r_ev, mod->r_slac); + car_simulation = std::make_unique(mod->r_ev_board_support, mod->r_ev, mod->r_slac, mod->p_ev_manager, + mod->config); std::thread(&car_simulatorImpl::run, this).detach(); } @@ -243,6 +244,10 @@ void car_simulatorImpl::subscribe_to_variables_on_init() { } }); + using types::board_support_common::BspEvent; + mod->r_ev_board_support->subscribe_bsp_event( + [this](const auto& bsp_event) { mod->p_ev_manager->publish_bsp_event(bsp_event); }); + // subscribe slac_state if (!mod->r_slac.empty()) { const auto& slac = mod->r_slac.at(0); diff --git a/modules/EvManager/main/simulation_data.hpp b/modules/EvManager/main/simulation_data.hpp index 6af9d1614..7e2bacf94 100644 --- a/modules/EvManager/main/simulation_data.hpp +++ b/modules/EvManager/main/simulation_data.hpp @@ -52,5 +52,8 @@ struct SimulationData { bool dc_power_on{false}; + double battery_charge_wh{0}; + double battery_capacity_wh{0}; + types::board_support_common::Event actual_bsp_event{types::board_support_common::Event::Disconnected}; }; diff --git a/modules/EvManager/manifest.yaml b/modules/EvManager/manifest.yaml index d725f30b6..dd74a0f83 100644 --- a/modules/EvManager/manifest.yaml +++ b/modules/EvManager/manifest.yaml @@ -76,10 +76,17 @@ config: description: Support three phase type: boolean default: true + soc: + description: SoC at start of a simulated charging process + type: integer + default: 30 provides: main: interface: car_simulator description: This implements the car simulator + ev_manager: + interface: ev_manager + description: TODO requires: ev_board_support: interface: ev_board_support diff --git a/modules/simulation/JsYetiSimulator/index.js b/modules/simulation/JsYetiSimulator/index.js index 5bf3dcdc2..995c38854 100644 --- a/modules/simulation/JsYetiSimulator/index.js +++ b/modules/simulation/JsYetiSimulator/index.js @@ -975,6 +975,10 @@ function publish_ev_board_support(mod) { rcd_current_mA: mod.simulation_data.rcd_current, proximity_pilot: pp, }); + + mod.provides.ev_board_support.publish.bsp_event({ + event: event_to_enum(mod.current_state) + }); } function simulate_powermeter(mod) { From feeb598f4526948de1b9646bbd03cd4588f8ff4c Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Wed, 6 Nov 2024 11:21:08 +0100 Subject: [PATCH 02/22] cleanup Signed-off-by: Kai-Uwe Hermann --- interfaces/ev_manager.yaml | 2 +- modules/EvAPI/EvAPI.cpp | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/interfaces/ev_manager.yaml b/interfaces/ev_manager.yaml index 7ed3b0ba0..77de0d497 100644 --- a/interfaces/ev_manager.yaml +++ b/interfaces/ev_manager.yaml @@ -21,4 +21,4 @@ vars: type: string $ref: /evse_manager#/CarManufacturer errors: - - reference: /errors/evse_manager \ No newline at end of file + - reference: /errors/evse_manager diff --git a/modules/EvAPI/EvAPI.cpp b/modules/EvAPI/EvAPI.cpp index 838a3bda3..c730cc464 100644 --- a/modules/EvAPI/EvAPI.cpp +++ b/modules/EvAPI/EvAPI.cpp @@ -1,8 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 - 2022 Pionix GmbH and Contributors to EVerest +// Copyright Pionix GmbH and Contributors to EVerest #include "EvAPI.hpp" #include -#include namespace module { @@ -153,7 +152,6 @@ void EvAPI::init() { }); std::string var_datetime = var_base + "datetime"; - std::string var_logging_path = var_base + "logging_path"; this->api_threads.push_back(std::thread([this, var_datetime, var_session_info, &session_info]() { auto next_tick = std::chrono::steady_clock::now(); while (this->running) { From 921a7f70f99b4a01406c316ebee665164a5294d4 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Wed, 6 Nov 2024 11:51:21 +0100 Subject: [PATCH 03/22] Public EvAPI connectors in "ev_connectors" do not use regular API "connectors" This allows both the API and EvAPI modules to run simultaneously Signed-off-by: Kai-Uwe Hermann --- modules/EvAPI/EvAPI.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/modules/EvAPI/EvAPI.cpp b/modules/EvAPI/EvAPI.cpp index c730cc464..770f31423 100644 --- a/modules/EvAPI/EvAPI.cpp +++ b/modules/EvAPI/EvAPI.cpp @@ -113,7 +113,6 @@ SessionInfo::operator std::string() { {"latest_total_w", this->latest_total_w}, {"charging_duration_s", charging_duration_s.count()}, {"datetime", Everest::Date::to_rfc3339(now)}, - }); json active_disable_enable = json::object({{"source", this->active_enable_disable_source}, @@ -127,14 +126,13 @@ SessionInfo::operator std::string() { void EvAPI::init() { invoke_init(*p_main); - std::vector connectors; - std::string var_connectors = this->api_base + "connectors"; + std::vector ev_connectors; + std::string var_ev_connectors = this->api_base + "ev_connectors"; for (auto& ev : this->r_ev_manager) { auto& session_info = this->info.emplace_back(std::make_unique()); - auto& hw_caps = this->hw_capabilities_str.emplace_back(""); std::string ev_base = this->api_base + ev->module_id; - connectors.push_back(ev->module_id); + ev_connectors.push_back(ev->module_id); // API variables std::string var_base = ev_base + "/var/"; @@ -168,11 +166,11 @@ void EvAPI::init() { std::string cmd_base = ev_base + "/cmd/"; } - this->api_threads.push_back(std::thread([this, var_connectors, connectors]() { + this->api_threads.push_back(std::thread([this, var_ev_connectors, ev_connectors]() { auto next_tick = std::chrono::steady_clock::now(); while (this->running) { - json connectors_array = connectors; - this->mqtt.publish(var_connectors, connectors_array.dump()); + json ev_connectors_array = ev_connectors; + this->mqtt.publish(var_ev_connectors, ev_connectors_array.dump()); next_tick += NOTIFICATION_PERIOD; std::this_thread::sleep_until(next_tick); From ed02b39c492dc2237ea1929961efb06774025ef0 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Wed, 6 Nov 2024 12:13:24 +0100 Subject: [PATCH 04/22] Remove session event from ev manager interface since it is not used Signed-off-by: Kai-Uwe Hermann --- interfaces/ev_manager.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/interfaces/ev_manager.yaml b/interfaces/ev_manager.yaml index 77de0d497..c7144b027 100644 --- a/interfaces/ev_manager.yaml +++ b/interfaces/ev_manager.yaml @@ -3,10 +3,6 @@ description: >- charging logic of the ev side cmds: {} vars: - session_event: - description: Emits all events related to sessions - type: object - $ref: /evse_manager#/SessionEvent ev_info: description: More details about the EV if available type: object From 3a919b20061d48638f8136dc706433a8c0521883 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Wed, 6 Nov 2024 12:18:06 +0100 Subject: [PATCH 05/22] Add EVInfo variable to ev board support interface This allows an EV implementation to report more detailed information such as SoC Signed-off-by: Kai-Uwe Hermann --- interfaces/ev_board_support.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/interfaces/ev_board_support.yaml b/interfaces/ev_board_support.yaml index b1dfb4e81..968d70b02 100644 --- a/interfaces/ev_board_support.yaml +++ b/interfaces/ev_board_support.yaml @@ -55,5 +55,9 @@ vars: BSP Measurements type: object $ref: /board_support_common#/BspMeasurement + ev_info: + description: More details about the EV if available + type: object + $ref: /evse_manager#/EVInfo errors: - - reference: /errors/generic \ No newline at end of file + - reference: /errors/generic From fad56c4f19f69a1dda37653966c7a34706e47dc2 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Wed, 6 Nov 2024 12:18:53 +0100 Subject: [PATCH 06/22] Remove car manufacturer from ev manager interface since it is not used Signed-off-by: Kai-Uwe Hermann --- interfaces/ev_manager.yaml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/interfaces/ev_manager.yaml b/interfaces/ev_manager.yaml index c7144b027..3f887ecab 100644 --- a/interfaces/ev_manager.yaml +++ b/interfaces/ev_manager.yaml @@ -3,18 +3,14 @@ description: >- charging logic of the ev side cmds: {} vars: - ev_info: - description: More details about the EV if available - type: object - $ref: /evse_manager#/EVInfo bsp_event: description: >- Events from CP/Relais type: object $ref: /board_support_common#/BspEvent - car_manufacturer: - description: Car manufacturer (if known) - type: string - $ref: /evse_manager#/CarManufacturer + ev_info: + description: More details about the EV if available + type: object + $ref: /evse_manager#/EVInfo errors: - reference: /errors/evse_manager From 038a90e76ac3329f787cf282cce7d6249fa5f257 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Wed, 6 Nov 2024 12:22:59 +0100 Subject: [PATCH 07/22] Re-publish bsp event in exeisting subscriber Signed-off-by: Kai-Uwe Hermann --- modules/EvManager/main/car_simulatorImpl.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/EvManager/main/car_simulatorImpl.cpp b/modules/EvManager/main/car_simulatorImpl.cpp index 85afb02e7..410088761 100644 --- a/modules/EvManager/main/car_simulatorImpl.cpp +++ b/modules/EvManager/main/car_simulatorImpl.cpp @@ -232,6 +232,7 @@ void car_simulatorImpl::subscribe_to_variables_on_init() { set_execution_active(false); car_simulation->set_state(SimState::UNPLUGGED); } + mod->p_ev_manager->publish_bsp_event(bsp_event); }); // subscribe bsp_measurement @@ -244,9 +245,6 @@ void car_simulatorImpl::subscribe_to_variables_on_init() { } }); - using types::board_support_common::BspEvent; - mod->r_ev_board_support->subscribe_bsp_event( - [this](const auto& bsp_event) { mod->p_ev_manager->publish_bsp_event(bsp_event); }); // subscribe slac_state if (!mod->r_slac.empty()) { From 59bc9b92e388755cc4b982b0f9f87d29045ba238 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Wed, 6 Nov 2024 12:23:25 +0100 Subject: [PATCH 08/22] Re-publish ev info coming from ev board support Signed-off-by: Kai-Uwe Hermann --- modules/EvManager/main/car_simulatorImpl.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/EvManager/main/car_simulatorImpl.cpp b/modules/EvManager/main/car_simulatorImpl.cpp index 410088761..ac69d22bc 100644 --- a/modules/EvManager/main/car_simulatorImpl.cpp +++ b/modules/EvManager/main/car_simulatorImpl.cpp @@ -245,6 +245,11 @@ void car_simulatorImpl::subscribe_to_variables_on_init() { } }); + // subscribe EVInfo + using types::evse_manager::EVInfo; + mod->r_ev_board_support->subscribe_ev_info([this](const auto& ev_info) { + mod->p_ev_manager->publish_ev_info(ev_info); + }); // subscribe slac_state if (!mod->r_slac.empty()) { From 5e9a275cebf725a153282a2829ad086d8b9d51cb Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Wed, 6 Nov 2024 12:25:57 +0100 Subject: [PATCH 09/22] Add description to ev manager provide Signed-off-by: Kai-Uwe Hermann --- modules/EvManager/manifest.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/EvManager/manifest.yaml b/modules/EvManager/manifest.yaml index dd74a0f83..b4d41edf0 100644 --- a/modules/EvManager/manifest.yaml +++ b/modules/EvManager/manifest.yaml @@ -86,7 +86,7 @@ provides: description: This implements the car simulator ev_manager: interface: ev_manager - description: TODO + description: Implementation of the ev manager to provide additional information such as detailed EV info requires: ev_board_support: interface: ev_board_support From eb4f6344de3fa24b5254a0752285238c687ffba9 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Wed, 6 Nov 2024 12:30:01 +0100 Subject: [PATCH 10/22] Remove wring years from license header Signed-off-by: Kai-Uwe Hermann --- modules/EvAPI/main/emptyImpl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/EvAPI/main/emptyImpl.cpp b/modules/EvAPI/main/emptyImpl.cpp index ffebed0ca..e69326b6c 100644 --- a/modules/EvAPI/main/emptyImpl.cpp +++ b/modules/EvAPI/main/emptyImpl.cpp @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 - 2022 Pionix GmbH and Contributors to EVerest +// Copyright Pionix GmbH and Contributors to EVerest #include "emptyImpl.hpp" From 81a79d8918d44ce8a426706b4402b226c9363e4f Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Wed, 6 Nov 2024 12:44:33 +0100 Subject: [PATCH 11/22] Fix naming of charge current/voltage, add AC nominal voltage to config Signed-off-by: Kai-Uwe Hermann --- modules/EvManager/EvManager.hpp | 1 + modules/EvManager/main/car_simulation.cpp | 20 ++++++++++---------- modules/EvManager/main/car_simulation.hpp | 4 ++-- modules/EvManager/manifest.yaml | 4 ++++ 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/modules/EvManager/EvManager.hpp b/modules/EvManager/EvManager.hpp index 05a2598d6..cda675cf9 100644 --- a/modules/EvManager/EvManager.hpp +++ b/modules/EvManager/EvManager.hpp @@ -32,6 +32,7 @@ struct Conf { bool auto_exec; bool auto_exec_infinite; std::string auto_exec_commands; + double ac_nominal_voltage; int dc_max_current_limit; int dc_max_power_limit; int dc_max_voltage_limit; diff --git a/modules/EvManager/main/car_simulation.cpp b/modules/EvManager/main/car_simulation.cpp index 057c1ee9a..82ca9c66b 100644 --- a/modules/EvManager/main/car_simulation.cpp +++ b/modules/EvManager/main/car_simulation.cpp @@ -109,13 +109,13 @@ void CarSimulation::simulate_soc() { double power = 0.0; types::evse_manager::EVInfo ev_info; if (charge_ac) { - charge_v = 230.0; + charge_voltage_v = config.ac_nominal_voltage; if (charge_three_phase) { - power = charge_a * charge_v * 3.0; + power = charge_current_a * charge_voltage_v * 3.0; } else { - power = charge_a * charge_v; + power = charge_current_a * charge_voltage_v; } - ev_info.target_current = charge_a; + ev_info.target_current = charge_current_a; ev_info.target_voltage = 0; } else { power = config.dc_target_current * config.dc_target_voltage; @@ -166,8 +166,8 @@ bool CarSimulation::iso_wait_pwm_is_running(const CmdArguments& arguments) { } bool CarSimulation::draw_power_regulated(const CmdArguments& arguments) { - r_ev_board_support->call_set_ac_max_current(std::stod(arguments[0])); - charge_a = std::stod(arguments[0]); + charge_current_a = std::stod(arguments[0]); + r_ev_board_support->call_set_ac_max_current(charge_current_a); if (arguments[1] == constants::THREE_PHASES) { r_ev_board_support->call_set_three_phases(true); charge_ac = true; @@ -182,8 +182,8 @@ bool CarSimulation::draw_power_regulated(const CmdArguments& arguments) { } bool CarSimulation::draw_power_fixed(const CmdArguments& arguments) { - r_ev_board_support->call_set_ac_max_current(std::stod(arguments[0])); - charge_a = std::stod(arguments[0]); + charge_current_a = std::stod(arguments[0]); + r_ev_board_support->call_set_ac_max_current(charge_current_a); if (arguments[1] == constants::THREE_PHASES) { r_ev_board_support->call_set_three_phases(true); charge_ac = true; @@ -286,8 +286,8 @@ bool CarSimulation::iso_start_v2g_session(const CmdArguments& arguments, bool th } bool CarSimulation::iso_draw_power_regulated(const CmdArguments& arguments) { - r_ev_board_support->call_set_ac_max_current(std::stod(arguments[0])); - charge_a = std::stod(arguments[0]); + charge_current_a = std::stod(arguments[0]); + r_ev_board_support->call_set_ac_max_current(charge_current_a); if (arguments[1] == constants::THREE_PHASES) { r_ev_board_support->call_set_three_phases(true); charge_ac = true; diff --git a/modules/EvManager/main/car_simulation.hpp b/modules/EvManager/main/car_simulation.hpp index 8ee4e8261..2ff9eb7e6 100644 --- a/modules/EvManager/main/car_simulation.hpp +++ b/modules/EvManager/main/car_simulation.hpp @@ -112,8 +112,8 @@ class CarSimulation { SimulationData sim_data; const module::Conf& config; std::chrono::time_point timepoint_last_update; - double charge_a{0}; - double charge_v{0}; + double charge_current_a{0}; + double charge_voltage_v{0}; bool charge_ac{false}; bool charge_three_phase{false}; diff --git a/modules/EvManager/manifest.yaml b/modules/EvManager/manifest.yaml index b4d41edf0..5280169fc 100644 --- a/modules/EvManager/manifest.yaml +++ b/modules/EvManager/manifest.yaml @@ -24,6 +24,10 @@ config: Simulation commands, e.g. sleep 1;iec_wait_pwr_ready;sleep 1;draw_power_regulated 16,3;sleep 30;unplug type: string default: "" + ac_nominal_voltage: + description: Nominal AC voltage between phase and neutral in Volt + type: number + default: 230 dc_max_current_limit: description: Maximum current allowed by the EV type: integer From d7a67aee1e3092d4bea167b987dc40f8b388d9e5 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Wed, 6 Nov 2024 17:48:23 +0100 Subject: [PATCH 12/22] Remove EvAPI from config-sil again Signed-off-by: Kai-Uwe Hermann --- config/config-sil.yaml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/config/config-sil.yaml b/config/config-sil.yaml index 0ab5e13d8..eb6b994b7 100644 --- a/config/config-sil.yaml +++ b/config/config-sil.yaml @@ -10,12 +10,6 @@ active_modules: - module_id: error_history implementation_id: error_history module: API - ev_api: - connections: - ev_manager: - - implementation_id: ev_manager - module_id: ev_manager - module: EvAPI error_history: module: ErrorHistory config_implementation: From fcf43bfa0e040077d921ad7ea8a59940076f9f5f Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Wed, 6 Nov 2024 17:57:13 +0100 Subject: [PATCH 13/22] Use EvSessionInfo in EvAPI with reduced information compared to API Signed-off-by: Kai-Uwe Hermann --- modules/EvAPI/EvAPI.cpp | 99 +++-------------------------------------- modules/EvAPI/EvAPI.hpp | 44 ++---------------- 2 files changed, 8 insertions(+), 135 deletions(-) diff --git a/modules/EvAPI/EvAPI.cpp b/modules/EvAPI/EvAPI.cpp index 770f31423..21673ddef 100644 --- a/modules/EvAPI/EvAPI.cpp +++ b/modules/EvAPI/EvAPI.cpp @@ -7,119 +7,30 @@ namespace module { static const auto NOTIFICATION_PERIOD = std::chrono::seconds(1); -SessionInfo::SessionInfo() : - start_energy_import_wh(0), - end_energy_import_wh(0), - start_energy_export_wh(0), - end_energy_export_wh(0), - latest_total_w(0), +EvSessionInfo::EvSessionInfo() : state("Unknown") { - this->start_time_point = date::utc_clock::now(); - this->end_time_point = this->start_time_point; } -void SessionInfo::reset() { +void EvSessionInfo::reset() { std::lock_guard lock(this->session_info_mutex); this->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; } -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 std::string& event) { +void EvSessionInfo::update_state(const std::string& event) { std::lock_guard lock(this->session_info_mutex); this->state = event; } -void SessionInfo::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 SessionInfo::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 SessionInfo::set_latest_energy_import_wh(int32_t latest_energy_wh) { -} - -void SessionInfo::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 SessionInfo::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 SessionInfo::set_latest_energy_export_wh(int32_t latest_export_energy_wh) { - std::lock_guard lock(this->session_info_mutex); -} - -void SessionInfo::set_latest_total_w(double latest_total_w) { +EvSessionInfo::operator std::string() { std::lock_guard lock(this->session_info_mutex); - this->latest_total_w = latest_total_w; -} - -void SessionInfo::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; -} -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); - - auto charged_energy_wh = this->end_energy_import_wh - this->start_energy_import_wh; - int32_t discharged_energy_wh{0}; - if ((this->start_energy_export_wh_was_set == true) && (this->end_energy_export_wh_was_set == true)) { - discharged_energy_wh = this->end_energy_export_wh - this->start_energy_export_wh; - } auto now = date::utc_clock::now(); - auto charging_duration_s = - std::chrono::duration_cast(this->end_time_point - this->start_time_point); - json session_info = json::object({ {"state", this->state}, - {"permanent_fault", this->permanent_fault}, - {"charged_energy_wh", charged_energy_wh}, - {"discharged_energy_wh", discharged_energy_wh}, - {"latest_total_w", this->latest_total_w}, - {"charging_duration_s", charging_duration_s.count()}, {"datetime", Everest::Date::to_rfc3339(now)}, }); - json active_disable_enable = json::object({{"source", this->active_enable_disable_source}, - {"state", this->active_enable_disable_state}, - {"priority", this->active_enable_disable_priority}}); - session_info["active_enable_disable_source"] = active_disable_enable; - return session_info.dump(); } @@ -130,7 +41,7 @@ void EvAPI::init() { std::string var_ev_connectors = this->api_base + "ev_connectors"; for (auto& ev : this->r_ev_manager) { - auto& session_info = this->info.emplace_back(std::make_unique()); + auto& session_info = this->info.emplace_back(std::make_unique()); std::string ev_base = this->api_base + ev->module_id; ev_connectors.push_back(ev->module_id); diff --git a/modules/EvAPI/EvAPI.hpp b/modules/EvAPI/EvAPI.hpp index 0df7b9fc9..ffd6baed0 100644 --- a/modules/EvAPI/EvAPI.hpp +++ b/modules/EvAPI/EvAPI.hpp @@ -32,55 +32,19 @@ namespace module { class LimitDecimalPlaces; -class SessionInfo { +class EvSessionInfo { 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 + EvSessionInfo(); void reset(); void update_state(const std::string& event); - 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); - void set_start_energy_export_wh(int32_t start_energy_export_wh); - void set_end_energy_export_wh(int32_t end_energy_export_wh); - void set_latest_energy_export_wh(int32_t latest_export_energy_wh); - void set_latest_total_w(double latest_total_w); - void set_enable_disable_source(const std::string& active_source, const std::string& active_state, - const int active_priority); - void set_permanent_fault(bool f) { - permanent_fault = f; - } /// \brief Converts this struct into a serialized json object operator std::string(); private: std::mutex session_info_mutex; - 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 - std::string state = "Unknown"; - - std::string active_enable_disable_source{"Unspecified"}; - std::string active_enable_disable_state{"Enabled"}; - int active_enable_disable_priority{0}; - bool permanent_fault{false}; }; } // namespace module // ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1 @@ -127,9 +91,7 @@ class EvAPI : public Everest::ModuleBase { std::vector api_threads; bool running = true; - std::list> info; - std::list hw_capabilities_str; - std::string selected_protocol; + std::list> info; const std::string api_base = "everest_api/"; // ev@211cfdbe-f69a-4cd6-a4ec-f8aaa3d1b6c8:v1 From 5060f53162f7ab4c3a18d24e876072f625a3d895 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Wed, 6 Nov 2024 19:54:05 +0100 Subject: [PATCH 14/22] clang-format Signed-off-by: Kai-Uwe Hermann --- modules/EvAPI/EvAPI.cpp | 3 +-- modules/EvManager/main/car_simulatorImpl.cpp | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/modules/EvAPI/EvAPI.cpp b/modules/EvAPI/EvAPI.cpp index 21673ddef..6e6137a55 100644 --- a/modules/EvAPI/EvAPI.cpp +++ b/modules/EvAPI/EvAPI.cpp @@ -7,8 +7,7 @@ namespace module { static const auto NOTIFICATION_PERIOD = std::chrono::seconds(1); -EvSessionInfo::EvSessionInfo() : - state("Unknown") { +EvSessionInfo::EvSessionInfo() : state("Unknown") { } void EvSessionInfo::reset() { diff --git a/modules/EvManager/main/car_simulatorImpl.cpp b/modules/EvManager/main/car_simulatorImpl.cpp index ac69d22bc..5f0f5da55 100644 --- a/modules/EvManager/main/car_simulatorImpl.cpp +++ b/modules/EvManager/main/car_simulatorImpl.cpp @@ -247,9 +247,8 @@ void car_simulatorImpl::subscribe_to_variables_on_init() { // subscribe EVInfo using types::evse_manager::EVInfo; - mod->r_ev_board_support->subscribe_ev_info([this](const auto& ev_info) { - mod->p_ev_manager->publish_ev_info(ev_info); - }); + mod->r_ev_board_support->subscribe_ev_info( + [this](const auto& ev_info) { mod->p_ev_manager->publish_ev_info(ev_info); }); // subscribe slac_state if (!mod->r_slac.empty()) { From ba781f8aded27c7885d546b15ffa9f2c08cdb26d Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Thu, 7 Nov 2024 13:02:03 +0100 Subject: [PATCH 15/22] Refactor EvSessioninfo Signed-off-by: Kai-Uwe Hermann --- modules/EvAPI/EvAPI.cpp | 20 +++++++++++--------- modules/EvAPI/EvAPI.hpp | 8 +++++--- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/modules/EvAPI/EvAPI.cpp b/modules/EvAPI/EvAPI.cpp index 6e6137a55..bd5c437db 100644 --- a/modules/EvAPI/EvAPI.cpp +++ b/modules/EvAPI/EvAPI.cpp @@ -7,26 +7,28 @@ namespace module { static const auto NOTIFICATION_PERIOD = std::chrono::seconds(1); -EvSessionInfo::EvSessionInfo() : state("Unknown") { -} - void EvSessionInfo::reset() { std::lock_guard lock(this->session_info_mutex); - this->state = "Unknown"; + this->event = std::nullopt; } -void EvSessionInfo::update_state(const std::string& event) { +void EvSessionInfo::update_event(const types::board_support_common::Event& event) { std::lock_guard lock(this->session_info_mutex); - this->state = event; + this->event = event; } EvSessionInfo::operator std::string() { std::lock_guard lock(this->session_info_mutex); - auto now = date::utc_clock::now(); + const auto now = date::utc_clock::now(); + + std::string state = "Unknown"; + if (this->event.has_value()) { + state = types::board_support_common::event_to_string(this->event.value()); + } json session_info = json::object({ - {"state", this->state}, + {"state", state}, {"datetime", Everest::Date::to_rfc3339(now)}, }); @@ -55,7 +57,7 @@ void EvAPI::init() { std::string var_session_info = var_base + "session_info"; ev->subscribe_bsp_event([this, var_session_info, &session_info](const auto& bsp_event) { - session_info->update_state(types::board_support_common::event_to_string(bsp_event.event)); + session_info->update_event(bsp_event.event); this->mqtt.publish(var_session_info, *session_info); }); diff --git a/modules/EvAPI/EvAPI.hpp b/modules/EvAPI/EvAPI.hpp index ffd6baed0..7d535ea03 100644 --- a/modules/EvAPI/EvAPI.hpp +++ b/modules/EvAPI/EvAPI.hpp @@ -28,23 +28,25 @@ #include #include +#include + namespace module { class LimitDecimalPlaces; class EvSessionInfo { public: - EvSessionInfo(); + EvSessionInfo(){}; void reset(); - void update_state(const std::string& event); + void update_event(const types::board_support_common::Event& event); /// \brief Converts this struct into a serialized json object operator std::string(); private: std::mutex session_info_mutex; - std::string state = "Unknown"; + std::optional event; }; } // namespace module // ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1 From 2ec49b937006114e3144dfd8f399665bb9cb71b8 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Thu, 7 Nov 2024 13:02:21 +0100 Subject: [PATCH 16/22] cleanup + const Signed-off-by: Kai-Uwe Hermann --- modules/EvAPI/EvAPI.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/modules/EvAPI/EvAPI.cpp b/modules/EvAPI/EvAPI.cpp index bd5c437db..992dc6ce6 100644 --- a/modules/EvAPI/EvAPI.cpp +++ b/modules/EvAPI/EvAPI.cpp @@ -43,25 +43,25 @@ void EvAPI::init() { for (auto& ev : this->r_ev_manager) { auto& session_info = this->info.emplace_back(std::make_unique()); - std::string ev_base = this->api_base + ev->module_id; + const std::string ev_base = this->api_base + ev->module_id; ev_connectors.push_back(ev->module_id); // API variables - std::string var_base = ev_base + "/var/"; + const std::string var_base = ev_base + "/var/"; - std::string var_ev_info = var_base + "ev_info"; + const std::string var_ev_info = var_base + "ev_info"; ev->subscribe_ev_info([this, &ev, var_ev_info](types::evse_manager::EVInfo ev_info) { json ev_info_json = ev_info; this->mqtt.publish(var_ev_info, ev_info_json.dump()); }); - std::string var_session_info = var_base + "session_info"; + const std::string var_session_info = var_base + "session_info"; ev->subscribe_bsp_event([this, var_session_info, &session_info](const auto& bsp_event) { session_info->update_event(bsp_event.event); this->mqtt.publish(var_session_info, *session_info); }); - std::string var_datetime = var_base + "datetime"; + const std::string var_datetime = var_base + "datetime"; this->api_threads.push_back(std::thread([this, var_datetime, var_session_info, &session_info]() { auto next_tick = std::chrono::steady_clock::now(); while (this->running) { @@ -75,13 +75,13 @@ void EvAPI::init() { })); // API commands - std::string cmd_base = ev_base + "/cmd/"; + const std::string cmd_base = ev_base + "/cmd/"; } this->api_threads.push_back(std::thread([this, var_ev_connectors, ev_connectors]() { auto next_tick = std::chrono::steady_clock::now(); while (this->running) { - json ev_connectors_array = ev_connectors; + const json ev_connectors_array = ev_connectors; this->mqtt.publish(var_ev_connectors, ev_connectors_array.dump()); next_tick += NOTIFICATION_PERIOD; @@ -93,17 +93,15 @@ void EvAPI::init() { void EvAPI::ready() { invoke_ready(*p_main); - std::string var_active_errors = this->api_base + "errors/var/active_errors"; + const std::string var_active_errors = this->api_base + "errors/var/active_errors"; this->api_threads.push_back(std::thread([this, var_active_errors]() { auto next_tick = std::chrono::steady_clock::now(); while (this->running) { - std::string datetime_str = Everest::Date::to_rfc3339(date::utc_clock::now()); - if (not r_error_history.empty()) { // request active errors types::error_history::FilterArguments filter; filter.state_filter = types::error_history::State::Active; - auto active_errors = r_error_history.at(0)->call_get_errors(filter); + const auto active_errors = r_error_history.at(0)->call_get_errors(filter); json errors_json = json(active_errors); // publish From 8bc6ab4ca466f8a1b32afe759009782706ae7a04 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Thu, 7 Nov 2024 13:11:58 +0100 Subject: [PATCH 17/22] Remove unnecessary charge_voltage_v member variables This is was only used for AC, where we now get it via the config Signed-off-by: Kai-Uwe Hermann --- modules/EvManager/main/car_simulation.cpp | 5 ++--- modules/EvManager/main/car_simulation.hpp | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/modules/EvManager/main/car_simulation.cpp b/modules/EvManager/main/car_simulation.cpp index 82ca9c66b..5ede9ab96 100644 --- a/modules/EvManager/main/car_simulation.cpp +++ b/modules/EvManager/main/car_simulation.cpp @@ -109,11 +109,10 @@ void CarSimulation::simulate_soc() { double power = 0.0; types::evse_manager::EVInfo ev_info; if (charge_ac) { - charge_voltage_v = config.ac_nominal_voltage; if (charge_three_phase) { - power = charge_current_a * charge_voltage_v * 3.0; + power = charge_current_a * config.ac_nominal_voltage * 3.0; } else { - power = charge_current_a * charge_voltage_v; + power = charge_current_a * config.ac_nominal_voltage; } ev_info.target_current = charge_current_a; ev_info.target_voltage = 0; diff --git a/modules/EvManager/main/car_simulation.hpp b/modules/EvManager/main/car_simulation.hpp index 2ff9eb7e6..cc40ee51e 100644 --- a/modules/EvManager/main/car_simulation.hpp +++ b/modules/EvManager/main/car_simulation.hpp @@ -113,7 +113,6 @@ class CarSimulation { const module::Conf& config; std::chrono::time_point timepoint_last_update; double charge_current_a{0}; - double charge_voltage_v{0}; bool charge_ac{false}; bool charge_three_phase{false}; From 536e8fb21d7d8f477f73bbfe26fdb55a5a131e0b Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Thu, 7 Nov 2024 13:13:03 +0100 Subject: [PATCH 18/22] make ms factor constexpr Signed-off-by: Kai-Uwe Hermann --- modules/EvManager/main/car_simulation.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/EvManager/main/car_simulation.cpp b/modules/EvManager/main/car_simulation.cpp index 5ede9ab96..ae878a2c8 100644 --- a/modules/EvManager/main/car_simulation.cpp +++ b/modules/EvManager/main/car_simulation.cpp @@ -6,6 +6,8 @@ #include +constexpr double MS_FACTOR = (1.0 / 60.0 / 60.0 / 1000.0); + void CarSimulation::state_machine() { using types::ev_board_support::EvCpState; @@ -102,10 +104,10 @@ void CarSimulation::state_machine() { }; void CarSimulation::simulate_soc() { - double ms = + const double ms = std::chrono::duration_cast(std::chrono::steady_clock::now() - timepoint_last_update) .count(); - double factor = (1.0 / 60.0 / 60.0 / 1000.0) * ms; + const double factor = MS_FACTOR * ms; double power = 0.0; types::evse_manager::EVInfo ev_info; if (charge_ac) { From 17c99985001b66aaca6e89be1a7b49a2505c46d3 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Thu, 7 Nov 2024 14:54:29 +0100 Subject: [PATCH 19/22] Replace charge_ac and charge_three_phase bool members with charge_mode enum Signed-off-by: Kai-Uwe Hermann --- modules/EvManager/main/car_simulation.cpp | 53 +++++++++++------------ modules/EvManager/main/car_simulation.hpp | 9 +++- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/modules/EvManager/main/car_simulation.cpp b/modules/EvManager/main/car_simulation.cpp index ae878a2c8..9313508a8 100644 --- a/modules/EvManager/main/car_simulation.cpp +++ b/modules/EvManager/main/car_simulation.cpp @@ -110,18 +110,25 @@ void CarSimulation::simulate_soc() { const double factor = MS_FACTOR * ms; double power = 0.0; types::evse_manager::EVInfo ev_info; - if (charge_ac) { - if (charge_three_phase) { - power = charge_current_a * config.ac_nominal_voltage * 3.0; - } else { - power = charge_current_a * config.ac_nominal_voltage; - } + switch (charge_mode) { + case ChargeMode::None: + // nothing to do + break; + case ChargeMode::AC: + power = charge_current_a * config.ac_nominal_voltage; ev_info.target_current = charge_current_a; ev_info.target_voltage = 0; - } else { + break; + case ChargeMode::ACThreePhase: + power = charge_current_a * config.ac_nominal_voltage * 3.0; + ev_info.target_current = charge_current_a; + ev_info.target_voltage = 0; + break; + case ChargeMode::DC: power = config.dc_target_current * config.dc_target_voltage; ev_info.target_current = config.dc_target_current; ev_info.target_voltage = config.dc_target_voltage; + break; } if (sim_data.battery_charge_wh > sim_data.battery_capacity_wh) { @@ -171,12 +178,10 @@ bool CarSimulation::draw_power_regulated(const CmdArguments& arguments) { r_ev_board_support->call_set_ac_max_current(charge_current_a); if (arguments[1] == constants::THREE_PHASES) { r_ev_board_support->call_set_three_phases(true); - charge_ac = true; - charge_three_phase = true; + charge_mode = ChargeMode::ACThreePhase; } else { r_ev_board_support->call_set_three_phases(false); - charge_ac = true; - charge_three_phase = false; + charge_mode = ChargeMode::AC; } sim_data.state = SimState::CHARGING_REGULATED; return true; @@ -187,12 +192,10 @@ bool CarSimulation::draw_power_fixed(const CmdArguments& arguments) { r_ev_board_support->call_set_ac_max_current(charge_current_a); if (arguments[1] == constants::THREE_PHASES) { r_ev_board_support->call_set_three_phases(true); - charge_ac = true; - charge_three_phase = true; + charge_mode = ChargeMode::ACThreePhase; } else { r_ev_board_support->call_set_three_phases(false); - charge_ac = true; - charge_three_phase = false; + charge_mode = ChargeMode::AC; } sim_data.state = SimState::CHARGING_FIXED; return true; @@ -205,6 +208,7 @@ bool CarSimulation::pause(const CmdArguments& arguments) { bool CarSimulation::unplug(const CmdArguments& arguments) { sim_data.state = SimState::UNPLUGGED; + charge_mode = ChargeMode::None; return true; } @@ -256,8 +260,7 @@ bool CarSimulation::iso_dc_power_on(const CmdArguments& arguments) { if (sim_data.dc_power_on) { sim_data.state = SimState::ISO_CHARGING_REGULATED; r_ev_board_support->call_allow_power_on(true); - charge_ac = false; - charge_three_phase = false; + charge_mode = ChargeMode::DC; return true; } return false; @@ -269,17 +272,14 @@ bool CarSimulation::iso_start_v2g_session(const CmdArguments& arguments, bool th if (energy_mode == constants::AC) { if (three_phases == false) { r_ev[0]->call_start_charging(types::iso15118_ev::EnergyTransferMode::AC_single_phase_core); - charge_ac = true; - charge_three_phase = false; + charge_mode = ChargeMode::AC; } else { r_ev[0]->call_start_charging(types::iso15118_ev::EnergyTransferMode::AC_three_phase_core); - charge_ac = true; - charge_three_phase = true; + charge_mode = ChargeMode::ACThreePhase; } } else if (energy_mode == constants::DC) { r_ev[0]->call_start_charging(types::iso15118_ev::EnergyTransferMode::DC_extended); - charge_ac = false; - charge_three_phase = false; + charge_mode = ChargeMode::DC; } else { return false; } @@ -291,12 +291,10 @@ bool CarSimulation::iso_draw_power_regulated(const CmdArguments& arguments) { r_ev_board_support->call_set_ac_max_current(charge_current_a); if (arguments[1] == constants::THREE_PHASES) { r_ev_board_support->call_set_three_phases(true); - charge_ac = true; - charge_three_phase = true; + charge_mode = ChargeMode::ACThreePhase; } else { r_ev_board_support->call_set_three_phases(false); - charge_ac = true; - charge_three_phase = false; + charge_mode = ChargeMode::AC; } sim_data.state = SimState::ISO_CHARGING_REGULATED; return true; @@ -306,6 +304,7 @@ bool CarSimulation::iso_stop_charging(const CmdArguments& arguments) { r_ev[0]->call_stop_charging(); r_ev_board_support->call_allow_power_on(false); sim_data.state = SimState::PLUGGED_IN; + charge_mode = ChargeMode::None; return true; } diff --git a/modules/EvManager/main/car_simulation.hpp b/modules/EvManager/main/car_simulation.hpp index cc40ee51e..0613bb8d4 100644 --- a/modules/EvManager/main/car_simulation.hpp +++ b/modules/EvManager/main/car_simulation.hpp @@ -113,8 +113,13 @@ class CarSimulation { const module::Conf& config; std::chrono::time_point timepoint_last_update; double charge_current_a{0}; - bool charge_ac{false}; - bool charge_three_phase{false}; + + enum class ChargeMode { + None, + AC, + ACThreePhase, + DC, + } charge_mode{ChargeMode::None}; const std::unique_ptr& r_ev_board_support; const std::vector>& r_ev; From c679a3276d4a836a6ab84aecced23f90da3c28d7 Mon Sep 17 00:00:00 2001 From: Sebastian Lukas Date: Thu, 14 Nov 2024 10:29:54 +0100 Subject: [PATCH 20/22] Adding iso_dc_power_on cmd to all node-red config-sil files. With this cmd the EvManager goes to state ISO_CHARGING_REGULATED and then the new simulate_soc() works also for DC Signed-off-by: Sebastian Lukas --- config/config-sil-dc-d20.yaml | 2 +- config/nodered/config-sil-dc-bpt-flow.json | 4 ++-- config/nodered/config-sil-dc-flow.json | 4 ++-- config/nodered/config-sil-two-evse-flow.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/config/config-sil-dc-d20.yaml b/config/config-sil-dc-d20.yaml index 7195d547f..abbec5de7 100644 --- a/config/config-sil-dc-d20.yaml +++ b/config/config-sil-dc-d20.yaml @@ -60,7 +60,7 @@ active_modules: connector_id: 1 auto_enable: true auto_exec: false - auto_exec_commands: sleep 3;iso_wait_slac_matched;iso_start_v2g_session DC;iso_wait_pwr_ready;iso_wait_for_stop 15;iso_wait_v2g_session_stopped;unplug; + auto_exec_commands: sleep 3;iso_wait_slac_matched;iso_start_v2g_session DC;iso_wait_pwr_ready;iso_dc_power_on;iso_wait_for_stop 15;iso_wait_v2g_session_stopped;unplug; dc_target_current: 20 dc_target_voltage: 400 connections: diff --git a/config/nodered/config-sil-dc-bpt-flow.json b/config/nodered/config-sil-dc-bpt-flow.json index 360fe772c..5a0b835f2 100644 --- a/config/nodered/config-sil-dc-bpt-flow.json +++ b/config/nodered/config-sil-dc-bpt-flow.json @@ -1789,7 +1789,7 @@ "options": [ { "label": "DC ISO15118-2", - "value": "sleep 1;iso_wait_slac_matched;iso_start_v2g_session DC;iso_wait_pwr_ready;sleep 36000#iso_stop_charging;iso_wait_v2g_session_stopped;unplug#iso_pause_charging;iso_wait_for_resume#iso_start_bcb_toggle 3;iso_wait_pwm_is_running;iso_start_v2g_session DC;iso_wait_pwr_ready;sleep 36000;", + "value": "sleep 1;iso_wait_slac_matched;iso_start_v2g_session DC;iso_wait_pwr_ready;iso_dc_power_on;sleep 36000#iso_stop_charging;iso_wait_v2g_session_stopped;unplug#iso_pause_charging;iso_wait_for_resume#iso_start_bcb_toggle 3;iso_wait_pwm_is_running;iso_start_v2g_session DC;iso_wait_pwr_ready;iso_dc_power_on;sleep 36000;", "type": "str" } ], @@ -1859,7 +1859,7 @@ "once": true, "onceDelay": "1", "topic": "sim_commands", - "payload": "sleep 1;iso_wait_slac_matched;iso_start_v2g_session DC;iso_wait_pwr_ready;sleep 36000#iso_stop_charging;iso_wait_v2g_session_stopped;unplug#iso_pause_charging;iso_wait_for_resume#iso_start_bcb_toggle 3;iso_wait_pwm_is_running;iso_start_v2g_session DC;iso_wait_pwr_ready;sleep 36000;", + "payload": "sleep 1;iso_wait_slac_matched;iso_start_v2g_session DC;iso_wait_pwr_ready;iso_dc_power_on;sleep 36000#iso_stop_charging;iso_wait_v2g_session_stopped;unplug#iso_pause_charging;iso_wait_for_resume#iso_start_bcb_toggle 3;iso_wait_pwm_is_running;iso_start_v2g_session DC;iso_wait_pwr_ready;iso_dc_power_on;sleep 36000;", "payloadType": "str", "x": 150, "y": 1180, diff --git a/config/nodered/config-sil-dc-flow.json b/config/nodered/config-sil-dc-flow.json index 484089a7e..debab06fc 100644 --- a/config/nodered/config-sil-dc-flow.json +++ b/config/nodered/config-sil-dc-flow.json @@ -1789,7 +1789,7 @@ "options": [ { "label": "DC ISO15118-2", - "value": "sleep 1;iso_wait_slac_matched;iso_start_v2g_session DC;iso_wait_pwr_ready;sleep 36000#iso_stop_charging;iso_wait_v2g_session_stopped;unplug#iso_pause_charging;iso_wait_for_resume#iso_start_bcb_toggle 3;iso_wait_pwm_is_running;iso_start_v2g_session DC;iso_wait_pwr_ready;sleep 36000;", + "value": "sleep 1;iso_wait_slac_matched;iso_start_v2g_session DC;iso_wait_pwr_ready;iso_dc_power_on;sleep 36000#iso_stop_charging;iso_wait_v2g_session_stopped;unplug#iso_pause_charging;iso_wait_for_resume#iso_start_bcb_toggle 3;iso_wait_pwm_is_running;iso_start_v2g_session DC;iso_wait_pwr_ready;iso_dc_power_on;sleep 36000;", "type": "str" } ], @@ -1859,7 +1859,7 @@ "once": true, "onceDelay": "1", "topic": "sim_commands", - "payload": "sleep 1;iso_wait_slac_matched;iso_start_v2g_session DC;iso_wait_pwr_ready;sleep 36000#iso_stop_charging;iso_wait_v2g_session_stopped;unplug#iso_pause_charging;iso_wait_for_resume#iso_start_bcb_toggle 3;iso_wait_pwm_is_running;iso_start_v2g_session DC;iso_wait_pwr_ready;sleep 36000;", + "payload": "sleep 1;iso_wait_slac_matched;iso_start_v2g_session DC;iso_wait_pwr_ready;iso_dc_power_on;sleep 36000#iso_stop_charging;iso_wait_v2g_session_stopped;unplug#iso_pause_charging;iso_wait_for_resume#iso_start_bcb_toggle 3;iso_wait_pwm_is_running;iso_start_v2g_session DC;iso_wait_pwr_ready;iso_dc_power_on;sleep 36000;", "payloadType": "str", "x": 150, "y": 1180, diff --git a/config/nodered/config-sil-two-evse-flow.json b/config/nodered/config-sil-two-evse-flow.json index 7908880d4..9b929830b 100644 --- a/config/nodered/config-sil-two-evse-flow.json +++ b/config/nodered/config-sil-two-evse-flow.json @@ -2141,7 +2141,7 @@ }, { "label": "DC ISO15118-2", - "value": "sleep 1;iso_wait_slac_matched;iso_start_v2g_session DC;iso_wait_pwr_ready;sleep 36000#iso_stop_charging;iso_wait_v2g_session_stopped;unplug#iso_pause_charging;iso_wait_for_resume#iso_start_bcb_toggle 3;iso_wait_pwm_is_running;iso_start_v2g_session DC;iso_wait_pwr_ready;sleep 36000;", + "value": "sleep 1;iso_wait_slac_matched;iso_start_v2g_session DC;iso_wait_pwr_ready;iso_dc_power_on;sleep 36000#iso_stop_charging;iso_wait_v2g_session_stopped;unplug#iso_pause_charging;iso_wait_for_resume#iso_start_bcb_toggle 3;iso_wait_pwm_is_running;iso_start_v2g_session DC;iso_wait_pwr_ready;iso_dc_power_on;sleep 36000;", "type": "str" } ], From 633fc087f042f0fbb17ac915018aec7efcbce439 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Thu, 21 Nov 2024 14:47:55 +0100 Subject: [PATCH 21/22] fix codacy issue Signed-off-by: Kai-Uwe Hermann --- modules/EvManager/main/car_simulation.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/EvManager/main/car_simulation.hpp b/modules/EvManager/main/car_simulation.hpp index 0613bb8d4..3d7d1b1f8 100644 --- a/modules/EvManager/main/car_simulation.hpp +++ b/modules/EvManager/main/car_simulation.hpp @@ -24,8 +24,8 @@ class CarSimulation { r_ev(r_ev_), r_slac(r_slac_), p_ev_manager(p_ev_manager_), - config(config_) { - timepoint_last_update = std::chrono::steady_clock::now(); + config(config_), + timepoint_last_update(std::chrono::steady_clock::now()) { }; ~CarSimulation() = default; From a902c7fdcb4cfcd86864e9bdfec2153dd02d5be5 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Thu, 21 Nov 2024 14:53:19 +0100 Subject: [PATCH 22/22] clang-format Signed-off-by: Kai-Uwe Hermann --- modules/EvManager/main/car_simulation.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/EvManager/main/car_simulation.hpp b/modules/EvManager/main/car_simulation.hpp index 3d7d1b1f8..60467b3c4 100644 --- a/modules/EvManager/main/car_simulation.hpp +++ b/modules/EvManager/main/car_simulation.hpp @@ -25,8 +25,7 @@ class CarSimulation { r_slac(r_slac_), p_ev_manager(p_ev_manager_), config(config_), - timepoint_last_update(std::chrono::steady_clock::now()) { - }; + timepoint_last_update(std::chrono::steady_clock::now()){}; ~CarSimulation() = default; void reset() {