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::integer_arithmetic,
|
||||
clippy::integer_division,
|
||||
// Expect prints a message when there is a critical error, so this is valid
|
||||
clippy::expect_used,
|
||||
clippy::unwrap_used,
|
||||
)]
|
||||
// See https://rust-lang.github.io/rust-clippy/master/index.html for more lints
|
||||
|
||||
mod color;
|
||||
mod errors;
|
||||
mod pattern;
|
||||
mod strip;
|
||||
mod ui;
|
||||
use errors::ProgramError;
|
||||
use std::sync::mpsc::channel;
|
||||
use std::thread;
|
||||
use strip::{LEDStrip, Message};
|
||||
use ui::console_ui_loop;
|
||||
|
||||
fn main() {
|
||||
fn main() -> Result<(), ProgramError> {
|
||||
let (tx, rx) = channel::<Message>();
|
||||
thread::spawn(move || {
|
||||
let handle = thread::spawn(move || -> Result<(), ProgramError> {
|
||||
let mut strip = LEDStrip::new(strip::Config {
|
||||
// I have 89 right now, but start off with 20
|
||||
num_lights: 20,
|
||||
@ -47,10 +48,14 @@ fn main() {
|
||||
// Scaling factor (scale 0..255)
|
||||
global_brightness_max: 20,
|
||||
tick_time_ms: strip::DEFAULT_TICK_TIME_MS,
|
||||
});
|
||||
})?;
|
||||
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::errors::ProgramError;
|
||||
use crate::pattern::{self, Pattern};
|
||||
use std::cmp;
|
||||
use std::ops::Add;
|
||||
@ -43,9 +44,10 @@ pub struct LEDStrip {
|
||||
}
|
||||
|
||||
impl LEDStrip {
|
||||
pub fn new(config: Config) -> Self {
|
||||
pub fn new(config: Config) -> Result<Self, ProgramError> {
|
||||
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 num_lights = config.num_lights;
|
||||
@ -55,10 +57,10 @@ impl LEDStrip {
|
||||
config,
|
||||
};
|
||||
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 data = vec![color::BLACK]
|
||||
.iter()
|
||||
@ -81,9 +83,8 @@ impl LEDStrip {
|
||||
})
|
||||
// TODO: Do not re-collect as u8s
|
||||
.collect::<Vec<(u8, u8, u8)>>();
|
||||
self.adapter
|
||||
.write_rgb(data.as_slice())
|
||||
.expect("TODO: Critical data write error!");
|
||||
self.adapter.write_rgb(data.as_slice())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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::errors::ProgramError;
|
||||
use crate::pattern::{self, Pattern};
|
||||
use crate::strip;
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -105,12 +107,14 @@ fn change_pattern(tx: &Sender<strip::Message>, pat: Box<dyn Pattern + Send>) ->
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
fn get_line(prompt: &str) -> String {
|
||||
fn get_line(prompt: &str) -> Result<String, ProgramError> {
|
||||
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();
|
||||
io::stdin()
|
||||
.read_line(&mut input_text)
|
||||
.expect("Could not read from stdin");
|
||||
input_text.trim().to_string()
|
||||
.map_err(|_| ProgramError::UiError(String::from("Could not read from stdin")))?;
|
||||
Ok(input_text.trim().to_string())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user