use std::{ sync::{Arc, Mutex}, thread, time::{Duration, SystemTime, UNIX_EPOCH}, }; use crate::db::DataBase; mod data; mod db; mod devices; mod tasmota; mod web_server; use actix_files::Files; use actix_web::{web::Data, App, HttpServer}; use anyhow::Result; use devices::Devices; use futures::{future::try_join_all, try_join, Future}; use tasmota::Tasmota; use web_server::{ change_device_name, change_plug_state, device_query, index, plug_data, plug_state, }; fn since_epoch() -> Result { Ok(SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs()) } fn read_power_usage( tasmota_plugs: Vec, db: Arc>, ) -> impl Future> { 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, db: Arc>, ) -> Result<()> { HttpServer::new(move || { App::new() .app_data(Data::new(devices.clone())) .app_data(Data::new(db.clone())) .app_data(Data::new(plugs.clone())) .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()) .service(index) .service(device_query) .service(plug_state) .service(change_plug_state) .service(change_device_name) .service(plug_data) }) .bind(("0.0.0.0", 8062)) .map_err(|err| anyhow::Error::msg(format!("failed binding to address: {err:#?}")))? .run() .await?; Ok(()) } #[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)?; db.register_devices(&devices)?; let shared_db = Arc::new(Mutex::new(db)); let tasmota_plugs: Vec = devices .plugs .iter() .map(|plug| Tasmota::new(plug)) .collect(); try_join!( read_power_usage(tasmota_plugs.clone(), shared_db.clone()), run_web_server(devices, tasmota_plugs, shared_db) )?; Ok(()) }