Skip to content

Commit 92a2c76

Browse files
committed
inprogress
Signed-off-by: Sahas Subramanian <sahas.subramanian@proton.me>
1 parent 6cb1337 commit 92a2c76

7 files changed

Lines changed: 189 additions & 63 deletions

File tree

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ path = "src/lib.rs"
99

1010
[dependencies]
1111
chrono = "0.4"
12-
frequenz-microgrid-component-graph = { git = "https://github.com/frequenz-floss/frequenz-microgrid-component-graph-rs.git", rev = "94dc826" }
13-
frequenz-microgrid-formula-engine = { git = "https://github.com/frequenz-floss/frequenz-microgrid-formula-engine-rs.git", rev = "e0567c0" }
12+
frequenz-microgrid-component-graph = { git = "https://github.com/frequenz-floss/frequenz-microgrid-component-graph-rs.git", rev = "9912648" }
13+
frequenz-microgrid-formula-engine = { git = "https://github.com/frequenz-floss/frequenz-microgrid-formula-engine-rs.git", rev = "463414a" }
1414
frequenz-resampling = { git = "https://github.com/frequenz-floss/frequenz-resampling-rs.git", rev = "ce84d66" }
1515
prost = "0.13"
1616
prost-types = "0.13"
1717
tokio = { version = "1.45", features = ["rt", "rt-multi-thread"] }
1818
tonic = "0.13"
1919
tracing = { version = "0.1" }
20-
tracing-subscriber = { version = "0.3" }
20+
tracing-subscriber = { version = "0.3", features = ["std", "env-filter"] }
2121

2222

2323
[build-dependencies]

examples/logical_meter.rs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,17 @@ use chrono::TimeDelta;
55
use frequenz_microgrid::{
66
Error, Formula, LogicalMeterConfig, LogicalMeterHandle, MicrogridClientHandle, metric,
77
};
8+
use tracing_subscriber::{
9+
EnvFilter,
10+
fmt::{self},
11+
prelude::*,
12+
};
813

