Skip to content

Commit 35b40a3

Browse files
committed
Support augmenting bounds from the client
Signed-off-by: Sahas Subramanian <sahas.subramanian@proton.me>
1 parent 773fe54 commit 35b40a3

5 files changed

Lines changed: 118 additions & 7 deletions

File tree

src/client/instruction.rs

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

44
//! Instructions that can be sent to the client actor from client handles.
55
6+
use chrono::TimeDelta;
67
use tokio::sync::{broadcast, oneshot};
78

89
use crate::{
910
Error,
10-
proto::common::microgrid::electrical_components::{
11-
ElectricalComponent, ElectricalComponentCategory, ElectricalComponentConnection,
12-
ElectricalComponentTelemetry,
11+
proto::common::{
12+
metrics::{Bounds, Metric},
13+
microgrid::electrical_components::{
14+
ElectricalComponent, ElectricalComponentCategory, ElectricalComponentConnection,
15+
ElectricalComponentTelemetry,
16+
},
1317
},
1418
};
1519

@@ -30,4 +34,11 @@ pub(super) enum Instruction {
3034
destination_electrical_component_ids: Vec<u64>,
3135
response_tx: oneshot::Sender<Result<Vec<ElectricalComponentConnection>, Error>>,
3236
},
37+
AugmentElectricalComponentBounds {
38+
electrical_component_id: u64,
39+
target_metric: Metric,
40+
bounds: Vec<Bounds>,
41+
request_lifetime: Option<TimeDelta>,
42+
response_tx: oneshot::Sender<Result<Option<chrono::DateTime<chrono::Utc>>, Error>>,
43+
},
3344
}

src/client/microgrid_api_client.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use tonic::transport::Channel;
88

99
use crate::proto::microgrid::{
10+
AugmentElectricalComponentBoundsRequest, AugmentElectricalComponentBoundsResponse,
1011
ListElectricalComponentConnectionsRequest, ListElectricalComponentConnectionsResponse,
1112
ListElectricalComponentsRequest, ListElectricalComponentsResponse,
1213
ReceiveElectricalComponentTelemetryStreamRequest,
@@ -44,6 +45,11 @@ pub trait MicrogridApiClient: Send + Sync + 'static {
4445
&mut self,
4546
request: impl tonic::IntoRequest<ReceiveElectricalComponentTelemetryStreamRequest> + Send,
4647
) -> std::result::Result<tonic::Response<Self::TelemetryStream>, tonic::Status>;
48+
49+
async fn augment_electrical_component_bounds(
50+
&mut self,
51+
request: impl tonic::IntoRequest<AugmentElectricalComponentBoundsRequest> + Send,
52+
) -> std::result::Result<tonic::Response<AugmentElectricalComponentBoundsResponse>, tonic::Status>;
4753
}
4854

4955
/// Implement the MicrogridApiClient trait for the generated gRPC client.
@@ -78,4 +84,12 @@ impl MicrogridApiClient for crate::proto::microgrid::microgrid_client::Microgrid
7884
self.receive_electrical_component_telemetry_stream(request)
7985
.await
8086
}
87+
88+
async fn augment_electrical_component_bounds(
89+
&mut self,
90+
request: impl tonic::IntoRequest<AugmentElectricalComponentBoundsRequest> + Send,
91+
) -> std::result::Result<tonic::Response<AugmentElectricalComponentBoundsResponse>, tonic::Status>
92+
{
93+
self.augment_electrical_component_bounds(request).await
94+
}
8195
}

src/client/microgrid_client_actor.rs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ use crate::{
1111
ReceiveElectricalComponentTelemetryStreamResponse,
1212
},
1313
};
14-
use std::collections::HashMap;
15-
14+
use chrono::DateTime;
1615
use futures::{Stream, StreamExt};
16+
use std::collections::HashMap;
1717
use tokio::{
1818
select,
1919
sync::{broadcast, mpsc},
@@ -180,6 +180,39 @@ async fn handle_instruction<T: MicrogridApiClient>(
180180
.send(connections)
181181
.map_err(|_| Error::internal("failed to send response"))?;
182182
}
183+
Some(Instruction::AugmentElectricalComponentBounds {
184+
electrical_component_id,
185+
target_metric,
186+
bounds,
187+
request_lifetime,
188+
response_tx,
189+
}) => {
190+
let response = client
191+
.augment_electrical_component_bounds(
192+
crate::proto::microgrid::AugmentElectricalComponentBoundsRequest {
193+
electrical_component_id,
194+
target_metric: target_metric as i32,
195+
bounds: bounds,
196+
request_lifetime: request_lifetime.map(|d| d.as_seconds_f64() as u64),
197+
},
198+
)
199+
.await
200+
.map_err(|e| {
201+
Error::api_server_error(format!(
202+
"augment_electrical_component_bounds failed: {e}"
203+
))
204+
})
205+
.map(|r| {
206+
r.into_inner()
207+
.valid_until_time
208+
.map(|t| DateTime::from_timestamp(t.seconds, t.nanos as u32))
209+
.flatten()
210+
});
211+
212+
response_tx
213+
.send(response)
214+
.map_err(|_| Error::internal("failed to send response"))?;
215+
}
183216
None => {}
184217
}
185218

