HomeServer/src/main.rs

102 lines
2.6 KiB
Rust
Raw Normal View History

2023-09-19 08:52:12 +00:00
use std::{
sync::{Arc, Mutex},
thread,
time::{Duration, SystemTime, UNIX_EPOCH},
};
use crate::db::DataBase;
2023-09-20 10:19:41 +00:00
mod data;
2023-09-19 08:52:12 +00:00
mod db;
mod devices;
mod tasmota;
2023-09-21 05:30:39 +00:00
mod web_server;
2023-09-19 08:52:12 +00:00
2023-09-21 08:08:23 +00:00
use actix_files::Files;
use actix_web::{web::Data, App, HttpServer};
2023-09-19 08:52:12 +00:00
use anyhow::Result;
use devices::Devices;
2023-09-21 05:30:39 +00:00
use futures::{future::try_join_all, try_join, Future};
2023-09-19 08:52:12 +00:00
use tasmota::Tasmota;
2023-09-21 20:20:42 +00:00
use web_server::{
change_device_name, change_plug_state, device_query, index, plug_data, plug_state,
};
2023-09-19 08:52:12 +00:00
fn since_epoch() -> Result<u64> {
Ok(SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs())
}
2023-09-21 05:30:39 +00:00
fn read_power_usage(
tasmota_plugs: Vec<Tasmota>,
db: Arc<Mutex<DataBase>>,
) -> impl Future<Output = Result<()>> {
async move {
loop {
try_join_all(tasmota_plugs.iter().map(|plug| async {
if let Ok(usage) = plug.read_power_usage().await {
db.lock()
.unwrap()
.write(plug.name(), since_epoch()?, usage)?;
}
Ok::<(), anyhow::Error>(())
}))
.await?;
thread::sleep(Duration::from_secs(3));
}
}
}
async fn run_web_server(
devices: Devices,
plugs: Vec<Tasmota>,
db: Arc<Mutex<DataBase>>,
) -> Result<()> {
HttpServer::new(move || {
App::new()
.app_data(Data::new(devices.clone()))
.app_data(Data::new(db.clone()))
.app_data(Data::new(plugs.clone()))
2023-09-21 08:08:23 +00:00
.service(Files::new("/images", "resources/images/").show_files_listing())
.service(Files::new("/css", "resources/css").show_files_listing())
.service(Files::new("/js", "resources/js").show_files_listing())
2023-09-21 05:30:39 +00:00
.service(index)
.service(device_query)
.service(plug_state)
.service(change_plug_state)
2023-09-21 08:46:23 +00:00
.service(change_device_name)
2023-09-21 20:20:42 +00:00
.service(plug_data)
2023-09-21 05:30:39 +00:00
})
2023-09-21 10:07:43 +00:00
.bind(("0.0.0.0", 8062))
2023-09-21 05:30:39 +00:00
.map_err(|err| anyhow::Error::msg(format!("failed binding to address: {err:#?}")))?
.run()
.await?;
Ok(())
}
2023-09-19 08:52:12 +00:00
#[tokio::main]
async fn main() -> Result<()> {
let db_future = DataBase::new("home_server.db");
let devices_future = Devices::read("devices.conf");
let (db, devices) = try_join!(db_future, devices_future)?;
2023-09-21 08:08:23 +00:00
db.register_devices(&devices)?;
2023-09-19 08:52:12 +00:00
let shared_db = Arc::new(Mutex::new(db));
2023-09-21 05:30:39 +00:00
2023-09-19 08:52:12 +00:00
let tasmota_plugs: Vec<Tasmota> = devices
.plugs
.iter()
.map(|plug| Tasmota::new(plug))
.collect();
2023-09-21 08:08:23 +00:00
try_join!(
2023-09-21 05:30:39 +00:00
read_power_usage(tasmota_plugs.clone(), shared_db.clone()),
run_web_server(devices, tasmota_plugs, shared_db)
)?;
2023-09-19 08:52:12 +00:00
2023-09-21 05:30:39 +00:00
Ok(())
2023-09-19 08:52:12 +00:00
}