Implementation of firmware for a sprinklers system using async Rust, Tokio, Actix, MQTT and more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

103 lines
2.8 KiB

#![warn(clippy::all)]
#![warn(clippy::print_stdout)]
5 years ago
use color_eyre::eyre::Result;
use rusqlite::Connection as DbConnection;
use rusqlite::NO_PARAMS;
use tracing::info;
5 years ago
use tracing_subscriber::EnvFilter;
5 years ago
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 model::{Program, Programs, Section, Sections};
use std::sync::Arc;
5 years ago
fn setup_db() -> Result<DbConnection> {
5 years ago
// 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)
5 years ago
}
fn query_programs(conn: &DbConnection) -> Result<Programs> {
let mut statement = conn.prepare_cached(
"
SELECT p.id, p.name, ps.sequence, p.enabled, p.schedule
FROM programs AS p
INNER JOIN program_sequences AS ps
ON ps.program_id = p.id;",
)?;
let rows = statement.query_map(NO_PARAMS, Program::from_sql)?;
let mut programs = Programs::new();
for row in rows {
let program = row?;
programs.insert(program.id, program.into());
}
Ok(programs)
}
#[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();
5 years ago
color_eyre::install()?;
let conn = setup_db()?;
let sections = query_sections(&conn)?;
for sec in sections.values() {
info!(section = debug(&sec), "read section");
}
5 years ago
// 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 programs = query_programs(&conn)?;
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;
5 years ago
Ok(())
}