src/client/microgrid_client_handle.rs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@
66
//! Instructions received by this handle are sent to the microgrid client actor,
77
//! which owns the connection to the microgrid API service.
88
9+
use chrono::TimeDelta;
910
use tokio::sync::{broadcast, mpsc, oneshot};
1011
use tonic::transport::Channel;
1112

1213
use crate::{
13-
Error,
14+
Bounds, Error,
1415
client::MicrogridApiClient,
16+
metric::Metric,
1517
proto::{
18+
common::metrics::Bounds as PbBounds,
1619
common::microgrid::electrical_components::{
1720
ElectricalComponent, ElectricalComponentCategory, ElectricalComponentConnection,
1821
ElectricalComponentTelemetry,
@@ -155,6 +158,55 @@ impl MicrogridClientHandle {
155158
.await
156159
.map_err(|e| Error::internal(format!("failed to receive response: {e}")))?
157160
}
161+
162+
/// Augments the overall bounds for a given metric of a given electrical
163+
/// component with the provided bounds.
164+
/// Returns the UTC time at which the provided bounds will expire and its
165+
/// effects will no longer be visible in the overall bounds for the
166+
/// given metric.
167+
///
168+
/// The request parameters allows users to select a duration until
169+
/// which the bounds will stay in effect. If no duration is provided, then the
170+
/// bounds will be removed after a default duration of 5 seconds.
171+
///
172+
/// Inclusion bounds give the range that the system will try to keep the
173+
/// metric within. If the metric goes outside of these bounds, the system will
174+
/// try to bring it back within the bounds.
175+
/// If the bounds for a metric are [Symbol’s value as variable is void: lower_1End.
176+
/// ---- values here are considered out of range.
177+
/// ==== values here are considered within range.
178+
///
179+
/// Note that for power metrics, regardless of the bounds, 0W is always
180+
/// allowed.
181+
pub async fn augment_electrical_component_bounds<M, I>(
182+
&mut self,
183+
electrical_component_id: u64,
184+
#[allow(unused_variables)] target_metric: M,
185+
bounds: Vec<I>,
186+
request_lifetime: Option<TimeDelta>,
187+
) -> Result<Option<chrono::DateTime<chrono::Utc>>, Error>
188+
where
189+
M: Metric,
190+
Bounds<M::QuantityType>: Into<PbBounds>,
191+
I: Into<Bounds<M::QuantityType>>,
192+
{
193+
let (response_tx, response_rx) = oneshot::channel();
194+
195+
self.instructions_tx
196+
.send(Instruction::AugmentElectricalComponentBounds {
197+
response_tx,
198+
electrical_component_id,
199+
target_metric: M::METRIC,
200+
bounds: bounds.into_iter().map(|x| x.into().into()).collect(),
201+
request_lifetime,
202+
})
203+
.await
204+
.map_err(|_| Error::internal("failed to send instruction"))?;
205+
206+
response_rx
207+
.await
208+
.map_err(|e| Error::internal(format!("failed to receive response: {e}")))?
209+
}
158210
}
159211

160212
#[cfg(test)]

src/error.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ ErrorKind!(
5858
(ChronoError, chrono_error),
5959
(DroppedUnusedFormulas, dropped_unused_formulas),
6060
(FormulaEngineError, formula_engine_error),
61-
(Internal, internal)
61+
(Internal, internal),
62+
(APIServerError, api_server_error),
6263
);
6364

6465
/// An error that can occur during the creation or traversal of a

0 commit comments

Comments
 (0)