libyee/
connection.rs

1use std::{
2    convert::TryFrom,
3    fmt::Debug,
4    io::{Error, Read, Write},
5    net::TcpStream,
6    sync::Mutex,
7    time::Duration,
8};
9
10use crate::{bulb::Bulb, lightmode::HSV, rgb::RGB};
11use rand::{prelude::ThreadRng, RngCore};
12use serde::Deserialize;
13
14pub struct BulbConnection<T: Read + Write, R: RngCore> {
15    pub bulb: Bulb,
16    pub connection: Mutex<T>,
17    pub rng: R,
18}
19
20#[derive(Debug)]
21pub enum MethodCallError {
22    BadRequest,
23    UnsupportedMethod,
24    IOError(std::io::Error),
25    ParseError,
26    SynchronizationError,
27    ErrorResponse(ErrorResponse),
28}
29
30pub trait MethodCallResponse<'a>: Deserialize<'a> + Debug {
31    fn id(&self) -> i16;
32}
33
34#[derive(Debug, Deserialize)]
35pub struct ErrorResponse {
36    id: i16,
37    error: BulbErrorResponse,
38}
39
40#[derive(Debug, Deserialize)]
41pub struct BulbErrorResponse {
42    code: i32,
43    message: String,
44}
45
46#[derive(Debug, Deserialize, Clone)]
47pub struct StringVecResponse {
48    pub id: i16,
49    pub result: Vec<String>,
50}
51
52#[derive(Debug, Deserialize, Clone)]
53pub struct CronResult {
54    #[serde(rename(serialize = "type", deserialize = "type"))]
55    pub cron_type: i32,
56    pub delay: u16,
57    pub mix: i32,
58}
59
60#[derive(Debug, Deserialize, Clone)]
61pub struct CronResponse {
62    pub id: i16,
63    pub result: Vec<CronResult>,
64}
65
66impl TryFrom<CronResult> for Cron {
67    type Error = String;
68
69    fn try_from(value: CronResult) -> Result<Self, Self::Error> {
70        if value.cron_type != 0 {
71            return Err("Unsupported cron type.".to_string());
72        }
73        Ok(Cron {
74            cron_type: CronType::PowerOff,
75            minutes: value.delay,
76        })
77    }
78}
79
80impl<'a> MethodCallResponse<'a> for CronResponse {
81    fn id(&self) -> i16 {
82        self.id
83    }
84}
85
86impl<'a> MethodCallResponse<'a> for StringVecResponse {
87    fn id(&self) -> i16 {
88        self.id
89    }
90}
91
92pub type TcpConnection = BulbConnection<TcpStream, ThreadRng>;
93
94impl TcpConnection {
95    pub fn new(bulb: Bulb) -> Result<Self, Error> {
96        return TcpStream::connect(&bulb.ip_address).map(|connection| BulbConnection {
97            bulb: bulb,
98            connection: Mutex::new(connection),
99            rng: rand::thread_rng(),
100        });
101    }
102}
103
104pub enum MusicMode<'a> {
105    On(&'a str, usize),
106    Off,
107}
108
109pub enum AdjustableProp {
110    Brightness,
111    Ct,
112    Color,
113}
114
115impl From<&AdjustableProp> for &str {
116    fn from(a: &AdjustableProp) -> Self {
117        match a {
118            AdjustableProp::Brightness => "bright",
119            AdjustableProp::Ct => "ct",
120            AdjustableProp::Color => "color",
121        }
122    }
123}
124
125pub enum AdjustAction {
126    Increase,
127    Decrease,
128    Circle,
129}
130
131impl From<&AdjustAction> for &str {
132    fn from(a: &AdjustAction) -> Self {
133        match a {
134            AdjustAction::Increase => "increase",
135            AdjustAction::Decrease => "decrease",
136            AdjustAction::Circle => "circle",
137        }
138    }
139}
140
141pub enum CronType {
142    PowerOff,
143}
144
145pub enum CfAction {
146    Recover,
147    Stay,
148    TurnOff,
149}
150
151pub enum Scene<'a, 'b> {
152    Color(&'a RGB, Brightness),
153    HSV(&'a HSV, Brightness),
154    Ct(Ct, Brightness),
155    Cf(&'b ColorFlow),
156
157    /// brightness, minutes
158    AutoDelayOff(Brightness, u16),
159}
160
161pub const MIN_AUTO_DELAY_OFF_MINUTES: u8 = 1;
162
163pub struct ColorFlow {
164    pub count: u16,
165    pub action: CfAction,
166    pub sequence: Vec<FlowTuple>,
167}
168
169pub struct Cron {
170    pub cron_type: CronType,
171    pub minutes: u16,
172}
173
174pub struct FlowTuple {
175    pub duration: Duration,
176    pub mode: FlowTupleMode,
177}
178
179pub struct ColorFlowTupleMode {
180    pub color: RGB,
181    pub brightness: Brightness,
182}
183
184pub type Ct = u16;
185pub type Brightness = u8;
186
187pub struct CtFlowTupleMode {
188    pub ct: Ct,
189    pub brightness: Brightness,
190}
191
192pub enum FlowTupleMode {
193    Color(ColorFlowTupleMode),
194    Ct(CtFlowTupleMode),
195    Sleep,
196}
197
198pub const MINIMUM_CF_DURATION: Duration = Duration::from_millis(50);
199
200pub enum PowerMode {
201    Ct = 1,
202    Rgb = 2,
203    Hsv = 3,
204    ColorFlow = 4,
205    NightLight = 5,
206}
207
208pub const MAX_BRIGHTNESS: u8 = 100;
209pub const MINIMUM_TRANSITION_DURATION: Duration = Duration::from_millis(30);
210pub const CT_MIN: u16 = 1700;
211pub const CT_MAX: u16 = 6500;
212
213pub enum TransitionMode {
214    Sudden,
215    Smooth(Duration),
216}