This library implements Controller Area Network (CAN) communications on Linux using the SocketCAN interfaces. This provides a network socket interface to the CAN bus.
Please see the documentation for details about the Rust API provided by this library.
Version 3.0 adds integrated support for async/await, with the most popular runtimes, tokio, async-std, and smol. To get started we have already merged the tokio-socketcan crate into this one and implemented async-io
.
Unfortunaly this required a minor breaking change to the existing API, so we bumped the version to 3.0.
The async support is optional, and can be enabled with a feature for the target runtime: tokio
, async-std
, or smol
.
async-tokio
build feature.async-io
for use with async-std
and smol
SocketOptions
trait out of Socket
trait for use with async (breaking)tokio
or async-io
.async-std
and smol
which just bring in the async-io
module and alias the module name to async-std
or smol
, respectively, and build examples for each.CanAddr
pulic and added functions to help interact with low-level sockaddr types. Sockets can now be opened with an address.Error
directly from a CanErrorFrame
or std::io::ErrorKind
.CanErrorFrame::new()
now works.CanErrorFrame::new_error()
is similar but more intuitive using a raw ID word.From<CanError> for CanErrorFrame
to create an error frame from a CanError
.Frame::from_raw_id()
and Frame::remote_from_raw_id()
A number of items still did not makei into a release. These will be added in v3.x, coming soon.
The current version of the crate targets Rust Edition 2021 with an MSRV of Rust v1.65.0.
Note that, at this time, the MSRV is mostly diven by use of the clap v4.0
crate for managing command-line parameters in the utilities and example applications. The core library could likely be built with an earlier version of the compiler if required.
The tokio-socketcan crate was merged into this one to provide async support for CANbus using tokio.
This is enabled with the optional feature, tokio
.
This is a simple example of sending data frames from one CAN interface to another. It is included in the example applications as tokio_bridge.rs.
```rust use futures_util::StreamExt; use socketcan::{tokio::CanSocket, CanFrame, Result}; use tokio;
async fn main() -> Result<()> { let mut sockrx = CanSocket::open("vcan0")?; let socktx = CanSocket::open("can0")?;
while let Some(Ok(frame)) = sock_rx.next().await {
if matches!(frame, CanFrame::Data(_)) {
sock_tx.write_frame(frame)?.await?;
}
}
Ok(())
} ```
New support was added for the async-io runtime, supporting the async-std and smol runtimes.
This is enabled with the optional feature, async-io
. It can also be enabled with either feature, async-std
or smol
. Either of those specific runtime flags will simply build the async-io
support but then also alias the async-io
submodule with the specific feature/runtime name. This is simply for convenience.
Additionally, when building examples, the specific examples for the runtime will be built if specifying the async-std
or smol
feature(s).
This is a simple example of sending data frames from one CAN interface to another. It is included in the example applications as asyncstdbridge.rs.
```rust use socketcan::{async_std::CanSocket, CanFrame, Result};
async fn main() -> Result<()> { let sockrx = CanSocket::open("vcan0")?; let socktx = CanSocket::open("can0")?;
loop {
let frame = sock_rx.read_frame().await?;
if matches!(frame, CanFrame::Data(_)) {
sock_tx.write_frame(&frame).await?;
}
}
} ```
Integrating the full suite of tests into a CI system is non-trivial as it relies on a vcan0
virtual CAN device existing. Adding it to most Linux systems is pretty easy with root access, but attaching a vcan device to a container for CI seems difficult to implement.
Therefore, tests requiring vcan0
were placed behind an optional feature, vcan_tests
.
The steps to install and add a virtual interface to Linux are in the scripts/vcan.sh
script. Run it with root proveleges, then run the tests:
sh
$ sudo ./scripts/vcan.sh
$ cargo test --features=vcan_tests