|
|
|
#![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<DbConnection> {
|
|
|
|
// 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<Sections> {
|
|
|
|
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(())
|
|
|
|
}
|