Skip to content

Commit

Permalink
Handle CANErrorFrame, move decode logic up to read_frame match (#54)
Browse files Browse the repository at this point in the history
* Added my format script to gitignore

* Experimental handling of CAN Error Frame

* Changes

* Handle Remote frame

* Set CAN Socket to accept errors

* SocketOptions now included

---------

Co-authored-by: Jack Rubacha <[email protected]>
  • Loading branch information
harrison-e and jr1221 authored Oct 3, 2024
1 parent 2d6d467 commit 80b17cd
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 22 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@ decode_data.rs
encode_data.rs
encode_master_mapping.rs
format_data.rs

# my dumb script
./format
76 changes: 54 additions & 22 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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/#";

Expand Down Expand Up @@ -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<u32> {
//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.");
Expand All @@ -57,6 +57,7 @@ fn read_can(pub_path: &str, can_interface: &str) -> JoinHandle<u32> {
}

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() {
Expand All @@ -65,31 +66,62 @@ fn read_can(pub_path: &str, can_interface: &str) -> JoinHandle<u32> {
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();
Expand Down

0 comments on commit 80b17cd

Please sign in to comment.