use crate::animations::Easing;
use crate::devices::Device;
use crate::errors::Error;
use crate::utils::{Scalable, State};
pub mod digital;
pub mod led;
pub mod pwm;
pub mod servo;
#[cfg_attr(feature = "serde", typetag::serde(tag = "type"))]
pub trait Output: Device {
fn get_state(&self) -> State;
fn set_state(&mut self, state: State) -> Result<State, Error>;
fn get_default(&self) -> State;
fn reset(&mut self) -> Result<State, Error> {
self.stop();
self.set_state(self.get_default())
}
fn animate<S: Into<State>>(&mut self, state: S, duration: u64, transition: Easing)
where
Self: Sized;
fn is_busy(&self) -> bool;
fn stop(&mut self);
fn scale_state(&mut self, previous: State, target: State, progress: f32) -> State {
match target {
State::Integer(value) => {
State::Integer(progress.scale(0, 1, previous.as_integer(), value))
}
State::Signed(value) => {
State::Signed(progress.scale(0, 1, previous.as_signed_integer(), value))
}
State::Float(value) => State::Float(progress.scale(0, 1, previous.as_float(), value)),
_ => match progress {
0.0 => previous,
_ => target,
},
}
}
}
dyn_clone::clone_trait_object!(Output);
#[cfg(test)]
mod tests {
use crate::mocks::output_device::MockOutputDevice;
use super::*;
#[test]
fn test_scale_state_integer() {
let mut device = MockOutputDevice::new(0);
let result = device.scale_state(State::Integer(10), State::Integer(20), 0.5);
assert_eq!(result, State::Integer(15));
let result = device.scale_state(State::Integer(10), State::Integer(20), 0.75);
assert_eq!(result, State::Integer(18));
let result = device.scale_state(State::Integer(10), State::Integer(20), 1.2);
assert_eq!(result, State::Integer(22));
}
#[test]
fn test_scale_state_signed() {
let mut device = MockOutputDevice::new(0);
let result = device.scale_state(State::Signed(-10), State::Signed(10), 0.5);
assert_eq!(result, State::Signed(0));
let result = device.scale_state(State::Signed(-10), State::Signed(10), 0.75);
assert_eq!(result, State::Signed(5));
let result = device.scale_state(State::Signed(-10), State::Signed(10), 1.2);
assert_eq!(result, State::Signed(14));
}
#[test]
fn test_scale_state_float() {
let mut device = MockOutputDevice::new(0);
let result = device.scale_state(State::Float(1.0), State::Float(2.0), 0.5);
assert_eq!(result, State::Float(1.5));
let result = device.scale_state(State::Float(1.0), State::Float(2.0), 0.75);
assert_eq!(result, State::Float(1.75));
let result = device.scale_state(State::Float(1.0), State::Float(2.0), 1.2);
assert_eq!(result, State::Float(2.200000047683716));
}
#[test]
fn test_scale_state_non_numeric() {
let mut device = MockOutputDevice::new(0);
let result = device.scale_state(State::Boolean(false), State::Boolean(true), 0.0);
assert_eq!(result, State::Boolean(false));
let result = device.scale_state(State::Boolean(false), State::Boolean(true), 0.5);
assert_eq!(result, State::Boolean(true));
}
#[test]
fn test_reset() {
let mut device = MockOutputDevice::new(42);
assert_eq!(device.get_state(), State::Integer(42));
assert!(device.reset().is_ok());
assert_eq!(device.get_state(), State::Integer(0))
}
}