hardbyte / hardbyte/python-can

Timeout for slcan Notifier breaks communication

Open
#727 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
1.6k
Forks
697
PR merge metrics
No merged PRs in 30d

Description

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?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.