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
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
// 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
|
||||
Reference in New Issue
Block a user