diff --git a/.gitignore b/.gitignore index a6a75d4..a9d34ae 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,6 @@ decode_data.rs encode_data.rs encode_master_mapping.rs format_data.rs + +# my dumb script +./format diff --git a/src/main.rs b/src/main.rs index 5cc647c..6a0778a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,13 +6,13 @@ use std::{ }; use calypso::{ - command_data, data::EncodeData, decodable_message::DecodableMessage, + command_data, data::DecodeData, data::EncodeData, decodable_message::DecodableMessage, encodable_message::EncodableMessage, encode_master_mapping::ENCODABLE_KEY_LIST, mqtt::MqttClient, serverdata, }; use clap::Parser; use protobuf::Message; -use socketcan::{CanFrame, CanSocket, EmbeddedFrame, Id, Socket}; +use socketcan::{CanError, CanFrame, CanSocket, EmbeddedFrame, Frame, Id, Socket, SocketOptions}; const ENCODER_MAP_SUB: &str = "Calypso/Bidir/Command/#"; @@ -47,7 +47,7 @@ struct CalypsoArgs { * Reads the can socket and publishes the data to the given client. */ fn read_can(pub_path: &str, can_interface: &str) -> JoinHandle { - //open can socket channel at name can_interface + // Open CAN socket channel at name can_interface let mut client = MqttClient::new(pub_path, "calypso-decoder"); if client.connect().is_err() { println!("Unable to connect to Siren, going into reconnection mode."); @@ -57,6 +57,7 @@ fn read_can(pub_path: &str, can_interface: &str) -> JoinHandle { } let socket = CanSocket::open(can_interface).expect("Failed to open CAN socket!"); + socket.set_error_filter_accept_all().expect("Failed to set error mask on CAN socket!"); thread::spawn(move || loop { if !client.is_connected() { @@ -65,31 +66,62 @@ fn read_can(pub_path: &str, can_interface: &str) -> JoinHandle { println!("[read_can] Reconnected to Siren!"); } } - - let msg = match socket.read_frame() { - Ok(CanFrame::Data(msg)) => msg, - Ok(CanFrame::Remote(_)) => { - println!("Ignoring remote frame"); - continue; + // Read from MQTT socket + let decoded_data = match socket.read_frame() { + // CanDataFrame + Ok(CanFrame::Data(data_frame)) => { + let data = data_frame.data(); + let message = DecodableMessage::new( + match data_frame.id() { + socketcan::Id::Standard(std) => std.as_raw().into(), + socketcan::Id::Extended(ext) => ext.as_raw(), + }, + data.to_vec(), + ); + message.decode() } - Ok(CanFrame::Error(_)) => { - println!("Ignoring error frame"); - continue; + // CanRemoteFrame + Ok(CanFrame::Remote(remote_frame)) => { + // Send frame ID for Remote + vec![DecodeData::new( + vec![remote_frame.raw_id() as f32], + "Calypso/Events/RemoteFrame", + "id", + )] } + // CanErrorFrame + Ok(CanFrame::Error(error_frame)) => { + // Publish enum index of error onto CAN + // TODO: Look into string representation with Display + // TODO: Ask `const` impl for Display or enum? + // Impl from ErrorFrame -> f32 + let error_index: f32 = match CanError::from(error_frame) { + CanError::TransmitTimeout => 0.0, + CanError::LostArbitration(_) => 1.0, + CanError::ControllerProblem(_) => 2.0, + CanError::ProtocolViolation { .. } => 3.0, + CanError::TransceiverError => 4.0, + CanError::NoAck => 5.0, + CanError::BusOff => 6.0, + CanError::BusError => 7.0, + CanError::Restarted => 8.0, + CanError::DecodingFailure(_) => 9.0, + CanError::Unknown(_) => 10.0, + }; + vec![DecodeData::new( + vec![error_index], + "Calypso/Events/ErrorFrame", + "CanError enum", + )] + } + // Socket failure Err(err) => { - println!("Failed to read CAN frame: {}", err); + println!("CAN Socket failure: {}", err); continue; } }; - let data = msg.data(); - let message = DecodableMessage::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(); + + // Convert decoded CAN to Protobuf and publish over MQTT for data in decoded_data.iter() { let mut payload = serverdata::ServerData::new(); payload.unit = data.unit.to_string();