Skip to main content

lager/nets/
custom.rs

1//! Custom-driver nets: instruments driven by a driver installed on the box
2//! (box >= 0.59.0), rather than one built into it.
3//!
4//! A custom driver declares its own role and actions in its manifest, so
5//! this handle has one generic method. `lager.status()?.capabilities` lists
6//! the installed roles in `net_command_roles` when `custom_drivers` is set.
7//!
8//! ```no_run
9//! # #[cfg(feature = "blocking")]
10//! # fn demo() -> lager::Result<()> {
11//! use lager::LagerBox;
12//! use serde_json::json;
13//!
14//! let lager = LagerBox::from_env()?;
15//! let reading = lager.custom("chamber1").command("read_temperature", json!({}))?;
16//! println!("{reading}");
17//! # Ok(())
18//! # }
19//! # fn main() {}
20//! ```
21//!
22//! Driver failures arrive as [`crate::Error::Box`] with the box's status:
23//! 409 (the device is busy), 503 (unavailable), 504 (timed out) or 502
24//! (the driver failed).
25
26use super::net_handle;
27
28pub(crate) mod ops {
29    use std::time::Duration;
30
31    use serde_json::Value;
32
33    use crate::error::Result;
34    use crate::wire::{net_command, CommandResponse, Op, Timeout};
35
36    fn parse_value(resp: CommandResponse) -> Result<Value> {
37        Ok(resp.value.unwrap_or(Value::Null))
38    }
39
40    /// The box resolves the role from the saved net, so none is sent.
41    pub(crate) fn command(name: &str, action: &str, params: Value) -> Op<Value> {
42        Op {
43            // A driver's actions can be slow; the box enforces the driver's
44            // own timeout and answers 504 past it.
45            req: net_command(
46                name,
47                None,
48                action,
49                params,
50                Timeout::After(Duration::from_secs(120)),
51            ),
52            parse: parse_value,
53        }
54    }
55}
56
57net_handle! {
58    /// Handle for a net driven by a custom driver installed on the box.
59    sync: CustomNet,
60    async: AsyncCustomNet,
61    methods: {
62        /// Run one of the driver's actions with JSON `params` (use `json!({})`
63        /// for none). Returns the action's `value`, or `null` when it has
64        /// none.
65        fn command(action: &str, params: serde_json::Value) -> serde_json::Value = ops::command;
66    }
67}