Files
cariflex/tools/EVerest-main/modules/EnergyManagement/EnergyManager/Offer.cpp
Eric F d398a6ced2 Add extracted tools: CitrineOS, OpenOCPP, ShapeShifter
- CitrineOS core extracted (CSMS OCPP 2.0.1)
- OpenOCPP extracted (firmware OCPP 1.6J/2.0.1)
- ShapeShifter library installed (pip install -e)
- ShapeShifter specification extracted
- EVerest extracted

TODO updated with progress
2026-06-08 00:38:27 -04:00

108 lines
4.3 KiB
C++

// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#include "Offer.hpp"
#include <everest/logging.hpp>
#include <fmt/core.h>
namespace module {
std::ostream& operator<<(std::ostream& out, const Offer& self) {
/*out << "\nOffer:\n\nImport:\n------\n";
for (auto e : self.import_offer) {
out << e;
}
out << "\n\nExport:\n------\n";
for (auto e : self.export_offer) {
out << e;
}*/
const types::energy::NumberWithSource nonumber = {-9999.0, "Not set"};
out << fmt::format("\033[1;34mOffer[0]: Import {}A ({}) {}W ({}) Export {}A ({}) {}W ({})\033[1;0m",
self.import_offer[0].limits_to_root.ac_max_current_A.value_or(nonumber).value,
self.import_offer[0].limits_to_root.ac_max_current_A.value_or(nonumber).source,
self.import_offer[0].limits_to_root.total_power_W.value_or(nonumber).value,
self.import_offer[0].limits_to_root.total_power_W.value_or(nonumber).source,
self.export_offer[0].limits_to_root.ac_max_current_A.value_or(nonumber).value,
self.export_offer[0].limits_to_root.ac_max_current_A.value_or(nonumber).source,
self.export_offer[0].limits_to_root.total_power_W.value_or(nonumber).value,
self.export_offer[0].limits_to_root.total_power_W.value_or(nonumber).source);
return out;
}
template <class T> void apply_one_limit_if_smaller(std::optional<T>& a, const std::optional<T>& b) {
if (b.has_value()) {
if (a.has_value()) {
if (a.value().value > b.value().value) {
a = b.value();
} else if (a.value().value == b.value().value) {
a.value().source += "," + b.value().source;
}
} else {
a = b.value();
}
}
}
template <class T> void apply_one_limit_if_greater(std::optional<T>& a, const std::optional<T>& b) {
if (b.has_value()) {
if (a.has_value()) {
if (a.value().value < b.value().value) {
a = b.value();
} else if (a.value().value == b.value().value) {
a.value().source += "," + b.value().source;
}
} else {
a = b.value();
}
}
}
static void apply_limits(ScheduleReq& a, const ScheduleReq& b) {
if (a.size() != b.size()) {
EVLOG_error << fmt::format("apply_limits: a({}) and b({}) do not have the same size.", a.size(), b.size());
return;
}
for (ScheduleReq::size_type i = 0; i < a.size(); i++) {
// limits to leave are already merged to the root side, so we dont use them here
apply_one_limit_if_smaller(a[i].limits_to_root.ac_max_current_A, b[i].limits_to_root.ac_max_current_A);
apply_one_limit_if_smaller(a[i].limits_to_root.ac_max_phase_count, b[i].limits_to_root.ac_max_phase_count);
apply_one_limit_if_smaller(a[i].limits_to_root.total_power_W, b[i].limits_to_root.total_power_W);
apply_one_limit_if_greater(a[i].limits_to_root.ac_min_phase_count, b[i].limits_to_root.ac_min_phase_count);
apply_one_limit_if_greater(a[i].limits_to_root.ac_min_current_A, b[i].limits_to_root.ac_min_current_A);
// copy other information if any
a[i].price_per_kwh = b[i].price_per_kwh;
a[i].limits_to_root.ac_number_of_active_phases = b[i].limits_to_root.ac_number_of_active_phases;
}
}
Offer::Offer(Market& market) {
// create maximum offer for this market place
create_offer_for_local_market(market);
}
// Recursive: start at leaf, walk to root and create empty root offer. On the way back, apply all limits of local
// marketplaces until we are at the leaf again.
void Offer::create_offer_for_local_market(Market& market) {
if (!market.is_root()) {
create_offer_for_local_market(*market.parent());
} else {
// initialize time slots
import_offer = globals.empty_schedule_req;
export_offer = globals.empty_schedule_req;
}
// limit offer with limits at this market place
apply_limits(import_offer, market.get_available_energy_import());
// limit offer with limits at this market place
apply_limits(export_offer, market.get_available_energy_export());
optimizer_target = market.energy_flow_request.optimizer_target;
}
} // namespace module