From 3f9dcf7e05bc0e77f2fb9c3014723925ea4f02e2 Mon Sep 17 00:00:00 2001 From: Jack Rubacha Date: Thu, 20 Jun 2024 18:58:44 -0400 Subject: [PATCH] bump deps, misc cleanup of old IPC abstraction code of client (#43) * bump deps, misc cleanup of old IPC abstraction code of client * document how u test calypso --- Cargo.lock | 144 ++++++++++++++++++++++++++++++++++++++++--------- Cargo.toml | 4 +- README.md | 40 +++++++------- build.rs | 8 +-- src/client.rs | 16 ------ src/data.rs | 6 +-- src/lib.rs | 5 +- src/main.rs | 105 +++++++++++------------------------- src/message.rs | 5 +- src/mqtt.rs | 68 +++++++++-------------- 10 files changed, 204 insertions(+), 197 deletions(-) delete mode 100644 src/client.rs diff --git a/Cargo.lock b/Cargo.lock index 3b51969..17697f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,12 +34,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "bitflags" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" - [[package]] name = "bitflags" version = "1.3.2" @@ -58,6 +52,18 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c12d1856e42f0d817a835fe55853957c85c8c8a470114029143d3f12671446e" +[[package]] +name = "byte_conv" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "649972315d4931137a26fc2bf3ca95ee257ad796a5b57bdeb04205c91a4b5780" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "calypso" version = "0.1.0" @@ -127,6 +133,15 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +[[package]] +name = "embedded-can" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d2e857f87ac832df68fa498d18ddc679175cf3d2e4aa893988e5601baf9438" +dependencies = [ + "nb", +] + [[package]] name = "errno" version = "0.3.8" @@ -205,7 +220,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.39", ] [[package]] @@ -252,9 +267,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hex" -version = "0.2.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "home" @@ -277,9 +292,12 @@ dependencies = [ [[package]] name = "itertools" -version = "0.4.19" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a9b56eb56058f43dc66e58f40a214b2ccbc9f3df51861b63d51dec7b65bc3f" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] [[package]] name = "libc" @@ -305,14 +323,57 @@ version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "neli" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1100229e06604150b3becd61a4965d5c70f3be1759544ea7274166f4be41ef43" +dependencies = [ + "byteorder", + "libc", + "log", + "neli-proc-macros", +] + +[[package]] +name = "neli-proc-macros" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c168194d373b1e134786274020dae7fc5513d565ea2ebb9bc9ff17ffb69106d4" +dependencies = [ + "either", + "proc-macro2", + "quote", + "serde", + "syn 1.0.109", +] + [[package]] name = "nix" -version = "0.5.1" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb3ddedaa14746434a02041940495bf11325c22f6d36125d3bdd56090d50a79" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ - "bitflags 0.4.0", + "bitflags 1.3.2", + "cfg-if", "libc", + "memoffset", + "pin-utils", ] [[package]] @@ -335,9 +396,9 @@ dependencies = [ [[package]] name = "paho-mqtt" -version = "0.12.3" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e405de34b835fb6457d8b0169eda21949f855472b3e346556af9e29fac6eb2" +checksum = "b8367868d51cef74c28da328ed8f60529ddd3f04dca1867dd825fcc3085a4308" dependencies = [ "async-channel", "crossbeam-channel", @@ -497,6 +558,26 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "serde" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "slab" version = "0.4.9" @@ -508,15 +589,32 @@ dependencies = [ [[package]] name = "socketcan" -version = "1.7.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3101efc6ef5af6f1c1a488241b469757b7a183baca63af958cd90e4696446c80" +checksum = "175eef9db7dedf6c5d3f5926fed7471633a9b9929a6ee086bdf436ee954532b6" dependencies = [ + "bitflags 1.3.2", + "byte_conv", + "embedded-can", "hex", "itertools", "libc", + "log", + "nb", + "neli", "nix", - "try_from", + "thiserror", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] @@ -560,15 +658,9 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.39", ] -[[package]] -name = "try_from" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "923a7ee3e97dbfe8685261beb4511cc9620a1252405d02693d43169729570111" - [[package]] name = "unicode-ident" version = "1.0.12" diff --git a/Cargo.toml b/Cargo.toml index e91bacf..932ac79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -socketcan = "1.7.0" -paho-mqtt = "0.12.3" +socketcan = "3.3.0" +paho-mqtt = "0.12.5" protobuf-codegen = "3.3.0" protobuf = "3.3.0" bitstream-io = "2.3.0" diff --git a/README.md b/README.md index baf331b..22756b6 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,8 @@ # Calypso -Custom CAN Decoder for all the data being streamed around the car +Custom CAN decoder to translate CAN messages to MQTT protobuf encoded packets with low latency and a YAML configuration structure. -### Recommended Extensions -View https://www.youtube.com/watch?v=BU1LYFkpJuk for more information - -- rust-analyzer -- CodeLLDB -- Even Better TOML -- Error Lens -- Todo Tree -- crates +### Develop setup #### Go to Settings in VSCode search Rust-analyzer check and set the command from check -> clippy @@ -23,19 +15,29 @@ add following information: } ``` -### NERO 1.0 Config -Utilizes a linux IPC to stream data to the NERO frontend +To test it on linux, please install: +- mosquitto broker: https://mosquitto.org +- can-utils +- mqttui: https://github.com/EdJoPaTo/mqttui + + +### Developing + +Process for testing: +- run `mosquitto` and leave it open +- run `mqttui` and leave it open +- setup the can network: + - `sudo ip link add dev vcan0 type vcan` + - `sudo ip link set dev vcan0 up` -run ```/home/ner/Desktop/Calypso/target/release/calypso ipc /tmp/ipc.sock``` +run ```cargo run localhost:1883 vcan0``` -### SIREN and NERO 2.0 Config -Utilizes MQTT Web Socket to offload data from the car for our telemetry system -run ```/home/ner/Desktop/Calypso/target/release/calypso mqtt localhost:1883``` +To send a can message: +- `cansend vcan0 #` +Ex. `cansend vcan0 702#01010101FFFFFFFF` +Now view calypso interpret the can message and broadcast it on `mqttui` -### Synthesize Rust -`cd oxy` -`python3 typedpoc.py` ### Generate Proto diff --git a/build.rs b/build.rs index 3944752..4d1ed5d 100644 --- a/build.rs +++ b/build.rs @@ -7,14 +7,14 @@ fn main() { match Command::new("python3").arg("./calypsogen.py").status() { Ok(status) if status.success() => { println!("Python script executed successfully"); - }, + } Ok(status) => { eprintln!("Python script exited with status: {}", status); std::process::exit(1); - }, + } Err(e) => { eprintln!("Failed to execute Python script: {}", e); std::process::exit(1); - }, + } } -} \ No newline at end of file +} diff --git a/src/client.rs b/src/client.rs deleted file mode 100644 index 41a4c85..0000000 --- a/src/client.rs +++ /dev/null @@ -1,16 +0,0 @@ -use crate::data::Data; - -/** - * Cummulative trait for structs that are able to connect to a server and publish data to it. - */ -pub trait Client { - /** - * Connects to the server at the given path. - */ - fn connect(&mut self, path: &str); - - /** - * Publishes the given data to the server. - */ - fn publish(&mut self, data: &Data); -} diff --git a/src/data.rs b/src/data.rs index 3c269e7..e797ead 100644 --- a/src/data.rs +++ b/src/data.rs @@ -41,8 +41,4 @@ impl Data { unit: unit.to_string(), } } - - pub fn to_json(&self) -> String { - format!("{{\"value\": {:#?}, \"unit\": \"{}\"}}", self.value, self.unit) - } -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs index 6c1f8a9..d45c958 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ -pub mod client; pub mod data; pub mod decode_data; +pub mod master_mapping; pub mod message; pub mod mqtt; -pub mod master_mapping; -pub mod serverdata; \ No newline at end of file +pub mod serverdata; diff --git a/src/main.rs b/src/main.rs index 1322d74..a62de0d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,52 +1,14 @@ -use std::{ - env, - process::{self, Command}, -}; +use std::{env, process}; -use calypso::{client::Client, message::Message, mqtt::MqttClient}; -use socketcan::CANSocket; - -fn configure_can(can_interface: &str) { - let mut down_command = Command::new("sudo") - .arg("ifconfig") - .arg(can_interface) - .arg("down") - .spawn() - .expect("down command did not work"); - down_command // Takes down any current can networks - .wait() - .expect("Fail while waiting for down command"); - let mut bit_rate_commmand = Command::new("sudo") - .arg("ip") - .arg("link") - .arg("set") - .arg(can_interface) - .arg("type") - .arg("can") - .arg("bitrate") - .arg("1000000") - .spawn() - .expect("bit rate command did not work"); - bit_rate_commmand //sets the bit rate of the can network - .wait() - .expect("Fail while waiting for bit rate"); - let mut up_command = Command::new("sudo") - .arg("ifconfig") - .arg(can_interface) - .arg("up") - .spawn() - .expect("up command did nto work"); - up_command // Brings up the new can network - .wait() - .expect("Fail while waiting for up command"); -} +use calypso::{message::Message, mqtt::MqttClient}; +use socketcan::{CanFrame, CanSocket, EmbeddedFrame, Socket}; /** * Reads the can socket and publishes the data to the given client. */ -fn read_can(mut publisher: Box, can_interface: &str) { +fn read_can(mut publisher: MqttClient, can_interface: &str) { //open can socket channel at name can_interface - let socket = CANSocket::open(can_interface); + let socket = CanSocket::open(can_interface); let socket = match socket { Ok(socket) => socket, Err(err) => { @@ -56,14 +18,28 @@ fn read_can(mut publisher: Box, can_interface: &str) { }; loop { let msg = match socket.read_frame() { - Ok(msg) => msg, + Ok(CanFrame::Data(msg)) => msg, + Ok(CanFrame::Remote(_)) => { + println!("Ignoring remote frame"); + continue; + } + Ok(CanFrame::Error(_)) => { + println!("Ignoring error frame"); + continue; + } Err(err) => { println!("Failed to read CAN frame: {}", err); continue; } }; let data = msg.data(); - let message = Message::new(msg.id(), data.to_vec()); + let message = Message::new( + match msg.id() { + socketcan::Id::Standard(std) => std.as_raw().into(), + socketcan::Id::Extended(ext) => ext.as_raw(), + }, + data.to_vec(), + ); let decoded_data = message.decode(); for data in decoded_data.iter() { publisher.publish(data) @@ -73,57 +49,36 @@ fn read_can(mut publisher: Box, can_interface: &str) { /** * Parses the command line arguments. - * Returns the client type and the path to connect to. */ -fn parse_args() -> (String, Box, String, bool) { +fn parse_args() -> (String, String) { let args: Vec = env::args().collect(); println!("{:?}", args); if args.len() < 3 { println!("Not enough arguments!"); - println!("Client type and client path are required."); + println!("Siren (MQTT) URL and can interface are required"); process::exit(1); } - let client_type = &args[1]; - let path = &args[2]; - let can_interface = if args.len() > 3 { &args[3] } else { "can0" }; - - let skip_can_config = args.len() > 4 && args[4] == "skip_can_configure"; + let path = &args[1]; + let can_interface = &args[2]; - println!("Client type: {}", client_type); - println!("Path: {}", path); + println!("Siren URL: {}", path); println!("Can interface: {}", can_interface); - println!("Skip can configuration: {}", skip_can_config); - match client_type.as_str() { - "mqtt" => ( - String::from(path), - Box::new(MqttClient::new()) as Box, - String::from(can_interface), - skip_can_config, - ), - _ => { - println!("Please provide a valid client type"); - process::exit(1); - } - } + (String::from(path), String::from(can_interface)) } /** * Main Function * Configures the can network, retrieves the client based on the command line arguments, * connects the client and then reads the can socket from specified interface. - * Sample Calls for IPC "/home/ner/Desktop/Calypso/target/release/calypso ipc /tmp/ipc.sock &" * Sample Call for Mqtt "/home/ner/Desktop/Calypso/target/release/calypso mqtt localhost:1883 &" * * 3rd argument: if a can interface is passed the program will use it instead of the default can0 - * 4th argument: if skip_can_configure is passed the program will not call can interface setup commands - * Ex: "/home/ner/Desktop/Calypso/target/release/calypso mqtt localhost:1883 can0 skip_can_configure &" + * Ex: "/home/ner/Desktop/Calypso/target/release/calypso mqtt localhost:1883 can0 &" */ fn main() { - let (path, mut client, can_interface, skip_can_configure) = parse_args(); - if !skip_can_configure { - configure_can(&can_interface) - } + let (path, can_interface) = parse_args(); + let mut client = MqttClient::new(); client.connect(&path); read_can(client, &can_interface); } diff --git a/src/message.rs b/src/message.rs index 0a8c9be..2783ed8 100644 --- a/src/message.rs +++ b/src/message.rs @@ -17,10 +17,7 @@ impl Message { * Creates a new message with the given timestamp, id, and data. */ pub fn new(id: u32, data: Vec) -> Self { - Self { - id, - data, - } + Self { id, data } } /** diff --git a/src/mqtt.rs b/src/mqtt.rs index 6fa97ec..48dae0e 100644 --- a/src/mqtt.rs +++ b/src/mqtt.rs @@ -3,11 +3,9 @@ use mqtt::ServerResponse; use std::time::Duration; use std::{process, thread}; -use crate::client::Client; use crate::data::Data; use crate::serverdata; -pub const DFLT_BROKER: &str = "mqtt://localhost:1883"; const DFLT_CLIENT: &str = "calypso"; /** @@ -17,15 +15,33 @@ pub struct MqttClient { client: Option, } +impl Default for MqttClient { + /** + * Creates a new MqttClient. + */ + fn default() -> Self { + Self::new() + } +} + /** - * Implement the Publish trait for MqttClient. + * Implementation of the MqttClient struct. */ -impl Client for MqttClient { +impl MqttClient { /** - * Publishes the given data to the broker. - * param data: The data object to format and send. + * Creates a new MqttClient. */ - fn publish(&mut self, data: &Data) { + pub fn new() -> MqttClient { + MqttClient { client: None } + } + + + pub fn connect(&mut self, host: &str) { + self._set_host(&host.to_string()); + self._connect(); + } + + pub fn publish(&mut self, data: &Data) { let topic = data.topic.to_string(); let mut payload = serverdata::ServerData::new(); payload.unit = data.unit.to_string(); @@ -51,41 +67,7 @@ impl Client for MqttClient { } } - /** - * Connects to the broker. - * Sets the host and then connects - */ - fn connect(&mut self, host: &str) { - self.set_host(&host.to_string()); - self.connect(); - } -} - -impl Default for MqttClient { - /** - * Creates a new MqttClient. - */ - fn default() -> Self { - Self::new() - } -} - -/** - * Implementation of the MqttClient struct. - */ -impl MqttClient { - /** - * Creates a new MqttClient. - */ - pub fn new() -> MqttClient { - MqttClient { client: None } - } - - /** - * Creates a new MqttClient with the given host name. - * param host_name: The host name of the broker. - */ - fn set_host(&mut self, host_name: &String) { + fn _set_host(&mut self, host_name: &String) { let create_options = mqtt::CreateOptionsBuilder::new() .server_uri(host_name) .client_id(DFLT_CLIENT.to_string()) @@ -103,7 +85,7 @@ impl MqttClient { * Connects to the broker. * Sets the last will and testament. */ - fn connect(&mut self) { + fn _connect(&mut self) { if let Some(client) = &self.client { let lastwilltestatment = mqtt::MessageBuilder::new() .topic("Calypso/Status")