11// SPDX-License-Identifier: Apache-2.0
2- // Copyright 2022 - 2022 Pionix GmbH and Contributors to EVerest
2+ // Copyright Pionix GmbH and Contributors to EVerest
33
44#include " energyImpl.hpp"
5+ #include " energy_schedule_utils.hpp"
56#include < chrono>
67#include < date/date.h>
78#include < date/tz.h>
@@ -11,60 +12,59 @@ namespace module {
1112namespace energy_grid {
1213
1314void energyImpl::init () {
15+ auto energy_state_handle = energy_state.handle ();
1416
15- // UUID must be unique also beyond this charging station -> will be handled on framework level and above later
16- energy_flow_request.uuid = mod->info .id ;
17- energy_flow_request.node_type = types::energy::NodeType::Generic;
17+ energy_state_handle->energy_flow_request .uuid = mod->info .id ;
18+ energy_state_handle->energy_flow_request .node_type = types::energy::NodeType::Generic;
1819
1920 source_cfg = mod->info .id + " /module_config" ;
2021
2122 // Initialize with sane defaults
22- energy_flow_request.schedule_import = get_local_schedule ();
23- energy_flow_request.schedule_export = get_local_schedule ();
23+ energy_state_handle-> energy_flow_request .schedule_import = get_local_schedule ();
24+ energy_state_handle-> energy_flow_request .schedule_export = get_local_schedule ();
2425
2526 for (auto & entry : mod->r_energy_consumer ) {
2627 entry->subscribe_energy_flow_request ([this ](types::energy::EnergyFlowRequest e) {
2728 // Received new energy_flow_request object from a child. Update in the cached object and republish.
28- std::scoped_lock lock (energy_mutex );
29+ auto energy_state_handle = energy_state. handle ( );
2930
3031 bool child_found = false ;
31- for (auto & child : energy_flow_request.children ) {
32+ for (auto & child : energy_state_handle-> energy_flow_request .children ) {
3233 if (child.uuid == e.uuid ) {
3334 child = e;
3435 child_found = true ;
3536 }
3637 }
3738
3839 if (!child_found) {
39- energy_flow_request.children .push_back (e);
40+ energy_state_handle-> energy_flow_request .children .push_back (e);
4041 }
4142
42- publish_complete_energy_object ();
43+ publish_complete_energy_object (*energy_state_handle );
4344 });
4445 }
4546
4647 if (!mod->r_powermeter .empty ()) {
4748 mod->r_powermeter [0 ]->subscribe_powermeter ([this ](types::powermeter::Powermeter p) {
4849 EVLOG_debug << " Incoming powermeter readings: " << p;
49- std::scoped_lock lock (energy_mutex );
50- energy_flow_request.energy_usage_root = p;
51- publish_complete_energy_object ();
50+ auto energy_state_handle = energy_state. handle ( );
51+ energy_state_handle-> energy_flow_request .energy_usage_root = p;
52+ publish_complete_energy_object (*energy_state_handle );
5253 });
5354 }
5455
5556 if (!mod->r_price_information .empty ()) {
5657 mod->r_price_information [0 ]->subscribe_energy_pricing (
5758 [this ](types::energy_price_information::EnergyPriceSchedule p) {
5859 EVLOG_debug << " Incoming price schedule: " << p;
59- std::scoped_lock lock (energy_mutex );
60- energy_pricing = p;
61- publish_complete_energy_object ();
60+ auto energy_state_handle = energy_state. handle ( );
61+ energy_state_handle-> energy_pricing = p;
62+ publish_complete_energy_object (*energy_state_handle );
6263 });
6364 }
6465}
6566
6667types::energy::ScheduleReqEntry energyImpl::get_local_schedule_req_entry () {
67- // local schedule of this module
6868 types::energy::ScheduleReqEntry local_schedule;
6969 auto tp = date::utc_clock::now ();
7070
@@ -84,52 +84,39 @@ std::vector<types::energy::ScheduleReqEntry> energyImpl::get_local_schedule() {
8484}
8585
8686void energyImpl::set_external_limits (types::energy::ExternalLimits& l) {
87- std::scoped_lock lock (energy_mutex);
88-
89- energy_flow_request.schedule_import = l.schedule_import ;
90- if (not energy_flow_request.schedule_import .empty ()) {
91- // add limits from our own fuse settings
92- for (auto & e : energy_flow_request.schedule_import ) {
93- if (!e.limits_to_root .ac_max_current_A .has_value () ||
94- e.limits_to_root .ac_max_current_A .value ().value > mod->config .fuse_limit_A )
95- e.limits_to_root .ac_max_current_A = {static_cast <float >(mod->config .fuse_limit_A ), source_cfg};
96-
97- if (!e.limits_to_root .ac_max_phase_count .has_value () ||
98- e.limits_to_root .ac_max_phase_count .value ().value > mod->config .phase_count )
99- e.limits_to_root .ac_max_phase_count = {mod->config .phase_count , source_cfg};
100- }
87+ auto energy_state_handle = energy_state.handle ();
88+
89+ // Process import schedule
90+ energy_state_handle->energy_flow_request .schedule_import = l.schedule_import ;
91+ if (not energy_state_handle->energy_flow_request .schedule_import .empty ()) {
92+ module::energy_grid::process_schedule_with_limits (
93+ energy_state_handle->energy_flow_request .schedule_import , source_cfg, mod->config .fuse_limit_A ,
94+ mod->config .phase_count , mod->config .nominal_voltage_V , mod->config .enhance_external_schedule );
10195 } else {
10296 // At least add our local config limit even if the external limit did not set an import schedule
103- energy_flow_request.schedule_import = get_local_schedule ();
97+ energy_state_handle-> energy_flow_request .schedule_import = get_local_schedule ();
10498 }
10599
106- energy_flow_request.schedule_export = l.schedule_export ;
107-
108- if (not energy_flow_request.schedule_export .empty ()) {
109- // add limits from our own fuse settings
110- for (auto & e : energy_flow_request.schedule_export ) {
111- if (!e.limits_to_root .ac_max_current_A .has_value () ||
112- e.limits_to_root .ac_max_current_A .value ().value > mod->config .fuse_limit_A )
113- e.limits_to_root .ac_max_current_A = {static_cast <float >(mod->config .fuse_limit_A ), source_cfg};
114-
115- if (!e.limits_to_root .ac_max_phase_count .has_value () ||
116- e.limits_to_root .ac_max_phase_count .value ().value > mod->config .phase_count )
117- e.limits_to_root .ac_max_phase_count = {mod->config .phase_count , source_cfg};
118- }
100+ // Process export schedule
101+ energy_state_handle->energy_flow_request .schedule_export = l.schedule_export ;
102+ if (not energy_state_handle->energy_flow_request .schedule_export .empty ()) {
103+ module::energy_grid::process_schedule_with_limits (
104+ energy_state_handle->energy_flow_request .schedule_export , source_cfg, mod->config .fuse_limit_A ,
105+ mod->config .phase_count , mod->config .nominal_voltage_V , mod->config .enhance_external_schedule );
119106 } else {
120107 // At least add our local config limit even if the external limit did not set an export schedule
121- energy_flow_request.schedule_export = get_local_schedule ();
108+ energy_state_handle-> energy_flow_request .schedule_export = get_local_schedule ();
122109 }
123110
124- energy_flow_request.schedule_setpoints = l.schedule_setpoints ;
111+ energy_state_handle-> energy_flow_request .schedule_setpoints = l.schedule_setpoints ;
125112}
126113
127- void energyImpl::publish_complete_energy_object () {
128- // join the different schedules to the complete array (with resampling)
129- types::energy::EnergyFlowRequest energy_complete = energy_flow_request;
114+ void energyImpl::publish_complete_energy_object (const EnergyState& state ) {
115+ // This method is always called from contexts that already hold the energy_state lock
116+ types::energy::EnergyFlowRequest energy_complete = state. energy_flow_request ;
130117
131- if (not energy_flow_request.schedule_export .empty () and not energy_pricing.schedule_export .empty ()) {
132- merge_price_into_schedule (energy_complete.schedule_export , energy_pricing.schedule_export );
118+ if (not state. energy_flow_request .schedule_export .empty () and not state. energy_pricing .schedule_export .empty ()) {
119+ merge_price_into_schedule (energy_complete.schedule_export , state. energy_pricing .schedule_export );
133120 }
134121
135122 publish_energy_flow_request (energy_complete);
@@ -181,16 +168,18 @@ void energyImpl::merge_price_into_schedule(std::vector<types::energy::ScheduleRe
181168}
182169
183170void energyImpl::ready () {
171+ auto energy_state_handle = energy_state.handle ();
184172 // publish own limits at least once
185- publish_energy_flow_request (energy_flow_request);
173+ publish_energy_flow_request (energy_state_handle-> energy_flow_request );
186174 mod->signalExternalLimit .connect ([this ](types::energy::ExternalLimits& l) { set_external_limits (l); });
187175}
188176
189177void energyImpl::handle_enforce_limits (types::energy::EnforcedLimits& value) {
178+ auto energy_state_handle = energy_state.handle ();
190179
191180 // route to children if it is not for me
192181 // FIXME: this sends it to all children, we could do a lookup on which branch it actually is
193- if (value.uuid != energy_flow_request.uuid ) {
182+ if (value.uuid != energy_state_handle-> energy_flow_request .uuid ) {
194183 for (auto & entry : mod->r_energy_consumer ) {
195184 entry->call_enforce_limits (value);
196185 }
0 commit comments