diff --git a/.gitignore b/.gitignore index 0e205d4..de3276d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ # Configuration file -Settings.* +settings.* # Generated by Cargo # will have compiled files and executables diff --git a/Cargo.toml b/Cargo.toml index ccbd534..18f311d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,3 +14,4 @@ log = "0.4.18" redis = "0.23.0" ron = "0.8.0" serde = { version = "1.0.163", features = ["derive"] } +toml = "0.7.4" diff --git a/copyme.Settings.toml b/copyme.settings.toml similarity index 76% rename from copyme.Settings.toml rename to copyme.settings.toml index d0055a3..f440bc0 100644 --- a/copyme.Settings.toml +++ b/copyme.settings.toml @@ -18,3 +18,11 @@ id = 0 # For Etherdream. IP of the DAC # [dac.etherdream] # url = "192.168.1.68" + +[[transformers]] +[transformers.translate] +x = 2000 +y = 2000 +[[transformers]] +[transformers.replicate] +Until = 48 diff --git a/src/conf.rs b/src/conf.rs index a92dcff..fe5e762 100644 --- a/src/conf.rs +++ b/src/conf.rs @@ -1,13 +1,16 @@ use config::Config; use serde::{Serialize,Deserialize}; -use crate::errors::LJResult; +use crate::errors::{LJError,LJResult}; +use crate::transformer; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Conf { pub laser_id: u8, pub debug: bool, pub redis_url: String, - pub dac: DacFamily + pub dac: DacFamily, + #[serde(default)] + pub transformers: Vec } #[derive(Serialize, Deserialize, Debug, Clone)] @@ -28,13 +31,49 @@ pub struct EtherDreamConf { pub url: String } +#[derive(Serialize, Deserialize, Debug, Clone)] +pub enum TransformConf { + #[serde(rename = "translate")] + Translate(transformer::Translate), + #[serde(rename = "replicate")] + Replicate(transformer::Replicate) +} + + impl Conf { pub fn new(path: &str) -> LJResult { let settings = Config::builder() .add_source(config::File::with_name(path)) .build()?; - let conf : Conf = settings.try_deserialize()?; + let conf : Conf = settings.try_deserialize().map_err(LJError::Config)?; Ok(conf) } + + pub fn get_transformers(&self) -> Vec> { + let mut v = vec![]; + for t in &self.transformers { + let t : Box = match t { + TransformConf::Translate(t) => Box::new(*t), + TransformConf::Replicate(r) => Box::new(*r) + }; + v.push(t); + } + v + } + + #[allow(dead_code)] + pub fn dump() { + let conf = Conf { laser_id: 0, + debug: true, + redis_url: "redis://127.0.0.1:6379/".to_string(), + dac: DacFamily::Helios(HeliosConf { id: 0 }), + transformers: vec![ + TransformConf::Translate(transformer::Translate::new(2000.0,2000.0)), + TransformConf::Replicate(transformer::Replicate::Until(48)) + ] + }; + let s = toml::to_string(&conf).unwrap(); + println!("{}", s); + } } diff --git a/src/device/mod.rs b/src/device.rs similarity index 90% rename from src/device/mod.rs rename to src/device.rs index 70a3916..d85d95a 100644 --- a/src/device/mod.rs +++ b/src/device.rs @@ -2,7 +2,7 @@ use crate::point::Point; mod helios; -use crate::conf::{Conf, DacFamily, EtherDreamConf, HeliosConf}; +use crate::conf::{Conf, DacFamily, /*EtherDreamConf, HeliosConf*/}; use crate::device::helios::HeliosDevice; use crate::errors::LJResult; @@ -29,7 +29,7 @@ pub struct Status { pub trait Device { fn status( &self ) -> Status; fn draw( - &self, + &mut self, frame: Vec, speed: u32, ) -> LJResult<()> ; diff --git a/src/device/common.rs b/src/device/common.rs new file mode 100644 index 0000000..020ad4d --- /dev/null +++ b/src/device/common.rs @@ -0,0 +1,31 @@ + +/* +self.protocol_version, +self.le_state, +self.playback_state, +self.source, +self.le_flags, +self.playback_flags, +self.source_flags, +self.fullness, +self.point_rate, +self.point_count +*/ + +pub struct Status { + pub active: bool, + pub last_traced_at: String, + pub properties: Vec +} + +pub trait Device { + /** + fn intersect(&self, orig : &Vec3, dir : &Vec3) -> Option; + fn get_surface(&self, v : &Vec3) -> Vec3; + fn get_normal(&self, v : &Vec3) -> Vec3; + fn get_material(&self) -> &dyn Material; + **/ + + fn status( &self ) -> Status; + +} diff --git a/src/device/helios.rs b/src/device/helios.rs index a090209..f607bb8 100644 --- a/src/device/helios.rs +++ b/src/device/helios.rs @@ -5,10 +5,10 @@ use helios_dac::{NativeHeliosDac, NativeHeliosDacController}; use helios_dac::{ // Coordinate, - Color, + // Color, DeviceStatus, Frame, - Point as HeliosPoint, + // Point as HeliosPoint, }; use crate::conf::HeliosConf; use crate::device::{Device, Status}; @@ -29,29 +29,29 @@ impl HeliosDevice { return Err(Box::new(LJError::HeliosDeviceMissing)); }; let dac = device.open()?; - Ok(Self { - conf: (*conf).clone(), dac, - }) + Ok(Self { conf: (*conf).clone(), dac }) } } impl Device for HeliosDevice { fn status(&self) -> Status { - return Status { + Status { active: true, last_traced_at: "now".to_string(), properties: vec!["foo".to_string()], - }; + } } - fn draw(&self, + fn draw(&mut self, line: Vec, speed: u32, ) -> LJResult<()> { - while let Ok(DeviceStatus::NotReady) = self.dac.status() {} + while let Ok(DeviceStatus::NotReady) = self.dac.status() { + } let points: Vec = line.into_iter().map(|p| p.into()).collect(); let frame = Frame::new(speed, points); + self.dac.write_frame(frame.clone())?; Ok(()) } diff --git a/src/errors.rs b/src/errors.rs index 45363e5..ff40f33 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,11 +1,13 @@ use std::error::Error; use std::fmt; use redis::RedisError; +use config::ConfigError; pub type LJResult = Result>; #[derive(Debug)] pub enum LJError { + Config(ConfigError), RedisConnect(RedisError), HeliosDeviceMissing } @@ -15,6 +17,10 @@ impl fmt::Display for LJError { use LJError::*; match self { + Config(err) => { + write!(f, "unable to load config file: {err}") + }, + RedisConnect(err) => { write!(f, "unable to connect to redis server: {err}") }, diff --git a/src/lib.rs b/src/lib.rs index 937f09a..b183c49 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ -pub mod conf; pub mod redis_ctrl; +pub mod conf; pub mod errors; pub mod device; pub mod point; +pub mod transformer; diff --git a/src/main.rs b/src/main.rs index ea02ccf..e52ef28 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,20 +10,17 @@ mod transformer; mod device; use device::device_factory; - - use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use redis_ctrl::{RedisCtrl, Order}; use conf::Conf; -use errors::{LJError, LJResult}; +use errors::LJResult; use point::Point; -use transformer::{Transformers, Translate, Replicate}; +use transformer::Transformers; use log::{LevelFilter, info, /* warn, */ error}; use env_logger::Builder; const DEFAULT_CONF_FILE: &str = "settings.toml"; -const CENTER: (f32, f32) = (2000.0, 2000.0); pub fn main() { match run_all() { @@ -35,16 +32,18 @@ pub fn main() { } 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)?; @@ -62,11 +61,7 @@ fn run_all() -> LJResult<()> { //dbg!(tracer); // Setup geometry transformers on points lists - // @todo use the config - let transformers: Vec> = vec![ - Box::new(Translate::new(CENTER.0, CENTER.1)), - Box::new(Replicate::Until(48)), - ]; + let transformers = config.get_transformers(); // Dispatch based on redis requests while running.load(Ordering::SeqCst) { @@ -74,6 +69,7 @@ fn run_all() -> LJResult<()> { if order != Order::Draw { info!("Order: {:?}", order); } + let frame = get_next_frame(&config, &transformers, &mut rs, order == Order::Black)?; @@ -113,6 +109,6 @@ fn get_next_frame( line = transformer.apply(&line); } - info!("Line: {:?}", line); + //info!("Line: {:?}", line); Ok(line) } diff --git a/src/transformer.rs b/src/transformer.rs index 3728f94..564b981 100644 --- a/src/transformer.rs +++ b/src/transformer.rs @@ -1,60 +1,13 @@ +//pub mod common; +mod translate; +mod replicate; + use crate::point::Point; +// re-export transformers to be abe to use it directly from transformer:: +pub use translate::Translate; +pub use replicate::Replicate; + pub trait Transformers { fn apply(&self, point_list: &[Point]) -> Vec; } - -/// Translate - -#[derive(Debug,Clone,Copy)] -pub struct Translate { - x: f32, - y: f32 -} - -impl Translate { - pub fn new(x: f32, y: f32) -> Self { - Self { x, y } - } -} - -impl Transformers for Translate { - fn apply(&self, point_list: &[Point]) -> Vec { - point_list.iter() - .map(| pt | { - Point { x: pt.x + self.x, - y: pt.y + self.y, - ..*pt - } - }).collect() - } -} - -/// Replicate - -#[allow(dead_code)] -#[derive(Debug,Clone,Copy)] -pub enum Replicate { - Until(usize), - Times(usize) -} - -impl Transformers for Replicate { - fn apply(&self, point_list: &[Point]) -> Vec { - let mut point_list2 = vec![]; - match self { - Replicate::Until(n) => { - while point_list2.len() < *n { - point_list2.append(&mut point_list.to_vec()); - } - }, - Replicate::Times(n) => { - for _ in 0..*n { - point_list2.append(&mut point_list.to_vec()); - } - } - } - point_list2 - } -} - diff --git a/src/transformer/replicate.rs b/src/transformer/replicate.rs new file mode 100644 index 0000000..99258ae --- /dev/null +++ b/src/transformer/replicate.rs @@ -0,0 +1,32 @@ +use crate::transformer::Transformers; +use crate::point::Point; +use serde::{Serialize,Deserialize}; + +/// Replicate + +#[allow(dead_code)] +#[derive(Serialize,Deserialize,Debug,Clone,Copy)] +pub enum Replicate { + Until(usize), + Times(usize) +} + +impl Transformers for Replicate { + fn apply(&self, point_list: &[Point]) -> Vec { + let mut point_list2 = vec![]; + match self { + Replicate::Until(n) => { + while point_list2.len() < *n { + point_list2.append(&mut point_list.to_vec()); + } + }, + Replicate::Times(n) => { + for _ in 0..*n { + point_list2.append(&mut point_list.to_vec()); + } + } + } + point_list2 + } +} + diff --git a/src/transformer/translate.rs b/src/transformer/translate.rs new file mode 100644 index 0000000..a36f272 --- /dev/null +++ b/src/transformer/translate.rs @@ -0,0 +1,29 @@ +use crate::transformer::Transformers; +use crate::point::Point; +use serde::{Serialize,Deserialize}; + +/// Translate + +#[derive(Serialize,Deserialize,Debug,Clone,Copy)] +pub struct Translate { + x: f32, + y: f32 +} + +impl Translate { + pub fn new(x: f32, y: f32) -> Self { + Self { x, y } + } +} + +impl Transformers for Translate { + fn apply(&self, point_list: &[Point]) -> Vec { + point_list.iter() + .map(| pt | { + Point { x: pt.x + self.x, + y: pt.y + self.y, + ..*pt + } + }).collect() + } +}