tango/lib.rs
1//! An implementation of the [Tango] distributed control system, written from scratch in
2//! Rust, for writing clients and device servers.
3//!
4//! The protocol actually used to reach a device is a detail of the crate rather than of
5//! the code using it: a [`dev::DevProxy`] talks to whatever backend can reach its target,
6//! and a [`server::Server`] serves its devices on every backend able to serve them.
7//!
8//! Every call is blocking, up to the timeout of the proxy or the deadline of the request:
9//! there is no runtime to install. Each one also has an asynchronous `*_async` form, which
10//! runs on any executor, so that a single thread can wait on many devices at once; either
11//! way, the backend multiplexes the concurrent requests over the connection it shares.
12//!
13//! # Client
14//!
15//! A client asks a device for what it wants and says which type it expects, one name
16//! giving one value and a tuple of names giving as many, in a single request.
17//!
18//! ```no_run
19//! use tango::dev::DevProxy;
20//! use tango::error::Result;
21//!
22//! fn main() -> Result<()> {
23//!
24//! // The device is looked up in the database given by `TANGO_HOST`, the connection
25//! // being made on the first request and kept for the following ones.
26//! let dev = DevProxy::new("sys/tg_test/1");
27//! println!("{} is {:?}", dev.name()?, dev.state()?);
28//!
29//! // A reading carries the value, the write value, the quality and the timestamp.
30//! let read = dev.read_attr::<f64, _>("double_scalar")?;
31//! println!("double_scalar = {:?} ({:?})", read.value, read.quality);
32//!
33//! dev.write_attr(("double_scalar", 3.14))?;
34//!
35//! // A command is typed the same way, on both of its sides, `()` being no data.
36//! let echo: String = dev.command("DevString", "hello")?;
37//! println!("DevString -> {echo}");
38//!
39//! Ok(())
40//! }
41//! ```
42//!
43//! # Server
44//!
45//! A device server is a plain Rust struct, its model, and the functions of it that the
46//! attributes and the commands of the device are defined from. Nothing is implemented on
47//! the model and no macro is involved: a read function is given a shared access to it, a
48//! write or an exclusive command an exclusive one, and the server takes care of the lock.
49//!
50//! ```no_run
51//! use tango::server::{AttrDef, ClassDef, CommandDef, Dev, ServerBuilder};
52//! use tango::error::Result;
53//!
54//! /// The model of one device, owned by the server serving it.
55//! struct Counter {
56//! count: i32,
57//! }
58//!
59//! impl Counter {
60//!
61//! /// Build the model of a device, and give it its interface.
62//! fn init(dev: &Dev<Self>) -> Result<Self> {
63//!
64//! dev.add_attr(AttrDef::new("count")
65//! .doc("The current value of the counter.")
66//! .read(Counter::count))?;
67//!
68//! dev.add_command(CommandDef::new("Add")
69//! .in_doc("How much to add to the counter.")
70//! .out_doc("The value of the counter afterwards.")
71//! .exec_exclusive(Counter::add))?;
72//!
73//! Ok(Self { count: 0 })
74//! }
75//!
76//! /// Read the attribute, sharing the model with the other readers.
77//! fn count(&self, _dev: &Dev<Self>) -> Result<i32> {
78//! Ok(self.count)
79//! }
80//!
81//! /// Execute the command, alone on the model for the time it takes.
82//! fn add(&mut self, _dev: &Dev<Self>, value: i32) -> Result<i32> {
83//! self.count += value;
84//! Ok(self.count)
85//! }
86//!
87//! }
88//!
89//! /// Serve the devices the database lists for this server until it is stopped.
90//! fn main() -> Result<()> {
91//! ServerBuilder::from_args()
92//! .class(ClassDef::new("Counter", Counter::init))?
93//! .run()
94//! }
95//! ```
96//!
97//! The server is named after its executable, as cppTango does, and its instance is taken
98//! from the command line, so that a `Counter` executable is launched as the `Counter/test`
99//! server with `Counter test`, or with `Counter test --dev test/counter/1` to serve a
100//! database of its own for testing, with that device in it, see
101//! [`server::ServerArgs`].
102//!
103//! [Tango]: https://www.tango-controls.org/
104
105mod future;
106mod pool;
107pub mod name;
108pub mod buf;
109
110pub mod value;
111pub mod prop;
112
113mod local;
114pub mod dev;
115pub mod error;
116pub mod database;
117pub mod backend;
118
119pub mod server;
120pub mod testing;
121
122pub mod corba;