914
#[tokio::main]
1015
async fn main() -> Result<(), Error> {
11-
tracing_subscriber::fmt::fmt()
12-
.with_file(true)
13-
.with_line_number(true)
16+
tracing_subscriber::registry()
17+
.with(EnvFilter::new("info,frequenz_microgrid=debug"))
18+
.with(fmt::layer().with_file(true).with_line_number(true))
1419
.init();
1520

1621
let client = MicrogridClientHandle::new("http://[::1]:8800");
@@ -36,7 +41,7 @@ async fn main() -> Result<(), Error> {
3641
let mut battery_rx = formula_battery.subscribe().await?;
3742
let mut consumer_rx = formula_consumer.subscribe().await?;
3843

39-
for _ in 0..10 {
44+
for _ in 0..3 {
4045
let sample = rx.recv().await.unwrap();
4146
let grid_sample = grid_rx.recv().await.unwrap();
4247
let battery_sample = battery_rx.recv().await.unwrap();
@@ -49,8 +54,19 @@ async fn main() -> Result<(), Error> {
4954
sample.value().unwrap()
5055
);
5156
}
52-
53-
let formula_grid_voltage = logical_meter.grid(metric::AcVoltagePhase1N)?;
57+
// drop(rx);
58+
// drop(grid_rx);
59+
// drop(battery_rx);
60+
// drop(consumer_rx);
61+
let bat_form = logical_meter.battery(None, metric::AcVoltagePhase1N)?;
62+
let pv_form = logical_meter.pv(None, metric::AcVoltagePhase1N)?;
63+
// println!("bat_form: {}", bat_form);
64+
// println!("pv_form: {}", pv_form);
65+
// let formula_grid_voltage = bat_form.coalesce(pv_form)?;
66+
let formula_grid_voltage = logical_meter
67+
.battery(None, metric::AcVoltagePhase1N)?
68+
.coalesce(logical_meter.pv(None, metric::AcVoltagePhase1N)?)?;
69+
println!("formula_grid_voltage: {}", formula_grid_voltage);
5470
let mut grid_voltage_rx = formula_grid_voltage.subscribe().await?;
5571
loop {
5672
let sample = grid_voltage_rx.recv().await.unwrap();

src/logical_meter/formula.rs

Lines changed: 89 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,101 @@
33

44
//! Formula module for the logical meter.
55
6+
use frequenz_microgrid_component_graph::Formula as _;
67
mod aggregation_formula;
78
mod coalesce_formula;
89
pub(crate) mod graph_formula_provider;
910
pub use aggregation_formula::AggregationFormula;
1011
pub use coalesce_formula::CoalesceFormula;
1112

12-
use crate::{Error, Sample};
13-
use tokio::sync::broadcast;
13+
use crate::{Error, Sample, proto::common::v1::metrics::Metric};
14+
use tokio::sync::{broadcast, mpsc};
1415

15-
/// Defines a formula that can be subscribed to for receiving samples.
16-
pub trait Formula: std::fmt::Display {
16+
use super::logical_meter_actor;
17+
18+
pub(super) struct FormulaParams<F: FormulaSubscriber> {
19+
pub(super) formula: F::GraphFormulaType,
20+
pub(super) metric: Metric,
21+
pub(super) instructions_tx: mpsc::Sender<logical_meter_actor::Instruction>,
22+
}
23+
24+
impl<F: FormulaSubscriber> FormulaParams<F> {
25+
pub(super) fn new(
26+
formula: F::GraphFormulaType,
27+
metric: Metric,
28+
instructions_tx: mpsc::Sender<logical_meter_actor::Instruction>,
29+
) -> Self {
30+
Self {
31+
formula,
32+
metric,
33+
instructions_tx,
34+
}
35+
}
36+
}
37+
38+
pub(crate) trait FormulaSubscriber: std::fmt::Display {
39+
type GraphFormulaType: frequenz_microgrid_component_graph::Formula;
40+
fn subscribe(&self) -> impl Future<Output = Result<broadcast::Receiver<Sample>, Error>> + Send;
41+
}
42+
43+
/// A trait that defines generic formula operations.
44+
pub trait Formula: std::fmt::Display + Sized {
45+
fn coalesce(self, other: Self) -> Result<Self, Error>;
46+
fn min(self, other: Self) -> Result<Self, Error>;
47+
fn max(self, other: Self) -> Result<Self, Error>;
1748
fn subscribe(&self) -> impl Future<Output = Result<broadcast::Receiver<Sample>, Error>> + Send;
1849
}
50+
51+
impl<T> Formula for T
52+
where
53+
T: FormulaSubscriber + From<FormulaParams<T>> + Into<FormulaParams<T>> + std::fmt::Display,
54+
{
55+
fn coalesce(self, other: Self) -> Result<Self, Error> {
56+
let mut params_self: FormulaParams<T> = self.into();
57+
let params_other: FormulaParams<T> = other.into();
58+
59+
if params_self.metric != params_other.metric {
60+
return Err(Error::invalid_metric(format!(
61+
"Cannot coalesce formulas with different metrics: {} and {}",
62+
params_self.metric.as_str_name(),
63+
params_other.metric.as_str_name()
64+
)));
65+
}
66+
params_self.formula = params_self.formula.coalesce(params_other.formula);
67+
Ok(params_self.into())
68+
}
69+
70+
fn min(self, other: Self) -> Result<Self, Error> {
71+
let mut params_self: FormulaParams<T> = self.into();
72+
let params_other: FormulaParams<T> = other.into();
73+
74+
if params_self.metric != params_other.metric {
75+
return Err(Error::invalid_metric(format!(
76+
"Cannot take min of formulas with different metrics: {} and {}",
77+
params_self.metric.as_str_name(),
78+
params_other.metric.as_str_name()
79+
)));
80+
}
81+
params_self.formula = params_self.formula.min(params_other.formula);
82+
Ok(params_self.into())
83+
}
84+
85+
fn max(self, other: Self) -> Result<Self, Error> {
86+
let mut params_self: FormulaParams<T> = self.into();
87+
let params_other: FormulaParams<T> = other.into();
88+
89+
if params_self.metric != params_other.metric {
90+
return Err(Error::invalid_metric(format!(
91+
"Cannot take max of formulas with different metrics: {} and {}",
92+
params_self.metric.as_str_name(),
93+
params_other.metric.as_str_name()
94+
)));
95+
}
96+
params_self.formula = params_self.formula.max(params_other.formula);
97+
Ok(params_self.into())
98+
}
99+
100+
fn subscribe(&self) -> impl Future<Output = Result<broadcast::Receiver<Sample>, Error>> + Send {
101+
<T as FormulaSubscriber>::subscribe(self)
102+
}
103+
}

src/logical_meter/formula/aggregation_formula.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
//! An formula that supports aggregation operations.
55
6-
use super::Formula;
6+
use super::{FormulaParams, FormulaSubscriber};
77
use crate::{
88
Error, Sample, logical_meter::logical_meter_actor, proto::common::v1::metrics::Metric,
99
};
@@ -22,21 +22,29 @@ impl std::fmt::Display for AggregationFormula {
2222
}
2323
}
2424

25-
impl AggregationFormula {
26-
pub(crate) fn new(
27-
formula: frequenz_microgrid_component_graph::AggregationFormula,
28-
metric: Metric,
29-
instructions_tx: mpsc::Sender<logical_meter_actor::Instruction>,
30-
) -> Self {
25+
impl From<FormulaParams<AggregationFormula>> for AggregationFormula {
26+
fn from(params: FormulaParams<AggregationFormula>) -> Self {
3127
Self {
32-
formula,
33-
metric,
34-
instructions_tx,
28+
formula: params.formula,
29+
metric: params.metric,
30+
instructions_tx: params.instructions_tx,
3531
}
3632
}
3733
}
3834

39-
impl Formula for AggregationFormula {
35+
impl From<AggregationFormula> for FormulaParams<AggregationFormula> {
36+
fn from(formula: AggregationFormula) -> Self {
37+
FormulaParams {
38+
formula: formula.formula,
39+
metric: formula.metric,
40+
instructions_tx: formula.instructions_tx,
41+
}
42+
}
43+
}
44+
45+
impl FormulaSubscriber for AggregationFormula {
46+
type GraphFormulaType = frequenz_microgrid_component_graph::AggregationFormula;
47+
4048
async fn subscribe(&self) -> Result<broadcast::Receiver<Sample>, Error> {
4149
let (tx, rx) = oneshot::channel();
4250

@@ -67,7 +75,7 @@ impl std::ops::Add for AggregationFormula {
6775
)));
6876
}
6977
let new_formula = self.formula + other.formula;
70-
Ok(Self::new(new_formula, self.metric, self.instructions_tx))
78+
Ok(FormulaParams::new(new_formula, self.metric, self.instructions_tx).into())
7179
}
7280
}
7381

@@ -82,7 +90,7 @@ impl std::ops::Sub for AggregationFormula {
8290
)));
8391
}
8492
let new_formula = self.formula - other.formula;
85-
Ok(Self::new(new_formula, self.metric, self.instructions_tx))
93+
Ok(FormulaParams::new(new_formula, self.metric, self.instructions_tx).into())
8694
}
8795
}
8896

