Hide navigation sidebar
Hide table of contents sidebar
Skip to content
Back to top
View this page
Toggle table of contents sidebar

# socketcand Interface

Socketcand is part of the Linux-CAN project, providing a Network-to-CAN bridge as a Linux damon. It implements a specific TCP/IP based communication protocol to transfer CAN frames and control commands.

The main advantage compared to UDP-based protocols (e.g. virtual interface) is, that TCP guarantees delivery and that the message order is kept.

Here is a small example dumping all can messages received by a socketcand daemon running on a remote Raspberry Pi:

    import can

    bus = can.interface.Bus(interface='socketcand', host="10.0.16.15", port=29536, channel="can0")

    # loop until Ctrl-C
    try:
      while True:
        msg = bus.recv()
        print(msg)
    except KeyboardInterrupt:
      pass

The output may look like this:

    Timestamp: 1637791111.209224    ID: 000006fd    X Rx                DLC:  8    c4 10 e3 2d 96 ff 25 6b
    Timestamp: 1637791111.233951    ID: 000001ad    X Rx                DLC:  4    4d 47 c7 64
    Timestamp: 1637791111.409415    ID: 000005f7    X Rx                DLC:  8    86 de e6 0f 42 55 5d 39
    Timestamp: 1637791111.434377    ID: 00000665    X Rx                DLC:  8    97 96 51 0f 23 25 fc 28
    Timestamp: 1637791111.609763    ID: 0000031d    X Rx                DLC:  8    16 27 d8 3d fe d8 31 24
    Timestamp: 1637791111.634630    ID: 00000587    X Rx                DLC:  8    4e 06 85 23 6f 81 2b 65

This interface also supports `detect_available_configs()`.

    import can
    import can.interfaces.socketcand

    cfg = can.interfaces.socketcand._detect_available_configs()
    if cfg:
        bus = can.Bus(**cfg[0])

The socketcand daemon broadcasts UDP beacons every 3 seconds. The default detection method waits for slightly more than 3 seconds to receive the beacon packet. If you want to increase the timeout, you can use `can.interfaces.socketcand.detect_beacon()` directly. Below is an example which detects the beacon and uses the configuration to create a socketcand bus.

    import can
    import can.interfaces.socketcand

    cfg = can.interfaces.socketcand.detect_beacon(6000)
    if cfg:
        bus = can.Bus(**cfg[0])

## Bus

class can.interfaces.socketcand.SocketCanDaemonBus(channel, host, port, tcp_tune=False, can_filters=None, **kwargs)

  Bases: `BusABC`

  Connects to a CAN bus served by socketcand.

  It implements `can.BusABC._detect_available_configs()` to search for available interfaces.

  It will attempt to connect to the server for up to 10s, after which a TimeoutError exception will be thrown.

  If the handshake with the socketcand server fails, a CanError exception is thrown.

  Parameters:

    - channel – The can interface name served by socketcand. An example channel would be ‘vcan0’ or ‘can0’.

    - host – The host address of the socketcand server.

    - port – The port of the socketcand server.

    - tcp_tune – This tunes the TCP socket for low latency (TCP_NODELAY, and TCP_QUICKACK). This option is not available under windows.

    - can_filters – See `can.BusABC.set_filters()`.

  send(msg, timeout=None)

    Transmit a message to the CAN bus.

    Parameters:

      - msg – A message object.

      - timeout – Ignored

  shutdown()

    Stops all active periodic tasks and closes the socket.

can.interfaces.socketcand.detect_beacon(timeout_ms=3100)

  Detects socketcand servers

  This is what `can.detect_available_configs()` ends up calling to search for available socketcand servers with a default timeout of 3100ms (socketcand sends a beacon packet every 3000ms).

  Using this method directly allows for adjusting the timeout. Extending the timeout beyond the default time period could be useful if UDP packet loss is a concern.

  Parameters:

    timeout_ms (int) – Timeout in milliseconds to wait for socketcand beacon packets

  Returns:

    See `detect_available_configs()`

  Return type:

    List[AutoDetectedConfig]

## Socketcand Quickstart

The following section will show how to get the stuff installed on a Raspberry Pi with a MCP2515-based CAN interface, e.g. available from Waveshare. However, it will also work with any other socketcan device.

### Install CAN Interface for a MCP2515 based interface on a Raspberry Pi

Add the following lines to `/boot/config.txt`. Please take care on the frequency of the crystal on your MCP2515 board:

    dtparam=spi=on
    dtoverlay=mcp2515-can0,oscillator=12000000,interrupt=25,spimaxfrequency=1000000

Reboot after `/boot/config.txt` has been modified.

### Enable socketcan for can0

Create config file for systemd-networkd to start the socketcan interface automatically:

    cat >/etc/systemd/network/80-can.network <<'EOT'
    [Match]
    Name=can0
    [CAN]
    BitRate=250K
    RestartSec=100ms
    EOT

Enable `systemd-networkd` on reboot and start it immediately (if it was not already startet):

    sudo systemctl enable systemd-networkd
    sudo systemctl start systemd-networkd

### Build socketcand from source

    # autoconf is needed to build socketcand
    sudo apt-get install -y autoconf
    # clone & build sources
    git clone https://github.com/linux-can/socketcand.git
    cd socketcand
    ./autogen.sh
    ./configure
    make

### Install socketcand

    make install

### Run socketcand

    ./socketcand -v -i can0

During start, socketcand will prompt its IP address and port it listens to:

    Verbose output activated

    Using network interface 'eth0'
    Listen adress is 10.0.16.15
    Broadcast adress is 10.0.255.255
    creating broadcast thread...
    binding socket to 10.0.16.15:29536