hardbyte / hardbyte/python-can

Timeout for slcan Notifier breaks communication

Offen
#727 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
Vorherrschende Sprache
Python
Sterne
1.6k
Forks
697
PR-Merge-Kennzahlen
Keine gemergten PRs in 30 T.

Beschreibung

Hello,
For about two days I'm investigating problem with python-can 3.3.2 and hardware called [UCCB](https://github.com/UsbCANConverter-UCCbasic/UCCBEmbedded) which implements (more or less) slcan protocol over USB.

During my tests, I'm using device in loopback mode, so I have changed method `open` in `slcan.py` from:
```
def open(self):
self.write('O')
```
to:
```
def open(self):
self.write('l')
```

Additionally, to monitor data sent and received by `slcan.py` interface I have changed `write` method from:
```
def write(self, string):
self.serialPortOrig.write(string.encode() + self.LINE_TERMINATOR)
self.serialPortOrig.flush()
```
to:
```
def write(self, string):
self.serialPortOrig.write(string.encode() + self.LINE_TERMINATOR)
print("SENT:"+str(string.encode() + self.LINE_TERMINATOR))
self.serialPortOrig.flush()
```
and, similar way, `_recv_internal` from:
```
# If we still don't have a complete message, do a blocking read
if self.LINE_TERMINATOR not in self._buffer:
self._buffer += self.serialPortOrig.read_until(self.LINE_TERMINATOR)

if self.LINE_TERMINATOR not in self._buffer:
# Timed out
return None, False
```
to:
```
# If we still don't have a complete message, do a blocking read
if self.LINE_TERMINATOR not in self._buffer:
self._buffer += self.serialPortOrig.read_until(self.LINE_TERMINATOR)

print("RECEIVED:"+str(self._buffer))

if self.LINE_TERMINATOR not in self._buffer:
# Timed out
return None, False
```

The minimal example which shows problem is:
```
import can, time

class canFramePrinter(can.Listener):

def __init__(self):
super().__init__()

def on_message_received(self,msg):
print("ID: {}\tDLC: {}\t{}".format(msg.arbitration_id,msg.dlc,msg.data.hex()))

canbus = can.interface.Bus(interface="slcan", channel="COM6") ## hardcoded serial port name
canbusNotifier=can.Notifier(canbus,[canFramePrinter()])

tx_msg = can.Message(arbitration_id=0x01, data=[0x11, 0x22], is_extended_id=False)

time.sleep(3)
canbus.send(tx_msg)

time.sleep(3)
canbus.send(tx_msg)

time.sleep(3)
canbus.send(tx_msg)

time.sleep(3)
canbus.send(tx_msg)

time.sleep(3)
```
I have expected that it will be possible to receive from loopback the same frames which were sent, but in the terminal I see following:
```
D:/Python37/python.exe ./test.py
SENT:b'l\r'
RECEIVED:bytearray(b'\r')
RECEIVED:bytearray(b'')
RECEIVED:bytearray(b'')
SENT:b't00121122\r'
RECEIVED:bytearray(b'\x07')
RECEIVED:bytearray(b'\x07')
RECEIVED:bytearray(b'\x07')
RECEIVED:bytearray(b'\x07')
SENT:b't00121122\r'
RECEIVED:bytearray(b'\x07\x07')
RECEIVED:bytearray(b'\x07\x07')
SENT:b't00121122\r'
RECEIVED:bytearray(b'\x07\x07\x07')
RECEIVED:bytearray(b'\x07\x07\x07')
RECEIVED:bytearray(b'\x07\x07\x07')
RECEIVED:bytearray(b'\x07\x07\x07\x07')
SENT:b't00121122\r'
RECEIVED:bytearray(b'\x07\x07\x07\x07')
RECEIVED:bytearray(b'\x07\x07\x07\x07')
RECEIVED:bytearray(b'\x07\x07\x07\x07')
```
0x07 sign is defined as error flag, when command sent to device is not recognised. Flag is duplicated when next error occurs. But when I change `Notifier` instantiation from:
```
canbusNotifier=can.Notifier(canbus,[canFramePrinter()])
```
to:
```
canbusNotifier=can.Notifier(canbus,[canFramePrinter()],None)
```
received terminal output is:
```
D:/Python37/python.exe ./test.py
SENT:b'l\r'
RECEIVED:bytearray(b'\r')
SENT:b't00121122\r'
RECEIVED:bytearray(b'z\r')
RECEIVED:bytearray(b't00121122\r')
ID: 1 DLC: 2 1122
RECEIVED:bytearray(b'z\r')
SENT:b't00121122\r'
RECEIVED:bytearray(b't00121122\r')
ID: 1 DLC: 2 1122
SENT:b't00121122\r'
RECEIVED:bytearray(b'z\r')
RECEIVED:bytearray(b't00121122\r')
ID: 1 DLC: 2 1122
SENT:b't00121122\r'
RECEIVED:bytearray(b'z\r')
RECEIVED:bytearray(b't00121122\r')
ID: 1 DLC: 2 1122
```
what indicates, IMHO, proper operation.

Changing `Notifier` timeout value for any finite value, causes the same problem, but with `None` timeout, I'm not able `stop()` `Notifier` in my target app.

I have not any idea, what goes bad with finite timeout. Have you any ideas, how it can be fixed?

Beitragsleitfaden

Beitragsleitfaden öffnen

Bewertung

Dieses Issue wurde noch nicht bewertet.

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.