Skip to main content

pamoja_dashboard/
source.rs

1//! The single seam between the dashboard and whatever produces its data.
2//!
3//! A real node and the [`Mock`](crate::Mock) both implement [`StateSource`], so the
4//! serving layer never knows which it is talking to. What you design and debug against
5//! the mock on a laptop is exactly what ships against real sensors.
6
7use crate::command::{Command, CommandError};
8use crate::state::State;
9
10/// Produces the current [`State`] snapshot whenever the dashboard asks for one.
11///
12/// The serving layer calls [`snapshot`](StateSource::snapshot) to answer `GET /state`
13/// and again on each live-update tick, so an implementation should return the latest
14/// view of the node cheaply. It takes `&mut self` so a source may advance internal
15/// state (a mock its clock, a real node its smoothing) as it is polled.
16pub trait StateSource {
17    /// Returns the node's current state snapshot.
18    ///
19    /// # Returns
20    ///
21    /// The latest language-neutral [`State`] to render.
22    fn snapshot(&mut self) -> State;
23
24    /// Switches a named view, for development and debugging only.
25    ///
26    /// The serving layer calls this when a request carries a `?scenario=` parameter,
27    /// so a single running dev server can be flipped through every state the UI must
28    /// handle. A real node has nothing to switch, so the default ignores the request.
29    ///
30    /// # Arguments
31    ///
32    /// * `key` - the requested view's identifier.
33    ///
34    /// # Returns
35    ///
36    /// `true` if the source switched to `key`, `false` if it does not recognize it.
37    fn select(&mut self, key: &str) -> bool {
38        let _ = key;
39        false
40    }
41
42    /// Carries out an authenticated control command, changing the node's state.
43    ///
44    /// The serving layer calls this only after a command has been authenticated, so an
45    /// implementation may act on it directly. A read-only source rejects every command,
46    /// which is the default.
47    ///
48    /// # Arguments
49    ///
50    /// * `command` - the action to carry out.
51    ///
52    /// # Returns
53    ///
54    /// `Ok(())` once the command has been applied; its effect shows in the next snapshot.
55    ///
56    /// # Errors
57    ///
58    /// Returns a [`CommandError`] if the source does not support the command, the target
59    /// is unknown, or the action is not allowed.
60    fn command(&mut self, command: &Command) -> Result<(), CommandError> {
61        let _ = command;
62        Err(CommandError::Unsupported)
63    }
64}