Start work on errors
This commit is contained in:
parent
2859a23b1e
commit
409f1d65a5
37
src/errors.rs
Normal file
37
src/errors.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
use core::any::Any;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ProgramError {
|
||||||
|
General(String),
|
||||||
|
UiError(String),
|
||||||
|
Boxed(Box<dyn Any + Send>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for ProgramError {
|
||||||
|
fn from(e: String) -> Self {
|
||||||
|
Self::General(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for ProgramError {
|
||||||
|
fn from(e: &str) -> Self {
|
||||||
|
Self::General(e.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Box<dyn Any + Send>> for ProgramError {
|
||||||
|
fn from(e: Box<dyn Any + Send>) -> Self {
|
||||||
|
Self::Boxed(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ProgramError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||||
|
match self {
|
||||||
|
Self::General(s) => write!(f, "{}", s),
|
||||||
|
Self::UiError(s) => write!(f, "Critial UI error: {}", s),
|
||||||
|
Self::Boxed(s) => write!(f, "{:?}", s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
src/main.rs
17
src/main.rs
@ -21,24 +21,25 @@
|
|||||||
clippy::indexing_slicing,
|
clippy::indexing_slicing,
|
||||||
clippy::integer_arithmetic,
|
clippy::integer_arithmetic,
|
||||||
clippy::integer_division,
|
clippy::integer_division,
|
||||||
// Expect prints a message when there is a critical error, so this is valid
|
|
||||||
clippy::expect_used,
|
clippy::expect_used,
|
||||||
clippy::unwrap_used,
|
clippy::unwrap_used,
|
||||||
)]
|
)]
|
||||||
// See https://rust-lang.github.io/rust-clippy/master/index.html for more lints
|
// See https://rust-lang.github.io/rust-clippy/master/index.html for more lints
|
||||||
|
|
||||||
mod color;
|
mod color;
|
||||||
|
mod errors;
|
||||||
mod pattern;
|
mod pattern;
|
||||||
mod strip;
|
mod strip;
|
||||||
mod ui;
|
mod ui;
|
||||||
|
use errors::ProgramError;
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use strip::{LEDStrip, Message};
|
use strip::{LEDStrip, Message};
|
||||||
use ui::console_ui_loop;
|
use ui::console_ui_loop;
|
||||||
|
|
||||||
fn main() {
|
fn main() -> Result<(), ProgramError> {
|
||||||
let (tx, rx) = channel::<Message>();
|
let (tx, rx) = channel::<Message>();
|
||||||
thread::spawn(move || {
|
let handle = thread::spawn(move || -> Result<(), ProgramError> {
|
||||||
let mut strip = LEDStrip::new(strip::Config {
|
let mut strip = LEDStrip::new(strip::Config {
|
||||||
// I have 89 right now, but start off with 20
|
// I have 89 right now, but start off with 20
|
||||||
num_lights: 20,
|
num_lights: 20,
|
||||||
@ -47,10 +48,14 @@ fn main() {
|
|||||||
// Scaling factor (scale 0..255)
|
// Scaling factor (scale 0..255)
|
||||||
global_brightness_max: 20,
|
global_brightness_max: 20,
|
||||||
tick_time_ms: strip::DEFAULT_TICK_TIME_MS,
|
tick_time_ms: strip::DEFAULT_TICK_TIME_MS,
|
||||||
});
|
})?;
|
||||||
strip.strip_loop(&rx);
|
strip.strip_loop(&rx);
|
||||||
panic!("Dead strip thread. Terminating");
|
Err(ProgramError::General(String::from(
|
||||||
|
"Dead strip thread. Terminating",
|
||||||
|
)))
|
||||||
});
|
});
|
||||||
|
|
||||||
console_ui_loop(&tx);
|
console_ui_loop(&tx)?;
|
||||||
|
|
||||||
|
handle.join()?
|
||||||
}
|
}
|
||||||
|
15
src/strip.rs
15
src/strip.rs
@ -1,4 +1,5 @@
|
|||||||
use crate::color;
|
use crate::color;
|
||||||
|
use crate::errors::ProgramError;
|
||||||
use crate::pattern::{self, Pattern};
|
use crate::pattern::{self, Pattern};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
@ -43,9 +44,10 @@ pub struct LEDStrip {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LEDStrip {
|
impl LEDStrip {
|
||||||
pub fn new(config: Config) -> Self {
|
pub fn new(config: Config) -> Result<Self, ProgramError> {
|
||||||
let adapter = Box::new(
|
let adapter = Box::new(
|
||||||
Ws28xxSpiAdapter::new("/dev/spidev0.0").expect("Cannot locate device /dev/spidev0.0!"),
|
Ws28xxSpiAdapter::new("/dev/spidev0.0")
|
||||||
|
.map_err(|_| "Cannot start device /dev/spidev0.0!")?,
|
||||||
);
|
);
|
||||||
let pattern = Box::new(pattern::Solid::new(color::BLACK));
|
let pattern = Box::new(pattern::Solid::new(color::BLACK));
|
||||||
let num_lights = config.num_lights;
|
let num_lights = config.num_lights;
|
||||||
@ -55,10 +57,10 @@ impl LEDStrip {
|
|||||||
config,
|
config,
|
||||||
};
|
};
|
||||||
ret.set_num_lights(num_lights);
|
ret.set_num_lights(num_lights);
|
||||||
ret
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_buf_from_pattern(&mut self) {
|
fn write_buf_from_pattern(&mut self) -> Result<(), ProgramError> {
|
||||||
let global_brightness_max = self.config.global_brightness_max;
|
let global_brightness_max = self.config.global_brightness_max;
|
||||||
let data = vec![color::BLACK]
|
let data = vec![color::BLACK]
|
||||||
.iter()
|
.iter()
|
||||||
@ -81,9 +83,8 @@ impl LEDStrip {
|
|||||||
})
|
})
|
||||||
// TODO: Do not re-collect as u8s
|
// TODO: Do not re-collect as u8s
|
||||||
.collect::<Vec<(u8, u8, u8)>>();
|
.collect::<Vec<(u8, u8, u8)>>();
|
||||||
self.adapter
|
self.adapter.write_rgb(data.as_slice())?;
|
||||||
.write_rgb(data.as_slice())
|
Ok(())
|
||||||
.expect("TODO: Critical data write error!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_num_lights(&mut self, num_lights: u16) {
|
fn set_num_lights(&mut self, num_lights: u16) {
|
||||||
|
16
src/ui.rs
16
src/ui.rs
@ -1,13 +1,15 @@
|
|||||||
use crate::color::Rgb;
|
use crate::color::Rgb;
|
||||||
|
use crate::errors::ProgramError;
|
||||||
use crate::pattern::{self, Pattern};
|
use crate::pattern::{self, Pattern};
|
||||||
use crate::strip;
|
use crate::strip;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::sync::mpsc::Sender;
|
use std::sync::mpsc::Sender;
|
||||||
|
|
||||||
pub fn console_ui_loop(tx: &Sender<strip::Message>) {
|
pub fn console_ui_loop(tx: &Sender<strip::Message>) -> Result<(), ProgramError> {
|
||||||
loop {
|
loop {
|
||||||
if let Err(msg) = parse_cmd(tx, &get_line("Command (cfqs)")) {
|
let line = get_line("Command (cfqs)")?;
|
||||||
|
if let Err(msg) = parse_cmd(tx, &line) {
|
||||||
println!("Command error: {}", msg);
|
println!("Command error: {}", msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,12 +107,14 @@ fn change_pattern(tx: &Sender<strip::Message>, pat: Box<dyn Pattern + Send>) ->
|
|||||||
.map_err(|e| e.to_string())
|
.map_err(|e| e.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_line(prompt: &str) -> String {
|
fn get_line(prompt: &str) -> Result<String, ProgramError> {
|
||||||
print!("{}: ", prompt);
|
print!("{}: ", prompt);
|
||||||
std::io::stdout().flush().expect("Could not flush stdout");
|
std::io::stdout()
|
||||||
|
.flush()
|
||||||
|
.map_err(|_| ProgramError::UiError(String::from("Could not flush stdout")))?;
|
||||||
let mut input_text = String::new();
|
let mut input_text = String::new();
|
||||||
io::stdin()
|
io::stdin()
|
||||||
.read_line(&mut input_text)
|
.read_line(&mut input_text)
|
||||||
.expect("Could not read from stdin");
|
.map_err(|_| ProgramError::UiError(String::from("Could not read from stdin")))?;
|
||||||
input_text.trim().to_string()
|
Ok(input_text.trim().to_string())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user