From 400531ab2f0959d50a87e45be281bcf9e8e534f3 Mon Sep 17 00:00:00 2001 From: Damien KAYSER Date: Wed, 21 Sep 2022 10:21:58 +0200 Subject: [PATCH 01/11] - integrate handling of Linux based event using select for pcan interface --- can/interfaces/pcan/basic.py | 5 ++- can/interfaces/pcan/pcan.py | 86 ++++++++++++++++++++++++++---------- 2 files changed, 65 insertions(+), 26 deletions(-) diff --git a/can/interfaces/pcan/basic.py b/can/interfaces/pcan/basic.py index 743fb55ee..e7bcf4685 100644 --- a/can/interfaces/pcan/basic.py +++ b/can/interfaces/pcan/basic.py @@ -21,9 +21,10 @@ import logging -if platform.system() == "Windows": - import winreg +PLATFORM = platform.system() +if PLATFORM == "Windows": + import winreg logger = logging.getLogger("can.pcan") diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index cd0349c99..2a65a3c8a 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -1,7 +1,6 @@ """ Enable basic CAN over a PCAN USB device. """ - import logging import time from datetime import datetime @@ -18,6 +17,7 @@ from .basic import ( + PLATFORM, PCAN_BITRATES, PCAN_FD_PARAMETER_LIST, PCAN_CHANNEL_NAMES, @@ -64,7 +64,8 @@ log = logging.getLogger("can.pcan") MIN_PCAN_API_VERSION = version.parse("4.2.0") - +IS_WINDOWS = PLATFORM == "Windows" +IS_LINUX = PLATFORM == "Linux" try: # use the "uptime" library if available @@ -82,24 +83,35 @@ ) boottimeEpoch = 0 -try: - # Try builtin Python 3 Windows API - from _overlapped import CreateEvent - from _winapi import WaitForSingleObject, WAIT_OBJECT_0, INFINITE - - HAS_EVENTS = True -except ImportError: +if IS_WINDOWS: try: - # Try pywin32 package - from win32event import CreateEvent - from win32event import WaitForSingleObject, WAIT_OBJECT_0, INFINITE + # Try builtin Python 3 Windows API + from _overlapped import CreateEvent + from _winapi import WaitForSingleObject, WAIT_OBJECT_0, INFINITE HAS_EVENTS = True except ImportError: - # Use polling instead + try: + # Try pywin32 package + from win32event import CreateEvent + from win32event import WaitForSingleObject, WAIT_OBJECT_0, INFINITE + + HAS_EVENTS = True + except ImportError: + # Use polling instead + HAS_EVENTS = False +elif IS_LINUX: + try: + import errno + import os + import select + + HAS_EVENTS = True + except Exception: HAS_EVENTS = False + class PcanBus(BusABC): def __init__( self, @@ -290,15 +302,20 @@ def __init__( raise PcanCanInitializationError(self._get_formatted_error(result)) if HAS_EVENTS: - self._recv_event = CreateEvent(None, 0, 0, None) - result = self.m_objPCANBasic.SetValue( - self.m_PcanHandle, PCAN_RECEIVE_EVENT, self._recv_event - ) + if IS_WINDOWS: + self._recv_event = CreateEvent(None, 0, 0, None) + result = self.m_objPCANBasic.SetValue( + self.m_PcanHandle, PCAN_RECEIVE_EVENT, self._recv_event + ) + elif IS_LINUX: + result, self._recv_event = self.m_objPCANBasic.GetValue(self.m_PcanHandle, PCAN_RECEIVE_EVENT) + if result != PCAN_ERROR_OK: raise PcanCanInitializationError(self._get_formatted_error(result)) super().__init__(channel=channel, state=state, bitrate=bitrate, *args, **kwargs) + def _find_channel_by_dev_id(self, device_id): """ Iterate over all possible channels to find a channel that matches the device @@ -437,11 +454,26 @@ def set_device_number(self, device_number): return False return True + def _read_message(self): + """Read a message using Basic API. + + :return: a tuple containing the current CAN status, the received + message and the timestamp + :rtype: tuple + """ + if self.fd: + return self.m_objPCANBasic.ReadFD(self.m_PcanHandle) + + return self.m_objPCANBasic.Read(self.m_PcanHandle) + def _recv_internal(self, timeout): - if HAS_EVENTS: + if HAS_EVENTS and IS_WINDOWS: # We will utilize events for the timeout handling timeout_ms = int(timeout * 1000) if timeout is not None else INFINITE + elif HAS_EVENTS and IS_LINUX: + # We will utilize events for the timeout handling + timeout_s = timeout if timeout != None else None elif timeout is not None: # Calculate max time end_time = time.perf_counter() + timeout @@ -450,16 +482,19 @@ def _recv_internal(self, timeout): result = None while result is None: - if self.fd: - result = self.m_objPCANBasic.ReadFD(self.m_PcanHandle) - else: - result = self.m_objPCANBasic.Read(self.m_PcanHandle) + + result = self._read_message() + if result[0] == PCAN_ERROR_QRCVEMPTY: - if HAS_EVENTS: - result = None + if HAS_EVENTS and IS_WINDOWS: val = WaitForSingleObject(self._recv_event, timeout_ms) if val != WAIT_OBJECT_0: return None, False + elif HAS_EVENTS and IS_LINUX: + recv, _, _ = select.select([self._recv_event], [], [], timeout_s) + if self._recv_event not in recv: + return None, False + result = self._read_message() elif timeout is not None and time.perf_counter() >= end_time: return None, False else: @@ -593,6 +628,9 @@ def flash(self, flash): def shutdown(self): super().shutdown() + if HAS_EVENTS and IS_LINUX: + self.m_objPCANBasic.SetValue(self.m_PcanHandle, PCAN_RECEIVE_EVENT, 0) + self.m_objPCANBasic.Uninitialize(self.m_PcanHandle) @property From 16ec2bfa55d9fe240dfaeb1da58d7f505bf22220 Mon Sep 17 00:00:00 2001 From: Damien KAYSER Date: Wed, 12 Oct 2022 11:04:08 +0200 Subject: [PATCH 02/11] - adapt pcan unit tests regarding PCAN_RECEIVE_EVENT GetValue call --- test/test_pcan.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/test_pcan.py b/test/test_pcan.py index 0a680fea0..fed80bb04 100644 --- a/test/test_pcan.py +++ b/test/test_pcan.py @@ -29,7 +29,6 @@ def setUp(self) -> None: self.mock_pcan.SetValue = Mock(return_value=PCAN_ERROR_OK) self.mock_pcan.GetValue = self._mockGetValue self.PCAN_API_VERSION_SIM = "4.2" - self.bus = None def tearDown(self) -> None: @@ -44,6 +43,8 @@ def _mockGetValue(self, channel, parameter): """ if parameter == PCAN_API_VERSION: return PCAN_ERROR_OK, self.PCAN_API_VERSION_SIM.encode("ascii") + elif parameter == PCAN_RECEIVE_EVENT: + return PCAN_ERROR_OK, int.from_bytes(PCAN_RECEIVE_EVENT, "big") raise NotImplementedError( f"No mock return value specified for parameter {parameter}" ) From 8f20849e8f8c8072ba2d4dc526096500a2f4de89 Mon Sep 17 00:00:00 2001 From: Damien KAYSER Date: Tue, 18 Oct 2022 14:17:46 +0200 Subject: [PATCH 03/11] - add the case HAS_EVENTS = FALSE whne no special event basic mechanism is importes --- can/interfaces/pcan/pcan.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index 2a65a3c8a..57de050a5 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -109,7 +109,8 @@ HAS_EVENTS = True except Exception: HAS_EVENTS = False - +else: + HAS_EVENTS = False class PcanBus(BusABC): From ac09a7d27c5d3534a91245ecac051e3d4a477b07 Mon Sep 17 00:00:00 2001 From: Damien KAYSER Date: Tue, 18 Oct 2022 15:06:58 +0200 Subject: [PATCH 04/11] - force select mock for test_recv_no_message --- test/test_pcan.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_pcan.py b/test/test_pcan.py index fed80bb04..d715d6fac 100644 --- a/test/test_pcan.py +++ b/test/test_pcan.py @@ -206,6 +206,7 @@ def test_recv_fd(self): @pytest.mark.timeout(3.0) def test_recv_no_message(self): + mock.patch("select.select", return_value=([],[],[])) self.mock_pcan.Read = Mock(return_value=(PCAN_ERROR_QRCVEMPTY, None, None)) self.bus = can.Bus(bustype="pcan") self.assertEqual(self.bus.recv(timeout=0.5), None) From 43ea0e18d5a243403be3d3570632f2e72e0fb80e Mon Sep 17 00:00:00 2001 From: Damien KAYSER Date: Tue, 25 Oct 2022 10:34:55 +0200 Subject: [PATCH 05/11] - just for testing : see what is going wrong with CI testing and my setup --- can/interfaces/pcan/pcan.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index 57de050a5..5d525d550 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -493,9 +493,13 @@ def _recv_internal(self, timeout): return None, False elif HAS_EVENTS and IS_LINUX: recv, _, _ = select.select([self._recv_event], [], [], timeout_s) + log.error(recv) + log.error(IS_LINUX) if self._recv_event not in recv: + log.error("Nothing received") return None, False result = self._read_message() + log.error(f"oh recived something {result}") elif timeout is not None and time.perf_counter() >= end_time: return None, False else: From 4e73c92f77e8ec378e21a81f72b8021eeabfb899 Mon Sep 17 00:00:00 2001 From: Damien KAYSER Date: Wed, 2 Nov 2022 13:50:20 +0100 Subject: [PATCH 06/11] - correct patch on pcan test test_recv_no_message - run black --- can/interfaces/pcan/pcan.py | 5 +++-- test/test_pcan.py | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index 5d525d550..84d94186f 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -309,14 +309,15 @@ def __init__( self.m_PcanHandle, PCAN_RECEIVE_EVENT, self._recv_event ) elif IS_LINUX: - result, self._recv_event = self.m_objPCANBasic.GetValue(self.m_PcanHandle, PCAN_RECEIVE_EVENT) + result, self._recv_event = self.m_objPCANBasic.GetValue( + self.m_PcanHandle, PCAN_RECEIVE_EVENT + ) if result != PCAN_ERROR_OK: raise PcanCanInitializationError(self._get_formatted_error(result)) super().__init__(channel=channel, state=state, bitrate=bitrate, *args, **kwargs) - def _find_channel_by_dev_id(self, device_id): """ Iterate over all possible channels to find a channel that matches the device diff --git a/test/test_pcan.py b/test/test_pcan.py index d715d6fac..87f693b08 100644 --- a/test/test_pcan.py +++ b/test/test_pcan.py @@ -5,7 +5,8 @@ import ctypes import unittest from unittest import mock -from unittest.mock import Mock +from unittest.mock import Mock, patch + import pytest from parameterized import parameterized @@ -205,8 +206,8 @@ def test_recv_fd(self): self.assertEqual(recv_msg.timestamp, 0) @pytest.mark.timeout(3.0) - def test_recv_no_message(self): - mock.patch("select.select", return_value=([],[],[])) + @patch("select.select", return_value=([],[],[])) + def test_recv_no_message(self, mock_select): self.mock_pcan.Read = Mock(return_value=(PCAN_ERROR_QRCVEMPTY, None, None)) self.bus = can.Bus(bustype="pcan") self.assertEqual(self.bus.recv(timeout=0.5), None) From fe3de2c3206f196e93ab5d03ecab2132fccc4a96 Mon Sep 17 00:00:00 2001 From: Damien KAYSER Date: Wed, 2 Nov 2022 14:20:01 +0100 Subject: [PATCH 07/11] - remove debug log --- can/interfaces/pcan/pcan.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index 84d94186f..01f9e1251 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -494,13 +494,9 @@ def _recv_internal(self, timeout): return None, False elif HAS_EVENTS and IS_LINUX: recv, _, _ = select.select([self._recv_event], [], [], timeout_s) - log.error(recv) - log.error(IS_LINUX) if self._recv_event not in recv: - log.error("Nothing received") return None, False result = self._read_message() - log.error(f"oh recived something {result}") elif timeout is not None and time.perf_counter() >= end_time: return None, False else: From 890eee374ec602d2681a41ef9eb2c086e50c368b Mon Sep 17 00:00:00 2001 From: Damien KAYSER Date: Wed, 9 Nov 2022 11:29:43 +0100 Subject: [PATCH 08/11] -just reformat test_pcan --- test/test_pcan.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_pcan.py b/test/test_pcan.py index 87f693b08..9333f1526 100644 --- a/test/test_pcan.py +++ b/test/test_pcan.py @@ -206,7 +206,7 @@ def test_recv_fd(self): self.assertEqual(recv_msg.timestamp, 0) @pytest.mark.timeout(3.0) - @patch("select.select", return_value=([],[],[])) + @patch("select.select", return_value=([], [], [])) def test_recv_no_message(self, mock_select): self.mock_pcan.Read = Mock(return_value=(PCAN_ERROR_QRCVEMPTY, None, None)) self.bus = can.Bus(bustype="pcan") From f54973f76115dbea2a870d467bca59db408b26bc Mon Sep 17 00:00:00 2001 From: Damien Date: Mon, 9 Jan 2023 11:34:07 +0100 Subject: [PATCH 09/11] - move global variable IS_WINDOW and IS_LINUX from pcan to basic module --- can/interfaces/pcan/basic.py | 4 +++- can/interfaces/pcan/pcan.py | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/can/interfaces/pcan/basic.py b/can/interfaces/pcan/basic.py index e7bcf4685..94f4a3910 100644 --- a/can/interfaces/pcan/basic.py +++ b/can/interfaces/pcan/basic.py @@ -22,8 +22,10 @@ import logging PLATFORM = platform.system() +IS_WINDOWS = PLATFORM == "Windows" +IS_LINUX = PLATFORM == "Linux" -if PLATFORM == "Windows": +if IS_WINDOWS: import winreg logger = logging.getLogger("can.pcan") diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index 01f9e1251..ea41ea09d 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -47,6 +47,8 @@ PCAN_LISTEN_ONLY, PCAN_PARAMETER_OFF, TPCANHandle, + IS_LINUX, + IS_WINDOWS, PCAN_PCIBUS1, PCAN_USBBUS1, PCAN_PCCBUS1, @@ -64,8 +66,6 @@ log = logging.getLogger("can.pcan") MIN_PCAN_API_VERSION = version.parse("4.2.0") -IS_WINDOWS = PLATFORM == "Windows" -IS_LINUX = PLATFORM == "Linux" try: # use the "uptime" library if available From d9c5a36d512ba5470ea9c753a03d28b6cbbbaf23 Mon Sep 17 00:00:00 2001 From: Damien Date: Mon, 16 Jan 2023 13:57:22 +0100 Subject: [PATCH 10/11] - remove redundant comment in pcan _recv_internal --- can/interfaces/pcan/pcan.py | 1 - 1 file changed, 1 deletion(-) diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index ea41ea09d..83f913944 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -474,7 +474,6 @@ def _recv_internal(self, timeout): # We will utilize events for the timeout handling timeout_ms = int(timeout * 1000) if timeout is not None else INFINITE elif HAS_EVENTS and IS_LINUX: - # We will utilize events for the timeout handling timeout_s = timeout if timeout != None else None elif timeout is not None: # Calculate max time From ef09567d0d74b944df4b675cebddc3485697e6b0 Mon Sep 17 00:00:00 2001 From: zariiii9003 <52598363+zariiii9003@users.noreply.github.com> Date: Sun, 22 Jan 2023 17:23:10 +0100 Subject: [PATCH 11/11] refactor _recv_internal --- can/interfaces/pcan/pcan.py | 169 +++++++++++++++++------------------- 1 file changed, 78 insertions(+), 91 deletions(-) diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index 83f913944..492e2cb2b 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -6,7 +6,7 @@ from datetime import datetime import platform -from typing import Optional +from typing import Optional, Tuple from packaging import version @@ -17,7 +17,6 @@ from .basic import ( - PLATFORM, PCAN_BITRATES, PCAN_FD_PARAMETER_LIST, PCAN_CHANNEL_NAMES, @@ -83,6 +82,8 @@ ) boottimeEpoch = 0 +HAS_EVENTS = False + if IS_WINDOWS: try: # Try builtin Python 3 Windows API @@ -91,15 +92,8 @@ HAS_EVENTS = True except ImportError: - try: - # Try pywin32 package - from win32event import CreateEvent - from win32event import WaitForSingleObject, WAIT_OBJECT_0, INFINITE - - HAS_EVENTS = True - except ImportError: - # Use polling instead - HAS_EVENTS = False + pass + elif IS_LINUX: try: import errno @@ -108,9 +102,7 @@ HAS_EVENTS = True except Exception: - HAS_EVENTS = False -else: - HAS_EVENTS = False + pass class PcanBus(BusABC): @@ -456,101 +448,96 @@ def set_device_number(self, device_number): return False return True - def _read_message(self): - """Read a message using Basic API. + def _recv_internal( + self, timeout: Optional[float] + ) -> Tuple[Optional[Message], bool]: + end_time = time.time() + timeout if timeout is not None else None - :return: a tuple containing the current CAN status, the received - message and the timestamp - :rtype: tuple - """ - if self.fd: - return self.m_objPCANBasic.ReadFD(self.m_PcanHandle) - - return self.m_objPCANBasic.Read(self.m_PcanHandle) - - def _recv_internal(self, timeout): - - if HAS_EVENTS and IS_WINDOWS: - # We will utilize events for the timeout handling - timeout_ms = int(timeout * 1000) if timeout is not None else INFINITE - elif HAS_EVENTS and IS_LINUX: - timeout_s = timeout if timeout != None else None - elif timeout is not None: - # Calculate max time - end_time = time.perf_counter() + timeout - - # log.debug("Trying to read a msg") - - result = None - while result is None: - - result = self._read_message() - - if result[0] == PCAN_ERROR_QRCVEMPTY: - if HAS_EVENTS and IS_WINDOWS: - val = WaitForSingleObject(self._recv_event, timeout_ms) - if val != WAIT_OBJECT_0: - return None, False - elif HAS_EVENTS and IS_LINUX: - recv, _, _ = select.select([self._recv_event], [], [], timeout_s) - if self._recv_event not in recv: - return None, False - result = self._read_message() - elif timeout is not None and time.perf_counter() >= end_time: - return None, False + while True: + if self.fd: + result, pcan_msg, pcan_timestamp = self.m_objPCANBasic.ReadFD( + self.m_PcanHandle + ) + else: + result, pcan_msg, pcan_timestamp = self.m_objPCANBasic.Read( + self.m_PcanHandle + ) + + if result == PCAN_ERROR_OK: + # message received + break + + if result == PCAN_ERROR_QRCVEMPTY: + # receive queue is empty, wait or return on timeout + + if end_time is None: + time_left: Optional[float] = None + timed_out = False else: - result = None + time_left = max(0.0, end_time - time.time()) + timed_out = time_left == 0.0 + + if timed_out: + return None, False + + if not HAS_EVENTS: + # polling mode time.sleep(0.001) - elif result[0] & (PCAN_ERROR_BUSLIGHT | PCAN_ERROR_BUSHEAVY): - log.warning(self._get_formatted_error(result[0])) - return None, False - elif result[0] != PCAN_ERROR_OK: - raise PcanCanOperationError(self._get_formatted_error(result[0])) - - theMsg = result[1] - itsTimeStamp = result[2] - - # log.debug("Received a message") - - is_extended_id = ( - theMsg.MSGTYPE & PCAN_MESSAGE_EXTENDED.value - ) == PCAN_MESSAGE_EXTENDED.value - is_remote_frame = ( - theMsg.MSGTYPE & PCAN_MESSAGE_RTR.value - ) == PCAN_MESSAGE_RTR.value - is_fd = (theMsg.MSGTYPE & PCAN_MESSAGE_FD.value) == PCAN_MESSAGE_FD.value - bitrate_switch = ( - theMsg.MSGTYPE & PCAN_MESSAGE_BRS.value - ) == PCAN_MESSAGE_BRS.value - error_state_indicator = ( - theMsg.MSGTYPE & PCAN_MESSAGE_ESI.value - ) == PCAN_MESSAGE_ESI.value - is_error_frame = ( - theMsg.MSGTYPE & PCAN_MESSAGE_ERRFRAME.value - ) == PCAN_MESSAGE_ERRFRAME.value + continue + + if IS_WINDOWS: + # Windows with event + if time_left is None: + time_left_ms = INFINITE + else: + time_left_ms = int(time_left * 1000) + _ret = WaitForSingleObject(self._recv_event, time_left_ms) + if _ret == WAIT_OBJECT_0: + continue + + elif IS_LINUX: + # Linux with event + recv, _, _ = select.select([self._recv_event], [], [], time_left) + if self._recv_event in recv: + continue + + elif result & (PCAN_ERROR_BUSLIGHT | PCAN_ERROR_BUSHEAVY): + log.warning(self._get_formatted_error(result)) + + else: + raise PcanCanOperationError(self._get_formatted_error(result)) + + return None, False + + is_extended_id = bool(pcan_msg.MSGTYPE & PCAN_MESSAGE_EXTENDED.value) + is_remote_frame = bool(pcan_msg.MSGTYPE & PCAN_MESSAGE_RTR.value) + is_fd = bool(pcan_msg.MSGTYPE & PCAN_MESSAGE_FD.value) + bitrate_switch = bool(pcan_msg.MSGTYPE & PCAN_MESSAGE_BRS.value) + error_state_indicator = bool(pcan_msg.MSGTYPE & PCAN_MESSAGE_ESI.value) + is_error_frame = bool(pcan_msg.MSGTYPE & PCAN_MESSAGE_ERRFRAME.value) if self.fd: - dlc = dlc2len(theMsg.DLC) - timestamp = boottimeEpoch + (itsTimeStamp.value / (1000.0 * 1000.0)) + dlc = dlc2len(pcan_msg.DLC) + timestamp = boottimeEpoch + (pcan_timestamp.value / (1000.0 * 1000.0)) else: - dlc = theMsg.LEN + dlc = pcan_msg.LEN timestamp = boottimeEpoch + ( ( - itsTimeStamp.micros - + 1000 * itsTimeStamp.millis - + 0x100000000 * 1000 * itsTimeStamp.millis_overflow + pcan_timestamp.micros + + 1000 * pcan_timestamp.millis + + 0x100000000 * 1000 * pcan_timestamp.millis_overflow ) / (1000.0 * 1000.0) ) rx_msg = Message( timestamp=timestamp, - arbitration_id=theMsg.ID, + arbitration_id=pcan_msg.ID, is_extended_id=is_extended_id, is_remote_frame=is_remote_frame, is_error_frame=is_error_frame, dlc=dlc, - data=theMsg.DATA[:dlc], + data=pcan_msg.DATA[:dlc], is_fd=is_fd, bitrate_switch=bitrate_switch, error_state_indicator=error_state_indicator,