Skip to content

IXXAT: does not recover / no exceptions after CAN bus disconneted for a few seconds #1828

Description

@IngmarPaetzold

Describe the bug

When I unplug the CAN bus (physically pull the connector), after a few seconds, the underlying Ixxat driver is raising an exception raise VCIError("Error warning limit exceeded") that I see in the output but cannot catch in any way.
After that, the bus seems dead (no receive, no transmit). It does not recover after the physical bus is reconnected.
The bus object is a can.TreadSafeBus().
Strangely, the bus's property .state is still can.BusState.ACTIVE, and I can happily call send() (without effect, of course). Unfortunately, it does not return a status code (the error?), nor is an exception thrown.
I tried to catch: can.CanError, can.CanOperationError, can.interfaces.ixxat.exceptions.VCIError
I tried to add a custom Listener on the Notifier with method on_error(), but this is not called (in contrast to on_message_received(), so the Listener basically works).

To Reproduce

some code lines from the CanBus class:

def __init__ ...
    can.rc = can.util.load_file_config(config_file)
    self._listener = MyListener(receive_handler)
    self._bus = can.ThreadSafeBus()
    ...
    loop = asyncio.get_event_loop()
    self._notifier = can.Notifier(self._bus, [self._listener], loop=loop)

async def send_can( self, message: can.Message ) -> bool:
    print( "Bus state: " + str(self._bus.state))
    if self._bus.state == can.BusState.ACTIVE:
        self._bus.send( message )
        return True
    else:
        return False

the Listener:

class MyListener(can.Listener):
    def __init__(self, receive_handler):
        self._receive_handler = receive_handler

    def __call__(self, msg: can.Message):
        return self.on_message_received(msg)

    async def on_message_received(self, msg):
        await self._receive_handler(msg)

    async def on_error(exc):
        print( "!!!!!!!!! Listener exception" )

Expected behavior

My assumptions were:

  • nice if the driver would recover on its own once the CAN is reconnected
  • nice if I could somehow retrieve the error state in any way (return value, exception, status call). Then I could -- somehow -- actively reset the interface. Don't know how, though...
  • is that an Ixxat related issue or a general one?

Additional context

OS and version: Windows 10
Python version: 3.12.4
python-can version: 4.4.2
python-can interface/s (if applicable): IXXAT

Traceback and logs This is what I get:
Other (unknown) CAN error
CAN message flags bAddFlags/bFlags2 0x00 bflags 0x03
Other (unknown) CAN error
CAN message flags bAddFlags/bFlags2 0x00 bflags 0x03
Other (unknown) CAN error
...  (lots of these messages)
CAN message flags bAddFlags/bFlags2 0x00 bflags 0x03
Exception in thread can.notifier for bus "unknown":
Traceback (most recent call last):
  File "C:\Users\xxxxx\AppData\Local\Programs\Python\Python312\Lib\threading.py", line 1073, in _bootstrap_inner
    self.run()
  File "C:\Users\xxxxx\AppData\Local\Programs\Python\Python312\Lib\threading.py", line 1010, in run
Exception in callback Notifier._on_error(VCIError('Err...mit exceeded'))
handle: <Handle Notifier._on_error(VCIError('Err...mit exceeded'))>
Traceback (most recent call last):
  File "C:\Users\xxxxx\AppData\Local\Programs\Python\Python312\Lib\asyncio\events.py", line 88, in _run     
    self._context.run(self._callback, *self._args)
  File "C:\Users\xxxxx\AppData\Local\Programs\Python\Python312\Lib\site-packages\can\notifier.py", line 163, in _on_error
    listener.on_error(exc)
TypeError: MyListener.on_error() takes 1 positional argument but 2 were given
    self._target(*self._args, **self._kwargs)
  File "C:\Users\xxxxx\AppData\Local\Programs\Python\Python312\Lib\site-packages\can\notifier.py", line 126, in _rx_thread
    if msg := bus.recv(self.timeout):
              ^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\xxxxx\AppData\Local\Programs\Python\Python312\Lib\site-packages\can\thread_safe_bus.py", line 53, in recv
    return self.__wrapped__.recv(timeout=timeout, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\xxxxx\AppData\Local\Programs\Python\Python312\Lib\site-packages\can\bus.py", line 127, in recv
    msg, already_filtered = self._recv_internal(timeout=time_left)
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\xxxxx\AppData\Local\Programs\Python\Python312\Lib\site-packages\can\interfaces\ixxat\canlib.py", line 148, in _recv_internal
    return self.bus._recv_internal(timeout)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\xxxxx\AppData\Local\Programs\Python\Python312\Lib\site-packages\can\interfaces\ixxat\canlib_vcinpl.py", line 731, in _recv_internal
    raise VCIError("Error warning limit exceeded")
can.interfaces.ixxat.exceptions.VCIError: Error warning limit exceeded
... (next bus.send() call:)
Bus state: BusState.ACTIVE

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions