Compare commits

..

No commits in common. "0f3ee7c54a01c4c982e9ba335e38229d8763d9f1" and "883c72ff24090401eb9f01e8e1ce3ad8d2b79c4b" have entirely different histories.

5 changed files with 71 additions and 125 deletions

View File

@ -6,7 +6,6 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
chrono = "0.4.26"
config = "0.13.3" config = "0.13.3"
ctrlc = "3.4.0" ctrlc = "3.4.0"
env_logger = "0.10.0" env_logger = "0.10.0"

View File

@ -1,12 +1,10 @@
use crate::point::Point;
mod helios; mod helios;
use std::fmt; 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;
use crate::point::Point;
use serde::Serialize;
/* /*
self.protocol_version, self.protocol_version,
@ -20,40 +18,22 @@ self.fullness,
self.point_rate, self.point_rate,
self.point_count self.point_count
*/ */
#[repr(u8)]
#[derive(Debug, PartialEq, Serialize, Copy, Clone)]
pub enum PlaybackState {
IDLE = 0,
PREPARE,
PLAYING,
}
impl fmt::Display for PlaybackState {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
}
#[derive(Debug)]
pub struct Status { pub struct Status {
pub last_traced_at: String, pub active: bool,
pub properties: Vec<String>, pub last_traced_at: String,
pub playback_state: PlaybackState, pub properties: Vec<String>
pub capacity: u16,
pub lack: String
} }
// /lstt/lasernumber etherdream last_status.playback_state (0: idle 1: prepare 2: playing)
// /cap/lasernumber number of empty points sent to fill etherdream buffer (up to 1799)
// /lack/lasernumber "a": ACK "F": Full "I": invalid. 64 or 35 for no connection.
pub trait Device { pub trait Device {
fn status(&self) -> Status; fn status( &self ) -> Status;
fn draw( fn draw(
&mut self, &mut self,
frame: Vec<Point>, frame: Vec<Point>,
speed: u32, speed: u32,
) -> LJResult<()>; ) -> LJResult<()> ;
fn stop(&mut self) -> LJResult<()>; fn stop(&mut self) -> LJResult<()>;
} }
pub fn device_factory(config: &Conf) -> LJResult<Box<dyn Device>> { pub fn device_factory(config: &Conf) -> LJResult<Box<dyn Device>> {

View File

@ -11,16 +11,13 @@ use helios_dac::{
// Point as HeliosPoint, // Point as HeliosPoint,
}; };
use crate::conf::HeliosConf; use crate::conf::HeliosConf;
use crate::device::{Device, Status, PlaybackState}; use crate::device::{Device, Status};
use crate::errors::{LJError, LJResult}; use crate::errors::{LJError, LJResult};
use crate::point::Point; use crate::point::Point;
pub struct HeliosDevice { pub struct HeliosDevice {
pub conf: HeliosConf, pub conf: HeliosConf,
dac: NativeHeliosDac, dac: NativeHeliosDac,
sent_points: u16,
state: PlaybackState,
lack: String
} }
impl HeliosDevice { impl HeliosDevice {
@ -32,20 +29,16 @@ impl HeliosDevice {
return Err(Box::new(LJError::HeliosDeviceMissing)); return Err(Box::new(LJError::HeliosDeviceMissing));
}; };
let dac = device.open()?; let dac = device.open()?;
Ok(Self { conf: (*conf).clone(), dac, sent_points: 0, state: PlaybackState::PREPARE, lack: "".to_string() }) Ok(Self { conf: (*conf).clone(), dac })
} }
} }
impl Device for HeliosDevice { impl Device for HeliosDevice {
fn status(&self) -> Status { fn status(&self) -> Status {
let lack = self.lack.clone();
Status { Status {
active: true,
last_traced_at: "now".to_string(), last_traced_at: "now".to_string(),
properties: vec!["foo".to_string()], properties: vec!["foo".to_string()],
playback_state: self.state,
capacity: self.sent_points,
lack,
} }
} }
@ -53,14 +46,12 @@ impl Device for HeliosDevice {
line: Vec<Point>, line: Vec<Point>,
speed: u32, speed: u32,
) -> LJResult<()> { ) -> LJResult<()> {
self.state = PlaybackState::IDLE; while let Ok(DeviceStatus::NotReady) = self.dac.status() {
while let Ok(DeviceStatus::NotReady) = self.dac.status() {} }
self.state = PlaybackState::PLAYING;
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.clone()); let frame = Frame::new(speed, points);
self.dac.write_frame(frame.clone())?; self.dac.write_frame(frame.clone())?;
self.sent_points = points.len() as u16;
Ok(()) Ok(())
} }

View File

