-
Notifications
You must be signed in to change notification settings - Fork 90
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
Feature/energymanagement extensions #1033
base: main
Are you sure you want to change the base?
Conversation
742536a
to
58b9691
Compare
- Extended energy types to align with requirements of OCPP2.1 - EnergyManager: Source tracking for all limits - EnergyManagerSetpoints for ampere, watt and frequency tables - Allow to set setpoints via external_limits interface Signed-off-by: Piet Gömpel <[email protected]> Signed-off-by: Cornelius Claussen <[email protected]>
8b9093f
to
f9a6cfb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In addition to the commands in line:
- Please verify that the documentation for the EnergyManager module at
doc/index.rst
is still up-to-date . Looks like some examples are outdated and its probably useful add some words about the introduced setpoints. - There are some viable codacy remarks
description: The total power in W | ||
type: number | ||
SetpointType: | ||
description: Defines a setpoint |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
description: Defines a setpoint | |
description: Defines a setpoint, which is a target value for either charging or discharging depending on the sign. Setpoints per phase are currently not supported. |
type: object | ||
additionalProperties: false | ||
required: | ||
- timestamp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldnt the setpoint
be required as well or does it mean that there is no setpoint for this point in time if omited? I would add this to the documentation then.
@@ -232,13 +328,27 @@ types: | |||
items: | |||
description: One entry for the time series. Values are always positive. | |||
type: object | |||
$ref: /energy#/ScheduleReqEntry | |||
$ref: /energy#/ScheduleReqEntry |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$ref: /energy#/ScheduleReqEntry | |
$ref: /energy#/ScheduleReqEntry |
|
||
if (is_watts) { | ||
target_entry.limits_to_leaves.total_power_W = std::fabs(limit); | ||
target_entry.limits_to_leaves.total_power_W = {std::fabs(limit), "API_module"}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can be defined as constexpr
|
||
// Allow only one actual setpoint value to be set, in this priority order | ||
if (sp.ac_current_A.has_value()) { | ||
if (sp.ac_current_A.value() >= 0.) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if its relevant here, but you may want to use a small epsilon value here (and at other places) to avoid floating point precision errors
if (b) { | ||
if (a) { | ||
if (a.value() > b.value()) { | ||
template <class T> static void apply_one_limit_if_smaller(std::optional<T>& a, const std::optional<T>& b) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
template <class T> static void apply_one_limit_if_smaller(std::optional<T>& a, const std::optional<T>& b) { | |
template <class T> void apply_one_limit_if_smaller(std::optional<T>& a, const std::optional<T>& b) { |
templates have internal linkage by default
if (b) { | ||
if (a) { | ||
if (a.value() < b.value()) { | ||
template <class T> static void apply_one_limit_if_greater(std::optional<T>& a, const std::optional<T>& b) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
template <class T> static void apply_one_limit_if_greater(std::optional<T>& a, const std::optional<T>& b) { | |
template <class T> void apply_one_limit_if_greater(std::optional<T>& a, const std::optional<T>& b) { |
same here
local_schedule.limits_to_root.ac_max_phase_count = {mod->config.phase_count, source_cfg}; | ||
local_schedule.limits_to_root.ac_max_current_A = {(float)mod->config.fuse_limit_A, source_cfg}; | ||
local_schedule.limits_to_leaves.ac_max_phase_count = {mod->config.phase_count, source_cfg}; | ||
local_schedule.limits_to_leaves.ac_max_current_A = {(float)mod->config.fuse_limit_A, source_cfg}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
local_schedule.limits_to_root.ac_max_phase_count = {mod->config.phase_count, source_cfg}; | |
local_schedule.limits_to_root.ac_max_current_A = {(float)mod->config.fuse_limit_A, source_cfg}; | |
local_schedule.limits_to_leaves.ac_max_phase_count = {mod->config.phase_count, source_cfg}; | |
local_schedule.limits_to_leaves.ac_max_current_A = {(float)mod->config.fuse_limit_A, source_cfg}; | |
local_schedule.limits_to_root.ac_max_phase_count = {mod->config.phase_count, source_cfg}; | |
local_schedule.limits_to_root.ac_max_current_A = {static_cast<float>(mod->config.fuse_limit_A), source_cfg}; | |
local_schedule.limits_to_leaves.ac_max_phase_count = {mod->config.phase_count, source_cfg}; | |
local_schedule.limits_to_leaves.ac_max_current_A = {static_cast<float>(mod->config.fuse_limit_A), source_cfg}; |
for (auto& e : energy_flow_request.schedule_import) { | ||
if (!e.limits_to_root.ac_max_current_A.has_value() || | ||
e.limits_to_root.ac_max_current_A.value().value > mod->config.fuse_limit_A) | ||
e.limits_to_root.ac_max_current_A = {(float)mod->config.fuse_limit_A, source_cfg}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
e.limits_to_root.ac_max_current_A = {(float)mod->config.fuse_limit_A, source_cfg}; | |
e.limits_to_root.ac_max_current_A = {static_cast<float>(mod->config.fuse_limit_A), source_cfg}; |
for (auto& e : energy_flow_request.schedule_export) { | ||
if (!e.limits_to_root.ac_max_current_A.has_value() || | ||
e.limits_to_root.ac_max_current_A.value().value > mod->config.fuse_limit_A) | ||
e.limits_to_root.ac_max_current_A = {(float)mod->config.fuse_limit_A, source_cfg}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
e.limits_to_root.ac_max_current_A = {(float)mod->config.fuse_limit_A, source_cfg}; | |
e.limits_to_root.ac_max_current_A = {static_cast<float>(mod->config.fuse_limit_A), source_cfg}; |
Describe your changes
OCPP 2.1 bidi smart charging uses cases can be used to set setpoints for ampere, watt and watt/frequency table. It also requires to track which limit is actually limiting the charging power.
This PR adds support for both to the energy types and implements the changes in EnergyManager, EnergyNode and EvseManager.
Issue ticket number and link
Checklist before requesting a review