Merge branch 'master' of git.interhacker.space:corpsmoderne/lazer_rust

This commit is contained in:
Lapin Raving 2023-06-08 22:15:41 +02:00
commit 5f03d74080
13 changed files with 179 additions and 83 deletions

2
.gitignore vendored
View File

@ -1,6 +1,6 @@
# Configuration file # Configuration file
Settings.* settings.*
# Generated by Cargo # Generated by Cargo
# will have compiled files and executables # will have compiled files and executables

View File

@ -14,3 +14,4 @@ log = "0.4.18"
redis = "0.23.0" redis = "0.23.0"
ron = "0.8.0" ron = "0.8.0"
serde = { version = "1.0.163", features = ["derive"] } serde = { version = "1.0.163", features = ["derive"] }
toml = "0.7.4"

View File

@ -18,3 +18,11 @@ id = 0
# For Etherdream. IP of the DAC # For Etherdream. IP of the DAC
# [dac.etherdream] # [dac.etherdream]
# url = "192.168.1.68" # url = "192.168.1.68"
[[transformers]]
[transformers.translate]
x = 2000
y = 2000
[[transformers]]
[transformers.replicate]
Until = 48

View File

@ -1,13 +1,16 @@
use config::Config; use config::Config;
use serde::{Serialize,Deserialize}; use serde::{Serialize,Deserialize};
use crate::errors::LJResult; use crate::errors::{LJError,LJResult};
use crate::transformer;
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Conf { pub struct Conf {
pub laser_id: u8, pub laser_id: u8,
pub debug: bool, pub debug: bool,
pub redis_url: String, pub redis_url: String,
pub dac: DacFamily pub dac: DacFamily,
#[serde(default)]
pub transformers: Vec<TransformConf>
} }
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
@ -28,13 +31,49 @@ pub struct EtherDreamConf {
pub url: String 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 { impl Conf {
pub fn new(path: &str) -> LJResult<Conf> { pub fn new(path: &str) -> LJResult<Conf> {
let settings = Config::builder() let settings = Config::builder()
.add_source(config::File::with_name(path)) .add_source(config::File::with_name(path))
.build()?; .build()?;
let conf : Conf = settings.try_deserialize()?; let conf : Conf = settings.try_deserialize().map_err(LJError::Config)?;
Ok(conf) Ok(conf)
} }
pub fn get_transformers(&self) -> Vec<Box<dyn transformer::Transformers>> {
let mut v = vec![];
for t in &self.transformers {
let t : Box<dyn transformer::Transformers> = 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);
}
} }

View File

@ -2,7 +2,7 @@ use crate::point::Point;
mod helios; mod helios;
use crate::conf::{Conf, DacFamily, EtherDreamConf, HeliosConf}; use crate::conf::{Conf, DacFamily, /*EtherDreamConf, HeliosConf*/};
use crate::device::helios::HeliosDevice; use crate::device::helios::HeliosDevice;
use crate::errors::LJResult; use crate::errors::LJResult;
@ -29,7 +29,7 @@ pub struct Status {
pub trait Device { pub trait Device {
fn status( &self ) -> Status; fn status( &self ) -> Status;
fn draw( fn draw(
&self, &mut self,
frame: Vec<Point>, frame: Vec<Point>,
speed: u32, speed: u32,
) -> LJResult<()> ; ) -> LJResult<()> ;

31
src/device/common.rs Normal file
View File

@ -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<String>
}
pub trait Device {
/**
fn intersect(&self, orig : &Vec3, dir : &Vec3) -> Option<Float>;
fn get_surface(&self, v : &Vec3) -> Vec3;
fn get_normal(&self, v : &Vec3) -> Vec3;
fn get_material(&self) -> &dyn Material;
**/
fn status( &self ) -> Status;
}

View File

@ -5,10 +5,10 @@
use helios_dac::{NativeHeliosDac, NativeHeliosDacController}; use helios_dac::{NativeHeliosDac, NativeHeliosDacController};
use helios_dac::{ use helios_dac::{
// Coordinate, // Coordinate,
Color, // Color,
DeviceStatus, DeviceStatus,
Frame, Frame,
Point as HeliosPoint, // Point as HeliosPoint,
}; };
use crate::conf::HeliosConf; use crate::conf::HeliosConf;
use crate::device::{Device, Status}; use crate::device::{Device, Status};
@ -29,29 +29,29 @@ impl HeliosDevice {
return Err(Box::new(LJError::HeliosDeviceMissing)); return Err(Box::new(LJError::HeliosDeviceMissing));
}; };
let dac = device.open()?; let dac = device.open()?;
Ok(Self { Ok(Self { conf: (*conf).clone(), dac })
conf: (*conf).clone(), dac,
})
} }
} }
impl Device for HeliosDevice { impl Device for HeliosDevice {
fn status(&self) -> Status { fn status(&self) -> Status {
return Status { Status {
active: true, active: true,
last_traced_at: "now".to_string(), last_traced_at: "now".to_string(),
properties: vec!["foo".to_string()], properties: vec!["foo".to_string()],
}; }
} }
fn draw(&self, fn draw(&mut self,
line: Vec<Point>, line: Vec<Point>,
speed: u32, speed: u32,
) -> LJResult<()> { ) -> LJResult<()> {
while let Ok(DeviceStatus::NotReady) = self.dac.status() {} while let Ok(DeviceStatus::NotReady) = self.dac.status() {
}
let points: Vec<helios_dac::Point> = line.into_iter().map(|p| p.into()).collect(); let points: Vec<helios_dac::Point> = line.into_iter().map(|p| p.into()).collect();
let frame = Frame::new(speed, points); let frame = Frame::new(speed, points);
self.dac.write_frame(frame.clone())?;
Ok(()) Ok(())
} }

View File

@ -1,11 +1,13 @@
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use redis::RedisError; use redis::RedisError;
use config::ConfigError;
pub type LJResult<T> = Result<T, Box<dyn std::error::Error>>; pub type LJResult<T> = Result<T, Box<dyn std::error::Error>>;
#[derive(Debug)] #[derive(Debug)]
pub enum LJError { pub enum LJError {
Config(ConfigError),
RedisConnect(RedisError), RedisConnect(RedisError),
HeliosDeviceMissing HeliosDeviceMissing
} }
@ -15,6 +17,10 @@ impl fmt::Display for LJError {
use LJError::*; use LJError::*;
match self { match self {
Config(err) => {
write!(f, "unable to load config file: {err}")
},
RedisConnect(err) => { RedisConnect(err) => {
write!(f, "unable to connect to redis server: {err}") write!(f, "unable to connect to redis server: {err}")
}, },

View File

@ -1,5 +1,6 @@
pub mod conf;
pub mod redis_ctrl; pub mod redis_ctrl;
pub mod conf;
pub mod errors; pub mod errors;
pub mod device; pub mod device;
pub mod point; pub mod point;
pub mod transformer;

View File

@ -10,20 +10,17 @@ mod transformer;
mod device; mod device;
use device::device_factory; use device::device_factory;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc; use std::sync::Arc;
use redis_ctrl::{RedisCtrl, Order}; use redis_ctrl::{RedisCtrl, Order};
use conf::Conf; use conf::Conf;
use errors::{LJError, LJResult}; use errors::LJResult;
use point::Point; use point::Point;
use transformer::{Transformers, Translate, Replicate}; use transformer::Transformers;
use log::{LevelFilter, info, /* warn, */ error}; use log::{LevelFilter, info, /* warn, */ error};
use env_logger::Builder; use env_logger::Builder;
const DEFAULT_CONF_FILE: &str = "settings.toml"; const DEFAULT_CONF_FILE: &str = "settings.toml";
const CENTER: (f32, f32) = (2000.0, 2000.0);
pub fn main() { pub fn main() {
match run_all() { match run_all() {
@ -35,16 +32,18 @@ pub fn main() {
} }
fn run_all() -> LJResult<()> { fn run_all() -> LJResult<()> {
// Setup configuration file and set up logs // Setup configuration file and set up logs
let filename = std::env::args().nth(1).unwrap_or_else(|| { let filename = std::env::args().nth(1).unwrap_or_else(|| {
DEFAULT_CONF_FILE.to_string() DEFAULT_CONF_FILE.to_string()
}); });
let config = Conf::new(&filename); let config = Conf::new(&filename);
init_logging(&config); init_logging(&config);
let config = config?; let config = config?;
info!("*** Starting up ***"); info!("*** Starting up ***");
info!("{:?}", config);
// Setup Redis Service // Setup Redis Service
let mut rs = RedisCtrl::new(&config.redis_url)?; let mut rs = RedisCtrl::new(&config.redis_url)?;
@ -62,11 +61,7 @@ fn run_all() -> LJResult<()> {
//dbg!(tracer); //dbg!(tracer);
// Setup geometry transformers on points lists // Setup geometry transformers on points lists
// @todo use the config let transformers = config.get_transformers();
let transformers: Vec<Box<dyn Transformers>> = vec![
Box::new(Translate::new(CENTER.0, CENTER.1)),
Box::new(Replicate::Until(48)),
];
// Dispatch based on redis requests // Dispatch based on redis requests
while running.load(Ordering::SeqCst) { while running.load(Ordering::SeqCst) {
@ -74,6 +69,7 @@ fn run_all() -> LJResult<()> {
if order != Order::Draw { if order != Order::Draw {
info!("Order: {:?}", order); info!("Order: {:?}", order);
} }
let frame = get_next_frame(&config, &transformers, let frame = get_next_frame(&config, &transformers,
&mut rs, order == Order::Black)?; &mut rs, order == Order::Black)?;
@ -113,6 +109,6 @@ fn get_next_frame(
line = transformer.apply(&line); line = transformer.apply(&line);
} }
info!("Line: {:?}", line); //info!("Line: {:?}", line);
Ok(line) Ok(line)
} }

View File

@ -1,60 +1,13 @@
//pub mod common;
mod translate;
mod replicate;
use crate::point::Point; 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 { pub trait Transformers {
fn apply(&self, point_list: &[Point]) -> Vec<Point>; fn apply(&self, point_list: &[Point]) -> Vec<Point>;
} }
/// 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> {
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<Point> {
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
}
}

View File

@ -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<Point> {
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
}
}

View File

@ -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> {
point_list.iter()
.map(| pt | {
Point { x: pt.x + self.x,
y: pt.y + self.y,
..*pt
}
}).collect()
}
}