Skip to content

Commit bb11e1a

Browse files
committed
Improve error handling
1 parent 87b1823 commit bb11e1a

File tree

7 files changed

+88
-31
lines changed

7 files changed

+88
-31
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ name = "ebyte-e32-gui"
1313
path = "bin/gui.rs"
1414

1515
[dependencies]
16+
anyhow = "1.0.66"
1617
clap = { version = "3.1.14", features = ["derive"] }
1718
ebyte-e32 = { git = "https://github.com/barafael/ebyte-e32-rs", rev = "fee291a427df8e7c55e8dc154e181257ebb52a41", features = [
1819
"arg_enum",

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ m1_pin = 24
4040
* CLI: `cargo run --bin ebyte-e32-cli -- [OPTIONS] --address <ADDRESS> --channel <CHANNEL> {listen|send|read-model-data}`. For `send` mode, enter your messages in the prompt or pipe them in via `stdin`.
4141
* GUI: `cargo run` or `cargo run --bin ebyte-e32-gui`. For `send` mode, the input provided in the `Input` tab is sent (there, you can also open a file to read the input from).
4242

43+
## Persistence
44+
45+
With the `persistence` argument, the settings can be saved `temporary` or `permanent`.
46+
4347
## Screenshots
4448

4549
![image](https://user-images.githubusercontent.com/6966738/167198228-d15e67e7-de91-4b65-a96f-f3ecb1c98f81.png)

bin/cli.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
use clap::StructOpt;
2-
use ebyte_e32_ui::{interface::App, load_default_config, process};
2+
use ebyte_e32_ui::{cli::App, config::Config, load_config, process};
33

4-
fn main() {
5-
let config = load_default_config();
4+
fn main() -> anyhow::Result<()> {
5+
let config = load_config().map_err(|e| {
6+
eprintln!(
7+
"Here's an example:\n{}",
8+
toml::to_string(&Config::example()).unwrap()
9+
);
10+
e.context("Failed to load configuration")
11+
})?;
612
let args = App::parse();
7-
process(config, args);
13+
process(config, args).expect("Failed to run app");
14+
Ok(())
815
}

bin/gui.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
1-
use ebyte_e32_ui::{interface::App, load_default_config, process};
1+
use ebyte_e32_ui::{cli::App, config::Config, load_config, process};
22
use klask::Settings;
33

4-
fn main() {
5-
let config = load_default_config();
4+
fn main() -> anyhow::Result<()> {
5+
let config = load_config().map_err(|e| {
6+
eprintln!(
7+
"Here's an example:\n{}",
8+
toml::to_string(&Config::example()).unwrap()
9+
);
10+
e.context("Failed to load configuration")
11+
})?;
612
let settings = Settings {
713
enable_stdin: Some("Text to be sent, line by line".to_string()),
814
..Default::default()
915
};
10-
klask::run_derived::<App, _>(settings, |args| process(config, args));
16+
klask::run_derived::<App, _>(settings, |args| {
17+
process(config, args).expect("Failed to run app");
18+
});
19+
Ok(())
1120
}

src/interface.rs renamed to src/cli.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! A CLI interface with configuration data for running an Ebyte module.
2+
13
use clap::Parser;
24
use ebyte_e32::parameters::{
35
air_baudrate::AirBaudRate,
@@ -10,17 +12,24 @@ use ebyte_e32::parameters::{
1012
Persistence,
1113
};
1214

15+
/// Operational mode for Ebyte module driver.
1316
#[derive(clap::Subcommand, Clone, Debug, Eq, PartialEq)]
1417
pub enum Mode {
18+
/// Read Ebyte module data and print to stdout.
1519
ReadModelData,
20+
21+
/// Listen for incoming data on the Ebyte module.
1622
Listen,
23+
24+
/// Send data from stdin over the Ebyte module.
1725
Send,
1826
}
1927

28+
/// CLI interface definition.
2029
#[derive(Clone, Debug, PartialEq, Eq, Parser)]
2130
#[clap(author, version, about, long_about = None)]
2231
pub struct App {
23-
/// Listen for transmissions or send stdin?
32+
/// Application mode.
2433
#[clap(subcommand)]
2534
pub mode: Mode,
2635

src/config.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use serde_derive::{Deserialize, Serialize};
22
use std::path::PathBuf;
33

4+
/// Configuration for connecting to the Ebyte module.
45
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
56
pub struct Config {
67
pub(crate) serial_path: PathBuf,
@@ -14,6 +15,7 @@ pub struct Config {
1415
}
1516

1617
impl Config {
18+
/// Example configuration
1719
pub fn example() -> Self {
1820
Config {
1921
serial_path: "dev/ttyAMA0".into(),

src/lib.rs

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
use crate::{config::Config, interface::Mode};
1+
//! Ebyte module control.
2+
3+
use crate::{cli::Mode, config::Config};
4+
use anyhow::Context;
5+
use anyhow::Result;
6+
use cli::App;
27
use ebyte_e32::{parameters::Parameters, Ebyte};
38
use embedded_hal::blocking::delay::DelayMs;
49
use embedded_hal::digital::v2::InputPin;
510
use embedded_hal::digital::v2::OutputPin;
611
use embedded_hal::prelude::*;
712
use embedded_hal::serial;
8-
use interface::App;
913
use linux_embedded_hal::Delay;
1014
use nb::block;
1115
use rppal::{gpio::Gpio, uart::Uart};
@@ -14,37 +18,50 @@ use std::fmt::Debug;
1418
use std::fs::read_to_string;
1519
use std::io::{self, Write};
1620

21+
/// Configuration from `Config.toml`.
1722
pub mod config;
18-
pub mod interface;
1923

20-
pub fn load_default_config() -> Config {
21-
let config = read_to_string("Config.toml").unwrap_or_else(|e| {
22-
panic!(
23-
"Failed to open Config.toml [{e:?}]\nHere's an example: {:#?}",
24-
Config::example()
25-
)
26-
});
27-
toml::from_str(&config).expect("Failed to parse config")
24+
/// Command line interface.
25+
pub mod cli;
26+
27+
/// Load a configuration from `Config.toml`,
28+
/// returning an error if something goes wrong.
29+
pub fn load_config() -> Result<Config> {
30+
let config = read_to_string("Config.toml").context("Failed to open Config.toml")?;
31+
toml::from_str(&config).context("Failed to parse config")
2832
}
2933

30-
pub fn process(config: Config, args: App) {
34+
/// Setup the hardware, then load some parameters,
35+
/// update them if needed, then listen, send, or read model data.
36+
pub fn process(config: Config, args: App) -> anyhow::Result<()> {
3137
let serial = Uart::with_path(
3238
config.serial_path,
3339
config.baudrate,
3440
config.parity.into(),
3541
config.data_bits,
3642
config.stop_bits,
3743
)
38-
.expect("Failed to set up serial port");
44+
.context("Failed to set up serial port")?;
3945

40-
let gpio = Gpio::new().unwrap();
41-
let aux = gpio.get(config.aux_pin).unwrap().into_input();
42-
let m0 = gpio.get(config.m0_pin).unwrap().into_output();
43-
let m1 = gpio.get(config.m1_pin).unwrap().into_output();
46+
let gpio = Gpio::new().context("Failed to open Gpio")?;
47+
let aux = gpio
48+
.get(config.aux_pin)
49+
.context("Failed to open AUX pin")?
50+
.into_input();
51+
let m0 = gpio
52+
.get(config.m0_pin)
53+
.context("Failed to open m0 pin")?
54+
.into_output();
55+
let m1 = gpio
56+
.get(config.m1_pin)
57+
.context("Failed to open m1 pin")?
58+
.into_output();
4459

4560
let mut ebyte = Ebyte::new(serial, aux, m0, m1, Delay).unwrap();
4661

47-
let old_params = ebyte.parameters().unwrap();
62+
let old_params = ebyte
63+
.parameters()
64+
.expect("Failed to read current parameters");
4865
println!("Loaded parameters: {old_params:#?}");
4966

5067
let new_params = Parameters::from(&args);
@@ -53,8 +70,12 @@ pub fn process(config: Config, args: App) {
5370
println!("Leaving parameters unchanged");
5471
} else {
5572
println!("Updating parameters (persistence: {:?})", args.persistence);
56-
ebyte.set_parameters(&new_params, args.persistence).unwrap();
57-
let current_params = ebyte.parameters().unwrap();
73+
ebyte
74+
.set_parameters(&new_params, args.persistence)
75+
.expect("Failed to set new parameters");
76+
let current_params = ebyte
77+
.parameters()
78+
.expect("Failed to read current parameters");
5879
if current_params != new_params {
5980
eprintln!("Error: parameters unchanged: {current_params:#?}");
6081
}
@@ -64,8 +85,9 @@ pub fn process(config: Config, args: App) {
6485
Mode::Send => send(ebyte),
6586
Mode::ReadModelData => {
6687
println!("Reading model data");
67-
let model_data = ebyte.model_data().unwrap();
88+
let model_data = ebyte.model_data().expect("Failed to read model data");
6889
println!("{model_data:#?}");
90+
Ok(())
6991
}
7092
Mode::Listen => loop {
7193
let b = block!(ebyte.read()).unwrap();
@@ -75,7 +97,9 @@ pub fn process(config: Config, args: App) {
7597
}
7698
}
7799

78-
fn send<S, Aux, M0, M1, D>(mut ebyte: Ebyte<S, Aux, M0, M1, D, ebyte_e32::mode::Normal>)
100+
fn send<S, Aux, M0, M1, D>(
101+
mut ebyte: Ebyte<S, Aux, M0, M1, D, ebyte_e32::mode::Normal>,
102+
) -> anyhow::Result<()>
79103
where
80104
S: serial::Read<u8> + serial::Write<u8>,
81105
<S as serial::Write<u8>>::Error: Debug,
@@ -115,4 +139,5 @@ where
115139
}
116140
}
117141
}
142+
Ok(())
118143
}

0 commit comments

Comments
 (0)