Refactor
This commit is contained in:
7
lib/Cargo.toml
Normal file
7
lib/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "lighter_lib"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
148
lib/src/lib.rs
Normal file
148
lib/src/lib.rs
Normal file
@ -0,0 +1,148 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
use std::num::ParseIntError;
|
||||
use std::ops::Deref;
|
||||
use std::str::FromStr;
|
||||
|
||||
/// The mqtt publish id of the bulb
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub struct BulbId(pub String);
|
||||
|
||||
#[derive(Serialize, Deserialize, Default, Debug, Clone)]
|
||||
pub struct BulbMode {
|
||||
pub power: bool,
|
||||
pub color: BulbColor,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
|
||||
pub enum BulbColor {
|
||||
/// Light temperature, brightness
|
||||
Kelvin { t: f32, b: f32 },
|
||||
|
||||
/// Hue, Saturation, Brightness
|
||||
HSB { h: f32, s: f32, b: f32 },
|
||||
}
|
||||
|
||||
impl FromStr for BulbColor {
|
||||
type Err = ParseIntError;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let parsed = u64::from_str_radix(s, 16)?;
|
||||
|
||||
let to_f32 = |byte: u8| byte as f32 / 255.;
|
||||
let [.., red, green, blue, white, warm] = parsed.to_be_bytes().map(to_f32);
|
||||
|
||||
if (red + green + blue) != 0. {
|
||||
let (h, s, b) = rgb_to_hsb(red, green, blue);
|
||||
Ok(BulbColor::hsb(h, s, b))
|
||||
} else {
|
||||
let b = warm + white;
|
||||
let t = white / b;
|
||||
|
||||
Ok(BulbColor::kelvin(t, b))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BulbColor {
|
||||
pub fn color_string(self) -> String {
|
||||
let [mut red, mut green, mut blue, mut white, mut warm] = [0u8; 5];
|
||||
|
||||
match self {
|
||||
BulbColor::HSB { h, s, b } => (red, green, blue) = hsb_to_rgb(h, s, b),
|
||||
BulbColor::Kelvin { t, b } => {
|
||||
(white, warm) = ((t * b * 255.0) as u8, ((1. - t) * b * 255.0) as u8)
|
||||
}
|
||||
}
|
||||
|
||||
let s = format!("{red:02x}{green:02x}{blue:02x}{white:02x}{warm:02x}");
|
||||
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
impl BulbColor {
|
||||
pub fn hsb(h: f32, s: f32, b: f32) -> Self {
|
||||
BulbColor::HSB {
|
||||
h: h.clamp(0.0, 1.0),
|
||||
s: s.clamp(0.0, 1.0),
|
||||
b: b.clamp(0.0, 1.0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn kelvin(t: f32, b: f32) -> Self {
|
||||
BulbColor::Kelvin {
|
||||
t: t.clamp(0.0, 1.0),
|
||||
b: b.clamp(0.0, 1.0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for BulbColor {
|
||||
fn default() -> Self {
|
||||
BulbColor::Kelvin { t: 0.0, b: 0.0 }
|
||||
}
|
||||
}
|
||||
|
||||
fn rgb_to_hsb(red: f32, green: f32, blue: f32) -> (f32, f32, f32) {
|
||||
let x_max = red.max(green).max(blue);
|
||||
let x_min = red.min(green).min(blue);
|
||||
|
||||
let b = x_max;
|
||||
let c = x_max - x_min;
|
||||
|
||||
let h = match b {
|
||||
_ if c == 0. => 0.,
|
||||
_ if b == red => (green - blue) / c,
|
||||
_ if b == green => 2. + (blue - red) / c,
|
||||
_ => 4. + (red - green) / c,
|
||||
};
|
||||
let mut h = h * 60.0 / 360.0;
|
||||
if h < 0.0 {
|
||||
h += 1.0;
|
||||
}
|
||||
|
||||
let s = if b == 0.0 { 0.0 } else { c / b };
|
||||
|
||||
(h, s, b)
|
||||
}
|
||||
|
||||
fn hsb_to_rgb(h: f32, s: f32, b: f32) -> (u8, u8, u8) {
|
||||
let h = 360.0 * h.clamp(0.0, 1.0);
|
||||
|
||||
let c = b * s; // chroma
|
||||
|
||||
let x = c * (1. - ((h / 60.) % 2. - 1.).abs());
|
||||
let m = b - c;
|
||||
let m = |v| ((v + m) * 255.0) as u8;
|
||||
|
||||
let (r, g, b) = match h {
|
||||
_ if h < 60. => (c, x, 0.0),
|
||||
_ if h < 120.0 => (x, c, 0.0),
|
||||
_ if h < 180.0 => (0.0, c, x),
|
||||
_ if h < 240.0 => (0.0, x, c),
|
||||
_ if h < 300.0 => (x, 0.0, c),
|
||||
_ => (c, 0.0, x),
|
||||
};
|
||||
|
||||
(m(r), m(g), m(b))
|
||||
}
|
||||
|
||||
impl Display for BulbId {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for BulbId {
|
||||
fn from(s: String) -> Self {
|
||||
BulbId(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for BulbId {
|
||||
type Target = str;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user