Skip to content

Commit

Permalink
Improve error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
barafael committed Oct 30, 2022
1 parent 87b1823 commit bb11e1a
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 31 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ name = "ebyte-e32-gui"
path = "bin/gui.rs"

[dependencies]
anyhow = "1.0.66"
clap = { version = "3.1.14", features = ["derive"] }
ebyte-e32 = { git = "https://github.com/barafael/ebyte-e32-rs", rev = "fee291a427df8e7c55e8dc154e181257ebb52a41", features = [
"arg_enum",
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ m1_pin = 24
* 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`.
* 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).

## Persistence

With the `persistence` argument, the settings can be saved `temporary` or `permanent`.

## Screenshots

![image](https://user-images.githubusercontent.com/6966738/167198228-d15e67e7-de91-4b65-a96f-f3ecb1c98f81.png)
Expand Down
15 changes: 11 additions & 4 deletions bin/cli.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
use clap::StructOpt;
use ebyte_e32_ui::{interface::App, load_default_config, process};
use ebyte_e32_ui::{cli::App, config::Config, load_config, process};

fn main() {
let config = load_default_config();
fn main() -> anyhow::Result<()> {
let config = load_config().map_err(|e| {
eprintln!(
"Here's an example:\n{}",
toml::to_string(&Config::example()).unwrap()
);
e.context("Failed to load configuration")
})?;
let args = App::parse();
process(config, args);
process(config, args).expect("Failed to run app");
Ok(())
}
17 changes: 13 additions & 4 deletions bin/gui.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
use ebyte_e32_ui::{interface::App, load_default_config, process};
use ebyte_e32_ui::{cli::App, config::Config, load_config, process};
use klask::Settings;

fn main() {
let config = load_default_config();
fn main() -> anyhow::Result<()> {
let config = load_config().map_err(|e| {
eprintln!(
"Here's an example:\n{}",
toml::to_string(&Config::example()).unwrap()
);
e.context("Failed to load configuration")
})?;
let settings = Settings {
enable_stdin: Some("Text to be sent, line by line".to_string()),
..Default::default()
};
klask::run_derived::<App, _>(settings, |args| process(config, args));
klask::run_derived::<App, _>(settings, |args| {
process(config, args).expect("Failed to run app");
});
Ok(())
}
11 changes: 10 additions & 1 deletion src/interface.rs → src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! A CLI interface with configuration data for running an Ebyte module.
use clap::Parser;
use ebyte_e32::parameters::{
air_baudrate::AirBaudRate,
Expand All @@ -10,17 +12,24 @@ use ebyte_e32::parameters::{
Persistence,
};

/// Operational mode for Ebyte module driver.
#[derive(clap::Subcommand, Clone, Debug, Eq, PartialEq)]
pub enum Mode {
/// Read Ebyte module data and print to stdout.
ReadModelData,

/// Listen for incoming data on the Ebyte module.
Listen,

/// Send data from stdin over the Ebyte module.
Send,
}

/// CLI interface definition.
#[derive(Clone, Debug, PartialEq, Eq, Parser)]
#[clap(author, version, about, long_about = None)]
pub struct App {
/// Listen for transmissions or send stdin?
/// Application mode.
#[clap(subcommand)]
pub mode: Mode,

Expand Down
2 changes: 2 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use serde_derive::{Deserialize, Serialize};
use std::path::PathBuf;

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

impl Config {
/// Example configuration
pub fn example() -> Self {
Config {
serial_path: "dev/ttyAMA0".into(),
Expand Down
69 changes: 47 additions & 22 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
use crate::{config::Config, interface::Mode};
//! Ebyte module control.
use crate::{cli::Mode, config::Config};
use anyhow::Context;
use anyhow::Result;
use cli::App;
use ebyte_e32::{parameters::Parameters, Ebyte};
use embedded_hal::blocking::delay::DelayMs;
use embedded_hal::digital::v2::InputPin;
use embedded_hal::digital::v2::OutputPin;
use embedded_hal::prelude::*;
use embedded_hal::serial;
use interface::App;
use linux_embedded_hal::Delay;
use nb::block;
use rppal::{gpio::Gpio, uart::Uart};
Expand All @@ -14,37 +18,50 @@ use std::fmt::Debug;
use std::fs::read_to_string;
use std::io::{self, Write};

/// Configuration from `Config.toml`.
pub mod config;
pub mod interface;

pub fn load_default_config() -> Config {
let config = read_to_string("Config.toml").unwrap_or_else(|e| {
panic!(
"Failed to open Config.toml [{e:?}]\nHere's an example: {:#?}",
Config::example()
)
});
toml::from_str(&config).expect("Failed to parse config")
/// Command line interface.
pub mod cli;

/// Load a configuration from `Config.toml`,
/// returning an error if something goes wrong.
pub fn load_config() -> Result<Config> {
let config = read_to_string("Config.toml").context("Failed to open Config.toml")?;
toml::from_str(&config).context("Failed to parse config")
}

pub fn process(config: Config, args: App) {
/// Setup the hardware, then load some parameters,
/// update them if needed, then listen, send, or read model data.
pub fn process(config: Config, args: App) -> anyhow::Result<()> {
let serial = Uart::with_path(
config.serial_path,
config.baudrate,
config.parity.into(),
config.data_bits,
config.stop_bits,
)
.expect("Failed to set up serial port");
.context("Failed to set up serial port")?;

let gpio = Gpio::new().unwrap();
let aux = gpio.get(config.aux_pin).unwrap().into_input();
let m0 = gpio.get(config.m0_pin).unwrap().into_output();
let m1 = gpio.get(config.m1_pin).unwrap().into_output();
let gpio = Gpio::new().context("Failed to open Gpio")?;
let aux = gpio
.get(config.aux_pin)
.context("Failed to open AUX pin")?
.into_input();
let m0 = gpio
.get(config.m0_pin)
.context("Failed to open m0 pin")?
.into_output();
let m1 = gpio
.get(config.m1_pin)
.context("Failed to open m1 pin")?
.into_output();

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

let old_params = ebyte.parameters().unwrap();
let old_params = ebyte
.parameters()
.expect("Failed to read current parameters");
println!("Loaded parameters: {old_params:#?}");

let new_params = Parameters::from(&args);
Expand All @@ -53,8 +70,12 @@ pub fn process(config: Config, args: App) {
println!("Leaving parameters unchanged");
} else {
println!("Updating parameters (persistence: {:?})", args.persistence);
ebyte.set_parameters(&new_params, args.persistence).unwrap();
let current_params = ebyte.parameters().unwrap();
ebyte
.set_parameters(&new_params, args.persistence)
.expect("Failed to set new parameters");
let current_params = ebyte
.parameters()
.expect("Failed to read current parameters");
if current_params != new_params {
eprintln!("Error: parameters unchanged: {current_params:#?}");
}
Expand All @@ -64,8 +85,9 @@ pub fn process(config: Config, args: App) {
Mode::Send => send(ebyte),
Mode::ReadModelData => {
println!("Reading model data");
let model_data = ebyte.model_data().unwrap();
let model_data = ebyte.model_data().expect("Failed to read model data");
println!("{model_data:#?}");
Ok(())
}
Mode::Listen => loop {
let b = block!(ebyte.read()).unwrap();
Expand All @@ -75,7 +97,9 @@ pub fn process(config: Config, args: App) {
}
}

fn send<S, Aux, M0, M1, D>(mut ebyte: Ebyte<S, Aux, M0, M1, D, ebyte_e32::mode::Normal>)
fn send<S, Aux, M0, M1, D>(
mut ebyte: Ebyte<S, Aux, M0, M1, D, ebyte_e32::mode::Normal>,
) -> anyhow::Result<()>
where
S: serial::Read<u8> + serial::Write<u8>,
<S as serial::Write<u8>>::Error: Debug,
Expand Down Expand Up @@ -115,4 +139,5 @@ where
}
}
}
Ok(())
}

0 comments on commit bb11e1a

Please sign in to comment.