@ -45,7 +45,7 @@ fn run_all() -> LJResult<()> {
info!("{:?}", config); info!("{:?}", config);
// Setup Redis Service // Setup Redis Service
let mut rs = RedisCtrl::new(&config.redis_url, &config.laser_id)?; let mut rs = RedisCtrl::new(&config.redis_url)?;
// Setup handler for interrupt Signals // Setup handler for interrupt Signals
let running = Arc::new(AtomicBool::new(true)); let running = Arc::new(AtomicBool::new(true));
@ -65,7 +65,6 @@ fn run_all() -> LJResult<()> {
// Dispatch based on redis requests // Dispatch based on redis requests
while running.load(Ordering::SeqCst) { while running.load(Ordering::SeqCst) {
rs.set_status( tracer.status())?;
let order = rs.get_order(config.laser_id)?; let order = rs.get_order(config.laser_id)?;
if order != Order::Draw { if order != Order::Draw {
info!("Order: {:?}", order); info!("Order: {:?}", order);

View File

@ -1,99 +1,76 @@
use redis::{Client, Commands, Connection}; use redis::{Client, Commands, Connection};
use ron::de::from_str; use ron::de::from_str;
use crate::device::Status; use crate::errors::{LJError,LJResult};
use crate::errors::{LJError, LJResult};
#[repr(u8)] #[repr(u8)]
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum Order { pub enum Order {
Draw = 0, Draw = 0,
Edh, Edh, //homography
//homography Black,
Black, Grid,
Grid, Resampler,
Resampler, ClientKey,
ClientKey, Intensity,
Intensity, Kpps,
Kpps, ColorBalance,
ColorBalance,
} }
impl TryFrom<u8> for Order { impl TryFrom<u8> for Order {
type Error = String; type Error = String;
fn try_from(value: u8) -> Result<Self, Self::Error> { fn try_from(value: u8) -> Result<Self, Self::Error> {
use Order::*; use Order::*;
if value > 8 { if value > 8 {
return Err("order out of range".to_string()); 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,
_ => unreachable!()
})
} }
Ok(match value {
0 => Draw,
1 => Edh,
2 => Black,
3 => Grid,
4 => Resampler,
5 => ClientKey,
6 => Intensity,
7 => Kpps,
8 => ColorBalance,
_ => unreachable!()
})
}
} }
pub type Line = Vec<(f32, f32, u32)>; pub type Line = Vec<(f32, f32, u32)>;
pub struct RedisCtrl { pub struct RedisCtrl {
pub client: Client, pub client: Client,
pub connection: Connection, pub connection: Connection,
laser_id: u8,
} }
impl RedisCtrl { impl RedisCtrl {
pub fn new(url: &str, laser_id: &u8) -> LJResult<Self> { pub fn new(url: &str) -> LJResult<Self> {
let client = Client::open(url) let client = Client::open(url)
.map_err(LJError::RedisConnect)?; .map_err(LJError::RedisConnect)?;
let connection = client.get_connection() let connection = client.get_connection()
.map_err(LJError::RedisConnect)?; .map_err(LJError::RedisConnect)?;
Ok(RedisCtrl { client, connection, laser_id: *laser_id }) Ok(RedisCtrl { client, connection })
} }
pub fn get(&mut self, key: &str) -> LJResult<Line> { pub fn get(&mut self, key: &str) -> LJResult<Line> {
let val: String = self.connection.get(key)?; let val: String = self.connection.get(key)?;
let line: Line = from_str(&val)?; let line: Line = from_str(&val)?;
Ok(line) Ok(line)
} }
pub fn set(&mut self, key: String, value: String) -> LJResult<()> { pub fn get_order(&mut self, id: u8) -> LJResult<Order> {
self.connection.set(key, value)?; let path = format!("/order/{id}");
Ok(()) let val: u8 = self.connection.get(path.clone())?;
}
pub fn get_order(&mut self, id: u8) -> LJResult<Order> { if val == 1 || val >= 4 {
let path = format!("/order/{id}"); self.connection.set(path, 0)?;
let val: u8 = self.connection.get(path.clone())?; }
if val == 1 || val >= 4 { Ok(val.try_into()?)
self.connection.set(path, 0)?; }
}
Ok(val.try_into()?)
}
/**
/lstt/lasernumber etherdream last_status.playback_state (0: idle 1: prepare 2: playing)
/cap/lasernumber number of empty points sent to fill etherdream buffer (up to 1799)
/lack/lasernumber "a": ACK "F": Full "I": invalid. 64 or 35 for no connection.
**/
pub fn set_status(&mut self, status: Status) -> LJResult<()> {
let lstt_key = format!("/lstt/{}", self.laser_id);
let cap_key = format!("/cap/{}", self.laser_id);
let lack_key = format!("/lack/{}", self.laser_id);
self.set(lstt_key, status.playback_state.to_string())?;
self.set(cap_key, status.capacity.to_string())?;
self.set(lack_key, status.lack.to_string())?;
Ok(())
}
} }