Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better error handling #26

Merged
merged 7 commits into from
Dec 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</head>

<body>
<div id="root"></div>
<div id="root">Loading...</div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"lint": "eslint src",
"lint:fix": "eslint src --fix",
"tauri:dev": "tauri dev",
"tauri:build": "tauri build"
"tauri:build": "tauri build",
"tauri:test": "cd src-tauri && cargo test && cd .."
},
"dependencies": {
"@radix-ui/react-checkbox": "^1.0.3",
Expand All @@ -27,7 +28,7 @@
"react-dom": "^18.2.0",
"tailwind-merge": "^1.12.0",
"tailwindcss-animate": "^1.0.5",
"tauri-plugin-autostart-api": "https://github.com/tauri-apps/tauri-plugin-autostart",
"tauri-plugin-autostart-api": "https://github.com/tauri-apps/tauri-plugin-autostart#v1",
"use-simple-async": "^1.4.2"
},
"devDependencies": {
Expand Down
40 changes: 20 additions & 20 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "Trayasen"
name = "trayasen"
version = "0.0.6"
description = "An app to control IKEA Idasen desk"
authors = ["Szymon Wiszczuk<[email protected]>"]
Expand All @@ -22,7 +22,7 @@ btleplug = "0.11.0"
tokio = { version = "1.24.1", features = ["full"] }
thiserror = "1.0.30"
uuid = "1.3.0"
tauri-plugin-autostart = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
tauri-plugin-autostart = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }

[features]
# by default Tauri runs in production mode
Expand Down
21 changes: 20 additions & 1 deletion src-tauri/src/config_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ pub fn update_config(updated_config: &ConfigData) {

let stringified_new_config = to_string::<ConfigData>(&updated_config).unwrap();
fs::write(config_path, stringified_new_config)
.expect("Saving a config after updatign a config");
.expect("Saving a config after updating a config");
}

#[tauri::command]
Expand All @@ -155,6 +155,25 @@ pub fn remove_config() {
let _ = remove_file(config_path);
}

#[tauri::command]
pub fn reset_desk() {
let config_path = get_config_path().trim_end().to_string();

let config =
read_to_string(&config_path).expect("err while reading config while resetting desk");
// Config exists
let config = from_str::<ConfigData>(config.as_str()).expect("Error while parsing config file");

let updated_config = ConfigData {
local_name: None,
saved_positions: config.saved_positions,
};

let stringified_new_config = to_string::<ConfigData>(&updated_config).unwrap();
fs::write(config_path, stringified_new_config)
.expect("Saving a config after updating a config");
}

