/// /// Configure udev: /// https://github.com/Grix/helios_dac/blob/master/docs/udev_rules_for_linux.md /// mod redis_ctrl; mod conf; mod errors; mod point; mod transformer; mod device; mod worldstate; use device::device_factory; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use redis_ctrl::{RedisCtrl, Order}; use conf::Conf; use errors::LJResult; use point::{Point, Color}; use transformer::Transformers; use log::{LevelFilter, info, /* warn, */ error}; use env_logger::Builder; 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 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 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); // 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")?; } 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 { let level = if config.debug { LevelFilter::Debug } else { LevelFilter::Info }; let mut builder = Builder::from_default_env(); builder .filter(None, level) .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) }