Skip to content

Commit

Permalink
fix: EnergyManager to select limit taking into account time (#610)
Browse files Browse the repository at this point in the history
* fix: EnergyManager to select limit taking into account time

EnergyManager calculates a list of optimised values and previously
selected the 1st item to set the root side limit.

Instead EnergyManager now traverses the list to find the
applicable limit based on the current time.
(the list can include schedules that have expired)

* fix: clang format
* fix: added additional boundary tests

Signed-off-by: James Chapman <[email protected]>
  • Loading branch information
james-ctc authored Mar 28, 2024
1 parent e3a6d05 commit 79121d4
Show file tree
Hide file tree
Showing 8 changed files with 1,097 additions and 16 deletions.
4 changes: 4 additions & 0 deletions modules/EnergyManager/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ target_sources(${MODULE_NAME}

# ev@c55432ab-152c-45a9-9d2e-7281d50c69c3:v1
# insert other things like install cmds etc here
# insert other things like install cmds etc here
if(EVEREST_CORE_BUILD_TESTING)
add_subdirectory(tests)
endif()
# ev@c55432ab-152c-45a9-9d2e-7281d50c69c3:v1
37 changes: 28 additions & 9 deletions modules/EnergyManager/EnergyManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "BrokerFastCharging.hpp"
#include "Market.hpp"
#include <fmt/core.h>
#include <optional>

using namespace std::literals::chrono_literals;

Expand Down Expand Up @@ -143,19 +144,37 @@ std::vector<types::energy::EnforcedLimits> EnergyManager::run_optimizer(types::e

for (auto broker : brokers) {
auto local_market = broker->get_local_market();
const auto sold_energy = local_market.get_sold_energy();

// EVLOG_info << "Sending enfored limits (import) to :" << local_market.energy_flow_request.uuid << " "
// << local_market.get_sold_energy_import()[0].limits_to_root;
types::energy::EnforcedLimits l;
l.uuid = local_market.energy_flow_request.uuid;
l.valid_until =
Everest::Date::to_rfc3339(date::utc_clock::now() + std::chrono::seconds(config.update_interval * 10));
if (sold_energy.size() > 0) {

l.limits_root_side = local_market.get_sold_energy()[0].limits_to_root;
types::energy::EnforcedLimits l;
l.uuid = local_market.energy_flow_request.uuid;
l.valid_until =
Everest::Date::to_rfc3339(globals.start_time + std::chrono::seconds(config.update_interval * 10));

l.schedule = local_market.get_sold_energy();
l.schedule = sold_energy;

optimized_values.push_back(l);
// select root limit from schedule based on globals.start_time
l.limits_root_side = sold_energy[0].limits_to_root;

for (const auto& s : sold_energy) {
const auto schedule_time = Everest::Date::from_rfc3339(s.timestamp);
if (globals.start_time < schedule_time) {
// all further schedules will be further into the future
break;
} else {
// use this schedule as the starting point
l.limits_root_side = s.limits_to_root;
}
}

optimized_values.push_back(l);

if (globals.debug && l.limits_root_side.has_value()) {
EVLOG_info << "Sending enfored limits (import) to :" << l.uuid << " " << l.limits_root_side.value();
}
}
}

return optimized_values;
Expand Down
17 changes: 17 additions & 0 deletions modules/EnergyManager/EnergyManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@
#include <utils/date.hpp>

#include <mutex>

#ifdef BUILD_TESTING_MODULE_ENERGY_MANAGER
#include <gtest/gtest_prod.h>
namespace module::test {
void schedule_test(const types::energy::EnergyFlowRequest& energy_flow_request, const std::string& start_time_str,
float expected_limit);
}

#endif
// ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1

namespace module {
Expand Down Expand Up @@ -76,6 +85,14 @@ class EnergyManager : public Everest::ModuleBase {

std::condition_variable mainloop_sleep_condvar;
std::mutex mainloop_sleep_mutex;

#ifdef BUILD_TESTING_MODULE_ENERGY_MANAGER
FRIEND_TEST(EnergyManagerTest, empty);
FRIEND_TEST(EnergyManagerTest, noSchedules);
FRIEND_TEST(EnergyManagerTest, schedules);
friend void test::schedule_test(const types::energy::EnergyFlowRequest& energy_flow_request,
const std::string& start_time_str, float expected_limit);
#endif
// ev@211cfdbe-f69a-4cd6-a4ec-f8aaa3d1b6c8:v1
};

Expand Down
8 changes: 4 additions & 4 deletions modules/EnergyManager/Market.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@ namespace module {

globals_t globals;

void globals_t::init(date::utc_clock::time_point start_time, int _interval_duration, int _schedule_duration,
void globals_t::init(date::utc_clock::time_point _start_time, int _interval_duration, int _schedule_duration,
float _slice_ampere, float _slice_watt, bool _debug,
const types::energy::EnergyFlowRequest& energy_flow_request) {
start_time = _start_time;
interval_duration = std::chrono::minutes(_interval_duration);
schedule_length = std::chrono::hours(_schedule_duration) / interval_duration;
slice_ampere = _slice_ampere;
slice_watt = _slice_watt;
debug = _debug;

create_timestamps(start_time, energy_flow_request);
create_timestamps(energy_flow_request);

zero_schedule_req = create_empty_schedule_req();

Expand All @@ -39,8 +40,7 @@ void globals_t::init(date::utc_clock::time_point start_time, int _interval_durat
empty_schedule_res = create_empty_schedule_res();
}

void globals_t::create_timestamps(const date::utc_clock::time_point& start_time,
const types::energy::EnergyFlowRequest& energy_flow_request) {
void globals_t::create_timestamps(const types::energy::EnergyFlowRequest& energy_flow_request) {

timestamps.clear();
timestamps.reserve(schedule_length);
Expand Down
6 changes: 3 additions & 3 deletions modules/EnergyManager/Market.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ typedef std::vector<types::energy::ScheduleResEntry> ScheduleRes;

class globals_t {
public:
void init(date::utc_clock::time_point start_time, int _interval_duration, int _schedule_duration,
void init(date::utc_clock::time_point _start_time, int _interval_duration, int _schedule_duration,
float _slice_ampere, float _slice_watt, bool _debug,
const types::energy::EnergyFlowRequest& energy_flow_request);
date::utc_clock::time_point start_time; // common start point
std::chrono::minutes interval_duration; // interval duration
int schedule_length; // total forcast length (in counts of (non-regular) intervals)
float slice_ampere; // ampere_slices for trades
Expand All @@ -29,8 +30,7 @@ class globals_t {
ScheduleRes zero_schedule_res, empty_schedule_res;

private:
void create_timestamps(const date::utc_clock::time_point& start_time,
const types::energy::EnergyFlowRequest& energy_flow_request);
void create_timestamps(const types::energy::EnergyFlowRequest& energy_flow_request);
void add_timestamps(const types::energy::EnergyFlowRequest& energy_flow_request);
ScheduleReq create_empty_schedule_req();
ScheduleRes create_empty_schedule_res();
Expand Down
34 changes: 34 additions & 0 deletions modules/EnergyManager/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
set(TEST_TARGET_NAME ${PROJECT_NAME}_EnergyManager_tests)
add_executable(${TEST_TARGET_NAME})

add_dependencies(${TEST_TARGET_NAME} ${MODULE_NAME})

get_target_property(GENERATED_INCLUDE_DIR generate_cpp_files EVEREST_GENERATED_INCLUDE_DIR)

target_include_directories(${TEST_TARGET_NAME} PRIVATE
. ..
${GENERATED_INCLUDE_DIR}
${CMAKE_BINARY_DIR}/generated/modules/${MODULE_NAME}
)

target_sources(${TEST_TARGET_NAME} PRIVATE
EnergyManagerTest.cpp
../Broker.cpp
../BrokerFastCharging.cpp
../EnergyManager.cpp
../Market.cpp
../Offer.cpp
)

target_compile_definitions(${TEST_TARGET_NAME} PRIVATE
BUILD_TESTING_MODULE_ENERGY_MANAGER
)

target_link_libraries(${TEST_TARGET_NAME} PRIVATE
GTest::gmock
GTest::gtest_main
everest::log
everest::framework
)

add_test(${TEST_TARGET_NAME} ${TEST_TARGET_NAME})
23 changes: 23 additions & 0 deletions modules/EnergyManager/tests/EnergyManagerImplStub.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest

#ifndef ENERGYMANAGERSTUB_H_
#define ENERGYMANAGERSTUB_H_

#include <generated/interfaces/energy_manager/Implementation.hpp>

//-----------------------------------------------------------------------------
namespace module::stub {

struct energy_managerImplStub : public energy_managerImplBase {
energy_managerImplStub() : energy_managerImplBase(nullptr, "manager") {
}
virtual void init() {
}
virtual void ready() {
}
};

} // namespace module::stub

#endif
Loading

0 comments on commit 79121d4

Please sign in to comment.