96 lines
2.7 KiB
Rust
96 lines
2.7 KiB
Rust
use std::{
|
|
net::IpAddr,
|
|
sync::{Arc, Mutex},
|
|
time::Duration,
|
|
};
|
|
|
|
use actix_web::web::Data;
|
|
use anyhow::{bail, Result};
|
|
use dns_lookup::{lookup_addr, lookup_host};
|
|
use reqwest::Client;
|
|
|
|
use crate::{
|
|
db::DataBase,
|
|
since_epoch,
|
|
task_scheduler::{Scheduler, Task},
|
|
};
|
|
|
|
pub struct Thermostat {
|
|
device: String,
|
|
}
|
|
|
|
impl Thermostat {
|
|
pub fn new(device: impl ToString) -> Self {
|
|
Self {
|
|
device: device.to_string(),
|
|
}
|
|
}
|
|
|
|
pub async fn set_temperature(&self, temperature: f32) -> Result<()> {
|
|
let ips = lookup_host(&self.device)?;
|
|
|
|
if ips.is_empty() {
|
|
bail!("could not resolve device name {}", self.device);
|
|
}
|
|
|
|
let resp = Client::new()
|
|
.post(format!("http://{}/ext_t?temp={}", ips[0], temperature))
|
|
.send()
|
|
.await?;
|
|
|
|
if !resp.status().is_success() {
|
|
bail!("response error");
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum ThermometerChange {
|
|
Temperature(f32),
|
|
Humidity(f32),
|
|
}
|
|
|
|
pub struct Thermometer;
|
|
|
|
impl Thermometer {
|
|
pub fn push_change(
|
|
change: ThermometerChange,
|
|
ip: IpAddr,
|
|
db: Data<Arc<Mutex<DataBase>>>,
|
|
scheduler: Data<Scheduler>,
|
|
) -> Result<()> {
|
|
let db_lock = db.lock().unwrap();
|
|
let device_id = lookup_addr(&ip)?.trim_end_matches(".fritz.box").to_string();
|
|
|
|
if db_lock.device_exists(&device_id)? {
|
|
match change {
|
|
ThermometerChange::Temperature(temp) => {
|
|
db_lock.write(&device_id, since_epoch()?, "temperature", temp)?;
|
|
|
|
for action_set in db_lock.action_sets(&device_id)? {
|
|
if let Some(push_device) = action_set.push_device() {
|
|
if action_set.parameter("temperature") && push_device == device_id {
|
|
if let Some(receive_device) = action_set.receive_device() {
|
|
scheduler.add_task(Task::one_shot(
|
|
Duration::from_secs(0),
|
|
Box::pin(async move {
|
|
let _ = Thermostat::new(receive_device)
|
|
.set_temperature(temp);
|
|
}),
|
|
));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
ThermometerChange::Humidity(humid) => {
|
|
db_lock.write(&device_id, since_epoch()?, "humidity", humid)?;
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|