1use std::net::TcpStream;
2use std::io::{self, Write};
3
4
5fn gen_rgb(r: u8, g: u8, b: u8, brightness: u8) -> (u8, u8, u8) {
6 let scale = brightness as f32 / 255.0;
7 (
8 (r as f32 * scale) as u8,
9 (g as f32 * scale) as u8,
10 (b as f32 * scale) as u8,
11 )
12}
13
14fn on() -> Vec<u8> {
15 vec![0x71, 0x23, 0x0F, 0xA4]
16}
17
18fn off() -> Vec<u8> {
19 vec![0x71, 0x24, 0x0F, 0xA4]
20}
21
22fn mk_rgb(r: u8, g: u8, b: u8, brightness: u8) -> Vec<u8> {
23 let (r_scaled, g_scaled, b_scaled) = gen_rgb(r, g, b, brightness);
24 vec![0x31, r_scaled, g_scaled, b_scaled, 0, 0, 0xF0, 0x0F, 0x2F]
25}
26
27fn mk_ww(brightness: u8) -> Vec<u8> {
28 vec![0x31, 0x00, 0x00, 0x00, brightness, 0x00, 0x0F, 0x0F, 0x4E]
29}
30
31fn mk_cw(brightness: u8) -> Vec<u8> {
32 vec![0x31, 0x00, 0x00, 0x00, 0x00, brightness, 0x0F, 0x0F, 0x4E]
33}
34
35pub struct MagicBulb {
36 ip: String,
37 stream: Option<std::net::TcpStream>,
38}
39
40impl MagicBulb {
41 pub fn new(ip: &str) -> Self {
42 MagicBulb {
43 ip: ip.to_string() + ":5577",
44 stream: None,
45 }
46 }
47
48 pub fn connect(&mut self) -> io::Result<()> {
49 let stream = TcpStream::connect(&self.ip)?;
50 self.stream = Some(stream);
51 Ok(())
52 }
53
54 fn send(&mut self, data: &[u8]) -> io::Result<()> {
55 if let Some(ref mut stream) = self.stream {
56 stream.write_all(data)?;
57 Ok(())
58 } else {
59 Err(io::Error::new(io::ErrorKind::NotConnected, "No connection"))
60 }
61 }
62
63 pub fn turn_on(&mut self) -> io::Result<()> {
64 self.send(&on())
65 }
66
67 pub fn turn_off(&mut self) -> io::Result<()> {
68 self.send(&off())
69 }
70
71 pub fn set_rgb(&mut self, r: u8, g: u8, b: u8, brightness: u8) -> io::Result<()> {
72 self.send(&mk_rgb(r, g, b, brightness))
73 }
74
75 pub fn set_ww(&mut self, brightness: u8) -> io::Result<()> {
76 self.send(&mk_ww(brightness))
77 }
78
79 pub fn set_cw(&mut self, brightness: u8) -> io::Result<()> {
80 self.send(&mk_cw(brightness))
81 }
82}
83