# Buggy code
def _recv_internal(self, timeout):
    if timeout is not None:
        self.serialPortOrig.timeout = timeout

    canId = None
    remote = False
    extended = False
    frame = []
    readStr = self.serialPort.readline()
    if not readStr:
        return None, False
    else:
        if readStr[0] == "T":
            # extended frame
            canId = int(readStr[1:9], 16)
            dlc = int(readStr[9])
            extended = True
            for i in range(0, dlc):
                frame.append(int(readStr[10 + i * 2 : 12 + i * 2], 16))
        elif readStr[0] == "t":
            # normal frame
            canId = int(readStr[1:4], 16)
            dlc = int(readStr[4])
            for i in range(0, dlc):
                frame.append(int(readStr[5 + i * 2 : 7 + i * 2], 16))
        elif readStr[0] == "r":
            # remote frame
            canId = int(readStr[1:4], 16)
            remote = True
        elif readStr[0] == "R":
            # remote extended frame
            canId = int(readStr[1:9], 16)
            extended = True
            remote = True

        if canId is not None:
            msg = Message(
                arbitration_id=canId,
                extended_id=extended,
                timestamp=time.time(),  # Better than nothing...
                is_remote_frame=remote,
                dlc=dlc,
                data=frame,
            )
            return msg, False
        else:
            return None, False


# Traceback (AttributeError)
DEBUG:can:loaded can config: {'interface': 'slcan', 'channel': '/dev/ttyUSB0@115200'}
Traceback (most recent call last):
File "encoder-test.py", line 19, in <module>
network.connect(channel='/dev/ttyUSB0@115200', bustype='slcan')
File "/usr/local/lib/python3.5/dist-packages/canopen/network.py", line 100, in connect
self.bus = can.interface.Bus(*args, **kwargs)
File "/usr/local/lib/python3.5/dist-packages/can/interface.py", line 120, in __new__
return cls(channel, *args, **config)
File "/usr/local/lib/python3.5/dist-packages/can/interfaces/slcan.py", line 81, in __init__
self.open()
File "/usr/local/lib/python3.5/dist-packages/can/interfaces/slcan.py", line 93, in open
self.write('O')
File "/usr/local/lib/python3.5/dist-packages/can/interfaces/slcan.py", line 89, in write
self.serialPort.write(string.decode())
AttributeError: 'str' object has no attribute 'decode'

# Fixed code
def _recv_internal(self, timeout):
    if timeout is not None:
        self.serialPortOrig.timeout = timeout

    canId = None
    remote = False
    extended = False
    frame = []

    readStr = self.serialPortOrig.read_until(b"\r")

    if not readStr:
        return None, False
    else:
        readStr = readStr.decode()
        if readStr[0] == "T":
            # extended frame
            canId = int(readStr[1:9], 16)
            dlc = int(readStr[9])
            extended = True
            for i in range(0, dlc):
                frame.append(int(readStr[10 + i * 2 : 12 + i * 2], 16))
        elif readStr[0] == "t":
            # normal frame
            canId = int(readStr[1:4], 16)
            dlc = int(readStr[4])
            for i in range(0, dlc):
                frame.append(int(readStr[5 + i * 2 : 7 + i * 2], 16))
        elif readStr[0] == "r":
            # remote frame
            canId = int(readStr[1:4], 16)
            remote = True
        elif readStr[0] == "R":
            # remote extended frame
            canId = int(readStr[1:9], 16)
            extended = True
            remote = True

        if canId is not None:
            msg = Message(
                arbitration_id=canId,
                extended_id=extended,
                timestamp=time.time(),  # Better than nothing...
                is_remote_frame=remote,
                dlc=dlc,
                data=frame,
            )
            return msg, False
        else:
            return None, False