hardbyte / hardbyte/python-can

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

オープン
#1,828 コメント 2 件 リアクション 0 件 担当者 0 名 GitHub で見る
bug
主要言語
Python
スター
1.6k
フォーク
697
PR マージ指標
30日以内にマージされた PR はありません

説明

### 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:

```python
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:

```python
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:
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

コントリビューションガイド

コントリビューションガイドを開く

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。