Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add simple EvAPI and extend EvManager with simplistic SoC calculation #891

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
b7a727d
Add simple EvAPI and extend EvManager with simplistic SoC calculation
hikinggrass Oct 1, 2024
5fcc16b
Merge branch 'main' into feature/ev-api
hikinggrass Nov 6, 2024
feeb598
cleanup
hikinggrass Nov 6, 2024
921a7f7
Public EvAPI connectors in "ev_connectors" do not use regular API "co…
hikinggrass Nov 6, 2024
ed02b39
Remove session event from ev manager interface since it is not used
hikinggrass Nov 6, 2024
3a919b2
Add EVInfo variable to ev board support interface
hikinggrass Nov 6, 2024
fad56c4
Remove car manufacturer from ev manager interface since it is not used
hikinggrass Nov 6, 2024
038a90e
Re-publish bsp event in exeisting subscriber
hikinggrass Nov 6, 2024
59bc9b9
Re-publish ev info coming from ev board support
hikinggrass Nov 6, 2024
5e9a275
Add description to ev manager provide
hikinggrass Nov 6, 2024
eb4f634
Remove wring years from license header
hikinggrass Nov 6, 2024
81a79d8
Fix naming of charge current/voltage, add AC nominal voltage to config
hikinggrass Nov 6, 2024
d7a67ae
Remove EvAPI from config-sil again
hikinggrass Nov 6, 2024
fcf43bf
Use EvSessionInfo in EvAPI with reduced information compared to API
hikinggrass Nov 6, 2024
5060f53
clang-format
hikinggrass Nov 6, 2024
ba781f8
Refactor EvSessioninfo
hikinggrass Nov 7, 2024
2ec49b9
cleanup + const
hikinggrass Nov 7, 2024
8bc6ab4
Remove unnecessary charge_voltage_v member variables
hikinggrass Nov 7, 2024
536e8fb
make ms factor constexpr
hikinggrass Nov 7, 2024
17c9998
Replace charge_ac and charge_three_phase bool members with charge_mod…
hikinggrass Nov 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion interfaces/ev_board_support.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
- reference: /errors/generic
16 changes: 16 additions & 0 deletions interfaces/ev_manager.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
description: >-
This interface defines the ev manager. An ev manager represents the
charging logic of the ev side
cmds: {}
vars:
bsp_event:
description: >-
Events from CP/Relais
type: object
$ref: /board_support_common#/BspEvent
ev_info:
description: More details about the EV if available
type: object
$ref: /evse_manager#/EVInfo
errors:
- reference: /errors/evse_manager
1 change: 1 addition & 0 deletions modules/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
21 changes: 21 additions & 0 deletions modules/EvAPI/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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
116 changes: 116 additions & 0 deletions modules/EvAPI/EvAPI.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#include "EvAPI.hpp"
#include <utils/date.hpp>

namespace module {

static const auto NOTIFICATION_PERIOD = std::chrono::seconds(1);

EvSessionInfo::EvSessionInfo() : state("Unknown") {
}

void EvSessionInfo::reset() {
std::lock_guard<std::mutex> lock(this->session_info_mutex);
this->state = "Unknown";
}

void EvSessionInfo::update_state(const std::string& event) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe rename event here? I think it might be a little bit confusing to call this variable event when it actually represents the state

std::lock_guard<std::mutex> lock(this->session_info_mutex);
this->state = event;
}

EvSessionInfo::operator std::string() {
std::lock_guard<std::mutex> lock(this->session_info_mutex);

auto now = date::utc_clock::now();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be made const?


json session_info = json::object({
{"state", this->state},
{"datetime", Everest::Date::to_rfc3339(now)},
});

return session_info.dump();
}

void EvAPI::init() {
invoke_init(*p_main);

std::vector<std::string> 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<EvSessionInfo>());
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/";

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);
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it could improve readability if those blocks are refactored to static functions like publish_ev_info and publish_session_info


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) {
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_ev_connectors, ev_connectors]() {
auto next_tick = std::chrono::steady_clock::now();
while (this->running) {
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);
}
}));
}

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
106 changes: 106 additions & 0 deletions modules/EvAPI/EvAPI.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// 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 <generated/interfaces/empty/Implementation.hpp>

// headers for required interface implementations
#include <generated/interfaces/error_history/Interface.hpp>
#include <generated/interfaces/ev_manager/Interface.hpp>

// ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1
// insert your custom include headers here
#include <condition_variable>
#include <list>
#include <memory>
#include <mutex>
#include <sstream>

#include <date/date.h>
#include <date/tz.h>

namespace module {

class LimitDecimalPlaces;

class EvSessionInfo {
public:
EvSessionInfo();

void reset();
void update_state(const std::string& event);

/// \brief Converts this struct into a serialized json object
operator std::string();

private:
std::mutex session_info_mutex;
std::string state = "Unknown";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think an enum could be preferable here. It would make it clearer what the possible values can be

Copy link
Contributor

@SebaLukas SebaLukas Nov 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, state should be types::board_support_common::event and not std::string

};
} // 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<emptyImplBase> p_main,
std::vector<std::unique_ptr<ev_managerIntf>> r_ev_manager,
std::vector<std::unique_ptr<error_historyIntf>> 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<emptyImplBase> p_main;
const std::vector<std::unique_ptr<ev_managerIntf>> r_ev_manager;
const std::vector<std::unique_ptr<error_historyIntf>> 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<std::thread> api_threads;

Check notice on line 91 in modules/EvAPI/EvAPI.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/EvAPI/EvAPI.hpp#L91

class member 'EvAPI::api_threads' is never used.
bool running = true;

std::list<std::unique_ptr<EvSessionInfo>> info;

Check notice on line 94 in modules/EvAPI/EvAPI.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/EvAPI/EvAPI.hpp#L94

class member 'EvAPI::info' is never used.

const std::string api_base = "everest_api/";

Check notice on line 96 in modules/EvAPI/EvAPI.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/EvAPI/EvAPI.hpp#L96

class member 'EvAPI::api_base' is never used.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps make this a static inline constexpr std::string_view

// 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
2 changes: 2 additions & 0 deletions modules/EvAPI/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# EvAPI module documentation

Check notice on line 1 in modules/EvAPI/README.md

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/EvAPI/README.md#L1

Expected: 1; Actual: 0; Below

Check notice on line 1 in modules/EvAPI/README.md

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/EvAPI/README.md#L1

Expected: [None]; Actual: # EvAPI module documentation
This module is responsible for providing a simple MQTT based API to EVerest internals exposing EvManager related functionality

Check notice on line 2 in modules/EvAPI/README.md

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/EvAPI/README.md#L2

Expected: 80; Actual: 126

Check notice on line 2 in modules/EvAPI/README.md

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/EvAPI/README.md#L2

Files should end with a single newline character
16 changes: 16 additions & 0 deletions modules/EvAPI/main/emptyImpl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest

#include "emptyImpl.hpp"

namespace module {
namespace main {

void emptyImpl::init() {
}

void emptyImpl::ready() {
}

} // namespace main
} // namespace module
60 changes: 60 additions & 0 deletions modules/EvAPI/main/emptyImpl.hpp
Original file line number Diff line number Diff line change
@@ -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 <generated/interfaces/empty/Implementation.hpp>

#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<EvAPI>& 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<EvAPI>& 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
22 changes: 22 additions & 0 deletions modules/EvAPI/manifest.yaml
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions modules/EvManager/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
Loading