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

Feature/energymanagement extensions #1033

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

corneliusclaussen
Copy link
Contributor

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

  • I have performed a self-review of my code
  • I have made corresponding changes to the documentation
  • I read the contribution documentation and made sure that my changes meet its requirements

@corneliusclaussen corneliusclaussen force-pushed the feature/energymanagement-extensions branch 5 times, most recently from 742536a to 58b9691 Compare January 31, 2025 08:13
@corneliusclaussen corneliusclaussen marked this pull request as ready for review January 31, 2025 08:14
- 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]>
@corneliusclaussen corneliusclaussen force-pushed the feature/energymanagement-extensions branch from 8b9093f to f9a6cfb Compare February 7, 2025 09:28
@Pietfried Pietfried added the post-release Tag that this PR should not go into the current merge window for the upcoming release label Feb 12, 2025
Copy link
Contributor

@Pietfried Pietfried left a 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
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
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
Copy link
Contributor

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
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
$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"};
Copy link
Contributor

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.) {
Copy link
Contributor

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) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
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) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
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

Comment on lines +74 to +77
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};
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
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};
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
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};
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
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};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
post-release Tag that this PR should not go into the current merge window for the upcoming release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants