Skip to content

Commit 316902a

Browse files
committed
support send CAN packet from user inputs
1 parent 8e2779a commit 316902a

File tree

4 files changed

+95
-19
lines changed

4 files changed

+95
-19
lines changed

src/event_handler/can_handler.rs

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ impl<'a> CanHandler<'a> {
3838
let _ = can_if.bring_down();
3939
let _ = can_if.set_bitrate(self.bitrate().unwrap(), None);
4040
let _ = can_if.bring_up();
41-
let can_socket = self.open_can_socket();
42-
self.process_ui_events(can_socket, can_if);
41+
let tx_can_socket = self.open_can_socket();
42+
let rx_can_socket = self.open_can_socket();
43+
self.process_ui_events(tx_can_socket, rx_can_socket, can_if);
4344
}
4445
#[cfg(target_os = "windows")]
4546
self.process_ui_events(dbc);
@@ -63,9 +64,54 @@ impl<'a> CanHandler<'a> {
6364
}
6465
}
6566
#[cfg(target_os = "linux")]
66-
fn process_ui_events(&mut self, can_socket: CanSocket, can_if: CanInterface) {
67+
fn process_ui_events(
68+
&mut self,
69+
tx_can_socket: CanSocket,
70+
rx_can_socket: CanSocket,
71+
can_if: CanInterface,
72+
) {
73+
use socketcan::{ExtendedId, StandardId};
74+
6775
let mut start_bus_load = Instant::now();
6876
let mut total_bits = 0;
77+
let _ = self.ui_handle.upgrade_in_event_loop(move |ui| {
78+
ui.on_can_transmit(move |is_extended, can_id, can_data| {
79+
match Self::convert_hex_string_u32(&can_id) {
80+
Ok(id) => match Self::convert_hex_string_arr(&can_data) {
81+
Ok(data) => {
82+
if is_extended {
83+
match ExtendedId::new(id) {
84+
Some(id) => {
85+
let can_frame = CanFrame::new(id, &data).unwrap();
86+
let _ = tx_can_socket.write_frame(&can_frame);
87+
}
88+
None => {
89+
println!("Invalid CAN extended ID {}", id)
90+
}
91+
}
92+
} else {
93+
match StandardId::new(id as u16) {
94+
Some(id) => {
95+
let can_frame = CanFrame::new(id, &data).unwrap();
96+
let _ = tx_can_socket.write_frame(&can_frame);
97+
}
98+
None => {
99+
println!("Invalid CAN standard ID {}", id)
100+
}
101+
}
102+
};
103+
}
104+
Err(e) => {
105+
println!("Failed to parse can data {}, error {}", can_data, e);
106+
}
107+
},
108+
Err(e) => {
109+
println!("Failed to parse can id {}, error: {}", can_id, e);
110+
}
111+
}
112+
});
113+
});
114+
69115
loop {
70116
let bus_state = match can_if.state().unwrap().unwrap() {
71117
socketcan::nl::CanState::ErrorActive => "ERR_ACTIVE",
@@ -103,7 +149,7 @@ impl<'a> CanHandler<'a> {
103149
}
104150
}
105151
}
106-
if let Ok(frame) = can_socket.read_frame() {
152+
if let Ok(frame) = rx_can_socket.read_frame() {
107153
let _ = self.can_tx.send(frame);
108154
total_bits += (frame.len() + 6) * 8; // Data length + overhead (approximation)
109155
let frame_id = frame.raw_id() & !0x80000000;
@@ -293,6 +339,30 @@ impl<'a> CanHandler<'a> {
293339
padded_data
294340
}
295341

342+
fn convert_hex_string_u32(hex_str: &str) -> Result<u32, String> {
343+
// Attempt to parse the hex string as a u32
344+
u32::from_str_radix(hex_str, 16).map_err(|e| format!("Failed to convert to u32: {}", e))
345+
}
346+
347+
fn convert_hex_string_arr(hex_str: &str) -> Result<Vec<u8>, String> {
348+
// Remove any whitespace from the input string
349+
let hex_str = hex_str.trim();
350+
351+
// Ensure the string has an even length
352+
if hex_str.len() % 2 != 0 {
353+
return Err("Hex string must have an even number of characters".to_string());
354+
}
355+
356+
// Convert the string into a vector of u8 bytes
357+
(0..hex_str.len())
358+
.step_by(2)
359+
.map(|i| {
360+
u8::from_str_radix(&hex_str[i..i + 2], 16)
361+
.map_err(|e| format!("Failed to convert to u8: {}", e))
362+
})
363+
.collect()
364+
}
365+
296366
fn array_to_hex_string(data: &[u8]) -> String {
297367
// Preallocate space for efficiency
298368
let mut hex_string = String::with_capacity(data.len() * 3);

src/main.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ async fn main() -> io::Result<()> {
4949
// Handle start event
5050
let ui_handle = ui.as_weak();
5151
ui.on_start(move |_name, _index, bitrate| {
52-
// start_tx.send((_name, _index));
5352
#[cfg(target_os = "linux")]
5453
{
5554
let ui = ui_handle.unwrap();

ui/app.slint

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export component AppWindow inherits Window {
2828
callback open_dbc_file();
2929
callback filter_id(CanData, bool);
3030
callback start(string, int, string);
31+
callback can_transmit(bool, string, string);
3132
title: @tr("CAN VIEWER (version 0.2.2)");
3233
icon: @image-url("images/can_viewer_128px.png");
3334
background: #1a1f2b;
@@ -122,6 +123,9 @@ export component AppWindow inherits Window {
122123
change_state(en) => {
123124
is_debug_en = en;
124125
}
126+
can_transmit(is_extended, can_id, can_data) => {
127+
can_transmit(is_extended, can_id, can_data)
128+
}
125129
}
126130
}
127131
}

ui/debug_page.slint

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,27 +39,21 @@ export component StartPauseButton inherits Rectangle {
3939
}
4040

4141
export component CanTransmitData inherits Rectangle {
42-
callback send(bool, string, string, string);
42+
callback send(bool, string, string);
4343
HorizontalLayout {
4444
is_extended := MyCheckBox {
4545
text: "Extended Frame";
4646
}
4747
can_id := LineEdit {
48-
placeholder-text: "ID (hex)";
49-
input-type: decimal;
50-
}
51-
can_len := LineEdit {
52-
placeholder-text: "length";
53-
input-type: number;
48+
placeholder-text: "ID (hex) - eg: 1814FF12";
5449
}
5550
can_data := LineEdit {
56-
placeholder-text: "data (hex)";
57-
input-type: decimal;
51+
placeholder-text: "data (hex) - eg: 1A2B3C4D";
5852
}
5953
Button {
6054
text: "send";
6155
clicked => {
62-
send(is_extended.checked, can_id.text, can_len.text, can_data.text)
56+
send(is_extended.checked, can_id.text, can_data.text)
6357
}
6458
}
6559
}
@@ -76,6 +70,7 @@ export component debugPage inherits Rectangle {
7670
{id: "181FF1FA", len: 4, data: "00 01 02 03 04 05 06 07"},
7771
{id: "181FF1FA", len: 4, data: "00 01 02 03 04 05 06 07"}];
7872
callback change_state(bool);
73+
callback can_transmit(bool, string, string);
7974

8075
VerticalLayout {
8176
HorizontalLayout {
@@ -182,16 +177,24 @@ export component debugPage inherits Rectangle {
182177
}
183178
VerticalLayout {
184179
CanTransmitData {
185-
180+
send(is_extended, can_id, can_data) => {
181+
can_transmit(is_extended, can_id, can_data);
182+
}
186183
}
187184
CanTransmitData {
188-
185+
send(is_extended, can_id, can_data) => {
186+
can_transmit(is_extended, can_id, can_data);
187+
}
189188
}
190189
CanTransmitData {
191-
190+
send(is_extended, can_id, can_data) => {
191+
can_transmit(is_extended, can_id, can_data);
192+
}
192193
}
193194
CanTransmitData {
194-
195+
send(is_extended, can_id, can_data) => {
196+
can_transmit(is_extended, can_id, can_data);
197+
}
195198
}
196199
}
197200
}

0 commit comments

Comments
 (0)