hardbyte / hardbyte/python-can

Timeout for slcan Notifier breaks communication

Ouverte
#727 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub
Langage dominant
Python
Étoiles
1.6k
Forks
697
Métriques de merge des PR
Aucune PR mergée en 30 j

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?

Guide de contribution

Ouvrir le guide de contribution

Évaluation

Cette issue n'a pas encore été évaluée.

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.