src/logical_meter/formula/coalesce_formula.rs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
//! An coalesce formula.
55
6-
use super::Formula;
6+
use super::{FormulaParams, FormulaSubscriber};
77
use crate::{
88
Error, Sample, logical_meter::logical_meter_actor, proto::common::v1::metrics::Metric,
99
};
@@ -22,21 +22,29 @@ impl std::fmt::Display for CoalesceFormula {
2222
}
2323
}
2424

25-
impl CoalesceFormula {
26-
pub(crate) fn new(
27-
formula: frequenz_microgrid_component_graph::CoalesceFormula,
28-
metric: Metric,
29-
instructions_tx: mpsc::Sender<logical_meter_actor::Instruction>,
30-
) -> Self {
25+
impl From<FormulaParams<CoalesceFormula>> for CoalesceFormula {
26+
fn from(params: FormulaParams<CoalesceFormula>) -> Self {
3127
Self {
32-
formula,
33-
metric,
34-
instructions_tx,
28+
formula: params.formula,
29+
metric: params.metric,
30+
instructions_tx: params.instructions_tx,
3531
}
3632
}
3733
}
3834

39-
impl Formula for CoalesceFormula {
35+
impl From<CoalesceFormula> for FormulaParams<CoalesceFormula> {
36+
fn from(formula: CoalesceFormula) -> Self {
37+
FormulaParams {
38+
formula: formula.formula,
39+
metric: formula.metric,
40+
instructions_tx: formula.instructions_tx,
41+
}
42+
}
43+
}
44+
45+
impl FormulaSubscriber for CoalesceFormula {
46+
type GraphFormulaType = frequenz_microgrid_component_graph::CoalesceFormula;
47+
4048
async fn subscribe(&self) -> Result<broadcast::Receiver<Sample>, Error> {
4149
let (tx, rx) = oneshot::channel();
4250

src/logical_meter/formula/graph_formula_provider.rs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//! A composable formula type, that can be subscribed to.
55
66
use crate::Error;
7+
use crate::logical_meter::formula::FormulaParams;
78
use crate::logical_meter::logical_meter_actor;
89
use crate::proto::common::v1::microgrid::components::Component;
910
use crate::proto::common::v1::microgrid::components::ComponentConnection;
@@ -14,13 +15,14 @@ use tokio::sync::mpsc;
1415
use super::{AggregationFormula, CoalesceFormula};
1516

1617
macro_rules! graph_formula_provider {
17-
($(($fnname:ident $(, $idsparam:ident)?)),+ $(,)?) => {$(
18+
($(($fnname:ident $(, ids:$idsparam:ident)? $(, id:$idparam:ident)?)),+ $(,)?) => {$(
1819

1920
fn $fnname<M: crate::metric::metric_trait::AcMetric>(
2021
_graph: &ComponentGraph<Component, ComponentConnection>,
2122
_metric: M,
2223
_instructions_tx: mpsc::Sender<logical_meter_actor::Instruction>,
2324
$($idsparam: Option<BTreeSet<u64>>,)?
25+
$($idparam: u64,)?
2426
) -> Result<Self, Error> {
2527
return Err(Error::component_graph_error(
2628
format!(
@@ -45,29 +47,37 @@ pub trait GraphFormulaProvider: Sized {
4547
(grid),
4648
(consumer),
4749
(producer),
48-
(battery, _battery_ids),
49-
(chp, _chp_ids),
50-
(pv, _pv_inverter_ids),
51-
(ev_charger, _ev_charger_ids),
50+
(battery, ids: _battery_ids),
51+
(chp, ids: _chp_ids),
52+
(pv, ids: _pv_inverter_ids),
53+
(ev_charger, ids: _ev_charger_ids),
54+
(component, id: _component_id),
5255
);
5356
}
5457

5558
macro_rules! impl_graph_formula_provider {
56-
($(($fnname:ident, $graphfnname:ident$(, $idsparam:ident)?)),+ $(,)?) => {$(
59+
($((
60+
$fnname:ident,
61+
$graphfnname:ident
62+
$(, ids:$idsparam:ident)?
63+
$(, id:$idparam:ident)?
64+
)),+ $(,)?) => {$(
5765

5866
fn $fnname<M: crate::metric::metric_trait::AcMetric>(
5967
graph: &ComponentGraph<Component, ComponentConnection>,
6068
_metric: M,
6169
instructions_tx: mpsc::Sender<logical_meter_actor::Instruction>,
6270
$($idsparam: Option<BTreeSet<u64>>,)?
71+
$($idparam: u64,)?
6372
) -> Result<Self, Error> {
64-
let formula = graph.$graphfnname($($idsparam)?).map_err(|e| {
73+
let formula = graph.$graphfnname($($idsparam)?$($idparam)?).map_err(|e| {
6574
Error::component_graph_error(
6675
format!("Could not get {} formula: {e}", stringify!($fnname))
6776
)
6877
})?;
69-
Ok(Self::new(formula, M::METRIC, instructions_tx))
78+
Ok(FormulaParams::new(formula, M::METRIC, instructions_tx).into())
7079
}
80+
7181
)+};
7282
}
7383

@@ -76,17 +86,19 @@ impl GraphFormulaProvider for AggregationFormula {
7686
(grid, grid_formula),
7787
(consumer, consumer_formula),
7888
(producer, producer_formula),
79-
(battery, battery_formula, battery_ids),
80-
(chp, chp_formula, chp_ids),
81-
(pv, pv_formula, pv_inverter_ids),
82-
(ev_charger, ev_charger_formula, ev_charger_ids),
89+
(battery, battery_formula, ids: battery_ids),
90+
(chp, chp_formula, ids: chp_ids),
91+
(pv, pv_formula, ids: pv_inverter_ids),
92+
(ev_charger, ev_charger_formula, ids: ev_charger_ids),
93+
(component, component_formula, id: component_id),
8394
);
8495
}
8596

8697
impl GraphFormulaProvider for CoalesceFormula {
8798
impl_graph_formula_provider!(
8899
(grid, grid_coalesce_formula),
89-
(battery, battery_ac_coalesce_formula, battery_ids),
90-
(pv, pv_ac_coalesce_formula, pv_inverter_ids),
100+
(battery, battery_ac_coalesce_formula, ids: battery_ids),
101+
(pv, pv_ac_coalesce_formula, ids: pv_inverter_ids),
102+
(component, component_ac_coalesce_formula, id: component_id),
91103
);
92104
}

0 commit comments

Comments
 (0)