Buildable again

This commit is contained in:
hodasemi 2022-07-15 19:08:22 +02:00
parent efbad0d676
commit 5b8ffc8dd9
7 changed files with 73 additions and 93 deletions

7
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,7 @@
{
"workbench.colorCustomizations": {
"activityBar.background": "#0E3502",
"titleBar.activeBackground": "#144B03",
"titleBar.activeForeground": "#F1FEED"
}
}

View file

@ -17,4 +17,6 @@ path = "src/gui.rs"
[dependencies]
serialport = "*"
gtk = { version = "*", features = ["v3_24"] }
utilities = { git = "http://dimov.cloud:80/hodasemi/Context.git" }
anyhow = "1.0"
serde = { version = "*", features = ["derive"] }
serde_json = "*"

View file

@ -2,7 +2,7 @@ use gtk;
use gtk::prelude::*;
use gtk::{Builder, Window};
use utilities::prelude::*;
use anyhow::{anyhow, Result};
use std::fs;
use std::path::Path;
@ -11,10 +11,10 @@ mod shared;
use shared::config::{Config, COMMAND_COUNT};
fn main() -> VerboseResult<()> {
gtk::init().map_err(|_| "failed to initialize GTK")?;
fn main() -> Result<()> {
gtk::init()?;
let builder = Builder::new_from_string(include_str!("../macro_ui.glade"));
let builder = Builder::from_string(include_str!("../macro_ui.glade"));
setup_gui(builder)?;
@ -23,15 +23,15 @@ fn main() -> VerboseResult<()> {
Ok(())
}
fn setup_gui(builder: Builder) -> VerboseResult<()> {
fn setup_gui(builder: Builder) -> Result<()> {
let config = load_config()?;
apply_config(&builder, &config)?;
setup_save(&builder)?;
let window: Window = builder
.get_object("MainWindow")
.ok_or("failed getting main window")?;
.object("MainWindow")
.ok_or(anyhow!("failed getting main window"))?;
window.show_all();
@ -44,8 +44,8 @@ fn setup_gui(builder: Builder) -> VerboseResult<()> {
Ok(())
}
fn load_config() -> VerboseResult<Config> {
let home_dir = std::env::var("HOME").map_err(|_| "failed getting home directory")?;
fn load_config() -> Result<Config> {
let home_dir = std::env::var("HOME")?;
if !Path::new(&format!("{}/.config", home_dir)).exists() {
fs::create_dir(format!("{}/.config", home_dir))?;
@ -58,26 +58,26 @@ fn load_config() -> VerboseResult<Config> {
Config::open(&format!("{}/.config/MacroBoard/commands.cfg", home_dir))
}
fn setup_save(builder: &Builder) -> VerboseResult<()> {
fn setup_save(builder: &Builder) -> Result<()> {
let mut text_fields = Vec::with_capacity(COMMAND_COUNT);
for i in 0..COMMAND_COUNT {
let command_text_field: gtk::Entry = builder
.get_object(&format!("ButtonCommand{}", i + 1))
.ok_or(format!("Failed getting Entry for command {}", i + 1))?;
.object(&format!("ButtonCommand{}", i + 1))
.ok_or(anyhow!("Failed getting Entry for command {}", i + 1))?;
text_fields.push(command_text_field);
}
let save_button: gtk::Button = builder
.get_object("SaveButton")
.ok_or("Failed getting save button")?;
.object("SaveButton")
.ok_or(anyhow!("Failed getting save button"))?;
save_button.connect_clicked(move |_| {
let mut config = Config::default();
for i in 0..COMMAND_COUNT {
let command = text_fields[i].get_buffer().get_text();
let command = text_fields[i].buffer().text();
config.commands[i] = Some(command);
}
@ -98,14 +98,14 @@ fn setup_save(builder: &Builder) -> VerboseResult<()> {
Ok(())
}
fn apply_config(builder: &Builder, config: &Config) -> VerboseResult<()> {
fn apply_config(builder: &Builder, config: &Config) -> Result<()> {
for i in 0..COMMAND_COUNT {
if let Some(command) = &config.commands[i] {
let command_text_field: gtk::Entry = builder
.get_object(&format!("ButtonCommand{}", i + 1))
.ok_or(format!("Failed getting Entry for command {}", i + 1))?;
.object(&format!("ButtonCommand{}", i + 1))
.ok_or(anyhow!("Failed getting Entry for command {}", i + 1))?;
command_text_field.get_buffer().set_text(command);
command_text_field.buffer().set_text(command);
}
}

View file

@ -1,9 +1,9 @@
mod service_specific;
use anyhow::Result;
use service_specific::*;
use utilities::prelude::*;
fn main() -> VerboseResult<()> {
fn main() -> Result<()> {
let mut port = Port::open(SerialPortSettings {
baud_rate: 9600,
data_bits: DataBits::Eight,

View file

@ -24,7 +24,7 @@ impl MessageBuilder {
if !self.complete {
match msg.chars().position(|c| c == MESSAGE_END) {
Some(position) => {
let mut remaining_msg = msg.split_off(position);
let remaining_msg = msg.split_off(position);
self.message.push_str(&msg);
self.complete = true;

View file

@ -1,11 +1,8 @@
use serialport;
use serialport::prelude::*;
use utilities::prelude::*;
use anyhow::{anyhow, Result};
use std::io;
pub use serialport::{DataBits, FlowControl, Parity, SerialPortSettings, StopBits};
pub use serialport::{DataBits, FlowControl, Parity, SerialPort, StopBits};
pub use std::time::Duration;
pub enum SerialReadResult {
@ -13,60 +10,68 @@ pub enum SerialReadResult {
Timeout,
}
pub struct SerialPortSettings {
pub baud_rate: u32,
pub data_bits: DataBits,
pub parity: Parity,
pub stop_bits: StopBits,
pub flow_control: FlowControl,
pub timeout: Duration,
}
pub struct Port {
serial_port: Box<dyn SerialPort>,
}
impl Port {
pub fn open(settings: SerialPortSettings) -> VerboseResult<Self> {
pub fn open(settings: SerialPortSettings) -> Result<Self> {
let port_path = Self::find_macroboard()?;
let port = serialport::open_with_settings(&port_path, &settings).map_err(|err| {
format!(
"could not open serial port ({:?}, {}, {})",
err.kind(),
err,
port_path
)
})?;
let port = serialport::new(port_path, settings.baud_rate)
.data_bits(settings.data_bits)
.parity(settings.parity)
.stop_bits(settings.stop_bits)
.flow_control(settings.flow_control)
.timeout(settings.timeout)
.open()?;
Ok(Port { serial_port: port })
}
#[allow(unused)]
pub fn read(&mut self) -> VerboseResult<SerialReadResult> {
pub fn read(&mut self) -> Result<SerialReadResult> {
let mut buf: Vec<u8> = (0..255).collect();
match self.serial_port.read(&mut buf[..]) {
Ok(t) => Ok(SerialReadResult::Message(
String::from_utf8(buf[0..t].to_vec())
.map_err(|err| format!("failed converting utf8 buffer ({})", err))?,
.map_err(|err| anyhow!("failed converting utf8 buffer ({})", err))?,
)),
Err(ref e) if e.kind() == io::ErrorKind::TimedOut => Ok(SerialReadResult::Timeout),
Err(err) => create_error!(format!("failed reading serial port ({})", err)),
Err(err) => Err(anyhow!("failed reading serial port ({})", err)),
}
}
#[allow(unused)]
pub fn write(&mut self, msg: &str) -> VerboseResult<()> {
pub fn write(&mut self, msg: &str) -> Result<()> {
self.serial_port
.write(msg.as_bytes())
.map_err(|err| format!("failed writing to serial port ({})", err))?;
.map_err(|err| anyhow!("failed writing to serial port ({})", err))?;
Ok(())
}
fn find_macroboard() -> VerboseResult<String> {
fn find_macroboard() -> Result<String> {
let available_ports = serialport::available_ports()
.map_err(|err| format!("error querying serial ports ( {})", err))?;
.map_err(|err| anyhow!("error querying serial ports ( {})", err))?;
for available_port in available_ports.iter() {
if let serialport::SerialPortType::UsbPort(usb_info) = &available_port.port_type {
// check for the correct device
if let Some(product_name) = &usb_info.product {
if product_name == "FT232R_USB_UART"
&& usb_info.vid == 1027
&& usb_info.pid == 24577
&& usb_info.vid == 0x0403
&& usb_info.pid == 0x6001
{
return Ok(available_port.port_name.clone());
}
@ -74,6 +79,6 @@ impl Port {
}
}
create_error!("macro board not found on usb bus")
return Err(anyhow!("macro board not found on usb bus".to_string()));
}
}

View file

@ -1,61 +1,27 @@
use utilities::prelude::*;
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::{fs::File, io::Write};
pub const COMMAND_COUNT: usize = 8;
const COMMANDS_TAG: &str = "Commands";
const COMMANDS: [&str; COMMAND_COUNT] = [
"command_1",
"command_2",
"command_3",
"command_4",
"command_5",
"command_6",
"command_7",
"command_8",
];
#[derive(Debug, Serialize, Deserialize)]
pub struct Config {
pub commands: [Option<String>; COMMAND_COUNT],
}
impl Config {
pub fn open(path: &str) -> VerboseResult<Config> {
let mut config = Config::default();
let config_loader = match ConfigHandler::read_config(path) {
Ok(config_loader) => config_loader,
Err(_) => return Ok(config),
};
if let Some(commands) = config_loader.get(COMMANDS_TAG) {
for i in 0..COMMAND_COUNT {
if let Some(command) = commands.get(COMMANDS[i]) {
config.commands[i] = Some(command.to_value()?);
}
}
}
Ok(config)
pub fn open(path: &str) -> Result<Config> {
Ok(serde_json::from_str(&std::fs::read_to_string(path)?)?)
}
pub fn save(&self, path: &str) -> VerboseResult<()> {
let fields = (0..COMMAND_COUNT)
.collect::<Vec<usize>>()
.iter()
.map(|i| {
(
COMMANDS[*i],
match &self.commands[*i] {
Some(command) => Value::from_value(command),
None => Value::empty(),
},
)
})
.collect();
pub fn save(&self, path: &str) -> Result<()> {
let mut file = File::create(path)?;
let s = serde_json::to_string(self)?;
let data = &[(COMMANDS_TAG, fields)];
write!(file, "{}", s)?;
ConfigHandler::write_config(path, data)
Ok(())
}
}