Skip to main content

hermes_five/devices/
mod.rs

1//! Defines devices of various [`Input`] / [`Output`] kinds (led, servo, button, sensor, etc.) to be controlled.
2
3mod input;
4mod output;
5
6// Input devices re-exports
7pub use crate::devices::input::analog::AnalogInput;
8pub use crate::devices::input::button::Button;
9pub use crate::devices::input::digital::DigitalInput;
10pub use crate::devices::input::{Input, InputEvent};
11// Output devices re-exports
12pub use crate::devices::output::digital::DigitalOutput;
13pub use crate::devices::output::led::Led;
14pub use crate::devices::output::pwm::PwmOutput;
15pub use crate::devices::output::servo::Servo;
16pub use crate::devices::output::servo::ServoType;
17pub use crate::devices::output::Output;
18
19use dyn_clone::DynClone;
20use std::fmt::{Debug, Display};
21
22/// A trait for devices that can be debugged, cloned, and used in concurrent contexts.
23/// `Device` are one of the entities defined in Hermes-Five project: it represents a physical
24/// device that is plugged to and can be controlled by a [`Board`](crate::hardware::Board). `Device`s come in two flavor:
25/// - `Actuator`: device that can act on the world
26/// - `Sensor`: device that can sense or measure data from the world
27///
28/// Implementors of this trait are required to be `Debug`, `DynClone`, `Send`, and `Sync`.
29/// This ensures that devices can be cloned and used safely in multithreaded and async environments.
30#[cfg_attr(feature = "serde", typetag::serde(tag = "type"))]
31pub trait Device: Debug + Display + DynClone + Send + Sync {}
32dyn_clone::clone_trait_object!(Device);
33
34#[cfg(feature = "serde")]
35/// Allows the serialization and deserialization of `Arc<RwLock<T>>` types.
36/// It is only available if the `serde` feature is enabled.
37pub mod arc_rwlock_serde {
38    use std::sync::Arc;
39
40    use parking_lot::RwLock;
41    use serde::de::Deserializer;
42    use serde::ser::Serializer;
43    use serde::{Deserialize, Serialize};
44
45    pub fn serialize<S, T>(val: &Arc<RwLock<T>>, s: S) -> Result<S::Ok, S::Error>
46    where
47        S: Serializer,
48        T: Serialize,
49    {
50        T::serialize(&*val.read(), s)
51    }
52
53    pub fn deserialize<'de, D, T>(d: D) -> Result<Arc<RwLock<T>>, D::Error>
54    where
55        D: Deserializer<'de>,
56        T: Deserialize<'de>,
57    {
58        Ok(Arc::new(RwLock::new(T::deserialize(d)?)))
59    }
60
61    #[cfg(test)]
62    mod serde_tests {
63        use serde_json;
64
65        use crate::mocks::output_device::MockOutputDevice;
66
67        #[test]
68        fn test_serialize() {
69            let test = MockOutputDevice::new(20);
70
71            let serialized = serde_json::to_string(&test);
72            assert!(serialized.is_ok());
73
74            let expected_json = r#"{"state":20,"lock":42}"#;
75            assert_eq!(serialized.unwrap(), expected_json);
76        }
77
78        #[test]
79        fn test_deserialize() {
80            let json_data = r#"{"state":20,"lock":42}"#;
81            let deserialized = serde_json::from_str::<MockOutputDevice>(json_data);
82
83            assert!(deserialized.is_ok());
84            assert_eq!(deserialized.unwrap().get_locked_value(), 42);
85        }
86    }
87}