lj_rust/src/main.rs

180 lines
5.3 KiB
Rust

mod conf;
mod device;
mod errors;
mod point;
///
/// Configure udev:
/// https://github.com/Grix/helios_dac/blob/master/docs/udev_rules_for_linux.md
///
mod redis_ctrl;
mod transformer;
mod worldstate;
use conf::Conf;
use device::device_factory;
use env_logger::Builder;
use errors::LJResult;
use log::{/* warn, */ error, info, LevelFilter};
use point::{Color, Point};
use redis_ctrl::{Order, RedisCtrl};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use transformer::Transformers;
use worldstate::WorldState;
const DEFAULT_CONF_FILE: &str = "settings.toml";
pub fn main() {
match run_all() {
Ok(()) => {}
Err(err) => {
error!("Error: {}", err);
}
}
}
fn run_all() -> LJResult<()> {
// Setup configuration file and set up logs
let filename = std::env::args()
.nth(1)
.unwrap_or_else(|| DEFAULT_CONF_FILE.to_string());
let config = Conf::new(&filename);
init_logging(&config);
let config = config?;
info!("*** Starting up ***");
info!("{:?}", config);
// Setup Redis Service
let mut rs = RedisCtrl::new(&config.redis_url, &config.laser_id)?;
let mut world_state = rs.init_world_state().unwrap();
info!("WorldState: {:?}", world_state);
dbg!("worldstate.kpps: {}", world_state.kpps);
// Setup handler for interrupt Signals
let running = Arc::new(AtomicBool::new(true));
let r = running.clone();
ctrlc::set_handler(move || {
r.store(false, Ordering::SeqCst);
})?;
// Setup Laser Device based on conf
let mut tracer = device_factory(&config)?;
world_state.grid = tracer.grid();
// can't work, but we can add + Debug to Device to make it work...
//dbg!(tracer);
// Setup geometry transformers on points lists
let transformers = config.get_transformers();
// Dispatch based on redis requests
while running.load(Ordering::SeqCst) {
rs.set_status(tracer.status())?;
let order = rs.get_order(config.laser_id)?;
match order {
Order::Draw | Order::Black | Order::Grid => {
// 0 : Draw Normal point list
// 2 : Draw BLACK point list
// 3 : Draw GRID point list
world_state.draw_black = order == Order::Black;
world_state.draw_grid = order == Order::Grid;
let frame = get_next_frame(&config, &transformers, &mut rs, &world_state)?;
// For now, draw all the time
tracer.draw(frame, world_state.kpps)?;
}
Order::Intensity => {
// 6 : Max Intensity Change = reread redis key /intensity
world_state.intensity = rs.get_int("intensity")?.try_into()?;
}
Order::Edh => {
// 1 : Get the new EDH = reread redis key /EDH/lasernumber
world_state.edh = rs.get_edh()?;
}
Order::Kpps => {
// 7 : kpps change = reread redis key /kpps
world_state.kpps = rs.get_int("kpps")?;
//dbg!(world_state.kpps);
}
Order::ClientKey => {
world_state.client_key = rs.get_client_key()?;
}
// Order::ColorBalance => {},
_ => {
// 4 : Resampler Change (longs and shorts lsteps)
// 5 : Client Key Change = reread redis key /clientkey
// 8 : color balance change = reread redis keys /red /green /blue
// 9 : poweroff LJ
info!("Order: {:?}", order);
}
}
}
info!("Exiting, stoping device.");
tracer.stop()?;
Ok(())
}
fn init_logging(config: &LJResult<Conf>) {
if let Ok(ref config) = config {
if config.debug {
let mut builder = Builder::from_default_env();
builder.filter(None, LevelFilter::Info).init();
info!("Debug mode enabled from configuration file");
return;
}
}
info!("Logging level inherited from env");
env_logger::init();
}
fn get_next_frame(
config: &Conf,
transformers: &[Box<dyn Transformers>],
rs: &mut RedisCtrl,
world_state: &WorldState,
) -> LJResult<Vec<Point>> {
let format_key = format!("{}{}", world_state.client_key, config.laser_id);
// Handle the grid case
let mut line: Vec<Point> = if world_state.draw_grid {
world_state.grid.clone()
} else {
let redis_line = rs.get_line(&format_key)?;
redis_line.into_iter().map(|tpl| tpl.into()).collect()
};
for transformer in transformers {
line = transformer.apply(&line, world_state);
}
info!("Draw Black -> {}", world_state.draw_black);
info!("Draw Grid -> {}", world_state.draw_grid);
// LIMITER and BLACK
line = line
.into_iter()
.map(|p| {
let color = if world_state.draw_black {
Color { r: 0, g: 0, b: 0 }
} else {
Color {
r: p.color.r.min(world_state.intensity),
g: p.color.g.min(world_state.intensity),
b: p.color.b.min(world_state.intensity),
}
};
Point { color, ..p }
})
.collect();
//info!("Line: {:?}", line);
Ok(line)
}