33
44//! Formula module for the logical meter.
55
6- use frequenz_microgrid_component_graph:: Formula as _;
7- mod aggregation_formula;
8- mod coalesce_formula;
6+ use async_trait:: async_trait;
7+ pub ( crate ) mod aggregation_formula;
8+ mod async_formula;
9+ pub ( crate ) mod coalesce_formula;
910pub ( crate ) mod graph_formula_provider;
10- pub use aggregation_formula:: AggregationFormula ;
11- pub use coalesce_formula:: CoalesceFormula ;
11+ pub use async_formula:: Formula ;
1212
13- use crate :: { Error , Sample , metric:: Metric , quantity:: Quantity } ;
13+ use crate :: {
14+ Error , Sample , logical_meter:: formula:: async_formula:: FormulaOperand , metric:: Metric ,
15+ quantity:: Quantity ,
16+ } ;
1417use tokio:: sync:: { broadcast, mpsc} ;
1518
1619use super :: logical_meter_actor;
1720
1821/// Connects logical meter formulas to the component graph formulas.
19- pub ( crate ) trait GraphFormulaProvider : std:: fmt:: Display {
22+ pub ( crate ) trait GraphFormulaConnector : std:: fmt:: Display {
2023 type GraphFormulaType : frequenz_microgrid_component_graph:: Formula ;
2124}
2225
23- /// Defines a formula that can be subscribed to for receiving samples.
24- pub ( crate ) trait FormulaSubscriber : std:: fmt:: Display {
25- type MetricType : Metric ;
26-
27- fn subscribe (
28- & self ,
29- ) -> impl Future <
30- Output = Result <
31- broadcast:: Receiver < Sample < <Self :: MetricType as Metric >:: QuantityType > > ,
32- Error ,
33- > ,
34- > + Send ;
26+ #[ async_trait]
27+ pub trait FormulaSubscriber : std:: fmt:: Display + Sync + Send {
28+ type QuantityType : Quantity ;
29+ async fn subscribe ( & self ) -> Result < broadcast:: Receiver < Sample < Self :: QuantityType > > , Error > ;
3530}
3631
3732/// Parameters for creating a logical meter formula.
38- pub ( super ) struct FormulaParams < F : GraphFormulaProvider , M : Metric > {
33+ pub ( super ) struct FormulaParams < F : GraphFormulaConnector , M : Metric > {
3934 pub ( super ) formula : F :: GraphFormulaType ,
4035 pub ( super ) metric : M ,
4136 pub ( super ) instructions_tx : mpsc:: Sender < logical_meter_actor:: Instruction > ,
4237}
4338
44- impl < F : GraphFormulaProvider , M : Metric > FormulaParams < F , M > {
39+ impl < F : GraphFormulaConnector , M : Metric > FormulaParams < F , M > {
4540 pub ( super ) fn new (
4641 formula : F :: GraphFormulaType ,
4742 metric : M ,
@@ -55,54 +50,108 @@ impl<F: GraphFormulaProvider, M: Metric> FormulaParams<F, M> {
5550 }
5651}
5752
58- /// A trait that defines generic formula operations.
59- pub trait Formula < Q : Quantity > : std:: fmt:: Display + Sized {
60- fn coalesce ( self , other : Self ) -> Result < Self , Error > ;
61- fn min ( self , other : Self ) -> Result < Self , Error > ;
62- fn max ( self , other : Self ) -> Result < Self , Error > ;
63- fn subscribe (
64- & self ,
65- ) -> impl Future < Output = Result < broadcast:: Receiver < Sample < Q > > , Error > > + Send ;
53+ // TODO: extend previous Coalesce instead of creating a new one, etc.
54+ impl < Q > Formula < Q >
55+ where
56+ Q : Quantity + ' static ,
57+ {
58+ pub fn coalesce ( self , other : Formula < Q > ) -> Result < Formula < Q > , Error > {
59+ match self {
60+ Formula :: Coalesce ( mut items) => {
61+ items. push ( other. into ( ) ) ;
62+ Ok ( Formula :: Coalesce ( items) )
63+ }
64+ _ => Ok ( Formula :: Coalesce ( vec ! [
65+ FormulaOperand :: Formula ( Box :: new( Formula :: <Q , Q , f32 >:: Subscriber ( Box :: new( self ) ) ) ) ,
66+ other. into( ) ,
67+ ] ) ) ,
68+ }
69+ }
70+
71+ pub fn min ( self , other : Formula < Q > ) -> Result < Formula < Q > , Error > {
72+ match self {
73+ Formula :: Min ( mut items) => {
74+ items. push ( other. into ( ) ) ;
75+ Ok ( Formula :: Min ( items) )
76+ }
77+ _ => Ok ( Formula :: Min ( vec ! [
78+ FormulaOperand :: Formula ( Box :: new( Formula :: <Q , Q , f32 >:: Subscriber ( Box :: new( self ) ) ) ) ,
79+ other. into( ) ,
80+ ] ) ) ,
81+ }
82+ }
83+
84+ pub fn max ( self , other : Formula < Q > ) -> Result < Formula < Q > , Error > {
85+ match self {
86+ Formula :: Max ( mut items) => {
87+ items. push ( other. into ( ) ) ;
88+ Ok ( Formula :: Max ( items) )
89+ }
90+ _ => Ok ( Formula :: Max ( vec ! [
91+ FormulaOperand :: Formula ( Box :: new( Formula :: <Q , Q , f32 >:: Subscriber ( Box :: new( self ) ) ) ) ,
92+ other. into( ) ,
93+ ] ) ) ,
94+ }
95+ }
96+
97+ pub fn avg ( self , others : Vec < Formula < Q > > ) -> Result < Formula < Q > , Error > {
98+ let mut exprs: Vec < FormulaOperand < Q > > =
99+ vec ! [ FormulaOperand :: Formula ( Box :: new(
100+ Formula :: <Q , Q , f32 >:: Subscriber ( Box :: new( self ) ) ,
101+ ) ) ] ;
102+ for other in others {
103+ exprs. push ( other. into ( ) ) ;
104+ }
105+ Ok ( Formula :: Avg ( exprs) )
106+ }
107+
108+ pub async fn subscribe ( & self ) -> Result < broadcast:: Receiver < Sample < Q > > , Error > {
109+ <Self as FormulaSubscriber >:: subscribe ( self ) . await
110+ }
66111}
67112
68- impl < T , Q , M > Formula < Q > for T
113+ impl < Q , F > std :: ops :: Add < F > for Formula < Q >
69114where
70- T : FormulaSubscriber < MetricType = M >
71- + GraphFormulaProvider
72- + From < FormulaParams < T , M > >
73- + Into < FormulaParams < T , M > >
74- + std:: fmt:: Display ,
75- Q : Quantity ,
76- M : Metric < QuantityType = Q > ,
115+ F : Into < FormulaOperand < Q > > ,
116+ Q : Quantity + ' static ,
77117{
78- fn coalesce ( self , other : Self ) -> Result < Self , Error > {
79- let mut params_self: FormulaParams < T , M > = self . into ( ) ;
80- let params_other: FormulaParams < T , M > = other. into ( ) ;
118+ type Output = Formula < Q > ;
81119
82- params_self . formula = params_self . formula . coalesce ( params_other . formula ) ;
83- Ok ( params_self . into ( ) )
120+ fn add ( self , other : F ) -> Self :: Output {
121+ Formula :: Add ( vec ! [ FormulaOperand :: Formula ( Box :: new ( self ) ) , other . into( ) ] )
84122 }
123+ }
85124
86- fn min ( self , other : Self ) -> Result < Self , Error > {
87- let mut params_self: FormulaParams < T , M > = self . into ( ) ;
88- let params_other: FormulaParams < T , M > = other. into ( ) ;
125+ impl < Q , F > std:: ops:: Sub < F > for Formula < Q >
126+ where
127+ F : Into < FormulaOperand < Q > > ,
128+ Q : Quantity + ' static ,
129+ {
130+ type Output = Formula < Q > ;
89131
90- params_self . formula = params_self . formula . min ( params_other . formula ) ;
91- Ok ( params_self . into ( ) )
132+ fn sub ( self , other : F ) -> Self :: Output {
133+ Formula :: Subtract ( vec ! [ FormulaOperand :: Formula ( Box :: new ( self ) ) , other . into( ) ] )
92134 }
135+ }
93136
94- fn max ( self , other : Self ) -> Result < Self , Error > {
95- let mut params_self: FormulaParams < T , M > = self . into ( ) ;
96- let params_other: FormulaParams < T , M > = other. into ( ) ;
137+ impl < Q > std:: ops:: Mul < f32 > for Formula < Q , Q , f32 >
138+ where
139+ Q : Quantity + ' static ,
140+ {
141+ type Output = Formula < Q , Q , f32 > ;
97142
98- params_self . formula = params_self . formula . max ( params_other . formula ) ;
99- Ok ( params_self . into ( ) )
143+ fn mul ( self , other : f32 ) -> Self :: Output {
144+ Formula :: < Q , Q , f32 > :: Multiply ( FormulaOperand :: < Q > :: Formula ( Box :: new ( self ) ) , other . into ( ) )
100145 }
146+ }
147+
148+ impl < Q > std:: ops:: Div < f32 > for Formula < Q , Q , f32 >
149+ where
150+ Q : Quantity + ' static ,
151+ {
152+ type Output = Formula < Q , Q , f32 > ;
101153
102- fn subscribe (
103- & self ,
104- ) -> impl Future < Output = Result < broadcast:: Receiver < Sample < M :: QuantityType > > , Error > > + Send
105- {
106- <T as FormulaSubscriber >:: subscribe ( self )
154+ fn div ( self , rhs : f32 ) -> Self :: Output {
155+ Formula :: < Q , Q , f32 > :: Divide ( FormulaOperand :: < Q > :: Formula ( Box :: new ( self ) ) , rhs. into ( ) )
107156 }
108157}
0 commit comments