Compare commits
2 Commits
883c72ff24
...
0f3ee7c54a
Author | SHA1 | Date | |
---|---|---|---|
|
0f3ee7c54a | ||
|
526a78428b |
@ -6,6 +6,7 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.4.26"
|
||||
config = "0.13.3"
|
||||
ctrlc = "3.4.0"
|
||||
env_logger = "0.10.0"
|
||||
|
@ -1,10 +1,12 @@
|
||||
use crate::point::Point;
|
||||
|
||||
mod helios;
|
||||
|
||||
use crate::conf::{Conf, DacFamily, /*EtherDreamConf, HeliosConf*/};
|
||||
use std::fmt;
|
||||
use crate::conf::{Conf, DacFamily /*EtherDreamConf, HeliosConf*/};
|
||||
use crate::device::helios::HeliosDevice;
|
||||
use crate::errors::LJResult;
|
||||
use crate::point::Point;
|
||||
use serde::Serialize;
|
||||
|
||||
/*
|
||||
self.protocol_version,
|
||||
@ -18,22 +20,40 @@ self.fullness,
|
||||
self.point_rate,
|
||||
self.point_count
|
||||
*/
|
||||
|
||||
|
||||
pub struct Status {
|
||||
pub active: bool,
|
||||
pub last_traced_at: String,
|
||||
pub properties: Vec<String>
|
||||
#[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 last_traced_at: String,
|
||||
pub properties: Vec<String>,
|
||||
pub playback_state: PlaybackState,
|
||||
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 {
|
||||
fn status( &self ) -> Status;
|
||||
fn draw(
|
||||
&mut self,
|
||||
frame: Vec<Point>,
|
||||
speed: u32,
|
||||
) -> LJResult<()> ;
|
||||
fn stop(&mut self) -> LJResult<()>;
|
||||
fn status(&self) -> Status;
|
||||
fn draw(
|
||||
&mut self,
|
||||
frame: Vec<Point>,
|
||||
speed: u32,
|
||||
) -> LJResult<()>;
|
||||
fn stop(&mut self) -> LJResult<()>;
|
||||
}
|
||||
|
||||
pub fn device_factory(config: &Conf) -> LJResult<Box<dyn Device>> {
|
||||
|
@ -11,13 +11,16 @@ use helios_dac::{
|
||||
// Point as HeliosPoint,
|
||||
};
|
||||
use crate::conf::HeliosConf;
|
||||
use crate::device::{Device, Status};
|
||||
use crate::device::{Device, Status, PlaybackState};
|
||||
use crate::errors::{LJError, LJResult};
|
||||
use crate::point::Point;
|
||||
|
||||
pub struct HeliosDevice {
|
||||
pub conf: HeliosConf,
|
||||
dac: NativeHeliosDac,
|
||||
sent_points: u16,
|
||||
state: PlaybackState,
|
||||
lack: String
|
||||
}
|
||||
|
||||
impl HeliosDevice {
|
||||
@ -29,16 +32,20 @@ impl HeliosDevice {
|
||||
return Err(Box::new(LJError::HeliosDeviceMissing));
|
||||
};
|
||||
let dac = device.open()?;
|
||||
Ok(Self { conf: (*conf).clone(), dac })
|
||||
Ok(Self { conf: (*conf).clone(), dac, sent_points: 0, state: PlaybackState::PREPARE, lack: "".to_string() })
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for HeliosDevice {
|
||||
fn status(&self) -> Status {
|
||||
|
||||
let lack = self.lack.clone();
|
||||
Status {
|
||||
active: true,
|
||||
last_traced_at: "now".to_string(),
|
||||
properties: vec!["foo".to_string()],
|
||||
playback_state: self.state,
|
||||
capacity: self.sent_points,
|
||||
lack,
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,12 +53,14 @@ impl Device for HeliosDevice {
|
||||
line: Vec<Point>,
|
||||
speed: u32,
|
||||
) -> LJResult<()> {
|
||||
while let Ok(DeviceStatus::NotReady) = self.dac.status() {
|
||||
}
|
||||
self.state = PlaybackState::IDLE;
|
||||
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 frame = Frame::new(speed, points);
|
||||
let frame = Frame::new(speed, points.clone());
|
||||
self.dac.write_frame(frame.clone())?;
|
||||
self.sent_points = points.len() as u16;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ fn run_all() -> LJResult<()> {
|
||||
info!("{:?}", config);
|
||||
|
||||
// Setup Redis Service
|
||||
let mut rs = RedisCtrl::new(&config.redis_url)?;
|
||||
let mut rs = RedisCtrl::new(&config.redis_url, &config.laser_id)?;
|
||||
|
||||
// Setup handler for interrupt Signals
|
||||
let running = Arc::new(AtomicBool::new(true));
|
||||
@ -65,6 +65,7 @@ fn run_all() -> LJResult<()> {
|
||||
|
||||
// Dispatch based on redis requests
|
||||
while running.load(Ordering::SeqCst) {
|
||||
rs.set_status( tracer.status())?;
|
||||
let order = rs.get_order(config.laser_id)?;
|
||||
if order != Order::Draw {
|
||||
info!("Order: {:?}", order);
|
||||
|
@ -1,76 +1,99 @@
|
||||
use redis::{Client, Commands, Connection};
|
||||
use ron::de::from_str;
|
||||
use crate::errors::{LJError,LJResult};
|
||||
use crate::device::Status;
|
||||
use crate::errors::{LJError, LJResult};
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Order {
|
||||
Draw = 0,
|
||||
Edh, //homography
|
||||
Black,
|
||||
Grid,
|
||||
Resampler,
|
||||
ClientKey,
|
||||
Intensity,
|
||||
Kpps,
|
||||
ColorBalance,
|
||||
Draw = 0,
|
||||
Edh,
|
||||
//homography
|
||||
Black,
|
||||
Grid,
|
||||
Resampler,
|
||||
ClientKey,
|
||||
Intensity,
|
||||
Kpps,
|
||||
ColorBalance,
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for Order {
|
||||
type Error = String;
|
||||
type Error = String;
|
||||
|
||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||
use Order::*;
|
||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||
use Order::*;
|
||||
|
||||
if value > 8 {
|
||||
return Err("order out of range".to_string());
|
||||
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,
|
||||
_ => 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 struct RedisCtrl {
|
||||
pub client: Client,
|
||||
pub connection: Connection,
|
||||
pub client: Client,
|
||||
pub connection: Connection,
|
||||
laser_id: u8,
|
||||
}
|
||||
|
||||
impl RedisCtrl {
|
||||
pub fn new(url: &str) -> LJResult<Self> {
|
||||
let client = Client::open(url)
|
||||
.map_err(LJError::RedisConnect)?;
|
||||
let connection = client.get_connection()
|
||||
.map_err(LJError::RedisConnect)?;
|
||||
Ok(RedisCtrl { client, connection })
|
||||
}
|
||||
pub fn new(url: &str, laser_id: &u8) -> LJResult<Self> {
|
||||
let client = Client::open(url)
|
||||
.map_err(LJError::RedisConnect)?;
|
||||
let connection = client.get_connection()
|
||||
.map_err(LJError::RedisConnect)?;
|
||||
Ok(RedisCtrl { client, connection, laser_id: *laser_id })
|
||||
}
|
||||
|
||||
pub fn get(&mut self, key: &str) -> LJResult<Line> {
|
||||
let val: String = self.connection.get(key)?;
|
||||
let line: Line = from_str(&val)?;
|
||||
Ok(line)
|
||||
}
|
||||
pub fn get(&mut self, key: &str) -> LJResult<Line> {
|
||||
let val: String = self.connection.get(key)?;
|
||||
let line: Line = from_str(&val)?;
|
||||
Ok(line)
|
||||
}
|
||||
|
||||
pub fn get_order(&mut self, id: u8) -> LJResult<Order> {
|
||||
let path = format!("/order/{id}");
|
||||
let val: u8 = self.connection.get(path.clone())?;
|
||||
pub fn set(&mut self, key: String, value: String) -> LJResult<()> {
|
||||
self.connection.set(key, value)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
if val == 1 || val >= 4 {
|
||||
self.connection.set(path, 0)?;
|
||||
}
|
||||
pub fn get_order(&mut self, id: u8) -> LJResult<Order> {
|
||||
let path = format!("/order/{id}");
|
||||
let val: u8 = self.connection.get(path.clone())?;
|
||||
|
||||
Ok(val.try_into()?)
|
||||
}
|
||||
if val == 1 || val >= 4 {
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user