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) { 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], rs: &mut RedisCtrl, world_state: &WorldState, ) -> LJResult> { let format_key = format!("{}{}", world_state.client_key, config.laser_id); // Handle the grid case let mut line: Vec = 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) }