feat!: overhaul the light protocol (i.e. collection of traits)
This commit is contained in:
@@ -4,6 +4,16 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = { workspace = true }
|
license = { workspace = true }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
||||||
|
serde = ["dep:serde"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
deranged = { workspace = true }
|
deranged = { workspace = true }
|
||||||
derive_more = { workspace = true }
|
derive_more = { workspace = true }
|
||||||
|
ext-trait = { workspace = true }
|
||||||
|
palette = { workspace = true }
|
||||||
|
snafu = { workspace = true }
|
||||||
|
strum = { workspace = true, features = ["derive"] }
|
||||||
|
|
||||||
|
serde = { optional = true, workspace = true, features = ["derive"] }
|
||||||
|
@@ -1,43 +1,126 @@
|
|||||||
use std::{error::Error, future::Future};
|
use std::{error::Error, future::Future};
|
||||||
|
|
||||||
use deranged::RangedU16;
|
use deranged::RangedU16;
|
||||||
|
use palette::Oklch;
|
||||||
|
use snafu::{ResultExt, Snafu};
|
||||||
|
|
||||||
pub trait Light {
|
#[derive(
|
||||||
type IsOnError: Error;
|
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, strum::Display, strum::EnumIs,
|
||||||
fn is_on(&self) -> impl Future<Output = Result<bool, Self::IsOnError>> + Send;
|
)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
|
pub enum State {
|
||||||
|
Off,
|
||||||
|
On,
|
||||||
|
}
|
||||||
|
|
||||||
type IsOffError: Error;
|
impl State {
|
||||||
fn is_off(&self) -> impl Future<Output = Result<bool, Self::IsOffError>> + Send;
|
pub const fn invert(self) -> Self {
|
||||||
|
match self {
|
||||||
|
State::Off => State::On,
|
||||||
|
State::On => State::Off,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type TurnOnError: Error;
|
impl From<bool> for State {
|
||||||
fn turn_on(&mut self) -> impl Future<Output = Result<(), Self::TurnOnError>> + Send;
|
fn from(bool: bool) -> Self {
|
||||||
|
if bool {
|
||||||
|
State::On
|
||||||
|
} else {
|
||||||
|
State::Off
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type TurnOffError: Error;
|
impl From<State> for bool {
|
||||||
fn turn_off(&mut self) -> impl Future<Output = Result<(), Self::TurnOffError>> + Send;
|
fn from(state: State) -> Self {
|
||||||
|
state.is_on()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type ToggleError: Error;
|
pub trait GetState {
|
||||||
fn toggle(&mut self) -> impl Future<Output = Result<(), Self::ToggleError>> + Send;
|
type Error: Error;
|
||||||
|
fn get_state(&self) -> impl Future<Output = Result<State, Self::Error>> + Send;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[ext_trait::extension(trait IsOff)]
|
||||||
|
impl<T: GetState> T {
|
||||||
|
async fn is_off(&self) -> Result<bool, T::Error> {
|
||||||
|
Ok(self.get_state().await?.is_off())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[ext_trait::extension(trait IsOn)]
|
||||||
|
impl<T: GetState> T {
|
||||||
|
async fn is_on(&self) -> Result<bool, T::Error> {
|
||||||
|
Ok(self.get_state().await?.is_on())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait SetState {
|
||||||
|
type Error: Error;
|
||||||
|
fn set_state(&mut self, state: State) -> impl Future<Output = Result<(), Self::Error>> + Send;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[ext_trait::extension(trait TurnOff)]
|
||||||
|
impl<T: SetState> T {
|
||||||
|
async fn turn_off(&mut self) -> Result<(), T::Error> {
|
||||||
|
self.set_state(State::Off).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[ext_trait::extension(trait TurnOn)]
|
||||||
|
impl<T: SetState> T {
|
||||||
|
async fn turn_on(&mut self) -> Result<(), T::Error> {
|
||||||
|
self.set_state(State::On).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Snafu)]
|
||||||
|
enum InvertToToggleError<GetStateError: Error + 'static, SetStateError: Error + 'static> {
|
||||||
|
GetStateError { source: GetStateError },
|
||||||
|
SetStateError { source: SetStateError },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[ext_trait::extension(trait InvertToToggle)]
|
||||||
|
impl<T: GetState + SetState> T
|
||||||
|
where
|
||||||
|
<T as GetState>::Error: 'static,
|
||||||
|
<T as SetState>::Error: 'static,
|
||||||
|
{
|
||||||
|
/// Toggle the light by setting it to the inverse of its current state
|
||||||
|
async fn toggle(
|
||||||
|
&mut self,
|
||||||
|
) -> Result<(), InvertToToggleError<<T as GetState>::Error, <T as SetState>::Error>> {
|
||||||
|
let state = self.get_state().await.context(GetStateSnafu)?;
|
||||||
|
self.set_state(state.invert())
|
||||||
|
.await
|
||||||
|
.context(SetStateSnafu)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Toggle {
|
||||||
|
type Error: Error;
|
||||||
|
fn toggle(&mut self, state: State) -> impl Future<Output = Result<(), Self::Error>> + Send;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, derive_more::From, derive_more::Into)]
|
#[derive(Debug, Clone, Copy, derive_more::From, derive_more::Into)]
|
||||||
pub struct Kelvin(pub RangedU16<2000, 10000>);
|
pub struct Kelvin(pub RangedU16<2000, 10000>);
|
||||||
|
|
||||||
pub trait KelvinLight: Light {
|
pub trait TurnToTemperature {
|
||||||
type TurnToKelvinError: Error;
|
type TurnToTemperatureError: Error;
|
||||||
fn turn_to_kelvin(
|
fn turn_to_temperature(
|
||||||
&mut self,
|
&mut self,
|
||||||
temperature: Kelvin,
|
temperature: Kelvin,
|
||||||
) -> impl Future<Output = Result<(), Self::TurnToKelvinError>> + Send;
|
) -> impl Future<Output = Result<(), Self::TurnToTemperatureError>> + Send;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: replace with a type from a respected and useful library
|
pub trait TurnToColor {
|
||||||
#[derive(Debug, Clone, Copy, derive_more::From, derive_more::Into)]
|
type TurnToColorError: Error;
|
||||||
pub struct Rgb(pub u8, pub u8, pub u8);
|
fn turn_to_color(
|
||||||
|
|
||||||
pub trait RgbLight: Light {
|
|
||||||
type TurnToRgbError: Error;
|
|
||||||
fn turn_to_rgb(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
color: Rgb,
|
color: Oklch<f64>,
|
||||||
) -> impl Future<Output = Result<(), Self::TurnToRgbError>> + Send;
|
) -> impl Future<Output = Result<(), Self::TurnToColorError>> + Send;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user