Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed-size tx/rx queues, improved error messages, 'any frame' callback handler, zero-length data payloads. #14

Merged
merged 9 commits into from
Mar 11, 2023
7 changes: 7 additions & 0 deletions examples/python_send_receive_callbacks/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,16 @@ def on_frame_d(frame : jcan.Frame):
print(f"FRAME 1AD {frame.data}")
# print(frame.data[0])

def on_anyother_frame(frame: jcan.Frame):
print(f"FRAME {frame.id}: {frame.data}")

bus.add_callback(0x1A5, on_frame_five)
bus.add_callback(0x1AD, on_frame_d)

# The add_callback for ID zero will be called when any other frame is received,
# as long as that frame does not have a callback associated with it.
bus.add_callback(0x0, on_anyother_frame)

bus.open("vcan0")

while True:
Expand Down
30 changes: 19 additions & 11 deletions jcan-python/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl PyJBus {
fn new() -> PyResult<Self> {
// Unbox the result of new_jbus, and return it
let bus = new_jbus().map_err(|e| {
PyOSError::new_err(format!("Error creating Bus: {}", e))
PyOSError::new_err(format!("{}", e))
})?;

// bus is a Box<JBus>, so we need to dereference it
Expand All @@ -50,17 +50,19 @@ impl PyJBus {
}

// Implement the open method for the PyJBus
fn open(&mut self, interface: String) -> PyResult<()> {
self.bus.open(interface).map_err(|e| {
PyOSError::new_err(format!("Error opening bus: {}", e))
// Add pyo3 default arguments of 256 for tx_queue_len and rx_queue_len
#[args(tx_queue_len = 256, rx_queue_len = 256)]
fn open(&mut self, interface: String, tx_queue_len: u16, rx_queue_len: u16) -> PyResult<()> {
self.bus.open(interface, tx_queue_len, rx_queue_len).map_err(|e| {
PyOSError::new_err(format!("{}", e))
})?;
Ok(())
}

// Implement the receive method for the PyJBus
fn receive(&mut self) -> PyResult<PyJFrame> {
let frame = self.bus.receive().map_err(|e| {
PyOSError::new_err(format!("Error receiving frame: {}", e))
PyOSError::new_err(format!("{}", e))
})?;
Ok(PyJFrame {
frame,
Expand All @@ -70,30 +72,30 @@ impl PyJBus {
// Implement the send method for the PyJBus
fn send(&mut self, frame: PyJFrame) -> PyResult<()> {
self.bus.send(frame.frame).map_err(|e| {
PyOSError::new_err(format!("Error sending frame: {}", e))
PyOSError::new_err(format!("{}", e))
})?;
Ok(())
}

// Implement set_id_filter for the PyJBus, which takes a list of IDs
fn set_id_filter(&mut self, allowed_ids: Vec<u32>) -> PyResult<()> {
self.bus.set_id_filter(allowed_ids).map_err(|e| {
PyOSError::new_err(format!("Error setting filter: {}", e))
PyOSError::new_err(format!("{}", e))
})?;
Ok(())
}

fn set_id_filter_mask(&mut self, allowed: u32, allowed_mask: u32) -> PyResult<()> {
self.bus.set_id_filter_mask(allowed, allowed_mask).map_err(|e| {
PyOSError::new_err(format!("Error setting filter mask: {}", e))
PyOSError::new_err(format!("{}", e))
})?;
Ok(())
}

// Receive many will return a list of buffered frames from the receive thread
fn receive_from_thread_buffer(&mut self) -> PyResult<Vec<PyJFrame>> {
let frames = self.bus.receive_from_thread_buffer().map_err(|e| {
PyOSError::new_err(format!("Error receiving frames: {}", e))
PyOSError::new_err(format!("{}", e))
})?;

Ok(frames.into_iter().map(|f| PyJFrame {
Expand Down Expand Up @@ -133,10 +135,16 @@ impl PyJBus {
let _gil = Python::with_gil(|py| {
for frame in frames {
// Lookup the callback function for the frame, given its ID
// If no callback is found, ignore the frame
// If no callback is found, check if we have an 'any' callback (ID of 0) assigned,
// otherwise ignore the frame.
let callback = match self.callbacks.get(&frame.frame.id) {
Some(c) => c,
None => continue,
None => {
match self.callbacks.get(&0) {
Some(c) => c,
None => continue,
}
},
};

// Call the callback function with the frame as an argument
Expand Down
2 changes: 2 additions & 0 deletions jcan/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ nix = "0.26"
serial_test = "0.9"
socketcan = { git = "https://github.com/socketcan-rs/socketcan-rs", version = "2.0.0-pre.0" }
cxx = "1.0"
env_logger = "0.10.0"
log = "0.4.17"

[build-dependencies]
cxx-build = "1.0"
Expand Down
2 changes: 1 addition & 1 deletion jcan/include/callback.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class Bus{
public:

Bus();
void open(const char *name);
void open(const char *name, uint16_t tx_queue_len, uint16_t rx_queue_len);

void set_id_filter(std::vector<uint32_t> allowed_ids);
void set_id_filter_mask(uint32_t allowed, uint32_t mask);
Expand Down
16 changes: 13 additions & 3 deletions jcan/src/callback.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ namespace org::jcan
return std::unique_ptr<Bus>(new Bus());
}

void Bus::open(const char *name) {
this->jBus->open(name);
void Bus::open(const char *name, uint16_t tx_queue_len, uint16_t rx_queue_len) {
this->jBus->open(name, tx_queue_len, rx_queue_len);
}

void Bus::set_id_filter(std::vector<uint32_t> allowed_ids) {
Expand Down Expand Up @@ -55,11 +55,21 @@ namespace org::jcan
// For each frame, call the callback function associated with the frame's ID
for (auto frame : frames) {
auto it = this->callbacks_.find(frame.id);
// If the ID is not in the map, do nothing

// If the ID is not in the map, check if we have an 'any' callback of ID 0 assigned
if (it != this->callbacks_.end())
{
// Call the callback function
it->second(frame);
}else{
// Check if '0' callback exists
auto it_any = this->callbacks_.find(0);

if (it_any != this->callbacks_.end())
{
// Call the '0' callback
it_any->second(frame);
}
}
}
}
Expand Down
Loading