Skip to content

Commit

Permalink
Smooth the Diagnostics page to avoid stuttering
Browse files Browse the repository at this point in the history
  • Loading branch information
rnd-ash committed Apr 20, 2023
1 parent ad15ff0 commit f99755a
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 50 deletions.
118 changes: 68 additions & 50 deletions config_app/src/ui/diagnostics/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
use crate::ui::status_bar::MainStatusBar;
use crate::window::{PageAction, StatusBar};
use backend::diag::Nag52Diag;
use backend::ecu_diagnostics::kwp2000::{KwpSessionTypeByte, KwpSessionType};
use eframe::egui::plot::{Legend, Line, Plot};
use eframe::egui::{Color32, RichText, Ui};
use std::borrow::Borrow;
use std::collections::hash_map::DefaultHasher;
use std::collections::VecDeque;
use std::hash::{Hash, Hasher};
use std::time::Instant;
use std::sync::{Arc, RwLock};
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::thread;
use std::time::{Instant, Duration};

pub mod data;
pub mod rli;
Expand All @@ -22,104 +27,118 @@ pub enum CommandStatus {

pub struct DiagnosticsPage {
bar: MainStatusBar,
nag: Nag52Diag,
text: CommandStatus,
record_data: Option<LocalRecordData>,
record_to_query: Option<RecordIdents>,
last_query_time: Instant,
query_ecu: Arc<AtomicBool>,
last_update_time: Arc<AtomicU64>,
curr_values: Arc<RwLock<Option<LocalRecordData>>>,
time_since_launch: Instant,
record_to_query: Arc<RwLock<Option<RecordIdents>>>,
charting_data: VecDeque<(u128, ChartData)>,
chart_idx: u128,
}

impl DiagnosticsPage {
pub fn new(nag: Nag52Diag, bar: MainStatusBar) -> Self {

let run = Arc::new(AtomicBool::new(true));
let run_t = run.clone();

let store = Arc::new(RwLock::new(None));
let store_t = store.clone();

let to_query: Arc<RwLock<Option<RecordIdents>>> = Arc::new(RwLock::new(None));
let to_query_t = to_query.clone();

let launch_time = Instant::now();
let launch_time_t = launch_time.clone();

let last_update = Arc::new(AtomicU64::new(0));
let last_update_t = last_update.clone();
let _ = thread::spawn(move || {
nag.with_kwp(|server| {
server.kwp_set_session(KwpSessionTypeByte::Standard(KwpSessionType::Normal))
});
while run_t.load(Ordering::Relaxed) {
let start = Instant::now();
if let Some(to_query) = *to_query_t.read().unwrap() {
match nag.with_kwp(|server| to_query.query_ecu(server)) {
Ok(r) => *store_t.write().unwrap() = Some(r),
Err(e) => {
eprintln!("Could not query {}", e);
}
}
}
let taken = start.elapsed().as_millis() as u64;
if taken < rli::RLI_QUERY_INTERVAL {
std::thread::sleep(Duration::from_millis(rli::RLI_QUERY_INTERVAL - taken));
}
}
});

Self {
nag,
query_ecu: run,
bar,
text: CommandStatus::Ok("".into()),
record_data: None,
record_to_query: None,
last_query_time: Instant::now(),
last_update_time: last_update,
curr_values: store,
record_to_query: to_query,
charting_data: VecDeque::new(),
chart_idx: 0,
time_since_launch: Instant::now()
}
}
}

impl crate::window::InterfacePage for DiagnosticsPage {
fn make_ui(&mut self, ui: &mut Ui, _frame: &eframe::Frame) -> PageAction {
let mut pending = false;
ui.heading("This is experimental, use with MOST up-to-date firmware");

if ui.button("Query gearbox sensor").clicked() {
self.record_to_query = Some(RecordIdents::GearboxSensors);
*self.record_to_query.write().unwrap() = Some(RecordIdents::GearboxSensors);
self.chart_idx = 0;
self.charting_data.clear();
self.record_data = None;
*self.curr_values.write().unwrap() = None;
}
if ui.button("Query gearbox solenoids").clicked() {
self.record_to_query = Some(RecordIdents::SolenoidStatus);
*self.record_to_query.write().unwrap() = Some(RecordIdents::SolenoidStatus);
self.chart_idx = 0;
self.charting_data.clear();
self.record_data = None;
*self.curr_values.write().unwrap() = None;
}
if ui.button("Query solenoid pressures").clicked() {
self.record_to_query = Some(RecordIdents::PressureStatus);
*self.record_to_query.write().unwrap() = Some(RecordIdents::PressureStatus);
self.chart_idx = 0;
self.charting_data.clear();
self.record_data = None;
*self.curr_values.write().unwrap() = None;
}
if ui.button("Query can Rx data").clicked() {
self.record_to_query = Some(RecordIdents::CanDataDump);
*self.record_to_query.write().unwrap() = Some(RecordIdents::CanDataDump);
self.chart_idx = 0;
self.charting_data.clear();
self.record_data = None;
*self.curr_values.write().unwrap() = None;
}
if ui.button("Query Shift data").clicked() {
self.record_to_query = Some(RecordIdents::SSData);
*self.record_to_query.write().unwrap() = Some(RecordIdents::SSData);
self.chart_idx = 0;
self.charting_data.clear();
self.record_data = None;
*self.curr_values.write().unwrap() = None;
}

if ui.button("Query Performance metrics").clicked() {
self.record_to_query = Some(RecordIdents::SysUsage);
*self.record_to_query.write().unwrap() = Some(RecordIdents::SysUsage);
self.chart_idx = 0;
self.charting_data.clear();
self.record_data = None;
}

match &self.text {
CommandStatus::Ok(res) => {
ui.label(RichText::new(res).color(Color32::from_rgb(0, 255, 0)));
}
CommandStatus::Err(res) => {
ui.label(RichText::new(res).color(Color32::from_rgb(255, 0, 0)));
}
*self.curr_values.write().unwrap() = None;
}

if pending || (self.last_query_time.elapsed().as_millis() > 100) {
self.last_query_time = Instant::now();
self.chart_idx += 100;
if let Some(rid) = self.record_to_query {
match self.nag.with_kwp(|server| rid.query_ecu(server)) {
Ok(r) => self.record_data = Some(r),
Err(e) => {
eprintln!("Could not query {}", e);
}
}
}
}

if let Some(data) = &self.record_data {
let current_val = self.curr_values.read().unwrap().clone();
if let Some(data) = current_val {
data.to_table(ui);

let c = data.get_chart_data();

if !c.is_empty() {
let d = &c[0];
self.charting_data.push_back((self.chart_idx, d.clone()));

self.chart_idx+=1;
if self.charting_data.len() > (20000 / 100) {
// 20 seconds
let _ = self.charting_data.pop_front();
Expand All @@ -129,7 +148,6 @@ impl crate::window::InterfacePage for DiagnosticsPage {
// as `d`
let mut lines = Vec::new();
let legend = Legend::default();

for (idx, (key, _, _)) in d.data.iter().enumerate() {
let mut points: Vec<[f64; 2]> = Vec::new();
for (timestamp, point) in &self.charting_data {
Expand All @@ -155,14 +173,14 @@ impl crate::window::InterfacePage for DiagnosticsPage {
plot = plot.include_y(*max);
}
}
plot = plot.include_x(200);

plot.show(ui, |plot_ui| {
for x in lines {
plot_ui.line(x)
}
});
}
ui.ctx().request_repaint();
}

PageAction::None
Expand Down
2 changes: 2 additions & 0 deletions config_app/src/ui/diagnostics/rli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use packed_struct::prelude::{PackedStruct, PrimitiveEnum_u8};
use std::borrow::Borrow;
use std::i16::MAX;

pub const RLI_QUERY_INTERVAL: u64 = 100;

#[repr(u8)]
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
pub enum RecordIdents {
Expand Down

0 comments on commit f99755a

Please sign in to comment.