Can bus on linux
CAN bus on Linux
Create virtual UDP can bus
This virutal bus works in a docker container without access to host system.
create using python-can
from can.interfaces.udp_multicast import UdpMulticastBus
bus = UdpMulticastBus("224.0.0.1", interface="udp_multicast")
Note
Using udp_multicast
will always result in bus
receiving own messages.
Create virtual system can bus
Note
This works only on linux systems with access to kernel. Does not work in a docker container.
This will create vcan0
adapter:
Now install
sudo apt install can-utils
And test it, terminal 1:
candump vcan0
terminal 2:
cansend vcan0 123#DEADBEEF
Tip
You can install a system service to create virtual can on system startup.
Use setup_vcan_service.sh
for that.
Abstracting bus creation
get_can_bus()
can help abstract away bus creation. Example code:
import os
import logging
from can.interfaces.udp_multicast import UdpMulticastBus
from can.interfaces.socketcan import SocketcanBus
def is_ci_environment() -> bool:
"""Check if the code is running in a CI environment"""
return os.getenv("CI") == "true"
def get_can_bus() -> UdpMulticastBus | SocketcanBus:
"""Get a CAN bus instance, using environment variables
CAN_CHANNEL and CAN_INTERFACE for configuration or a multicast bus in CI"""
if is_ci_environment():
return UdpMulticastBus("224.0.0.1", interface="udp_multicast")
channel = os.getenv("CAN_CHANNEL")
if channel is None:
raise ValueError(
"Missing CAN_CHANNEL environment variable, set to can0 or similar"
)
interface = os.getenv("CAN_INTERFACE", "socketcan")
logging.info(f"Using CAN interface: {interface}, channel: {channel}")
if interface == "udp_multicast":
# note: will always receive own messages
return UdpMulticastBus(channel, interface=interface)
return SocketcanBus(
channel=channel, interface=interface, receive_own_messages=False
)
Setup can RPI hat
Tip
use setup_can.sh
to install system service.