Skip to main content

pamoja_core/
device.rs

1//! Device-model traits implemented by capability crates.
2//!
3//! These traits describe the roles a piece of hardware can play in an
4//! application: a connectable [`Device`], a [`Sensor`] that produces readings, an
5//! [`Actuator`] that accepts commands, and a [`Telemetry`] source that streams
6//! frames. A single type may implement more than one of them.
7
8use crate::error::Result;
9
10/// A connectable physical or virtual device.
11///
12/// Implementors manage the lifecycle of an underlying resource such as a serial
13/// port, a network socket, or a vehicle link.
14pub trait Device {
15    /// Returns the stable identifier for this device.
16    ///
17    /// The identifier is expected to remain constant for the lifetime of the
18    /// device, for example a serial number, MAC address, or vehicle URI.
19    ///
20    /// # Returns
21    ///
22    /// A string slice borrowing the device's identifier.
23    fn id(&self) -> &str;
24
25    /// Opens the device and prepares it for use.
26    ///
27    /// # Returns
28    ///
29    /// `Ok(())` once the device is connected and ready.
30    ///
31    /// # Errors
32    ///
33    /// Returns [`Error::Io`](crate::Error::Io) if the underlying resource cannot
34    /// be opened, or [`Error::Transport`](crate::Error::Transport) if a link to
35    /// the device cannot be established.
36    async fn connect(&mut self) -> Result<()>;
37
38    /// Releases the device and any resources it holds.
39    ///
40    /// # Returns
41    ///
42    /// `Ok(())` once the device has been disconnected and its resources freed.
43    ///
44    /// # Errors
45    ///
46    /// Returns [`Error::Io`](crate::Error::Io) if the underlying resource cannot
47    /// be released cleanly.
48    async fn disconnect(&mut self) -> Result<()>;
49}
50
51/// A source of typed readings, such as a thermometer, GPS receiver, or lidar.
52pub trait Sensor {
53    /// The value produced by a single read, for example a temperature or a fix.
54    type Reading;
55
56    /// Takes a single reading from the sensor.
57    ///
58    /// # Returns
59    ///
60    /// The next [`Reading`](Self::Reading) sampled from the sensor.
61    ///
62    /// # Errors
63    ///
64    /// Returns [`Error::Io`](crate::Error::Io) if the sensor cannot be read, or
65    /// [`Error::Closed`](crate::Error::Closed) if the sensor has been
66    /// disconnected.
67    async fn read(&mut self) -> Result<Self::Reading>;
68}
69
70/// A sink that accepts typed commands, such as a motor or a valve.
71pub trait Actuator {
72    /// The command accepted by a single application, for example a setpoint.
73    type Command;
74
75    /// Applies a command to the actuator.
76    ///
77    /// # Arguments
78    ///
79    /// * `command` - the command to apply, consumed by the call.
80    ///
81    /// # Returns
82    ///
83    /// `Ok(())` once the command has been accepted by the actuator.
84    ///
85    /// # Errors
86    ///
87    /// Returns [`Error::Io`](crate::Error::Io) if the command cannot be
88    /// delivered, or [`Error::Closed`](crate::Error::Closed) if the actuator has
89    /// been disconnected.
90    async fn apply(&mut self, command: Self::Command) -> Result<()>;
91}
92
93/// A device that emits a continuous stream of telemetry frames.
94pub trait Telemetry {
95    /// A single telemetry frame, for example a status or position report.
96    type Frame;
97
98    /// Awaits the next telemetry frame.
99    ///
100    /// # Returns
101    ///
102    /// `Some(frame)` when a frame is available, or `None` once the telemetry
103    /// stream has ended.
104    ///
105    /// # Errors
106    ///
107    /// Returns [`Error::Transport`](crate::Error::Transport) if the telemetry
108    /// link fails while waiting.
109    async fn next_frame(&mut self) -> Result<Option<Self::Frame>>;
110}