automation_rs/src/hue_bridge.rs
2023-04-14 01:06:08 +02:00

98 lines
2.4 KiB
Rust

use std::net::{Ipv4Addr, SocketAddr};
use serde::{Deserialize, Serialize};
use tracing::{error, trace, warn};
use crate::event::{Event, EventChannel};
pub enum Flag {
Presence,
Darkness,
}
#[derive(Debug, Clone, Deserialize)]
pub struct FlagIDs {
pub presence: isize,
pub darkness: isize,
}
#[derive(Debug, Deserialize)]
pub struct HueBridgeConfig {
pub ip: Ipv4Addr,
pub login: String,
pub flags: FlagIDs,
}
struct HueBridge {
addr: SocketAddr,
login: String,
flag_ids: FlagIDs,
}
#[derive(Debug, Serialize)]
struct FlagMessage {
flag: bool,
}
impl HueBridge {
pub fn new(config: HueBridgeConfig) -> Self {
Self {
addr: (config.ip, 80).into(),
login: config.login,
flag_ids: config.flags,
}
}
pub async fn set_flag(&self, flag: Flag, value: bool) {
let flag_id = match flag {
Flag::Presence => self.flag_ids.presence,
Flag::Darkness => self.flag_ids.darkness,
};
let url = format!(
"http://{}/api/{}/sensors/{flag_id}/state",
self.addr, self.login
);
let res = reqwest::Client::new()
.put(url)
.json(&FlagMessage { flag: value })
.send()
.await;
match res {
Ok(res) => {
let status = res.status();
if !status.is_success() {
warn!(flag_id, "Status code is not success: {status}");
}
}
Err(err) => {
error!(flag_id, "Error: {err}");
}
}
}
}
pub fn start(config: HueBridgeConfig, event_channel: &EventChannel) {
let hue_bridge = HueBridge::new(config);
let mut rx = event_channel.get_rx();
tokio::spawn(async move {
loop {
match rx.recv().await {
Ok(Event::Presence(presence)) => {
trace!("Bridging presence to hue");
hue_bridge.set_flag(Flag::Presence, presence).await;
}
Ok(Event::Darkness(dark)) => {
trace!("Bridging darkness to hue");
hue_bridge.set_flag(Flag::Darkness, dark).await;
}
Ok(_) => {}
Err(_) => todo!("Handle errors with the event channel properly"),
}
}
});
}