From c02389ad4d5b79d6f9dc1688469da9b0d1f6fc62 Mon Sep 17 00:00:00 2001 From: alban Date: Sat, 3 Jun 2023 18:42:17 +0200 Subject: [PATCH 1/5] fix: crate name --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 1b4a46d..a9ba871 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "lazer" +name = "lj_rust" version = "0.1.0" edition = "2021" From 05f43c680cab7553460a4185d30461a2914495b7 Mon Sep 17 00:00:00 2001 From: alban Date: Sat, 3 Jun 2023 18:42:44 +0200 Subject: [PATCH 2/5] fix: settings template --- copyme.Settings.toml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/copyme.Settings.toml b/copyme.Settings.toml index 5296d56..21944b6 100644 --- a/copyme.Settings.toml +++ b/copyme.Settings.toml @@ -1,6 +1,20 @@ +# file: Settings.toml +# Rename me ! + +# The main key of your laser in LJ laser_id = 0 + +# Activate for more debug debug = "true" + +# Redis URL as IP:port redis_url = "127.0.0.1" + +# Either Helios or Etherdream dac_family = "Helios" -dac_id = 1 + +# For Helios. USB Device Id of the DAC +dac_id = 0 + +# For Etherdream. IP of the DAC dac_url = "192.168.1.68" From 4ce35dfd0d36ca8fb190fe5f8d96e6096b32be37 Mon Sep 17 00:00:00 2001 From: alban Date: Sat, 3 Jun 2023 18:43:04 +0200 Subject: [PATCH 3/5] feat: add testing infrastructure --- src/lib.rs | 2 ++ tests/test_conf.rs | 6 ++++++ 2 files changed, 8 insertions(+) create mode 100644 src/lib.rs create mode 100644 tests/test_conf.rs diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..167b21e --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,2 @@ +pub mod conf; +pub mod redis_ctrl; \ No newline at end of file diff --git a/tests/test_conf.rs b/tests/test_conf.rs new file mode 100644 index 0000000..1305e13 --- /dev/null +++ b/tests/test_conf.rs @@ -0,0 +1,6 @@ +use lj_rust::conf; + +#[test] +fn it_adds_two() { + assert_eq!(4, 4); +} \ No newline at end of file From ae14cb600dda247e8c0e2456e7858443a8bc7e7f Mon Sep 17 00:00:00 2001 From: alban Date: Sat, 3 Jun 2023 18:54:41 +0200 Subject: [PATCH 4/5] fix: format using rustfmt --- src/conf.rs | 36 +++++++------- src/lib.rs | 2 +- src/main.rs | 120 +++++++++++++++++++++------------------------- src/redis_ctrl.rs | 95 ++++++++++++++++-------------------- 4 files changed, 113 insertions(+), 140 deletions(-) diff --git a/src/conf.rs b/src/conf.rs index 7cbf585..051cd58 100644 --- a/src/conf.rs +++ b/src/conf.rs @@ -1,32 +1,28 @@ - use config::Config; use serde::Deserialize; - -#[derive(Deserialize,Debug)] +#[derive(Deserialize, Debug)] pub enum DacFamily { Helios, - Etherdream - } - -#[derive(Deserialize,Debug)] -pub struct Conf { - laser_id : u8, - debug : bool, - redis_url : String, - dac_family: DacFamily, - dac_id : Option, - dac_url : Option + Etherdream, } +#[derive(Deserialize, Debug)] +pub struct Conf { + laser_id: u8, + debug: bool, + redis_url: String, + dac_family: DacFamily, + dac_id: Option, + dac_url: Option, +} -pub fn load_config( path : &str )-> Result> { +pub fn load_config(path: &str) -> Result> { let settings = Config::builder() .add_source(config::File::with_name(path)) - .build()?; - - let conf = settings - .try_deserialize::()?; - + .build()?; + + let conf = settings.try_deserialize::()?; + Ok(conf) } diff --git a/src/lib.rs b/src/lib.rs index 167b21e..524f793 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,2 @@ pub mod conf; -pub mod redis_ctrl; \ No newline at end of file +pub mod redis_ctrl; diff --git a/src/main.rs b/src/main.rs index e1a22a5..374e9a0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,81 +1,77 @@ +mod conf; /// /// Configure udev: /// https://github.com/Grix/helios_dac/blob/master/docs/udev_rules_for_linux.md /// - mod redis_ctrl; -mod conf; -use helios_dac::{Frame, - Point, - DeviceStatus, - // Coordinate, - Color}; use helios_dac::NativeHeliosDacController; +use helios_dac::{ + // Coordinate, + Color, + DeviceStatus, + Frame, + Point, +}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; -use redis_ctrl::{RedisCtrl,Order}; -use conf::{load_config,Conf}; +use conf::{load_config, Conf}; +use redis_ctrl::{Order, RedisCtrl}; - -const CENTER : (u16,u16) = (2000, 2000); +const CENTER: (u16, u16) = (2000, 2000); pub fn main() { - let config = match load_config("Settings") { - Ok(c) => c, - Err(err) => { - panic!("Unable to load config file: {:?}", err) - } + Ok(c) => c, + Err(err) => { + panic!("Unable to load config file: {:?}", err) + } }; - + let rs = match RedisCtrl::new() { - Ok(rs) => rs, - Err(err) => { - panic!("Unable to connect to redis: {:?}", err); - } + Ok(rs) => rs, + Err(err) => { + panic!("Unable to connect to redis: {:?}", err); + } }; match run_dac(config, rs) { - Ok(()) => {}, - Err(err) => { - panic!("Error: {:?}", err) - } + Ok(()) => {} + Err(err) => { + panic!("Error: {:?}", err) + } } } -fn run_dac( - config: Conf, - mut rs: RedisCtrl -) -> Result<(), Box> { +fn run_dac(config: Conf, mut rs: RedisCtrl) -> Result<(), Box> { let running = Arc::new(AtomicBool::new(true)); let r = running.clone(); ctrlc::set_handler(move || { r.store(false, Ordering::SeqCst); - }).expect("Error setting Ctrl-C handler"); + }) + .expect("Error setting Ctrl-C handler"); let controller = NativeHeliosDacController::new()?; let devices = controller.list_devices()?; - + let Some(device) = devices.into_iter().next() else { println!("Unable to find an helios device"); return Ok(()); }; - - let mut device = device.open()?; - - while running.load(Ordering::SeqCst) { - let order = rs.get_order(0)?; - if order != Order::Draw { - println!("{:?}", order); - } - let frame = get_next_frame(1000, &mut rs)?; - - while let Ok(DeviceStatus::NotReady) = device.status() { - } + let mut device = device.open()?; + + while running.load(Ordering::SeqCst) { + let order = rs.get_order(0)?; + if order != Order::Draw { + println!("{:?}", order); + } + + let frame = get_next_frame(1000, &mut rs)?; + + while let Ok(DeviceStatus::NotReady) = device.status() {} device.write_frame(frame)?; } @@ -84,45 +80,39 @@ fn run_dac( Ok(()) } -fn get_next_frame( - speed: u32, - rs: &mut RedisCtrl -) -> Result> { - +fn get_next_frame(speed: u32, rs: &mut RedisCtrl) -> Result> { let line = rs.get("/pl/0/0")?; - let line : Vec = line.iter() - .map(tuple_to_point) - .collect(); - + let line: Vec = line.iter().map(tuple_to_point).collect(); + let mut line2 = vec![]; while line2.len() < 48 { - for p in &line { - line2.push(*p); - } + for p in &line { + line2.push(*p); + } } - + Ok(Frame::new(speed, line2)) } -fn tuple_to_point(tpl: &(f32,f32,u32)) -> Point { +fn tuple_to_point(tpl: &(f32, f32, u32)) -> Point { let (x, y, col) = tpl; - - let r = (col >> 16) as u8 ; - let g = ((col >> 8) & 255) as u8 ; - let b = (col & 255) as u8 ; - + + let r = (col >> 16) as u8; + let g = ((col >> 8) & 255) as u8; + let b = (col & 255) as u8; + let x = CENTER.0 + *x as u16; let y = CENTER.1 + *y as u16; if x >= 4096 || y >= 4096 { - println!("WARN: coordinate out of range: {} {}", x, y); + println!("WARN: coordinate out of range: {} {}", x, y); } let x = x.clamp(0, 4095); let y = y.clamp(0, 4095); - + Point { coordinate: (x, y).into(), color: Color::new(r, g, b), - intensity: 0xFF + intensity: 0xFF, } } diff --git a/src/redis_ctrl.rs b/src/redis_ctrl.rs index ff60f80..238bd8a 100644 --- a/src/redis_ctrl.rs +++ b/src/redis_ctrl.rs @@ -1,12 +1,8 @@ -use redis::{ - Client, - Connection, - Commands -}; +use redis::{Client, Commands, Connection}; use ron::de::from_str; #[repr(u8)] -#[derive(Debug,PartialEq)] +#[derive(Debug, PartialEq)] pub enum Order { Draw = 0, Edh, //homography @@ -16,71 +12,62 @@ pub enum Order { ClientKey, Intensity, Kpps, - ColorBalance + ColorBalance, } impl TryFrom for Order { type Error = String; - + fn try_from(value: u8) -> Result { - use Order::*; + use Order::*; - if value > 8 { - return Err("order out of range".to_string()); - } - - Ok(match value { - 0 => Draw, - 1 => Edh, - 2 => Black, - 3 => Grid, - 4 => Resampler, - 5 => ClientKey, - 6 => Intensity, - 7 => Kpps, - 8 => ColorBalance, - _ => panic!("Can't be there") - }) + if value > 8 { + return Err("order out of range".to_string()); + } + + Ok(match value { + 0 => Draw, + 1 => Edh, + 2 => Black, + 3 => Grid, + 4 => Resampler, + 5 => ClientKey, + 6 => Intensity, + 7 => Kpps, + 8 => ColorBalance, + _ => panic!("Can't be there"), + }) } -} +} -pub type Line = Vec<(f32,f32,u32)>; +pub type Line = Vec<(f32, f32, u32)>; pub struct RedisCtrl { pub client: Client, - pub connection: Connection + pub connection: Connection, } impl RedisCtrl { - pub fn new() -> Result> { - let client = Client::open("redis://127.0.0.1/")?; - let connection = client.get_connection()?; - Ok(RedisCtrl { client, connection }) + let client = Client::open("redis://127.0.0.1/")?; + let connection = client.get_connection()?; + Ok(RedisCtrl { client, connection }) } - pub fn get( - &mut self, - key: &str - ) -> Result> { - let val : String = self.connection.get(key)?; - let line : Line = from_str(&val)?; - Ok(line) - } - - pub fn get_order( - &mut self, - id: u8 - ) -> Result> { - let path = format!("/order/{id}"); - let val : u8 = self.connection.get(path.clone())?; - - if val == 1 || val >= 4 { - self.connection.set(path, 0)?; - } - - Ok(val.try_into()?) + pub fn get(&mut self, key: &str) -> Result> { + let val: String = self.connection.get(key)?; + let line: Line = from_str(&val)?; + Ok(line) } + pub fn get_order(&mut self, id: u8) -> Result> { + let path = format!("/order/{id}"); + let val: u8 = self.connection.get(path.clone())?; + + if val == 1 || val >= 4 { + self.connection.set(path, 0)?; + } + + Ok(val.try_into()?) + } } - From 312a48ff5b9346872eddace40da72121d507cab2 Mon Sep 17 00:00:00 2001 From: alban Date: Sat, 3 Jun 2023 23:27:12 +0200 Subject: [PATCH 5/5] feat: add tests for conf --- src/conf.rs | 14 +++++++------- tests/settings/empty.toml | 0 tests/settings/valid.toml | 19 +++++++++++++++++++ tests/test_conf.rs | 34 ++++++++++++++++++++++++++++++---- 4 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 tests/settings/empty.toml create mode 100644 tests/settings/valid.toml diff --git a/src/conf.rs b/src/conf.rs index 051cd58..02ea741 100644 --- a/src/conf.rs +++ b/src/conf.rs @@ -9,14 +9,13 @@ pub enum DacFamily { #[derive(Deserialize, Debug)] pub struct Conf { - laser_id: u8, - debug: bool, - redis_url: String, - dac_family: DacFamily, - dac_id: Option, - dac_url: Option, + pub laser_id: u8, + pub debug: bool, + pub redis_url: String, + pub dac_family: DacFamily, + pub dac_id: Option, + pub dac_url: Option, } - pub fn load_config(path: &str) -> Result> { let settings = Config::builder() .add_source(config::File::with_name(path)) @@ -24,5 +23,6 @@ pub fn load_config(path: &str) -> Result> { let conf = settings.try_deserialize::()?; + Ok(conf) } diff --git a/tests/settings/empty.toml b/tests/settings/empty.toml new file mode 100644 index 0000000..e69de29 diff --git a/tests/settings/valid.toml b/tests/settings/valid.toml new file mode 100644 index 0000000..1d9689c --- /dev/null +++ b/tests/settings/valid.toml @@ -0,0 +1,19 @@ +# file: valid.toml + +# The main key of your laser in LJ +laser_id = 0 + +# Activate for more debug +debug = "true" + +# Redis URL as IP:port +redis_url = "127.0.0.1" + +# Either Helios or Etherdream +dac_family = "Helios" + +# For Helios. USB Device Id of the DAC +dac_id = 0 + +# For Etherdream. IP of the DAC +dac_url = "192.168.1.68" diff --git a/tests/test_conf.rs b/tests/test_conf.rs index 1305e13..a366a11 100644 --- a/tests/test_conf.rs +++ b/tests/test_conf.rs @@ -1,6 +1,32 @@ -use lj_rust::conf; +use lj_rust::conf::{load_config, DacFamily}; #[test] -fn it_adds_two() { - assert_eq!(4, 4); -} \ No newline at end of file +fn it_loads_a_valid_conf() { + let result = load_config("tests/settings/valid"); + assert!(result.is_ok()); +} + +#[test] +fn it_fails_invalid_conf() { + let result = load_config("tests/settings/empty"); + assert!(result.is_err()); +} + +#[test] +fn it_finds_struct_fields() { + let config = match load_config("tests/settings/valid") { + Ok(c) => c, + Err(err) => { + panic!("Unable to load config file: {:?}", err) + } + }; + assert_eq!(config.laser_id, u8::from(0)); + assert_eq!(config.debug, true); + assert_eq!(config.redis_url, String::from("127.0.0.1")); + assert!(match config.dac_family { + DacFamily::Helios => true, + _ => false, + }); + assert_eq!(config.dac_id, Some(0)); + assert_eq!(config.dac_url, Some(String::from("192.168.1.68"))); +}