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}