pub struct MenuConfigItem {
pub position_elem: CustomMenuItem,
pub name: String,
Expand Down
22 changes: 22 additions & 0 deletions src-tauri/src/desk_mutex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Set of utils to interact with desk mutex, since it's pretty complex

use btleplug::platform::Peripheral as PlatformPeripheral;
use tauri::Manager;

use crate::TauriSharedDesk;

pub fn get_desk_from_app_state(app_handle: &tauri::AppHandle) -> PlatformPeripheral {
let desk = app_handle.state::<TauriSharedDesk>();
let desk = desk.0.lock().expect("Error while unwrapping shared desk");
let desk = desk
.as_ref()
.expect("Desk should have been defined at this point");
desk.clone()
}

pub fn assign_desk_to_mutex(desk_mutex: &TauriSharedDesk, new_desk: Option<PlatformPeripheral>) {
*desk_mutex
.0
.lock()
.expect("Failed to deref mutex during instantiation") = new_desk;
}
108 changes: 69 additions & 39 deletions src-tauri/src/loose_idasen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use btleplug::{
use serde::Serialize;
use uuid::Uuid;

use crate::config_utils;
use crate::{config_utils, TauriSharedDesk};

/*
This file contains loose utils to interact with a desk bluetooth peripheral as if it's a desk.
Expand Down Expand Up @@ -86,8 +86,8 @@ pub async fn setup_bt_desk_device(
) -> Result<ConnectedBtDevice<impl ApiPeripheral>, BtError> {
let mac_addr = BDAddr::default();
println!("got the mac! desk: {:?}", &device);
device.connect().await.unwrap();
device.discover_services().await.unwrap();
device.connect().await?;
device.discover_services().await?;

let control_characteristic = get_control_characteristic(device).await;
let position_characteristic = get_position_characteristic(device).await;
Expand Down Expand Up @@ -122,26 +122,21 @@ async fn get_list_of_desks_once(
}
}

pub async fn get_list_of_desks(loc_name: &Option<String>) -> Vec<ExpandedPeripheral> {
let mut desks = get_list_of_desks_once(loc_name).await;
let mut success = false;
let mut tries = 0;
pub async fn get_list_of_desks(
loc_name: &Option<String>,
) -> Result<Vec<ExpandedPeripheral>, BtError> {
// try 3 times before erroring
while tries < 2 {
let mut desks;
for _loop_iter in 0..3 {
desks = get_list_of_desks_once(loc_name).await;
let ok = desks.is_ok();

if ok {
success = true;
break;
if desks.is_ok() {
return desks;
// break;
}

tries += 1;
}
if success == false {
panic!("Error while getting a list of desks");
}
desks.unwrap()

Err(BtError::CannotFindDevice)
}

// Getting characteristics every time is wasteful
Expand Down Expand Up @@ -317,30 +312,40 @@ pub struct PotentialDesk {
// https://github.com/tauri-apps/tauri/issues/2533 - this has to be a Result
/// Desk we're connecting to for UI info
#[tauri::command]
pub async fn get_desk_to_connect() -> Result<Vec<PotentialDesk>, ()> {
pub async fn get_desk_to_connect() -> Result<Vec<PotentialDesk>, String> {
let config = config_utils::get_or_create_config();
let desk_list = get_list_of_desks(&config.local_name).await;
let desk_list_view = desk_list
.iter()
.map(|x| match config.local_name {
Some(_) => PotentialDesk {
name: x.name.to_string(),
status: SavedDeskStates::Saved.as_str().to_string(),
},
None => PotentialDesk {
name: x.name.to_string(),
status: SavedDeskStates::New.as_str().to_string(),
},
})
.collect::<Vec<PotentialDesk>>();

println!("Found desk list: {:?}", &desk_list_view);

Ok(desk_list_view)

match desk_list {
Ok(desk_list) => {
let desk_list_view = desk_list
.iter()
.map(|x| match config.local_name {
Some(_) => PotentialDesk {
name: x.name.to_string(),
status: SavedDeskStates::Saved.as_str().to_string(),
},
None => PotentialDesk {
name: x.name.to_string(),
status: SavedDeskStates::New.as_str().to_string(),
},
})
.collect::<Vec<PotentialDesk>>();

println!("Found desk list: {:?}", &desk_list_view);

return Ok(desk_list_view);
}
Err(e) => {
return Err(e.to_string());
}
}
}

pub async fn connect_to_desk_by_name_internal(name: String) -> Result<PlatformPeripheral, ()> {
let desk_to_connect = get_list_of_desks(&Some(name.clone())).await;
// TODO: UPDATE THE DESK INSTANCE MUTEX EVERY TIME YOU USE THIS FUNCTION HERE OTHERWISE IT WILL BREAK
// AS WE WILL HAVE DESYNC OF ACTUAL DESK AND CONNECTED ONE
pub async fn connect_to_desk_by_name_internal(name: String) -> Result<PlatformPeripheral, BtError> {
let desk_to_connect = get_list_of_desks(&Some(name.clone())).await?;
let desk_to_connect = desk_to_connect
.into_iter()
.next()
Expand All @@ -350,7 +355,32 @@ pub async fn connect_to_desk_by_name_internal(name: String) -> Result<PlatformPe

config_utils::save_local_name(name);
println!("saved desk!");
let _ = setup_bt_desk_device(&desk_to_connect).await;
// TODO: try to use the ACTUAL connected bt device, instead of the pre-connected device instance
// Challenge here is that we cannot operate on `impl ApiPeripheral`, cause it's not sized.
// Maybe it should be boxed/arced?
let bt = setup_bt_desk_device(&desk_to_connect).await;

let _bt_ok = match &bt {
Ok(val) => val,
Err(asd) => {
println!("{:?}", asd);
panic!("asd");
}
};

Ok(desk_to_connect)
}

// TODO: Figure out bluetooth mocking to improve testing; without mocks tests are impossible
#[cfg(test)]
mod connecting_suite {
#[tokio::test]
async fn should_fail_for_not_found_desk() {
let result =
crate::loose_idasen::connect_to_desk_by_name_internal("nonexistant_desk".to_string())
.await;
let err = result.unwrap_err();

assert_eq!(err.to_string(), "Cannot find the device.");
}
}
Loading