From 762e650f30de670c41a939c4dc1b797e793e1e44 Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Wed, 24 Nov 2021 17:45:27 +0100 Subject: [PATCH 01/29] Fix repository URL --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index abe11be..9da0ebe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ readme = "README.md" license-file = "LICENSE.md" edition = "2018" homepage = "https://github.com/makers-for-life/makair" -repository = "https://github.com/makers-for-life/makair.git" +repository = "https://github.com/makers-for-life/makair-control-ui" keywords = ["covid-19", "fusion-360", "cad", "covid", "coronavirus", "sars-cov-2", "nucleo-board", "covid-respirator", "makair-respirators", "medical", "ards"] categories = ["gui", "hardware-support"] authors = ["Valerian Saliou ", "Quentin Adam ", "David Sferruzza "] From d19fcf281b80259fa782cafa20a0aa8c79826c4c Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Wed, 24 Nov 2021 17:47:03 +0100 Subject: [PATCH 02/29] Add simulator --- Cargo.lock | 127 ++++++++++++---------------------------- Cargo.toml | 6 +- src/config/arguments.rs | 29 +++++++-- src/display/drawer.rs | 13 ++++ 4 files changed, 80 insertions(+), 95 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 995b1f5..9eb6c65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,9 +25,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.15.2" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a2e47a1fbe209ee101dd6d61285226744c6c8d3c21c8dc878ba6cb9f467f3a" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" dependencies = [ "gimli", ] @@ -46,9 +46,9 @@ checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" [[package]] name = "aho-corasick" -version = "0.7.15" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" dependencies = [ "memchr", ] @@ -82,12 +82,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "autocfg" version = "1.0.1" @@ -96,9 +90,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" -version = "0.3.59" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4717cfcbfaa661a0fd48f8453951837ae7e8f81e481fbb136e3202d72805a744" +checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" dependencies = [ "addr2line", "cc", @@ -121,18 +115,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bitvec" -version = "0.19.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - [[package]] name = "block" version = "0.1.6" @@ -526,12 +508,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -[[package]] -name = "funty" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" - [[package]] name = "getrandom" version = "0.2.3" @@ -545,9 +521,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.24.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4075386626662786ddb0ec9081e7c7eeb1ba31951f447ca780ef9f5d568189" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" [[package]] name = "gl_generator" @@ -802,19 +778,6 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -[[package]] -name = "lexical-core" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" -dependencies = [ - "arrayvec", - "bitflags", - "cfg-if 1.0.0", - "ryu", - "static_assertions", -] - [[package]] name = "libc" version = "0.1.12" @@ -955,6 +918,7 @@ dependencies = [ "intl-memoizer", "lazy_static", "log", + "makair-simulator", "makair-telemetry", "paste", "plotters", @@ -967,10 +931,20 @@ dependencies = [ "winit", ] +[[package]] +name = "makair-simulator" +version = "0.1.0" +source = "git+https://github.com/makers-for-life/makair-simulator?rev=f8f6da6467d556d5e79f827cec275f34cae44240#f8f6da6467d556d5e79f827cec275f34cae44240" +dependencies = [ + "cc", + "log", + "makair-telemetry", +] + [[package]] name = "makair-telemetry" -version = "2.1.0" -source = "git+https://github.com/makers-for-life/makair-telemetry?tag=v2.1.0#f644c7952faadb8370022a391937f9d1d208b6dc" +version = "2.2.0" +source = "git+https://github.com/makers-for-life/makair-telemetry?rev=184185d4301fa7343018cd6733e1fb23e2cb032e#184185d4301fa7343018cd6733e1fb23e2cb032e" dependencies = [ "base64", "crc32fast", @@ -997,9 +971,9 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.3.4" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memmap" @@ -1020,6 +994,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.3.7" @@ -1054,14 +1034,12 @@ dependencies = [ [[package]] name = "nom" -version = "6.2.1" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c5c51b9083a3c620fa67a2a635d1ce7d95b897e957d6b28ff9a5da960a103a6" +checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" dependencies = [ - "bitvec", - "funty", - "lexical-core", "memchr", + "minimal-lexical", "version_check", ] @@ -1194,9 +1172,12 @@ dependencies = [ [[package]] name = "object" -version = "0.24.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5b3dd1c072ee7963717671d1ca129f1048fda25edea6b752bfc71ac8854170" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +dependencies = [ + "memchr", +] [[package]] name = "ordered-float" @@ -1397,12 +1378,6 @@ dependencies = [ "proc-macro2 1.0.32", ] -[[package]] -name = "radium" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" - [[package]] name = "raw-window-handle" version = "0.3.3" @@ -1439,9 +1414,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.4.6" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" dependencies = [ "aho-corasick", "memchr", @@ -1550,12 +1525,6 @@ dependencies = [ "stb_truetype", ] -[[package]] -name = "ryu" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" - [[package]] name = "same-file" version = "1.0.6" @@ -1739,12 +1708,6 @@ dependencies = [ "smithay-client-toolkit 0.6.6", ] -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "stb_truetype" version = "0.3.1" @@ -1774,12 +1737,6 @@ dependencies = [ "nix", ] -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - [[package]] name = "termios" version = "0.2.2" @@ -2155,12 +2112,6 @@ dependencies = [ "x11-dl", ] -[[package]] -name = "wyz" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" - [[package]] name = "x11-clipboard" version = "0.5.3" diff --git a/Cargo.toml b/Cargo.toml index 9da0ebe..a9d5b47 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ confy = "0.4" lazy_static = "1.4" serde = { version = "1.0", features = ["derive"] } paste = "1.0" -rust-embed = { version = "5.6", default-features = false, features = ["compression"] } +rust-embed = { version = "5.6", default-features = false, features = ["compression", "debug-embed"] } chrono = { version = "0.4", default-features = false } fluent = "0.15" intl-memoizer = "0.5" @@ -39,12 +39,14 @@ conrod_winit = "0.70" conrod_core = "0.70" sysfs_gpio = { version = "0.5", optional = true } rn2903 = { git = "https://github.com/waxzce/lora-rust-rn2903-rn2483.git", rev = "b086057ba096920abef3870ad0cefa2c80a343e2", optional = true } -makair-telemetry = { git = "https://github.com/makers-for-life/makair-telemetry", tag = "v2.1.0", default-features = false, features = ["serial"] } +makair-telemetry = { git = "https://github.com/makers-for-life/makair-telemetry", rev = "184185d4301fa7343018cd6733e1fb23e2cb032e", default-features = false, features = ["serial"] } +makair-simulator = { git = "https://github.com/makers-for-life/makair-simulator", rev = "f8f6da6467d556d5e79f827cec275f34cae44240", optional = true } [features] default = [] fonts-cjk = [] lora = ["rn2903", "sysfs_gpio"] +simulator = ["makair-simulator"] [profile.dev] opt-level = 0 diff --git a/src/config/arguments.rs b/src/config/arguments.rs index d16202d..e3c4489 100644 --- a/src/config/arguments.rs +++ b/src/config/arguments.rs @@ -18,6 +18,8 @@ pub enum RunMode { output_dir: Option, }, Input(String), + #[cfg(feature = "simulator")] + Simulator, } pub struct ConfigArguments { @@ -59,6 +61,12 @@ impl ConfigArguments { .help("Path to a recorded input file") .takes_value(true), ) + .arg( + Arg::with_name("simulator") + .short("s") + .long("simulator") + .help("Run MakAir Simulator to get data"), + ) .arg( Arg::with_name("output") .short("o") @@ -94,15 +102,26 @@ impl ConfigArguments { .get_matches(); // Parse input mode - let mode = match (matches.value_of("port"), matches.value_of("input")) { - (Some(p), _) => RunMode::Port { + let mode = match ( + matches.value_of("port"), + matches.value_of("input"), + matches.is_present("simulator"), + ) { + (Some(p), _, _) => RunMode::Port { port: p.to_string(), output_dir: matches.value_of("output").map(|str| str.to_string()), }, - (None, Some(i)) => RunMode::Input(i.to_string()), - (None, None) => { - eprintln!("You should provide either a serial port (-p) or an input file (-i)"); + (None, Some(i), _) => RunMode::Input(i.to_string()), + #[cfg(feature = "simulator")] + (None, None, true) => RunMode::Simulator, + #[cfg(not(feature = "simulator"))] + (None, None, true) => { + eprintln!("Program was not compiled with the 'simulator' feature"); + std::process::exit(1); + } + (None, None, false) => { + eprintln!("You should provide either a serial port (-p), an input file (-i) or enable MakAir Simulator (-s)"); std::process::exit(1); } }; diff --git a/src/display/drawer.rs b/src/display/drawer.rs index 464398b..4c215b5 100644 --- a/src/display/drawer.rs +++ b/src/display/drawer.rs @@ -268,6 +268,19 @@ impl<'a> DisplayDrawer<'a> { makair_telemetry::gather_telemetry_from_file(file, tx.clone(), true); }); } + + #[cfg(feature = "simulator")] + RunMode::Simulator => { + let mut simulator = makair_simulator::MakAirSimulator::new(tx); + simulator.initialize(); + + let settings_receiver = self.chip.init_settings_receiver(); + std::thread::spawn(move || { + while let Ok(message) = settings_receiver.recv() { + simulator.send_control_message(message); + } + }); + } } rx From 1048155e9034843725087867bcac0bb5d37607b0 Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Wed, 24 Nov 2021 21:16:28 +0100 Subject: [PATCH 03/29] Fix Clippy warnings --- src/chip/mod.rs | 4 ++-- src/chip/settings/advanced.rs | 2 +- src/chip/settings/mod.rs | 2 +- src/chip/settings/run.rs | 2 +- src/chip/settings/snooze.rs | 2 +- src/config/settings.rs | 2 +- src/display/drawer.rs | 11 +++++------ src/display/renderer.rs | 4 ++-- src/display/screen.rs | 16 ++++++++-------- src/locale/accessor.rs | 2 +- src/widget/advanced_settings.rs | 3 ++- src/widget/alarm.rs | 4 ++-- src/widget/graph.rs | 8 ++++---- src/widget/run_settings.rs | 4 ++-- src/widget/snooze_settings.rs | 4 ++-- 15 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/chip/mod.rs b/src/chip/mod.rs index 4519b1a..c9c53d5 100644 --- a/src/chip/mod.rs +++ b/src/chip/mod.rs @@ -301,8 +301,8 @@ impl Chip { // Sort final alarm list by code, then priority (ensures codes are ordered within their \ // priority group, which are themselves sorted by priority) - alarm_list.sort_by(|(code1, _), (code2, _)| code1.cmp(&code2)); - alarm_list.sort_by(|(_, priority1), (_, priority2)| priority2.cmp(&priority1)); + alarm_list.sort_by(|(code1, _), (code2, _)| code1.cmp(code2)); + alarm_list.sort_by(|(_, priority1), (_, priority2)| priority2.cmp(priority1)); alarm_list } diff --git a/src/chip/settings/advanced.rs b/src/chip/settings/advanced.rs index ac9ac43..569dedd 100644 --- a/src/chip/settings/advanced.rs +++ b/src/chip/settings/advanced.rs @@ -82,7 +82,7 @@ impl SettingsAdvanced { } // Replace current locale with new locale - APP_I18N.replace(LocaleLoader::new(&self.locale.to_code()).into_bundle()); + APP_I18N.replace(LocaleLoader::new(self.locale.to_code()).into_bundle()); } } } diff --git a/src/chip/settings/mod.rs b/src/chip/settings/mod.rs index eb243d2..d949e9d 100644 --- a/src/chip/settings/mod.rs +++ b/src/chip/settings/mod.rs @@ -59,7 +59,7 @@ impl SettingActionState { } } - fn to_toggled(&self) -> Self { + fn as_toggled(&self) -> Self { match self { Self::Enabled => Self::Disabled, Self::Disabled => Self::Enabled, diff --git a/src/chip/settings/run.rs b/src/chip/settings/run.rs index fd54e4d..084ca5a 100644 --- a/src/chip/settings/run.rs +++ b/src/chip/settings/run.rs @@ -35,7 +35,7 @@ impl SettingsRun { fn toggle_state(&self) -> ControlMessage { ControlMessage { setting: ControlSetting::RespirationEnabled, - value: self.state.to_toggled() as u16, + value: self.state.as_toggled() as u16, } } } diff --git a/src/chip/settings/snooze.rs b/src/chip/settings/snooze.rs index 138bc35..af10ea3 100644 --- a/src/chip/settings/snooze.rs +++ b/src/chip/settings/snooze.rs @@ -35,7 +35,7 @@ impl SettingsSnooze { fn toggle_alarms(&self) -> ControlMessage { ControlMessage { setting: ControlSetting::AlarmSnooze, - value: self.alarms.to_toggled() as u16, + value: self.alarms.as_toggled() as u16, } } } diff --git a/src/config/settings.rs b/src/config/settings.rs index c39260e..f6e3883 100644 --- a/src/config/settings.rs +++ b/src/config/settings.rs @@ -54,7 +54,7 @@ impl ConfigSettings { // Ensure configuration is still valid // Notice: as the UI may be resumed from an old saved state, some saved configuration \ // values may not be valid anymore, hence this check to ensure their validity. - if LocaleCode::from_code(&configuration.locale.as_str()).is_none() { + if LocaleCode::from_code(configuration.locale.as_str()).is_none() { configuration.locale = LocaleCode::default().to_code().to_string(); } diff --git a/src/display/drawer.rs b/src/display/drawer.rs index 4c215b5..442df17 100644 --- a/src/display/drawer.rs +++ b/src/display/drawer.rs @@ -231,16 +231,15 @@ impl<'a> DisplayDrawer<'a> { match &APP_ARGS.mode { RunMode::Port { port, output_dir } => { let optional_file_buffer = output_dir.as_ref().map(|dir| { - let file_count: Vec> = - std::fs::read_dir(dir) - .expect("should read directory") - .collect(); + let file_count = std::fs::read_dir(dir) + .expect("should read directory") + .count(); let path = format!( "{}/{}-{}.record", &dir, chrono::Local::now().format("%Y%m%d-%H%M%S"), - file_count.len() + 1 + file_count + 1 ); let file = std::fs::File::create(&path) @@ -253,7 +252,7 @@ impl<'a> DisplayDrawer<'a> { std::thread::spawn(move || { makair_telemetry::gather_telemetry( - &port, + port, tx, optional_file_buffer, Some(settings_receiver), diff --git a/src/display/renderer.rs b/src/display/renderer.rs index af307d8..70a0e1e 100644 --- a/src/display/renderer.rs +++ b/src/display/renderer.rs @@ -256,10 +256,10 @@ impl DisplayRenderer { ), step: match eol { ChipEndOfLine::Ongoing(eol_step, _) => { - index_from_end_of_line_step(&eol_step).unwrap_or(0) + index_from_end_of_line_step(eol_step).unwrap_or(0) } ChipEndOfLine::Failed(eol_failure, _) => { - index_from_end_of_line_failure(&eol_failure).unwrap_or(0) + index_from_end_of_line_failure(eol_failure).unwrap_or(0) } ChipEndOfLine::Succeeded(_, _) => END_OF_LINE_STEPS_COUNT, }, diff --git a/src/display/screen.rs b/src/display/screen.rs index b68ae69..ba6d995 100644 --- a/src/display/screen.rs +++ b/src/display/screen.rs @@ -423,25 +423,25 @@ impl<'a> Screen<'a> { self.render_telemetry_mode_overview(mode); // Initialize the peak widget - self.render_telemetry_peak(&machine_snapshot, has_target_pressure); + self.render_telemetry_peak(machine_snapshot, has_target_pressure); // Initialize the plateau widget - self.render_telemetry_plateau(&machine_snapshot, mode, has_target_pressure); + self.render_telemetry_plateau(machine_snapshot, mode, has_target_pressure); // Initialize the PEEP widget - self.render_telemetry_peep(&machine_snapshot, has_target_pressure); + self.render_telemetry_peep(machine_snapshot, has_target_pressure); // Initialize the cycles widget - self.render_telemetry_cycles(&machine_snapshot); + self.render_telemetry_cycles(machine_snapshot); // Initialize the tidal widget - self.render_telemetry_tidal(&machine_snapshot, mode); + self.render_telemetry_tidal(machine_snapshot, mode); // Initialize the minute volume widget - self.render_telemetry_minute_volume(&machine_snapshot); + self.render_telemetry_minute_volume(machine_snapshot); // Initialize the ratio widget - self.render_telemetry_ratio(&machine_snapshot, mode); + self.render_telemetry_ratio(machine_snapshot, mode); } fn render_telemetry_graph(&mut self) { @@ -957,7 +957,7 @@ impl<'a> Screen<'a> { advanced_settings: settings, last_tick: self.timers.1, - machine_snapshot: &self.machine_snapshot.unwrap(), + machine_snapshot: self.machine_snapshot.unwrap(), data_snapshot: self.data_snapshot, alarms: self.ongoing_alarms.unwrap(), diff --git a/src/locale/accessor.rs b/src/locale/accessor.rs index 9c568fa..87c26a5 100644 --- a/src/locale/accessor.rs +++ b/src/locale/accessor.rs @@ -39,7 +39,7 @@ impl LocaleAccessor { if let Some(pattern) = message.value() { let mut errors = vec![]; - let formatted = bundle.format_pattern(&pattern, arguments, &mut errors); + let formatted = bundle.format_pattern(pattern, arguments, &mut errors); // Any error? Panic if !errors.is_empty() { diff --git a/src/widget/advanced_settings.rs b/src/widget/advanced_settings.rs index 7f49c49..3a492c7 100644 --- a/src/widget/advanced_settings.rs +++ b/src/widget/advanced_settings.rs @@ -290,6 +290,7 @@ fn form_statistics_lines<'a>( let line_text = line_data[index].0; // Render line label (the positioning method varies if the line is the first one) + #[allow(clippy::branches_sharing_code)] if index == 0 { gen_widget_label_styled!( master, @@ -326,7 +327,7 @@ fn form_statistics_lines<'a>( widget::Text::new(if line_data[index].1.is_empty() { ADVANCED_SETTINGS_LINE_VALUE_EMPTY } else { - &line_data[index].1 + line_data[index].1 }) .with_style(value_text_style) .top_left_with_margins_on( diff --git a/src/widget/alarm.rs b/src/widget/alarm.rs index ed1f930..820d499 100644 --- a/src/widget/alarm.rs +++ b/src/widget/alarm.rs @@ -65,8 +65,8 @@ pub fn render( .set(config.alarm_widgets[index], &mut master.ui); // Draw code & message - code(master, &config, alarm_code, alarm_priority, index); - message(master, &config, alarm_code, alarm_priority, index); + code(master, config, alarm_code, alarm_priority, index); + message(master, config, alarm_code, alarm_priority, index); } fn code_color(alarm_priority: &AlarmPriority) -> Color { diff --git a/src/widget/graph.rs b/src/widget/graph.rs index e17d19b..dc1b4ae 100644 --- a/src/widget/graph.rs +++ b/src/widget/graph.rs @@ -155,7 +155,7 @@ fn pressure<'a>( plot_id: config.pressure_id, precision_divide: TELEMETRY_POINTS_PRESSURE_PRECISION_DIVIDE, line_color: &GRAPH_PRESSURE_LINE_COLOR, - data_values: &config.data_pressure, + data_values: config.data_pressure, }, ); @@ -176,7 +176,7 @@ fn pressure<'a>( time_range, config.pressure_id, config.pressure_saturate_ids, - &config.data_pressure, + config.data_pressure, ); } } @@ -211,7 +211,7 @@ fn flow<'a>( plot_id: config.flow_id, precision_divide: TELEMETRY_POINTS_FLOW_PRECISION_DIVIDE, line_color: &GRAPH_FLOW_LINE_COLOR, - data_values: &config.data_flow, + data_values: config.data_flow, }, ); @@ -232,7 +232,7 @@ fn flow<'a>( time_range, config.flow_id, config.flow_saturate_ids, - &config.data_flow, + config.data_flow, ); } } diff --git a/src/widget/run_settings.rs b/src/widget/run_settings.rs index 12430ce..fb410f6 100644 --- a/src/widget/run_settings.rs +++ b/src/widget/run_settings.rs @@ -53,8 +53,8 @@ pub fn render<'a>(master: &mut ControlWidget<'a>, config: Config) -> f64 { fn status<'a>(master: &mut ControlWidget<'a>, config: &Config) { // Append sub-contents - status_label(master, &config); - status_form(master, &config); + status_label(master, config); + status_form(master, config); } fn status_label<'a>(master: &mut ControlWidget<'a>, config: &Config) { diff --git a/src/widget/snooze_settings.rs b/src/widget/snooze_settings.rs index f628f13..8005911 100644 --- a/src/widget/snooze_settings.rs +++ b/src/widget/snooze_settings.rs @@ -54,8 +54,8 @@ pub fn render<'a>(master: &mut ControlWidget<'a>, config: Config) -> f64 { fn alarms<'a>(master: &mut ControlWidget<'a>, config: &Config) { // Append sub-contents - alarms_label(master, &config); - alarms_form(master, &config); + alarms_label(master, config); + alarms_form(master, config); } fn alarms_label<'a>(master: &mut ControlWidget<'a>, config: &Config) { From d36bdd896da115ba215e957ea7320c9f447f972a Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Wed, 24 Nov 2021 21:29:11 +0100 Subject: [PATCH 04/29] Update rust-embed --- Cargo.lock | 75 +++++++++++++++++++++++++++++++++++++++---- Cargo.toml | 2 +- src/display/macros.rs | 9 ++++-- src/display/window.rs | 12 ++++--- src/locale/loader.rs | 4 +-- 5 files changed, 87 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9eb6c65..8b00882 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -121,6 +121,15 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + [[package]] name = "bumpalo" version = "3.8.0" @@ -327,6 +336,15 @@ dependencies = [ "libc 0.2.108", ] +[[package]] +name = "cpufeatures" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +dependencies = [ + "libc 0.2.108", +] + [[package]] name = "crc32fast" version = "1.2.2" @@ -392,6 +410,15 @@ dependencies = [ "byteorder", ] +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "directories" version = "2.0.2" @@ -508,6 +535,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "generic-array" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.3" @@ -1179,6 +1216,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + [[package]] name = "ordered-float" version = "1.1.1" @@ -1447,9 +1490,9 @@ dependencies = [ [[package]] name = "rust-embed" -version = "5.9.0" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fe1fe6aac5d6bb9e1ffd81002340363272a7648234ec7bdfac5ee202cb65523" +checksum = "1be44a6694859b7cfc955699935944a6844aa9fe416aeda5d40829e3e38dfee6" dependencies = [ "include-flate", "rust-embed-impl", @@ -1459,9 +1502,9 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "5.9.0" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed91c41c42ef7bf687384439c312e75e0da9c149b0390889b94de3c7d9d9e66" +checksum = "f567ca01565c50c67b29e535f5f67b8ea8aeadaeed16a88f10792ab57438b957" dependencies = [ "proc-macro2 1.0.32", "quote 1.0.10", @@ -1472,10 +1515,11 @@ dependencies = [ [[package]] name = "rust-embed-utils" -version = "5.1.0" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a512219132473ab0a77b52077059f1c47ce4af7fbdc94503e9862a34422876d" +checksum = "6116e7ab9ea963f60f2f20291d8fcf6c7273192cdd7273b3c80729a9605c97b2" dependencies = [ + "sha2", "walkdir", ] @@ -1640,6 +1684,19 @@ dependencies = [ "winapi", ] +[[package]] +name = "sha2" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" +dependencies = [ + "block-buffer", + "cfg-if 1.0.0", + "cpufeatures", + "digest", + "opaque-debug", +] + [[package]] name = "shared_library" version = "0.1.9" @@ -1810,6 +1867,12 @@ dependencies = [ "rustc-hash", ] +[[package]] +name = "typenum" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" + [[package]] name = "unic-langid" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index a9d5b47..35556d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ confy = "0.4" lazy_static = "1.4" serde = { version = "1.0", features = ["derive"] } paste = "1.0" -rust-embed = { version = "5.6", default-features = false, features = ["compression", "debug-embed"] } +rust-embed = { version = "6.2", default-features = false, features = ["compression", "debug-embed"] } chrono = { version = "0.4", default-features = false } fluent = "0.15" intl-memoizer = "0.5" diff --git a/src/display/macros.rs b/src/display/macros.rs index 5d225da..9d7051a 100644 --- a/src/display/macros.rs +++ b/src/display/macros.rs @@ -30,8 +30,12 @@ macro_rules! image_ids { macro_rules! gen_load_font { ($embedded_fonts:ident, $name:expr) => { conrod_core::text::Font::from_bytes( - inflate_bytes_zlib(&$embedded_fonts::get(&format!("{}.ttf.zz", $name)).unwrap()) - .unwrap(), + inflate_bytes_zlib( + &$embedded_fonts::get(&format!("{}.ttf.zz", $name)) + .unwrap() + .data, + ) + .unwrap(), ) .unwrap() }; @@ -43,6 +47,7 @@ macro_rules! gen_load_image_reverse { &load_from_memory( EmbeddedImages::get(&format!("{}.png", $name)) .unwrap() + .data .to_mut(), ) .unwrap() diff --git a/src/display/window.rs b/src/display/window.rs index 16be048..747a38b 100644 --- a/src/display/window.rs +++ b/src/display/window.rs @@ -31,11 +31,15 @@ impl DisplayWindowBuilder { } lazy_static! { - static ref IMAGE_WINDOW_ICON_RGBA_RAW: Vec = - load_from_memory(EmbeddedImages::get("window-icon.png").unwrap().to_mut()) + static ref IMAGE_WINDOW_ICON_RGBA_RAW: Vec = load_from_memory( + EmbeddedImages::get("window-icon.png") .unwrap() - .into_rgba8() - .into_raw(); + .data + .to_mut() + ) + .unwrap() + .into_rgba8() + .into_raw(); static ref FONT_DEFAULT_NOTOSANS_REGULAR: conrod_core::text::Font = gen_load_font!(EmbeddedFontsDefault, "notosans_regular"); static ref FONT_DEFAULT_NOTOSANS_BOLD: conrod_core::text::Font = diff --git a/src/locale/loader.rs b/src/locale/loader.rs index a5d6a27..8d2b797 100644 --- a/src/locale/loader.rs +++ b/src/locale/loader.rs @@ -34,8 +34,8 @@ impl LocaleLoader { let locale_id: LanguageIdentifier = locale.parse().expect("locale code parsing failed"); let locale_buffer = EmbeddedLocales::get(&format!("{}{}", locale, LOCALE_EXTENSION)) .expect("locale not found"); - let locale_string = - String::from_utf8(locale_buffer.into_owned()).expect("locale file is not a string"); + let locale_string = String::from_utf8(locale_buffer.data.into_owned()) + .expect("locale file is not a string"); info!("loaded locale: [{}]", locale); From bb55cf12034ca71383f91e261989d1ef82f93005 Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Wed, 24 Nov 2021 21:38:58 +0100 Subject: [PATCH 05/29] Update dependencies --- Cargo.lock | 52 +++++++++++++++++++++++++++++++++++++--------------- Cargo.toml | 6 +++--- 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8b00882..aac9abf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -376,7 +376,7 @@ dependencies = [ "crossbeam-utils", "lazy_static", "maybe-uninit", - "memoffset", + "memoffset 0.5.6", "scopeguard", ] @@ -472,9 +472,9 @@ checksum = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" [[package]] name = "fluent" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc4d7142005e2066e4844caf9f271b93fc79836ee96ec85057b8c109687e629a" +checksum = "61f69378194459db76abd2ce3952b790db103ceb003008d3d50d97c41ff847a7" dependencies = [ "fluent-bundle", "unic-langid", @@ -971,7 +971,7 @@ dependencies = [ [[package]] name = "makair-simulator" version = "0.1.0" -source = "git+https://github.com/makers-for-life/makair-simulator?rev=f8f6da6467d556d5e79f827cec275f34cae44240#f8f6da6467d556d5e79f827cec275f34cae44240" +source = "git+https://github.com/makers-for-life/makair-simulator?rev=9cba9863592791f2d6bcd36fcfc9103d552243f1#9cba9863592791f2d6bcd36fcfc9103d552243f1" dependencies = [ "cc", "log", @@ -1031,6 +1031,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +dependencies = [ + "autocfg", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1069,6 +1078,19 @@ dependencies = [ "void", ] +[[package]] +name = "nix" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f305c2c2e4c39a82f7bf0bf65fb557f9070ce06781d4f2454295cc34b1c43188" +dependencies = [ + "bitflags", + "cc", + "cfg-if 1.0.0", + "libc 0.2.108", + "memoffset 0.6.4", +] + [[package]] name = "nom" version = "7.1.0" @@ -1679,7 +1701,7 @@ dependencies = [ "cfg-if 0.1.10", "libudev", "mach 0.2.3", - "nix", + "nix 0.14.1", "regex", "winapi", ] @@ -1733,7 +1755,7 @@ dependencies = [ "dlib", "lazy_static", "memmap", - "nix", + "nix 0.14.1", "wayland-client 0.21.13", "wayland-commons 0.21.13", "wayland-protocols 0.21.13", @@ -1750,7 +1772,7 @@ dependencies = [ "dlib", "lazy_static", "memmap", - "nix", + "nix 0.14.1", "wayland-client 0.23.6", "wayland-protocols 0.23.6", ] @@ -1761,7 +1783,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "917e8ec7f535cd1a6cbf749c8866c24d67c548a80ac48c8e88a182eab5c07bd1" dependencies = [ - "nix", + "nix 0.14.1", "smithay-client-toolkit 0.6.6", ] @@ -1787,11 +1809,11 @@ dependencies = [ [[package]] name = "sysfs_gpio" -version = "0.5.4" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24961a55846623d8e4f6cec38718945116fed8d6970336a7110710a07aa9b5d1" +checksum = "9ef9c9bcbfeb596ce4da59b2c59736235f35dcd516f03958ea10834473224157" dependencies = [ - "nix", + "nix 0.23.0", ] [[package]] @@ -2001,7 +2023,7 @@ dependencies = [ "bitflags", "downcast-rs", "libc 0.2.108", - "nix", + "nix 0.14.1", "wayland-commons 0.21.13", "wayland-scanner 0.21.13", "wayland-sys 0.21.13", @@ -2016,7 +2038,7 @@ dependencies = [ "bitflags", "downcast-rs", "libc 0.2.108", - "nix", + "nix 0.14.1", "wayland-commons 0.23.6", "wayland-scanner 0.23.6", "wayland-sys 0.23.6", @@ -2028,7 +2050,7 @@ version = "0.21.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c08896768b667e1df195d88a62a53a2d1351a1ed96188be79c196b35bb32ec" dependencies = [ - "nix", + "nix 0.14.1", "wayland-sys 0.21.13", ] @@ -2038,7 +2060,7 @@ version = "0.23.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb66b0d1a27c39bbce712b6372131c6e25149f03ffb0cd017cf8f7de8d66dbdb" dependencies = [ - "nix", + "nix 0.14.1", "wayland-sys 0.23.6", ] diff --git a/Cargo.toml b/Cargo.toml index 35556d8..03d2493 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ serde = { version = "1.0", features = ["derive"] } paste = "1.0" rust-embed = { version = "6.2", default-features = false, features = ["compression", "debug-embed"] } chrono = { version = "0.4", default-features = false } -fluent = "0.15" +fluent = "0.16" intl-memoizer = "0.5" unic-langid = "0.9" inflate = "0.4" @@ -37,10 +37,10 @@ plotters-conrod = "0.3" conrod_glium = "0.70" conrod_winit = "0.70" conrod_core = "0.70" -sysfs_gpio = { version = "0.5", optional = true } +sysfs_gpio = { version = "0.6", optional = true } rn2903 = { git = "https://github.com/waxzce/lora-rust-rn2903-rn2483.git", rev = "b086057ba096920abef3870ad0cefa2c80a343e2", optional = true } makair-telemetry = { git = "https://github.com/makers-for-life/makair-telemetry", rev = "184185d4301fa7343018cd6733e1fb23e2cb032e", default-features = false, features = ["serial"] } -makair-simulator = { git = "https://github.com/makers-for-life/makair-simulator", rev = "f8f6da6467d556d5e79f827cec275f34cae44240", optional = true } +makair-simulator = { git = "https://github.com/makers-for-life/makair-simulator", rev = "9cba9863592791f2d6bcd36fcfc9103d552243f1", optional = true } [features] default = [] From 0b428e9f8ae845e34ef6658ea6826d54e47dfc54 Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Fri, 26 Nov 2021 18:17:43 +0100 Subject: [PATCH 06/29] Update to conrod 0.71 + glium 0.28 + winit 0.23 --- Cargo.lock | 917 ++++++++++++++++++++++++++++++----------- Cargo.toml | 12 +- src/display/drawer.rs | 345 ++++++++-------- src/display/events.rs | 58 --- src/display/support.rs | 27 +- src/display/window.rs | 30 +- src/main.rs | 2 - 7 files changed, 867 insertions(+), 524 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aac9abf..83f1848 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,7 +8,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0e9889e6db118d49d88d84728d0e964d973a5680befb5f85f55141beea5c20b" dependencies = [ - "libc 0.2.108", + "libc", "mach 0.1.2", ] @@ -19,10 +19,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99696c398cbaf669d2368076bdb3d627fb0ce51a26899d7c61228c5c0af3bf4a" dependencies = [ "CoreFoundation-sys", - "libc 0.2.108", + "libc", "mach 0.1.2", ] +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13739d7177fbd22bb0ed28badfff9f372f8bef46c863db4e1c6248f6b223b6e" + [[package]] name = "addr2line" version = "0.17.0" @@ -67,6 +73,19 @@ dependencies = [ "xml-rs", ] +[[package]] +name = "andrew" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c4afb09dd642feec8408e33f92f3ffc4052946f6b20f32fb99c1f58cd4fa7cf" +dependencies = [ + "bitflags", + "rusttype 0.9.2", + "walkdir", + "xdg", + "xml-rs", +] + [[package]] name = "android_glue" version = "0.2.3" @@ -97,7 +116,7 @@ dependencies = [ "addr2line", "cc", "cfg-if 1.0.0", - "libc 0.2.108", + "libc", "miniz_oxide 0.4.4", "object", "rustc-demangle", @@ -148,6 +167,16 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "calloop" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b036167e76041694579972c28cf4877b4f92da222560ddb49008937b6a6727c" +dependencies = [ + "log", + "nix 0.18.0", +] + [[package]] name = "cc" version = "1.0.72" @@ -168,12 +197,11 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cgl" -version = "0.2.3" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55e7ec0b74fe5897894cbc207092c577e87c52f8a59e8ca8d97ef37551f60a49" +checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" dependencies = [ - "gleam", - "libc 0.2.108", + "libc", ] [[package]] @@ -182,11 +210,11 @@ version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ - "libc 0.2.108", + "libc", "num-integer", "num-traits", "time", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -206,30 +234,37 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3a093d6fed558e5fe24c3dfc85a68bb68f1c824f440d3ba5aca189e2998786b" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] -name = "cloudabi" -version = "0.0.3" +name = "cocoa" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +checksum = "c54201c07dcf3a5ca33fececb8042aed767ee4bfd5a0235a8ceabcda956044b2" dependencies = [ "bitflags", + "block", + "cocoa-foundation", + "core-foundation 0.9.2", + "core-graphics 0.22.3", + "foreign-types", + "libc", + "objc", ] [[package]] -name = "cocoa" -version = "0.18.5" +name = "cocoa-foundation" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1706996401131526e36b3b49f0c4d912639ce110996f3ca144d78946727bce54" +checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" dependencies = [ "bitflags", "block", - "core-foundation", - "core-graphics", + "core-foundation 0.9.2", + "core-graphics-types", "foreign-types", - "libc 0.2.108", + "libc", "objc", ] @@ -252,9 +287,9 @@ dependencies = [ [[package]] name = "conrod_core" -version = "0.70.0" +version = "0.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a079920382700ee474e118991a4bc866039e0a0537ca2308d82b9b47976c4a99" +checksum = "5c07b39486d6ab17012506a6ed359efdfbfcc7b616e4ff52eaf75bc6fd3c03f9" dependencies = [ "conrod_derive", "copypasta", @@ -268,9 +303,9 @@ dependencies = [ [[package]] name = "conrod_derive" -version = "0.70.0" +version = "0.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3608c2b51dfdd85355b113113d35118d9b0629bafc72b0d3e163239e5576728" +checksum = "f7b034b19c35f46461439c130fcebada7e67c7379a2f91a259a83f9e9643085e" dependencies = [ "proc-macro2 1.0.32", "quote 1.0.10", @@ -279,9 +314,9 @@ dependencies = [ [[package]] name = "conrod_glium" -version = "0.70.0" +version = "0.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3b264ca85076f5f888c5f9de39b088c4cd4e778352d74d04cf872992dd8cfd" +checksum = "ea62a2faf29da55238e515cf0b32d8a554488a606a84a0f176a7d577c76499e5" dependencies = [ "conrod_core", "glium", @@ -289,9 +324,9 @@ dependencies = [ [[package]] name = "conrod_winit" -version = "0.70.0" +version = "0.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d12a5620cd3d4540565e32e6f322fb8bcf58c20bf3c3ccfdbf0a0c2201b8fba" +checksum = "dfbe64a64440965cbb4897bd4c35631d34304426e683a4dd86fd00074cecb514" [[package]] name = "copypasta" @@ -310,30 +345,84 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.6.4" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" +dependencies = [ + "core-foundation-sys 0.7.0", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" +checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" dependencies = [ - "core-foundation-sys", - "libc 0.2.108", + "core-foundation-sys 0.8.3", + "libc", ] [[package]] name = "core-foundation-sys" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" +checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "core-graphics" -version = "0.17.3" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" +dependencies = [ + "bitflags", + "core-foundation 0.7.0", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +dependencies = [ + "bitflags", + "core-foundation 0.9.2", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56790968ab1c8a1202a102e6de05fc6e1ec87da99e4e93e9a7d13efbfc1e95a9" +checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" dependencies = [ "bitflags", - "core-foundation", + "core-foundation 0.9.2", "foreign-types", - "libc 0.2.108", + "libc", +] + +[[package]] +name = "core-video-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ecad23610ad9757664d644e369246edde1803fcb43ed72876565098a5d3828" +dependencies = [ + "cfg-if 0.1.10", + "core-foundation-sys 0.7.0", + "core-graphics 0.19.2", + "libc", + "objc", ] [[package]] @@ -342,7 +431,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" dependencies = [ - "libc 0.2.108", + "libc", ] [[package]] @@ -400,6 +489,41 @@ dependencies = [ "petgraph", ] +[[package]] +name = "darling" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2 1.0.32", + "quote 1.0.10", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" +dependencies = [ + "darling_core", + "quote 1.0.10", + "syn", +] + [[package]] name = "deflate" version = "0.8.6" @@ -410,6 +534,17 @@ dependencies = [ "byteorder", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2 1.0.32", + "quote 1.0.10", + "syn", +] + [[package]] name = "digest" version = "0.9.0" @@ -444,11 +579,17 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" dependencies = [ - "libc 0.2.108", + "libc", "redox_users", - "winapi", + "winapi 0.3.9", ] +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + [[package]] name = "dlib" version = "0.4.2" @@ -458,6 +599,15 @@ dependencies = [ "libloading 0.6.7", ] +[[package]] +name = "dlib" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" +dependencies = [ + "libloading 0.7.2", +] + [[package]] name = "downcast-rs" version = "1.2.0" @@ -492,7 +642,7 @@ dependencies = [ "intl_pluralrules", "rustc-hash", "self_cell", - "smallvec 1.7.0", + "smallvec", "unic-langid", ] @@ -535,6 +685,22 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + [[package]] name = "generic-array" version = "0.14.4" @@ -552,7 +718,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ "cfg-if 1.0.0", - "libc 0.2.108", + "libc", "wasi", ] @@ -562,28 +728,6 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" -[[package]] -name = "gl_generator" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39a23d5e872a275135d66895d954269cf5e8661d234eb1c2480f4ce0d586acbd" -dependencies = [ - "khronos_api", - "log", - "xml-rs", -] - -[[package]] -name = "gl_generator" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca98bbde17256e02d17336a6bdb5a50f7d0ccacee502e191d3e3d0ec2f96f84a" -dependencies = [ - "khronos_api", - "log", - "xml-rs", -] - [[package]] name = "gl_generator" version = "0.14.0" @@ -595,52 +739,46 @@ dependencies = [ "xml-rs", ] -[[package]] -name = "gleam" -version = "0.6.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cae10d7c99d0e77b4766e850a60898a17c1abaf01075531f1066f03dc7dc5fc5" -dependencies = [ - "gl_generator 0.13.1", -] - [[package]] name = "glium" -version = "0.24.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213290166315d0ff3cf48dd76a31f3ad57c934182d3e87aeec890f2747226a21" +checksum = "7eeec7b733d14519e2541f4cc8a1230de9143d4ec439dd51b6c048d8ec991759" dependencies = [ "backtrace", "fnv", - "gl_generator 0.11.0", + "gl_generator", "glutin", "lazy_static", - "smallvec 0.6.14", + "memoffset 0.5.6", + "smallvec", + "takeable-option", ] [[package]] name = "glutin" -version = "0.20.1" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e5cc17ac6cb35704f434faaa5bb5e4254a66f50853976c7e6f00aee09ff1bf2" +checksum = "d8bae26a39a728b003e9fad473ea89527de0de050143b4df866f18bb154bc86e" dependencies = [ "android_glue", "cgl", "cocoa", - "core-foundation", - "core-graphics", + "core-foundation 0.9.2", "glutin_egl_sys", + "glutin_emscripten_sys", "glutin_gles2_sys", "glutin_glx_sys", "glutin_wgl_sys", "lazy_static", - "libc 0.2.108", - "libloading 0.5.2", + "libloading 0.6.7", + "log", "objc", "osmesa-sys", - "shared_library", - "wayland-client 0.21.13", - "winapi", + "parking_lot", + "wayland-client 0.28.6", + "wayland-egl", + "winapi 0.3.9", "winit", ] @@ -650,17 +788,23 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2abb6aa55523480c4adc5a56bbaa249992e2dddb2fc63dc96e04a3355364c211" dependencies = [ - "gl_generator 0.14.0", - "winapi", + "gl_generator", + "winapi 0.3.9", ] +[[package]] +name = "glutin_emscripten_sys" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80de4146df76e8a6c32b03007bc764ff3249dcaeb4f675d68a06caf1bac363f1" + [[package]] name = "glutin_gles2_sys" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094e708b730a7c8a1954f4f8a31880af00eb8a1c5b5bf85d28a0a3c6d69103" dependencies = [ - "gl_generator 0.14.0", + "gl_generator", "objc", ] @@ -670,7 +814,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e393c8fc02b807459410429150e9c4faffdb312d59b8c038566173c81991351" dependencies = [ - "gl_generator 0.14.0", + "gl_generator", "x11-dl", ] @@ -680,7 +824,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3da5951a1569dbab865c6f2a863efafff193a93caf05538d193e9e3816d21696" dependencies = [ - "gl_generator 0.14.0", + "gl_generator", ] [[package]] @@ -689,7 +833,7 @@ version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ - "libc 0.2.108", + "libc", ] [[package]] @@ -698,6 +842,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "image" version = "0.23.14" @@ -791,9 +941,24 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7970510895cee30b3e9128319f2cefd4bde883a39f38baa279567ba3a7eb97d" dependencies = [ - "libc 0.2.108", + "libc", +] + +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", ] +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + [[package]] name = "js-sys" version = "0.3.55" @@ -803,6 +968,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "khronos_api" version = "3.1.0" @@ -816,10 +991,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] -name = "libc" -version = "0.1.12" +name = "lazycell" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" @@ -849,22 +1024,22 @@ dependencies = [ [[package]] name = "libloading" -version = "0.5.2" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" +checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" dependencies = [ - "cc", - "winapi", + "cfg-if 1.0.0", + "winapi 0.3.9", ] [[package]] name = "libloading" -version = "0.6.7" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" +checksum = "afe203d669ec979b7128619bae5a63b7b42e9203c1b29146079ee05e2f604b52" dependencies = [ "cfg-if 1.0.0", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -873,7 +1048,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea626d3bdf40a1c5aee3bcd4f40826970cae8d80a8fec934c82a63840094dcfe" dependencies = [ - "libc 0.2.108", + "libc", "libudev-sys", ] @@ -883,7 +1058,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324" dependencies = [ - "libc 0.2.108", + "libc", "pkg-config", ] @@ -904,9 +1079,9 @@ checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" [[package]] name = "lock_api" -version = "0.3.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" dependencies = [ "scopeguard", ] @@ -926,7 +1101,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fd13ee2dd61cc82833ba05ade5a30bb3d63f7ced605ef827063c63078302de9" dependencies = [ - "libc 0.2.108", + "libc", ] [[package]] @@ -935,7 +1110,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86dd2487cdfea56def77b88438a2c915fb45113c5319bfe7e14306ca4cd0b0e1" dependencies = [ - "libc 0.2.108", + "libc", ] [[package]] @@ -997,7 +1172,7 @@ version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" dependencies = [ - "libc 0.2.108", + "libc", ] [[package]] @@ -1018,8 +1193,17 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" dependencies = [ - "libc 0.2.108", - "winapi", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "memmap2" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b70ca2a6103ac8b665dc150b142ef0e4e89df640c9e6cf295d189c3caebe5a" +dependencies = [ + "libc", ] [[package]] @@ -1065,6 +1249,105 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow", + "net2", + "slab", + "winapi 0.2.8", +] + +[[package]] +name = "mio-extras" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" +dependencies = [ + "lazycell", + "log", + "mio", + "slab", +] + +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + +[[package]] +name = "ndk" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eb167c1febed0a496639034d0c76b3b74263636045db5489eee52143c246e73" +dependencies = [ + "jni-sys", + "ndk-sys", + "num_enum", + "thiserror", +] + +[[package]] +name = "ndk-glue" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdf399b8b7a39c6fb153c4ec32c72fd5fe789df24a647f229c239aa7adb15241" +dependencies = [ + "lazy_static", + "libc", + "log", + "ndk", + "ndk-macro", + "ndk-sys", +] + +[[package]] +name = "ndk-macro" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d1c6307dc424d0f65b9b06e94f88248e6305726b14729fd67a5e47b2dc481d" +dependencies = [ + "darling", + "proc-macro-crate", + "proc-macro2 1.0.32", + "quote 1.0.10", + "syn", +] + +[[package]] +name = "ndk-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121" + +[[package]] +name = "net2" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + [[package]] name = "nix" version = "0.14.1" @@ -1074,10 +1357,34 @@ dependencies = [ "bitflags", "cc", "cfg-if 0.1.10", - "libc 0.2.108", + "libc", "void", ] +[[package]] +name = "nix" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83450fe6a6142ddd95fb064b746083fc4ef1705fe81f64a64e1d4b39f54a1055" +dependencies = [ + "bitflags", + "cc", + "cfg-if 0.1.10", + "libc", +] + +[[package]] +name = "nix" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" +dependencies = [ + "bitflags", + "cc", + "cfg-if 1.0.0", + "libc", +] + [[package]] name = "nix" version = "0.23.0" @@ -1087,7 +1394,7 @@ dependencies = [ "bitflags", "cc", "cfg-if 1.0.0", - "libc 0.2.108", + "libc", "memoffset 0.6.4", ] @@ -1197,7 +1504,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" dependencies = [ "hermit-abi", - "libc 0.2.108", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca565a7df06f3d4b485494f25ba05da1435950f4dc263440eda7a6fa9b8e36e4" +dependencies = [ + "derivative", + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffa5a33ddddfee04c0283a7653987d634e880347e96b5b2ed64de07efb59db9d" +dependencies = [ + "proc-macro-crate", + "proc-macro2 1.0.32", + "quote 1.0.10", + "syn", ] [[package]] @@ -1238,6 +1567,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "once_cell" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" + [[package]] name = "opaque-debug" version = "0.3.0" @@ -1262,30 +1597,38 @@ dependencies = [ "shared_library", ] +[[package]] +name = "owned_ttf_parser" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f923fb806c46266c02ab4a5b239735c144bdeda724a50ed058e5226f594cde3" +dependencies = [ + "ttf-parser", +] + [[package]] name = "parking_lot" -version = "0.9.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ + "instant", "lock_api", "parking_lot_core", - "rustc_version", ] [[package]] name = "parking_lot_core" -version = "0.6.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ - "cfg-if 0.1.10", - "cloudabi", - "libc 0.2.108", - "redox_syscall 0.1.57", - "rustc_version", - "smallvec 0.6.14", - "winapi", + "cfg-if 1.0.0", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi 0.3.9", ] [[package]] @@ -1311,24 +1654,24 @@ dependencies = [ [[package]] name = "piston-float" -version = "0.3.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b058c3a640efd4bcf63266512e4bb03187192c1b29edd38b16d5a014613e3199" +checksum = "ad78bf43dcf80e8f950c92b84f938a0fc7590b7f6866fbcbeca781609c115590" [[package]] name = "piston-viewport" -version = "0.5.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d96dd995f7dabe6d57cda668ec0fda39d6fe6e1e0b23f772582f383f2013611" +checksum = "12cd38d4259b30d42eaea6a35191feba5b0b4758dbbacc21dee8c223a3a7898a" dependencies = [ "piston-float", ] [[package]] name = "pistoncore-input" -version = "0.24.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c612ce242c7bac8e96426a0ca34275fd980af440f0cca7c6c0e840ef8a4052f" +checksum = "2977fed6eb16c554fd445a09a50c8a0c250f4c50f752be46a7bd9dcc5ba471f0" dependencies = [ "bitflags", "piston-viewport", @@ -1364,12 +1707,11 @@ checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c" [[package]] name = "plotters-conrod" version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76964b0aa3b1dac37fe3c6716a78b559ca0b2ded37dcbfb90fa7df8e913ab563" +source = "git+https://github.com/dsferruzza/plotters-conrod?branch=conrod0.71-glium0.28-winit0.23#00a9e017221865dac8cd0937b72202513b24db55" dependencies = [ "cc", "conrod_core", - "libc 0.1.12", + "libc", "num-traits", "plotters-backend", ] @@ -1386,6 +1728,15 @@ dependencies = [ "miniz_oxide 0.3.7", ] +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml", +] + [[package]] name = "proc-macro-hack" version = "0.5.19" @@ -1449,15 +1800,9 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a441a7a6c80ad6473bd4b74ec1c9a4c951794285bf941c2126f607c72e48211" dependencies = [ - "libc 0.2.108", + "libc", ] -[[package]] -name = "redox_syscall" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - [[package]] name = "redox_syscall" version = "0.2.10" @@ -1474,7 +1819,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ "getrandom", - "redox_syscall 0.2.10", + "redox_syscall", ] [[package]] @@ -1557,15 +1902,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] - [[package]] name = "rusttype" version = "0.7.9" @@ -1591,6 +1927,16 @@ dependencies = [ "stb_truetype", ] +[[package]] +name = "rusttype" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc7c727aded0be18c5b80c1640eae0ac8e396abf6fa8477d96cb37d18ee5ec59" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + [[package]] name = "same-file" version = "1.0.6" @@ -1600,6 +1946,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scoped-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" + [[package]] name = "scopeguard" version = "1.1.0" @@ -1612,21 +1964,6 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ac753e6625df1711012c6469644ddd9b6338be1e4abf235c3a8817191411ae1" -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "serde" version = "1.0.130" @@ -1664,7 +2001,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f46209b345401737ae2125fe5b19a77acce90cd53e1658cda928e4fe9a64581" dependencies = [ - "libc 0.2.108", + "libc", ] [[package]] @@ -1674,7 +2011,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f03fbca4c9d866e24a459cbca71283f545a37f8e3e002ad8c70593871453cab7" dependencies = [ "ioctl-rs", - "libc 0.2.108", + "libc", "serial-core", "termios", ] @@ -1685,7 +2022,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15c6d3b776267a75d31bbdfd5d36c0ca051251caafc285827052bc53bcdc8162" dependencies = [ - "libc 0.2.108", + "libc", "serial-core", ] @@ -1703,7 +2040,7 @@ dependencies = [ "mach 0.2.3", "nix 0.14.1", "regex", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1726,17 +2063,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11" dependencies = [ "lazy_static", - "libc 0.2.108", + "libc", ] [[package]] -name = "smallvec" -version = "0.6.14" +name = "slab" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" -dependencies = [ - "maybe-uninit", -] +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" [[package]] name = "smallvec" @@ -1746,35 +2080,37 @@ checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" [[package]] name = "smithay-client-toolkit" -version = "0.4.6" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ccb8c57049b2a34d2cc2b203fa785020ba0129d31920ef0d317430adaf748fa" +checksum = "421c8dc7acf5cb205b88160f8b4cc2c5cfabe210e43b2f80f009f4c1ef910f1d" dependencies = [ - "andrew", + "andrew 0.2.1", "bitflags", - "dlib", + "dlib 0.4.2", "lazy_static", "memmap", "nix 0.14.1", - "wayland-client 0.21.13", - "wayland-commons 0.21.13", - "wayland-protocols 0.21.13", + "wayland-client 0.23.6", + "wayland-protocols 0.23.6", ] [[package]] name = "smithay-client-toolkit" -version = "0.6.6" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "421c8dc7acf5cb205b88160f8b4cc2c5cfabe210e43b2f80f009f4c1ef910f1d" +checksum = "4750c76fd5d3ac95fa3ed80fe667d6a3d8590a960e5b575b98eea93339a80b80" dependencies = [ - "andrew", + "andrew 0.3.1", "bitflags", - "dlib", + "calloop", + "dlib 0.4.2", "lazy_static", - "memmap", - "nix 0.14.1", - "wayland-client 0.23.6", - "wayland-protocols 0.23.6", + "log", + "memmap2", + "nix 0.18.0", + "wayland-client 0.28.6", + "wayland-cursor", + "wayland-protocols 0.28.6", ] [[package]] @@ -1796,6 +2132,12 @@ dependencies = [ "byteorder", ] +[[package]] +name = "strsim" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" + [[package]] name = "syn" version = "1.0.81" @@ -1816,13 +2158,19 @@ dependencies = [ "nix 0.23.0", ] +[[package]] +name = "takeable-option" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36ae8932fcfea38b7d3883ae2ab357b0d57a02caaa18ebb4f5ece08beaec4aa0" + [[package]] name = "termios" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5d9cf598a6d7ce700a4e6a9199da127e6819a61e64b68609683cc9a01b5683a" dependencies = [ - "libc 0.2.108", + "libc", ] [[package]] @@ -1860,9 +2208,9 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ - "libc 0.2.108", + "libc", "wasi", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1880,6 +2228,12 @@ dependencies = [ "serde", ] +[[package]] +name = "ttf-parser" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e5d7cd7ab3e47dda6e56542f4bbf3824c15234958c6e1bd6aaa347e93499fdc" + [[package]] name = "type-map" version = "0.4.0" @@ -1950,7 +2304,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" dependencies = [ "same-file", - "winapi", + "winapi 0.3.9", "winapi-util", ] @@ -2016,65 +2370,76 @@ checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" [[package]] name = "wayland-client" -version = "0.21.13" +version = "0.23.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49963e5f9eeaf637bfcd1b9f0701c99fd5cd05225eb51035550d4272806f2713" +checksum = "af1080ebe0efabcf12aef2132152f616038f2d7dcbbccf7b2d8c5270fe14bcda" dependencies = [ "bitflags", "downcast-rs", - "libc 0.2.108", + "libc", "nix 0.14.1", - "wayland-commons 0.21.13", - "wayland-scanner 0.21.13", - "wayland-sys 0.21.13", + "wayland-commons 0.23.6", + "wayland-scanner 0.23.6", + "wayland-sys 0.23.6", ] [[package]] name = "wayland-client" -version = "0.23.6" +version = "0.28.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1080ebe0efabcf12aef2132152f616038f2d7dcbbccf7b2d8c5270fe14bcda" +checksum = "e3ab332350e502f159382201394a78e3cc12d0f04db863429260164ea40e0355" dependencies = [ "bitflags", "downcast-rs", - "libc 0.2.108", - "nix 0.14.1", - "wayland-commons 0.23.6", - "wayland-scanner 0.23.6", - "wayland-sys 0.23.6", + "libc", + "nix 0.20.0", + "scoped-tls", + "wayland-commons 0.28.6", + "wayland-scanner 0.28.6", + "wayland-sys 0.28.6", ] [[package]] name = "wayland-commons" -version = "0.21.13" +version = "0.23.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40c08896768b667e1df195d88a62a53a2d1351a1ed96188be79c196b35bb32ec" +checksum = "bb66b0d1a27c39bbce712b6372131c6e25149f03ffb0cd017cf8f7de8d66dbdb" dependencies = [ "nix 0.14.1", - "wayland-sys 0.21.13", + "wayland-sys 0.23.6", ] [[package]] name = "wayland-commons" -version = "0.23.6" +version = "0.28.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb66b0d1a27c39bbce712b6372131c6e25149f03ffb0cd017cf8f7de8d66dbdb" +checksum = "a21817947c7011bbd0a27e11b17b337bfd022e8544b071a2641232047966fbda" dependencies = [ - "nix 0.14.1", - "wayland-sys 0.23.6", + "nix 0.20.0", + "once_cell", + "smallvec", + "wayland-sys 0.28.6", ] [[package]] -name = "wayland-protocols" -version = "0.21.13" +name = "wayland-cursor" +version = "0.28.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afde2ea2a428eee6d7d2c8584fdbe8b82eee8b6c353e129a434cd6e07f42145" +checksum = "be610084edd1586d45e7bdd275fe345c7c1873598caa464c4fb835dee70fa65a" dependencies = [ - "bitflags", - "wayland-client 0.21.13", - "wayland-commons 0.21.13", - "wayland-scanner 0.21.13", - "wayland-sys 0.21.13", + "nix 0.20.0", + "wayland-client 0.28.6", + "xcursor", +] + +[[package]] +name = "wayland-egl" +version = "0.28.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99ba1ab1e18756b23982d36f08856d521d7df45015f404a2d7c4f0b2d2f66956" +dependencies = [ + "wayland-client 0.28.6", + "wayland-sys 0.28.6", ] [[package]] @@ -2090,14 +2455,15 @@ dependencies = [ ] [[package]] -name = "wayland-scanner" -version = "0.21.13" +name = "wayland-protocols" +version = "0.28.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf3828c568714507315ee425a9529edc4a4aa9901409e373e9e0027e7622b79e" +checksum = "286620ea4d803bacf61fa087a4242ee316693099ee5a140796aaba02b29f861f" dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "xml-rs", + "bitflags", + "wayland-client 0.28.6", + "wayland-commons 0.28.6", + "wayland-scanner 0.28.6", ] [[package]] @@ -2112,13 +2478,14 @@ dependencies = [ ] [[package]] -name = "wayland-sys" -version = "0.21.13" +name = "wayland-scanner" +version = "0.28.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520ab0fd578017a0ee2206623ba9ef4afe5e8f23ca7b42f6acfba2f4e66b1628" +checksum = "ce923eb2deb61de332d1f356ec7b6bf37094dc5573952e1c8936db03b54c03f1" dependencies = [ - "dlib", - "lazy_static", + "proc-macro2 1.0.32", + "quote 1.0.10", + "xml-rs", ] [[package]] @@ -2127,8 +2494,19 @@ version = "0.23.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d94e89a86e6d6d7c7c9b19ebf48a03afaac4af6bc22ae570e9a24124b75358f4" dependencies = [ - "dlib", + "dlib 0.4.2", + "lazy_static", +] + +[[package]] +name = "wayland-sys" +version = "0.28.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d841fca9aed7febf9bed2e9796c49bf58d4152ceda8ac949ebe00868d8f0feb8" +dependencies = [ + "dlib 0.5.0", "lazy_static", + "pkg-config", ] [[package]] @@ -2141,6 +2519,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + [[package]] name = "winapi" version = "0.3.9" @@ -2151,6 +2535,12 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -2163,7 +2553,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2174,29 +2564,45 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "winit" -version = "0.19.5" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e96eb4bb472fa43e718e8fa4aef82f86cd9deac9483a1e1529230babdb394a8" +checksum = "b5bc559da567d8aa671bbcd08304d49e982c7bf2cb91e10288b9188931c1b772" dependencies = [ - "android_glue", - "backtrace", "bitflags", "cocoa", - "core-foundation", - "core-graphics", + "core-foundation 0.9.2", + "core-graphics 0.22.3", + "core-video-sys", + "dispatch", + "instant", "lazy_static", - "libc 0.2.108", + "libc", "log", + "mio", + "mio-extras", + "ndk", + "ndk-glue", + "ndk-sys", "objc", "parking_lot", "percent-encoding", "raw-window-handle", - "smithay-client-toolkit 0.4.6", - "wayland-client 0.21.13", - "winapi", + "smithay-client-toolkit 0.12.3", + "wayland-client 0.28.6", + "winapi 0.3.9", "x11-dl", ] +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "x11-clipboard" version = "0.5.3" @@ -2213,7 +2619,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59" dependencies = [ "lazy_static", - "libc 0.2.108", + "libc", "pkg-config", ] @@ -2223,11 +2629,20 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "771e2b996df720cd1c6dd9ff90f62d91698fd3610cc078388d0564bdd6622a9c" dependencies = [ - "libc 0.2.108", + "libc", "log", "quick-xml", ] +[[package]] +name = "xcursor" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7" +dependencies = [ + "nom", +] + [[package]] name = "xdg" version = "2.4.0" diff --git a/Cargo.toml b/Cargo.toml index 03d2493..b78cdf9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,14 +29,14 @@ fluent = "0.16" intl-memoizer = "0.5" unic-langid = "0.9" inflate = "0.4" -winit = "0.19" +winit = "0.23" image = { version = "0.23", default-features = false, features = ["png"] } -glium = "0.24" +glium = "0.28" plotters = { version = "0.3", default_features = false, features = ["chrono", "area_series"] } -plotters-conrod = "0.3" -conrod_glium = "0.70" -conrod_winit = "0.70" -conrod_core = "0.70" +plotters-conrod = { git = "https://github.com/dsferruzza/plotters-conrod", branch = "conrod0.71-glium0.28-winit0.23" } +conrod_glium = "0.71" +conrod_winit = "0.71" +conrod_core = "0.71" sysfs_gpio = { version = "0.6", optional = true } rn2903 = { git = "https://github.com/waxzce/lora-rust-rn2903-rn2483.git", rev = "b086057ba096920abef3870ad0cefa2c80a343e2", optional = true } makair-telemetry = { git = "https://github.com/makers-for-life/makair-telemetry", rev = "184185d4301fa7343018cd6733e1fb23e2cb032e", default-features = false, features = ["serial"] } diff --git a/src/display/drawer.rs b/src/display/drawer.rs index 442df17..0aa76b2 100644 --- a/src/display/drawer.rs +++ b/src/display/drawer.rs @@ -8,7 +8,10 @@ use std::sync::mpsc::{Receiver, Sender}; use std::time::{Duration, Instant}; use conrod_core::Ui; -use glium::glutin::{ContextBuilder, EventsLoop, WindowBuilder}; +use glium::glutin::event::{Event, KeyboardInput, VirtualKeyCode, WindowEvent}; +use glium::glutin::event_loop::{ControlFlow, EventLoop}; +use glium::glutin::window::WindowBuilder; +use glium::glutin::{ContextBuilder, ContextCurrentState}; use glium::{texture, Surface}; use makair_telemetry::{self, TelemetryChannelType}; @@ -18,10 +21,9 @@ use crate::config::environment::*; use crate::serial::poller::{PollEvent, SerialPoller, SerialPollerBuilder}; use crate::APP_ARGS; -use super::events::{DisplayEventsBuilder, DisplayEventsHandleOutcome}; use super::fonts::Fonts; use super::identifiers::{Ids, ImageIds}; -use super::renderer::{DisplayRenderer, DisplayRendererBuilder}; +use super::renderer::DisplayRendererBuilder; use super::support::GliumDisplayWinitWrapper; const FRAMERATE_SLEEP_THROTTLE_SMOOTH_HEAVY: Duration = @@ -34,33 +36,21 @@ const FRAMERATE_SLEEP_THROTTLE_MINIMUM: Duration = Duration::from_millis(10); const FORCE_REFRESH_INACTIVE_PERIOD: Duration = Duration::from_secs(5); -pub struct DisplayDrawerBuilder<'a> { - _phantom: &'a std::marker::PhantomData, -} - -pub struct DisplayDrawer<'a> { - renderer: DisplayRenderer, - glium_renderer: conrod_glium::Renderer, - display: GliumDisplayWinitWrapper, - interface: &'a mut Ui, - events_loop: EventsLoop, - image_map: conrod_core::image::Map, - chip: Chip, -} +pub struct DisplayDrawer; -impl<'a> DisplayDrawerBuilder<'a> { - #[allow(clippy::new_ret_no_self)] - pub fn new( - window: WindowBuilder, - context: ContextBuilder, - events_loop: EventsLoop, - mut interface: &'a mut Ui, +impl DisplayDrawer { + pub fn run( + window_builder: WindowBuilder, + context: ContextBuilder, + event_loop: EventLoop, + mut interface: Ui, fonts: Fonts, - chip: Chip, - ) -> DisplayDrawer<'a> { + mut chip: Chip, + ) -> ! { // Create display - let display = - GliumDisplayWinitWrapper(glium::Display::new(window, context, &events_loop).unwrap()); + let display = GliumDisplayWinitWrapper( + glium::Display::new(window_builder, context, &event_loop).unwrap(), + ); // Create widget IDs (simplified to 'IDs') let mut ids = Ids::new(interface.widget_id_generator()); @@ -72,27 +62,16 @@ impl<'a> DisplayDrawerBuilder<'a> { let images = ImageIds::new(&display, &mut image_map); - // Create drawer - DisplayDrawer { - renderer: DisplayRendererBuilder::new(fonts, ids, images), - glium_renderer: conrod_glium::Renderer::new(&display.0).unwrap(), - display, - interface, - events_loop, - image_map, - chip, - } - } -} + let mut renderer = DisplayRendererBuilder::new(fonts, ids, images); + let mut glium_renderer = conrod_glium::Renderer::new(&display.0).unwrap(); + + debug!("window built, will spawn now"); -impl<'a> DisplayDrawer<'a> { - pub fn run(&mut self) { // Create handlers - let (mut serial_poller, mut events_handler) = - (SerialPollerBuilder::new(), DisplayEventsBuilder::new()); + let mut serial_poller = SerialPollerBuilder::new(); // Start gathering telemetry - let rx = self.bind_telemetry(); + let rx = Self::bind_telemetry(&mut chip); // Start drawer loop // Flow: cycles through telemetry events, and refreshes the view every time there is an \ @@ -101,8 +80,9 @@ impl<'a> DisplayDrawer<'a> { let (mut last_chip_state, mut last_refresh, mut last_heartbeat, mut is_first_frame) = (ChipState::WaitingData(now_time), now_time, now_time, true); + let mut window_updated = true; - 'main: loop { + event_loop.run(move |event, _window_target, control_flow| { // Measure loop tick start time // Notice: this will be used to prevent the FPS throttler from skipping frames, as the \ // methods called here may add a bit of overhead time to the final thread sleep \ @@ -112,118 +92,166 @@ impl<'a> DisplayDrawer<'a> { // Receive telemetry data (from the input serial from the motherboard) // Empty the events queue before doing anything else - let has_poll_events = self.poll_telemetry(&mut serial_poller, &rx); + let has_poll_events = Self::poll_telemetry(&mut chip, &mut serial_poller, &rx); - // Handle incoming UI events (ie. from the window, eg. 'ESC' key is pressed) - match events_handler.handle(&self.display, &mut self.interface, &mut self.events_loop) { - DisplayEventsHandleOutcome::Break => break 'main, - DisplayEventsHandleOutcome::Continue => {} + // Handle incoming UI events (ie. from the window) + if let Some(event) = + super::support::convert_event(&event, display.0.gl_window().window()) + { + interface.handle_event(event); + window_updated = true; } - // Catch chip state changes - let mut has_chip_state_change = false; - - if self.chip.state != last_chip_state { - last_chip_state = self.chip.state.to_owned(); + // Break from the loop upon `Escape` or closed window. + if let Event::WindowEvent { event, .. } = &event { + match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + input: + KeyboardInput { + virtual_keycode: Some(VirtualKeyCode::Escape), + .. + }, + .. + } => { + *control_flow = ControlFlow::Exit; + } + _ => (), + } + } else { + match &event { + glium::glutin::event::Event::MainEventsCleared => { + // Catch chip state changes + let mut has_chip_state_change = false; + + if chip.state != last_chip_state { + last_chip_state = chip.state.to_owned(); + + has_chip_state_change = true; + } + + // Run events since the last render + let (has_heartbeat, has_user_events, user_intents, user_events) = renderer + .run_events( + &mut interface, + &mut chip, + &last_heartbeat, + &tick_start_time, + ); + + // Dispatch heartbeat? + // Notice: heartbeats are critical, as they indicate the firmware that the Control UI \ + // is still up and running. If the firmware misses a certain number of heartbeats, \ + // it will think that the Control UI is frozen, and thus will power cycle the \ + // computer that runs it. Note that, while this may look dangerous, heartbeats \ + // should be sent from the drawer loop itself, as this is the main Control UI event \ + // loop. If the Control UI drawer loop freezes, then the Control UI would be \ + // unusable and unresponsive, and thus heartbeats MUST be stopped so that a power \ + // cycle gets triggered by the firmware. + if has_heartbeat { + chip.dispatch_heartbeat_event(); + + last_heartbeat = tick_start_time; + } + + // Refresh UI? (if any event occured, either user-based or poll-based) + // Notice: if this is the first frame, do not wait for an event to occur, refresh \ + // immediately. Only check those if the chip state is stopped, as to minimize \ + // CPU usage when no graph needs to be drawn and animated. + if last_chip_state == ChipState::Running + || has_poll_events + || has_user_events + || has_chip_state_change + || is_first_frame + || last_refresh.elapsed() >= FORCE_REFRESH_INACTIVE_PERIOD + || window_updated + { + window_updated = false; + + // Unstack all user events & intents + if has_user_events { + if !user_intents.is_empty() { + chip.dispatch_settings_intents(user_intents); + } + + if !user_events.is_empty() { + chip.dispatch_settings_events(user_events); + } + } + + // Render screen to an image + renderer.render(&mut interface, &chip); + + // Mark as refreshed now + is_first_frame = false; + last_refresh = tick_start_time; + + // Request a redraw + display.0.gl_window().window().request_redraw(); + } + } + glium::glutin::event::Event::RedrawRequested(_) => { + // A redraw was requested + // Let's see if it is really necessary + if let Some(primitives) = interface.draw_if_changed() { + glium_renderer.fill(&display.0, primitives, &image_map); - has_chip_state_change = true; - } + let mut target = display.0.draw(); - // Run events since the last render - let (has_heartbeat, has_user_events, user_intents, user_events) = - self.renderer.run_events( - &mut self.interface, - &mut self.chip, - &last_heartbeat, - &tick_start_time, - ); - - // Dispatch heartbeat? - // Notice: heartbeats are critical, as they indicate the firmware that the Control UI \ - // is still up and running. If the firmware misses a certain number of heartbeats, \ - // it will think that the Control UI is frozen, and thus will power cycle the \ - // computer that runs it. Note that, while this may look dangerous, heartbeats \ - // should be sent from the drawer loop itself, as this is the main Control UI event \ - // loop. If the Control UI drawer loop freezes, then the Control UI would be \ - // unusable and unresponsive, and thus heartbeats MUST be stopped so that a power \ - // cycle gets triggered by the firmware. - if has_heartbeat { - self.chip.dispatch_heartbeat_event(); - - last_heartbeat = tick_start_time; - } + target.clear_color(0.0, 0.0, 0.0, 1.0); - // Refresh UI? (if any event occured, either user-based or poll-based) - // Notice: if this is the first frame, do not wait for an event to occur, refresh \ - // immediately. Only check those if the chip state is stopped, as to minimize \ - // CPU usage when no graph needs to be drawn and animated. - if last_chip_state == ChipState::Running - || has_poll_events - || has_user_events - || has_chip_state_change - || is_first_frame - || last_refresh.elapsed() >= FORCE_REFRESH_INACTIVE_PERIOD - { - // Unstack all user events & intents - if has_user_events { - if !user_intents.is_empty() { - self.chip.dispatch_settings_intents(user_intents); - } + glium_renderer + .draw(&display.0, &mut target, &image_map) + .unwrap(); - if !user_events.is_empty() { - self.chip.dispatch_settings_events(user_events); + target.finish().unwrap(); + } } + _ => (), } - // Proceed UI refresh? - self.refresh(); - - // Mark as refreshed now - is_first_frame = false; - last_refresh = tick_start_time; - } - - // Measure loop tick total elapsed time - let tick_spent_time = tick_start_time.elapsed(); - - // Limit framerate to 'FRAMERATE_SLEEP_THROTTLE_SMOOTH_HEAVY' or \ - // 'DISPLAY_FRAMERATE_STATIC_LIGHT' (depending on current chip state, as we do not \ - // need as many frames in stopped states; this way we can guarantee the CPU usage \ - // will be minimal, even if something asks for frequent UI refreshes while in \ - // stopped state; also depends on other states like if a settings modal is open) - // Notice #1: limit the speed at the drawer loop is called. If this is not limited, \ - // CPU usage can grow as high as 5% residual under release mode, and 40% residual \ - // under debug mode. - // Notice #2: substract the time it took to perform this loop tick, as to converge to \ - // the real on-screen FPS rate. If this tick took longer than the throttle sleep \ - // time, then fallback on a minimum guaranteed throttle time as to release the \ - // thread for some time. - let mut throttle_sleep_duration = if last_chip_state == ChipState::Running { - // A state requests that framerate should be moderated (lighter middle-ground \ - // between the fast but jerky framerate and the smooth but heavy framerate) - if self.renderer.has_state_moderate_framerate() { - FRAMERATE_SLEEP_THROTTLE_MODERATE_FAST + // Measure loop tick total elapsed time + let tick_spent_time = tick_start_time.elapsed(); + + // Limit framerate to 'FRAMERATE_SLEEP_THROTTLE_SMOOTH_HEAVY' or \ + // 'DISPLAY_FRAMERATE_STATIC_LIGHT' (depending on current chip state, as we do not \ + // need as many frames in stopped states; this way we can guarantee the CPU usage \ + // will be minimal, even if something asks for frequent UI refreshes while in \ + // stopped state; also depends on other states like if a settings modal is open) + // Notice #1: limit the speed at the drawer loop is called. If this is not limited, \ + // CPU usage can grow as high as 5% residual under release mode, and 40% residual \ + // under debug mode. + // Notice #2: substract the time it took to perform this loop tick, as to converge to \ + // the real on-screen FPS rate. If this tick took longer than the throttle sleep \ + // time, then fallback on a minimum guaranteed throttle time as to release the \ + // thread for some time. + let mut throttle_sleep_duration = if last_chip_state == ChipState::Running { + // A state requests that framerate should be moderated (lighter middle-ground \ + // between the fast but jerky framerate and the smooth but heavy framerate) + if renderer.has_state_moderate_framerate() { + FRAMERATE_SLEEP_THROTTLE_MODERATE_FAST + } else { + FRAMERATE_SLEEP_THROTTLE_SMOOTH_HEAVY + } } else { - FRAMERATE_SLEEP_THROTTLE_SMOOTH_HEAVY - } - } else { - FRAMERATE_SLEEP_THROTTLE_JERKY_FAST - }; + FRAMERATE_SLEEP_THROTTLE_JERKY_FAST + }; + + throttle_sleep_duration = if throttle_sleep_duration > tick_spent_time { + max( + throttle_sleep_duration - tick_spent_time, + FRAMERATE_SLEEP_THROTTLE_MINIMUM, + ) + } else { + FRAMERATE_SLEEP_THROTTLE_MINIMUM + }; - if throttle_sleep_duration > tick_spent_time { - throttle_sleep_duration = max( - throttle_sleep_duration - tick_spent_time, - FRAMERATE_SLEEP_THROTTLE_MINIMUM, - ); - } else { - throttle_sleep_duration = FRAMERATE_SLEEP_THROTTLE_MINIMUM; + *control_flow = ControlFlow::WaitUntil(Instant::now() + throttle_sleep_duration); } - - std::thread::sleep(throttle_sleep_duration); - } + }) } - fn bind_telemetry(&mut self) -> Receiver { + fn bind_telemetry(chip: &mut Chip) -> Receiver { // Start gathering telemetry let (tx, rx): (Sender, Receiver) = std::sync::mpsc::channel(); @@ -248,7 +276,7 @@ impl<'a> DisplayDrawer<'a> { std::io::BufWriter::new(file) }); - let settings_receiver = self.chip.init_settings_receiver(); + let settings_receiver = chip.init_settings_receiver(); std::thread::spawn(move || { makair_telemetry::gather_telemetry( @@ -273,7 +301,7 @@ impl<'a> DisplayDrawer<'a> { let mut simulator = makair_simulator::MakAirSimulator::new(tx); simulator.initialize(); - let settings_receiver = self.chip.init_settings_receiver(); + let settings_receiver = chip.init_settings_receiver(); std::thread::spawn(move || { while let Ok(message) = settings_receiver.recv() { simulator.send_control_message(message); @@ -286,7 +314,7 @@ impl<'a> DisplayDrawer<'a> { } fn poll_telemetry( - &mut self, + chip: &mut Chip, poller: &mut SerialPoller, rx: &Receiver, ) -> bool { @@ -297,20 +325,20 @@ impl<'a> DisplayDrawer<'a> { Ok(PollEvent::Ready(event)) => { // Do we need to mark this event as resulting in an UI update? (due to an \ // internal data point having been updated) - if self.chip.new_event(event) == ChipEventUpdate::May { + if chip.new_event(event) == ChipEventUpdate::May { has_poll_events = true; } } Ok(PollEvent::Corrupted(error)) => { // Handle unrecoverable corruption errors - self.chip.new_telemetry_error(error); + chip.new_telemetry_error(error); break 'poll_serial; } Ok(PollEvent::Pending) => break 'poll_serial, Err(error) => { // Handle unrecoverable core errors - self.chip.new_core_error(error); + chip.new_core_error(error); break 'poll_serial; } @@ -319,25 +347,4 @@ impl<'a> DisplayDrawer<'a> { has_poll_events } - - fn refresh(&mut self) { - // Render screen to an image - self.renderer.render(&mut self.interface, &self.chip); - - // Draw interface if it changed - if let Some(primitives) = self.interface.draw_if_changed() { - self.glium_renderer - .fill(&self.display.0, primitives, &self.image_map); - - let mut target = self.display.0.draw(); - - target.clear_color(0.0, 0.0, 0.0, 1.0); - - self.glium_renderer - .draw(&self.display.0, &mut target, &self.image_map) - .unwrap(); - - target.finish().unwrap(); - } - } } diff --git a/src/display/events.rs b/src/display/events.rs index 19bf28e..a46f98c 100644 --- a/src/display/events.rs +++ b/src/display/events.rs @@ -6,7 +6,6 @@ use std::time::Duration; use conrod_core::{widget::Id as WidgetId, Ui}; -use glium::glutin::{Event, EventsLoop, KeyboardInput, WindowEvent}; use crate::chip::{ settings::{ @@ -23,68 +22,11 @@ use crate::chip::{ use super::identifiers::Ids; use super::renderer::{DisplayRendererSettingsStateVisibility, DisplayRendererStates}; -use super::support::{self, EventLoop, GliumDisplayWinitWrapper}; const FORCED_CLICKS_PRESET_SETTINGS_OPEN_DEBOUNCE_DELAY: Duration = Duration::from_secs(5); -pub struct DisplayEventsBuilder; - -pub struct DisplayEvents { - event_loop: EventLoop, -} - pub struct DisplayUiEvents; -pub enum DisplayEventsHandleOutcome { - Break, - Continue, -} - -#[allow(clippy::new_ret_no_self)] -impl DisplayEventsBuilder { - pub fn new() -> DisplayEvents { - DisplayEvents { - event_loop: EventLoop::new(), - } - } -} - -impl DisplayEvents { - pub fn handle( - &mut self, - display: &GliumDisplayWinitWrapper, - interface: &mut Ui, - mut events_loop: &mut EventsLoop, - ) -> DisplayEventsHandleOutcome { - for event in self.event_loop.next(&mut events_loop) { - // Use the `winit` backend feature to convert the winit event to a conrod one. - if let Some(event) = support::convert_event(event.clone(), display) { - interface.handle_event(event); - } - - // Break from the loop upon `Escape` or closed window. - if let Event::WindowEvent { event, .. } = event.clone() { - match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - input: - KeyboardInput { - virtual_keycode: Some(glium::glutin::VirtualKeyCode::Escape), - .. - }, - .. - } => { - return DisplayEventsHandleOutcome::Break; - } - _ => (), - } - } - } - - DisplayEventsHandleOutcome::Continue - } -} - impl DisplayUiEvents { pub fn run( interface: &mut Ui, diff --git a/src/display/support.rs b/src/display/support.rs index 4854a70..932ef7d 100644 --- a/src/display/support.rs +++ b/src/display/support.rs @@ -6,37 +6,18 @@ use conrod_winit::WinitWindow; pub struct GliumDisplayWinitWrapper(pub glium::Display); -pub struct EventLoop; impl WinitWindow for GliumDisplayWinitWrapper { fn get_inner_size(&self) -> Option<(u32, u32)> { - self.0.gl_window().get_inner_size().map(Into::into) + let s = self.0.gl_window().window().inner_size(); + Some((s.width, s.height)) } fn hidpi_factor(&self) -> f32 { - self.0.gl_window().get_hidpi_factor() as _ - } -} - -impl EventLoop { - pub fn new() -> Self { - EventLoop {} - } - - /// Produce an iterator yielding all available events. - pub fn next( - &mut self, - events_loop: &mut glium::glutin::EventsLoop, - ) -> Vec { - // Collect all pending events. - let mut events = Vec::new(); - - events_loop.poll_events(|event| events.push(event)); - - events + self.0.gl_window().window().scale_factor() as f32 } } // Conversion functions for converting between types from glium's version of `winit` and \ // `conrod_core`. -conrod_winit::conversion_fns!(); +conrod_winit::v023_conversion_fns!(); diff --git a/src/display/window.rs b/src/display/window.rs index 747a38b..9692b2c 100644 --- a/src/display/window.rs +++ b/src/display/window.rs @@ -4,10 +4,12 @@ // License: Public Domain License use conrod_core::UiBuilder; -use glium::glutin::Icon; -use glium::glutin::{ContextBuilder, EventsLoop, GlProfile, WindowBuilder}; +use glium::glutin::event_loop::EventLoop; +use glium::glutin::window::{Fullscreen, Icon, WindowBuilder}; +use glium::glutin::{ContextBuilder, GlProfile}; use image::load_from_memory; use inflate::inflate_bytes_zlib; +use winit::dpi::LogicalSize; use crate::chip::Chip; use crate::config::environment::*; @@ -17,7 +19,7 @@ use crate::EmbeddedFontsDefault; use crate::EmbeddedImages; use crate::APP_ARGS; -use super::drawer::DisplayDrawerBuilder; +use super::drawer::DisplayDrawer; use super::fonts::Fonts; pub struct DisplayWindowBuilder; @@ -53,11 +55,11 @@ lazy_static! { } impl DisplayWindow { - pub fn spawn(&self, chip: Chip) { + pub fn spawn(&self, chip: Chip) -> ! { debug!("spawning window..."); // Create event loop - let events_loop = EventsLoop::new(); + let event_loop = EventLoop::new(); // Create window let window = WindowBuilder::new() @@ -70,15 +72,18 @@ impl DisplayWindow { ) .unwrap(), )) - .with_dimensions((DISPLAY_WINDOW_SIZE_WIDTH, DISPLAY_WINDOW_SIZE_HEIGHT).into()) + .with_inner_size(LogicalSize::new( + DISPLAY_WINDOW_SIZE_WIDTH, + DISPLAY_WINDOW_SIZE_HEIGHT, + )) .with_decorations(!APP_ARGS.fullscreen) .with_resizable(false) .with_always_on_top(APP_ARGS.fullscreen); let window = if APP_ARGS.fullscreen { - let primary_monitor = events_loop.get_primary_monitor(); + let primary_monitor = event_loop.primary_monitor(); - window.with_fullscreen(Some(primary_monitor)) + window.with_fullscreen(Some(Fullscreen::Borderless(primary_monitor))) } else { window }; @@ -116,12 +121,7 @@ impl DisplayWindow { ), }; - // Create window contents drawer - let mut drawer = - DisplayDrawerBuilder::new(window, context, events_loop, &mut interface, fonts, chip); - - debug!("window built, will spawn now"); - - drawer.run(); + // Create and run window contents drawer + DisplayDrawer::run(window, context, event_loop, interface, fonts, chip) } } diff --git a/src/main.rs b/src/main.rs index 074195c..ba70edb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -126,6 +126,4 @@ fn main() { // Spawn window manager DisplayWindowBuilder::new().spawn(chip); - - info!("stopped"); } From 3278121912a3d2e63e6c05bece570fcf721fa0fe Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Fri, 26 Nov 2021 18:40:09 +0100 Subject: [PATCH 07/29] Do not start breathing automatically when initializing the simulator --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/display/drawer.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 83f1848..6e50966 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1146,7 +1146,7 @@ dependencies = [ [[package]] name = "makair-simulator" version = "0.1.0" -source = "git+https://github.com/makers-for-life/makair-simulator?rev=9cba9863592791f2d6bcd36fcfc9103d552243f1#9cba9863592791f2d6bcd36fcfc9103d552243f1" +source = "git+https://github.com/makers-for-life/makair-simulator?rev=59bf7bce05ee26075e126753a74ebebf00c5bfb0#59bf7bce05ee26075e126753a74ebebf00c5bfb0" dependencies = [ "cc", "log", diff --git a/Cargo.toml b/Cargo.toml index b78cdf9..1060102 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,7 @@ conrod_core = "0.71" sysfs_gpio = { version = "0.6", optional = true } rn2903 = { git = "https://github.com/waxzce/lora-rust-rn2903-rn2483.git", rev = "b086057ba096920abef3870ad0cefa2c80a343e2", optional = true } makair-telemetry = { git = "https://github.com/makers-for-life/makair-telemetry", rev = "184185d4301fa7343018cd6733e1fb23e2cb032e", default-features = false, features = ["serial"] } -makair-simulator = { git = "https://github.com/makers-for-life/makair-simulator", rev = "9cba9863592791f2d6bcd36fcfc9103d552243f1", optional = true } +makair-simulator = { git = "https://github.com/makers-for-life/makair-simulator", rev = "59bf7bce05ee26075e126753a74ebebf00c5bfb0", optional = true } [features] default = [] diff --git a/src/display/drawer.rs b/src/display/drawer.rs index 0aa76b2..3877cfb 100644 --- a/src/display/drawer.rs +++ b/src/display/drawer.rs @@ -299,7 +299,7 @@ impl DisplayDrawer { #[cfg(feature = "simulator")] RunMode::Simulator => { let mut simulator = makair_simulator::MakAirSimulator::new(tx); - simulator.initialize(); + simulator.initialize(false); let settings_receiver = chip.init_settings_receiver(); std::thread::spawn(move || { From f92a75c0e005299e07a74994c81b3fda34b35dc0 Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Fri, 26 Nov 2021 21:25:38 +0100 Subject: [PATCH 08/29] Update dependencies --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e50966..0fdc727 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1707,7 +1707,7 @@ checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c" [[package]] name = "plotters-conrod" version = "0.3.11" -source = "git+https://github.com/dsferruzza/plotters-conrod?branch=conrod0.71-glium0.28-winit0.23#00a9e017221865dac8cd0937b72202513b24db55" +source = "git+https://github.com/dsferruzza/plotters-conrod?branch=conrod0.71-glium0.28-winit0.23#1e4da66691550584d9e1a2351d400513739269b9" dependencies = [ "cc", "conrod_core", @@ -2140,9 +2140,9 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" [[package]] name = "syn" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" dependencies = [ "proc-macro2 1.0.32", "quote 1.0.10", From 743fba7519f56fbcfa1b8960dec2ace4bb5ce245 Mon Sep 17 00:00:00 2001 From: Gabriel Moneyron Date: Fri, 26 Nov 2021 22:41:58 +0100 Subject: [PATCH 09/29] UI for simulator tab in advanced settings --- res/locales/de.ftl | 8 ++ res/locales/en.ftl | 9 ++ res/locales/es.ftl | 9 ++ res/locales/fr.ftl | 9 ++ res/locales/it.ftl | 9 ++ res/locales/lv.ftl | 9 ++ res/locales/pt.ftl | 8 ++ res/locales/ru.ftl | 8 ++ res/locales/uk.ftl | 8 ++ res/locales/zh.ftl | 8 ++ src/chip/settings/advanced.rs | 87 ++++++++++++++++ src/config/environment.rs | 2 +- src/display/events.rs | 171 ++++++++++++++++++++++++++++++++ src/display/identifiers.rs | 50 ++++++++++ src/display/screen.rs | 10 +- src/locale/advanced.rs | 1 + src/widget/advanced_settings.rs | 78 +++++++++++++++ 17 files changed, 482 insertions(+), 2 deletions(-) diff --git a/res/locales/de.ftl b/res/locales/de.ftl index f319aed..0e06209 100644 --- a/res/locales/de.ftl +++ b/res/locales/de.ftl @@ -54,6 +54,7 @@ mode-group-alarms = Alarm advanced-group-statistics = Statistiken advanced-group-settings = Optionen +advanced-group-simulator = Simulator modal-close = Schließen modal-apply = Anwenden @@ -105,6 +106,13 @@ modal-advanced-date = Datum modal-advanced-time = Zeit modal-advanced-timezone = Zeitzone +modal-advanced-simulator-airway-resistance = Resistance +modal-advanced-simulator-airway-compliance = Compliance +modal-advanced-simulator-spontaneous-breath-rate = Breath rate +modal-advanced-simulator-spontaneous-breath-effort = Breath effort +modal-advanced-simulator-spontaneous-breath-duration = Breath duration +modal-advanced-simulator-acceleration-factor = Acceleration factor + initializing-connecting = Inbetriebnahme... initializing-connected = Initialisierung... diff --git a/res/locales/en.ftl b/res/locales/en.ftl index e4a4f46..8d9f8fb 100644 --- a/res/locales/en.ftl +++ b/res/locales/en.ftl @@ -54,6 +54,7 @@ mode-group-alarms = Alarms advanced-group-statistics = Statistics advanced-group-settings = Settings +advanced-group-simulator = Simulator modal-close = Close modal-apply = Apply @@ -105,6 +106,14 @@ modal-advanced-date = Date modal-advanced-time = Time modal-advanced-timezone = Timezone +modal-advanced-simulator-airway-resistance = Resistance +modal-advanced-simulator-airway-compliance = Compliance +modal-advanced-simulator-spontaneous-breath-rate = Breath rate +modal-advanced-simulator-spontaneous-breath-effort = Breath effort +modal-advanced-simulator-spontaneous-breath-duration = Breath duration +modal-advanced-simulator-acceleration-factor = Acceleration factor + + initializing-connecting = Starting up... initializing-connected = Initializing... diff --git a/res/locales/es.ftl b/res/locales/es.ftl index cbd82bf..23a99dc 100644 --- a/res/locales/es.ftl +++ b/res/locales/es.ftl @@ -54,6 +54,8 @@ mode-group-alarms = Alarmas advanced-group-statistics = Estadísticas advanced-group-settings = Configuraciones +advanced-group-simulator = Simulator + modal-close = Cerca modal-apply = Aplicar @@ -105,6 +107,13 @@ modal-advanced-date = Fecha modal-advanced-time = Hora modal-advanced-timezone = Zona horaria +modal-advanced-simulator-airway-resistance = Resistance +modal-advanced-simulator-airway-compliance = Compliance +modal-advanced-simulator-spontaneous-breath-rate = Breath rate +modal-advanced-simulator-spontaneous-breath-effort = Breath effort +modal-advanced-simulator-spontaneous-breath-duration = Breath duration +modal-advanced-simulator-acceleration-factor = Acceleration factor + initializing-connecting = Empezando... initializing-connected = Inicializando... diff --git a/res/locales/fr.ftl b/res/locales/fr.ftl index 847557e..8a78994 100644 --- a/res/locales/fr.ftl +++ b/res/locales/fr.ftl @@ -54,6 +54,8 @@ mode-group-alarms = Alarmes advanced-group-statistics = Statistiques advanced-group-settings = Paramètres +advanced-group-simulator = Simulator + modal-close = Fermer modal-apply = Valider @@ -105,6 +107,13 @@ modal-advanced-date = Date modal-advanced-time = Heure modal-advanced-timezone = Fuseau horaire +modal-advanced-simulator-airway-resistance = Resistance +modal-advanced-simulator-airway-compliance = Compliance +modal-advanced-simulator-spontaneous-breath-rate = Breath rate +modal-advanced-simulator-spontaneous-breath-effort = Breath effort +modal-advanced-simulator-spontaneous-breath-duration = Breath duration +modal-advanced-simulator-acceleration-factor = Acceleration factor + initializing-connecting = Démarrage en cours... initializing-connected = Préparation en cours... diff --git a/res/locales/it.ftl b/res/locales/it.ftl index 3a894de..bbfe88e 100644 --- a/res/locales/it.ftl +++ b/res/locales/it.ftl @@ -54,6 +54,8 @@ mode-group-alarms = Allarmi advanced-group-statistics = Statistiche advanced-group-settings = Impostazioni +advanced-group-simulator = Simulator + modal-close = Cerca modal-apply = Aplicar @@ -105,6 +107,13 @@ modal-advanced-date = Data modal-advanced-time = Tempo modal-advanced-timezone = Fuso orario +modal-advanced-simulator-airway-resistance = Resistance +modal-advanced-simulator-airway-compliance = Compliance +modal-advanced-simulator-spontaneous-breath-rate = Breath rate +modal-advanced-simulator-spontaneous-breath-effort = Breath effort +modal-advanced-simulator-spontaneous-breath-duration = Breath duration +modal-advanced-simulator-acceleration-factor = Acceleration factor + initializing-connecting = Cominciando... initializing-connected = Inizializzazione in corso... diff --git a/res/locales/lv.ftl b/res/locales/lv.ftl index b6ee5f7..226c8eb 100644 --- a/res/locales/lv.ftl +++ b/res/locales/lv.ftl @@ -54,6 +54,8 @@ mode-group-alarms = Signāli advanced-group-statistics = Statistika advanced-group-settings = Iestatījumi +advanced-group-simulator = Simulator + modal-close = Aizvērt modal-apply = Piesakies @@ -105,6 +107,13 @@ modal-advanced-date = Datums modal-advanced-time = Laiks modal-advanced-timezone = Laika zona +modal-advanced-simulator-airway-resistance = Resistance +modal-advanced-simulator-airway-compliance = Compliance +modal-advanced-simulator-spontaneous-breath-rate = Breath rate +modal-advanced-simulator-spontaneous-breath-effort = Breath effort +modal-advanced-simulator-spontaneous-breath-duration = Breath duration +modal-advanced-simulator-acceleration-factor = Acceleration factor + initializing-connecting = Notiek palaišana... initializing-connected = Notiek inicializēšana... diff --git a/res/locales/pt.ftl b/res/locales/pt.ftl index 01c6e05..548bd92 100644 --- a/res/locales/pt.ftl +++ b/res/locales/pt.ftl @@ -54,6 +54,7 @@ mode-group-alarms = Alarmes advanced-group-statistics = Estatisticas advanced-group-settings = Configurações +advanced-group-simulator = Simulator modal-close = Fechar modal-apply = Aplique @@ -105,6 +106,13 @@ modal-advanced-date = Encontro modal-advanced-time = Tempo modal-advanced-timezone = Fuso horário +modal-advanced-simulator-airway-resistance = Resistance +modal-advanced-simulator-airway-compliance = Compliance +modal-advanced-simulator-spontaneous-breath-rate = Breath rate +modal-advanced-simulator-spontaneous-breath-effort = Breath effort +modal-advanced-simulator-spontaneous-breath-duration = Breath duration +modal-advanced-simulator-acceleration-factor = Acceleration factor + initializing-connecting = Começando... initializing-connected = Inicializando... diff --git a/res/locales/ru.ftl b/res/locales/ru.ftl index e52dbbf..3c30da3 100644 --- a/res/locales/ru.ftl +++ b/res/locales/ru.ftl @@ -54,6 +54,7 @@ mode-group-alarms = Будильники advanced-group-statistics = Статистика advanced-group-settings = Настройки +advanced-group-simulator = Simulator modal-close = Закрыть modal-apply = Применять @@ -105,6 +106,13 @@ modal-advanced-date = Свидание modal-advanced-time = Время modal-advanced-timezone = Часовой пояс +modal-advanced-simulator-airway-resistance = Resistance +modal-advanced-simulator-airway-compliance = Compliance +modal-advanced-simulator-spontaneous-breath-rate = Breath rate +modal-advanced-simulator-spontaneous-breath-effort = Breath effort +modal-advanced-simulator-spontaneous-breath-duration = Breath duration +modal-advanced-simulator-acceleration-factor = Acceleration factor + initializing-connecting = Начиная... initializing-connected = Инициализация... diff --git a/res/locales/uk.ftl b/res/locales/uk.ftl index 7bc0143..7028681 100644 --- a/res/locales/uk.ftl +++ b/res/locales/uk.ftl @@ -54,6 +54,7 @@ mode-group-alarms = Сигналізація advanced-group-statistics = Статистика advanced-group-settings = Налаштування +advanced-group-simulator = Simulator modal-close = Закрити modal-apply = Подати заявку @@ -105,6 +106,13 @@ modal-advanced-date = Дата modal-advanced-time = Час modal-advanced-timezone = Часовий пояс +modal-advanced-simulator-airway-resistance = Resistance +modal-advanced-simulator-airway-compliance = Compliance +modal-advanced-simulator-spontaneous-breath-rate = Breath rate +modal-advanced-simulator-spontaneous-breath-effort = Breath effort +modal-advanced-simulator-spontaneous-breath-duration = Breath duration +modal-advanced-simulator-acceleration-factor = Acceleration factor + initializing-connecting = Запуск... initializing-connected = Ініціалізація... diff --git a/res/locales/zh.ftl b/res/locales/zh.ftl index c865ac5..2fbce3e 100644 --- a/res/locales/zh.ftl +++ b/res/locales/zh.ftl @@ -54,6 +54,7 @@ mode-group-alarms = 警报器 advanced-group-statistics = 统计 advanced-group-settings = 设定值 +advanced-group-simulator = Simulator modal-close = 关 modal-apply = 应用 @@ -105,6 +106,13 @@ modal-advanced-date = 日期 modal-advanced-time = 时间 modal-advanced-timezone = 时区 +modal-advanced-simulator-airway-resistance = Resistance +modal-advanced-simulator-airway-compliance = Compliance +modal-advanced-simulator-spontaneous-breath-rate = Breath rate +modal-advanced-simulator-spontaneous-breath-effort = Breath effort +modal-advanced-simulator-spontaneous-breath-duration = Breath duration +modal-advanced-simulator-acceleration-factor = Acceleration factor + initializing-connecting = 启动... initializing-connected = 初始化中... diff --git a/src/chip/settings/advanced.rs b/src/chip/settings/advanced.rs index 569dedd..965ab87 100644 --- a/src/chip/settings/advanced.rs +++ b/src/chip/settings/advanced.rs @@ -11,12 +11,19 @@ use crate::{APP_I18N, APP_SETTINGS}; pub struct SettingsAdvanced { pub group: SettingsAdvancedGroupTab, pub locale: LocaleCode, + pub resistance : i32, + pub compliance : i32, + pub spontaneous_breath_rate : i32, + pub spontaneous_breath_effort : i32, + pub spontaneous_breath_duration : i32, + pub acceleration_factor : f32, } #[derive(Debug, PartialEq)] pub enum SettingsAdvancedGroupTab { Statistics, Settings, + Simulator, } impl SettingsAdvancedGroupTab { @@ -24,6 +31,7 @@ impl SettingsAdvancedGroupTab { match index { 0 => Some(Self::Statistics), 1 => Some(Self::Settings), + 2 => Some(Self::Simulator), _ => None, } } @@ -40,6 +48,12 @@ impl SettingsAdvanced { SettingsAdvanced { group: SettingsAdvancedGroupTab::default(), locale: LocaleCode::from_code(&APP_SETTINGS.read().unwrap().locale).unwrap_or_default(), + resistance : 1, // TODO get value from simulator + compliance : 1, // TODO get value from simulator + spontaneous_breath_rate : 0, // TODO get value from simulator + spontaneous_breath_effort : 0,// TODO get value from simulator + spontaneous_breath_duration : 0,// TODO get value from simulator + acceleration_factor : 1.0,// TODO get value from simulator } } @@ -86,4 +100,77 @@ impl SettingsAdvanced { } } } + + pub fn switch_resistance(&mut self, action: SettingActionRange) { + + let next_resistance = action.to_next_index(self.resistance as _); + // TODO : check if value is allowed and send it to simulator + + if next_resistance as i32 != self.resistance { + self.resistance = next_resistance as i32; + + + } + } + + pub fn switch_compliance(&mut self, action: SettingActionRange) { + + let next_compliance = action.to_next_index(self.compliance as _); + // TODO : check if value is allowed and send it to simulator + + if next_compliance as i32 != self.compliance { + self.compliance = next_compliance as i32; + + + } + } + + pub fn switch_spontaneous_breath_rate(&mut self, action: SettingActionRange) { + + let next_spontaneous_breath_rate = action.to_next_index(self.spontaneous_breath_rate as _); + // TODO : check if value is allowed and send it to simulator + + if next_spontaneous_breath_rate as i32 != self.spontaneous_breath_rate { + self.spontaneous_breath_rate = next_spontaneous_breath_rate as i32; + + + } + } + + pub fn switch_spontaneous_breath_effort(&mut self, action: SettingActionRange) { + + let next_spontaneous_breath_effort = action.to_next_index(self.spontaneous_breath_effort as _); + // TODO : check if value is allowed and send it to simulator + + if next_spontaneous_breath_effort as i32 != self.spontaneous_breath_effort { + self.spontaneous_breath_effort = next_spontaneous_breath_effort as i32; + + + } + } + + pub fn switch_spontaneous_breath_duration(&mut self, action: SettingActionRange) { + + let next_spontaneous_breath_duration = action.to_next_index(self.spontaneous_breath_duration as _); + // TODO : check if value is allowed and send it to simulator + + if next_spontaneous_breath_duration as i32 != self.spontaneous_breath_duration { + self.spontaneous_breath_duration = next_spontaneous_breath_duration as i32; + + + } + } + + pub fn switch_acceleration_factor(&mut self, action: SettingActionRange) { + + let next_acceleration_factor = action.to_next_index(self.acceleration_factor as _); + // TODO : check if value is allowed and send it to simulator + + if next_acceleration_factor as f32 != self.acceleration_factor { + self.acceleration_factor = next_acceleration_factor as f32; + + + } + } + } diff --git a/src/config/environment.rs b/src/config/environment.rs index 3e883dc..cefc01a 100644 --- a/src/config/environment.rs +++ b/src/config/environment.rs @@ -265,7 +265,7 @@ pub const ADVANCED_SETTINGS_LINES_COUNT: usize = 15; pub const ADVANCED_SETTINGS_LINE_MARGIN_TOP: f64 = 8.0; pub const ADVANCED_SETTINGS_LINE_FONT_SIZE: u32 = 14; pub const ADVANCED_SETTINGS_LINE_VALUE_PADDING_LEFT: f64 = 240.0; -pub const ADVANCED_SETTINGS_GROUP_TABS_COUNT: usize = 2; +pub const ADVANCED_SETTINGS_GROUP_TABS_COUNT: usize = 3; pub const ADVANCED_SETTINGS_LINE_VALUE_EMPTY: &str = "--"; pub const MODE_SETTINGS_MODAL_PADDING: f64 = 20.0; diff --git a/src/display/events.rs b/src/display/events.rs index a46f98c..f251901 100644 --- a/src/display/events.rs +++ b/src/display/events.rs @@ -621,6 +621,20 @@ impl DisplayUiEvents { chip.settings.advanced.group = SettingsAdvancedGroupTab::Settings; } }, + + { + "group simulator", + + [ + ids.advanced_group_tab_simulator_button, + ids.advanced_group_tab_simulator_text, + ], + + { + chip.settings.advanced.group = SettingsAdvancedGroupTab::Simulator; + } + }, + { "settings locale previous", @@ -646,7 +660,164 @@ impl DisplayUiEvents { { chip.settings.advanced.switch_locale(SettingActionRange::More); } + }, + + { + "settings resistance previous", + + [ + ids.advanced_field_resistance_less, + ids.advanced_field_resistance_less_text, + ], + + { + chip.settings.advanced.switch_resistance(SettingActionRange::Less); + } + }, + + { + "settings resistance next", + + [ + ids.advanced_field_resistance_more, + ids.advanced_field_resistance_more_text, + ], + + { + chip.settings.advanced.switch_resistance(SettingActionRange::More); + } + }, + + { + "settings compliance previous", + + [ + ids.advanced_field_compliance_less, + ids.advanced_field_compliance_less_text, + ], + + { + chip.settings.advanced.switch_compliance(SettingActionRange::Less); + } + }, + + { + "settings compliance next", + + [ + ids.advanced_field_compliance_more, + ids.advanced_field_compliance_more_text, + ], + + { + chip.settings.advanced.switch_compliance(SettingActionRange::More); + } + }, + + { + "settings spontaneous_breath_rate previous", + + [ + ids.advanced_field_spontaneous_breath_rate_less, + ids.advanced_field_spontaneous_breath_rate_less_text, + ], + + { + chip.settings.advanced.switch_spontaneous_breath_rate(SettingActionRange::Less); + } + }, + + { + "settings spontaneous_breath_rate next", + + [ + ids.advanced_field_spontaneous_breath_rate_more, + ids.advanced_field_spontaneous_breath_rate_more_text, + ], + + { + chip.settings.advanced.switch_spontaneous_breath_rate(SettingActionRange::More); + } + }, + + { + "settings spontaneous_breath_effort previous", + + [ + ids.advanced_field_spontaneous_breath_effort_less, + ids.advanced_field_spontaneous_breath_effort_less_text, + ], + + { + chip.settings.advanced.switch_spontaneous_breath_effort(SettingActionRange::Less); + } + }, + + { + "settings spontaneous_breath_effort next", + + [ + ids.advanced_field_spontaneous_breath_effort_more, + ids.advanced_field_spontaneous_breath_effort_more_text, + ], + + { + chip.settings.advanced.switch_spontaneous_breath_effort(SettingActionRange::More); + } + }, + + { + "settings spontaneous_breath_duration previous", + + [ + ids.advanced_field_spontaneous_breath_duration_less, + ids.advanced_field_spontaneous_breath_duration_less_text, + ], + + { + chip.settings.advanced.switch_spontaneous_breath_duration(SettingActionRange::Less); + } + }, + + { + "settings spontaneous_breath_duration next", + + [ + ids.advanced_field_spontaneous_breath_duration_more, + ids.advanced_field_spontaneous_breath_duration_more_text, + ], + + { + chip.settings.advanced.switch_spontaneous_breath_duration(SettingActionRange::More); + } + }, + + { + "settings acceleration_factor previous", + + [ + ids.advanced_field_acceleration_factor_less, + ids.advanced_field_acceleration_factor_less_text, + ], + + { + chip.settings.advanced.switch_acceleration_factor(SettingActionRange::Less); + } + }, + + { + "settings acceleration_factor next", + + [ + ids.advanced_field_acceleration_factor_more, + ids.advanced_field_acceleration_factor_more_text, + ], + + { + chip.settings.advanced.switch_acceleration_factor(SettingActionRange::More); + } } + }, ); diff --git a/src/display/identifiers.rs b/src/display/identifiers.rs index c2f23d5..c5a63af 100644 --- a/src/display/identifiers.rs +++ b/src/display/identifiers.rs @@ -375,8 +375,10 @@ widget_ids!(pub struct Ids { advanced_form_wrapper, advanced_group_tab_statistics_button, advanced_group_tab_settings_button, + advanced_group_tab_simulator_button, advanced_group_tab_statistics_text, advanced_group_tab_settings_text, + advanced_group_tab_simulator_text, advanced_field_locale_text, advanced_field_locale_value, @@ -386,6 +388,54 @@ widget_ids!(pub struct Ids { advanced_field_locale_less, advanced_field_locale_less_text, + advanced_field_resistance_text, + advanced_field_resistance_value, + advanced_field_resistance_value_wrapper, + advanced_field_resistance_more, + advanced_field_resistance_more_text, + advanced_field_resistance_less, + advanced_field_resistance_less_text, + + advanced_field_compliance_text, + advanced_field_compliance_value, + advanced_field_compliance_value_wrapper, + advanced_field_compliance_more, + advanced_field_compliance_more_text, + advanced_field_compliance_less, + advanced_field_compliance_less_text, + + advanced_field_spontaneous_breath_rate_text, + advanced_field_spontaneous_breath_rate_value, + advanced_field_spontaneous_breath_rate_value_wrapper, + advanced_field_spontaneous_breath_rate_more, + advanced_field_spontaneous_breath_rate_more_text, + advanced_field_spontaneous_breath_rate_less, + advanced_field_spontaneous_breath_rate_less_text, + + advanced_field_spontaneous_breath_effort_text, + advanced_field_spontaneous_breath_effort_value, + advanced_field_spontaneous_breath_effort_value_wrapper, + advanced_field_spontaneous_breath_effort_more, + advanced_field_spontaneous_breath_effort_more_text, + advanced_field_spontaneous_breath_effort_less, + advanced_field_spontaneous_breath_effort_less_text, + + advanced_field_spontaneous_breath_duration_text, + advanced_field_spontaneous_breath_duration_value, + advanced_field_spontaneous_breath_duration_value_wrapper, + advanced_field_spontaneous_breath_duration_more, + advanced_field_spontaneous_breath_duration_more_text, + advanced_field_spontaneous_breath_duration_less, + advanced_field_spontaneous_breath_duration_less_text, + + advanced_field_acceleration_factor_text, + advanced_field_acceleration_factor_value, + advanced_field_acceleration_factor_value_wrapper, + advanced_field_acceleration_factor_more, + advanced_field_acceleration_factor_more_text, + advanced_field_acceleration_factor_less, + advanced_field_acceleration_factor_less_text, + advanced_text_date_text, advanced_text_date_value, diff --git a/src/display/screen.rs b/src/display/screen.rs index ba6d995..e2bc0fa 100644 --- a/src/display/screen.rs +++ b/src/display/screen.rs @@ -972,18 +972,26 @@ impl<'a> Screen<'a> { advanced_group_tab_buttons: [ self.ids.advanced_group_tab_statistics_button, self.ids.advanced_group_tab_settings_button, + self.ids.advanced_group_tab_simulator_button, ], advanced_group_tab_texts: [ self.ids.advanced_group_tab_statistics_text, self.ids.advanced_group_tab_settings_text, + self.ids.advanced_group_tab_simulator_text, ], field_locale_ids: gen_render_advanced_settings_field_ids!(self, locale), - text_date_ids: gen_render_advanced_settings_text_ids!(self, date), text_time_ids: gen_render_advanced_settings_text_ids!(self, time), text_timezone_ids: gen_render_advanced_settings_text_ids!(self, timezone), + + field_resistance_ids: gen_render_advanced_settings_field_ids!(self, resistance), + field_compliance_ids: gen_render_advanced_settings_field_ids!(self, compliance), + field_spontaneous_breath_rate_ids: gen_render_advanced_settings_field_ids!(self, spontaneous_breath_rate), + field_spontaneous_breath_effort_ids: gen_render_advanced_settings_field_ids!(self, spontaneous_breath_effort), + field_spontaneous_breath_duration_ids: gen_render_advanced_settings_field_ids!(self, spontaneous_breath_duration), + field_acceleration_factor_ids: gen_render_advanced_settings_field_ids!(self, acceleration_factor), }, )); } diff --git a/src/locale/advanced.rs b/src/locale/advanced.rs index 6336edd..a132d94 100644 --- a/src/locale/advanced.rs +++ b/src/locale/advanced.rs @@ -11,6 +11,7 @@ pub fn group_tab_to_locale(group_tab: SettingsAdvancedGroupTab) -> String { let locale_key = match group_tab { SettingsAdvancedGroupTab::Statistics => "statistics", SettingsAdvancedGroupTab::Settings => "settings", + SettingsAdvancedGroupTab::Simulator => "simulator", }; APP_I18N.t(&format!("advanced-group-{}", locale_key)) diff --git a/src/widget/advanced_settings.rs b/src/widget/advanced_settings.rs index 3a492c7..4839dfa 100644 --- a/src/widget/advanced_settings.rs +++ b/src/widget/advanced_settings.rs @@ -68,6 +68,14 @@ pub struct Config<'a> { pub text_date_ids: TextWidgetIds, pub text_time_ids: TextWidgetIds, pub text_timezone_ids: TextWidgetIds, + + pub field_resistance_ids: FieldWidgetIds, + pub field_compliance_ids : FieldWidgetIds, + pub field_spontaneous_breath_rate_ids: FieldWidgetIds, + pub field_spontaneous_breath_effort_ids: FieldWidgetIds, + pub field_spontaneous_breath_duration_ids: FieldWidgetIds, + pub field_acceleration_factor_ids: FieldWidgetIds, + } struct Field { @@ -166,6 +174,7 @@ fn form<'a>(master: &mut ControlWidget<'a>, config: &Config, parent_size: (f64, match config.advanced_settings.group { SettingsAdvancedGroupTab::Statistics => form_statistics(master, config), SettingsAdvancedGroupTab::Settings => form_settings(master, config), + SettingsAdvancedGroupTab::Simulator => form_simulator(master, config), } } @@ -387,6 +396,75 @@ fn form_settings<'a>(master: &mut ControlWidget<'a>, config: &Config) { ); } +fn form_simulator<'a>(master: &mut ControlWidget<'a>, config: &Config) { + + draw_field( + 0, + master, + config, + Field { + label_text: APP_I18N.t("modal-advanced-simulator-airway-resistance"), + value_text: config.advanced_settings.resistance.to_string(), + ids: config.field_resistance_ids, + }, + ); + + draw_field( + 1, + master, + config, + Field { + label_text: APP_I18N.t("modal-advanced-simulator-airway-compliance"), + value_text: config.advanced_settings.compliance.to_string(), + ids: config.field_compliance_ids, + }, + ); + + draw_field( + 2, + master, + config, + Field { + label_text: APP_I18N.t("modal-advanced-simulator-spontaneous-breath-rate"), + value_text: config.advanced_settings.spontaneous_breath_rate.to_string(), + ids: config.field_spontaneous_breath_rate_ids, + }, + ); + + draw_field( + 3, + master, + config, + Field { + label_text: APP_I18N.t("modal-advanced-simulator-spontaneous-breath-effort"), + value_text: config.advanced_settings.spontaneous_breath_effort.to_string(), + ids: config.field_spontaneous_breath_effort_ids, + }, + ); + + draw_field( + 4, + master, + config, + Field { + label_text: APP_I18N.t("modal-advanced-simulator-spontaneous-breath-duration"), + value_text: config.advanced_settings.spontaneous_breath_duration.to_string(), + ids: config.field_spontaneous_breath_duration_ids, + }, + ); + + draw_field( + 5, + master, + config, + Field { + label_text: APP_I18N.t("modal-advanced-simulator-acceleration-factor"), + value_text: config.advanced_settings.acceleration_factor.to_string(), + ids: config.field_acceleration_factor_ids, + }, + ); +} + fn draw_field<'a>(index: usize, master: &mut ControlWidget<'a>, config: &Config, field: Field) { // Generate label gen_widget_label_form!( From 0a2d32e3e4528cc34704cc85093055e73fdcd552 Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Fri, 26 Nov 2021 23:00:05 +0100 Subject: [PATCH 10/29] Allow to disable serial support --- Cargo.toml | 5 +++-- README.md | 19 ++++++++++++++++--- src/chip/mod.rs | 41 +++++++++++++++++++++++++---------------- src/config/arguments.rs | 12 ++++++++++++ src/display/drawer.rs | 1 + src/locale/error.rs | 1 + src/serial/poller.rs | 30 +++++++++++++++++++++++------- src/utilities/parse.rs | 1 + 8 files changed, 82 insertions(+), 28 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1060102..c078057 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,13 +39,14 @@ conrod_winit = "0.71" conrod_core = "0.71" sysfs_gpio = { version = "0.6", optional = true } rn2903 = { git = "https://github.com/waxzce/lora-rust-rn2903-rn2483.git", rev = "b086057ba096920abef3870ad0cefa2c80a343e2", optional = true } -makair-telemetry = { git = "https://github.com/makers-for-life/makair-telemetry", rev = "184185d4301fa7343018cd6733e1fb23e2cb032e", default-features = false, features = ["serial"] } +makair-telemetry = { git = "https://github.com/makers-for-life/makair-telemetry", rev = "184185d4301fa7343018cd6733e1fb23e2cb032e", default-features = false } makair-simulator = { git = "https://github.com/makers-for-life/makair-simulator", rev = "59bf7bce05ee26075e126753a74ebebf00c5bfb0", optional = true } [features] -default = [] +default = ["serial"] fonts-cjk = [] lora = ["rn2903", "sysfs_gpio"] +serial = ["makair-telemetry/serial"] simulator = ["makair-simulator"] [profile.dev] diff --git a/README.md b/README.md index 2a75831..3ccd4e9 100644 --- a/README.md +++ b/README.md @@ -121,18 +121,31 @@ _Make sure to replace the `version` script argument with the current release ver **⚠️ Important note: this is still a work in progress. We are near cross-compiling capabilities, though some work still needs to be done due to non-MUSL C-based dependencies. See issue [#38](https://github.com/makers-for-life/makair-control-ui/issues/38).** -## Optional Features +## Compilation Features + +### Default Features + +By default, the Control UI comes with the following features: + +* **Support for telemetry/control over serial:** + * Feature name: `serial` + * Purpose: allow to open a serial device (using `-p [device]` or `--port [device]`) in order to get telemetry data from it and send control messages to it. + +It is possible to disable all default features at once by using the `--no-default-features` when building with Cargo. +If some default features need to stay enabled, it is possible to add `--features [feature1],[feature2],...` to re-enable them. + +### Optional Features The Control UI behavior can be tuned at compile time, by enabling some optional features while building the binary: * **Support for CJK languages (eg. Chinese):** * Feature name: `fonts-cjk` - * Build command: `cargo build --features=fonts-cjk` + * Build command: `cargo build --features fonts-cjk` * Purpose: enables font support for CJK languages. As the CJK font weights 10MB+, and given that all assets get bundled in the final release binary, this feature is disabled by default as an optimization on binary size. If you need to use CJK languages in your MakAir ventilator, please build the Control UI with this feature enabled. Note that with this feature disabled, you will still be able to run with a CJK font, though all its glyphs will render as squares. * **Radio broadcasting of metrics over [LoRa / LoRaWAN](https://en.wikipedia.org/wiki/LoRa):** * Feature name: `lora` - * Build command: `cargo build --features=lora` + * Build command: `cargo build --features lora` * Purpose: enables periodic radio broadcasts of metrics, using an attached LoRa transmitter chip. This is an experimental feature, that is turned off by default. It aims at helping us build a central monitoring dashboard for hospitals, nesting all running MakAir metrics together. ## Prepared System Images diff --git a/src/chip/mod.rs b/src/chip/mod.rs index c9c53d5..961c8d2 100644 --- a/src/chip/mod.rs +++ b/src/chip/mod.rs @@ -16,7 +16,6 @@ use std::time::Instant; use makair_telemetry::alarm::{AlarmCode, RMC_SW_16}; use makair_telemetry::control::{ControlMessage, ControlSetting}; -use makair_telemetry::serial::core; use makair_telemetry::structures::{ AlarmPriority, ControlAck, DataSnapshot, EolTestSnapshot, EolTestSnapshotContent, EolTestStep, FatalErrorDetails, HighLevelError, MachineStateSnapshot, PatientGender, StoppedMessage, @@ -28,7 +27,7 @@ use settings::{ }; use crate::config::environment::*; -use crate::utilities::parse::parse_text_lines_to_single; +use crate::serial::poller::PollError; use crate::utilities::{ battery::estimate_lead_acid_12v_2s_soc, units::{ @@ -61,6 +60,7 @@ pub enum ChipState { #[derive(Debug, Clone, PartialEq, Eq)] pub enum ChipError { + #[cfg(feature = "serial")] NoDevice, TimedOut, BadProtocol, @@ -322,20 +322,29 @@ impl Chip { channel.1 } - pub fn new_core_error(&mut self, error: makair_telemetry::error::Error) { - use makair_telemetry::error::Error; - - if let Error::SerialError(serial_error) = error { - match serial_error.kind() { - core::ErrorKind::NoDevice => self.state = ChipState::Error(ChipError::NoDevice), - err => { - self.state = ChipState::Error(ChipError::Other(parse_text_lines_to_single( - &format!("{:?}", err), - "; ", - ))) - } - }; - } + pub fn new_core_error(&mut self, error: PollError) { + #[allow(clippy::single_match)] + match error { + #[cfg(feature = "serial")] + PollError::TelemetryError(makair_telemetry::error::Error::SerialError( + serial_error, + )) => { + match serial_error.kind() { + makair_telemetry::serial::core::ErrorKind::NoDevice => { + self.state = ChipState::Error(ChipError::NoDevice) + } + err => { + self.state = ChipState::Error(ChipError::Other( + crate::utilities::parse::parse_text_lines_to_single( + &format!("{:?}", err), + "; ", + ), + )) + } + }; + } + _ => (), + }; } pub fn new_telemetry_error(&mut self, error: HighLevelError) { diff --git a/src/config/arguments.rs b/src/config/arguments.rs index e3c4489..635146c 100644 --- a/src/config/arguments.rs +++ b/src/config/arguments.rs @@ -13,6 +13,7 @@ const LOG_LEVEL_DEFAULT: &str = "debug"; const LOG_LEVEL_DEFAULT: &str = "warn"; pub enum RunMode { + #[cfg(feature = "serial")] Port { port: String, output_dir: Option, @@ -107,13 +108,23 @@ impl ConfigArguments { matches.value_of("input"), matches.is_present("simulator"), ) { + #[cfg(feature = "serial")] (Some(p), _, _) => RunMode::Port { port: p.to_string(), output_dir: matches.value_of("output").map(|str| str.to_string()), }, + + #[cfg(not(feature = "serial"))] + (Some(_), _, _) => { + eprintln!("Program was not compiled with the 'serial' feature"); + std::process::exit(1); + } + (None, Some(i), _) => RunMode::Input(i.to_string()), + #[cfg(feature = "simulator")] (None, None, true) => RunMode::Simulator, + #[cfg(not(feature = "simulator"))] (None, None, true) => { eprintln!("Program was not compiled with the 'simulator' feature"); @@ -149,6 +160,7 @@ impl ConfigArguments { pub fn is_recording(&self) -> bool { match &self.mode { + #[cfg(feature = "serial")] RunMode::Port { output_dir, .. } => output_dir.is_some(), _ => false, } diff --git a/src/display/drawer.rs b/src/display/drawer.rs index 3877cfb..d17f359 100644 --- a/src/display/drawer.rs +++ b/src/display/drawer.rs @@ -257,6 +257,7 @@ impl DisplayDrawer { std::sync::mpsc::channel(); match &APP_ARGS.mode { + #[cfg(feature = "serial")] RunMode::Port { port, output_dir } => { let optional_file_buffer = output_dir.as_ref().map(|dir| { let file_count = std::fs::read_dir(dir) diff --git a/src/locale/error.rs b/src/locale/error.rs index 4c53254..3d1c9f2 100644 --- a/src/locale/error.rs +++ b/src/locale/error.rs @@ -10,6 +10,7 @@ use crate::APP_I18N; pub fn error_to_locales(error: &ChipError) -> (String, String) { // Acquire target locale attributes let (locale_key, error_details) = match error { + #[cfg(feature = "serial")] ChipError::NoDevice => ("no-device", None), ChipError::TimedOut => ("timed-out", None), ChipError::BadProtocol => ("bad-protocol", None), diff --git a/src/serial/poller.rs b/src/serial/poller.rs index 26830b9..f10deae 100644 --- a/src/serial/poller.rs +++ b/src/serial/poller.rs @@ -6,7 +6,6 @@ use std::sync::mpsc::{Receiver, TryRecvError}; use makair_telemetry::error::Error; -use makair_telemetry::serial::core::{Error as SerialError, ErrorKind}; use makair_telemetry::structures::{HighLevelError, TelemetryMessage}; use makair_telemetry::{self, TelemetryChannelType}; @@ -20,6 +19,14 @@ pub enum PollEvent { Pending, } +#[derive(Debug)] +pub enum PollError { + #[cfg(feature = "serial")] + TelemetryError(makair_telemetry::error::Error), + #[cfg(not(feature = "serial"))] + DisconnectedChannel, +} + #[allow(clippy::new_ret_no_self)] impl SerialPollerBuilder { pub fn new() -> SerialPoller { @@ -28,7 +35,7 @@ impl SerialPollerBuilder { } impl SerialPoller { - pub fn poll(&mut self, rx: &Receiver) -> Result { + pub fn poll(&mut self, rx: &Receiver) -> Result { match rx.try_recv() { // 1. Telemetry message can be handled and is valid Ok(Ok(message)) => Ok(PollEvent::Ready(message)), @@ -37,13 +44,22 @@ impl SerialPoller { Ok(PollEvent::Corrupted(message_error)) } // 3. A serial error occurred - Ok(Err(error)) => Err(error), + #[cfg(feature = "serial")] + Ok(Err(error)) => Err(PollError::TelemetryError(error)), // 4. Empty data was received (this is expected) Err(TryRecvError::Empty) => Ok(PollEvent::Pending), - // 5. The serial device is disconnected - Err(TryRecvError::Disconnected) => { - Err(SerialError::new(ErrorKind::NoDevice, "device is disconnected").into()) - } + // 6. The serial device is disconnected + #[cfg(feature = "serial")] + Err(TryRecvError::Disconnected) => Err(PollError::TelemetryError( + makair_telemetry::serial::core::Error::new( + makair_telemetry::serial::core::ErrorKind::NoDevice, + "device is disconnected", + ) + .into(), + )), + // 5. channel is disconnected + #[cfg(not(feature = "serial"))] + Err(TryRecvError::Disconnected) => Err(PollError::DisconnectedChannel), } } } diff --git a/src/utilities/parse.rs b/src/utilities/parse.rs index 79c538d..24e4495 100644 --- a/src/utilities/parse.rs +++ b/src/utilities/parse.rs @@ -39,6 +39,7 @@ pub fn parse_optional_number_to_string(value: Option) -> String { } } +#[cfg(feature = "serial")] pub fn parse_text_lines_to_single(text: &str, delimiter: &str) -> String { text.split('\n').collect::>().join(delimiter) } From 3a64d48a6b12ef33d644e55bb4c7ad5037beb120 Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Fri, 26 Nov 2021 23:07:54 +0100 Subject: [PATCH 11/29] Add documentation for the simulator feature --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 3ccd4e9..46b60d5 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ The following options can be passed to the Control UI upon running it: * `--input={file}`: path to a telemetry record to play in the UI, where `{file}` is a record file (all UI controls will be inactive); * `--output={directory}`: path to directory in which telemetry records should be stored, where `{directory}` is a path (disabled by default); * `--fullscreen`: enables fullscreen mode (used on the final ventilator display only); +* `--simulator`: use a [MakAir Simulator](https://github.com/makers-for-life/makair-simulator) instance as source of data (`simulator` build feature); * `--translation={locale}`: locale to use in the UI, where `{locale}` is a [supported locale code](#supported-translations) (defaults to `en`; overrides user settings); * `--disable-lora`: disables LoRa telemetry broadcasts (`lora` build feature); * `--lora-device={device}`: LoRa device path, where `{device}` is a path eg. `/dev/ttyAMA0` (`lora` build feature; defaults to `/dev/ttyAMA0`); @@ -148,6 +149,11 @@ The Control UI behavior can be tuned at compile time, by enabling some optional * Build command: `cargo build --features lora` * Purpose: enables periodic radio broadcasts of metrics, using an attached LoRa transmitter chip. This is an experimental feature, that is turned off by default. It aims at helping us build a central monitoring dashboard for hospitals, nesting all running MakAir metrics together. +* **Embed [MakAir Simulator](https://github.com/makers-for-life/makair-simulator):** + * Feature name: `simulator` + * Build command: `cargo build --features simulator` + * Purpose: embed the MakAir Simulator projet, which means that using `-s` or `--simulator` will run the [MakAir Firmware](https://github.com/makers-for-life/makair-firmware) attached to a mathematical model that simulates sensors and actuators in a realistic way and allow to visualize/control it using Control UI. + ## Prepared System Images Prepared system images that run on a Raspberry Pi and pack the Control UI are available in the [makair-files](https://github.com/makers-for-life/makair-files) repository (over Git LFS). They can be flashed to a microSD card and ran in a MakAir in a matter of minutes. From 99ff8b8d839ab03d1ab8863195139a614772c26a Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Fri, 26 Nov 2021 23:21:03 +0100 Subject: [PATCH 12/29] Fix warnings and coding style --- src/chip/settings/advanced.rs | 53 +++++++++++---------------------- src/display/events.rs | 2 +- src/display/screen.rs | 20 ++++++++++--- src/widget/advanced_settings.rs | 14 +++++---- 4 files changed, 44 insertions(+), 45 deletions(-) diff --git a/src/chip/settings/advanced.rs b/src/chip/settings/advanced.rs index 965ab87..53ad061 100644 --- a/src/chip/settings/advanced.rs +++ b/src/chip/settings/advanced.rs @@ -11,12 +11,12 @@ use crate::{APP_I18N, APP_SETTINGS}; pub struct SettingsAdvanced { pub group: SettingsAdvancedGroupTab, pub locale: LocaleCode, - pub resistance : i32, - pub compliance : i32, - pub spontaneous_breath_rate : i32, - pub spontaneous_breath_effort : i32, - pub spontaneous_breath_duration : i32, - pub acceleration_factor : f32, + pub resistance: i32, + pub compliance: i32, + pub spontaneous_breath_rate: i32, + pub spontaneous_breath_effort: i32, + pub spontaneous_breath_duration: i32, + pub acceleration_factor: f32, } #[derive(Debug, PartialEq)] @@ -48,12 +48,12 @@ impl SettingsAdvanced { SettingsAdvanced { group: SettingsAdvancedGroupTab::default(), locale: LocaleCode::from_code(&APP_SETTINGS.read().unwrap().locale).unwrap_or_default(), - resistance : 1, // TODO get value from simulator - compliance : 1, // TODO get value from simulator - spontaneous_breath_rate : 0, // TODO get value from simulator - spontaneous_breath_effort : 0,// TODO get value from simulator - spontaneous_breath_duration : 0,// TODO get value from simulator - acceleration_factor : 1.0,// TODO get value from simulator + resistance: 1, // TODO get value from simulator + compliance: 1, // TODO get value from simulator + spontaneous_breath_rate: 0, // TODO get value from simulator + spontaneous_breath_effort: 0, // TODO get value from simulator + spontaneous_breath_duration: 0, // TODO get value from simulator + acceleration_factor: 1.0, // TODO get value from simulator } } @@ -102,75 +102,58 @@ impl SettingsAdvanced { } pub fn switch_resistance(&mut self, action: SettingActionRange) { - let next_resistance = action.to_next_index(self.resistance as _); // TODO : check if value is allowed and send it to simulator if next_resistance as i32 != self.resistance { self.resistance = next_resistance as i32; - - } } pub fn switch_compliance(&mut self, action: SettingActionRange) { - let next_compliance = action.to_next_index(self.compliance as _); // TODO : check if value is allowed and send it to simulator if next_compliance as i32 != self.compliance { self.compliance = next_compliance as i32; - - } } pub fn switch_spontaneous_breath_rate(&mut self, action: SettingActionRange) { - let next_spontaneous_breath_rate = action.to_next_index(self.spontaneous_breath_rate as _); // TODO : check if value is allowed and send it to simulator if next_spontaneous_breath_rate as i32 != self.spontaneous_breath_rate { self.spontaneous_breath_rate = next_spontaneous_breath_rate as i32; - - } } pub fn switch_spontaneous_breath_effort(&mut self, action: SettingActionRange) { - - let next_spontaneous_breath_effort = action.to_next_index(self.spontaneous_breath_effort as _); + let next_spontaneous_breath_effort = + action.to_next_index(self.spontaneous_breath_effort as _); // TODO : check if value is allowed and send it to simulator if next_spontaneous_breath_effort as i32 != self.spontaneous_breath_effort { self.spontaneous_breath_effort = next_spontaneous_breath_effort as i32; - - } } pub fn switch_spontaneous_breath_duration(&mut self, action: SettingActionRange) { - - let next_spontaneous_breath_duration = action.to_next_index(self.spontaneous_breath_duration as _); + let next_spontaneous_breath_duration = + action.to_next_index(self.spontaneous_breath_duration as _); // TODO : check if value is allowed and send it to simulator if next_spontaneous_breath_duration as i32 != self.spontaneous_breath_duration { self.spontaneous_breath_duration = next_spontaneous_breath_duration as i32; - - } } pub fn switch_acceleration_factor(&mut self, action: SettingActionRange) { - let next_acceleration_factor = action.to_next_index(self.acceleration_factor as _); // TODO : check if value is allowed and send it to simulator - - if next_acceleration_factor as f32 != self.acceleration_factor { - self.acceleration_factor = next_acceleration_factor as f32; - + if (next_acceleration_factor as f32 - self.acceleration_factor).abs() > f32::EPSILON { + self.acceleration_factor = next_acceleration_factor as f32; } } - } diff --git a/src/display/events.rs b/src/display/events.rs index f251901..04c9d96 100644 --- a/src/display/events.rs +++ b/src/display/events.rs @@ -621,7 +621,7 @@ impl DisplayUiEvents { chip.settings.advanced.group = SettingsAdvancedGroupTab::Settings; } }, - + { "group simulator", diff --git a/src/display/screen.rs b/src/display/screen.rs index e2bc0fa..4782003 100644 --- a/src/display/screen.rs +++ b/src/display/screen.rs @@ -988,10 +988,22 @@ impl<'a> Screen<'a> { field_resistance_ids: gen_render_advanced_settings_field_ids!(self, resistance), field_compliance_ids: gen_render_advanced_settings_field_ids!(self, compliance), - field_spontaneous_breath_rate_ids: gen_render_advanced_settings_field_ids!(self, spontaneous_breath_rate), - field_spontaneous_breath_effort_ids: gen_render_advanced_settings_field_ids!(self, spontaneous_breath_effort), - field_spontaneous_breath_duration_ids: gen_render_advanced_settings_field_ids!(self, spontaneous_breath_duration), - field_acceleration_factor_ids: gen_render_advanced_settings_field_ids!(self, acceleration_factor), + field_spontaneous_breath_rate_ids: gen_render_advanced_settings_field_ids!( + self, + spontaneous_breath_rate + ), + field_spontaneous_breath_effort_ids: gen_render_advanced_settings_field_ids!( + self, + spontaneous_breath_effort + ), + field_spontaneous_breath_duration_ids: gen_render_advanced_settings_field_ids!( + self, + spontaneous_breath_duration + ), + field_acceleration_factor_ids: gen_render_advanced_settings_field_ids!( + self, + acceleration_factor + ), }, )); } diff --git a/src/widget/advanced_settings.rs b/src/widget/advanced_settings.rs index 4839dfa..fe11280 100644 --- a/src/widget/advanced_settings.rs +++ b/src/widget/advanced_settings.rs @@ -70,12 +70,11 @@ pub struct Config<'a> { pub text_timezone_ids: TextWidgetIds, pub field_resistance_ids: FieldWidgetIds, - pub field_compliance_ids : FieldWidgetIds, + pub field_compliance_ids: FieldWidgetIds, pub field_spontaneous_breath_rate_ids: FieldWidgetIds, pub field_spontaneous_breath_effort_ids: FieldWidgetIds, pub field_spontaneous_breath_duration_ids: FieldWidgetIds, pub field_acceleration_factor_ids: FieldWidgetIds, - } struct Field { @@ -397,7 +396,6 @@ fn form_settings<'a>(master: &mut ControlWidget<'a>, config: &Config) { } fn form_simulator<'a>(master: &mut ControlWidget<'a>, config: &Config) { - draw_field( 0, master, @@ -437,7 +435,10 @@ fn form_simulator<'a>(master: &mut ControlWidget<'a>, config: &Config) { config, Field { label_text: APP_I18N.t("modal-advanced-simulator-spontaneous-breath-effort"), - value_text: config.advanced_settings.spontaneous_breath_effort.to_string(), + value_text: config + .advanced_settings + .spontaneous_breath_effort + .to_string(), ids: config.field_spontaneous_breath_effort_ids, }, ); @@ -448,7 +449,10 @@ fn form_simulator<'a>(master: &mut ControlWidget<'a>, config: &Config) { config, Field { label_text: APP_I18N.t("modal-advanced-simulator-spontaneous-breath-duration"), - value_text: config.advanced_settings.spontaneous_breath_duration.to_string(), + value_text: config + .advanced_settings + .spontaneous_breath_duration + .to_string(), ids: config.field_spontaneous_breath_duration_ids, }, ); From f99368853968327bbd3cff7c525518b6672b9237 Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Sat, 27 Nov 2021 09:52:08 +0100 Subject: [PATCH 13/29] Do not display simulator settings when compilation flag was not enabled --- src/config/environment.rs | 3 ++- src/display/screen.rs | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/config/environment.rs b/src/config/environment.rs index cefc01a..c9ecbe4 100644 --- a/src/config/environment.rs +++ b/src/config/environment.rs @@ -265,7 +265,8 @@ pub const ADVANCED_SETTINGS_LINES_COUNT: usize = 15; pub const ADVANCED_SETTINGS_LINE_MARGIN_TOP: f64 = 8.0; pub const ADVANCED_SETTINGS_LINE_FONT_SIZE: u32 = 14; pub const ADVANCED_SETTINGS_LINE_VALUE_PADDING_LEFT: f64 = 240.0; -pub const ADVANCED_SETTINGS_GROUP_TABS_COUNT: usize = 3; +pub const ADVANCED_SETTINGS_GROUP_TABS_COUNT: usize = + if cfg!(feature = "simulator") { 3 } else { 2 }; pub const ADVANCED_SETTINGS_LINE_VALUE_EMPTY: &str = "--"; pub const MODE_SETTINGS_MODAL_PADDING: f64 = 20.0; diff --git a/src/display/screen.rs b/src/display/screen.rs index 4782003..eb8b692 100644 --- a/src/display/screen.rs +++ b/src/display/screen.rs @@ -972,12 +972,14 @@ impl<'a> Screen<'a> { advanced_group_tab_buttons: [ self.ids.advanced_group_tab_statistics_button, self.ids.advanced_group_tab_settings_button, + #[cfg(feature = "simulator")] self.ids.advanced_group_tab_simulator_button, ], advanced_group_tab_texts: [ self.ids.advanced_group_tab_statistics_text, self.ids.advanced_group_tab_settings_text, + #[cfg(feature = "simulator")] self.ids.advanced_group_tab_simulator_text, ], From 3801e86181f459e4b5d4c4144dcf33eb23bcb5e5 Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Sat, 27 Nov 2021 20:23:13 +0100 Subject: [PATCH 14/29] Allow to change simulator settings using the UI --- Cargo.lock | 45 ++++++++- Cargo.toml | 2 +- res/locales/de.ftl | 2 +- res/locales/en.ftl | 2 +- res/locales/es.ftl | 2 +- res/locales/fr.ftl | 2 +- res/locales/it.ftl | 2 +- res/locales/lv.ftl | 2 +- res/locales/pt.ftl | 2 +- res/locales/ru.ftl | 2 +- res/locales/uk.ftl | 2 +- res/locales/zh.ftl | 2 +- src/chip/mod.rs | 36 ++++++- src/chip/settings/advanced.rs | 170 ++++++++++++++++++++++--------- src/chip/settings/mod.rs | 33 ++++++ src/{serial => data}/mod.rs | 2 + src/{serial => data}/poller.rs | 0 src/data/simulator.rs | 22 ++++ src/display/drawer.rs | 40 ++++---- src/display/events.rs | 174 ++++++++++++++++++++++++++++---- src/display/identifiers.rs | 14 +-- src/display/renderer.rs | 31 +++++- src/display/screen.rs | 10 +- src/locale/advanced.rs | 1 + src/main.rs | 2 +- src/widget/advanced_settings.rs | 14 ++- 26 files changed, 500 insertions(+), 116 deletions(-) rename src/{serial => data}/mod.rs (69%) rename src/{serial => data}/poller.rs (100%) create mode 100644 src/data/simulator.rs diff --git a/Cargo.lock b/Cargo.lock index 0fdc727..c07f4c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -827,6 +827,15 @@ dependencies = [ "gl_generator", ] +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1146,11 +1155,11 @@ dependencies = [ [[package]] name = "makair-simulator" version = "0.1.0" -source = "git+https://github.com/makers-for-life/makair-simulator?rev=59bf7bce05ee26075e126753a74ebebf00c5bfb0#59bf7bce05ee26075e126753a74ebebf00c5bfb0" dependencies = [ "cc", "log", "makair-telemetry", + "strum", ] [[package]] @@ -1937,6 +1946,12 @@ dependencies = [ "owned_ttf_parser", ] +[[package]] +name = "rustversion" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" + [[package]] name = "same-file" version = "1.0.6" @@ -2138,6 +2153,28 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" +[[package]] +name = "strum" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38" +dependencies = [ + "heck", + "proc-macro2 1.0.32", + "quote 1.0.10", + "rustversion", + "syn", +] + [[package]] name = "syn" version = "1.0.82" @@ -2267,6 +2304,12 @@ dependencies = [ "tinystr", ] +[[package]] +name = "unicode-segmentation" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" + [[package]] name = "unicode-width" version = "0.1.9" diff --git a/Cargo.toml b/Cargo.toml index c078057..998b775 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,7 @@ conrod_core = "0.71" sysfs_gpio = { version = "0.6", optional = true } rn2903 = { git = "https://github.com/waxzce/lora-rust-rn2903-rn2483.git", rev = "b086057ba096920abef3870ad0cefa2c80a343e2", optional = true } makair-telemetry = { git = "https://github.com/makers-for-life/makair-telemetry", rev = "184185d4301fa7343018cd6733e1fb23e2cb032e", default-features = false } -makair-simulator = { git = "https://github.com/makers-for-life/makair-simulator", rev = "59bf7bce05ee26075e126753a74ebebf00c5bfb0", optional = true } +makair-simulator = { git = "https://github.com/makers-for-life/makair-simulator", rev = "8060cf63e387ee0fc4ecbce34af057c3aa5ad987", optional = true } [features] default = ["serial"] diff --git a/res/locales/de.ftl b/res/locales/de.ftl index 0e06209..5c36e74 100644 --- a/res/locales/de.ftl +++ b/res/locales/de.ftl @@ -111,7 +111,7 @@ modal-advanced-simulator-airway-compliance = Compliance modal-advanced-simulator-spontaneous-breath-rate = Breath rate modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration -modal-advanced-simulator-acceleration-factor = Acceleration factor +modal-advanced-simulator-acceleration-factor = Acceleration percent initializing-connecting = Inbetriebnahme... initializing-connected = Initialisierung... diff --git a/res/locales/en.ftl b/res/locales/en.ftl index 8d9f8fb..1923be5 100644 --- a/res/locales/en.ftl +++ b/res/locales/en.ftl @@ -111,7 +111,7 @@ modal-advanced-simulator-airway-compliance = Compliance modal-advanced-simulator-spontaneous-breath-rate = Breath rate modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration -modal-advanced-simulator-acceleration-factor = Acceleration factor +modal-advanced-simulator-acceleration-factor = Acceleration percent initializing-connecting = Starting up... diff --git a/res/locales/es.ftl b/res/locales/es.ftl index 23a99dc..44e78a3 100644 --- a/res/locales/es.ftl +++ b/res/locales/es.ftl @@ -112,7 +112,7 @@ modal-advanced-simulator-airway-compliance = Compliance modal-advanced-simulator-spontaneous-breath-rate = Breath rate modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration -modal-advanced-simulator-acceleration-factor = Acceleration factor +modal-advanced-simulator-acceleration-factor = Acceleration percent initializing-connecting = Empezando... initializing-connected = Inicializando... diff --git a/res/locales/fr.ftl b/res/locales/fr.ftl index 8a78994..eac266f 100644 --- a/res/locales/fr.ftl +++ b/res/locales/fr.ftl @@ -112,7 +112,7 @@ modal-advanced-simulator-airway-compliance = Compliance modal-advanced-simulator-spontaneous-breath-rate = Breath rate modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration -modal-advanced-simulator-acceleration-factor = Acceleration factor +modal-advanced-simulator-acceleration-factor = Acceleration percent initializing-connecting = Démarrage en cours... initializing-connected = Préparation en cours... diff --git a/res/locales/it.ftl b/res/locales/it.ftl index bbfe88e..233c7d6 100644 --- a/res/locales/it.ftl +++ b/res/locales/it.ftl @@ -112,7 +112,7 @@ modal-advanced-simulator-airway-compliance = Compliance modal-advanced-simulator-spontaneous-breath-rate = Breath rate modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration -modal-advanced-simulator-acceleration-factor = Acceleration factor +modal-advanced-simulator-acceleration-factor = Acceleration percent initializing-connecting = Cominciando... initializing-connected = Inizializzazione in corso... diff --git a/res/locales/lv.ftl b/res/locales/lv.ftl index 226c8eb..5bcf8a6 100644 --- a/res/locales/lv.ftl +++ b/res/locales/lv.ftl @@ -112,7 +112,7 @@ modal-advanced-simulator-airway-compliance = Compliance modal-advanced-simulator-spontaneous-breath-rate = Breath rate modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration -modal-advanced-simulator-acceleration-factor = Acceleration factor +modal-advanced-simulator-acceleration-factor = Acceleration percent initializing-connecting = Notiek palaišana... initializing-connected = Notiek inicializēšana... diff --git a/res/locales/pt.ftl b/res/locales/pt.ftl index 548bd92..0a5edd4 100644 --- a/res/locales/pt.ftl +++ b/res/locales/pt.ftl @@ -111,7 +111,7 @@ modal-advanced-simulator-airway-compliance = Compliance modal-advanced-simulator-spontaneous-breath-rate = Breath rate modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration -modal-advanced-simulator-acceleration-factor = Acceleration factor +modal-advanced-simulator-acceleration-factor = Acceleration percent initializing-connecting = Começando... initializing-connected = Inicializando... diff --git a/res/locales/ru.ftl b/res/locales/ru.ftl index 3c30da3..dd078ba 100644 --- a/res/locales/ru.ftl +++ b/res/locales/ru.ftl @@ -111,7 +111,7 @@ modal-advanced-simulator-airway-compliance = Compliance modal-advanced-simulator-spontaneous-breath-rate = Breath rate modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration -modal-advanced-simulator-acceleration-factor = Acceleration factor +modal-advanced-simulator-acceleration-factor = Acceleration percent initializing-connecting = Начиная... initializing-connected = Инициализация... diff --git a/res/locales/uk.ftl b/res/locales/uk.ftl index 7028681..59581bc 100644 --- a/res/locales/uk.ftl +++ b/res/locales/uk.ftl @@ -111,7 +111,7 @@ modal-advanced-simulator-airway-compliance = Compliance modal-advanced-simulator-spontaneous-breath-rate = Breath rate modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration -modal-advanced-simulator-acceleration-factor = Acceleration factor +modal-advanced-simulator-acceleration-factor = Acceleration percent initializing-connecting = Запуск... initializing-connected = Ініціалізація... diff --git a/res/locales/zh.ftl b/res/locales/zh.ftl index 2fbce3e..f786da1 100644 --- a/res/locales/zh.ftl +++ b/res/locales/zh.ftl @@ -111,7 +111,7 @@ modal-advanced-simulator-airway-compliance = Compliance modal-advanced-simulator-spontaneous-breath-rate = Breath rate modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration -modal-advanced-simulator-acceleration-factor = Acceleration factor +modal-advanced-simulator-acceleration-factor = Acceleration percent initializing-connecting = 启动... initializing-connected = 初始化中... diff --git a/src/chip/mod.rs b/src/chip/mod.rs index 961c8d2..b2b3454 100644 --- a/src/chip/mod.rs +++ b/src/chip/mod.rs @@ -27,7 +27,7 @@ use settings::{ }; use crate::config::environment::*; -use crate::serial::poller::PollError; +use crate::data::poller::PollError; use crate::utilities::{ battery::estimate_lead_acid_12v_2s_soc, units::{ @@ -164,6 +164,8 @@ pub struct Chip { pub state: ChipState, lora_tx: Option>, channel_for_settings: Option>, + #[cfg(feature = "simulator")] + simulator: Option, } impl ChipData { @@ -202,6 +204,8 @@ impl Chip { state: ChipState::WaitingData(Instant::now()), lora_tx: lora_sender, channel_for_settings: None, + #[cfg(feature = "simulator")] + simulator: None, } } @@ -266,6 +270,31 @@ impl Chip { } } + #[cfg(feature = "simulator")] + pub fn dispatch_simulator_settings_events( + &mut self, + events: Vec, + ) { + for event in events { + let settings = self.settings.new_simulator_settings_event(event); + + for setting in settings { + debug!("handled simulator setting event: {:?}", setting); + + if let Some(simulator) = &self.simulator { + if let Err(err) = simulator.simulator_setting_sender().send(setting.clone()) { + error!( + "error sending setting {:?} to the simulator: {:?}", + setting, err + ); + } else { + debug!("simulator setting {:?} sent", setting); + } + } + } + } + } + pub fn ongoing_alarms_sorted(&self) -> Vec<(AlarmCode, AlarmPriority)> { // This acquires a sorted list of ongoing alarms. It also clears out related alarms. In \ // some cases, the list of alarms might contain the same alarm, at different priority \ @@ -484,6 +513,11 @@ impl Chip { } } + #[cfg(feature = "simulator")] + pub fn set_simulator(&mut self, simulator: makair_simulator::MakAirSimulator) { + self.simulator = Some(simulator); + } + fn new_alarm(&mut self, code: AlarmCode, priority: AlarmPriority, triggered: bool) { if triggered { // If we ever receive the same alarm, just replace the one we have diff --git a/src/chip/settings/advanced.rs b/src/chip/settings/advanced.rs index 53ad061..818aaae 100644 --- a/src/chip/settings/advanced.rs +++ b/src/chip/settings/advanced.rs @@ -11,18 +11,25 @@ use crate::{APP_I18N, APP_SETTINGS}; pub struct SettingsAdvanced { pub group: SettingsAdvancedGroupTab, pub locale: LocaleCode, + #[cfg(feature = "simulator")] pub resistance: i32, + #[cfg(feature = "simulator")] pub compliance: i32, + #[cfg(feature = "simulator")] pub spontaneous_breath_rate: i32, + #[cfg(feature = "simulator")] pub spontaneous_breath_effort: i32, + #[cfg(feature = "simulator")] pub spontaneous_breath_duration: i32, - pub acceleration_factor: f32, + #[cfg(feature = "simulator")] + pub acceleration_percent: i32, } #[derive(Debug, PartialEq)] pub enum SettingsAdvancedGroupTab { Statistics, Settings, + #[cfg(feature = "simulator")] Simulator, } @@ -31,6 +38,7 @@ impl SettingsAdvancedGroupTab { match index { 0 => Some(Self::Statistics), 1 => Some(Self::Settings), + #[cfg(feature = "simulator")] 2 => Some(Self::Simulator), _ => None, } @@ -48,15 +56,44 @@ impl SettingsAdvanced { SettingsAdvanced { group: SettingsAdvancedGroupTab::default(), locale: LocaleCode::from_code(&APP_SETTINGS.read().unwrap().locale).unwrap_or_default(), - resistance: 1, // TODO get value from simulator - compliance: 1, // TODO get value from simulator - spontaneous_breath_rate: 0, // TODO get value from simulator - spontaneous_breath_effort: 0, // TODO get value from simulator - spontaneous_breath_duration: 0, // TODO get value from simulator - acceleration_factor: 1.0, // TODO get value from simulator + #[cfg(feature = "simulator")] + resistance: makair_simulator::SimulatorSettingKind::Resistance.default(), + #[cfg(feature = "simulator")] + compliance: makair_simulator::SimulatorSettingKind::Compliance.default(), + #[cfg(feature = "simulator")] + spontaneous_breath_rate: makair_simulator::SimulatorSettingKind::SpontaneousBreathRate + .default(), + #[cfg(feature = "simulator")] + spontaneous_breath_effort: + makair_simulator::SimulatorSettingKind::SpontaneousBreathEffort.default(), + #[cfg(feature = "simulator")] + spontaneous_breath_duration: + makair_simulator::SimulatorSettingKind::SpontaneousBreathDuration.default(), + #[cfg(feature = "simulator")] + acceleration_percent: makair_simulator::SimulatorSettingKind::AccelerationPercent + .default(), } } + #[cfg(feature = "simulator")] + pub fn new_event( + &self, + event: makair_simulator::SimulatorSettingKind, + ) -> Vec { + use makair_simulator::{SimulatorSetting, SimulatorSettingKind}; + + let value = match event { + SimulatorSettingKind::AccelerationPercent => self.acceleration_percent, + SimulatorSettingKind::Resistance => self.resistance, + SimulatorSettingKind::Compliance => self.compliance, + SimulatorSettingKind::SpontaneousBreathRate => self.spontaneous_breath_rate, + SimulatorSettingKind::SpontaneousBreathEffort => self.spontaneous_breath_effort, + SimulatorSettingKind::SpontaneousBreathDuration => self.spontaneous_breath_duration, + }; + + vec![SimulatorSetting { kind: event, value }] + } + pub fn switch_locale(&mut self, action: SettingActionRange) { let locales = LocaleCode::list_available(); let locales_size = locales.len() as i16; @@ -101,59 +138,102 @@ impl SettingsAdvanced { } } - pub fn switch_resistance(&mut self, action: SettingActionRange) { - let next_resistance = action.to_next_index(self.resistance as _); - // TODO : check if value is allowed and send it to simulator - - if next_resistance as i32 != self.resistance { - self.resistance = next_resistance as i32; + #[cfg(feature = "simulator")] + pub fn switch_resistance(&mut self, action: super::SimulatorSettingActionRange) { + let current_resistance = makair_simulator::SimulatorSetting { + kind: makair_simulator::SimulatorSettingKind::Resistance, + value: self.resistance, + }; + let next_resistance = makair_simulator::SimulatorSetting { + kind: makair_simulator::SimulatorSettingKind::Resistance, + value: action.to_new_value(¤t_resistance), + }; + + if next_resistance != current_resistance { + self.resistance = next_resistance.value; } } - pub fn switch_compliance(&mut self, action: SettingActionRange) { - let next_compliance = action.to_next_index(self.compliance as _); - // TODO : check if value is allowed and send it to simulator - - if next_compliance as i32 != self.compliance { - self.compliance = next_compliance as i32; + #[cfg(feature = "simulator")] + pub fn switch_compliance(&mut self, action: super::SimulatorSettingActionRange) { + let current_compliance = makair_simulator::SimulatorSetting { + kind: makair_simulator::SimulatorSettingKind::Compliance, + value: self.compliance, + }; + let next_compliance = makair_simulator::SimulatorSetting { + kind: makair_simulator::SimulatorSettingKind::Compliance, + value: action.to_new_value(¤t_compliance), + }; + + if next_compliance != current_compliance { + self.compliance = next_compliance.value; } } - pub fn switch_spontaneous_breath_rate(&mut self, action: SettingActionRange) { - let next_spontaneous_breath_rate = action.to_next_index(self.spontaneous_breath_rate as _); - // TODO : check if value is allowed and send it to simulator - - if next_spontaneous_breath_rate as i32 != self.spontaneous_breath_rate { - self.spontaneous_breath_rate = next_spontaneous_breath_rate as i32; + #[cfg(feature = "simulator")] + pub fn switch_spontaneous_breath_rate(&mut self, action: super::SimulatorSettingActionRange) { + let current_spontaneous_breath_rate = makair_simulator::SimulatorSetting { + kind: makair_simulator::SimulatorSettingKind::SpontaneousBreathRate, + value: self.spontaneous_breath_rate, + }; + let next_spontaneous_breath_rate = makair_simulator::SimulatorSetting { + kind: makair_simulator::SimulatorSettingKind::SpontaneousBreathRate, + value: action.to_new_value(¤t_spontaneous_breath_rate), + }; + + if next_spontaneous_breath_rate != current_spontaneous_breath_rate { + self.spontaneous_breath_rate = next_spontaneous_breath_rate.value; } } - pub fn switch_spontaneous_breath_effort(&mut self, action: SettingActionRange) { - let next_spontaneous_breath_effort = - action.to_next_index(self.spontaneous_breath_effort as _); - // TODO : check if value is allowed and send it to simulator - - if next_spontaneous_breath_effort as i32 != self.spontaneous_breath_effort { - self.spontaneous_breath_effort = next_spontaneous_breath_effort as i32; + #[cfg(feature = "simulator")] + pub fn switch_spontaneous_breath_effort(&mut self, action: super::SimulatorSettingActionRange) { + let current_spontaneous_breath_effort = makair_simulator::SimulatorSetting { + kind: makair_simulator::SimulatorSettingKind::SpontaneousBreathEffort, + value: self.spontaneous_breath_effort, + }; + let next_spontaneous_breath_effort = makair_simulator::SimulatorSetting { + kind: makair_simulator::SimulatorSettingKind::SpontaneousBreathEffort, + value: action.to_new_value(¤t_spontaneous_breath_effort), + }; + + if next_spontaneous_breath_effort != current_spontaneous_breath_effort { + self.spontaneous_breath_effort = next_spontaneous_breath_effort.value; } } - pub fn switch_spontaneous_breath_duration(&mut self, action: SettingActionRange) { - let next_spontaneous_breath_duration = - action.to_next_index(self.spontaneous_breath_duration as _); - // TODO : check if value is allowed and send it to simulator - - if next_spontaneous_breath_duration as i32 != self.spontaneous_breath_duration { - self.spontaneous_breath_duration = next_spontaneous_breath_duration as i32; + #[cfg(feature = "simulator")] + pub fn switch_spontaneous_breath_duration( + &mut self, + action: super::SimulatorSettingActionRange, + ) { + let current_spontaneous_breath_duration = makair_simulator::SimulatorSetting { + kind: makair_simulator::SimulatorSettingKind::SpontaneousBreathDuration, + value: self.spontaneous_breath_duration, + }; + let next_spontaneous_breath_duration = makair_simulator::SimulatorSetting { + kind: makair_simulator::SimulatorSettingKind::SpontaneousBreathDuration, + value: action.to_new_value(¤t_spontaneous_breath_duration), + }; + + if next_spontaneous_breath_duration != current_spontaneous_breath_duration { + self.spontaneous_breath_duration = next_spontaneous_breath_duration.value; } } - pub fn switch_acceleration_factor(&mut self, action: SettingActionRange) { - let next_acceleration_factor = action.to_next_index(self.acceleration_factor as _); - // TODO : check if value is allowed and send it to simulator - - if (next_acceleration_factor as f32 - self.acceleration_factor).abs() > f32::EPSILON { - self.acceleration_factor = next_acceleration_factor as f32; + #[cfg(feature = "simulator")] + pub fn switch_acceleration_percent(&mut self, action: super::SimulatorSettingActionRange) { + let current_acceleration_percent = makair_simulator::SimulatorSetting { + kind: makair_simulator::SimulatorSettingKind::AccelerationPercent, + value: self.acceleration_percent, + }; + let next_acceleration_percent = makair_simulator::SimulatorSetting { + kind: makair_simulator::SimulatorSettingKind::AccelerationPercent, + value: action.to_new_value(¤t_acceleration_percent), + }; + + if next_acceleration_percent != current_acceleration_percent { + self.acceleration_percent = next_acceleration_percent.value; } } } diff --git a/src/chip/settings/mod.rs b/src/chip/settings/mod.rs index d949e9d..d096d69 100644 --- a/src/chip/settings/mod.rs +++ b/src/chip/settings/mod.rs @@ -38,6 +38,12 @@ pub enum ChipSettingsIntent { Mode(SettingsModeIntent), } +#[cfg(feature = "simulator")] +#[derive(Debug)] +pub enum ChipSettingsSimulatorEvent { + UpdateSetting(makair_simulator::SimulatorSettingKind), +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum SettingActionState { Disabled = 0, @@ -113,6 +119,23 @@ impl SettingActionRange { } } +#[cfg(feature = "simulator")] +#[derive(Debug)] +pub enum SimulatorSettingActionRange { + More, + Less, +} + +#[cfg(feature = "simulator")] +impl SimulatorSettingActionRange { + fn to_new_value(&self, setting: &makair_simulator::SimulatorSetting) -> i32 { + match self { + Self::More => setting.increment().value, + Self::Less => setting.decrement().value, + } + } +} + #[derive(Debug)] pub struct ChipSettings { pub run: SettingsRun, @@ -150,4 +173,14 @@ impl ChipSettings { ChipSettingsIntent::Mode(intent) => self.mode.new_intent(intent), } } + + #[cfg(feature = "simulator")] + pub fn new_simulator_settings_event( + &mut self, + event: ChipSettingsSimulatorEvent, + ) -> Vec { + match event { + ChipSettingsSimulatorEvent::UpdateSetting(event) => self.advanced.new_event(event), + } + } } diff --git a/src/serial/mod.rs b/src/data/mod.rs similarity index 69% rename from src/serial/mod.rs rename to src/data/mod.rs index b46dda2..91eced3 100644 --- a/src/serial/mod.rs +++ b/src/data/mod.rs @@ -4,3 +4,5 @@ // License: Public Domain License pub mod poller; +#[cfg(feature = "simulator")] +pub mod simulator; diff --git a/src/serial/poller.rs b/src/data/poller.rs similarity index 100% rename from src/serial/poller.rs rename to src/data/poller.rs diff --git a/src/data/simulator.rs b/src/data/simulator.rs new file mode 100644 index 0000000..6ab6289 --- /dev/null +++ b/src/data/simulator.rs @@ -0,0 +1,22 @@ +use makair_simulator::MakAirSimulator; +use makair_telemetry::control::ControlMessage; +use makair_telemetry::TelemetryChannelType; +use std::sync::mpsc::{Receiver, Sender}; + +pub fn init( + tx: Sender, + control_rx: Receiver, +) -> MakAirSimulator { + let mut simulator = MakAirSimulator::new(tx); + simulator.initialize(false); + + let control_message_sender = simulator.control_message_sender(); + + std::thread::spawn(move || loop { + while let Ok(message) = control_rx.recv() { + control_message_sender.send(message).unwrap(); + } + }); + + simulator +} diff --git a/src/display/drawer.rs b/src/display/drawer.rs index d17f359..0f908dc 100644 --- a/src/display/drawer.rs +++ b/src/display/drawer.rs @@ -18,12 +18,12 @@ use makair_telemetry::{self, TelemetryChannelType}; use crate::chip::{Chip, ChipEventUpdate, ChipState}; use crate::config::arguments::RunMode; use crate::config::environment::*; -use crate::serial::poller::{PollEvent, SerialPoller, SerialPollerBuilder}; +use crate::data::poller::{PollEvent, SerialPoller, SerialPollerBuilder}; use crate::APP_ARGS; use super::fonts::Fonts; use super::identifiers::{Ids, ImageIds}; -use super::renderer::DisplayRendererBuilder; +use super::renderer::{DisplayRendererBuilder, DisplayRendererRunEventsResult}; use super::support::GliumDisplayWinitWrapper; const FRAMERATE_SLEEP_THROTTLE_SMOOTH_HEAVY: Duration = @@ -131,13 +131,19 @@ impl DisplayDrawer { } // Run events since the last render - let (has_heartbeat, has_user_events, user_intents, user_events) = renderer - .run_events( - &mut interface, - &mut chip, - &last_heartbeat, - &tick_start_time, - ); + let DisplayRendererRunEventsResult { + has_heartbeat, + has_user_events, + user_intents, + user_events, + #[cfg(feature = "simulator")] + user_simulator_events, + } = renderer.run_events( + &mut interface, + &mut chip, + &last_heartbeat, + &tick_start_time, + ); // Dispatch heartbeat? // Notice: heartbeats are critical, as they indicate the firmware that the Control UI \ @@ -177,6 +183,11 @@ impl DisplayDrawer { if !user_events.is_empty() { chip.dispatch_settings_events(user_events); } + + #[cfg(feature = "simulator")] + if !user_simulator_events.is_empty() { + chip.dispatch_simulator_settings_events(user_simulator_events); + } } // Render screen to an image @@ -299,15 +310,8 @@ impl DisplayDrawer { #[cfg(feature = "simulator")] RunMode::Simulator => { - let mut simulator = makair_simulator::MakAirSimulator::new(tx); - simulator.initialize(false); - - let settings_receiver = chip.init_settings_receiver(); - std::thread::spawn(move || { - while let Ok(message) = settings_receiver.recv() { - simulator.send_control_message(message); - } - }); + let simulator = crate::data::simulator::init(tx, chip.init_settings_receiver()); + chip.set_simulator(simulator); } } diff --git a/src/display/events.rs b/src/display/events.rs index 04c9d96..f660b52 100644 --- a/src/display/events.rs +++ b/src/display/events.rs @@ -20,11 +20,23 @@ use crate::chip::{ Chip, }; +#[cfg(feature = "simulator")] +use crate::chip::settings::SimulatorSettingActionRange; + use super::identifiers::Ids; use super::renderer::{DisplayRendererSettingsStateVisibility, DisplayRendererStates}; const FORCED_CLICKS_PRESET_SETTINGS_OPEN_DEBOUNCE_DELAY: Duration = Duration::from_secs(5); +#[derive(Debug)] +pub struct DisplayUiEventsRunResult { + pub has_events: bool, + pub intents: Vec, + pub events: Vec, + #[cfg(feature = "simulator")] + pub simulator_events: Vec, +} + pub struct DisplayUiEvents; impl DisplayUiEvents { @@ -33,9 +45,12 @@ impl DisplayUiEvents { ids: &Ids, chip: &mut Chip, states: &mut DisplayRendererStates, - ) -> (bool, Vec, Vec) { + ) -> DisplayUiEventsRunResult { let (mut has_events, mut intents, mut events) = (false, Vec::new(), Vec::new()); + #[cfg(feature = "simulator")] + let mut simulator_events = Vec::new(); + // Handle 'forced' clicks // Notice: those are non-user events, but rather interface clicks that are forced based \ // on data coming from the firmware itself, as to force the UI into a specific state \ @@ -55,7 +70,14 @@ impl DisplayUiEvents { } // Handle modal local clicks - if Self::run_modal_local_clicks(interface, ids, chip, states) { + if Self::run_modal_local_clicks( + interface, + ids, + chip, + states, + #[cfg(feature = "simulator")] + &mut simulator_events, + ) { has_events = true; } @@ -64,7 +86,13 @@ impl DisplayUiEvents { has_events = true; } - (has_events, intents, events) + DisplayUiEventsRunResult { + has_events, + intents, + events, + #[cfg(feature = "simulator")] + simulator_events, + } } fn run_forced_clicks(chip: &mut Chip, states: &mut DisplayRendererStates) -> bool { @@ -473,6 +501,9 @@ impl DisplayUiEvents { ids: &Ids, chip: &mut Chip, states: &mut DisplayRendererStates, + #[cfg(feature = "simulator")] simulator_events: &mut Vec< + crate::chip::settings::ChipSettingsSimulatorEvent, + >, ) -> bool { let mut has_events = false; @@ -631,7 +662,10 @@ impl DisplayUiEvents { ], { - chip.settings.advanced.group = SettingsAdvancedGroupTab::Simulator; + #[cfg(feature = "simulator")] + { + chip.settings.advanced.group = SettingsAdvancedGroupTab::Simulator; + } } }, @@ -671,7 +705,15 @@ impl DisplayUiEvents { ], { - chip.settings.advanced.switch_resistance(SettingActionRange::Less); + #[cfg(feature = "simulator")] + { + chip.settings.advanced.switch_resistance(SimulatorSettingActionRange::Less); + simulator_events.push( + crate::chip::settings::ChipSettingsSimulatorEvent::UpdateSetting( + makair_simulator::SimulatorSettingKind::Resistance + ) + ); + } } }, @@ -684,7 +726,15 @@ impl DisplayUiEvents { ], { - chip.settings.advanced.switch_resistance(SettingActionRange::More); + #[cfg(feature = "simulator")] + { + chip.settings.advanced.switch_resistance(SimulatorSettingActionRange::More); + simulator_events.push( + crate::chip::settings::ChipSettingsSimulatorEvent::UpdateSetting( + makair_simulator::SimulatorSettingKind::Resistance + ) + ); + } } }, @@ -697,7 +747,15 @@ impl DisplayUiEvents { ], { - chip.settings.advanced.switch_compliance(SettingActionRange::Less); + #[cfg(feature = "simulator")] + { + chip.settings.advanced.switch_compliance(SimulatorSettingActionRange::Less); + simulator_events.push( + crate::chip::settings::ChipSettingsSimulatorEvent::UpdateSetting( + makair_simulator::SimulatorSettingKind::Compliance + ) + ); + } } }, @@ -710,7 +768,15 @@ impl DisplayUiEvents { ], { - chip.settings.advanced.switch_compliance(SettingActionRange::More); + #[cfg(feature = "simulator")] + { + chip.settings.advanced.switch_compliance(SimulatorSettingActionRange::More); + simulator_events.push( + crate::chip::settings::ChipSettingsSimulatorEvent::UpdateSetting( + makair_simulator::SimulatorSettingKind::Compliance + ) + ); + } } }, @@ -723,7 +789,15 @@ impl DisplayUiEvents { ], { - chip.settings.advanced.switch_spontaneous_breath_rate(SettingActionRange::Less); + #[cfg(feature = "simulator")] + { + chip.settings.advanced.switch_spontaneous_breath_rate(SimulatorSettingActionRange::Less); + simulator_events.push( + crate::chip::settings::ChipSettingsSimulatorEvent::UpdateSetting( + makair_simulator::SimulatorSettingKind::SpontaneousBreathRate + ) + ); + } } }, @@ -736,7 +810,15 @@ impl DisplayUiEvents { ], { - chip.settings.advanced.switch_spontaneous_breath_rate(SettingActionRange::More); + #[cfg(feature = "simulator")] + { + chip.settings.advanced.switch_spontaneous_breath_rate(SimulatorSettingActionRange::More); + simulator_events.push( + crate::chip::settings::ChipSettingsSimulatorEvent::UpdateSetting( + makair_simulator::SimulatorSettingKind::SpontaneousBreathRate + ) + ); + } } }, @@ -749,7 +831,15 @@ impl DisplayUiEvents { ], { - chip.settings.advanced.switch_spontaneous_breath_effort(SettingActionRange::Less); + #[cfg(feature = "simulator")] + { + chip.settings.advanced.switch_spontaneous_breath_effort(SimulatorSettingActionRange::Less); + simulator_events.push( + crate::chip::settings::ChipSettingsSimulatorEvent::UpdateSetting( + makair_simulator::SimulatorSettingKind::SpontaneousBreathEffort + ) + ); + } } }, @@ -762,7 +852,15 @@ impl DisplayUiEvents { ], { - chip.settings.advanced.switch_spontaneous_breath_effort(SettingActionRange::More); + #[cfg(feature = "simulator")] + { + chip.settings.advanced.switch_spontaneous_breath_effort(SimulatorSettingActionRange::More); + simulator_events.push( + crate::chip::settings::ChipSettingsSimulatorEvent::UpdateSetting( + makair_simulator::SimulatorSettingKind::SpontaneousBreathEffort + ) + ); + } } }, @@ -775,7 +873,15 @@ impl DisplayUiEvents { ], { - chip.settings.advanced.switch_spontaneous_breath_duration(SettingActionRange::Less); + #[cfg(feature = "simulator")] + { + chip.settings.advanced.switch_spontaneous_breath_duration(SimulatorSettingActionRange::Less); + simulator_events.push( + crate::chip::settings::ChipSettingsSimulatorEvent::UpdateSetting( + makair_simulator::SimulatorSettingKind::SpontaneousBreathDuration + ) + ); + } } }, @@ -788,33 +894,57 @@ impl DisplayUiEvents { ], { - chip.settings.advanced.switch_spontaneous_breath_duration(SettingActionRange::More); + #[cfg(feature = "simulator")] + { + chip.settings.advanced.switch_spontaneous_breath_duration(SimulatorSettingActionRange::More); + simulator_events.push( + crate::chip::settings::ChipSettingsSimulatorEvent::UpdateSetting( + makair_simulator::SimulatorSettingKind::SpontaneousBreathDuration + ) + ); + } } }, { - "settings acceleration_factor previous", + "settings acceleration_percent previous", [ - ids.advanced_field_acceleration_factor_less, - ids.advanced_field_acceleration_factor_less_text, + ids.advanced_field_acceleration_percent_less, + ids.advanced_field_acceleration_percent_less_text, ], { - chip.settings.advanced.switch_acceleration_factor(SettingActionRange::Less); + #[cfg(feature = "simulator")] + { + chip.settings.advanced.switch_acceleration_percent(SimulatorSettingActionRange::Less); + simulator_events.push( + crate::chip::settings::ChipSettingsSimulatorEvent::UpdateSetting( + makair_simulator::SimulatorSettingKind::AccelerationPercent + ) + ); + } } }, { - "settings acceleration_factor next", + "settings acceleration_percent next", [ - ids.advanced_field_acceleration_factor_more, - ids.advanced_field_acceleration_factor_more_text, + ids.advanced_field_acceleration_percent_more, + ids.advanced_field_acceleration_percent_more_text, ], { - chip.settings.advanced.switch_acceleration_factor(SettingActionRange::More); + #[cfg(feature = "simulator")] + { + chip.settings.advanced.switch_acceleration_percent(SimulatorSettingActionRange::More); + simulator_events.push( + crate::chip::settings::ChipSettingsSimulatorEvent::UpdateSetting( + makair_simulator::SimulatorSettingKind::AccelerationPercent + ) + ); + } } } diff --git a/src/display/identifiers.rs b/src/display/identifiers.rs index c5a63af..f97ddb1 100644 --- a/src/display/identifiers.rs +++ b/src/display/identifiers.rs @@ -428,13 +428,13 @@ widget_ids!(pub struct Ids { advanced_field_spontaneous_breath_duration_less, advanced_field_spontaneous_breath_duration_less_text, - advanced_field_acceleration_factor_text, - advanced_field_acceleration_factor_value, - advanced_field_acceleration_factor_value_wrapper, - advanced_field_acceleration_factor_more, - advanced_field_acceleration_factor_more_text, - advanced_field_acceleration_factor_less, - advanced_field_acceleration_factor_less_text, + advanced_field_acceleration_percent_text, + advanced_field_acceleration_percent_value, + advanced_field_acceleration_percent_value_wrapper, + advanced_field_acceleration_percent_more, + advanced_field_acceleration_percent_more_text, + advanced_field_acceleration_percent_less, + advanced_field_acceleration_percent_less_text, advanced_text_date_text, advanced_text_date_value, diff --git a/src/display/renderer.rs b/src/display/renderer.rs index 70a0e1e..383afcf 100644 --- a/src/display/renderer.rs +++ b/src/display/renderer.rs @@ -17,7 +17,7 @@ use crate::utilities::{ }; use super::data::*; -use super::events::DisplayUiEvents; +use super::events::{DisplayUiEvents, DisplayUiEventsRunResult}; use super::fonts::Fonts; use super::identifiers::{Ids, ImageIds}; use super::screen::{Screen, ScreenModalsOpen}; @@ -116,6 +116,15 @@ impl Default for DisplayRendererSettingsState { } } +pub struct DisplayRendererRunEventsResult { + pub has_heartbeat: bool, + pub has_user_events: bool, + pub user_intents: Vec, + pub user_events: Vec, + #[cfg(feature = "simulator")] + pub user_simulator_events: Vec, +} + #[allow(clippy::new_ret_no_self)] impl DisplayRendererBuilder { pub fn new(fonts: Fonts, ids: Ids, images: ImageIds) -> DisplayRenderer { @@ -163,10 +172,15 @@ impl DisplayRenderer { chip: &mut Chip, last_heartbeat: &Instant, tick_time: &Instant, - ) -> (bool, bool, Vec, Vec) { + ) -> DisplayRendererRunEventsResult { // Run all UI events (defer to sub-handler) - let (has_user_events, user_intents, user_events) = - DisplayUiEvents::run(interface, &self.ids, chip, &mut self.states); + let DisplayUiEventsRunResult { + has_events, + intents, + events, + #[cfg(feature = "simulator")] + simulator_events, + } = DisplayUiEvents::run(interface, &self.ids, chip, &mut self.states); // Check if should run heartbeat? (ie. if it should be sent to the firmware) let mut has_heartbeat = false; @@ -175,7 +189,14 @@ impl DisplayRenderer { has_heartbeat = true; } - (has_heartbeat, has_user_events, user_intents, user_events) + DisplayRendererRunEventsResult { + has_heartbeat, + has_user_events: has_events, + user_intents: intents, + user_events: events, + #[cfg(feature = "simulator")] + user_simulator_events: simulator_events, + } } pub fn has_state_moderate_framerate(&self) -> bool { diff --git a/src/display/screen.rs b/src/display/screen.rs index eb8b692..4e7eb5d 100644 --- a/src/display/screen.rs +++ b/src/display/screen.rs @@ -988,23 +988,29 @@ impl<'a> Screen<'a> { text_time_ids: gen_render_advanced_settings_text_ids!(self, time), text_timezone_ids: gen_render_advanced_settings_text_ids!(self, timezone), + #[cfg(feature = "simulator")] field_resistance_ids: gen_render_advanced_settings_field_ids!(self, resistance), + #[cfg(feature = "simulator")] field_compliance_ids: gen_render_advanced_settings_field_ids!(self, compliance), + #[cfg(feature = "simulator")] field_spontaneous_breath_rate_ids: gen_render_advanced_settings_field_ids!( self, spontaneous_breath_rate ), + #[cfg(feature = "simulator")] field_spontaneous_breath_effort_ids: gen_render_advanced_settings_field_ids!( self, spontaneous_breath_effort ), + #[cfg(feature = "simulator")] field_spontaneous_breath_duration_ids: gen_render_advanced_settings_field_ids!( self, spontaneous_breath_duration ), - field_acceleration_factor_ids: gen_render_advanced_settings_field_ids!( + #[cfg(feature = "simulator")] + field_acceleration_percent_ids: gen_render_advanced_settings_field_ids!( self, - acceleration_factor + acceleration_percent ), }, )); diff --git a/src/locale/advanced.rs b/src/locale/advanced.rs index a132d94..518b69a 100644 --- a/src/locale/advanced.rs +++ b/src/locale/advanced.rs @@ -11,6 +11,7 @@ pub fn group_tab_to_locale(group_tab: SettingsAdvancedGroupTab) -> String { let locale_key = match group_tab { SettingsAdvancedGroupTab::Statistics => "statistics", SettingsAdvancedGroupTab::Settings => "settings", + #[cfg(feature = "simulator")] SettingsAdvancedGroupTab::Simulator => "simulator", }; diff --git a/src/main.rs b/src/main.rs index ba70edb..7a969f8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,7 +29,7 @@ mod display; mod locale; #[cfg(feature = "lora")] mod lora; -mod serial; +mod data; mod utilities; mod widget; diff --git a/src/widget/advanced_settings.rs b/src/widget/advanced_settings.rs index fe11280..289eec2 100644 --- a/src/widget/advanced_settings.rs +++ b/src/widget/advanced_settings.rs @@ -69,12 +69,18 @@ pub struct Config<'a> { pub text_time_ids: TextWidgetIds, pub text_timezone_ids: TextWidgetIds, + #[cfg(feature = "simulator")] pub field_resistance_ids: FieldWidgetIds, + #[cfg(feature = "simulator")] pub field_compliance_ids: FieldWidgetIds, + #[cfg(feature = "simulator")] pub field_spontaneous_breath_rate_ids: FieldWidgetIds, + #[cfg(feature = "simulator")] pub field_spontaneous_breath_effort_ids: FieldWidgetIds, + #[cfg(feature = "simulator")] pub field_spontaneous_breath_duration_ids: FieldWidgetIds, - pub field_acceleration_factor_ids: FieldWidgetIds, + #[cfg(feature = "simulator")] + pub field_acceleration_percent_ids: FieldWidgetIds, } struct Field { @@ -173,6 +179,7 @@ fn form<'a>(master: &mut ControlWidget<'a>, config: &Config, parent_size: (f64, match config.advanced_settings.group { SettingsAdvancedGroupTab::Statistics => form_statistics(master, config), SettingsAdvancedGroupTab::Settings => form_settings(master, config), + #[cfg(feature = "simulator")] SettingsAdvancedGroupTab::Simulator => form_simulator(master, config), } } @@ -395,6 +402,7 @@ fn form_settings<'a>(master: &mut ControlWidget<'a>, config: &Config) { ); } +#[cfg(feature = "simulator")] fn form_simulator<'a>(master: &mut ControlWidget<'a>, config: &Config) { draw_field( 0, @@ -463,8 +471,8 @@ fn form_simulator<'a>(master: &mut ControlWidget<'a>, config: &Config) { config, Field { label_text: APP_I18N.t("modal-advanced-simulator-acceleration-factor"), - value_text: config.advanced_settings.acceleration_factor.to_string(), - ids: config.field_acceleration_factor_ids, + value_text: config.advanced_settings.acceleration_percent.to_string(), + ids: config.field_acceleration_percent_ids, }, ); } From fc8736501c8e0d541f20b0a0eee43b858a457ff6 Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Sat, 27 Nov 2021 20:33:40 +0100 Subject: [PATCH 15/29] Update to Rust 2021 Edition & update dependencies --- Cargo.lock | 27 ++++++++++++++++++++++----- Cargo.toml | 2 +- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c07f4c2..7a11ae9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -480,6 +480,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "cty" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" + [[package]] name = "daggy" version = "0.5.0" @@ -1155,6 +1161,7 @@ dependencies = [ [[package]] name = "makair-simulator" version = "0.1.0" +source = "git+https://github.com/makers-for-life/makair-simulator?rev=8060cf63e387ee0fc4ecbce34af057c3aa5ad987#8060cf63e387ee0fc4ecbce34af057c3aa5ad987" dependencies = [ "cc", "log", @@ -1805,11 +1812,21 @@ dependencies = [ [[package]] name = "raw-window-handle" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a441a7a6c80ad6473bd4b74ec1c9a4c951794285bf941c2126f607c72e48211" +checksum = "e28f55143d0548dad60bb4fbdc835a3d7ac6acc3324506450c5fdd6e42903a76" dependencies = [ "libc", + "raw-window-handle 0.4.2", +] + +[[package]] +name = "raw-window-handle" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba75eee94a9d5273a68c9e1e105d9cffe1ef700532325788389e5a83e2522b7" +dependencies = [ + "cty", ] [[package]] @@ -1975,9 +1992,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "self_cell" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ac753e6625df1711012c6469644ddd9b6338be1e4abf235c3a8817191411ae1" +checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af" [[package]] name = "serde" @@ -2629,7 +2646,7 @@ dependencies = [ "objc", "parking_lot", "percent-encoding", - "raw-window-handle", + "raw-window-handle 0.3.4", "smithay-client-toolkit 0.12.3", "wayland-client 0.28.6", "winapi 0.3.9", diff --git a/Cargo.toml b/Cargo.toml index 998b775..c04941d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "2.4.0" description = "Control UI for the MakAir open source ventilator." readme = "README.md" license-file = "LICENSE.md" -edition = "2018" +edition = "2021" homepage = "https://github.com/makers-for-life/makair" repository = "https://github.com/makers-for-life/makair-control-ui" keywords = ["covid-19", "fusion-360", "cad", "covid", "coronavirus", "sars-cov-2", "nucleo-board", "covid-respirator", "makair-respirators", "medical", "ards"] From 7484e66d538f4b03e4db925a6e967b889c354305 Mon Sep 17 00:00:00 2001 From: Benhalor Date: Sat, 27 Nov 2021 21:21:01 +0100 Subject: [PATCH 16/29] update simulator dependecy version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c04941d..1010fb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,7 @@ conrod_core = "0.71" sysfs_gpio = { version = "0.6", optional = true } rn2903 = { git = "https://github.com/waxzce/lora-rust-rn2903-rn2483.git", rev = "b086057ba096920abef3870ad0cefa2c80a343e2", optional = true } makair-telemetry = { git = "https://github.com/makers-for-life/makair-telemetry", rev = "184185d4301fa7343018cd6733e1fb23e2cb032e", default-features = false } -makair-simulator = { git = "https://github.com/makers-for-life/makair-simulator", rev = "8060cf63e387ee0fc4ecbce34af057c3aa5ad987", optional = true } +makair-simulator = { git = "https://github.com/makers-for-life/makair-simulator", rev = "6a5ea65e65f5919cade4417d1612fe2a0f4db485", optional = true } [features] default = ["serial"] From 9c7383cbf77b003d1b80cd4b5a3ba8d87cbd289b Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Sat, 27 Nov 2021 20:42:09 +0100 Subject: [PATCH 17/29] Fix coding style --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 7a969f8..75cb5d3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,11 +25,11 @@ extern crate conrod_core; mod chip; mod config; +mod data; mod display; mod locale; #[cfg(feature = "lora")] mod lora; -mod data; mod utilities; mod widget; From 54e4887cfa1fc5cf073971eccc0d4a72c83110df Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Sat, 27 Nov 2021 23:52:26 +0100 Subject: [PATCH 18/29] Hide simulator setting when not running in simulator mode --- src/config/arguments.rs | 1 + src/config/environment.rs | 20 ++++++++++++++++++-- src/display/screen.rs | 4 ++-- src/widget/advanced_settings.rs | 6 +++--- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/config/arguments.rs b/src/config/arguments.rs index 635146c..6ead1a2 100644 --- a/src/config/arguments.rs +++ b/src/config/arguments.rs @@ -12,6 +12,7 @@ const LOG_LEVEL_DEFAULT: &str = "debug"; #[cfg(not(debug_assertions))] const LOG_LEVEL_DEFAULT: &str = "warn"; +#[derive(Debug, Clone, PartialEq, Eq)] pub enum RunMode { #[cfg(feature = "serial")] Port { diff --git a/src/config/environment.rs b/src/config/environment.rs index c9ecbe4..0a8ac05 100644 --- a/src/config/environment.rs +++ b/src/config/environment.rs @@ -3,9 +3,27 @@ // Copyright: 2020, Makers For Life // License: Public Domain License +use lazy_static::lazy_static; + +use crate::config::arguments::RunMode; +use crate::APP_ARGS; + pub const RUNTIME_NAME: &str = env!("CARGO_PKG_NAME"); pub const RUNTIME_VERSION: &str = env!("CARGO_PKG_VERSION"); +lazy_static! { + pub static ref SIMULATOR_ENABLED: bool = { + #[cfg(not(feature = "simulator"))] + let enabled = false; + + #[cfg(feature = "simulator")] + let enabled = APP_ARGS.mode == RunMode::Simulator; + + enabled + }; + pub static ref ADVANCED_SETTINGS_GROUP_TABS_COUNT: usize = if *SIMULATOR_ENABLED { 3 } else { 2 }; +} + pub const WINDOW_ICON_WIDTH: u32 = 512; pub const WINDOW_ICON_HEIGHT: u32 = 512; @@ -265,8 +283,6 @@ pub const ADVANCED_SETTINGS_LINES_COUNT: usize = 15; pub const ADVANCED_SETTINGS_LINE_MARGIN_TOP: f64 = 8.0; pub const ADVANCED_SETTINGS_LINE_FONT_SIZE: u32 = 14; pub const ADVANCED_SETTINGS_LINE_VALUE_PADDING_LEFT: f64 = 240.0; -pub const ADVANCED_SETTINGS_GROUP_TABS_COUNT: usize = - if cfg!(feature = "simulator") { 3 } else { 2 }; pub const ADVANCED_SETTINGS_LINE_VALUE_EMPTY: &str = "--"; pub const MODE_SETTINGS_MODAL_PADDING: f64 = 20.0; diff --git a/src/display/screen.rs b/src/display/screen.rs index 4e7eb5d..2829499 100644 --- a/src/display/screen.rs +++ b/src/display/screen.rs @@ -969,14 +969,14 @@ impl<'a> Screen<'a> { advanced_group_wrapper: self.ids.advanced_group_wrapper, advanced_form_wrapper: self.ids.advanced_form_wrapper, - advanced_group_tab_buttons: [ + advanced_group_tab_buttons: vec![ self.ids.advanced_group_tab_statistics_button, self.ids.advanced_group_tab_settings_button, #[cfg(feature = "simulator")] self.ids.advanced_group_tab_simulator_button, ], - advanced_group_tab_texts: [ + advanced_group_tab_texts: vec![ self.ids.advanced_group_tab_statistics_text, self.ids.advanced_group_tab_settings_text, #[cfg(feature = "simulator")] diff --git a/src/widget/advanced_settings.rs b/src/widget/advanced_settings.rs index 289eec2..e3e5592 100644 --- a/src/widget/advanced_settings.rs +++ b/src/widget/advanced_settings.rs @@ -60,8 +60,8 @@ pub struct Config<'a> { pub advanced_group_wrapper: WidgetId, pub advanced_form_wrapper: WidgetId, - pub advanced_group_tab_buttons: [WidgetId; ADVANCED_SETTINGS_GROUP_TABS_COUNT], - pub advanced_group_tab_texts: [WidgetId; ADVANCED_SETTINGS_GROUP_TABS_COUNT], + pub advanced_group_tab_buttons: Vec, + pub advanced_group_tab_texts: Vec, pub field_locale_ids: FieldWidgetIds, @@ -131,7 +131,7 @@ fn group<'a>(master: &mut ControlWidget<'a>, config: &Config, parent_size: (f64, ); // Render all group tabs - for index in 0..ADVANCED_SETTINGS_GROUP_TABS_COUNT { + for index in 0..*ADVANCED_SETTINGS_GROUP_TABS_COUNT { group_tab( master, config, From 7427c874d6a35f4a6693ff53e2d0fdcf945263bd Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Sun, 28 Nov 2021 00:01:44 +0100 Subject: [PATCH 19/29] Fix coding style and warnings --- Cargo.lock | 2 +- src/config/environment.rs | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7a11ae9..21fce7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1161,7 +1161,7 @@ dependencies = [ [[package]] name = "makair-simulator" version = "0.1.0" -source = "git+https://github.com/makers-for-life/makair-simulator?rev=8060cf63e387ee0fc4ecbce34af057c3aa5ad987#8060cf63e387ee0fc4ecbce34af057c3aa5ad987" +source = "git+https://github.com/makers-for-life/makair-simulator?rev=6a5ea65e65f5919cade4417d1612fe2a0f4db485#6a5ea65e65f5919cade4417d1612fe2a0f4db485" dependencies = [ "cc", "log", diff --git a/src/config/environment.rs b/src/config/environment.rs index 0a8ac05..389dca5 100644 --- a/src/config/environment.rs +++ b/src/config/environment.rs @@ -5,9 +5,6 @@ use lazy_static::lazy_static; -use crate::config::arguments::RunMode; -use crate::APP_ARGS; - pub const RUNTIME_NAME: &str = env!("CARGO_PKG_NAME"); pub const RUNTIME_VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -17,11 +14,12 @@ lazy_static! { let enabled = false; #[cfg(feature = "simulator")] - let enabled = APP_ARGS.mode == RunMode::Simulator; + let enabled = crate::APP_ARGS.mode == crate::config::arguments::RunMode::Simulator; enabled }; - pub static ref ADVANCED_SETTINGS_GROUP_TABS_COUNT: usize = if *SIMULATOR_ENABLED { 3 } else { 2 }; + pub static ref ADVANCED_SETTINGS_GROUP_TABS_COUNT: usize = + if *SIMULATOR_ENABLED { 3 } else { 2 }; } pub const WINDOW_ICON_WIDTH: u32 = 512; From 3872d0caf484334a7d471f32cc72b43e8b667459 Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Sun, 28 Nov 2021 00:16:21 +0100 Subject: [PATCH 20/29] Update to conrod 0.76 --- Cargo.lock | 48 ++++++++++++++++++------------------------------ Cargo.toml | 6 +++--- 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 21fce7a..4d890a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -287,9 +287,9 @@ dependencies = [ [[package]] name = "conrod_core" -version = "0.71.0" +version = "0.76.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c07b39486d6ab17012506a6ed359efdfbfcc7b616e4ff52eaf75bc6fd3c03f9" +checksum = "e771d90d3a662af197c2772cdf9d71d858e8a56f06c16fc3c791144340444354" dependencies = [ "conrod_derive", "copypasta", @@ -303,9 +303,9 @@ dependencies = [ [[package]] name = "conrod_derive" -version = "0.71.0" +version = "0.76.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7b034b19c35f46461439c130fcebada7e67c7379a2f91a259a83f9e9643085e" +checksum = "1aedfc4d8bd72b652d5e1678dc388627a24307d0d39ad85ab771fe5dbbaddd2f" dependencies = [ "proc-macro2 1.0.32", "quote 1.0.10", @@ -314,9 +314,9 @@ dependencies = [ [[package]] name = "conrod_glium" -version = "0.71.0" +version = "0.76.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea62a2faf29da55238e515cf0b32d8a554488a606a84a0f176a7d577c76499e5" +checksum = "ee393fffdb7333e404e1625099dbddd1dd95ea2a0e43227bb1fcd27c80d7db0d" dependencies = [ "conrod_core", "glium", @@ -324,9 +324,9 @@ dependencies = [ [[package]] name = "conrod_winit" -version = "0.71.0" +version = "0.76.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe64a64440965cbb4897bd4c35631d34304426e683a4dd86fd00074cecb514" +checksum = "8ba80e6493619a9323b69710e92752a40705712f604096e99e8281a57fd7e781" [[package]] name = "copypasta" @@ -873,7 +873,7 @@ dependencies = [ "byteorder", "color_quant", "num-iter", - "num-rational 0.3.2", + "num-rational", "num-traits", "png", ] @@ -1427,23 +1427,23 @@ dependencies = [ [[package]] name = "num" -version = "0.2.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" +checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" dependencies = [ "num-bigint", "num-complex", "num-integer", "num-iter", - "num-rational 0.2.4", + "num-rational", "num-traits", ] [[package]] name = "num-bigint" -version = "0.2.6" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" +checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" dependencies = [ "autocfg", "num-integer", @@ -1452,11 +1452,10 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.2.4" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" dependencies = [ - "autocfg", "num-traits", ] @@ -1481,18 +1480,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-rational" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-rational" version = "0.3.2" @@ -1500,6 +1487,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" dependencies = [ "autocfg", + "num-bigint", "num-integer", "num-traits", ] @@ -1723,7 +1711,7 @@ checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c" [[package]] name = "plotters-conrod" version = "0.3.11" -source = "git+https://github.com/dsferruzza/plotters-conrod?branch=conrod0.71-glium0.28-winit0.23#1e4da66691550584d9e1a2351d400513739269b9" +source = "git+https://github.com/dsferruzza/plotters-conrod?branch=conrod0.71-glium0.28-winit0.23#c00dedb66fb5f58c77f28c23181bdc85b965ff1f" dependencies = [ "cc", "conrod_core", diff --git a/Cargo.toml b/Cargo.toml index 1010fb5..5385715 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,9 +34,9 @@ image = { version = "0.23", default-features = false, features = ["png"] } glium = "0.28" plotters = { version = "0.3", default_features = false, features = ["chrono", "area_series"] } plotters-conrod = { git = "https://github.com/dsferruzza/plotters-conrod", branch = "conrod0.71-glium0.28-winit0.23" } -conrod_glium = "0.71" -conrod_winit = "0.71" -conrod_core = "0.71" +conrod_glium = "0.76" +conrod_winit = "0.76" +conrod_core = "0.76" sysfs_gpio = { version = "0.6", optional = true } rn2903 = { git = "https://github.com/waxzce/lora-rust-rn2903-rn2483.git", rev = "b086057ba096920abef3870ad0cefa2c80a343e2", optional = true } makair-telemetry = { git = "https://github.com/makers-for-life/makair-telemetry", rev = "184185d4301fa7343018cd6733e1fb23e2cb032e", default-features = false } From 1da073da5075fed34be849182107306178dd4aee Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Sun, 28 Nov 2021 12:16:56 +0100 Subject: [PATCH 21/29] Update to glium 0.30 and winit 0.25 --- Cargo.lock | 307 ++++++++++++++++++++--------------------- Cargo.toml | 10 +- src/display/support.rs | 2 +- 3 files changed, 157 insertions(+), 162 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4d890a6..8f1a87b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -214,7 +214,7 @@ dependencies = [ "num-integer", "num-traits", "time", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -234,14 +234,14 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3a093d6fed558e5fe24c3dfc85a68bb68f1c824f440d3ba5aca189e2998786b" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] name = "cocoa" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54201c07dcf3a5ca33fececb8042aed767ee4bfd5a0235a8ceabcda956044b2" +checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832" dependencies = [ "bitflags", "block", @@ -288,8 +288,7 @@ dependencies = [ [[package]] name = "conrod_core" version = "0.76.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e771d90d3a662af197c2772cdf9d71d858e8a56f06c16fc3c791144340444354" +source = "git+https://github.com/dsferruzza/conrod?branch=update-glium-winit#5506360853c60e57a8ae5ac0f22b4a97bbdef92b" dependencies = [ "conrod_derive", "copypasta", @@ -304,8 +303,7 @@ dependencies = [ [[package]] name = "conrod_derive" version = "0.76.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aedfc4d8bd72b652d5e1678dc388627a24307d0d39ad85ab771fe5dbbaddd2f" +source = "git+https://github.com/dsferruzza/conrod?branch=update-glium-winit#5506360853c60e57a8ae5ac0f22b4a97bbdef92b" dependencies = [ "proc-macro2 1.0.32", "quote 1.0.10", @@ -315,8 +313,7 @@ dependencies = [ [[package]] name = "conrod_glium" version = "0.76.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee393fffdb7333e404e1625099dbddd1dd95ea2a0e43227bb1fcd27c80d7db0d" +source = "git+https://github.com/dsferruzza/conrod?branch=update-glium-winit#5506360853c60e57a8ae5ac0f22b4a97bbdef92b" dependencies = [ "conrod_core", "glium", @@ -325,8 +322,7 @@ dependencies = [ [[package]] name = "conrod_winit" version = "0.76.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ba80e6493619a9323b69710e92752a40705712f604096e99e8281a57fd7e781" +source = "git+https://github.com/dsferruzza/conrod?branch=update-glium-winit#5506360853c60e57a8ae5ac0f22b4a97bbdef92b" [[package]] name = "copypasta" @@ -443,17 +439,52 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "crossbeam" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae5588f6b3c3cb05239e90bd110f257254aecd01e4635400391aeae07497845" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-channel", + "crossbeam-deque 0.8.1", + "crossbeam-epoch 0.9.5", + "crossbeam-queue", + "crossbeam-utils 0.8.5", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils 0.8.5", +] + [[package]] name = "crossbeam-deque" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c20ff29ded3204c5106278a81a38f4b482636ed4fa1e6cfbeef193291beb29ed" dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", + "crossbeam-epoch 0.8.2", + "crossbeam-utils 0.7.2", "maybe-uninit", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-epoch 0.9.5", + "crossbeam-utils 0.8.5", +] + [[package]] name = "crossbeam-epoch" version = "0.8.2" @@ -462,13 +493,36 @@ checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ "autocfg", "cfg-if 0.1.10", - "crossbeam-utils", + "crossbeam-utils 0.7.2", "lazy_static", "maybe-uninit", "memoffset 0.5.6", "scopeguard", ] +[[package]] +name = "crossbeam-epoch" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils 0.8.5", + "lazy_static", + "memoffset 0.6.4", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b10ddc024425c88c2ad148c1b0fd53f4c6d38db9697c9f1588381212fa657c9" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils 0.8.5", +] + [[package]] name = "crossbeam-utils" version = "0.7.2" @@ -480,6 +534,16 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "crossbeam-utils" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +dependencies = [ + "cfg-if 1.0.0", + "lazy_static", +] + [[package]] name = "cty" version = "0.2.2" @@ -587,7 +651,7 @@ checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" dependencies = [ "libc", "redox_users", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -691,22 +755,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - [[package]] name = "generic-array" version = "0.14.4" @@ -747,25 +795,25 @@ dependencies = [ [[package]] name = "glium" -version = "0.28.0" +version = "0.30.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eeec7b733d14519e2541f4cc8a1230de9143d4ec439dd51b6c048d8ec991759" +checksum = "506a2aa1564891d447ae5d1ba37519a8efd6d01ea3e7952da81aa30430c90007" dependencies = [ "backtrace", "fnv", "gl_generator", "glutin", "lazy_static", - "memoffset 0.5.6", + "memoffset 0.6.4", "smallvec", "takeable-option", ] [[package]] name = "glutin" -version = "0.25.1" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8bae26a39a728b003e9fad473ea89527de0de050143b4df866f18bb154bc86e" +checksum = "762d6cd2e1b855d99668ebe591cc9058659d85ac39a9a2078000eb122ddba8f0" dependencies = [ "android_glue", "cgl", @@ -777,14 +825,14 @@ dependencies = [ "glutin_glx_sys", "glutin_wgl_sys", "lazy_static", - "libloading 0.6.7", + "libloading 0.7.2", "log", "objc", "osmesa-sys", "parking_lot", "wayland-client 0.28.6", "wayland-egl", - "winapi 0.3.9", + "winapi", "winit", ] @@ -795,7 +843,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2abb6aa55523480c4adc5a56bbaa249992e2dddb2fc63dc96e04a3355364c211" dependencies = [ "gl_generator", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -959,15 +1007,6 @@ dependencies = [ "libc", ] -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", -] - [[package]] name = "jni-sys" version = "0.3.0" @@ -983,16 +1022,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "khronos_api" version = "3.1.0" @@ -1005,12 +1034,6 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "libc" version = "0.2.108" @@ -1044,7 +1067,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" dependencies = [ "cfg-if 1.0.0", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1054,7 +1077,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afe203d669ec979b7128619bae5a63b7b42e9203c1b29146079ee05e2f604b52" dependencies = [ "cfg-if 1.0.0", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1210,7 +1233,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" dependencies = [ "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1267,52 +1290,43 @@ dependencies = [ [[package]] name = "mio" -version = "0.6.23" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", "libc", "log", "miow", - "net2", - "slab", - "winapi 0.2.8", + "ntapi", + "winapi", ] [[package]] -name = "mio-extras" -version = "2.0.6" +name = "mio-misc" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" +checksum = "0ddf05411bb159cdb5801bb10002afb66cb4572be656044315e363460ce69dc2" dependencies = [ - "lazycell", + "crossbeam", + "crossbeam-queue", "log", "mio", - "slab", ] [[package]] name = "miow" -version = "0.2.2" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", + "winapi", ] [[package]] name = "ndk" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb167c1febed0a496639034d0c76b3b74263636045db5489eee52143c246e73" +checksum = "8794322172319b972f528bf90c6b467be0079f1fa82780ffb431088e741a73ab" dependencies = [ "jni-sys", "ndk-sys", @@ -1322,9 +1336,9 @@ dependencies = [ [[package]] name = "ndk-glue" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf399b8b7a39c6fb153c4ec32c72fd5fe789df24a647f229c239aa7adb15241" +checksum = "c5caf0c24d51ac1c905c27d4eda4fa0635bbe0de596b8f79235e0b17a4d29385" dependencies = [ "lazy_static", "libc", @@ -1341,7 +1355,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05d1c6307dc424d0f65b9b06e94f88248e6305726b14729fd67a5e47b2dc481d" dependencies = [ "darling", - "proc-macro-crate", + "proc-macro-crate 0.1.5", "proc-macro2 1.0.32", "quote 1.0.10", "syn", @@ -1353,17 +1367,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121" -[[package]] -name = "net2" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", -] - [[package]] name = "nix" version = "0.14.1" @@ -1425,6 +1428,15 @@ dependencies = [ "version_check", ] +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi", +] + [[package]] name = "num" version = "0.3.1" @@ -1513,9 +1525,9 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.4.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca565a7df06f3d4b485494f25ba05da1435950f4dc263440eda7a6fa9b8e36e4" +checksum = "3f9bd055fb730c4f8f4f57d45d35cd6b3f0980535b056dc7ff119cee6a66ed6f" dependencies = [ "derivative", "num_enum_derive", @@ -1523,11 +1535,11 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.4.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffa5a33ddddfee04c0283a7653987d634e880347e96b5b2ed64de07efb59db9d" +checksum = "486ea01961c4a818096de679a8b740b26d9033146ac5291b1c98557658f8cdd9" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.1.0", "proc-macro2 1.0.32", "quote 1.0.10", "syn", @@ -1632,7 +1644,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1711,7 +1723,7 @@ checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c" [[package]] name = "plotters-conrod" version = "0.3.11" -source = "git+https://github.com/dsferruzza/plotters-conrod?branch=conrod0.71-glium0.28-winit0.23#c00dedb66fb5f58c77f28c23181bdc85b965ff1f" +source = "git+https://github.com/dsferruzza/plotters-conrod?branch=conrod0.71-glium0.28-winit0.23#51d8562dbc800a2d7d463c6a2ddb0f23968206a9" dependencies = [ "cc", "conrod_core", @@ -1741,6 +1753,16 @@ dependencies = [ "toml", ] +[[package]] +name = "proc-macro-crate" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" +dependencies = [ + "thiserror", + "toml", +] + [[package]] name = "proc-macro-hack" version = "0.5.19" @@ -1871,9 +1893,9 @@ dependencies = [ [[package]] name = "rust-embed" -version = "6.2.0" +version = "6.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be44a6694859b7cfc955699935944a6844aa9fe416aeda5d40829e3e38dfee6" +checksum = "d40377bff8cceee81e28ddb73ac97f5c2856ce5522f0b260b763f434cdfae602" dependencies = [ "include-flate", "rust-embed-impl", @@ -1883,9 +1905,9 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "6.1.0" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f567ca01565c50c67b29e535f5f67b8ea8aeadaeed16a88f10792ab57438b957" +checksum = "94e763e24ba2bf0c72bc6be883f967f794a019fafd1b86ba1daff9c91a7edd30" dependencies = [ "proc-macro2 1.0.32", "quote 1.0.10", @@ -1896,9 +1918,9 @@ dependencies = [ [[package]] name = "rust-embed-utils" -version = "7.0.0" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6116e7ab9ea963f60f2f20291d8fcf6c7273192cdd7273b3c80729a9605c97b2" +checksum = "ad22c7226e4829104deab21df575e995bfbc4adfad13a595e387477f238c1aec" dependencies = [ "sha2", "walkdir", @@ -1932,8 +1954,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f61411055101f7b60ecf1041d87fb74205fb20b0c7a723f07ef39174cf6b4c0" dependencies = [ "approx", - "crossbeam-deque", - "crossbeam-utils", + "crossbeam-deque 0.7.4", + "crossbeam-utils 0.7.2", "linked-hash-map", "num_cpus", "ordered-float", @@ -2060,7 +2082,7 @@ dependencies = [ "mach 0.2.3", "nix 0.14.1", "regex", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2086,12 +2108,6 @@ dependencies = [ "libc", ] -[[package]] -name = "slab" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" - [[package]] name = "smallvec" version = "1.7.0" @@ -2252,7 +2268,7 @@ checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", "wasi", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2352,7 +2368,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" dependencies = [ "same-file", - "winapi 0.3.9", + "winapi", "winapi-util", ] @@ -2567,12 +2583,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - [[package]] name = "winapi" version = "0.3.9" @@ -2583,12 +2593,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -2601,7 +2605,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2612,9 +2616,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "winit" -version = "0.23.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5bc559da567d8aa671bbcd08304d49e982c7bf2cb91e10288b9188931c1b772" +checksum = "79610794594d5e86be473ef7763f604f2159cbac8c94debd00df8fb41e86c2f8" dependencies = [ "bitflags", "cocoa", @@ -2627,7 +2631,7 @@ dependencies = [ "libc", "log", "mio", - "mio-extras", + "mio-misc", "ndk", "ndk-glue", "ndk-sys", @@ -2635,22 +2639,13 @@ dependencies = [ "parking_lot", "percent-encoding", "raw-window-handle 0.3.4", + "scopeguard", "smithay-client-toolkit 0.12.3", "wayland-client 0.28.6", - "winapi 0.3.9", + "winapi", "x11-dl", ] -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "x11-clipboard" version = "0.5.3" diff --git a/Cargo.toml b/Cargo.toml index 5385715..3606c3f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,14 +29,14 @@ fluent = "0.16" intl-memoizer = "0.5" unic-langid = "0.9" inflate = "0.4" -winit = "0.23" +winit = "0.25" image = { version = "0.23", default-features = false, features = ["png"] } -glium = "0.28" +glium = "0.30" plotters = { version = "0.3", default_features = false, features = ["chrono", "area_series"] } plotters-conrod = { git = "https://github.com/dsferruzza/plotters-conrod", branch = "conrod0.71-glium0.28-winit0.23" } -conrod_glium = "0.76" -conrod_winit = "0.76" -conrod_core = "0.76" +conrod_glium = { git = "https://github.com/dsferruzza/conrod", branch = "update-glium-winit" } +conrod_winit = { git = "https://github.com/dsferruzza/conrod", branch = "update-glium-winit" } +conrod_core = { git = "https://github.com/dsferruzza/conrod", branch = "update-glium-winit" } sysfs_gpio = { version = "0.6", optional = true } rn2903 = { git = "https://github.com/waxzce/lora-rust-rn2903-rn2483.git", rev = "b086057ba096920abef3870ad0cefa2c80a343e2", optional = true } makair-telemetry = { git = "https://github.com/makers-for-life/makair-telemetry", rev = "184185d4301fa7343018cd6733e1fb23e2cb032e", default-features = false } diff --git a/src/display/support.rs b/src/display/support.rs index 932ef7d..ca274ca 100644 --- a/src/display/support.rs +++ b/src/display/support.rs @@ -20,4 +20,4 @@ impl WinitWindow for GliumDisplayWinitWrapper { // Conversion functions for converting between types from glium's version of `winit` and \ // `conrod_core`. -conrod_winit::v023_conversion_fns!(); +conrod_winit::v025_conversion_fns!(); From a40be79e616810521f84315fd8eb0d062dbb7186 Mon Sep 17 00:00:00 2001 From: Gabriel Moneyron Date: Sun, 28 Nov 2021 15:42:57 +0100 Subject: [PATCH 22/29] add unit to simulator tab --- res/locales/de.ftl | 7 +++++ res/locales/en.ftl | 9 +++++- res/locales/es.ftl | 7 +++++ res/locales/fr.ftl | 7 +++++ res/locales/it.ftl | 7 +++++ res/locales/lv.ftl | 7 +++++ res/locales/pt.ftl | 7 +++++ res/locales/ru.ftl | 7 +++++ res/locales/uk.ftl | 7 +++++ res/locales/zh.ftl | 7 +++++ src/widget/advanced_settings.rs | 49 +++++++++++++++++++++++++-------- 11 files changed, 108 insertions(+), 13 deletions(-) diff --git a/res/locales/de.ftl b/res/locales/de.ftl index 5c36e74..f267eb4 100644 --- a/res/locales/de.ftl +++ b/res/locales/de.ftl @@ -113,6 +113,13 @@ modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration modal-advanced-simulator-acceleration-factor = Acceleration percent +modal-advanced-simulator-airway-resistance-unit = cmH2O/L/s +modal-advanced-simulator-airway-compliance-unit = mL/cmH2O +modal-advanced-simulator-spontaneous-breath-rate-unit = cycle/min +modal-advanced-simulator-spontaneous-breath-effort-unit = cmH2O +modal-advanced-simulator-spontaneous-breath-duration-unit = ms +modal-advanced-simulator-acceleration-factor-unit = % + initializing-connecting = Inbetriebnahme... initializing-connected = Initialisierung... diff --git a/res/locales/en.ftl b/res/locales/en.ftl index 1923be5..95639dd 100644 --- a/res/locales/en.ftl +++ b/res/locales/en.ftl @@ -111,7 +111,14 @@ modal-advanced-simulator-airway-compliance = Compliance modal-advanced-simulator-spontaneous-breath-rate = Breath rate modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration -modal-advanced-simulator-acceleration-factor = Acceleration percent +modal-advanced-simulator-acceleration-factor = Acceleration + +modal-advanced-simulator-airway-resistance-unit = cmH2O/L/s +modal-advanced-simulator-airway-compliance-unit = mL/cmH2O +modal-advanced-simulator-spontaneous-breath-rate-unit = cycle/min +modal-advanced-simulator-spontaneous-breath-effort-unit = cmH2O +modal-advanced-simulator-spontaneous-breath-duration-unit = ms +modal-advanced-simulator-acceleration-factor-unit = % initializing-connecting = Starting up... diff --git a/res/locales/es.ftl b/res/locales/es.ftl index 44e78a3..7f7b665 100644 --- a/res/locales/es.ftl +++ b/res/locales/es.ftl @@ -114,6 +114,13 @@ modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration modal-advanced-simulator-acceleration-factor = Acceleration percent +modal-advanced-simulator-airway-resistance-unit = cmH2O/L/s +modal-advanced-simulator-airway-compliance-unit = mL/cmH2O +modal-advanced-simulator-spontaneous-breath-rate-unit = cycle/min +modal-advanced-simulator-spontaneous-breath-effort-unit = cmH2O +modal-advanced-simulator-spontaneous-breath-duration-unit = ms +modal-advanced-simulator-acceleration-factor-unit = % + initializing-connecting = Empezando... initializing-connected = Inicializando... diff --git a/res/locales/fr.ftl b/res/locales/fr.ftl index eac266f..83770b4 100644 --- a/res/locales/fr.ftl +++ b/res/locales/fr.ftl @@ -114,6 +114,13 @@ modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration modal-advanced-simulator-acceleration-factor = Acceleration percent +modal-advanced-simulator-airway-resistance-unit = cmH2O/L/s +modal-advanced-simulator-airway-compliance-unit = mL/cmH2O +modal-advanced-simulator-spontaneous-breath-rate-unit = cycle/min +modal-advanced-simulator-spontaneous-breath-effort-unit = cmH2O +modal-advanced-simulator-spontaneous-breath-duration-unit = ms +modal-advanced-simulator-acceleration-factor-unit = % + initializing-connecting = Démarrage en cours... initializing-connected = Préparation en cours... diff --git a/res/locales/it.ftl b/res/locales/it.ftl index 233c7d6..7aa7bc3 100644 --- a/res/locales/it.ftl +++ b/res/locales/it.ftl @@ -114,6 +114,13 @@ modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration modal-advanced-simulator-acceleration-factor = Acceleration percent +modal-advanced-simulator-airway-resistance-unit = cmH2O/L/s +modal-advanced-simulator-airway-compliance-unit = mL/cmH2O +modal-advanced-simulator-spontaneous-breath-rate-unit = cycle/min +modal-advanced-simulator-spontaneous-breath-effort-unit = cmH2O +modal-advanced-simulator-spontaneous-breath-duration-unit = ms +modal-advanced-simulator-acceleration-factor-unit = % + initializing-connecting = Cominciando... initializing-connected = Inizializzazione in corso... diff --git a/res/locales/lv.ftl b/res/locales/lv.ftl index 5bcf8a6..0f4659f 100644 --- a/res/locales/lv.ftl +++ b/res/locales/lv.ftl @@ -114,6 +114,13 @@ modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration modal-advanced-simulator-acceleration-factor = Acceleration percent +modal-advanced-simulator-airway-resistance-unit = cmH2O/L/s +modal-advanced-simulator-airway-compliance-unit = mL/cmH2O +modal-advanced-simulator-spontaneous-breath-rate-unit = cycle/min +modal-advanced-simulator-spontaneous-breath-effort-unit = cmH2O +modal-advanced-simulator-spontaneous-breath-duration-unit = ms +modal-advanced-simulator-acceleration-factor-unit = % + initializing-connecting = Notiek palaišana... initializing-connected = Notiek inicializēšana... diff --git a/res/locales/pt.ftl b/res/locales/pt.ftl index 0a5edd4..b819e26 100644 --- a/res/locales/pt.ftl +++ b/res/locales/pt.ftl @@ -113,6 +113,13 @@ modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration modal-advanced-simulator-acceleration-factor = Acceleration percent +modal-advanced-simulator-airway-resistance-unit = cmH2O/L/s +modal-advanced-simulator-airway-compliance-unit = mL/cmH2O +modal-advanced-simulator-spontaneous-breath-rate-unit = cycle/min +modal-advanced-simulator-spontaneous-breath-effort-unit = cmH2O +modal-advanced-simulator-spontaneous-breath-duration-unit = ms +modal-advanced-simulator-acceleration-factor-unit = % + initializing-connecting = Começando... initializing-connected = Inicializando... diff --git a/res/locales/ru.ftl b/res/locales/ru.ftl index dd078ba..105e726 100644 --- a/res/locales/ru.ftl +++ b/res/locales/ru.ftl @@ -113,6 +113,13 @@ modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration modal-advanced-simulator-acceleration-factor = Acceleration percent +modal-advanced-simulator-airway-resistance-unit = cmH2O/L/s +modal-advanced-simulator-airway-compliance-unit = mL/cmH2O +modal-advanced-simulator-spontaneous-breath-rate-unit = cycle/min +modal-advanced-simulator-spontaneous-breath-effort-unit = cmH2O +modal-advanced-simulator-spontaneous-breath-duration-unit = ms +modal-advanced-simulator-acceleration-factor-unit = % + initializing-connecting = Начиная... initializing-connected = Инициализация... diff --git a/res/locales/uk.ftl b/res/locales/uk.ftl index 59581bc..838ec30 100644 --- a/res/locales/uk.ftl +++ b/res/locales/uk.ftl @@ -113,6 +113,13 @@ modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration modal-advanced-simulator-acceleration-factor = Acceleration percent +modal-advanced-simulator-airway-resistance-unit = cmH2O/L/s +modal-advanced-simulator-airway-compliance-unit = mL/cmH2O +modal-advanced-simulator-spontaneous-breath-rate-unit = cycle/min +modal-advanced-simulator-spontaneous-breath-effort-unit = cmH2O +modal-advanced-simulator-spontaneous-breath-duration-unit = ms +modal-advanced-simulator-acceleration-factor-unit = % + initializing-connecting = Запуск... initializing-connected = Ініціалізація... diff --git a/res/locales/zh.ftl b/res/locales/zh.ftl index f786da1..2f70c76 100644 --- a/res/locales/zh.ftl +++ b/res/locales/zh.ftl @@ -113,6 +113,13 @@ modal-advanced-simulator-spontaneous-breath-effort = Breath effort modal-advanced-simulator-spontaneous-breath-duration = Breath duration modal-advanced-simulator-acceleration-factor = Acceleration percent +modal-advanced-simulator-airway-resistance-unit = cmH2O/L/s +modal-advanced-simulator-airway-compliance-unit = mL/cmH2O +modal-advanced-simulator-spontaneous-breath-rate-unit = cycle/min +modal-advanced-simulator-spontaneous-breath-effort-unit = cmH2O +modal-advanced-simulator-spontaneous-breath-duration-unit = ms +modal-advanced-simulator-acceleration-factor-unit = % + initializing-connecting = 启动... initializing-connected = 初始化中... diff --git a/src/widget/advanced_settings.rs b/src/widget/advanced_settings.rs index e3e5592..809e02a 100644 --- a/src/widget/advanced_settings.rs +++ b/src/widget/advanced_settings.rs @@ -410,7 +410,12 @@ fn form_simulator<'a>(master: &mut ControlWidget<'a>, config: &Config) { config, Field { label_text: APP_I18N.t("modal-advanced-simulator-airway-resistance"), - value_text: config.advanced_settings.resistance.to_string(), + value_text: format!( + "{} {}", + config.advanced_settings.resistance.to_string(), + APP_I18N.t("modal-advanced-simulator-airway-resistance-unit") + ), + ids: config.field_resistance_ids, }, ); @@ -421,7 +426,11 @@ fn form_simulator<'a>(master: &mut ControlWidget<'a>, config: &Config) { config, Field { label_text: APP_I18N.t("modal-advanced-simulator-airway-compliance"), - value_text: config.advanced_settings.compliance.to_string(), + value_text: format!( + "{} {}", + config.advanced_settings.compliance.to_string(), + APP_I18N.t("modal-advanced-simulator-airway-compliance-unit") + ), ids: config.field_compliance_ids, }, ); @@ -432,7 +441,11 @@ fn form_simulator<'a>(master: &mut ControlWidget<'a>, config: &Config) { config, Field { label_text: APP_I18N.t("modal-advanced-simulator-spontaneous-breath-rate"), - value_text: config.advanced_settings.spontaneous_breath_rate.to_string(), + value_text: format!( + "{} {}", + config.advanced_settings.spontaneous_breath_rate.to_string(), + APP_I18N.t("modal-advanced-simulator-spontaneous-breath-rate-unit") + ), ids: config.field_spontaneous_breath_rate_ids, }, ); @@ -443,10 +456,14 @@ fn form_simulator<'a>(master: &mut ControlWidget<'a>, config: &Config) { config, Field { label_text: APP_I18N.t("modal-advanced-simulator-spontaneous-breath-effort"), - value_text: config - .advanced_settings - .spontaneous_breath_effort - .to_string(), + value_text: format!( + "{} {}", + config + .advanced_settings + .spontaneous_breath_effort + .to_string(), + APP_I18N.t("modal-advanced-simulator-spontaneous-breath-effort-unit") + ), ids: config.field_spontaneous_breath_effort_ids, }, ); @@ -457,10 +474,14 @@ fn form_simulator<'a>(master: &mut ControlWidget<'a>, config: &Config) { config, Field { label_text: APP_I18N.t("modal-advanced-simulator-spontaneous-breath-duration"), - value_text: config - .advanced_settings - .spontaneous_breath_duration - .to_string(), + value_text: format!( + "{} {}", + config + .advanced_settings + .spontaneous_breath_duration + .to_string(), + APP_I18N.t("modal-advanced-simulator-spontaneous-breath-duration-unit") + ), ids: config.field_spontaneous_breath_duration_ids, }, ); @@ -471,7 +492,11 @@ fn form_simulator<'a>(master: &mut ControlWidget<'a>, config: &Config) { config, Field { label_text: APP_I18N.t("modal-advanced-simulator-acceleration-factor"), - value_text: config.advanced_settings.acceleration_percent.to_string(), + value_text: format!( + "{} {}", + config.advanced_settings.acceleration_percent.to_string(), + APP_I18N.t("modal-advanced-simulator-acceleration-factor-unit") + ), ids: config.field_acceleration_percent_ids, }, ); From 27d3e2494d7135f426294962bc8d33f7fc9f574c Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Sun, 28 Nov 2021 12:55:16 +0100 Subject: [PATCH 23/29] Remove Cargo profile settings that are defaults --- Cargo.toml | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3606c3f..f4fb7f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,18 +49,6 @@ lora = ["rn2903", "sysfs_gpio"] serial = ["makair-telemetry/serial"] simulator = ["makair-simulator"] -[profile.dev] -opt-level = 0 -debug = true -debug-assertions = true - [profile.release] -opt-level = 3 lto = true -debug = false -debug-assertions = false - -[profile.bench] -opt-level = 3 -debug = false -debug-assertions = false +codegen-units = 1 From 2962e7e7c58346c0eded093f4f90c257a6a18884 Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Sun, 28 Nov 2021 16:14:58 +0100 Subject: [PATCH 24/29] Add missing file header --- src/data/simulator.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/data/simulator.rs b/src/data/simulator.rs index 6ab6289..bea098f 100644 --- a/src/data/simulator.rs +++ b/src/data/simulator.rs @@ -1,3 +1,8 @@ +// MakAir Control UI +// +// Copyright: 2020, Makers For Life +// License: Public Domain License + use makair_simulator::MakAirSimulator; use makair_telemetry::control::ControlMessage; use makair_telemetry::TelemetryChannelType; From a193738c04fb99bf25bf18a8e85a6b24d2c6965c Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Sun, 28 Nov 2021 16:21:02 +0100 Subject: [PATCH 25/29] Add Windows icon and metadata to built executable --- Cargo.lock | 11 ++++++++++- Cargo.toml | 10 +++++++++- build.rs | 38 ++++++++++++++++++++++++++++++++++++++ res/images/app-icon.ico | Bin 0 -> 53799 bytes 4 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 build.rs create mode 100644 res/images/app-icon.ico diff --git a/Cargo.lock b/Cargo.lock index 8f1a87b..4bfcdb9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1152,7 +1152,7 @@ dependencies = [ ] [[package]] -name = "makair-control" +name = "makair-control-ui" version = "2.4.0" dependencies = [ "chrono", @@ -1179,6 +1179,7 @@ dependencies = [ "sysfs_gpio", "unic-langid", "winit", + "winres", ] [[package]] @@ -2646,6 +2647,14 @@ dependencies = [ "x11-dl", ] +[[package]] +name = "winres" +version = "0.1.11" +source = "git+https://github.com/Skirmisher/winres?rev=7333e0ff201d25eaaa70352682cd1a37614f93f4#7333e0ff201d25eaaa70352682cd1a37614f93f4" +dependencies = [ + "toml", +] + [[package]] name = "x11-clipboard" version = "0.5.3" diff --git a/Cargo.toml b/Cargo.toml index f4fb7f6..8424f30 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "makair-control" +name = "makair-control-ui" version = "2.4.0" description = "Control UI for the MakAir open source ventilator." readme = "README.md" @@ -42,6 +42,14 @@ rn2903 = { git = "https://github.com/waxzce/lora-rust-rn2903-rn2483.git", rev = makair-telemetry = { git = "https://github.com/makers-for-life/makair-telemetry", rev = "184185d4301fa7343018cd6733e1fb23e2cb032e", default-features = false } makair-simulator = { git = "https://github.com/makers-for-life/makair-simulator", rev = "6a5ea65e65f5919cade4417d1612fe2a0f4db485", optional = true } +[build-dependencies] +winres = { git = "https://github.com/Skirmisher/winres", rev = "7333e0ff201d25eaaa70352682cd1a37614f93f4" } # https://github.com/mxre/winres/pull/36 is required + +[package.metadata.winres] +ProductName = "MakAir Control UI" +CompanyName = "Makers For Life" +LegalCopyright = "Copyright © 2020, Makers For Life" + [features] default = ["serial"] fonts-cjk = [] diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..b930d1d --- /dev/null +++ b/build.rs @@ -0,0 +1,38 @@ +// MakAir Control UI +// +// Copyright: 2020, Makers For Life +// License: Public Domain License + +fn main() { + // This is only useful when compiling to a Windows target + if std::env::var("CARGO_CFG_TARGET_FAMILY").unwrap_or_else(|_| "".to_owned()) == "windows" + && std::env::var("DISABLE_WINRES").is_err() + { + const ICON_PATH: &str = "res/images/app-icon.ico"; + println!("cargo:rerun-if-changed={}", ICON_PATH); + + let features = std::env::vars_os() + .flat_map(|(k, v)| { + let var_name = k.to_string_lossy(); + match var_name.strip_prefix("CARGO_FEATURE_") { + Some(name) if v == "1" => Some(name.to_lowercase()), + _ => None, + } + }) + .collect::>() + .join(", "); + + let mut res = winres::WindowsResource::new(); + res.set_icon(ICON_PATH); + res.set( + "FileDescription", + &format!( + "{} Compiled with features: {}.", + env!("CARGO_PKG_DESCRIPTION"), + &features + ), + ); + res.compile() + .expect("could not compile with Windows icon and metadata"); + } +} diff --git a/res/images/app-icon.ico b/res/images/app-icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..7f4f4fbb9894a5f1e7be5673b6c0f903b4e8d3ae GIT binary patch literal 53799 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 Hu0mjfhm?N2 literal 0 HcmV?d00001 From 1af3d5e5d75dd68079569f2e1c7fb8e2fb374c36 Mon Sep 17 00:00:00 2001 From: Gabriel Moneyron Date: Sun, 28 Nov 2021 17:14:26 +0100 Subject: [PATCH 26/29] revert init/run separation and update french locale --- Cargo.toml | 2 +- res/locales/fr.ftl | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8424f30..e510424 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,7 @@ conrod_core = { git = "https://github.com/dsferruzza/conrod", branch = "update-g sysfs_gpio = { version = "0.6", optional = true } rn2903 = { git = "https://github.com/waxzce/lora-rust-rn2903-rn2483.git", rev = "b086057ba096920abef3870ad0cefa2c80a343e2", optional = true } makair-telemetry = { git = "https://github.com/makers-for-life/makair-telemetry", rev = "184185d4301fa7343018cd6733e1fb23e2cb032e", default-features = false } -makair-simulator = { git = "https://github.com/makers-for-life/makair-simulator", rev = "6a5ea65e65f5919cade4417d1612fe2a0f4db485", optional = true } +makair-simulator = { git = "https://github.com/makers-for-life/makair-simulator", rev = "c2c7e77c23c2025e552334ab1f69f91eeb51470f", optional = true } [build-dependencies] winres = { git = "https://github.com/Skirmisher/winres", rev = "7333e0ff201d25eaaa70352682cd1a37614f93f4" } # https://github.com/mxre/winres/pull/36 is required diff --git a/res/locales/fr.ftl b/res/locales/fr.ftl index 83770b4..78e0577 100644 --- a/res/locales/fr.ftl +++ b/res/locales/fr.ftl @@ -54,7 +54,7 @@ mode-group-alarms = Alarmes advanced-group-statistics = Statistiques advanced-group-settings = Paramètres -advanced-group-simulator = Simulator +advanced-group-simulator = Simulateur modal-close = Fermer @@ -107,16 +107,16 @@ modal-advanced-date = Date modal-advanced-time = Heure modal-advanced-timezone = Fuseau horaire -modal-advanced-simulator-airway-resistance = Resistance +modal-advanced-simulator-airway-resistance = Résistance modal-advanced-simulator-airway-compliance = Compliance -modal-advanced-simulator-spontaneous-breath-rate = Breath rate -modal-advanced-simulator-spontaneous-breath-effort = Breath effort -modal-advanced-simulator-spontaneous-breath-duration = Breath duration -modal-advanced-simulator-acceleration-factor = Acceleration percent +modal-advanced-simulator-spontaneous-breath-rate = Fréquence respiratoire +modal-advanced-simulator-spontaneous-breath-effort = Effort spontané +modal-advanced-simulator-spontaneous-breath-duration = Durée d'effort +modal-advanced-simulator-acceleration-factor = Accélération du temps modal-advanced-simulator-airway-resistance-unit = cmH2O/L/s modal-advanced-simulator-airway-compliance-unit = mL/cmH2O -modal-advanced-simulator-spontaneous-breath-rate-unit = cycle/min +modal-advanced-simulator-spontaneous-breath-rate-unit = /min modal-advanced-simulator-spontaneous-breath-effort-unit = cmH2O modal-advanced-simulator-spontaneous-breath-duration-unit = ms modal-advanced-simulator-acceleration-factor-unit = % From 943703e0d513b89411e06ddb366da61ec616749a Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Sun, 28 Nov 2021 17:39:35 +0100 Subject: [PATCH 27/29] Allow to run from Windows Explorer --- src/config/arguments.rs | 5 +++++ src/main.rs | 3 +++ 2 files changed, 8 insertions(+) diff --git a/src/config/arguments.rs b/src/config/arguments.rs index 6ead1a2..da3fdfc 100644 --- a/src/config/arguments.rs +++ b/src/config/arguments.rs @@ -132,6 +132,11 @@ impl ConfigArguments { std::process::exit(1); } + // If the simulator feature is enabled, we use the simulator as the default mode + #[cfg(feature = "simulator")] + (None, None, false) => RunMode::Simulator, + + #[cfg(not(feature = "simulator"))] (None, None, false) => { eprintln!("You should provide either a serial port (-p), an input file (-i) or enable MakAir Simulator (-s)"); std::process::exit(1); diff --git a/src/main.rs b/src/main.rs index 75cb5d3..3840f04 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,9 @@ #![recursion_limit = "512"] // Some Clippy rules should be ignored, as they go against code design choices that were made #![cfg_attr(feature = "cargo-clippy", allow(clippy::field_reassign_with_default))] +// If compiling for Windows in release mode, do not open a console window when launching the app in graphical mode (i.e. not from a terminal) +// This also has the effect to disable stdout and stderr when lauching from a terminal, which is why we do not enable this in debug mode +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] #[macro_use] extern crate log; From 52bb30373052efd7f058c905298981fd153cc901 Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Sun, 28 Nov 2021 17:41:38 +0100 Subject: [PATCH 28/29] Update simulator lib in Cargo.lock --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 4bfcdb9..eab86a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1185,7 +1185,7 @@ dependencies = [ [[package]] name = "makair-simulator" version = "0.1.0" -source = "git+https://github.com/makers-for-life/makair-simulator?rev=6a5ea65e65f5919cade4417d1612fe2a0f4db485#6a5ea65e65f5919cade4417d1612fe2a0f4db485" +source = "git+https://github.com/makers-for-life/makair-simulator?rev=c2c7e77c23c2025e552334ab1f69f91eeb51470f#c2c7e77c23c2025e552334ab1f69f91eeb51470f" dependencies = [ "cc", "log", From 45abc88eda629e56726a4088936c4e067c16f4a9 Mon Sep 17 00:00:00 2001 From: David Sferruzza Date: Sun, 28 Nov 2021 20:42:09 +0100 Subject: [PATCH 29/29] Update dependencies --- Cargo.lock | 4 ++-- Cargo.toml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eab86a9..2b20e3b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1185,7 +1185,7 @@ dependencies = [ [[package]] name = "makair-simulator" version = "0.1.0" -source = "git+https://github.com/makers-for-life/makair-simulator?rev=c2c7e77c23c2025e552334ab1f69f91eeb51470f#c2c7e77c23c2025e552334ab1f69f91eeb51470f" +source = "git+https://github.com/makers-for-life/makair-simulator?rev=0b91e1b6fd5740ea3cb379cc16f71d701ce66166#0b91e1b6fd5740ea3cb379cc16f71d701ce66166" dependencies = [ "cc", "log", @@ -1196,7 +1196,7 @@ dependencies = [ [[package]] name = "makair-telemetry" version = "2.2.0" -source = "git+https://github.com/makers-for-life/makair-telemetry?rev=184185d4301fa7343018cd6733e1fb23e2cb032e#184185d4301fa7343018cd6733e1fb23e2cb032e" +source = "git+https://github.com/makers-for-life/makair-telemetry?rev=72e9bf31a9baa5f2ef143bdc313bf5124a5223e2#72e9bf31a9baa5f2ef143bdc313bf5124a5223e2" dependencies = [ "base64", "crc32fast", diff --git a/Cargo.toml b/Cargo.toml index e510424..9b8041a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,8 +39,8 @@ conrod_winit = { git = "https://github.com/dsferruzza/conrod", branch = "update- conrod_core = { git = "https://github.com/dsferruzza/conrod", branch = "update-glium-winit" } sysfs_gpio = { version = "0.6", optional = true } rn2903 = { git = "https://github.com/waxzce/lora-rust-rn2903-rn2483.git", rev = "b086057ba096920abef3870ad0cefa2c80a343e2", optional = true } -makair-telemetry = { git = "https://github.com/makers-for-life/makair-telemetry", rev = "184185d4301fa7343018cd6733e1fb23e2cb032e", default-features = false } -makair-simulator = { git = "https://github.com/makers-for-life/makair-simulator", rev = "c2c7e77c23c2025e552334ab1f69f91eeb51470f", optional = true } +makair-telemetry = { git = "https://github.com/makers-for-life/makair-telemetry", rev = "72e9bf31a9baa5f2ef143bdc313bf5124a5223e2", default-features = false } +makair-simulator = { git = "https://github.com/makers-for-life/makair-simulator", rev = "0b91e1b6fd5740ea3cb379cc16f71d701ce66166", optional = true } [build-dependencies] winres = { git = "https://github.com/Skirmisher/winres", rev = "7333e0ff201d25eaaa70352682cd1a37614f93f4" } # https://github.com/mxre/winres/pull/36 is required