|
6 | 6 | //! Instructions received by this handle are sent to the microgrid client actor, |
7 | 7 | //! which owns the connection to the microgrid API service. |
8 | 8 |
|
| 9 | +use chrono::TimeDelta; |
9 | 10 | use tokio::sync::{broadcast, mpsc, oneshot}; |
10 | 11 | use tonic::transport::Channel; |
11 | 12 |
|
12 | 13 | use crate::{ |
13 | | - Error, |
| 14 | + Bounds, Error, |
14 | 15 | client::MicrogridApiClient, |
| 16 | + metric::Metric, |
15 | 17 | proto::{ |
| 18 | + common::metrics::Bounds as PbBounds, |
16 | 19 | common::microgrid::electrical_components::{ |
17 | 20 | ElectricalComponent, ElectricalComponentCategory, ElectricalComponentConnection, |
18 | 21 | ElectricalComponentTelemetry, |
@@ -155,6 +158,55 @@ impl MicrogridClientHandle { |
155 | 158 | .await |
156 | 159 | .map_err(|e| Error::internal(format!("failed to receive response: {e}")))? |
157 | 160 | } |
| 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 | + } |
158 | 210 | } |
159 | 211 |
|
160 | 212 | #[cfg(test)] |
|
0 commit comments