#![warn(clippy::all)] #![warn(clippy::print_stdout)] use color_eyre::eyre::Result; use rusqlite::Connection as DbConnection; use rusqlite::NO_PARAMS; use tracing::info; use tracing_subscriber::EnvFilter; mod db; mod migrations; mod model; mod option_future; mod program_runner; mod schedule; mod section_interface; mod section_runner; #[cfg(test)] mod trace_listeners; use im::ordmap; use model::{Program, ProgramItem, ProgramRef, Section, Sections}; use schedule::Schedule; use std::{sync::Arc, time::Duration}; fn setup_db() -> Result { // let conn = DbConnection::open_in_memory()?; let mut conn = DbConnection::open("test.db")?; let migs = db::create_migrations(); migs.apply(&mut conn)?; Ok(conn) } fn query_sections(conn: &DbConnection) -> Result { let mut statement = conn.prepare_cached( "SELECT s.id, s.name, s.interface_id \ FROM sections AS s;", )?; let rows = statement.query_map(NO_PARAMS, Section::from_sql)?; let mut sections = Sections::new(); for row in rows { let section = row?; sections.insert(section.id, section.into()); } Ok(sections) } #[tokio::main] async fn main() -> Result<()> { tracing_subscriber::fmt() .with_ansi(true) .with_env_filter( EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")), ) .init(); color_eyre::install()?; let conn = setup_db()?; let sections = query_sections(&conn)?; for sec in sections.values() { info!(section = debug(&sec), "read section"); } // TODO: Section interface which actual does something. Preferrably selectable somehow let section_interface: Arc<_> = section_interface::MockSectionInterface::new(6).into(); let mut section_runner = section_runner::SectionRunner::new(section_interface); let mut program_runner = program_runner::ProgramRunner::new(section_runner.clone()); let run_time = chrono::Local::now().time() + chrono::Duration::seconds(5); let schedule = Schedule::new( vec![run_time], schedule::every_day(), schedule::DateTimeBound::None, schedule::DateTimeBound::None, ); let program: ProgramRef = Program { id: 1, name: "Test Program".into(), sequence: sections .values() .map(|sec| ProgramItem { section_id: sec.id, duration: Duration::from_secs(2), }) .collect(), enabled: true, schedule, } .into(); let programs = ordmap![1 => program]; program_runner.update_sections(sections.clone()).await?; program_runner.update_programs(programs.clone()).await?; info!("sprinklers_rs initialized"); tokio::signal::ctrl_c().await?; info!("Interrupt received, shutting down"); program_runner.quit().await?; section_runner.quit().await?; tokio::task::yield_now().await; Ok(()) }