# Demo\_app.py utilizing can as transport layer

**URL:** <https://forum.opencyphal.org/t/demo-app-py-utilizing-can-as-transport-layer/2065>\
**Category:** Applications & Usage\
**Created:** [January 5, 2024, 5:10pm UTC](https://forum.opencyphal.org/t/demo-app-py-utilizing-can-as-transport-layer/2065 "2024-01-05T17:10:13Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Scoeerg](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/scoeerg/32/1713_2.png) [@Scoeerg](https://forum.opencyphal.org/u/Scoeerg)\
**Post date:** [January 5, 2024, 5:10pm UTC](https://forum.opencyphal.org/t/demo-app-py-utilizing-can-as-transport-layer/2065/1 "2024-01-05T17:10:13Z")

</div>

Hi all,

I am fairly new to the game of CAN and Cyphal. I did the [pycyphal.com demo](https://pycyphal.readthedocs.io/en/stable/pages/demo.html), which works like a charm for UDP as transport layer. Now, I would like to utilize CAN as transport layer, instead of UDP. To do this I changed the code accordingly:

```auto
export UAVCAN __NODE__ ID=42 # Set the local node-ID 42 (anonymous by default)
export UAVCAN __CAN__ IFACE="socketcan:can0" # Use CAN can0 as transport layer
export UAVCAN __CAN__ BITRATE="500000 5000000" # 500kbits
export UAVCAN __CAN__ MTU=16 # Maximum Transmission Unit (largest package size for a single frame)
export UAVCAN __SUB__ TEMPERATURE_SETPOINT__ID=2345 # Subject "temperature_setpoint" on ID 2345
export UAVCAN __SUB__ TEMPERATURE_MEASUREMENT__ID=2346 # Subject "temperature_measurement" on ID 2346
export UAVCAN __PUB__ HEATER_VOLTAGE__ID=2347 # Subject "heater_voltage" on ID 2347
export UAVCAN __SRV__ LEAST_SQUARES__ID=123 # Service "least_squares" on ID 123
export UAVCAN __DIAGNOSTIC__ SEVERITY=2 

```

based on scarcely scattered information on this forum. `can0` of course exists, hence

```auto
sudo ip link set can0 up type can bitrate 500000
ifconfig

```

returns

```auto
can0: flags=193<UP,RUNNING,NOARP> mtu 16
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 10 (UNSPEC)
        RX packets 0 bytes 0 (0.0 B)
        RX errors 0 dropped 0 overruns 0 frame 0
        TX packets 0 bytes 0 (0.0 B)
        TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

```

and then when running `python3 demo_app.py` simply returns `Running. Press Ctrl+C to stop.`, as expected. But when aborting, it prints

```auto
CDiagnosticPublisher(Publisher(dtype=uavcan.diagnostic.Record.1.1, transport_session=BroadcastCANOutputSession(OutputSessionSpecifier
(data_specifier=MessageDataSpecifier(subject_id=8184), remote_node_id=None), PayloadMetadata(extent_bytes=300)))) TIMEOUT 
uavcan.diagnostic.Record.1.1(timestamp=uavcan.time.SynchronizedTimestamp.1.0(microsecond=0), 
severity=uavcan.diagnostic.Severity.1.0(value=2), text="pycyphal.transport.can.media.socketcan._socketcan: 
SocketCANMedia('can0', mtu=16) FIXME: acceptance filter configuration is not yet implemented; please submit patches! 
Requested configuration: ext:xxx1x0xxxxxxxxx0101010xxxxxxx, ext:xxxxx0xxxxxxxxxxxxxxxx0")

Traceback (most recent call last):
  File "$mypath/demo_app.py", line 159, in <module>
    asyncio.run(main())
  File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.10/asyncio/base_events.py", line 636, in run_until_complete
    self.run_forever()
  File "/usr/lib/python3.10/asyncio/base_events.py", line 603, in run_forever
    self._run_once()
  File "/usr/lib/python3.10/asyncio/base_events.py", line 1871, in _run_once
    event_list = self._selector.select(timeout)
  File "/usr/lib/python3.10/selectors.py", line 469, in select
    fd_event_list = self._selector.poll(timeout, max_ev)
KeyboardInterrupt

```

tells me this has not yet been implemented ( **FIXME: acceptance filter configuration is not yet implemented; please submit patches!** ), and `yakut` cannot echo the heartbeat as intended, doing:

```auto
export UAVCAN __CAN__ IFACE="socketcan:can0"
yakut sub --with-metadata uavcan.node.heartbeat uavcan.diagnostic.record

```

returns nothing. `ifconfig` also tells me there’s nothing happening on the BUS (aka RX/TX-packets are 0). Any advice?

— Nice to Know—  
When switching between UDP and CAN as transport layer, one must delete the `demo_app.db`, otherwise things go boomboom.  
— Nice to Know —

---

<div class="post-metadata">

**Author:** ![pavel.kirienko](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/pavel.kirienko/32/9_2.png) [@pavel.kirienko](https://forum.opencyphal.org/u/pavel.kirienko)\
**Post date:** [January 5, 2024, 6:13pm UTC](https://forum.opencyphal.org/t/demo-app-py-utilizing-can-as-transport-layer/2065/2 "2024-01-05T18:13:07Z")

</div>

The MTU is set incorrectly. According to ifconfig, your `can0` is a Classic CAN, because its kernel MTU is 16 bytes (8 bytes of payload plus 8 bytes of overhead); whereas you’re setting the transport MTU to 16 bytes, which requires CAN FD. Set the MTU to 8 bytes to fix the problem:

```auto
export UAVCAN __CAN__ MTU=8

```

I regularly see much confusion caused by the fact that the MTU reported by the Linux tools includes the 8 bytes of overhead.

> [@Scoeerg](#):
>
> tells me this has not yet been implemented

This message is irrelevant.

---

<div class="post-metadata">

**Author:** ![Scoeerg](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/scoeerg/32/1713_2.png) [@Scoeerg](https://forum.opencyphal.org/u/Scoeerg)\
**Post date:** [January 6, 2024, 3:14pm UTC](https://forum.opencyphal.org/t/demo-app-py-utilizing-can-as-transport-layer/2065/3 "2024-01-06T15:14:40Z")

</div>

Hi @pavel.kirienko

this worked, thank you. New config is now

```auto
export UAVCAN __NODE__ ID=42 # Set the local node-ID 42 (anonymous by default)
export UAVCAN __CAN__ IFACE="socketcan:can0" # Use CAN can0 as transport layer
export UAVCAN __CAN__ BITRATE="500000 5000000" # 500kbits, 500kbits arbitration 
export UAVCAN __CAN__ MTU=8 # Maximum Transmission Unit (largest package size for a single frame)
export UAVCAN __SUB__ TEMPERATURE_SETPOINT__ID=2345 # Subject "temperature_setpoint" on ID 2345
export UAVCAN __SUB__ TEMPERATURE_MEASUREMENT__ID=2346 # Subject "temperature_measurement" on ID 2346
export UAVCAN __PUB__ HEATER_VOLTAGE__ID=2347 # Subject "heater_voltage" on ID 2347
export UAVCAN __SRV__ LEAST_SQUARES__ID=123 # Service "least_squares" on ID 123
export UAVCAN __DIAGNOSTIC__ SEVERITY=2 

```

and ifconfig now replied with

```auto
can0: flags=193<UP,RUNNING,NOARP> mtu 16
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 10 (UNSPEC)
        RX packets 165121 bytes 1320968 (1.3 MB)
        RX errors 0 dropped 0 overruns 0 frame 0
        TX packets 3 bytes 24 (24.0 B)
        TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

```

i.e. there’s traffic on the CAN bus now. Every once in a while `demo_app.py` prints

```auto
DiagnosticPublisher(Publisher(dtype=uavcan.diagnostic.Record.1.1, 
transport_session=BroadcastCANOutputSession(OutputSessionSpecifier(data_specifier=
MessageDataSpecifier(subject_id=8184), remote_node_id=None), PayloadMetadata(extent_bytes=300)))) 
TIMEOUT uavcan.diagnostic.Record.1.1(timestamp=uavcan.time.SynchronizedTimestamp.1.0(microsecond=0), 
severity=uavcan.diagnostic.Severity.1.0(value=2), text="pycyphal.transport.can._can: 
CANTransport(SocketCANMedia('can0', mtu=8), local_node_id=42): 1 frames of 1 total with CAN ID 0x107d552a could 
not be sent before the deadline")

```

which I will ignore (for now). **But** sourcing the data types

```auto
export YAKUT_PATH="$mypath/uavcan"
export YAKUT_PATH="$mypath/sirius_cyber_corp"
# Setting up the Cyphal/UAVCAN parameters, in this case we are using Cyphal via CAN
export UAVCAN __CAN__ IFACE="socketcan:can0"
yakut sub --with-metadata uavcan.node.heartbeat uavcan.diagnostic.record

```

**still won’t print the heartbeat as expected.**

— `demo_app.py` problem —  
Also, restarting `demo_app.py` responds with

```auto
DiagnosticPublisher(Publisher(dtype=uavcan.diagnostic.Record.1.1, transport_session=BroadcastCANOutputSession(OutputSessionSpecifier
(data_specifier=MessageDataSpecifier(subject_id=8184), remote_node_id=None), 
PayloadMetadata(extent_bytes=300)))) ERROR OSError [Errno 105] No buffer space available

```

**Fixed** by restarting `can0`, i.e. `sudo ip link set can0 down`, `sudo ip link set can0 up type can bitrate 500000`  
— `demo_app.py` problem —

---

<div class="post-metadata">

**Author:** ![pavel.kirienko](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/pavel.kirienko/32/9_2.png) [@pavel.kirienko](https://forum.opencyphal.org/u/pavel.kirienko)\
**Post date:** [January 6, 2024, 5:17pm UTC](https://forum.opencyphal.org/t/demo-app-py-utilizing-can-as-transport-layer/2065/4 "2024-01-06T17:17:46Z")

</div>

If your `can0` is a physical bus, ensure there is at least one other node available for the interface to function. Alternatively, use vcan.

---

<div class="post-metadata">

**Author:** ![Scoeerg](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/scoeerg/32/1713_2.png) [@Scoeerg](https://forum.opencyphal.org/u/Scoeerg)\
**Post date:** [January 6, 2024, 7:27pm UTC](https://forum.opencyphal.org/t/demo-app-py-utilizing-can-as-transport-layer/2065/5 "2024-01-06T19:27:01Z")

</div>

Yes `can0` is a physical bus, something like [CAN USB adapter](https://www.google.com/search?q=can+usb+adapter), which registers as a [Geschwister Schneider GmbH / Candlelight CAN USB adapter as used for Unix Kernel](https://linux-automation.com/de/products/candlelight.html) ([or here](https://python-can.readthedocs.io/en/stable/interfaces/gs_usb.html)).

Meaning for the UDP tutorial, since its’s looped(?) to `localhost/127.0.0.1` it works even without a second node? I am note sure I tried `yakut` in UDP with or without the second node up.

Please elaborate.

---

<div class="post-metadata">

**Author:** ![pavel.kirienko](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/pavel.kirienko/32/9_2.png) [@pavel.kirienko](https://forum.opencyphal.org/u/pavel.kirienko)\
**Post date:** [January 7, 2024, 1:10pm UTC](https://forum.opencyphal.org/t/demo-app-py-utilizing-can-as-transport-layer/2065/6 "2024-01-07T13:10:46Z")

</div>

The requirement to have at least one node follows from the design of the CAN bus itself and it has no relation to Cyphal. A CAN controller will keep retransmitting the frame until at least one node has confirmed its reception. Since you have no nodes on the physical bus, the frames cannot be confirmed, so transmission cannot make progress. As a result, the frames you’re attempting to transmit just get stuck in the TX queue until it’s full; this is where you get the warnings about timed out transmissions.

Virtual CAN ifaces do not require TX frames to be confirmed so they can work without physical nodes (and they can’t have physical nodes indeed since they are virtual).

UDP/IP does not require frame transmission confirmation since it is built on completely different principles.

---

<div class="post-metadata">

**Author:** ![Scoeerg](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/scoeerg/32/1713_2.png) [@Scoeerg](https://forum.opencyphal.org/u/Scoeerg)\
**Post date:** [January 8, 2024, 9:27am UTC](https://forum.opencyphal.org/t/demo-app-py-utilizing-can-as-transport-layer/2065/7 "2024-01-08T09:27:55Z")

</div>

Thank you for the elaborate answer. I wrongly assumed `yakut` is just another node on the bus.
