hermes_five/devices/output/
mod.rs1use crate::animations::Easing;
2use crate::devices::Device;
3use crate::errors::Error;
4use crate::utils::{Scalable, State};
5
6pub mod digital;
7pub mod led;
8pub mod pwm;
9pub mod servo;
10
11#[cfg_attr(feature = "serde", typetag::serde(tag = "type"))]
16pub trait Output: Device {
17 fn get_state(&self) -> State;
19 fn set_state(&mut self, state: State) -> Result<State, Error>;
21 fn get_default(&self) -> State;
23 fn reset(&mut self) -> Result<State, Error> {
25 self.stop();
26 self.set_state(self.get_default())
27 }
28 fn animate<S: Into<State>>(&mut self, state: S, duration: u64, transition: Easing)
38 where
39 Self: Sized;
40 fn is_busy(&self) -> bool;
42 fn stop(&mut self);
44 fn scale_state(&mut self, previous: State, target: State, progress: f32) -> State {
46 match target {
47 State::Integer(value) => {
48 State::Integer(progress.scale(0, 1, previous.as_integer(), value))
49 }
50 State::Signed(value) => {
51 State::Signed(progress.scale(0, 1, previous.as_signed_integer(), value))
52 }
53 State::Float(value) => State::Float(progress.scale(0, 1, previous.as_float(), value)),
54 _ => match progress {
55 0.0 => previous,
56 _ => target,
57 },
58 }
59 }
60}
61dyn_clone::clone_trait_object!(Output);
62
63#[cfg(test)]
64mod tests {
65 use crate::mocks::output_device::MockOutputDevice;
66
67 use super::*;
68
69 #[test]
70 fn test_scale_state_integer() {
71 let mut device = MockOutputDevice::new(0);
72
73 let result = device.scale_state(State::Integer(10), State::Integer(20), 0.5);
75 assert_eq!(result, State::Integer(15));
76
77 let result = device.scale_state(State::Integer(10), State::Integer(20), 0.75);
79 assert_eq!(result, State::Integer(18));
80
81 let result = device.scale_state(State::Integer(10), State::Integer(20), 1.2);
83 assert_eq!(result, State::Integer(22));
84 }
85
86 #[test]
87 fn test_scale_state_signed() {
88 let mut device = MockOutputDevice::new(0);
89
90 let result = device.scale_state(State::Signed(-10), State::Signed(10), 0.5);
92 assert_eq!(result, State::Signed(0));
93
94 let result = device.scale_state(State::Signed(-10), State::Signed(10), 0.75);
96 assert_eq!(result, State::Signed(5));
97
98 let result = device.scale_state(State::Signed(-10), State::Signed(10), 1.2);
100 assert_eq!(result, State::Signed(14));
101 }
102
103 #[test]
104 fn test_scale_state_float() {
105 let mut device = MockOutputDevice::new(0);
106
107 let result = device.scale_state(State::Float(1.0), State::Float(2.0), 0.5);
109 assert_eq!(result, State::Float(1.5));
110
111 let result = device.scale_state(State::Float(1.0), State::Float(2.0), 0.75);
113 assert_eq!(result, State::Float(1.75));
114
115 let result = device.scale_state(State::Float(1.0), State::Float(2.0), 1.2);
117 assert_eq!(result, State::Float(2.200000047683716));
118 }
119
120 #[test]
121 fn test_scale_state_non_numeric() {
122 let mut device = MockOutputDevice::new(0);
123
124 let result = device.scale_state(State::Boolean(false), State::Boolean(true), 0.0);
125 assert_eq!(result, State::Boolean(false));
126
127 let result = device.scale_state(State::Boolean(false), State::Boolean(true), 0.5);
128 assert_eq!(result, State::Boolean(true));
129 }
130
131 #[test]
132 fn test_reset() {
133 let mut device = MockOutputDevice::new(42);
134 assert_eq!(device.get_state(), State::Integer(42));
135 assert!(device.reset().is_ok());
136 assert_eq!(device.get_state(), State::Integer(0))
137 }
138}