First commit
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,7 +3,7 @@
|
|||||||
# will have compiled files and executables
|
# will have compiled files and executables
|
||||||
debug/
|
debug/
|
||||||
target/
|
target/
|
||||||
|
traffic.db
|
||||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
|
|||||||
13
Cargo.toml
Normal file
13
Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "traffic-monitor"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
eframe = "0.32.0"
|
||||||
|
egui = "0.32.0"
|
||||||
|
egui_extras = "0.32.0"
|
||||||
|
egui_plot = "0.33.0"
|
||||||
|
env_logger = "0.11.8"
|
||||||
|
rusqlite = "0.37.0"
|
||||||
|
winit = "0.30.12"
|
||||||
74
src/database.rs
Normal file
74
src/database.rs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
use egui::emath::Numeric;
|
||||||
|
use rusqlite::{Connection, Result};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct TrafficDay {
|
||||||
|
id: i32,
|
||||||
|
date: String,
|
||||||
|
rx: String,
|
||||||
|
rp: String,
|
||||||
|
tx: String,
|
||||||
|
rt: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_db() -> Result<Vec<TrafficDay>> {
|
||||||
|
let db_path: &str = "/home/xuser/Downloads/rust/traffic-monitor/traffic.db";
|
||||||
|
let router = Connection::open(db_path)?;
|
||||||
|
let mut data = router.prepare("SELECT * FROM traffic")?;
|
||||||
|
let traffic_map = data.query_map([], |row| {
|
||||||
|
Ok(TrafficDay {
|
||||||
|
id: row.get(0)?,
|
||||||
|
date: row.get(1)?,
|
||||||
|
rx: row.get(2)?,
|
||||||
|
rp: row.get(3)?,
|
||||||
|
tx: row.get(4)?,
|
||||||
|
rt: row.get(5)?
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let mut data: Vec<TrafficDay> = Vec::new();
|
||||||
|
|
||||||
|
for line in traffic_map {
|
||||||
|
let traffic_option = line.ok(); // Преобразует `Ok` в `Some` и `Err` в `None`.
|
||||||
|
if let Some(trafficday) = traffic_option {
|
||||||
|
// Здесь `trafficday` имеет тип `TrafficDay`.
|
||||||
|
data.push(trafficday);
|
||||||
|
} else {
|
||||||
|
println!("Ошибка при обработке строки, пропущено.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_list() -> Vec<[f64;2]> {
|
||||||
|
let data = read_db();
|
||||||
|
let mut lines: Vec<[f64;2]> = Vec::new();
|
||||||
|
|
||||||
|
let mut n: usize = 0;
|
||||||
|
let mut stop: i8 = 0;
|
||||||
|
|
||||||
|
match data {
|
||||||
|
Ok(list) => {
|
||||||
|
while stop != -1 {
|
||||||
|
if let Some(entry) = list.get(n) {
|
||||||
|
n += 1;
|
||||||
|
// let line: [String; 5] = [
|
||||||
|
// entry.date.clone(),
|
||||||
|
// entry.rp.clone(),
|
||||||
|
// entry.rx.clone(),
|
||||||
|
// entry.rt.clone(),
|
||||||
|
// entry.tx.clone()];
|
||||||
|
let rp: String = entry.rp.clone();
|
||||||
|
let line: [f64; 2] = [entry.id.to_f64(),rp.parse().unwrap()];
|
||||||
|
lines.push(line);
|
||||||
|
} else {
|
||||||
|
stop = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Ошибка при получении данных: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
37
src/main.rs
Normal file
37
src/main.rs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||||
|
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||||
|
|
||||||
|
use eframe::egui;
|
||||||
|
use egui_plot::{Plot, PlotPoints, Line};
|
||||||
|
mod database;
|
||||||
|
|
||||||
|
fn main() -> eframe::Result {
|
||||||
|
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
||||||
|
|
||||||
|
let options = eframe::NativeOptions {
|
||||||
|
viewport: egui::ViewportBuilder::default().with_inner_size([320.0, 240.0]),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
eframe::run_simple_native("Traffic Monitor", options, move |ctx, _frame| {
|
||||||
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
// ui.horizontal(|ui| {
|
||||||
|
// let name_label = ui.label("Your name: ");
|
||||||
|
// ui.text_edit_singleline(&mut name)
|
||||||
|
// .labelled_by(name_label.id);
|
||||||
|
// });
|
||||||
|
// ui.add(egui::Slider::new(&mut age, 0..=120).text("age"));
|
||||||
|
// if ui.button("Increment").clicked() {
|
||||||
|
// age += 1;
|
||||||
|
// }
|
||||||
|
ui.label(format!("Hello"));
|
||||||
|
egui_plot::Plot::new(1).show(ui, |plot_ui| {
|
||||||
|
let points: Vec<[f64; 2]> = database::generate_list();
|
||||||
|
// println!("{:?}", points);
|
||||||
|
let pp = Line::new("low",points);
|
||||||
|
plot_ui.line(pp);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
65
src/main.rs.bak
Normal file
65
src/main.rs.bak
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
use rusqlite::{Connection, Result};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct TrafficDay {
|
||||||
|
id: i32,
|
||||||
|
date: String,
|
||||||
|
rx: String,
|
||||||
|
rp: String,
|
||||||
|
tx: String,
|
||||||
|
rt: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_db() -> Result<Vec<TrafficDay>> {
|
||||||
|
let db_path: &str = "/home/xuser/Downloads/rust/traffic-monitor/traffic.db";
|
||||||
|
let router = Connection::open(db_path)?;
|
||||||
|
let mut data = router.prepare("SELECT * FROM traffic")?;
|
||||||
|
let traffic_map = data.query_map([], |row| {
|
||||||
|
Ok(TrafficDay {
|
||||||
|
id: row.get(0)?,
|
||||||
|
date: row.get(1)?,
|
||||||
|
rx: row.get(2)?,
|
||||||
|
rp: row.get(3)?,
|
||||||
|
tx: row.get(4)?,
|
||||||
|
rt: row.get(5)?
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let mut data: Vec<TrafficDay> = Vec::new();
|
||||||
|
|
||||||
|
for line in traffic_map {
|
||||||
|
let traffic_option = line.ok(); // Преобразует `Ok` в `Some` и `Err` в `None`.
|
||||||
|
if let Some(trafficday) = traffic_option {
|
||||||
|
// Здесь `trafficday` имеет тип `TrafficDay`.
|
||||||
|
data.push(trafficday);
|
||||||
|
} else {
|
||||||
|
println!("Ошибка при обработке строки, пропущено.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let data = read_db();
|
||||||
|
// println!("{:?}", data);
|
||||||
|
|
||||||
|
let mut n: usize = 0;
|
||||||
|
let mut stop: i8 = 0;
|
||||||
|
|
||||||
|
match data {
|
||||||
|
Ok(list) => {
|
||||||
|
while stop != -1 {
|
||||||
|
if let Some(entry) = list.get(n) {
|
||||||
|
n += 1;
|
||||||
|
let temp: f32 = entry.rx.parse().unwrap();
|
||||||
|
println!("date: {:?}", temp);
|
||||||
|
} else {
|
||||||
|
stop = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Ошибка при получении данных: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
132
src/main_example.rs
Normal file
132
src/main_example.rs
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
//! This example shows how to implement custom gestures to pan and zoom in the plot
|
||||||
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||||
|
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||||
|
|
||||||
|
use eframe::egui::{self, DragValue, Event, Vec2};
|
||||||
|
use egui_plot::{Legend, Line, PlotPoints};
|
||||||
|
|
||||||
|
fn main() -> eframe::Result {
|
||||||
|
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
||||||
|
let options = eframe::NativeOptions::default();
|
||||||
|
eframe::run_native(
|
||||||
|
"Plot",
|
||||||
|
options,
|
||||||
|
Box::new(|_cc| Ok(Box::<PlotExample>::default())),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PlotExample {
|
||||||
|
lock_x: bool,
|
||||||
|
lock_y: bool,
|
||||||
|
ctrl_to_zoom: bool,
|
||||||
|
shift_to_horizontal: bool,
|
||||||
|
zoom_speed: f32,
|
||||||
|
scroll_speed: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for PlotExample {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
lock_x: false,
|
||||||
|
lock_y: false,
|
||||||
|
ctrl_to_zoom: false,
|
||||||
|
shift_to_horizontal: false,
|
||||||
|
zoom_speed: 1.0,
|
||||||
|
scroll_speed: 1.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl eframe::App for PlotExample {
|
||||||
|
fn update(&mut self, ctx: &egui::Context, _: &mut eframe::Frame) {
|
||||||
|
egui::SidePanel::left("options").show(ctx, |ui| {
|
||||||
|
ui.checkbox(&mut self.lock_x, "Lock x axis").on_hover_text("Check to keep the X axis fixed, i.e., pan and zoom will only affect the Y axis");
|
||||||
|
ui.checkbox(&mut self.lock_y, "Lock y axis").on_hover_text("Check to keep the Y axis fixed, i.e., pan and zoom will only affect the X axis");
|
||||||
|
ui.checkbox(&mut self.ctrl_to_zoom, "Ctrl to zoom").on_hover_text("If unchecked, the behavior of the Ctrl key is inverted compared to the default controls\ni.e., scrolling the mouse without pressing any keys zooms the plot");
|
||||||
|
ui.checkbox(&mut self.shift_to_horizontal, "Shift for horizontal scroll").on_hover_text("If unchecked, the behavior of the shift key is inverted compared to the default controls\ni.e., hold to scroll vertically, release to scroll horizontally");
|
||||||
|
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.add(
|
||||||
|
DragValue::new(&mut self.zoom_speed)
|
||||||
|
.range(0.1..=2.0)
|
||||||
|
.speed(0.1),
|
||||||
|
);
|
||||||
|
ui.label("Zoom speed").on_hover_text("How fast to zoom in and out with the mouse wheel");
|
||||||
|
});
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.add(
|
||||||
|
DragValue::new(&mut self.scroll_speed)
|
||||||
|
.range(0.1..=100.0)
|
||||||
|
.speed(0.1),
|
||||||
|
);
|
||||||
|
ui.label("Scroll speed").on_hover_text("How fast to pan with the mouse wheel");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
let (scroll, pointer_down, modifiers) = ui.input(|i| {
|
||||||
|
let scroll = i.events.iter().find_map(|e| match e {
|
||||||
|
Event::MouseWheel {
|
||||||
|
unit: _,
|
||||||
|
delta,
|
||||||
|
modifiers: _,
|
||||||
|
} => Some(*delta),
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
(scroll, i.pointer.primary_down(), i.modifiers)
|
||||||
|
});
|
||||||
|
|
||||||
|
ui.label("This example shows how to use raw input events to implement different plot controls than the ones egui provides by default, e.g., default to zooming instead of panning when the Ctrl key is not pressed, or controlling much it zooms with each mouse wheel step.");
|
||||||
|
|
||||||
|
egui_plot::Plot::new("plot")
|
||||||
|
.allow_zoom(false)
|
||||||
|
.allow_drag(false)
|
||||||
|
.allow_scroll(false)
|
||||||
|
.legend(Legend::default())
|
||||||
|
.show(ui, |plot_ui| {
|
||||||
|
if let Some(mut scroll) = scroll {
|
||||||
|
if modifiers.ctrl == self.ctrl_to_zoom {
|
||||||
|
scroll = Vec2::splat(scroll.x + scroll.y);
|
||||||
|
let mut zoom_factor = Vec2::from([
|
||||||
|
(scroll.x * self.zoom_speed / 10.0).exp(),
|
||||||
|
(scroll.y * self.zoom_speed / 10.0).exp(),
|
||||||
|
]);
|
||||||
|
if self.lock_x {
|
||||||
|
zoom_factor.x = 1.0;
|
||||||
|
}
|
||||||
|
if self.lock_y {
|
||||||
|
zoom_factor.y = 1.0;
|
||||||
|
}
|
||||||
|
plot_ui.zoom_bounds_around_hovered(zoom_factor);
|
||||||
|
} else {
|
||||||
|
if modifiers.shift == self.shift_to_horizontal {
|
||||||
|
scroll = Vec2::new(scroll.y, scroll.x);
|
||||||
|
}
|
||||||
|
if self.lock_x {
|
||||||
|
scroll.x = 0.0;
|
||||||
|
}
|
||||||
|
if self.lock_y {
|
||||||
|
scroll.y = 0.0;
|
||||||
|
}
|
||||||
|
let delta_pos = self.scroll_speed * scroll;
|
||||||
|
plot_ui.translate_bounds(delta_pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if plot_ui.response().hovered() && pointer_down {
|
||||||
|
let mut pointer_translate = -plot_ui.pointer_coordinate_drag_delta();
|
||||||
|
if self.lock_x {
|
||||||
|
pointer_translate.x = 0.0;
|
||||||
|
}
|
||||||
|
if self.lock_y {
|
||||||
|
pointer_translate.y = 0.0;
|
||||||
|
}
|
||||||
|
plot_ui.translate_bounds(pointer_translate);
|
||||||
|
}
|
||||||
|
|
||||||
|
let sine_points = PlotPoints::from_explicit_callback(|x| x.sin(), .., 5000);
|
||||||
|
let sine_line = Line::new("Sine", sine_points).name("Sine");
|
||||||
|
|
||||||
|
plot_ui.line(sine_line);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user