From cc51bb522ae3125e37edf4c40bb2f5b288730f4a Mon Sep 17 00:00:00 2001 From: MattWoodhead Date: Sat, 3 Jun 2023 09:18:03 +0100 Subject: [PATCH 01/15] initial modification to force VCINPL2 usage --- can/interfaces/ixxat/canlib.py | 81 ++++++++++++++++--------------- can/interfaces/ixxat/constants.py | 20 ++++++-- 2 files changed, 57 insertions(+), 44 deletions(-) diff --git a/can/interfaces/ixxat/canlib.py b/can/interfaces/ixxat/canlib.py index 8c07508e4..adead5284 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/can/interfaces/ixxat/canlib.py @@ -94,46 +94,47 @@ def __init__( Secondary sample point (data). Only takes effect with fd and bitrate switch enabled. """ - if fd: - if rx_fifo_size is None: - rx_fifo_size = 1024 - if tx_fifo_size is None: - tx_fifo_size = 128 - self.bus = vcinpl2.IXXATBus( - channel=channel, - can_filters=can_filters, - receive_own_messages=receive_own_messages, - unique_hardware_id=unique_hardware_id, - extended=extended, - rx_fifo_size=rx_fifo_size, - tx_fifo_size=tx_fifo_size, - bitrate=bitrate, - data_bitrate=data_bitrate, - sjw_abr=sjw_abr, - tseg1_abr=tseg1_abr, - tseg2_abr=tseg2_abr, - sjw_dbr=sjw_dbr, - tseg1_dbr=tseg1_dbr, - tseg2_dbr=tseg2_dbr, - ssp_dbr=ssp_dbr, - **kwargs, - ) - else: - if rx_fifo_size is None: - rx_fifo_size = 16 - if tx_fifo_size is None: - tx_fifo_size = 16 - self.bus = vcinpl.IXXATBus( - channel=channel, - can_filters=can_filters, - receive_own_messages=receive_own_messages, - unique_hardware_id=unique_hardware_id, - extended=extended, - rx_fifo_size=rx_fifo_size, - tx_fifo_size=tx_fifo_size, - bitrate=bitrate, - **kwargs, - ) + # if fd: + if rx_fifo_size is None: + rx_fifo_size = 1024 + if tx_fifo_size is None: + tx_fifo_size = 128 + self.bus = vcinpl2.IXXATBus( + channel=channel, + can_filters=can_filters, + receive_own_messages=receive_own_messages, + unique_hardware_id=unique_hardware_id, + extended=extended, + rx_fifo_size=rx_fifo_size, + tx_fifo_size=tx_fifo_size, + bitrate=bitrate, + data_bitrate=data_bitrate, + sjw_abr=sjw_abr, + tseg1_abr=tseg1_abr, + tseg2_abr=tseg2_abr, + sjw_dbr=sjw_dbr, + tseg1_dbr=tseg1_dbr, + tseg2_dbr=tseg2_dbr, + ssp_dbr=ssp_dbr, + fd=fd, + **kwargs, + ) + # else: + # if rx_fifo_size is None: + # rx_fifo_size = 16 + # if tx_fifo_size is None: + # tx_fifo_size = 16 + # self.bus = vcinpl.IXXATBus( + # channel=channel, + # can_filters=can_filters, + # receive_own_messages=receive_own_messages, + # unique_hardware_id=unique_hardware_id, + # extended=extended, + # rx_fifo_size=rx_fifo_size, + # tx_fifo_size=tx_fifo_size, + # bitrate=bitrate, + # **kwargs, + # ) super().__init__(channel=channel, **kwargs) self._can_protocol = self.bus.protocol diff --git a/can/interfaces/ixxat/constants.py b/can/interfaces/ixxat/constants.py index 3bc1aa42e..82a2f9bfa 100644 --- a/can/interfaces/ixxat/constants.py +++ b/can/interfaces/ixxat/constants.py @@ -123,10 +123,10 @@ CAN_OPMODE_AUTOBAUD = 0x20 # automatic bit rate detection # Extended operating modes -CAN_EXMODE_DISABLED = 0x00 -CAN_EXMODE_EXTDATALEN = 0x01 -CAN_EXMODE_FASTDATA = 0x02 -CAN_EXMODE_NONISOCANFD = 0x04 +CAN_EXMODE_DISABLED = 0x00 # no extended operation +CAN_EXMODE_EXTDATALEN = 0x01 # extended data length +CAN_EXMODE_FASTDATA = 0x02 # fast data bit rate +CAN_EXMODE_NONISOCANFD = 0x04 # non ISO conform frames # Message types CAN_MSGTYPE_DATA = 0 @@ -160,13 +160,19 @@ CAN_BTMODE_RAW = 0x00000001 # raw mode CAN_BTMODE_TSM = 0x00000002 # triple sampling mode +# Filter selection +CAN_FILTER_STD = 1 # select standard filter (11-bit) +CAN_FILTER_EXT = 2 # select extended filter (29-bit) +# Filter modw CAN_FILTER_VOID = 0x00 # invalid or unknown filter mode (do not use for initialization) CAN_FILTER_LOCK = 0x01 # lock filter (inhibit all IDs) CAN_FILTER_PASS = 0x02 # bypass filter (pass all IDs) CAN_FILTER_INCL = 0x03 # inclusive filtering (pass registered IDs) CAN_FILTER_EXCL = 0x04 # exclusive filtering (inhibit registered IDs) +# additional filter mode flag for ICanChannel2 initialization +CAN_FILTER_SRRA = 0x80 # pass self-rec messages from all channels # message information flags (used by ) CAN_MSGFLAGS_DLC = 0x0F # [bit 0] data length code @@ -214,6 +220,12 @@ CAN_BITRATE_PRESETS = { + 50000: structures.CANBTP( + dwMode=0, dwBPS=50000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 + ), # SP = 80,0% + 125000: structures.CANBTP( + dwMode=0, dwBPS=125000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 + ), # SP = 80,0% 250000: structures.CANBTP( dwMode=0, dwBPS=250000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 ), # SP = 80,0% From 5149a651eb422a931dd82536d79cbb091dcd1e6c Mon Sep 17 00:00:00 2001 From: MattWoodhead Date: Sat, 3 Jun 2023 09:52:53 +0100 Subject: [PATCH 02/15] Add FD switch. Add detect configs --- can/interfaces/ixxat/canlib.py | 7 +- can/interfaces/ixxat/canlib_vcinpl2.py | 241 ++++++++++++------------- 2 files changed, 117 insertions(+), 131 deletions(-) diff --git a/can/interfaces/ixxat/canlib.py b/can/interfaces/ixxat/canlib.py index adead5284..372874c20 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/can/interfaces/ixxat/canlib.py @@ -1,4 +1,4 @@ -from typing import Callable, Optional, Sequence, Union +from typing import Callable, List, Optional, Sequence, Union import can.interfaces.ixxat.canlib_vcinpl as vcinpl import can.interfaces.ixxat.canlib_vcinpl2 as vcinpl2 @@ -8,6 +8,7 @@ CyclicSendTaskABC, Message, ) +from can.typechecking import AutoDetectedConfig class IXXATBus(BusABC): @@ -171,3 +172,7 @@ def state(self) -> BusState: Return the current state of the hardware """ return self.bus.state + + @staticmethod + def _detect_available_configs() -> List[AutoDetectedConfig]: + return vcinpl2._detect_available_configs() diff --git a/can/interfaces/ixxat/canlib_vcinpl2.py b/can/interfaces/ixxat/canlib_vcinpl2.py index b10ac1b94..07e94d397 100644 --- a/can/interfaces/ixxat/canlib_vcinpl2.py +++ b/can/interfaces/ixxat/canlib_vcinpl2.py @@ -15,7 +15,7 @@ import sys import time import warnings -from typing import Callable, Optional, Sequence, Tuple, Union +from typing import Callable, List, Optional, Sequence, Tuple, Union from can import ( BusABC, @@ -28,6 +28,7 @@ from can.ctypesutil import HANDLE, PHANDLE, CLibrary from can.ctypesutil import HRESULT as ctypes_HRESULT from can.exceptions import CanInitializationError, CanInterfaceNotImplementedError +from can.typechecking import AutoDetectedConfig from can.util import deprecated_args_alias, dlc2len, len2dlc from . import constants, structures @@ -61,9 +62,7 @@ log.warning("IXXAT VCI library does not work on %s platform", sys.platform) -def __vciFormatErrorExtended( - library_instance: CLibrary, function: Callable, vret: int, args: Tuple -): +def __vciFormatErrorExtended(library_instance: CLibrary, function: Callable, vret: int, args: Tuple): """Format a VCI error and attach failed function, decoded HRESULT and arguments :param CLibrary library_instance: Mapped instance of IXXAT vcinpl library @@ -77,9 +76,7 @@ def __vciFormatErrorExtended( Formatted string """ # TODO: make sure we don't generate another exception - return "{} - arguments were {}".format( - __vciFormatError(library_instance, function, vret), args - ) + return "{} - arguments were {}".format(__vciFormatError(library_instance, function, vret), args) def __vciFormatError(library_instance: CLibrary, function: Callable, vret: int): @@ -96,12 +93,10 @@ def __vciFormatError(library_instance: CLibrary, function: Callable, vret: int): buf = ctypes.create_string_buffer(constants.VCI_MAX_ERRSTRLEN) ctypes.memset(buf, 0, constants.VCI_MAX_ERRSTRLEN) library_instance.vciFormatError(vret, buf, constants.VCI_MAX_ERRSTRLEN) - return "function {} failed ({})".format( - function._name, buf.value.decode("utf-8", "replace") - ) + return "function {} failed ({})".format(function._name, buf.value.decode("utf-8", "replace")) -def __check_status(result, function, args): +def __check_status(result: int, function: Callable, args: Tuple): """ Check the result of a vcinpl function call and raise appropriate exception in case of an error. Used as errcheck function when mapping C functions @@ -140,13 +135,9 @@ def __check_status(result, function, args): # void VCIAPI vciFormatError (HRESULT hrError, PCHAR pszText, UINT32 dwsize); try: - _canlib.map_symbol( - "vciFormatError", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32) - ) + _canlib.map_symbol("vciFormatError", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32)) except ImportError: - _canlib.map_symbol( - "vciFormatErrorA", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32) - ) + _canlib.map_symbol("vciFormatErrorA", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32)) _canlib.vciFormatError = _canlib.vciFormatErrorA # Hack to have vciFormatError as a free function vciFormatError = functools.partial(__vciFormatError, _canlib) @@ -164,9 +155,7 @@ def __check_status(result, function, args): ) # HRESULT VCIAPI vciDeviceOpen( IN REFVCIID rVciid, OUT PHANDLE phDevice ); - _canlib.map_symbol( - "vciDeviceOpen", hresult_type, (structures.PVCIID, PHANDLE), __check_status - ) + _canlib.map_symbol("vciDeviceOpen", hresult_type, (structures.PVCIID, PHANDLE), __check_status) # HRESULT vciDeviceClose( HANDLE hDevice ) _canlib.map_symbol("vciDeviceClose", hresult_type, (HANDLE,), __check_status) @@ -200,9 +189,7 @@ def __check_status(result, function, args): __check_status, ) # EXTERN_C HRESULT VCIAPI canChannelActivate( IN HANDLE hCanChn, IN BOOL fEnable ); - _canlib.map_symbol( - "canChannelActivate", hresult_type, (HANDLE, ctypes.c_long), __check_status - ) + _canlib.map_symbol("canChannelActivate", hresult_type, (HANDLE, ctypes.c_long), __check_status) # HRESULT canChannelClose( HANDLE hChannel ) _canlib.map_symbol("canChannelClose", hresult_type, (HANDLE,), __check_status) # EXTERN_C HRESULT VCIAPI canChannelReadMessage( IN HANDLE hCanChn, IN UINT32 dwMsTimeout, OUT PCANMSG2 pCanMsg ); @@ -286,9 +273,7 @@ def __check_status(result, function, args): # EXTERN_C HRESULT VCIAPI canControlReset( IN HANDLE hCanCtl ); _canlib.map_symbol("canControlReset", hresult_type, (HANDLE,), __check_status) # EXTERN_C HRESULT VCIAPI canControlStart( IN HANDLE hCanCtl, IN BOOL fStart ); - _canlib.map_symbol( - "canControlStart", hresult_type, (HANDLE, ctypes.c_long), __check_status - ) + _canlib.map_symbol("canControlStart", hresult_type, (HANDLE, ctypes.c_long), __check_status) # EXTERN_C HRESULT VCIAPI canControlGetStatus( IN HANDLE hCanCtl, OUT PCANLINESTATUS2 pStatus ); _canlib.map_symbol( "canControlGetStatus", @@ -341,9 +326,7 @@ def __check_status(result, function, args): __check_status, ) # EXTERN_C HRESULT canSchedulerActivate ( HANDLE hScheduler, BOOL fEnable ); - _canlib.map_symbol( - "canSchedulerActivate", hresult_type, (HANDLE, ctypes.c_int), __check_status - ) + _canlib.map_symbol("canSchedulerActivate", hresult_type, (HANDLE, ctypes.c_int), __check_status) # EXTERN_C HRESULT canSchedulerAddMessage (HANDLE hScheduler, PCANCYCLICTXMSG2 pMessage, PUINT32 pdwIndex ); _canlib.map_symbol( "canSchedulerAddMessage", @@ -432,6 +415,7 @@ def __init__( receive_own_messages: int = False, unique_hardware_id: Optional[int] = None, extended: bool = True, + fd: bool = False, rx_fifo_size: int = 1024, tx_fifo_size: int = 128, bitrate: int = 500000, @@ -461,6 +445,9 @@ def __init__( :param extended: Default True, enables the capability to use extended IDs. + :param fd: + Default False, enables CAN-FD usage. + :param rx_fifo_size: Receive fifo size (default 1024) @@ -505,9 +492,7 @@ def __init__( # Usually comes as a string from the config file channel = int(channel) - if bitrate not in constants.CAN_BITRATE_PRESETS and ( - tseg1_abr is None or tseg2_abr is None or sjw_abr is None - ): + if bitrate not in constants.CAN_BITRATE_PRESETS and (tseg1_abr is None or tseg2_abr is None or sjw_abr is None): raise ValueError( "To use bitrate {} (that has not predefined preset) is mandatory to use also parameters tseg1_abr, tseg2_abr and swj_abr".format( bitrate @@ -538,7 +523,6 @@ def __init__( self._channel_capabilities = structures.CANCAPABILITIES2() self._message = structures.CANMSG2() self._payload = (ctypes.c_byte * 64)() - self._can_protocol = CanProtocol.CAN_FD # Search for supplied device if unique_hardware_id is None: @@ -548,24 +532,19 @@ def __init__( _canlib.vciEnumDeviceOpen(ctypes.byref(self._device_handle)) while True: try: - _canlib.vciEnumDeviceNext( - self._device_handle, ctypes.byref(self._device_info) - ) - except StopIteration: + _canlib.vciEnumDeviceNext(self._device_handle, ctypes.byref(self._device_info)) + except StopIteration as exc: if unique_hardware_id is None: raise VCIDeviceNotFoundError( "No IXXAT device(s) connected or device(s) in use by other process(es)." - ) + ) from exc else: raise VCIDeviceNotFoundError( - "Unique HW ID {} not connected or not available.".format( - unique_hardware_id - ) - ) + "Unique HW ID {} not connected or not available.".format(unique_hardware_id) + ) from exc else: if (unique_hardware_id is None) or ( - self._device_info.UniqueHardwareId.AsChar - == bytes(unique_hardware_id, "ascii") + self._device_info.UniqueHardwareId.AsChar == bytes(unique_hardware_id, "ascii") ): break else: @@ -580,8 +559,8 @@ def __init__( ctypes.byref(self._device_info.VciObjectId), ctypes.byref(self._device_handle), ) - except Exception as exception: - raise CanInitializationError(f"Could not open device: {exception}") + except Exception as exc: + raise CanInitializationError(f"Could not open device: {exc}") from exc log.info("Using unique HW ID %s", self._device_info.UniqueHardwareId.AsChar) @@ -599,10 +578,8 @@ def __init__( constants.FALSE, ctypes.byref(self._channel_handle), ) - except Exception as exception: - raise CanInitializationError( - f"Could not open and initialize channel: {exception}" - ) + except Exception as exc: + raise CanInitializationError(f"Could not open and initialize channel: {exc}") from exc # Signal TX/RX events when at least one frame has been handled _canlib.canChannelInitialize( @@ -639,51 +616,40 @@ def __init__( pBtpSDR, pBtpFDR, ) - _canlib.canControlOpen( - self._device_handle, channel, ctypes.byref(self._control_handle) - ) + _canlib.canControlOpen(self._device_handle, channel, ctypes.byref(self._control_handle)) - _canlib.canControlGetCaps( - self._control_handle, ctypes.byref(self._channel_capabilities) - ) + _canlib.canControlGetCaps(self._control_handle, ctypes.byref(self._channel_capabilities)) # check capabilities bOpMode = constants.CAN_OPMODE_UNDEFINED - if ( - self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT - ) != 0: - # controller supportes CAN_OPMODE_STANDARD and CAN_OPMODE_EXTENDED at the same time + if (self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT) != 0: + # controller supports CAN_OPMODE_STANDARD and CAN_OPMODE_EXTENDED at the same time bOpMode |= constants.CAN_OPMODE_STANDARD # enable both 11 bits reception if extended: # parameter from configuration bOpMode |= constants.CAN_OPMODE_EXTENDED # enable 29 bits reception - elif ( - self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT - ) != 0: + elif (self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT) != 0: log.warning( "Channel %d capabilities allow either basic or extended IDs, but not both. using %s according to parameter [extended=%s]", channel, "extended" if extended else "basic", "True" if extended else "False", ) - bOpMode |= ( - constants.CAN_OPMODE_EXTENDED - if extended - else constants.CAN_OPMODE_STANDARD - ) + # controller supports either CAN_OPMODE_STANDARD or CAN_OPMODE_EXTENDED, but not both simultaneously + bOpMode |= constants.CAN_OPMODE_EXTENDED if extended else constants.CAN_OPMODE_STANDARD - if ( + if ( # controller supports receiving error frames: self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_ERRFRAME ) != 0: bOpMode |= constants.CAN_OPMODE_ERRFRAME bExMode = constants.CAN_EXMODE_DISABLED - if (self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_EXTDATA) != 0: - bExMode |= constants.CAN_EXMODE_EXTDATALEN - - if ( - self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_FASTDATA - ) != 0: - bExMode |= constants.CAN_EXMODE_FASTDATA + self._can_protocol = CanProtocol.CAN_20 # default to standard CAN protocol + if fd: + if (self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_EXTDATA) != 0: + bExMode |= constants.CAN_EXMODE_EXTDATALEN + if (self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_FASTDATA) != 0: + bExMode |= constants.CAN_EXMODE_FASTDATA + self._can_protocol = CanProtocol.CAN_FD # set bus to CAN FD protocol once FD capability is verified _canlib.canControlInitialize( self._control_handle, @@ -701,10 +667,7 @@ def __init__( # the message in ticks. The resolution of a tick can be calculated from the fields # dwClockFreq and dwTscDivisor of the structure CANCAPABILITIES in accordance with the following formula: # frequency [1/s] = dwClockFreq / dwTscDivisor - self._tick_resolution = ( - self._channel_capabilities.dwTscClkFreq - / self._channel_capabilities.dwTscDivisor - ) + self._tick_resolution = self._channel_capabilities.dwTscClkFreq / self._channel_capabilities.dwTscDivisor # Setup filters before starting the channel if can_filters: @@ -722,9 +685,7 @@ def __init__( code = int(can_filter["can_id"]) mask = int(can_filter["can_mask"]) extended = can_filter.get("extended", False) - _canlib.canControlAddFilterIds( - self._control_handle, 1 if extended else 0, code << 1, mask << 1 - ) + _canlib.canControlAddFilterIds(self._control_handle, 1 if extended else 0, code << 1, mask << 1) log.info("Accepting ID: 0x%X MASK: 0x%X", code, mask) # Start the CAN controller. Messages will be forwarded to the channel @@ -739,9 +700,7 @@ def __init__( # Clear the FIFO by filter them out with low timeout for _ in range(rx_fifo_size): try: - _canlib.canChannelReadMessage( - self._channel_handle, 0, ctypes.byref(self._message) - ) + _canlib.canChannelReadMessage(self._channel_handle, 0, ctypes.byref(self._message)) except (VCITimeout, VCIRxQueueEmptyError): break @@ -794,9 +753,7 @@ def _recv_internal(self, timeout): if timeout == 0: # Peek without waiting try: - _canlib.canChannelPeekMessage( - self._channel_handle, ctypes.byref(self._message) - ) + _canlib.canChannelPeekMessage(self._channel_handle, ctypes.byref(self._message)) except (VCITimeout, VCIRxQueueEmptyError, VCIError): # VCIError means no frame available (canChannelPeekMessage returned different from zero) return None, True @@ -815,9 +772,7 @@ def _recv_internal(self, timeout): while True: try: - _canlib.canChannelReadMessage( - self._channel_handle, remaining_ms, ctypes.byref(self._message) - ) + _canlib.canChannelReadMessage(self._channel_handle, remaining_ms, ctypes.byref(self._message)) except (VCITimeout, VCIRxQueueEmptyError): # Ignore the 2 errors, the timeout is handled manually with the perf_counter() pass @@ -834,9 +789,7 @@ def _recv_internal(self, timeout): ) ) - elif ( - self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR - ): + elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR: log.warning( CAN_ERROR_MESSAGES.get( self._message.abData[0], @@ -844,17 +797,12 @@ def _recv_internal(self, timeout): ) ) - elif ( - self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_STATUS - ): + elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_STATUS: log.info(_format_can_status(self._message.abData[0])) if self._message.abData[0] & constants.CAN_STATUS_BUSOFF: raise VCIBusOffError() - elif ( - self._message.uMsgInfo.Bits.type - == constants.CAN_MSGTYPE_TIMEOVR - ): + elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_TIMEOVR: pass else: log.warning("Unexpected message info type") @@ -872,14 +820,11 @@ def _recv_internal(self, timeout): # The _message.dwTime is a 32bit tick value and will overrun, # so expect to see the value restarting from 0 rx_msg = Message( - timestamp=self._message.dwTime - / self._tick_resolution, # Relative time in s + timestamp=self._message.dwTime / self._tick_resolution, # Relative time in s is_remote_frame=bool(self._message.uMsgInfo.Bits.rtr), is_fd=bool(self._message.uMsgInfo.Bits.edl), is_rx=True, - is_error_frame=bool( - self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR - ), + is_error_frame=bool(self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR), bitrate_switch=bool(self._message.uMsgInfo.Bits.fdr), error_state_indicator=bool(self._message.uMsgInfo.Bits.esi), is_extended_id=bool(self._message.uMsgInfo.Bits.ext), @@ -905,11 +850,7 @@ def send(self, msg: Message, timeout: Optional[float] = None) -> None: """ # This system is not designed to be very efficient message = structures.CANMSG2() - message.uMsgInfo.Bits.type = ( - constants.CAN_MSGTYPE_ERROR - if msg.is_error_frame - else constants.CAN_MSGTYPE_DATA - ) + message.uMsgInfo.Bits.type = constants.CAN_MSGTYPE_ERROR if msg.is_error_frame else constants.CAN_MSGTYPE_DATA message.uMsgInfo.Bits.rtr = 1 if msg.is_remote_frame else 0 message.uMsgInfo.Bits.ext = 1 if msg.is_extended_id else 0 message.uMsgInfo.Bits.srr = 1 if self._receive_own_messages else 0 @@ -920,16 +861,12 @@ def send(self, msg: Message, timeout: Optional[float] = None) -> None: if msg.dlc: # this dlc means number of bytes of payload message.uMsgInfo.Bits.dlc = len2dlc(msg.dlc) data_len_dif = msg.dlc - len(msg.data) - data = msg.data + bytearray( - [0] * data_len_dif - ) # pad with zeros until required length + data = msg.data + bytearray([0] * data_len_dif) # pad with zeros until required length adapter = (ctypes.c_uint8 * msg.dlc).from_buffer(data) ctypes.memmove(message.abData, adapter, msg.dlc) if timeout: - _canlib.canChannelSendMessage( - self._channel_handle, int(timeout * 1000), message - ) + _canlib.canChannelSendMessage(self._channel_handle, int(timeout * 1000), message) else: _canlib.canChannelPostMessage(self._channel_handle, message) @@ -945,18 +882,12 @@ def _send_periodic_internal( if modifier_callback is None: if self._scheduler is None: self._scheduler = HANDLE() - _canlib.canSchedulerOpen( - self._device_handle, self.channel, self._scheduler - ) + _canlib.canSchedulerOpen(self._device_handle, self.channel, self._scheduler) caps = structures.CANCAPABILITIES2() _canlib.canSchedulerGetCaps(self._scheduler, caps) - self._scheduler_resolution = ( - caps.dwCmsClkFreq / caps.dwCmsDivisor - ) # TODO: confirm + self._scheduler_resolution = caps.dwCmsClkFreq / caps.dwCmsDivisor # TODO: confirm _canlib.canSchedulerActivate(self._scheduler, constants.TRUE) - return CyclicSendTask( - self._scheduler, msgs, period, duration, self._scheduler_resolution - ) + return CyclicSendTask(self._scheduler, msgs, period, duration, self._scheduler_resolution) # fallback to thread based cyclic task warnings.warn( @@ -987,9 +918,7 @@ class CyclicSendTask(LimitedDurationCyclicSendTaskABC, RestartableCyclicTaskABC) def __init__(self, scheduler, msgs, period, duration, resolution): super().__init__(msgs, period, duration) if len(self.messages) != 1: - raise ValueError( - "IXXAT Interface only supports periodic transmission of 1 element" - ) + raise ValueError("IXXAT Interface only supports periodic transmission of 1 element") self._scheduler = scheduler self._index = None @@ -1064,3 +993,55 @@ def get_ixxat_hwids(): _canlib.vciEnumDeviceClose(device_handle) return hwids + + +def _detect_available_configs() -> List[AutoDetectedConfig]: + config_list = [] # list in wich to store the resulting bus kwargs + + # used to detect HWID + device_handle = HANDLE() + device_info = structures.VCIDEVICEINFO() + + # used to attempt to open channels + channel_handle = HANDLE() + device_handle2 = HANDLE() + + try: + _canlib.vciEnumDeviceOpen(ctypes.byref(device_handle)) + while True: + try: + _canlib.vciEnumDeviceNext(device_handle, ctypes.byref(device_info)) + except StopIteration: + break + else: + hwid = device_info.UniqueHardwareId.AsChar.decode("ascii") + _canlib.vciDeviceOpen( + ctypes.byref(device_info.VciObjectId), + ctypes.byref(device_handle2), + ) + for channel in range(4): + try: + _canlib.canChannelOpen( + device_handle2, + channel, + constants.FALSE, + ctypes.byref(channel_handle), + ) + except Exception: + # Array outside of bounds error == accessing a channel not in the hardware + break + else: + _canlib.canChannelClose(channel_handle) + config_list.append( + { + "interface": "ixxat", + "channel": channel, + "unique_hardware_id": hwid, + } + ) + _canlib.vciDeviceClose(device_handle2) + _canlib.vciEnumDeviceClose(device_handle) + except AttributeError: + pass # _canlib is None in the CI tests -> return a blank list + + return config_list From b6a0c3c729a21e6b89a57ca68282dbad8932deda Mon Sep 17 00:00:00 2001 From: MattWoodhead Date: Sat, 3 Jun 2023 08:53:36 +0000 Subject: [PATCH 03/15] Format code with black --- can/interfaces/ixxat/canlib_vcinpl2.py | 160 +++++++++++++++++++------ 1 file changed, 121 insertions(+), 39 deletions(-) diff --git a/can/interfaces/ixxat/canlib_vcinpl2.py b/can/interfaces/ixxat/canlib_vcinpl2.py index 07e94d397..2cac2aa8e 100644 --- a/can/interfaces/ixxat/canlib_vcinpl2.py +++ b/can/interfaces/ixxat/canlib_vcinpl2.py @@ -62,7 +62,9 @@ log.warning("IXXAT VCI library does not work on %s platform", sys.platform) -def __vciFormatErrorExtended(library_instance: CLibrary, function: Callable, vret: int, args: Tuple): +def __vciFormatErrorExtended( + library_instance: CLibrary, function: Callable, vret: int, args: Tuple +): """Format a VCI error and attach failed function, decoded HRESULT and arguments :param CLibrary library_instance: Mapped instance of IXXAT vcinpl library @@ -76,7 +78,9 @@ def __vciFormatErrorExtended(library_instance: CLibrary, function: Callable, vre Formatted string """ # TODO: make sure we don't generate another exception - return "{} - arguments were {}".format(__vciFormatError(library_instance, function, vret), args) + return "{} - arguments were {}".format( + __vciFormatError(library_instance, function, vret), args + ) def __vciFormatError(library_instance: CLibrary, function: Callable, vret: int): @@ -93,7 +97,9 @@ def __vciFormatError(library_instance: CLibrary, function: Callable, vret: int): buf = ctypes.create_string_buffer(constants.VCI_MAX_ERRSTRLEN) ctypes.memset(buf, 0, constants.VCI_MAX_ERRSTRLEN) library_instance.vciFormatError(vret, buf, constants.VCI_MAX_ERRSTRLEN) - return "function {} failed ({})".format(function._name, buf.value.decode("utf-8", "replace")) + return "function {} failed ({})".format( + function._name, buf.value.decode("utf-8", "replace") + ) def __check_status(result: int, function: Callable, args: Tuple): @@ -135,9 +141,13 @@ def __check_status(result: int, function: Callable, args: Tuple): # void VCIAPI vciFormatError (HRESULT hrError, PCHAR pszText, UINT32 dwsize); try: - _canlib.map_symbol("vciFormatError", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32)) + _canlib.map_symbol( + "vciFormatError", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32) + ) except ImportError: - _canlib.map_symbol("vciFormatErrorA", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32)) + _canlib.map_symbol( + "vciFormatErrorA", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32) + ) _canlib.vciFormatError = _canlib.vciFormatErrorA # Hack to have vciFormatError as a free function vciFormatError = functools.partial(__vciFormatError, _canlib) @@ -155,7 +165,9 @@ def __check_status(result: int, function: Callable, args: Tuple): ) # HRESULT VCIAPI vciDeviceOpen( IN REFVCIID rVciid, OUT PHANDLE phDevice ); - _canlib.map_symbol("vciDeviceOpen", hresult_type, (structures.PVCIID, PHANDLE), __check_status) + _canlib.map_symbol( + "vciDeviceOpen", hresult_type, (structures.PVCIID, PHANDLE), __check_status + ) # HRESULT vciDeviceClose( HANDLE hDevice ) _canlib.map_symbol("vciDeviceClose", hresult_type, (HANDLE,), __check_status) @@ -189,7 +201,9 @@ def __check_status(result: int, function: Callable, args: Tuple): __check_status, ) # EXTERN_C HRESULT VCIAPI canChannelActivate( IN HANDLE hCanChn, IN BOOL fEnable ); - _canlib.map_symbol("canChannelActivate", hresult_type, (HANDLE, ctypes.c_long), __check_status) + _canlib.map_symbol( + "canChannelActivate", hresult_type, (HANDLE, ctypes.c_long), __check_status + ) # HRESULT canChannelClose( HANDLE hChannel ) _canlib.map_symbol("canChannelClose", hresult_type, (HANDLE,), __check_status) # EXTERN_C HRESULT VCIAPI canChannelReadMessage( IN HANDLE hCanChn, IN UINT32 dwMsTimeout, OUT PCANMSG2 pCanMsg ); @@ -273,7 +287,9 @@ def __check_status(result: int, function: Callable, args: Tuple): # EXTERN_C HRESULT VCIAPI canControlReset( IN HANDLE hCanCtl ); _canlib.map_symbol("canControlReset", hresult_type, (HANDLE,), __check_status) # EXTERN_C HRESULT VCIAPI canControlStart( IN HANDLE hCanCtl, IN BOOL fStart ); - _canlib.map_symbol("canControlStart", hresult_type, (HANDLE, ctypes.c_long), __check_status) + _canlib.map_symbol( + "canControlStart", hresult_type, (HANDLE, ctypes.c_long), __check_status + ) # EXTERN_C HRESULT VCIAPI canControlGetStatus( IN HANDLE hCanCtl, OUT PCANLINESTATUS2 pStatus ); _canlib.map_symbol( "canControlGetStatus", @@ -326,7 +342,9 @@ def __check_status(result: int, function: Callable, args: Tuple): __check_status, ) # EXTERN_C HRESULT canSchedulerActivate ( HANDLE hScheduler, BOOL fEnable ); - _canlib.map_symbol("canSchedulerActivate", hresult_type, (HANDLE, ctypes.c_int), __check_status) + _canlib.map_symbol( + "canSchedulerActivate", hresult_type, (HANDLE, ctypes.c_int), __check_status + ) # EXTERN_C HRESULT canSchedulerAddMessage (HANDLE hScheduler, PCANCYCLICTXMSG2 pMessage, PUINT32 pdwIndex ); _canlib.map_symbol( "canSchedulerAddMessage", @@ -492,7 +510,9 @@ def __init__( # Usually comes as a string from the config file channel = int(channel) - if bitrate not in constants.CAN_BITRATE_PRESETS and (tseg1_abr is None or tseg2_abr is None or sjw_abr is None): + if bitrate not in constants.CAN_BITRATE_PRESETS and ( + tseg1_abr is None or tseg2_abr is None or sjw_abr is None + ): raise ValueError( "To use bitrate {} (that has not predefined preset) is mandatory to use also parameters tseg1_abr, tseg2_abr and swj_abr".format( bitrate @@ -532,7 +552,9 @@ def __init__( _canlib.vciEnumDeviceOpen(ctypes.byref(self._device_handle)) while True: try: - _canlib.vciEnumDeviceNext(self._device_handle, ctypes.byref(self._device_info)) + _canlib.vciEnumDeviceNext( + self._device_handle, ctypes.byref(self._device_info) + ) except StopIteration as exc: if unique_hardware_id is None: raise VCIDeviceNotFoundError( @@ -540,11 +562,14 @@ def __init__( ) from exc else: raise VCIDeviceNotFoundError( - "Unique HW ID {} not connected or not available.".format(unique_hardware_id) + "Unique HW ID {} not connected or not available.".format( + unique_hardware_id + ) ) from exc else: if (unique_hardware_id is None) or ( - self._device_info.UniqueHardwareId.AsChar == bytes(unique_hardware_id, "ascii") + self._device_info.UniqueHardwareId.AsChar + == bytes(unique_hardware_id, "ascii") ): break else: @@ -579,7 +604,9 @@ def __init__( ctypes.byref(self._channel_handle), ) except Exception as exc: - raise CanInitializationError(f"Could not open and initialize channel: {exc}") from exc + raise CanInitializationError( + f"Could not open and initialize channel: {exc}" + ) from exc # Signal TX/RX events when at least one frame has been handled _canlib.canChannelInitialize( @@ -616,18 +643,26 @@ def __init__( pBtpSDR, pBtpFDR, ) - _canlib.canControlOpen(self._device_handle, channel, ctypes.byref(self._control_handle)) + _canlib.canControlOpen( + self._device_handle, channel, ctypes.byref(self._control_handle) + ) - _canlib.canControlGetCaps(self._control_handle, ctypes.byref(self._channel_capabilities)) + _canlib.canControlGetCaps( + self._control_handle, ctypes.byref(self._channel_capabilities) + ) # check capabilities bOpMode = constants.CAN_OPMODE_UNDEFINED - if (self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT) != 0: + if ( + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT + ) != 0: # controller supports CAN_OPMODE_STANDARD and CAN_OPMODE_EXTENDED at the same time bOpMode |= constants.CAN_OPMODE_STANDARD # enable both 11 bits reception if extended: # parameter from configuration bOpMode |= constants.CAN_OPMODE_EXTENDED # enable 29 bits reception - elif (self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT) != 0: + elif ( + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT + ) != 0: log.warning( "Channel %d capabilities allow either basic or extended IDs, but not both. using %s according to parameter [extended=%s]", channel, @@ -635,7 +670,11 @@ def __init__( "True" if extended else "False", ) # controller supports either CAN_OPMODE_STANDARD or CAN_OPMODE_EXTENDED, but not both simultaneously - bOpMode |= constants.CAN_OPMODE_EXTENDED if extended else constants.CAN_OPMODE_STANDARD + bOpMode |= ( + constants.CAN_OPMODE_EXTENDED + if extended + else constants.CAN_OPMODE_STANDARD + ) if ( # controller supports receiving error frames: self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_ERRFRAME @@ -645,11 +684,17 @@ def __init__( bExMode = constants.CAN_EXMODE_DISABLED self._can_protocol = CanProtocol.CAN_20 # default to standard CAN protocol if fd: - if (self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_EXTDATA) != 0: + if ( + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_EXTDATA + ) != 0: bExMode |= constants.CAN_EXMODE_EXTDATALEN - if (self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_FASTDATA) != 0: + if ( + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_FASTDATA + ) != 0: bExMode |= constants.CAN_EXMODE_FASTDATA - self._can_protocol = CanProtocol.CAN_FD # set bus to CAN FD protocol once FD capability is verified + self._can_protocol = ( + CanProtocol.CAN_FD + ) # set bus to CAN FD protocol once FD capability is verified _canlib.canControlInitialize( self._control_handle, @@ -667,7 +712,10 @@ def __init__( # the message in ticks. The resolution of a tick can be calculated from the fields # dwClockFreq and dwTscDivisor of the structure CANCAPABILITIES in accordance with the following formula: # frequency [1/s] = dwClockFreq / dwTscDivisor - self._tick_resolution = self._channel_capabilities.dwTscClkFreq / self._channel_capabilities.dwTscDivisor + self._tick_resolution = ( + self._channel_capabilities.dwTscClkFreq + / self._channel_capabilities.dwTscDivisor + ) # Setup filters before starting the channel if can_filters: @@ -685,7 +733,9 @@ def __init__( code = int(can_filter["can_id"]) mask = int(can_filter["can_mask"]) extended = can_filter.get("extended", False) - _canlib.canControlAddFilterIds(self._control_handle, 1 if extended else 0, code << 1, mask << 1) + _canlib.canControlAddFilterIds( + self._control_handle, 1 if extended else 0, code << 1, mask << 1 + ) log.info("Accepting ID: 0x%X MASK: 0x%X", code, mask) # Start the CAN controller. Messages will be forwarded to the channel @@ -700,7 +750,9 @@ def __init__( # Clear the FIFO by filter them out with low timeout for _ in range(rx_fifo_size): try: - _canlib.canChannelReadMessage(self._channel_handle, 0, ctypes.byref(self._message)) + _canlib.canChannelReadMessage( + self._channel_handle, 0, ctypes.byref(self._message) + ) except (VCITimeout, VCIRxQueueEmptyError): break @@ -753,7 +805,9 @@ def _recv_internal(self, timeout): if timeout == 0: # Peek without waiting try: - _canlib.canChannelPeekMessage(self._channel_handle, ctypes.byref(self._message)) + _canlib.canChannelPeekMessage( + self._channel_handle, ctypes.byref(self._message) + ) except (VCITimeout, VCIRxQueueEmptyError, VCIError): # VCIError means no frame available (canChannelPeekMessage returned different from zero) return None, True @@ -772,7 +826,9 @@ def _recv_internal(self, timeout): while True: try: - _canlib.canChannelReadMessage(self._channel_handle, remaining_ms, ctypes.byref(self._message)) + _canlib.canChannelReadMessage( + self._channel_handle, remaining_ms, ctypes.byref(self._message) + ) except (VCITimeout, VCIRxQueueEmptyError): # Ignore the 2 errors, the timeout is handled manually with the perf_counter() pass @@ -789,7 +845,9 @@ def _recv_internal(self, timeout): ) ) - elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR: + elif ( + self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR + ): log.warning( CAN_ERROR_MESSAGES.get( self._message.abData[0], @@ -797,12 +855,17 @@ def _recv_internal(self, timeout): ) ) - elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_STATUS: + elif ( + self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_STATUS + ): log.info(_format_can_status(self._message.abData[0])) if self._message.abData[0] & constants.CAN_STATUS_BUSOFF: raise VCIBusOffError() - elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_TIMEOVR: + elif ( + self._message.uMsgInfo.Bits.type + == constants.CAN_MSGTYPE_TIMEOVR + ): pass else: log.warning("Unexpected message info type") @@ -820,11 +883,14 @@ def _recv_internal(self, timeout): # The _message.dwTime is a 32bit tick value and will overrun, # so expect to see the value restarting from 0 rx_msg = Message( - timestamp=self._message.dwTime / self._tick_resolution, # Relative time in s + timestamp=self._message.dwTime + / self._tick_resolution, # Relative time in s is_remote_frame=bool(self._message.uMsgInfo.Bits.rtr), is_fd=bool(self._message.uMsgInfo.Bits.edl), is_rx=True, - is_error_frame=bool(self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR), + is_error_frame=bool( + self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR + ), bitrate_switch=bool(self._message.uMsgInfo.Bits.fdr), error_state_indicator=bool(self._message.uMsgInfo.Bits.esi), is_extended_id=bool(self._message.uMsgInfo.Bits.ext), @@ -850,7 +916,11 @@ def send(self, msg: Message, timeout: Optional[float] = None) -> None: """ # This system is not designed to be very efficient message = structures.CANMSG2() - message.uMsgInfo.Bits.type = constants.CAN_MSGTYPE_ERROR if msg.is_error_frame else constants.CAN_MSGTYPE_DATA + message.uMsgInfo.Bits.type = ( + constants.CAN_MSGTYPE_ERROR + if msg.is_error_frame + else constants.CAN_MSGTYPE_DATA + ) message.uMsgInfo.Bits.rtr = 1 if msg.is_remote_frame else 0 message.uMsgInfo.Bits.ext = 1 if msg.is_extended_id else 0 message.uMsgInfo.Bits.srr = 1 if self._receive_own_messages else 0 @@ -861,12 +931,16 @@ def send(self, msg: Message, timeout: Optional[float] = None) -> None: if msg.dlc: # this dlc means number of bytes of payload message.uMsgInfo.Bits.dlc = len2dlc(msg.dlc) data_len_dif = msg.dlc - len(msg.data) - data = msg.data + bytearray([0] * data_len_dif) # pad with zeros until required length + data = msg.data + bytearray( + [0] * data_len_dif + ) # pad with zeros until required length adapter = (ctypes.c_uint8 * msg.dlc).from_buffer(data) ctypes.memmove(message.abData, adapter, msg.dlc) if timeout: - _canlib.canChannelSendMessage(self._channel_handle, int(timeout * 1000), message) + _canlib.canChannelSendMessage( + self._channel_handle, int(timeout * 1000), message + ) else: _canlib.canChannelPostMessage(self._channel_handle, message) @@ -882,12 +956,18 @@ def _send_periodic_internal( if modifier_callback is None: if self._scheduler is None: self._scheduler = HANDLE() - _canlib.canSchedulerOpen(self._device_handle, self.channel, self._scheduler) + _canlib.canSchedulerOpen( + self._device_handle, self.channel, self._scheduler + ) caps = structures.CANCAPABILITIES2() _canlib.canSchedulerGetCaps(self._scheduler, caps) - self._scheduler_resolution = caps.dwCmsClkFreq / caps.dwCmsDivisor # TODO: confirm + self._scheduler_resolution = ( + caps.dwCmsClkFreq / caps.dwCmsDivisor + ) # TODO: confirm _canlib.canSchedulerActivate(self._scheduler, constants.TRUE) - return CyclicSendTask(self._scheduler, msgs, period, duration, self._scheduler_resolution) + return CyclicSendTask( + self._scheduler, msgs, period, duration, self._scheduler_resolution + ) # fallback to thread based cyclic task warnings.warn( @@ -918,7 +998,9 @@ class CyclicSendTask(LimitedDurationCyclicSendTaskABC, RestartableCyclicTaskABC) def __init__(self, scheduler, msgs, period, duration, resolution): super().__init__(msgs, period, duration) if len(self.messages) != 1: - raise ValueError("IXXAT Interface only supports periodic transmission of 1 element") + raise ValueError( + "IXXAT Interface only supports periodic transmission of 1 element" + ) self._scheduler = scheduler self._index = None From f5642fd2cc00d7ad73a9eb4104784be9dd2be6e3 Mon Sep 17 00:00:00 2001 From: MattWoodhead Date: Mon, 5 Jun 2023 23:40:34 +0100 Subject: [PATCH 04/15] remove proxy class --- can/interfaces/ixxat/__init__.py | 5 +- can/interfaces/ixxat/canlib.py | 1209 ++++++++++++++++++++++-- can/interfaces/ixxat/canlib_vcinpl.py | 945 ------------------ can/interfaces/ixxat/canlib_vcinpl2.py | 1129 ---------------------- can/interfaces/ixxat/constants.py | 24 + 5 files changed, 1138 insertions(+), 2174 deletions(-) delete mode 100644 can/interfaces/ixxat/canlib_vcinpl.py delete mode 100644 can/interfaces/ixxat/canlib_vcinpl2.py diff --git a/can/interfaces/ixxat/__init__.py b/can/interfaces/ixxat/__init__.py index 6fe79adb8..e4c7564cb 100644 --- a/can/interfaces/ixxat/__init__.py +++ b/can/interfaces/ixxat/__init__.py @@ -15,7 +15,4 @@ "structures", ] -from can.interfaces.ixxat.canlib import IXXATBus - -# import this and not the one from vcinpl2 for backward compatibility -from can.interfaces.ixxat.canlib_vcinpl import get_ixxat_hwids +from can.interfaces.ixxat.canlib import IXXATBus, get_ixxat_hwids diff --git a/can/interfaces/ixxat/canlib.py b/can/interfaces/ixxat/canlib.py index 372874c20..a2b6c4494 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/can/interfaces/ixxat/canlib.py @@ -1,45 +1,431 @@ -from typing import Callable, List, Optional, Sequence, Union +""" +Ctypes wrapper module for IXXAT Virtual CAN Interface V4 on win32 systems + +TODO: We could implement this interface such that setting other filters + could work when the initial filters were set to zero using the + software fallback. Or could the software filters even be changed + after the connection was opened? We need to document that bahaviour! + See also the NICAN interface. + +""" + +import ctypes +import functools +import logging +import sys +import time +import warnings +from typing import Callable, List, Optional, Sequence, Tuple, Union -import can.interfaces.ixxat.canlib_vcinpl as vcinpl -import can.interfaces.ixxat.canlib_vcinpl2 as vcinpl2 from can import ( + BitTiming, + BitTimingFd, BusABC, BusState, + CanProtocol, CyclicSendTaskABC, + LimitedDurationCyclicSendTaskABC, Message, + RestartableCyclicTaskABC, ) -from can.typechecking import AutoDetectedConfig +from can.ctypesutil import HANDLE, PHANDLE, CLibrary +from can.ctypesutil import HRESULT as ctypes_HRESULT +from can.exceptions import CanInitializationError, CanInterfaceNotImplementedError +from can.typechecking import AutoDetectedConfig, CanFilters +from can.util import deprecated_args_alias, dlc2len, len2dlc + +from can.interfaces.ixxat import constants, structures +from .exceptions import * + +__all__ = [ + "VCITimeout", + "VCIError", + "VCIBusOffError", + "VCIDeviceNotFoundError", + "IXXATBus", + "vciFormatError", +] + +log = logging.getLogger("can.ixxat") + +# Hack to have vciFormatError as a free function, see below +vciFormatError = None + +# main ctypes instance +_canlib = None +# TODO: Use ECI driver for linux +if sys.platform in ("win32", "cygwin"): + try: + _canlib = CLibrary("vcinpl2.dll") + except Exception as e: + log.warning("Cannot load IXXAT vcinpl library: %s", e) +else: + # Will not work on other systems, but have it importable anyway for + # tests/sphinx + log.warning("IXXAT VCI library does not work on %s platform", sys.platform) + + +def __vciFormatErrorExtended( + library_instance: CLibrary, function: Callable, vret: int, args: Tuple +): + """Format a VCI error and attach failed function, decoded HRESULT and arguments + :param CLibrary library_instance: + Mapped instance of IXXAT vcinpl library + :param callable function: + Failed function + :param HRESULT vret: + HRESULT returned by vcinpl call + :param args: + Arbitrary arguments tuple + :return: + Formatted string + """ + # TODO: make sure we don't generate another exception + return "{} - arguments were {}".format( + __vciFormatError(library_instance, function, vret), args + ) + + +def __vciFormatError(library_instance: CLibrary, function: Callable, vret: int): + """Format a VCI error and attach failed function and decoded HRESULT + :param CLibrary library_instance: + Mapped instance of IXXAT vcinpl library + :param callable function: + Failed function + :param HRESULT vret: + HRESULT returned by vcinpl call + :return: + Formatted string + """ + buf = ctypes.create_string_buffer(constants.VCI_MAX_ERRSTRLEN) + ctypes.memset(buf, 0, constants.VCI_MAX_ERRSTRLEN) + library_instance.vciFormatError(vret, buf, constants.VCI_MAX_ERRSTRLEN) + return "function {} failed ({})".format( + function._name, buf.value.decode("utf-8", "replace") + ) + + +def __check_status(result: int, function: Callable, args: Tuple): + """ + Check the result of a vcinpl function call and raise appropriate exception + in case of an error. Used as errcheck function when mapping C functions + with ctypes. + :param result: + Function call numeric result + :param callable function: + Called function + :param args: + Arbitrary arguments tuple + :raise: + :class:VCITimeout + :class:VCIRxQueueEmptyError + :class:StopIteration + :class:VCIError + """ + if result == constants.VCI_E_TIMEOUT: + raise VCITimeout(f"Function {function._name} timed out") + elif result == constants.VCI_E_RXQUEUE_EMPTY: + raise VCIRxQueueEmptyError() + elif result == constants.VCI_E_NO_MORE_ITEMS: + raise StopIteration() + elif result == constants.VCI_E_ACCESSDENIED: + pass # not a real error, might happen if another program has initialized the bus + elif result != constants.VCI_OK: + raise VCIError(vciFormatError(function, result)) + + return result + + +try: + hresult_type = ctypes.c_ulong + # Map all required symbols and initialize library --------------------------- + # HRESULT VCIAPI vciInitialize ( void ); + _canlib.map_symbol("vciInitialize", hresult_type, (), __check_status) + + # void VCIAPI vciFormatError (HRESULT hrError, PCHAR pszText, UINT32 dwsize); + try: + _canlib.map_symbol( + "vciFormatError", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32) + ) + except ImportError: + _canlib.map_symbol( + "vciFormatErrorA", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32) + ) + _canlib.vciFormatError = _canlib.vciFormatErrorA + # Hack to have vciFormatError as a free function + vciFormatError = functools.partial(__vciFormatError, _canlib) + + # HRESULT VCIAPI vciEnumDeviceOpen( OUT PHANDLE hEnum ); + _canlib.map_symbol("vciEnumDeviceOpen", hresult_type, (PHANDLE,), __check_status) + # HRESULT VCIAPI vciEnumDeviceClose ( IN HANDLE hEnum ); + _canlib.map_symbol("vciEnumDeviceClose", hresult_type, (HANDLE,), __check_status) + # HRESULT VCIAPI vciEnumDeviceNext( IN HANDLE hEnum, OUT PVCIDEVICEINFO pInfo ); + _canlib.map_symbol( + "vciEnumDeviceNext", + hresult_type, + (HANDLE, structures.PVCIDEVICEINFO), + __check_status, + ) + + # HRESULT VCIAPI vciDeviceOpen( IN REFVCIID rVciid, OUT PHANDLE phDevice ); + _canlib.map_symbol( + "vciDeviceOpen", hresult_type, (structures.PVCIID, PHANDLE), __check_status + ) + # HRESULT vciDeviceClose( HANDLE hDevice ) + _canlib.map_symbol("vciDeviceClose", hresult_type, (HANDLE,), __check_status) + + # HRESULT VCIAPI canChannelOpen( IN HANDLE hDevice, IN UINT32 dwCanNo, IN BOOL fExclusive, OUT PHANDLE phCanChn ); + _canlib.map_symbol( + "canChannelOpen", + hresult_type, + (HANDLE, ctypes.c_uint32, ctypes.c_long, PHANDLE), + __check_status, + ) + # EXTERN_C HRESULT VCIAPI + # canChannelInitialize( IN HANDLE hCanChn, + # IN UINT16 wRxFifoSize, + # IN UINT16 wRxThreshold, + # IN UINT16 wTxFifoSize, + # IN UINT16 wTxThreshold, + # IN UINT32 dwFilterSize, + # IN UINT8 bFilterMode ); + _canlib.map_symbol( + "canChannelInitialize", + hresult_type, + ( + HANDLE, + ctypes.c_uint16, + ctypes.c_uint16, + ctypes.c_uint16, + ctypes.c_uint16, + ctypes.c_uint32, + ctypes.c_uint8, + ), + __check_status, + ) + # EXTERN_C HRESULT VCIAPI canChannelActivate( IN HANDLE hCanChn, IN BOOL fEnable ); + _canlib.map_symbol( + "canChannelActivate", hresult_type, (HANDLE, ctypes.c_long), __check_status + ) + # HRESULT canChannelClose( HANDLE hChannel ) + _canlib.map_symbol("canChannelClose", hresult_type, (HANDLE,), __check_status) + # EXTERN_C HRESULT VCIAPI canChannelReadMessage( IN HANDLE hCanChn, IN UINT32 dwMsTimeout, OUT PCANMSG2 pCanMsg ); + _canlib.map_symbol( + "canChannelReadMessage", + hresult_type, + (HANDLE, ctypes.c_uint32, structures.PCANMSG2), + __check_status, + ) + # HRESULT canChannelPeekMessage(HANDLE hChannel,PCANMSG2 pCanMsg ); + _canlib.map_symbol( + "canChannelPeekMessage", + hresult_type, + (HANDLE, structures.PCANMSG2), + __check_status, + ) + # HRESULT canChannelWaitTxEvent (HANDLE hChannel UINT32 dwMsTimeout ); + _canlib.map_symbol( + "canChannelWaitTxEvent", + hresult_type, + (HANDLE, ctypes.c_uint32), + __check_status, + ) + # HRESULT canChannelWaitRxEvent (HANDLE hChannel, UINT32 dwMsTimeout ); + _canlib.map_symbol( + "canChannelWaitRxEvent", + hresult_type, + (HANDLE, ctypes.c_uint32), + __check_status, + ) + # HRESULT canChannelPostMessage (HANDLE hChannel, PCANMSG2 pCanMsg ); + _canlib.map_symbol( + "canChannelPostMessage", + hresult_type, + (HANDLE, structures.PCANMSG2), + __check_status, + ) + # HRESULT canChannelSendMessage (HANDLE hChannel, UINT32 dwMsTimeout, PCANMSG2 pCanMsg ); + _canlib.map_symbol( + "canChannelSendMessage", + hresult_type, + (HANDLE, ctypes.c_uint32, structures.PCANMSG2), + __check_status, + ) + + # EXTERN_C HRESULT VCIAPI canControlOpen( IN HANDLE hDevice, IN UINT32 dwCanNo, OUT PHANDLE phCanCtl ); + _canlib.map_symbol( + "canControlOpen", + hresult_type, + (HANDLE, ctypes.c_uint32, PHANDLE), + __check_status, + ) + # EXTERN_C HRESULT VCIAPI + # canControlInitialize( IN HANDLE hCanCtl, + # IN UINT8 bOpMode, + # IN UINT8 bExMode, + # IN UINT8 bSFMode, + # IN UINT8 bEFMode, + # IN UINT32 dwSFIds, + # IN UINT32 dwEFIds, + # IN PCANBTP pBtpSDR, + # IN PCANBTP pBtpFDR ); + _canlib.map_symbol( + "canControlInitialize", + hresult_type, + ( + HANDLE, + ctypes.c_uint8, + ctypes.c_uint8, + ctypes.c_uint8, + ctypes.c_uint8, + ctypes.c_uint32, + ctypes.c_uint32, + structures.PCANBTP, + structures.PCANBTP, + ), + __check_status, + ) + # EXTERN_C HRESULT VCIAPI canControlClose( IN HANDLE hCanCtl ); + _canlib.map_symbol("canControlClose", hresult_type, (HANDLE,), __check_status) + # EXTERN_C HRESULT VCIAPI canControlReset( IN HANDLE hCanCtl ); + _canlib.map_symbol("canControlReset", hresult_type, (HANDLE,), __check_status) + # EXTERN_C HRESULT VCIAPI canControlStart( IN HANDLE hCanCtl, IN BOOL fStart ); + _canlib.map_symbol( + "canControlStart", hresult_type, (HANDLE, ctypes.c_long), __check_status + ) + # EXTERN_C HRESULT VCIAPI canControlGetStatus( IN HANDLE hCanCtl, OUT PCANLINESTATUS2 pStatus ); + _canlib.map_symbol( + "canControlGetStatus", + hresult_type, + (HANDLE, structures.PCANLINESTATUS2), + __check_status, + ) + # EXTERN_C HRESULT VCIAPI canControlGetCaps( IN HANDLE hCanCtl, OUT PCANCAPABILITIES2 pCanCaps ); + _canlib.map_symbol( + "canControlGetCaps", + hresult_type, + (HANDLE, structures.PCANCAPABILITIES2), + __check_status, + ) + # EXTERN_C HRESULT VCIAPI canControlSetAccFilter( IN HANDLE hCanCtl, IN BOOL fExtend, IN UINT32 dwCode, IN UINT32 dwMask ); + _canlib.map_symbol( + "canControlSetAccFilter", + hresult_type, + (HANDLE, ctypes.c_int, ctypes.c_uint32, ctypes.c_uint32), + __check_status, + ) + # EXTERN_C HRESULT canControlAddFilterIds (HANDLE hControl, BOOL fExtended, UINT32 dwCode, UINT32 dwMask); + _canlib.map_symbol( + "canControlAddFilterIds", + hresult_type, + (HANDLE, ctypes.c_int, ctypes.c_uint32, ctypes.c_uint32), + __check_status, + ) + # EXTERN_C HRESULT canControlRemFilterIds (HANDLE hControl, BOOL fExtendend, UINT32 dwCode, UINT32 dwMask ); + _canlib.map_symbol( + "canControlRemFilterIds", + hresult_type, + (HANDLE, ctypes.c_int, ctypes.c_uint32, ctypes.c_uint32), + __check_status, + ) + # EXTERN_C HRESULT canSchedulerOpen (HANDLE hDevice, UINT32 dwCanNo, PHANDLE phScheduler ); + _canlib.map_symbol( + "canSchedulerOpen", + hresult_type, + (HANDLE, ctypes.c_uint32, PHANDLE), + __check_status, + ) + # EXTERN_C HRESULT canSchedulerClose (HANDLE hScheduler ); + _canlib.map_symbol("canSchedulerClose", hresult_type, (HANDLE,), __check_status) + # EXTERN_C HRESULT canSchedulerGetCaps (HANDLE hScheduler, PCANCAPABILITIES2 pCaps ); + _canlib.map_symbol( + "canSchedulerGetCaps", + hresult_type, + (HANDLE, structures.PCANCAPABILITIES2), + __check_status, + ) + # EXTERN_C HRESULT canSchedulerActivate ( HANDLE hScheduler, BOOL fEnable ); + _canlib.map_symbol( + "canSchedulerActivate", hresult_type, (HANDLE, ctypes.c_int), __check_status + ) + # EXTERN_C HRESULT canSchedulerAddMessage (HANDLE hScheduler, PCANCYCLICTXMSG2 pMessage, PUINT32 pdwIndex ); + _canlib.map_symbol( + "canSchedulerAddMessage", + hresult_type, + (HANDLE, structures.PCANCYCLICTXMSG2, ctypes.POINTER(ctypes.c_uint32)), + __check_status, + ) + # EXTERN_C HRESULT canSchedulerRemMessage (HANDLE hScheduler, UINT32 dwIndex ); + _canlib.map_symbol( + "canSchedulerRemMessage", + hresult_type, + (HANDLE, ctypes.c_uint32), + __check_status, + ) + # EXTERN_C HRESULT canSchedulerStartMessage (HANDLE hScheduler, UINT32 dwIndex, UINT16 dwCount ); + _canlib.map_symbol( + "canSchedulerStartMessage", + hresult_type, + (HANDLE, ctypes.c_uint32, ctypes.c_uint16), + __check_status, + ) + # EXTERN_C HRESULT canSchedulerStopMessage (HANDLE hScheduler, UINT32 dwIndex ); + _canlib.map_symbol( + "canSchedulerStopMessage", + hresult_type, + (HANDLE, ctypes.c_uint32), + __check_status, + ) + _canlib.vciInitialize() +except AttributeError: + # In case _canlib == None meaning we're not on win32/no lib found + pass +except Exception as exc: + log.warning("Could not initialize IXXAT VCI library: %s", exc) class IXXATBus(BusABC): """The CAN Bus implemented for the IXXAT interface. - Based on the C implementation of IXXAT, two different dlls are provided by IXXAT, one to work with CAN, - the other with CAN-FD. + .. warning:: + + This interface does implement efficient filtering of messages, but + the filters have to be set in ``__init__`` using the ``can_filters`` parameter. + Using :meth:`~can.BusABC.set_filters` does not work. - This class only delegates to related implementation (in calib_vcinpl or canlib_vcinpl2) - class depending on fd user option. """ + @deprecated_args_alias( + deprecation_start="4.2.2", + deprecation_end="5.0.0", + sjw_abr=None, # Use BitTiming class instead + tseg1_abr=None, + tseg2_abr=None, + sjw_dbr=None, + tseg1_dbr=None, + tseg2_dbr=None, + ssp_dbr=None, + ) + @deprecated_args_alias( + deprecation_start="4.0.0", + deprecation_end="5.0.0", + UniqueHardwareId="unique_hardware_id", + rxFifoSize="rx_fifo_size", + txFifoSize="tx_fifo_size", + ) def __init__( self, channel: int, - can_filters=None, - receive_own_messages: bool = False, + can_filters: Optional[CanFilters] = None, + receive_own_messages: Optional[int] = False, unique_hardware_id: Optional[int] = None, - extended: bool = True, - fd: bool = False, - rx_fifo_size: int = None, - tx_fifo_size: int = None, - bitrate: int = 500000, - data_bitrate: int = 2000000, - sjw_abr: int = None, - tseg1_abr: int = None, - tseg2_abr: int = None, - sjw_dbr: int = None, - tseg1_dbr: int = None, - tseg2_dbr: int = None, - ssp_dbr: int = None, + extended: Optional[bool] = True, + fd: Optional[bool] = False, + rx_fifo_size: Optional[int] = None, + tx_fifo_size: Optional[int] = None, + bitrate: Optional[int] = 500000, + data_bitrate: Optional[int] = 500000, + timing: Optional[Union[BitTiming, BitTimingFd]] = None, **kwargs, ): """ @@ -53,103 +439,553 @@ def __init__( Enable self-reception of sent messages. :param unique_hardware_id: - UniqueHardwareId to connect (optional, will use the first found if not supplied) + unique_hardware_id to connect (optional, will use the first found if not supplied) :param extended: Default True, enables the capability to use extended IDs. :param fd: - Default False, enables CAN-FD usage. + Default False, enables CAN-FD usage (alternatively a :class:`~can.BitTimingFd` + instance may be passed to the `timing` parameter). :param rx_fifo_size: - Receive fifo size (default 1024 for fd, else 16) + Receive fifo size (default 16). If initialised as an FD bus, this value is automatically + increased to 1024 unless a value is specified by the user. :param tx_fifo_size: - Transmit fifo size (default 128 for fd, else 16) + Transmit fifo size (default 16). If initialised as an FD bus, this value is automatically + increased to 128 unless a value is specified by the user. :param bitrate: - Channel bitrate in bit/s + Channel bitrate in bit/s. Note that this value will be overriden if a + :class:`~can.BitTiming` or :class:`~can.BitTimingFd` instance is provided + in the `timing` parameter. :param data_bitrate: - Channel bitrate in bit/s (only in CAN-Fd if baudrate switch enabled). + Channel bitrate in bit/s (only in CAN-Fd if baudrate switch enabled). Note that + this value will be overriden if a :class:`~can.BitTimingFd` instance is provided + in the `timing` parameter. + + :param timing: + Optional :class:`~can.BitTiming` or :class:`~can.BitTimingFd` instance + to use for custom bit timing setting. The `f_clock` value of the timing + instance must be set to 40_000_000 (40MHz). + If this parameter is provided, it takes precedence over all other + timing-related parameters like `bitrate`, `fd_bitrate` and `fd`. - :param sjw_abr: - Bus timing value sample jump width (arbitration). Only takes effect with fd enabled. + """ + if _canlib is None: + raise CanInterfaceNotImplementedError( + "The IXXAT VCI library has not been initialized. Check the logs for more details." + ) + log.info("CAN Filters: %s", can_filters) - :param tseg1_abr: - Bus timing value tseg1 (arbitration). Only takes effect with fd enabled. + # Configuration options + self._receive_own_messages = receive_own_messages + if isinstance(timing, BitTimingFd): + # if a BitTimingFd instance has been passed, we can presume the user wants to use FD capability + fd = True + channel = int(channel) # Usually comes as a string from the config file + if channel < 0: + raise ValueError("channel number must be >= 0") + bitrate = int(bitrate) + data_bitrate = int(data_bitrate) + if (bitrate < 0) or (data_bitrate < 0): + raise ValueError("bitrate and data_bitrate must be >= 0") - :param tseg2_abr: - Bus timing value tseg2 (arbitration). Only takes effect with fd enabled. + # fetch deprecated timing arguments (if provided) + tseg1_abr = kwargs.get("tseg1_abr") + tseg2_abr = kwargs.get("tseg2_abr") + sjw_abr = kwargs.get("sjw_abr") + tseg1_dbr = kwargs.get("tseg1_dbr") + tseg2_dbr = kwargs.get("tseg2_dbr") + sjw_dbr = kwargs.get("sjw_dbr") + ssp_dbr = kwargs.get("ssp_dbr") - :param sjw_dbr: - Bus timing value sample jump width (data). Only takes effect with fd and baudrate switch enabled. + # setup buffer sizes + if rx_fifo_size: # if the user provided an rx fifo size + if rx_fifo_size <= 0: + raise ValueError("rx_fifo_size must be > 0") + else: # otherwise use the default size (depending upon if FD or not) + rx_fifo_size = 16 + if fd: + rx_fifo_size = 1024 - :param tseg1_dbr: - Bus timing value tseg1 (data). Only takes effect with fd and bitrate switch enabled. + if tx_fifo_size: # if the user provided a tx fifo size + if tx_fifo_size <= 0: + raise ValueError("tx_fifo_size must be > 0") + else: # otherwise use the default size (depending upon if FD or not) + tx_fifo_size = 16 + if fd: + tx_fifo_size = 128 - :param tseg2_dbr: - Bus timing value tseg2 (data). Only takes effect with fd and bitrate switch enabled. + self._device_handle = HANDLE() + self._device_info = structures.VCIDEVICEINFO() + self._control_handle = HANDLE() + self._channel_handle = HANDLE() + self._channel_capabilities = structures.CANCAPABILITIES2() + self._message = structures.CANMSG2() + if fd: + self._payload = (ctypes.c_byte * 64)() + else: + self._payload = (ctypes.c_byte * 8)() - :param ssp_dbr: - Secondary sample point (data). Only takes effect with fd and bitrate switch enabled. + # Search for supplied device + if unique_hardware_id is None: + log.info("Searching for first available device") + else: + log.info("Searching for unique HW ID %s", unique_hardware_id) + _canlib.vciEnumDeviceOpen(ctypes.byref(self._device_handle)) + while True: + try: + _canlib.vciEnumDeviceNext( + self._device_handle, ctypes.byref(self._device_info) + ) + except StopIteration as exc: + if unique_hardware_id is None: + raise VCIDeviceNotFoundError( + "No IXXAT device(s) connected or device(s) in use by other process(es)." + ) from exc + else: + raise VCIDeviceNotFoundError( + "Unique HW ID {} not connected or not available.".format( + unique_hardware_id + ) + ) from exc + else: + if (unique_hardware_id is None) or ( + self._device_info.UniqueHardwareId.AsChar + == bytes(unique_hardware_id, "ascii") + ): + break + else: + log.debug( + "Ignoring IXXAT with hardware id '%s'.", + self._device_info.UniqueHardwareId.AsChar.decode("ascii"), + ) + _canlib.vciEnumDeviceClose(self._device_handle) - """ - # if fd: - if rx_fifo_size is None: - rx_fifo_size = 1024 - if tx_fifo_size is None: - tx_fifo_size = 128 - self.bus = vcinpl2.IXXATBus( - channel=channel, - can_filters=can_filters, - receive_own_messages=receive_own_messages, - unique_hardware_id=unique_hardware_id, - extended=extended, - rx_fifo_size=rx_fifo_size, - tx_fifo_size=tx_fifo_size, - bitrate=bitrate, - data_bitrate=data_bitrate, - sjw_abr=sjw_abr, - tseg1_abr=tseg1_abr, - tseg2_abr=tseg2_abr, - sjw_dbr=sjw_dbr, - tseg1_dbr=tseg1_dbr, - tseg2_dbr=tseg2_dbr, - ssp_dbr=ssp_dbr, - fd=fd, - **kwargs, + try: + _canlib.vciDeviceOpen( + ctypes.byref(self._device_info.VciObjectId), + ctypes.byref(self._device_handle), + ) + except Exception as exc: + raise CanInitializationError(f"Could not open device: {exc}") from exc + + log.info("Using unique HW ID %s", self._device_info.UniqueHardwareId.AsChar) + + log.info( + "Initializing channel %d in shared mode, %d rx buffers, %d tx buffers", + channel, + rx_fifo_size, + tx_fifo_size, + ) + + try: + _canlib.canChannelOpen( + self._device_handle, + channel, + constants.FALSE, + ctypes.byref(self._channel_handle), + ) + except Exception as exc: + raise CanInitializationError( + f"Could not open and initialize channel: {exc}" + ) from exc + + # Signal TX/RX events when at least one frame has been handled + _canlib.canChannelInitialize( + self._channel_handle, + rx_fifo_size, + 1, + tx_fifo_size, + 1, + 0, + constants.CAN_FILTER_PASS, + ) + _canlib.canChannelActivate(self._channel_handle, constants.TRUE) + + _canlib.canControlOpen( + self._device_handle, channel, ctypes.byref(self._control_handle) ) - # else: - # if rx_fifo_size is None: - # rx_fifo_size = 16 - # if tx_fifo_size is None: - # tx_fifo_size = 16 - # self.bus = vcinpl.IXXATBus( - # channel=channel, - # can_filters=can_filters, - # receive_own_messages=receive_own_messages, - # unique_hardware_id=unique_hardware_id, - # extended=extended, - # rx_fifo_size=rx_fifo_size, - # tx_fifo_size=tx_fifo_size, - # bitrate=bitrate, - # **kwargs, - # ) - - super().__init__(channel=channel, **kwargs) - self._can_protocol = self.bus.protocol + + log.debug("Fetching capabilities for interface channel %d", channel) + _canlib.canControlGetCaps( + self._control_handle, ctypes.byref(self._channel_capabilities) + ) + + # check capabilities + bOpMode = constants.CAN_OPMODE_UNDEFINED + if ( + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT + ) != 0: + # controller supports CAN_OPMODE_STANDARD and CAN_OPMODE_EXTENDED at the same time + bOpMode |= constants.CAN_OPMODE_STANDARD # enable both 11 bits reception + if extended: # parameter from configuration + bOpMode |= constants.CAN_OPMODE_EXTENDED # enable 29 bits reception + elif ( + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT + ) != 0: + log.warning( + "Channel %d capabilities allow either basic or extended IDs, but not both. using %s according to parameter [extended=%s]", + channel, + "extended" if extended else "basic", + "True" if extended else "False", + ) + # controller supports either CAN_OPMODE_STANDARD or CAN_OPMODE_EXTENDED, but not both simultaneously + bOpMode |= ( + constants.CAN_OPMODE_EXTENDED + if extended + else constants.CAN_OPMODE_STANDARD + ) + + if ( # controller supports receiving error frames: + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_ERRFRAME + ) != 0: + bOpMode |= constants.CAN_OPMODE_ERRFRAME + + bExMode = constants.CAN_EXMODE_DISABLED + self._can_protocol = CanProtocol.CAN_20 # default to standard CAN protocol + if fd: + if ( + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_EXTDATA + ) != 0: + bExMode |= constants.CAN_EXMODE_EXTDATALEN + else: + raise CanInitializationError( + "The interface %s does not support extended data frames (FD)" % + self._device_info.UniqueHardwareId.AsChar.decode("ascii"), + ) + if ( + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_FASTDATA + ) != 0: + bExMode |= constants.CAN_EXMODE_FASTDATA + else: + raise CanInitializationError( + "The interface %s does not support fast data rates (FD)" % + self._device_info.UniqueHardwareId.AsChar.decode("ascii"), + ) + # set bus to CAN FD protocol once FD capability is verified + self._can_protocol = CanProtocol.CAN_FD + + if not timing: + # only use bitrate and the deprecated args if no timing argument is provided + if tseg1_abr and tseg2_abr and sjw_abr: + if not tseg1_dbr and not tseg2_dbr and not sjw_dbr: + # if only the arbitration rate segments have been specified, duplicate them for data rate segments + tseg1_dbr = tseg1_abr + tseg1_dbr = tseg2_dbr + sjw_dbr = sjw_abr + try: + timing = BitTimingFd.from_bitrate_and_segments( + f_clock=self._channel_capabilities.dwCanClockFreq, + nom_bitrate=bitrate, + nom_tseg1=tseg1_abr, + nom_tseg2=tseg2_abr, + nom_sjw=sjw_abr, + data_bitrate=data_bitrate, + data_tseg1=tseg1_dbr, + data_tseg2=tseg2_dbr, + data_sjw=sjw_dbr, + ) + except ValueError as exc: + raise CanInitializationError( + "Could not initialise the channel with the given bitrate and segment timings" + ) from exc + else: + try: + timing = BitTimingFd.from_sample_point( + f_clock=self._channel_capabilities.dwCanClockFreq, + nom_bitrate=bitrate, + nom_sample_point=80, + data_bitrate=data_bitrate, + data_sample_point=80, + ) + except ValueError as exc: + raise CanInitializationError( + "Could not initialise the channel with the given bitrate and sample point target of 80%." + ) from exc + elif isinstance(timing, BitTiming): + # if a standard BitTiming class has been passed, convert it to a BitTimingFD instance + timing = BitTimingFd.from_bitrate_and_segments( + f_clock=timing.f_clock, + nom_bitrate=timing.bitrate, + nom_tseg1=timing.tseg1, + nom_tseg2=timing.tseg2, + nom_sjw=timing.sjw, + data_bitrate=timing.bitrate, + data_tseg1=timing.tseg1, + data_tseg2=timing.tseg2, + data_sjw=timing.sjw, + ) + + pBtpSDR = IXXATBus._canptb_build( + defaults=constants.CAN_BITRATE_PRESETS, + bitrate=timing.bitrate, + tseg1=timing.tseg1, + tseg2=timing.tseg2, + sjw=timing.sjw, + ssp=0, + ) + pBtpFDR = IXXATBus._canptb_build( + defaults=constants.CAN_DATABITRATE_PRESETS, + bitrate=data_bitrate, + tseg1=tseg1_dbr, + tseg2=tseg2_dbr, + sjw=sjw_dbr, + ssp=ssp_dbr if ssp_dbr is not None else tseg1_dbr, + ) + + _canlib.canControlInitialize( + self._control_handle, + bOpMode, + bExMode, + constants.CAN_FILTER_PASS, + constants.CAN_FILTER_PASS, + 0, + 0, + ctypes.byref(pBtpSDR), + ctypes.byref(pBtpFDR), + ) + + # With receive messages, this field contains the relative reception time of + # the message in ticks. The resolution of a tick can be calculated from the fields + # dwClockFreq and dwTscDivisor of the structure CANCAPABILITIES in accordance with the following formula: + # frequency [1/s] = dwClockFreq / dwTscDivisor + self._tick_resolution = ( + self._channel_capabilities.dwTscClkFreq + / self._channel_capabilities.dwTscDivisor + ) + + # Setup filters before starting the channel + if can_filters: + log.info("The IXXAT VCI backend is filtering messages") + # Disable every message coming in + for extended_filter in (False, True): + _canlib.canControlSetAccFilter( + self._control_handle, + extended_filter, + constants.CAN_ACC_CODE_NONE, + constants.CAN_ACC_MASK_NONE, + ) + for can_filter in can_filters: + # Filters define what messages are accepted + code = int(can_filter["can_id"]) + mask = int(can_filter["can_mask"]) + extended = can_filter.get("extended", False) + _canlib.canControlAddFilterIds( + self._control_handle, 1 if extended else 0, code << 1, mask << 1 + ) + log.info("Accepting ID: 0x%X MASK: 0x%X", code, mask) + + # Start the CAN controller. Messages will be forwarded to the channel + _canlib.canControlStart(self._control_handle, constants.TRUE) + + # For cyclic transmit list. Set when .send_periodic() is first called + self._scheduler = None + self._scheduler_resolution = None + self.channel = channel + + # Usually you get back 3 messages like "CAN initialized" ecc... + # Clear the FIFO by filter them out with low timeout + for _ in range(rx_fifo_size): + try: + _canlib.canChannelReadMessage( + self._channel_handle, 0, ctypes.byref(self._message) + ) + except (VCITimeout, VCIRxQueueEmptyError): + break + + super().__init__(channel=channel, can_filters=None, **kwargs) + + @staticmethod # TODO - implement BitTiming class + def _canptb_build(defaults, bitrate, tseg1, tseg2, sjw, ssp): + if bitrate in defaults: + d = defaults[bitrate] + if tseg1 is None: + tseg1 = d.wTS1 + if tseg2 is None: + tseg2 = d.wTS2 + if sjw is None: + sjw = d.wSJW + if ssp is None: + ssp = d.wTDO + dw_mode = d.dwMode + else: + dw_mode = 0 + + return structures.CANBTP( + dwMode=dw_mode, + dwBPS=bitrate, + wTS1=tseg1, + wTS2=tseg2, + wSJW=sjw, + wTDO=ssp, + ) + + def _inWaiting(self): + try: + _canlib.canChannelWaitRxEvent(self._channel_handle, 0) + except VCITimeout: + return 0 + else: + return 1 def flush_tx_buffer(self): """Flushes the transmit buffer on the IXXAT""" - return self.bus.flush_tx_buffer() + # TODO #64: no timeout? + _canlib.canChannelWaitTxEvent(self._channel_handle, constants.INFINITE) def _recv_internal(self, timeout): """Read a message from IXXAT device.""" - return self.bus._recv_internal(timeout) + + # TODO: handling CAN error messages? + data_received = False + + if timeout == 0: + # Peek without waiting + try: + _canlib.canChannelPeekMessage( + self._channel_handle, ctypes.byref(self._message) + ) + except (VCITimeout, VCIRxQueueEmptyError, VCIError): + # VCIError means no frame available (canChannelPeekMessage returned different from zero) + return None, True + else: + if self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_DATA: + data_received = True + else: + # Wait if no message available + if timeout is None or timeout < 0: + remaining_ms = constants.INFINITE + t0 = None + else: + timeout_ms = int(timeout * 1000) + remaining_ms = timeout_ms + t0 = time.perf_counter() + + while True: + try: + _canlib.canChannelReadMessage( + self._channel_handle, remaining_ms, ctypes.byref(self._message) + ) + except (VCITimeout, VCIRxQueueEmptyError): + # Ignore the 2 errors, the timeout is handled manually with the perf_counter() + pass + else: + # See if we got a data or info/error messages + if self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_DATA: + data_received = True + break + elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_INFO: + log.info( + constants.CAN_INFO_MESSAGES.get( + self._message.abData[0], + f"Unknown CAN info message code {self._message.abData[0]}", + ) + ) + + elif ( + self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR + ): + log.warning( + constants.CAN_ERROR_MESSAGES.get( + self._message.abData[0], + f"Unknown CAN error message code {self._message.abData[0]}", + ) + ) + + elif ( + self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_STATUS + ): + log.info(_format_can_status(self._message.abData[0])) + if self._message.abData[0] & constants.CAN_STATUS_BUSOFF: + raise VCIBusOffError() + + elif ( + self._message.uMsgInfo.Bits.type + == constants.CAN_MSGTYPE_TIMEOVR + ): + pass + else: + log.warning("Unexpected message info type") + + if t0 is not None: + remaining_ms = timeout_ms - int((time.perf_counter() - t0) * 1000) + if remaining_ms < 0: + break + + if not data_received: + # Timed out / can message type is not DATA + return None, True + + data_len = dlc2len(self._message.uMsgInfo.Bits.dlc) + # The _message.dwTime is a 32bit tick value and will overrun, + # so expect to see the value restarting from 0 + rx_msg = Message( + timestamp=self._message.dwTime + / self._tick_resolution, # Relative time in s + is_remote_frame=bool(self._message.uMsgInfo.Bits.rtr), + is_fd=bool(self._message.uMsgInfo.Bits.edl), + is_rx=True, + is_error_frame=bool( + self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR + ), + bitrate_switch=bool(self._message.uMsgInfo.Bits.fdr), + error_state_indicator=bool(self._message.uMsgInfo.Bits.esi), + is_extended_id=bool(self._message.uMsgInfo.Bits.ext), + arbitration_id=self._message.dwMsgId, + dlc=data_len, + data=self._message.abData[:data_len], + channel=self.channel, + ) + + return rx_msg, True + def send(self, msg: Message, timeout: Optional[float] = None) -> None: - return self.bus.send(msg, timeout) + """ + Sends a message on the bus. The interface may buffer the message. + + :param msg: + The message to send. + :param timeout: + Timeout after some time. + :raise: + :class:CanTimeoutError + :class:CanOperationError + """ + # This system is not designed to be very efficient + message = structures.CANMSG2() + message.uMsgInfo.Bits.type = ( + constants.CAN_MSGTYPE_ERROR + if msg.is_error_frame + else constants.CAN_MSGTYPE_DATA + ) + message.uMsgInfo.Bits.rtr = 1 if msg.is_remote_frame else 0 + message.uMsgInfo.Bits.ext = 1 if msg.is_extended_id else 0 + message.uMsgInfo.Bits.srr = 1 if self._receive_own_messages else 0 + message.uMsgInfo.Bits.fdr = 1 if msg.bitrate_switch else 0 + message.uMsgInfo.Bits.esi = 1 if msg.error_state_indicator else 0 + message.uMsgInfo.Bits.edl = 1 if msg.is_fd else 0 + message.dwMsgId = msg.arbitration_id + if msg.dlc: # this dlc means number of bytes of payload + message.uMsgInfo.Bits.dlc = len2dlc(msg.dlc) + data_len_dif = msg.dlc - len(msg.data) + data = msg.data + bytearray( + [0] * data_len_dif + ) # pad with zeros until required length + adapter = (ctypes.c_uint8 * msg.dlc).from_buffer(data) + ctypes.memmove(message.abData, adapter, msg.dlc) + + if timeout: + _canlib.canChannelSendMessage( + self._channel_handle, int(timeout * 1000), message + ) + + else: + _canlib.canChannelPostMessage(self._channel_handle, message) def _send_periodic_internal( self, @@ -158,21 +994,202 @@ def _send_periodic_internal( duration: Optional[float] = None, modifier_callback: Optional[Callable[[Message], None]] = None, ) -> CyclicSendTaskABC: - return self.bus._send_periodic_internal( - msgs, period, duration, modifier_callback + """Send a message using built-in cyclic transmit list functionality.""" + if modifier_callback is None: + if self._scheduler is None: + self._scheduler = HANDLE() + _canlib.canSchedulerOpen( + self._device_handle, self.channel, self._scheduler + ) + caps = structures.CANCAPABILITIES2() + _canlib.canSchedulerGetCaps(self._scheduler, caps) + self._scheduler_resolution = ( + caps.dwCmsClkFreq / caps.dwCmsDivisor + ) # TODO: confirm + _canlib.canSchedulerActivate(self._scheduler, constants.TRUE) + return CyclicSendTask( + self._scheduler, msgs, period, duration, self._scheduler_resolution + ) + + # fallback to thread based cyclic task + warnings.warn( + f"{self.__class__.__name__} falls back to a thread-based cyclic task, " + "when the `modifier_callback` argument is given." + ) + return BusABC._send_periodic_internal( + self, + msgs=msgs, + period=period, + duration=duration, + modifier_callback=modifier_callback, ) - def shutdown(self) -> None: + + def shutdown(self): super().shutdown() - self.bus.shutdown() + if self._scheduler is not None: + _canlib.canSchedulerClose(self._scheduler) + _canlib.canChannelClose(self._channel_handle) + _canlib.canControlStart(self._control_handle, constants.FALSE) + _canlib.canControlClose(self._control_handle) + _canlib.vciDeviceClose(self._device_handle) @property def state(self) -> BusState: """ Return the current state of the hardware """ - return self.bus.state + status = structures.CANLINESTATUS() + _canlib.canControlGetStatus(self._control_handle, ctypes.byref(status)) + if status.bOpMode == constants.CAN_OPMODE_LISTONLY: + return BusState.PASSIVE + + error_byte_1 = status.dwStatus & 0x0F + # CAN_STATUS_BUSOFF = 0x08 # bus off status + if error_byte_1 & constants.CAN_STATUS_BUSOFF: + return BusState.ERROR + + error_byte_2 = status.dwStatus & 0xF0 + # CAN_STATUS_BUSCERR = 0x20 # bus coupling error + if error_byte_2 & constants.CAN_STATUS_BUSCERR: + raise BusState.ERROR + + return BusState.ACTIVE @staticmethod def _detect_available_configs() -> List[AutoDetectedConfig]: - return vcinpl2._detect_available_configs() + + config_list = [] # list in wich to store the resulting bus kwargs + + # used to detect HWID + device_handle = HANDLE() + device_info = structures.VCIDEVICEINFO() + + # used to attempt to open channels + channel_handle = HANDLE() + device_handle2 = HANDLE() + + try: + _canlib.vciEnumDeviceOpen(ctypes.byref(device_handle)) + while True: + try: + _canlib.vciEnumDeviceNext(device_handle, ctypes.byref(device_info)) + except StopIteration: + break + else: + hwid = device_info.UniqueHardwareId.AsChar.decode("ascii") + _canlib.vciDeviceOpen( + ctypes.byref(device_info.VciObjectId), + ctypes.byref(device_handle2), + ) + for channel in range(4): + try: + _canlib.canChannelOpen( + device_handle2, + channel, + constants.FALSE, + ctypes.byref(channel_handle), + ) + except Exception: + # Array outside of bounds error == accessing a channel not in the hardware + break + else: + _canlib.canChannelClose(channel_handle) + config_list.append( + { + "interface": "ixxat", + "channel": channel, + "unique_hardware_id": hwid, + } + ) + _canlib.vciDeviceClose(device_handle2) + _canlib.vciEnumDeviceClose(device_handle) + except AttributeError: + pass # _canlib is None in the CI tests -> return a blank list + + return config_list + + +class CyclicSendTask(LimitedDurationCyclicSendTaskABC, RestartableCyclicTaskABC): + """A message in the cyclic transmit list.""" + + def __init__(self, scheduler, msgs, period, duration, resolution): + super().__init__(msgs, period, duration) + if len(self.messages) != 1: + raise ValueError( + "IXXAT Interface only supports periodic transmission of 1 element" + ) + + self._scheduler = scheduler + self._index = None + self._count = int(duration / period) if duration else 0 + + self._msg = structures.CANCYCLICTXMSG2() + self._msg.wCycleTime = int(round(period * resolution)) + self._msg.dwMsgId = self.messages[0].arbitration_id + self._msg.uMsgInfo.Bits.type = constants.CAN_MSGTYPE_DATA + self._msg.uMsgInfo.Bits.ext = 1 if self.messages[0].is_extended_id else 0 + self._msg.uMsgInfo.Bits.rtr = 1 if self.messages[0].is_remote_frame else 0 + self._msg.uMsgInfo.Bits.dlc = self.messages[0].dlc + for i, b in enumerate(self.messages[0].data): + self._msg.abData[i] = b + self.start() + + def start(self): + """Start transmitting message (add to list if needed).""" + if self._index is None: + self._index = ctypes.c_uint32() + _canlib.canSchedulerAddMessage(self._scheduler, self._msg, self._index) + _canlib.canSchedulerStartMessage(self._scheduler, self._index, self._count) + + def pause(self): + """Pause transmitting message (keep it in the list).""" + _canlib.canSchedulerStopMessage(self._scheduler, self._index) + + def stop(self): + """Stop transmitting message (remove from list).""" + # Remove it completely instead of just stopping it to avoid filling up + # the list with permanently stopped messages + _canlib.canSchedulerRemMessage(self._scheduler, self._index) + self._index = None + + +def _format_can_status(status_flags: int): + """ + Format a status bitfield found in CAN_MSGTYPE_STATUS messages or in dwStatus + field in CANLINESTATUS. + + Valid states are defined in the CAN_STATUS_* constants in cantype.h + """ + states = [] + for flag, description in constants.CAN_STATUS_FLAGS.items(): + if status_flags & flag: + states.append(description) + status_flags &= ~flag + + if status_flags: + states.append(f"unknown state 0x{status_flags:02x}") + + if states: + return "CAN status message: {}".format(", ".join(states)) + else: + return "Empty CAN status message" + + +def get_ixxat_hwids(): + """Get a list of hardware ids of all available IXXAT devices.""" + hwids = [] + device_handle = HANDLE() + device_info = structures.VCIDEVICEINFO() + + _canlib.vciEnumDeviceOpen(ctypes.byref(device_handle)) + while True: + try: + _canlib.vciEnumDeviceNext(device_handle, ctypes.byref(device_info)) + except StopIteration: + break + else: + hwids.append(device_info.UniqueHardwareId.AsChar.decode("ascii")) + _canlib.vciEnumDeviceClose(device_handle) + + return hwids diff --git a/can/interfaces/ixxat/canlib_vcinpl.py b/can/interfaces/ixxat/canlib_vcinpl.py deleted file mode 100644 index 1bb0fd802..000000000 --- a/can/interfaces/ixxat/canlib_vcinpl.py +++ /dev/null @@ -1,945 +0,0 @@ -""" -Ctypes wrapper module for IXXAT Virtual CAN Interface V4 on win32 systems - -TODO: We could implement this interface such that setting other filters - could work when the initial filters were set to zero using the - software fallback. Or could the software filters even be changed - after the connection was opened? We need to document that bahaviour! - See also the NICAN interface. - -""" - -import ctypes -import functools -import logging -import sys -import warnings -from typing import Callable, Optional, Sequence, Tuple, Union - -from can import ( - BusABC, - BusState, - CanProtocol, - CyclicSendTaskABC, - LimitedDurationCyclicSendTaskABC, - Message, - RestartableCyclicTaskABC, -) -from can.ctypesutil import HANDLE, PHANDLE, CLibrary -from can.ctypesutil import HRESULT as ctypes_HRESULT -from can.exceptions import CanInitializationError, CanInterfaceNotImplementedError -from can.util import deprecated_args_alias - -from . import constants, structures -from .exceptions import * - -__all__ = [ - "VCITimeout", - "VCIError", - "VCIBusOffError", - "VCIDeviceNotFoundError", - "IXXATBus", - "vciFormatError", -] - -log = logging.getLogger("can.ixxat") - - -# Hack to have vciFormatError as a free function, see below -vciFormatError = None - -# main ctypes instance -_canlib = None -# TODO: Use ECI driver for linux -if sys.platform == "win32" or sys.platform == "cygwin": - try: - _canlib = CLibrary("vcinpl.dll") - except Exception as e: - log.warning("Cannot load IXXAT vcinpl library: %s", e) -else: - # Will not work on other systems, but have it importable anyway for - # tests/sphinx - log.warning("IXXAT VCI library does not work on %s platform", sys.platform) - - -def __vciFormatErrorExtended( - library_instance: CLibrary, function: Callable, vret: int, args: Tuple -): - """Format a VCI error and attach failed function, decoded HRESULT and arguments - :param CLibrary library_instance: - Mapped instance of IXXAT vcinpl library - :param callable function: - Failed function - :param HRESULT vret: - HRESULT returned by vcinpl call - :param args: - Arbitrary arguments tuple - :return: - Formatted string - """ - # TODO: make sure we don't generate another exception - return "{} - arguments were {}".format( - __vciFormatError(library_instance, function, vret), args - ) - - -def __vciFormatError(library_instance: CLibrary, function: Callable, vret: int): - """Format a VCI error and attach failed function and decoded HRESULT - :param CLibrary library_instance: - Mapped instance of IXXAT vcinpl library - :param callable function: - Failed function - :param HRESULT vret: - HRESULT returned by vcinpl call - :return: - Formatted string - """ - buf = ctypes.create_string_buffer(constants.VCI_MAX_ERRSTRLEN) - ctypes.memset(buf, 0, constants.VCI_MAX_ERRSTRLEN) - library_instance.vciFormatError(vret, buf, constants.VCI_MAX_ERRSTRLEN) - return "function {} failed ({})".format( - function._name, buf.value.decode("utf-8", "replace") - ) - - -def __check_status(result, function, args): - """ - Check the result of a vcinpl function call and raise appropriate exception - in case of an error. Used as errcheck function when mapping C functions - with ctypes. - :param result: - Function call numeric result - :param callable function: - Called function - :param args: - Arbitrary arguments tuple - :raise: - :class:VCITimeout - :class:VCIRxQueueEmptyError - :class:StopIteration - :class:VCIError - """ - if isinstance(result, int): - # Real return value is an unsigned long, the following line converts the number to unsigned - result = ctypes.c_ulong(result).value - - if result == constants.VCI_E_TIMEOUT: - raise VCITimeout(f"Function {function._name} timed out") - elif result == constants.VCI_E_RXQUEUE_EMPTY: - raise VCIRxQueueEmptyError() - elif result == constants.VCI_E_NO_MORE_ITEMS: - raise StopIteration() - elif result == constants.VCI_E_ACCESSDENIED: - pass # not a real error, might happen if another program has initialized the bus - elif result != constants.VCI_OK: - raise VCIError(vciFormatError(function, result)) - - return result - - -try: - # Map all required symbols and initialize library --------------------------- - # HRESULT VCIAPI vciInitialize ( void ); - _canlib.map_symbol("vciInitialize", ctypes.c_long, (), __check_status) - - # void VCIAPI vciFormatError (HRESULT hrError, PCHAR pszText, UINT32 dwsize); - _canlib.map_symbol( - "vciFormatError", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32) - ) - # Hack to have vciFormatError as a free function - vciFormatError = functools.partial(__vciFormatError, _canlib) - - # HRESULT VCIAPI vciEnumDeviceOpen( OUT PHANDLE hEnum ); - _canlib.map_symbol("vciEnumDeviceOpen", ctypes.c_long, (PHANDLE,), __check_status) - # HRESULT VCIAPI vciEnumDeviceClose ( IN HANDLE hEnum ); - _canlib.map_symbol("vciEnumDeviceClose", ctypes.c_long, (HANDLE,), __check_status) - # HRESULT VCIAPI vciEnumDeviceNext( IN HANDLE hEnum, OUT PVCIDEVICEINFO pInfo ); - _canlib.map_symbol( - "vciEnumDeviceNext", - ctypes.c_long, - (HANDLE, structures.PVCIDEVICEINFO), - __check_status, - ) - - # HRESULT VCIAPI vciDeviceOpen( IN REFVCIID rVciid, OUT PHANDLE phDevice ); - _canlib.map_symbol( - "vciDeviceOpen", ctypes.c_long, (structures.PVCIID, PHANDLE), __check_status - ) - # HRESULT vciDeviceClose( HANDLE hDevice ) - _canlib.map_symbol("vciDeviceClose", ctypes.c_long, (HANDLE,), __check_status) - - # HRESULT VCIAPI canChannelOpen( IN HANDLE hDevice, IN UINT32 dwCanNo, IN BOOL fExclusive, OUT PHANDLE phCanChn ); - _canlib.map_symbol( - "canChannelOpen", - ctypes.c_long, - (HANDLE, ctypes.c_uint32, ctypes.c_long, PHANDLE), - __check_status, - ) - # EXTERN_C HRESULT VCIAPI canChannelInitialize( IN HANDLE hCanChn, IN UINT16 wRxFifoSize, IN UINT16 wRxThreshold, IN UINT16 wTxFifoSize, IN UINT16 wTxThreshold ); - _canlib.map_symbol( - "canChannelInitialize", - ctypes.c_long, - (HANDLE, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint16), - __check_status, - ) - # EXTERN_C HRESULT VCIAPI canChannelActivate( IN HANDLE hCanChn, IN BOOL fEnable ); - _canlib.map_symbol( - "canChannelActivate", ctypes.c_long, (HANDLE, ctypes.c_long), __check_status - ) - # HRESULT canChannelClose( HANDLE hChannel ) - _canlib.map_symbol("canChannelClose", ctypes.c_long, (HANDLE,), __check_status) - # EXTERN_C HRESULT VCIAPI canChannelReadMessage( IN HANDLE hCanChn, IN UINT32 dwMsTimeout, OUT PCANMSG pCanMsg ); - _canlib.map_symbol( - "canChannelReadMessage", - ctypes.c_long, - (HANDLE, ctypes.c_uint32, structures.PCANMSG), - __check_status, - ) - # HRESULT canChannelPeekMessage(HANDLE hChannel,PCANMSG pCanMsg ); - _canlib.map_symbol( - "canChannelPeekMessage", - ctypes.c_long, - (HANDLE, structures.PCANMSG), - __check_status, - ) - # HRESULT canChannelWaitTxEvent (HANDLE hChannel UINT32 dwMsTimeout ); - _canlib.map_symbol( - "canChannelWaitTxEvent", - ctypes.c_long, - (HANDLE, ctypes.c_uint32), - __check_status, - ) - # HRESULT canChannelWaitRxEvent (HANDLE hChannel, UINT32 dwMsTimeout ); - _canlib.map_symbol( - "canChannelWaitRxEvent", - ctypes.c_long, - (HANDLE, ctypes.c_uint32), - __check_status, - ) - # HRESULT canChannelPostMessage (HANDLE hChannel, PCANMSG pCanMsg ); - _canlib.map_symbol( - "canChannelPostMessage", - ctypes.c_long, - (HANDLE, structures.PCANMSG), - __check_status, - ) - # HRESULT canChannelSendMessage (HANDLE hChannel, UINT32 dwMsTimeout, PCANMSG pCanMsg ); - _canlib.map_symbol( - "canChannelSendMessage", - ctypes.c_long, - (HANDLE, ctypes.c_uint32, structures.PCANMSG), - __check_status, - ) - # HRESULT canChannelGetStatus (HANDLE hCanChn, PCANCHANSTATUS pStatus ); - _canlib.map_symbol( - "canChannelGetStatus", - ctypes.c_long, - (HANDLE, structures.PCANCHANSTATUS), - __check_status, - ) - - # EXTERN_C HRESULT VCIAPI canControlOpen( IN HANDLE hDevice, IN UINT32 dwCanNo, OUT PHANDLE phCanCtl ); - _canlib.map_symbol( - "canControlOpen", - ctypes.c_long, - (HANDLE, ctypes.c_uint32, PHANDLE), - __check_status, - ) - # EXTERN_C HRESULT VCIAPI canControlInitialize( IN HANDLE hCanCtl, IN UINT8 bMode, IN UINT8 bBtr0, IN UINT8 bBtr1 ); - _canlib.map_symbol( - "canControlInitialize", - ctypes.c_long, - (HANDLE, ctypes.c_uint8, ctypes.c_uint8, ctypes.c_uint8), - __check_status, - ) - # EXTERN_C HRESULT VCIAPI canControlClose( IN HANDLE hCanCtl ); - _canlib.map_symbol("canControlClose", ctypes.c_long, (HANDLE,), __check_status) - # EXTERN_C HRESULT VCIAPI canControlReset( IN HANDLE hCanCtl ); - _canlib.map_symbol("canControlReset", ctypes.c_long, (HANDLE,), __check_status) - # EXTERN_C HRESULT VCIAPI canControlStart( IN HANDLE hCanCtl, IN BOOL fStart ); - _canlib.map_symbol( - "canControlStart", ctypes.c_long, (HANDLE, ctypes.c_long), __check_status - ) - # EXTERN_C HRESULT VCIAPI canControlGetStatus( IN HANDLE hCanCtl, OUT PCANLINESTATUS pStatus ); - _canlib.map_symbol( - "canControlGetStatus", - ctypes.c_long, - (HANDLE, structures.PCANLINESTATUS), - __check_status, - ) - # EXTERN_C HRESULT VCIAPI canControlGetCaps( IN HANDLE hCanCtl, OUT PCANCAPABILITIES pCanCaps ); - _canlib.map_symbol( - "canControlGetCaps", - ctypes.c_long, - (HANDLE, structures.PCANCAPABILITIES), - __check_status, - ) - # EXTERN_C HRESULT VCIAPI canControlSetAccFilter( IN HANDLE hCanCtl, IN BOOL fExtend, IN UINT32 dwCode, IN UINT32 dwMask ); - _canlib.map_symbol( - "canControlSetAccFilter", - ctypes.c_long, - (HANDLE, ctypes.c_int, ctypes.c_uint32, ctypes.c_uint32), - __check_status, - ) - # EXTERN_C HRESULT canControlAddFilterIds (HANDLE hControl, BOOL fExtended, UINT32 dwCode, UINT32 dwMask); - _canlib.map_symbol( - "canControlAddFilterIds", - ctypes.c_long, - (HANDLE, ctypes.c_int, ctypes.c_uint32, ctypes.c_uint32), - __check_status, - ) - # EXTERN_C HRESULT canControlRemFilterIds (HANDLE hControl, BOOL fExtendend, UINT32 dwCode, UINT32 dwMask ); - _canlib.map_symbol( - "canControlRemFilterIds", - ctypes.c_long, - (HANDLE, ctypes.c_int, ctypes.c_uint32, ctypes.c_uint32), - __check_status, - ) - # EXTERN_C HRESULT canSchedulerOpen (HANDLE hDevice, UINT32 dwCanNo, PHANDLE phScheduler ); - _canlib.map_symbol( - "canSchedulerOpen", - ctypes.c_long, - (HANDLE, ctypes.c_uint32, PHANDLE), - __check_status, - ) - # EXTERN_C HRESULT canSchedulerClose (HANDLE hScheduler ); - _canlib.map_symbol("canSchedulerClose", ctypes.c_long, (HANDLE,), __check_status) - # EXTERN_C HRESULT canSchedulerGetCaps (HANDLE hScheduler, PCANCAPABILITIES pCaps ); - _canlib.map_symbol( - "canSchedulerGetCaps", - ctypes.c_long, - (HANDLE, structures.PCANCAPABILITIES), - __check_status, - ) - # EXTERN_C HRESULT canSchedulerActivate ( HANDLE hScheduler, BOOL fEnable ); - _canlib.map_symbol( - "canSchedulerActivate", ctypes.c_long, (HANDLE, ctypes.c_int), __check_status - ) - # EXTERN_C HRESULT canSchedulerAddMessage (HANDLE hScheduler, PCANCYCLICTXMSG pMessage, PUINT32 pdwIndex ); - _canlib.map_symbol( - "canSchedulerAddMessage", - ctypes.c_long, - (HANDLE, structures.PCANCYCLICTXMSG, ctypes.POINTER(ctypes.c_uint32)), - __check_status, - ) - # EXTERN_C HRESULT canSchedulerRemMessage (HANDLE hScheduler, UINT32 dwIndex ); - _canlib.map_symbol( - "canSchedulerRemMessage", - ctypes.c_long, - (HANDLE, ctypes.c_uint32), - __check_status, - ) - # EXTERN_C HRESULT canSchedulerStartMessage (HANDLE hScheduler, UINT32 dwIndex, UINT16 dwCount ); - _canlib.map_symbol( - "canSchedulerStartMessage", - ctypes.c_long, - (HANDLE, ctypes.c_uint32, ctypes.c_uint16), - __check_status, - ) - # EXTERN_C HRESULT canSchedulerStopMessage (HANDLE hScheduler, UINT32 dwIndex ); - _canlib.map_symbol( - "canSchedulerStopMessage", - ctypes.c_long, - (HANDLE, ctypes.c_uint32), - __check_status, - ) - _canlib.vciInitialize() -except AttributeError: - # In case _canlib == None meaning we're not on win32/no lib found - pass -except Exception as e: - log.warning("Could not initialize IXXAT VCI library: %s", e) -# --------------------------------------------------------------------------- - - -CAN_INFO_MESSAGES = { - constants.CAN_INFO_START: "CAN started", - constants.CAN_INFO_STOP: "CAN stopped", - constants.CAN_INFO_RESET: "CAN reset", -} - -CAN_ERROR_MESSAGES = { - constants.CAN_ERROR_STUFF: "CAN bit stuff error", - constants.CAN_ERROR_FORM: "CAN form error", - constants.CAN_ERROR_ACK: "CAN acknowledgment error", - constants.CAN_ERROR_BIT: "CAN bit error", - constants.CAN_ERROR_CRC: "CAN CRC error", - constants.CAN_ERROR_OTHER: "Other (unknown) CAN error", -} - -CAN_STATUS_FLAGS = { - constants.CAN_STATUS_TXPEND: "transmission pending", - constants.CAN_STATUS_OVRRUN: "data overrun occurred", - constants.CAN_STATUS_ERRLIM: "error warning limit exceeded", - constants.CAN_STATUS_BUSOFF: "bus off", - constants.CAN_STATUS_ININIT: "init mode active", - constants.CAN_STATUS_BUSCERR: "bus coupling error", -} -# ---------------------------------------------------------------------------- - - -class IXXATBus(BusABC): - """The CAN Bus implemented for the IXXAT interface. - - .. warning:: - - This interface does implement efficient filtering of messages, but - the filters have to be set in ``__init__`` using the ``can_filters`` parameter. - Using :meth:`~can.BusABC.set_filters` does not work. - """ - - CHANNEL_BITRATES = { - 0: { - 10000: constants.CAN_BT0_10KB, - 20000: constants.CAN_BT0_20KB, - 50000: constants.CAN_BT0_50KB, - 100000: constants.CAN_BT0_100KB, - 125000: constants.CAN_BT0_125KB, - 250000: constants.CAN_BT0_250KB, - 500000: constants.CAN_BT0_500KB, - 666000: constants.CAN_BT0_667KB, - 666666: constants.CAN_BT0_667KB, - 666667: constants.CAN_BT0_667KB, - 667000: constants.CAN_BT0_667KB, - 800000: constants.CAN_BT0_800KB, - 1000000: constants.CAN_BT0_1000KB, - }, - 1: { - 10000: constants.CAN_BT1_10KB, - 20000: constants.CAN_BT1_20KB, - 50000: constants.CAN_BT1_50KB, - 100000: constants.CAN_BT1_100KB, - 125000: constants.CAN_BT1_125KB, - 250000: constants.CAN_BT1_250KB, - 500000: constants.CAN_BT1_500KB, - 666000: constants.CAN_BT1_667KB, - 666666: constants.CAN_BT1_667KB, - 666667: constants.CAN_BT1_667KB, - 667000: constants.CAN_BT1_667KB, - 800000: constants.CAN_BT1_800KB, - 1000000: constants.CAN_BT1_1000KB, - }, - } - - @deprecated_args_alias( - deprecation_start="4.0.0", - deprecation_end="5.0.0", - UniqueHardwareId="unique_hardware_id", - rxFifoSize="rx_fifo_size", - txFifoSize="tx_fifo_size", - ) - def __init__( - self, - channel: int, - can_filters=None, - receive_own_messages: bool = False, - unique_hardware_id: Optional[int] = None, - extended: bool = True, - rx_fifo_size: int = 16, - tx_fifo_size: int = 16, - bitrate: int = 500000, - **kwargs, - ): - """ - :param channel: - The Channel id to create this bus with. - - :param can_filters: - See :meth:`can.BusABC.set_filters`. - - :param receive_own_messages: - Enable self-reception of sent messages. - - :param unique_hardware_id: - unique_hardware_id to connect (optional, will use the first found if not supplied) - - :param extended: - Default True, enables the capability to use extended IDs. - - :param rx_fifo_size: - Receive fifo size (default 16) - - :param tx_fifo_size: - Transmit fifo size (default 16) - - :param bitrate: - Channel bitrate in bit/s - """ - if _canlib is None: - raise CanInterfaceNotImplementedError( - "The IXXAT VCI library has not been initialized. Check the logs for more details." - ) - log.info("CAN Filters: %s", can_filters) - # Configuration options - self._receive_own_messages = receive_own_messages - # Usually comes as a string from the config file - channel = int(channel) - - if bitrate not in self.CHANNEL_BITRATES[0]: - raise ValueError(f"Invalid bitrate {bitrate}") - - if rx_fifo_size <= 0: - raise ValueError("rx_fifo_size must be > 0") - - if tx_fifo_size <= 0: - raise ValueError("tx_fifo_size must be > 0") - - if channel < 0: - raise ValueError("channel number must be >= 0") - - self._device_handle = HANDLE() - self._device_info = structures.VCIDEVICEINFO() - self._control_handle = HANDLE() - self._channel_handle = HANDLE() - self._channel_capabilities = structures.CANCAPABILITIES() - self._message = structures.CANMSG() - self._payload = (ctypes.c_byte * 8)() - self._can_protocol = CanProtocol.CAN_20 - - # Search for supplied device - if unique_hardware_id is None: - log.info("Searching for first available device") - else: - log.info("Searching for unique HW ID %s", unique_hardware_id) - _canlib.vciEnumDeviceOpen(ctypes.byref(self._device_handle)) - while True: - try: - _canlib.vciEnumDeviceNext( - self._device_handle, ctypes.byref(self._device_info) - ) - except StopIteration: - if unique_hardware_id is None: - raise VCIDeviceNotFoundError( - "No IXXAT device(s) connected or device(s) in use by other process(es)." - ) - else: - raise VCIDeviceNotFoundError( - "Unique HW ID {} not connected or not available.".format( - unique_hardware_id - ) - ) - else: - if (unique_hardware_id is None) or ( - self._device_info.UniqueHardwareId.AsChar - == bytes(unique_hardware_id, "ascii") - ): - break - - log.debug( - "Ignoring IXXAT with hardware id '%s'.", - self._device_info.UniqueHardwareId.AsChar.decode("ascii"), - ) - _canlib.vciEnumDeviceClose(self._device_handle) - - try: - _canlib.vciDeviceOpen( - ctypes.byref(self._device_info.VciObjectId), - ctypes.byref(self._device_handle), - ) - except Exception as exception: - raise CanInitializationError( - f"Could not open device: {exception}" - ) from exception - - log.info("Using unique HW ID %s", self._device_info.UniqueHardwareId.AsChar) - - log.info( - "Initializing channel %d in shared mode, %d rx buffers, %d tx buffers", - channel, - rx_fifo_size, - tx_fifo_size, - ) - - try: - _canlib.canChannelOpen( - self._device_handle, - channel, - constants.FALSE, - ctypes.byref(self._channel_handle), - ) - except Exception as exception: - raise CanInitializationError( - f"Could not open and initialize channel: {exception}" - ) from exception - - # Signal TX/RX events when at least one frame has been handled - _canlib.canChannelInitialize( - self._channel_handle, rx_fifo_size, 1, tx_fifo_size, 1 - ) - _canlib.canChannelActivate(self._channel_handle, constants.TRUE) - - log.info("Initializing control %d bitrate %d", channel, bitrate) - _canlib.canControlOpen( - self._device_handle, channel, ctypes.byref(self._control_handle) - ) - - # compute opmode before control initialize - opmode = constants.CAN_OPMODE_STANDARD | constants.CAN_OPMODE_ERRFRAME - if extended: - opmode |= constants.CAN_OPMODE_EXTENDED - - # control initialize - _canlib.canControlInitialize( - self._control_handle, - opmode, - self.CHANNEL_BITRATES[0][bitrate], - self.CHANNEL_BITRATES[1][bitrate], - ) - _canlib.canControlGetCaps( - self._control_handle, ctypes.byref(self._channel_capabilities) - ) - - # With receive messages, this field contains the relative reception time of - # the message in ticks. The resolution of a tick can be calculated from the fields - # dwClockFreq and dwTscDivisor of the structure CANCAPABILITIES in accordance with the following formula: - # frequency [1/s] = dwClockFreq / dwTscDivisor - self._tick_resolution = ( - self._channel_capabilities.dwClockFreq - / self._channel_capabilities.dwTscDivisor - ) - - # Setup filters before starting the channel - if can_filters: - log.info("The IXXAT VCI backend is filtering messages") - # Disable every message coming in - for extended in (0, 1): - _canlib.canControlSetAccFilter( - self._control_handle, - extended, - constants.CAN_ACC_CODE_NONE, - constants.CAN_ACC_MASK_NONE, - ) - for can_filter in can_filters: - # Filters define what messages are accepted - code = int(can_filter["can_id"]) - mask = int(can_filter["can_mask"]) - extended = can_filter.get("extended", False) - _canlib.canControlAddFilterIds( - self._control_handle, 1 if extended else 0, code << 1, mask << 1 - ) - log.info("Accepting ID: 0x%X MASK: 0x%X", code, mask) - - # Start the CAN controller. Messages will be forwarded to the channel - _canlib.canControlStart(self._control_handle, constants.TRUE) - - # For cyclic transmit list. Set when .send_periodic() is first called - self._scheduler = None - self._scheduler_resolution = None - self.channel = channel - - # Usually you get back 3 messages like "CAN initialized" ecc... - # Clear the FIFO by filter them out with low timeout - for _ in range(rx_fifo_size): - try: - _canlib.canChannelReadMessage( - self._channel_handle, 0, ctypes.byref(self._message) - ) - except (VCITimeout, VCIRxQueueEmptyError): - break - - super().__init__(channel=channel, can_filters=None, **kwargs) - - def _inWaiting(self): - try: - _canlib.canChannelWaitRxEvent(self._channel_handle, 0) - except VCITimeout: - return 0 - else: - return 1 - - def flush_tx_buffer(self): - """Flushes the transmit buffer on the IXXAT""" - # TODO #64: no timeout? - _canlib.canChannelWaitTxEvent(self._channel_handle, constants.INFINITE) - - def _recv_internal(self, timeout): - """Read a message from IXXAT device.""" - data_received = False - - if self._inWaiting() or timeout == 0: - # Peek without waiting - recv_function = functools.partial( - _canlib.canChannelPeekMessage, - self._channel_handle, - ctypes.byref(self._message), - ) - else: - # Wait if no message available - timeout = ( - constants.INFINITE - if (timeout is None or timeout < 0) - else int(timeout * 1000) - ) - recv_function = functools.partial( - _canlib.canChannelReadMessage, - self._channel_handle, - timeout, - ctypes.byref(self._message), - ) - - try: - recv_function() - except (VCITimeout, VCIRxQueueEmptyError): - # Ignore the 2 errors, overall timeout is handled by BusABC.recv - pass - else: - # See if we got a data or info/error messages - if self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_DATA: - data_received = True - elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_INFO: - log.info( - CAN_INFO_MESSAGES.get( - self._message.abData[0], - f"Unknown CAN info message code {self._message.abData[0]}", - ) - ) - elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR: - if self._message.uMsgInfo.Bytes.bFlags & constants.CAN_MSGFLAGS_OVR: - log.warning("CAN error: data overrun") - else: - log.warning( - CAN_ERROR_MESSAGES.get( - self._message.abData[0], - f"Unknown CAN error message code {self._message.abData[0]}", - ) - ) - log.warning( - "CAN message flags bAddFlags/bFlags2 0x%02X bflags 0x%02X", - self._message.uMsgInfo.Bytes.bAddFlags, - self._message.uMsgInfo.Bytes.bFlags, - ) - elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_TIMEOVR: - pass - else: - log.warning( - "Unexpected message info type 0x%X", - self._message.uMsgInfo.Bits.type, - ) - finally: - if not data_received: - # Check hard errors - status = structures.CANLINESTATUS() - _canlib.canControlGetStatus(self._control_handle, ctypes.byref(status)) - error_byte_1 = status.dwStatus & 0x0F - error_byte_2 = status.dwStatus & 0xF0 - if error_byte_1 > constants.CAN_STATUS_TXPEND: - # CAN_STATUS_OVRRUN = 0x02 # data overrun occurred - # CAN_STATUS_ERRLIM = 0x04 # error warning limit exceeded - # CAN_STATUS_BUSOFF = 0x08 # bus off status - if error_byte_1 & constants.CAN_STATUS_OVRRUN: - raise VCIError("Data overrun occurred") - elif error_byte_1 & constants.CAN_STATUS_ERRLIM: - raise VCIError("Error warning limit exceeded") - elif error_byte_1 & constants.CAN_STATUS_BUSOFF: - raise VCIError("Bus off status") - elif error_byte_2 > constants.CAN_STATUS_ININIT: - # CAN_STATUS_BUSCERR = 0x20 # bus coupling error - if error_byte_2 & constants.CAN_STATUS_BUSCERR: - raise VCIError("Bus coupling error") - - if not data_received: - # Timed out / can message type is not DATA - return None, True - - # The _message.dwTime is a 32bit tick value and will overrun, - # so expect to see the value restarting from 0 - rx_msg = Message( - timestamp=self._message.dwTime - / self._tick_resolution, # Relative time in s - is_remote_frame=bool(self._message.uMsgInfo.Bits.rtr), - is_extended_id=bool(self._message.uMsgInfo.Bits.ext), - arbitration_id=self._message.dwMsgId, - dlc=self._message.uMsgInfo.Bits.dlc, - data=self._message.abData[: self._message.uMsgInfo.Bits.dlc], - channel=self.channel, - ) - - return rx_msg, True - - def send(self, msg: Message, timeout: Optional[float] = None) -> None: - """ - Sends a message on the bus. The interface may buffer the message. - - :param msg: - The message to send. - :param timeout: - Timeout after some time. - :raise: - :class:CanTimeoutError - :class:CanOperationError - """ - # This system is not designed to be very efficient - message = structures.CANMSG() - message.uMsgInfo.Bits.type = constants.CAN_MSGTYPE_DATA - message.uMsgInfo.Bits.rtr = 1 if msg.is_remote_frame else 0 - message.uMsgInfo.Bits.ext = 1 if msg.is_extended_id else 0 - message.uMsgInfo.Bits.srr = 1 if self._receive_own_messages else 0 - message.dwMsgId = msg.arbitration_id - if msg.dlc: - message.uMsgInfo.Bits.dlc = msg.dlc - adapter = (ctypes.c_uint8 * len(msg.data)).from_buffer(msg.data) - ctypes.memmove(message.abData, adapter, len(msg.data)) - - if timeout: - _canlib.canChannelSendMessage( - self._channel_handle, int(timeout * 1000), message - ) - else: - _canlib.canChannelPostMessage(self._channel_handle, message) - # Want to log outgoing messages? - # log.log(self.RECV_LOGGING_LEVEL, "Sent: %s", message) - - def _send_periodic_internal( - self, - msgs: Union[Sequence[Message], Message], - period: float, - duration: Optional[float] = None, - modifier_callback: Optional[Callable[[Message], None]] = None, - ) -> CyclicSendTaskABC: - """Send a message using built-in cyclic transmit list functionality.""" - if modifier_callback is None: - if self._scheduler is None: - self._scheduler = HANDLE() - _canlib.canSchedulerOpen( - self._device_handle, self.channel, self._scheduler - ) - caps = structures.CANCAPABILITIES() - _canlib.canSchedulerGetCaps(self._scheduler, caps) - self._scheduler_resolution = caps.dwClockFreq / caps.dwCmsDivisor - _canlib.canSchedulerActivate(self._scheduler, constants.TRUE) - return CyclicSendTask( - self._scheduler, msgs, period, duration, self._scheduler_resolution - ) - - # fallback to thread based cyclic task - warnings.warn( - f"{self.__class__.__name__} falls back to a thread-based cyclic task, " - "when the `modifier_callback` argument is given." - ) - return BusABC._send_periodic_internal( - self, - msgs=msgs, - period=period, - duration=duration, - modifier_callback=modifier_callback, - ) - - def shutdown(self): - super().shutdown() - if self._scheduler is not None: - _canlib.canSchedulerClose(self._scheduler) - _canlib.canChannelClose(self._channel_handle) - _canlib.canControlStart(self._control_handle, constants.FALSE) - _canlib.canControlReset(self._control_handle) - _canlib.canControlClose(self._control_handle) - _canlib.vciDeviceClose(self._device_handle) - - @property - def state(self) -> BusState: - """ - Return the current state of the hardware - """ - status = structures.CANLINESTATUS() - _canlib.canControlGetStatus(self._control_handle, ctypes.byref(status)) - if status.bOpMode == constants.CAN_OPMODE_LISTONLY: - return BusState.PASSIVE - - error_byte_1 = status.dwStatus & 0x0F - # CAN_STATUS_BUSOFF = 0x08 # bus off status - if error_byte_1 & constants.CAN_STATUS_BUSOFF: - return BusState.ERROR - - error_byte_2 = status.dwStatus & 0xF0 - # CAN_STATUS_BUSCERR = 0x20 # bus coupling error - if error_byte_2 & constants.CAN_STATUS_BUSCERR: - raise BusState.ERROR - - return BusState.ACTIVE - - -# ~class IXXATBus(BusABC): --------------------------------------------------- - - -class CyclicSendTask(LimitedDurationCyclicSendTaskABC, RestartableCyclicTaskABC): - """A message in the cyclic transmit list.""" - - def __init__(self, scheduler, msgs, period, duration, resolution): - super().__init__(msgs, period, duration) - if len(self.messages) != 1: - raise ValueError( - "IXXAT Interface only supports periodic transmission of 1 element" - ) - - self._scheduler = scheduler - self._index = None - self._count = int(duration / period) if duration else 0 - - self._msg = structures.CANCYCLICTXMSG() - self._msg.wCycleTime = int(round(period * resolution)) - self._msg.dwMsgId = self.messages[0].arbitration_id - self._msg.uMsgInfo.Bits.type = constants.CAN_MSGTYPE_DATA - self._msg.uMsgInfo.Bits.ext = 1 if self.messages[0].is_extended_id else 0 - self._msg.uMsgInfo.Bits.rtr = 1 if self.messages[0].is_remote_frame else 0 - self._msg.uMsgInfo.Bits.dlc = self.messages[0].dlc - for i, b in enumerate(self.messages[0].data): - self._msg.abData[i] = b - self.start() - - def start(self): - """Start transmitting message (add to list if needed).""" - if self._index is None: - self._index = ctypes.c_uint32() - _canlib.canSchedulerAddMessage(self._scheduler, self._msg, self._index) - _canlib.canSchedulerStartMessage(self._scheduler, self._index, self._count) - - def pause(self): - """Pause transmitting message (keep it in the list).""" - _canlib.canSchedulerStopMessage(self._scheduler, self._index) - - def stop(self): - """Stop transmitting message (remove from list).""" - # Remove it completely instead of just stopping it to avoid filling up - # the list with permanently stopped messages - _canlib.canSchedulerRemMessage(self._scheduler, self._index) - self._index = None - - -def _format_can_status(status_flags: int): - """ - Format a status bitfield found in CAN_MSGTYPE_STATUS messages or in dwStatus - field in CANLINESTATUS. - - Valid states are defined in the CAN_STATUS_* constants in cantype.h - """ - states = [] - for flag, description in CAN_STATUS_FLAGS.items(): - if status_flags & flag: - states.append(description) - status_flags &= ~flag - - if status_flags: - states.append(f"unknown state 0x{status_flags:02x}") - - if states: - return "CAN status message: {}".format(", ".join(states)) - else: - return "Empty CAN status message" - - -def get_ixxat_hwids(): - """Get a list of hardware ids of all available IXXAT devices.""" - hwids = [] - device_handle = HANDLE() - device_info = structures.VCIDEVICEINFO() - - _canlib.vciEnumDeviceOpen(ctypes.byref(device_handle)) - while True: - try: - _canlib.vciEnumDeviceNext(device_handle, ctypes.byref(device_info)) - except StopIteration: - break - else: - hwids.append(device_info.UniqueHardwareId.AsChar.decode("ascii")) - _canlib.vciEnumDeviceClose(device_handle) - - return hwids diff --git a/can/interfaces/ixxat/canlib_vcinpl2.py b/can/interfaces/ixxat/canlib_vcinpl2.py deleted file mode 100644 index 2cac2aa8e..000000000 --- a/can/interfaces/ixxat/canlib_vcinpl2.py +++ /dev/null @@ -1,1129 +0,0 @@ -""" -Ctypes wrapper module for IXXAT Virtual CAN Interface V3 on win32 systems - -TODO: We could implement this interface such that setting other filters - could work when the initial filters were set to zero using the - software fallback. Or could the software filters even be changed - after the connection was opened? We need to document that bahaviour! - See also the NICAN interface. - -""" - -import ctypes -import functools -import logging -import sys -import time -import warnings -from typing import Callable, List, Optional, Sequence, Tuple, Union - -from can import ( - BusABC, - CanProtocol, - CyclicSendTaskABC, - LimitedDurationCyclicSendTaskABC, - Message, - RestartableCyclicTaskABC, -) -from can.ctypesutil import HANDLE, PHANDLE, CLibrary -from can.ctypesutil import HRESULT as ctypes_HRESULT -from can.exceptions import CanInitializationError, CanInterfaceNotImplementedError -from can.typechecking import AutoDetectedConfig -from can.util import deprecated_args_alias, dlc2len, len2dlc - -from . import constants, structures -from .exceptions import * - -__all__ = [ - "VCITimeout", - "VCIError", - "VCIBusOffError", - "VCIDeviceNotFoundError", - "IXXATBus", - "vciFormatError", -] - -log = logging.getLogger("can.ixxat") - -# Hack to have vciFormatError as a free function, see below -vciFormatError = None - -# main ctypes instance -_canlib = None -# TODO: Use ECI driver for linux -if sys.platform == "win32" or sys.platform == "cygwin": - try: - _canlib = CLibrary("vcinpl2.dll") - except Exception as e: - log.warning("Cannot load IXXAT vcinpl library: %s", e) -else: - # Will not work on other systems, but have it importable anyway for - # tests/sphinx - log.warning("IXXAT VCI library does not work on %s platform", sys.platform) - - -def __vciFormatErrorExtended( - library_instance: CLibrary, function: Callable, vret: int, args: Tuple -): - """Format a VCI error and attach failed function, decoded HRESULT and arguments - :param CLibrary library_instance: - Mapped instance of IXXAT vcinpl library - :param callable function: - Failed function - :param HRESULT vret: - HRESULT returned by vcinpl call - :param args: - Arbitrary arguments tuple - :return: - Formatted string - """ - # TODO: make sure we don't generate another exception - return "{} - arguments were {}".format( - __vciFormatError(library_instance, function, vret), args - ) - - -def __vciFormatError(library_instance: CLibrary, function: Callable, vret: int): - """Format a VCI error and attach failed function and decoded HRESULT - :param CLibrary library_instance: - Mapped instance of IXXAT vcinpl library - :param callable function: - Failed function - :param HRESULT vret: - HRESULT returned by vcinpl call - :return: - Formatted string - """ - buf = ctypes.create_string_buffer(constants.VCI_MAX_ERRSTRLEN) - ctypes.memset(buf, 0, constants.VCI_MAX_ERRSTRLEN) - library_instance.vciFormatError(vret, buf, constants.VCI_MAX_ERRSTRLEN) - return "function {} failed ({})".format( - function._name, buf.value.decode("utf-8", "replace") - ) - - -def __check_status(result: int, function: Callable, args: Tuple): - """ - Check the result of a vcinpl function call and raise appropriate exception - in case of an error. Used as errcheck function when mapping C functions - with ctypes. - :param result: - Function call numeric result - :param callable function: - Called function - :param args: - Arbitrary arguments tuple - :raise: - :class:VCITimeout - :class:VCIRxQueueEmptyError - :class:StopIteration - :class:VCIError - """ - if result == constants.VCI_E_TIMEOUT: - raise VCITimeout(f"Function {function._name} timed out") - elif result == constants.VCI_E_RXQUEUE_EMPTY: - raise VCIRxQueueEmptyError() - elif result == constants.VCI_E_NO_MORE_ITEMS: - raise StopIteration() - elif result == constants.VCI_E_ACCESSDENIED: - pass # not a real error, might happen if another program has initialized the bus - elif result != constants.VCI_OK: - raise VCIError(vciFormatError(function, result)) - - return result - - -try: - hresult_type = ctypes.c_ulong - # Map all required symbols and initialize library --------------------------- - # HRESULT VCIAPI vciInitialize ( void ); - _canlib.map_symbol("vciInitialize", hresult_type, (), __check_status) - - # void VCIAPI vciFormatError (HRESULT hrError, PCHAR pszText, UINT32 dwsize); - try: - _canlib.map_symbol( - "vciFormatError", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32) - ) - except ImportError: - _canlib.map_symbol( - "vciFormatErrorA", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32) - ) - _canlib.vciFormatError = _canlib.vciFormatErrorA - # Hack to have vciFormatError as a free function - vciFormatError = functools.partial(__vciFormatError, _canlib) - - # HRESULT VCIAPI vciEnumDeviceOpen( OUT PHANDLE hEnum ); - _canlib.map_symbol("vciEnumDeviceOpen", hresult_type, (PHANDLE,), __check_status) - # HRESULT VCIAPI vciEnumDeviceClose ( IN HANDLE hEnum ); - _canlib.map_symbol("vciEnumDeviceClose", hresult_type, (HANDLE,), __check_status) - # HRESULT VCIAPI vciEnumDeviceNext( IN HANDLE hEnum, OUT PVCIDEVICEINFO pInfo ); - _canlib.map_symbol( - "vciEnumDeviceNext", - hresult_type, - (HANDLE, structures.PVCIDEVICEINFO), - __check_status, - ) - - # HRESULT VCIAPI vciDeviceOpen( IN REFVCIID rVciid, OUT PHANDLE phDevice ); - _canlib.map_symbol( - "vciDeviceOpen", hresult_type, (structures.PVCIID, PHANDLE), __check_status - ) - # HRESULT vciDeviceClose( HANDLE hDevice ) - _canlib.map_symbol("vciDeviceClose", hresult_type, (HANDLE,), __check_status) - - # HRESULT VCIAPI canChannelOpen( IN HANDLE hDevice, IN UINT32 dwCanNo, IN BOOL fExclusive, OUT PHANDLE phCanChn ); - _canlib.map_symbol( - "canChannelOpen", - hresult_type, - (HANDLE, ctypes.c_uint32, ctypes.c_long, PHANDLE), - __check_status, - ) - # EXTERN_C HRESULT VCIAPI - # canChannelInitialize( IN HANDLE hCanChn, - # IN UINT16 wRxFifoSize, - # IN UINT16 wRxThreshold, - # IN UINT16 wTxFifoSize, - # IN UINT16 wTxThreshold, - # IN UINT32 dwFilterSize, - # IN UINT8 bFilterMode ); - _canlib.map_symbol( - "canChannelInitialize", - hresult_type, - ( - HANDLE, - ctypes.c_uint16, - ctypes.c_uint16, - ctypes.c_uint16, - ctypes.c_uint16, - ctypes.c_uint32, - ctypes.c_uint8, - ), - __check_status, - ) - # EXTERN_C HRESULT VCIAPI canChannelActivate( IN HANDLE hCanChn, IN BOOL fEnable ); - _canlib.map_symbol( - "canChannelActivate", hresult_type, (HANDLE, ctypes.c_long), __check_status - ) - # HRESULT canChannelClose( HANDLE hChannel ) - _canlib.map_symbol("canChannelClose", hresult_type, (HANDLE,), __check_status) - # EXTERN_C HRESULT VCIAPI canChannelReadMessage( IN HANDLE hCanChn, IN UINT32 dwMsTimeout, OUT PCANMSG2 pCanMsg ); - _canlib.map_symbol( - "canChannelReadMessage", - hresult_type, - (HANDLE, ctypes.c_uint32, structures.PCANMSG2), - __check_status, - ) - # HRESULT canChannelPeekMessage(HANDLE hChannel,PCANMSG2 pCanMsg ); - _canlib.map_symbol( - "canChannelPeekMessage", - hresult_type, - (HANDLE, structures.PCANMSG2), - __check_status, - ) - # HRESULT canChannelWaitTxEvent (HANDLE hChannel UINT32 dwMsTimeout ); - _canlib.map_symbol( - "canChannelWaitTxEvent", - hresult_type, - (HANDLE, ctypes.c_uint32), - __check_status, - ) - # HRESULT canChannelWaitRxEvent (HANDLE hChannel, UINT32 dwMsTimeout ); - _canlib.map_symbol( - "canChannelWaitRxEvent", - hresult_type, - (HANDLE, ctypes.c_uint32), - __check_status, - ) - # HRESULT canChannelPostMessage (HANDLE hChannel, PCANMSG2 pCanMsg ); - _canlib.map_symbol( - "canChannelPostMessage", - hresult_type, - (HANDLE, structures.PCANMSG2), - __check_status, - ) - # HRESULT canChannelSendMessage (HANDLE hChannel, UINT32 dwMsTimeout, PCANMSG2 pCanMsg ); - _canlib.map_symbol( - "canChannelSendMessage", - hresult_type, - (HANDLE, ctypes.c_uint32, structures.PCANMSG2), - __check_status, - ) - - # EXTERN_C HRESULT VCIAPI canControlOpen( IN HANDLE hDevice, IN UINT32 dwCanNo, OUT PHANDLE phCanCtl ); - _canlib.map_symbol( - "canControlOpen", - hresult_type, - (HANDLE, ctypes.c_uint32, PHANDLE), - __check_status, - ) - # EXTERN_C HRESULT VCIAPI - # canControlInitialize( IN HANDLE hCanCtl, - # IN UINT8 bOpMode, - # IN UINT8 bExMode, - # IN UINT8 bSFMode, - # IN UINT8 bEFMode, - # IN UINT32 dwSFIds, - # IN UINT32 dwEFIds, - # IN PCANBTP pBtpSDR, - # IN PCANBTP pBtpFDR ); - _canlib.map_symbol( - "canControlInitialize", - hresult_type, - ( - HANDLE, - ctypes.c_uint8, - ctypes.c_uint8, - ctypes.c_uint8, - ctypes.c_uint8, - ctypes.c_uint32, - ctypes.c_uint32, - structures.PCANBTP, - structures.PCANBTP, - ), - __check_status, - ) - # EXTERN_C HRESULT VCIAPI canControlClose( IN HANDLE hCanCtl ); - _canlib.map_symbol("canControlClose", hresult_type, (HANDLE,), __check_status) - # EXTERN_C HRESULT VCIAPI canControlReset( IN HANDLE hCanCtl ); - _canlib.map_symbol("canControlReset", hresult_type, (HANDLE,), __check_status) - # EXTERN_C HRESULT VCIAPI canControlStart( IN HANDLE hCanCtl, IN BOOL fStart ); - _canlib.map_symbol( - "canControlStart", hresult_type, (HANDLE, ctypes.c_long), __check_status - ) - # EXTERN_C HRESULT VCIAPI canControlGetStatus( IN HANDLE hCanCtl, OUT PCANLINESTATUS2 pStatus ); - _canlib.map_symbol( - "canControlGetStatus", - hresult_type, - (HANDLE, structures.PCANLINESTATUS2), - __check_status, - ) - # EXTERN_C HRESULT VCIAPI canControlGetCaps( IN HANDLE hCanCtl, OUT PCANCAPABILITIES2 pCanCaps ); - _canlib.map_symbol( - "canControlGetCaps", - hresult_type, - (HANDLE, structures.PCANCAPABILITIES2), - __check_status, - ) - # EXTERN_C HRESULT VCIAPI canControlSetAccFilter( IN HANDLE hCanCtl, IN BOOL fExtend, IN UINT32 dwCode, IN UINT32 dwMask ); - _canlib.map_symbol( - "canControlSetAccFilter", - hresult_type, - (HANDLE, ctypes.c_int, ctypes.c_uint32, ctypes.c_uint32), - __check_status, - ) - # EXTERN_C HRESULT canControlAddFilterIds (HANDLE hControl, BOOL fExtended, UINT32 dwCode, UINT32 dwMask); - _canlib.map_symbol( - "canControlAddFilterIds", - hresult_type, - (HANDLE, ctypes.c_int, ctypes.c_uint32, ctypes.c_uint32), - __check_status, - ) - # EXTERN_C HRESULT canControlRemFilterIds (HANDLE hControl, BOOL fExtendend, UINT32 dwCode, UINT32 dwMask ); - _canlib.map_symbol( - "canControlRemFilterIds", - hresult_type, - (HANDLE, ctypes.c_int, ctypes.c_uint32, ctypes.c_uint32), - __check_status, - ) - # EXTERN_C HRESULT canSchedulerOpen (HANDLE hDevice, UINT32 dwCanNo, PHANDLE phScheduler ); - _canlib.map_symbol( - "canSchedulerOpen", - hresult_type, - (HANDLE, ctypes.c_uint32, PHANDLE), - __check_status, - ) - # EXTERN_C HRESULT canSchedulerClose (HANDLE hScheduler ); - _canlib.map_symbol("canSchedulerClose", hresult_type, (HANDLE,), __check_status) - # EXTERN_C HRESULT canSchedulerGetCaps (HANDLE hScheduler, PCANCAPABILITIES2 pCaps ); - _canlib.map_symbol( - "canSchedulerGetCaps", - hresult_type, - (HANDLE, structures.PCANCAPABILITIES2), - __check_status, - ) - # EXTERN_C HRESULT canSchedulerActivate ( HANDLE hScheduler, BOOL fEnable ); - _canlib.map_symbol( - "canSchedulerActivate", hresult_type, (HANDLE, ctypes.c_int), __check_status - ) - # EXTERN_C HRESULT canSchedulerAddMessage (HANDLE hScheduler, PCANCYCLICTXMSG2 pMessage, PUINT32 pdwIndex ); - _canlib.map_symbol( - "canSchedulerAddMessage", - hresult_type, - (HANDLE, structures.PCANCYCLICTXMSG2, ctypes.POINTER(ctypes.c_uint32)), - __check_status, - ) - # EXTERN_C HRESULT canSchedulerRemMessage (HANDLE hScheduler, UINT32 dwIndex ); - _canlib.map_symbol( - "canSchedulerRemMessage", - hresult_type, - (HANDLE, ctypes.c_uint32), - __check_status, - ) - # EXTERN_C HRESULT canSchedulerStartMessage (HANDLE hScheduler, UINT32 dwIndex, UINT16 dwCount ); - _canlib.map_symbol( - "canSchedulerStartMessage", - hresult_type, - (HANDLE, ctypes.c_uint32, ctypes.c_uint16), - __check_status, - ) - # EXTERN_C HRESULT canSchedulerStopMessage (HANDLE hScheduler, UINT32 dwIndex ); - _canlib.map_symbol( - "canSchedulerStopMessage", - hresult_type, - (HANDLE, ctypes.c_uint32), - __check_status, - ) - _canlib.vciInitialize() -except AttributeError: - # In case _canlib == None meaning we're not on win32/no lib found - pass -except Exception as e: - log.warning("Could not initialize IXXAT VCI library: %s", e) -# --------------------------------------------------------------------------- - - -CAN_INFO_MESSAGES = { - constants.CAN_INFO_START: "CAN started", - constants.CAN_INFO_STOP: "CAN stopped", - constants.CAN_INFO_RESET: "CAN reset", -} - -CAN_ERROR_MESSAGES = { - constants.CAN_ERROR_STUFF: "CAN bit stuff error", - constants.CAN_ERROR_FORM: "CAN form error", - constants.CAN_ERROR_ACK: "CAN acknowledgment error", - constants.CAN_ERROR_BIT: "CAN bit error", - constants.CAN_ERROR_CRC: "CAN CRC error", - constants.CAN_ERROR_OTHER: "Other (unknown) CAN error", -} - -CAN_STATUS_FLAGS = { - constants.CAN_STATUS_TXPEND: "transmission pending", - constants.CAN_STATUS_OVRRUN: "data overrun occurred", - constants.CAN_STATUS_ERRLIM: "error warning limit exceeded", - constants.CAN_STATUS_BUSOFF: "bus off", - constants.CAN_STATUS_ININIT: "init mode active", - constants.CAN_STATUS_BUSCERR: "bus coupling error", -} -# ---------------------------------------------------------------------------- - - -class IXXATBus(BusABC): - """The CAN Bus implemented for the IXXAT interface. - - .. warning:: - - This interface does implement efficient filtering of messages, but - the filters have to be set in ``__init__`` using the ``can_filters`` parameter. - Using :meth:`~can.BusABC.set_filters` does not work. - - """ - - @deprecated_args_alias( - deprecation_start="4.0.0", - deprecation_end="5.0.0", - UniqueHardwareId="unique_hardware_id", - rxFifoSize="rx_fifo_size", - txFifoSize="tx_fifo_size", - ) - def __init__( - self, - channel: int, - can_filters=None, - receive_own_messages: int = False, - unique_hardware_id: Optional[int] = None, - extended: bool = True, - fd: bool = False, - rx_fifo_size: int = 1024, - tx_fifo_size: int = 128, - bitrate: int = 500000, - data_bitrate: int = 2000000, - sjw_abr: int = None, - tseg1_abr: int = None, - tseg2_abr: int = None, - sjw_dbr: int = None, - tseg1_dbr: int = None, - tseg2_dbr: int = None, - ssp_dbr: int = None, - **kwargs, - ): - """ - :param channel: - The Channel id to create this bus with. - - :param can_filters: - See :meth:`can.BusABC.set_filters`. - - :param receive_own_messages: - Enable self-reception of sent messages. - - :param unique_hardware_id: - unique_hardware_id to connect (optional, will use the first found if not supplied) - - :param extended: - Default True, enables the capability to use extended IDs. - - :param fd: - Default False, enables CAN-FD usage. - - :param rx_fifo_size: - Receive fifo size (default 1024) - - :param tx_fifo_size: - Transmit fifo size (default 128) - - :param bitrate: - Channel bitrate in bit/s - - :param data_bitrate: - Channel bitrate in bit/s (only in CAN-Fd if baudrate switch enabled). - - :param sjw_abr: - Bus timing value sample jump width (arbitration). - - :param tseg1_abr: - Bus timing value tseg1 (arbitration) - - :param tseg2_abr: - Bus timing value tseg2 (arbitration) - - :param sjw_dbr: - Bus timing value sample jump width (data) - - :param tseg1_dbr: - Bus timing value tseg1 (data). Only takes effect with fd and bitrate switch enabled. - - :param tseg2_dbr: - Bus timing value tseg2 (data). Only takes effect with fd and bitrate switch enabled. - - :param ssp_dbr: - Secondary sample point (data). Only takes effect with fd and bitrate switch enabled. - - """ - if _canlib is None: - raise CanInterfaceNotImplementedError( - "The IXXAT VCI library has not been initialized. Check the logs for more details." - ) - log.info("CAN Filters: %s", can_filters) - # Configuration options - self._receive_own_messages = receive_own_messages - # Usually comes as a string from the config file - channel = int(channel) - - if bitrate not in constants.CAN_BITRATE_PRESETS and ( - tseg1_abr is None or tseg2_abr is None or sjw_abr is None - ): - raise ValueError( - "To use bitrate {} (that has not predefined preset) is mandatory to use also parameters tseg1_abr, tseg2_abr and swj_abr".format( - bitrate - ) - ) - if data_bitrate not in constants.CAN_DATABITRATE_PRESETS and ( - tseg1_dbr is None or tseg2_dbr is None or sjw_dbr is None - ): - raise ValueError( - "To use data_bitrate {} (that has not predefined preset) is mandatory to use also parameters tseg1_dbr, tseg2_dbr and swj_dbr".format( - data_bitrate - ) - ) - - if rx_fifo_size <= 0: - raise ValueError("rx_fifo_size must be > 0") - - if tx_fifo_size <= 0: - raise ValueError("tx_fifo_size must be > 0") - - if channel < 0: - raise ValueError("channel number must be >= 0") - - self._device_handle = HANDLE() - self._device_info = structures.VCIDEVICEINFO() - self._control_handle = HANDLE() - self._channel_handle = HANDLE() - self._channel_capabilities = structures.CANCAPABILITIES2() - self._message = structures.CANMSG2() - self._payload = (ctypes.c_byte * 64)() - - # Search for supplied device - if unique_hardware_id is None: - log.info("Searching for first available device") - else: - log.info("Searching for unique HW ID %s", unique_hardware_id) - _canlib.vciEnumDeviceOpen(ctypes.byref(self._device_handle)) - while True: - try: - _canlib.vciEnumDeviceNext( - self._device_handle, ctypes.byref(self._device_info) - ) - except StopIteration as exc: - if unique_hardware_id is None: - raise VCIDeviceNotFoundError( - "No IXXAT device(s) connected or device(s) in use by other process(es)." - ) from exc - else: - raise VCIDeviceNotFoundError( - "Unique HW ID {} not connected or not available.".format( - unique_hardware_id - ) - ) from exc - else: - if (unique_hardware_id is None) or ( - self._device_info.UniqueHardwareId.AsChar - == bytes(unique_hardware_id, "ascii") - ): - break - else: - log.debug( - "Ignoring IXXAT with hardware id '%s'.", - self._device_info.UniqueHardwareId.AsChar.decode("ascii"), - ) - _canlib.vciEnumDeviceClose(self._device_handle) - - try: - _canlib.vciDeviceOpen( - ctypes.byref(self._device_info.VciObjectId), - ctypes.byref(self._device_handle), - ) - except Exception as exc: - raise CanInitializationError(f"Could not open device: {exc}") from exc - - log.info("Using unique HW ID %s", self._device_info.UniqueHardwareId.AsChar) - - log.info( - "Initializing channel %d in shared mode, %d rx buffers, %d tx buffers", - channel, - rx_fifo_size, - tx_fifo_size, - ) - - try: - _canlib.canChannelOpen( - self._device_handle, - channel, - constants.FALSE, - ctypes.byref(self._channel_handle), - ) - except Exception as exc: - raise CanInitializationError( - f"Could not open and initialize channel: {exc}" - ) from exc - - # Signal TX/RX events when at least one frame has been handled - _canlib.canChannelInitialize( - self._channel_handle, - rx_fifo_size, - 1, - tx_fifo_size, - 1, - 0, - constants.CAN_FILTER_PASS, - ) - _canlib.canChannelActivate(self._channel_handle, constants.TRUE) - - pBtpSDR = IXXATBus._canptb_build( - defaults=constants.CAN_BITRATE_PRESETS, - bitrate=bitrate, - tseg1=tseg1_abr, - tseg2=tseg2_abr, - sjw=sjw_abr, - ssp=0, - ) - pBtpFDR = IXXATBus._canptb_build( - defaults=constants.CAN_DATABITRATE_PRESETS, - bitrate=data_bitrate, - tseg1=tseg1_dbr, - tseg2=tseg2_dbr, - sjw=sjw_dbr, - ssp=ssp_dbr if ssp_dbr is not None else tseg1_dbr, - ) - - log.info( - "Initializing control %d with SDR={%s}, FDR={%s}", - channel, - pBtpSDR, - pBtpFDR, - ) - _canlib.canControlOpen( - self._device_handle, channel, ctypes.byref(self._control_handle) - ) - - _canlib.canControlGetCaps( - self._control_handle, ctypes.byref(self._channel_capabilities) - ) - - # check capabilities - bOpMode = constants.CAN_OPMODE_UNDEFINED - if ( - self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT - ) != 0: - # controller supports CAN_OPMODE_STANDARD and CAN_OPMODE_EXTENDED at the same time - bOpMode |= constants.CAN_OPMODE_STANDARD # enable both 11 bits reception - if extended: # parameter from configuration - bOpMode |= constants.CAN_OPMODE_EXTENDED # enable 29 bits reception - elif ( - self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT - ) != 0: - log.warning( - "Channel %d capabilities allow either basic or extended IDs, but not both. using %s according to parameter [extended=%s]", - channel, - "extended" if extended else "basic", - "True" if extended else "False", - ) - # controller supports either CAN_OPMODE_STANDARD or CAN_OPMODE_EXTENDED, but not both simultaneously - bOpMode |= ( - constants.CAN_OPMODE_EXTENDED - if extended - else constants.CAN_OPMODE_STANDARD - ) - - if ( # controller supports receiving error frames: - self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_ERRFRAME - ) != 0: - bOpMode |= constants.CAN_OPMODE_ERRFRAME - - bExMode = constants.CAN_EXMODE_DISABLED - self._can_protocol = CanProtocol.CAN_20 # default to standard CAN protocol - if fd: - if ( - self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_EXTDATA - ) != 0: - bExMode |= constants.CAN_EXMODE_EXTDATALEN - if ( - self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_FASTDATA - ) != 0: - bExMode |= constants.CAN_EXMODE_FASTDATA - self._can_protocol = ( - CanProtocol.CAN_FD - ) # set bus to CAN FD protocol once FD capability is verified - - _canlib.canControlInitialize( - self._control_handle, - bOpMode, - bExMode, - constants.CAN_FILTER_PASS, - constants.CAN_FILTER_PASS, - 0, - 0, - ctypes.byref(pBtpSDR), - ctypes.byref(pBtpFDR), - ) - - # With receive messages, this field contains the relative reception time of - # the message in ticks. The resolution of a tick can be calculated from the fields - # dwClockFreq and dwTscDivisor of the structure CANCAPABILITIES in accordance with the following formula: - # frequency [1/s] = dwClockFreq / dwTscDivisor - self._tick_resolution = ( - self._channel_capabilities.dwTscClkFreq - / self._channel_capabilities.dwTscDivisor - ) - - # Setup filters before starting the channel - if can_filters: - log.info("The IXXAT VCI backend is filtering messages") - # Disable every message coming in - for extended in (0, 1): - _canlib.canControlSetAccFilter( - self._control_handle, - extended, - constants.CAN_ACC_CODE_NONE, - constants.CAN_ACC_MASK_NONE, - ) - for can_filter in can_filters: - # Filters define what messages are accepted - code = int(can_filter["can_id"]) - mask = int(can_filter["can_mask"]) - extended = can_filter.get("extended", False) - _canlib.canControlAddFilterIds( - self._control_handle, 1 if extended else 0, code << 1, mask << 1 - ) - log.info("Accepting ID: 0x%X MASK: 0x%X", code, mask) - - # Start the CAN controller. Messages will be forwarded to the channel - _canlib.canControlStart(self._control_handle, constants.TRUE) - - # For cyclic transmit list. Set when .send_periodic() is first called - self._scheduler = None - self._scheduler_resolution = None - self.channel = channel - - # Usually you get back 3 messages like "CAN initialized" ecc... - # Clear the FIFO by filter them out with low timeout - for _ in range(rx_fifo_size): - try: - _canlib.canChannelReadMessage( - self._channel_handle, 0, ctypes.byref(self._message) - ) - except (VCITimeout, VCIRxQueueEmptyError): - break - - super().__init__(channel=channel, can_filters=None, **kwargs) - - @staticmethod - def _canptb_build(defaults, bitrate, tseg1, tseg2, sjw, ssp): - if bitrate in defaults: - d = defaults[bitrate] - if tseg1 is None: - tseg1 = d.wTS1 - if tseg2 is None: - tseg2 = d.wTS2 - if sjw is None: - sjw = d.wSJW - if ssp is None: - ssp = d.wTDO - dw_mode = d.dwMode - else: - dw_mode = 0 - - return structures.CANBTP( - dwMode=dw_mode, - dwBPS=bitrate, - wTS1=tseg1, - wTS2=tseg2, - wSJW=sjw, - wTDO=ssp, - ) - - def _inWaiting(self): - try: - _canlib.canChannelWaitRxEvent(self._channel_handle, 0) - except VCITimeout: - return 0 - else: - return 1 - - def flush_tx_buffer(self): - """Flushes the transmit buffer on the IXXAT""" - # TODO #64: no timeout? - _canlib.canChannelWaitTxEvent(self._channel_handle, constants.INFINITE) - - def _recv_internal(self, timeout): - """Read a message from IXXAT device.""" - - # TODO: handling CAN error messages? - data_received = False - - if timeout == 0: - # Peek without waiting - try: - _canlib.canChannelPeekMessage( - self._channel_handle, ctypes.byref(self._message) - ) - except (VCITimeout, VCIRxQueueEmptyError, VCIError): - # VCIError means no frame available (canChannelPeekMessage returned different from zero) - return None, True - else: - if self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_DATA: - data_received = True - else: - # Wait if no message available - if timeout is None or timeout < 0: - remaining_ms = constants.INFINITE - t0 = None - else: - timeout_ms = int(timeout * 1000) - remaining_ms = timeout_ms - t0 = time.perf_counter() - - while True: - try: - _canlib.canChannelReadMessage( - self._channel_handle, remaining_ms, ctypes.byref(self._message) - ) - except (VCITimeout, VCIRxQueueEmptyError): - # Ignore the 2 errors, the timeout is handled manually with the perf_counter() - pass - else: - # See if we got a data or info/error messages - if self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_DATA: - data_received = True - break - elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_INFO: - log.info( - CAN_INFO_MESSAGES.get( - self._message.abData[0], - f"Unknown CAN info message code {self._message.abData[0]}", - ) - ) - - elif ( - self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR - ): - log.warning( - CAN_ERROR_MESSAGES.get( - self._message.abData[0], - f"Unknown CAN error message code {self._message.abData[0]}", - ) - ) - - elif ( - self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_STATUS - ): - log.info(_format_can_status(self._message.abData[0])) - if self._message.abData[0] & constants.CAN_STATUS_BUSOFF: - raise VCIBusOffError() - - elif ( - self._message.uMsgInfo.Bits.type - == constants.CAN_MSGTYPE_TIMEOVR - ): - pass - else: - log.warning("Unexpected message info type") - - if t0 is not None: - remaining_ms = timeout_ms - int((time.perf_counter() - t0) * 1000) - if remaining_ms < 0: - break - - if not data_received: - # Timed out / can message type is not DATA - return None, True - - data_len = dlc2len(self._message.uMsgInfo.Bits.dlc) - # The _message.dwTime is a 32bit tick value and will overrun, - # so expect to see the value restarting from 0 - rx_msg = Message( - timestamp=self._message.dwTime - / self._tick_resolution, # Relative time in s - is_remote_frame=bool(self._message.uMsgInfo.Bits.rtr), - is_fd=bool(self._message.uMsgInfo.Bits.edl), - is_rx=True, - is_error_frame=bool( - self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR - ), - bitrate_switch=bool(self._message.uMsgInfo.Bits.fdr), - error_state_indicator=bool(self._message.uMsgInfo.Bits.esi), - is_extended_id=bool(self._message.uMsgInfo.Bits.ext), - arbitration_id=self._message.dwMsgId, - dlc=data_len, - data=self._message.abData[:data_len], - channel=self.channel, - ) - - return rx_msg, True - - def send(self, msg: Message, timeout: Optional[float] = None) -> None: - """ - Sends a message on the bus. The interface may buffer the message. - - :param msg: - The message to send. - :param timeout: - Timeout after some time. - :raise: - :class:CanTimeoutError - :class:CanOperationError - """ - # This system is not designed to be very efficient - message = structures.CANMSG2() - message.uMsgInfo.Bits.type = ( - constants.CAN_MSGTYPE_ERROR - if msg.is_error_frame - else constants.CAN_MSGTYPE_DATA - ) - message.uMsgInfo.Bits.rtr = 1 if msg.is_remote_frame else 0 - message.uMsgInfo.Bits.ext = 1 if msg.is_extended_id else 0 - message.uMsgInfo.Bits.srr = 1 if self._receive_own_messages else 0 - message.uMsgInfo.Bits.fdr = 1 if msg.bitrate_switch else 0 - message.uMsgInfo.Bits.esi = 1 if msg.error_state_indicator else 0 - message.uMsgInfo.Bits.edl = 1 if msg.is_fd else 0 - message.dwMsgId = msg.arbitration_id - if msg.dlc: # this dlc means number of bytes of payload - message.uMsgInfo.Bits.dlc = len2dlc(msg.dlc) - data_len_dif = msg.dlc - len(msg.data) - data = msg.data + bytearray( - [0] * data_len_dif - ) # pad with zeros until required length - adapter = (ctypes.c_uint8 * msg.dlc).from_buffer(data) - ctypes.memmove(message.abData, adapter, msg.dlc) - - if timeout: - _canlib.canChannelSendMessage( - self._channel_handle, int(timeout * 1000), message - ) - - else: - _canlib.canChannelPostMessage(self._channel_handle, message) - - def _send_periodic_internal( - self, - msgs: Union[Sequence[Message], Message], - period: float, - duration: Optional[float] = None, - modifier_callback: Optional[Callable[[Message], None]] = None, - ) -> CyclicSendTaskABC: - """Send a message using built-in cyclic transmit list functionality.""" - if modifier_callback is None: - if self._scheduler is None: - self._scheduler = HANDLE() - _canlib.canSchedulerOpen( - self._device_handle, self.channel, self._scheduler - ) - caps = structures.CANCAPABILITIES2() - _canlib.canSchedulerGetCaps(self._scheduler, caps) - self._scheduler_resolution = ( - caps.dwCmsClkFreq / caps.dwCmsDivisor - ) # TODO: confirm - _canlib.canSchedulerActivate(self._scheduler, constants.TRUE) - return CyclicSendTask( - self._scheduler, msgs, period, duration, self._scheduler_resolution - ) - - # fallback to thread based cyclic task - warnings.warn( - f"{self.__class__.__name__} falls back to a thread-based cyclic task, " - "when the `modifier_callback` argument is given." - ) - return BusABC._send_periodic_internal( - self, - msgs=msgs, - period=period, - duration=duration, - modifier_callback=modifier_callback, - ) - - def shutdown(self): - super().shutdown() - if self._scheduler is not None: - _canlib.canSchedulerClose(self._scheduler) - _canlib.canChannelClose(self._channel_handle) - _canlib.canControlStart(self._control_handle, constants.FALSE) - _canlib.canControlClose(self._control_handle) - _canlib.vciDeviceClose(self._device_handle) - - -class CyclicSendTask(LimitedDurationCyclicSendTaskABC, RestartableCyclicTaskABC): - """A message in the cyclic transmit list.""" - - def __init__(self, scheduler, msgs, period, duration, resolution): - super().__init__(msgs, period, duration) - if len(self.messages) != 1: - raise ValueError( - "IXXAT Interface only supports periodic transmission of 1 element" - ) - - self._scheduler = scheduler - self._index = None - self._count = int(duration / period) if duration else 0 - - self._msg = structures.CANCYCLICTXMSG2() - self._msg.wCycleTime = int(round(period * resolution)) - self._msg.dwMsgId = self.messages[0].arbitration_id - self._msg.uMsgInfo.Bits.type = constants.CAN_MSGTYPE_DATA - self._msg.uMsgInfo.Bits.ext = 1 if self.messages[0].is_extended_id else 0 - self._msg.uMsgInfo.Bits.rtr = 1 if self.messages[0].is_remote_frame else 0 - self._msg.uMsgInfo.Bits.dlc = self.messages[0].dlc - for i, b in enumerate(self.messages[0].data): - self._msg.abData[i] = b - self.start() - - def start(self): - """Start transmitting message (add to list if needed).""" - if self._index is None: - self._index = ctypes.c_uint32() - _canlib.canSchedulerAddMessage(self._scheduler, self._msg, self._index) - _canlib.canSchedulerStartMessage(self._scheduler, self._index, self._count) - - def pause(self): - """Pause transmitting message (keep it in the list).""" - _canlib.canSchedulerStopMessage(self._scheduler, self._index) - - def stop(self): - """Stop transmitting message (remove from list).""" - # Remove it completely instead of just stopping it to avoid filling up - # the list with permanently stopped messages - _canlib.canSchedulerRemMessage(self._scheduler, self._index) - self._index = None - - -def _format_can_status(status_flags: int): - """ - Format a status bitfield found in CAN_MSGTYPE_STATUS messages or in dwStatus - field in CANLINESTATUS. - - Valid states are defined in the CAN_STATUS_* constants in cantype.h - """ - states = [] - for flag, description in CAN_STATUS_FLAGS.items(): - if status_flags & flag: - states.append(description) - status_flags &= ~flag - - if status_flags: - states.append(f"unknown state 0x{status_flags:02x}") - - if states: - return "CAN status message: {}".format(", ".join(states)) - else: - return "Empty CAN status message" - - -def get_ixxat_hwids(): - """Get a list of hardware ids of all available IXXAT devices.""" - hwids = [] - device_handle = HANDLE() - device_info = structures.VCIDEVICEINFO() - - _canlib.vciEnumDeviceOpen(ctypes.byref(device_handle)) - while True: - try: - _canlib.vciEnumDeviceNext(device_handle, ctypes.byref(device_info)) - except StopIteration: - break - else: - hwids.append(device_info.UniqueHardwareId.AsChar.decode("ascii")) - _canlib.vciEnumDeviceClose(device_handle) - - return hwids - - -def _detect_available_configs() -> List[AutoDetectedConfig]: - config_list = [] # list in wich to store the resulting bus kwargs - - # used to detect HWID - device_handle = HANDLE() - device_info = structures.VCIDEVICEINFO() - - # used to attempt to open channels - channel_handle = HANDLE() - device_handle2 = HANDLE() - - try: - _canlib.vciEnumDeviceOpen(ctypes.byref(device_handle)) - while True: - try: - _canlib.vciEnumDeviceNext(device_handle, ctypes.byref(device_info)) - except StopIteration: - break - else: - hwid = device_info.UniqueHardwareId.AsChar.decode("ascii") - _canlib.vciDeviceOpen( - ctypes.byref(device_info.VciObjectId), - ctypes.byref(device_handle2), - ) - for channel in range(4): - try: - _canlib.canChannelOpen( - device_handle2, - channel, - constants.FALSE, - ctypes.byref(channel_handle), - ) - except Exception: - # Array outside of bounds error == accessing a channel not in the hardware - break - else: - _canlib.canChannelClose(channel_handle) - config_list.append( - { - "interface": "ixxat", - "channel": channel, - "unique_hardware_id": hwid, - } - ) - _canlib.vciDeviceClose(device_handle2) - _canlib.vciEnumDeviceClose(device_handle) - except AttributeError: - pass # _canlib is None in the CI tests -> return a blank list - - return config_list diff --git a/can/interfaces/ixxat/constants.py b/can/interfaces/ixxat/constants.py index 82a2f9bfa..ce07f8757 100644 --- a/can/interfaces/ixxat/constants.py +++ b/can/interfaces/ixxat/constants.py @@ -269,3 +269,27 @@ dwMode=0, dwBPS=10000000, wTS1=300, wTS2=100, wSJW=100, wTDO=200 ), # SP = 75,0% } + +CAN_INFO_MESSAGES = { + CAN_INFO_START: "CAN started", + CAN_INFO_STOP: "CAN stopped", + CAN_INFO_RESET: "CAN reset", +} + +CAN_ERROR_MESSAGES = { + CAN_ERROR_STUFF: "CAN bit stuff error", + CAN_ERROR_FORM: "CAN form error", + CAN_ERROR_ACK: "CAN acknowledgment error", + CAN_ERROR_BIT: "CAN bit error", + CAN_ERROR_CRC: "CAN CRC error", + CAN_ERROR_OTHER: "Other (unknown) CAN error", +} + +CAN_STATUS_FLAGS = { + CAN_STATUS_TXPEND: "transmission pending", + CAN_STATUS_OVRRUN: "data overrun occurred", + CAN_STATUS_ERRLIM: "error warning limit exceeded", + CAN_STATUS_BUSOFF: "bus off", + CAN_STATUS_ININIT: "init mode active", + CAN_STATUS_BUSCERR: "bus coupling error", +} From e0505f6da0e9a59ca96a9e64627377e6ec3eb952 Mon Sep 17 00:00:00 2001 From: MattWoodhead Date: Tue, 6 Jun 2023 23:40:47 +0100 Subject: [PATCH 05/15] Fix issues identified in hardware testing --- can/interfaces/ixxat/canlib.py | 65 ++++++++++++++------- can/interfaces/ixxat/structures.py | 91 ++++++++---------------------- doc/interfaces/ixxat.rst | 61 +++++++++++++------- 3 files changed, 107 insertions(+), 110 deletions(-) diff --git a/can/interfaces/ixxat/canlib.py b/can/interfaces/ixxat/canlib.py index a2b6c4494..210a7565e 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/can/interfaces/ixxat/canlib.py @@ -31,12 +31,11 @@ from can.ctypesutil import HANDLE, PHANDLE, CLibrary from can.ctypesutil import HRESULT as ctypes_HRESULT from can.exceptions import CanInitializationError, CanInterfaceNotImplementedError +from can.interfaces.ixxat import constants, structures +from can.interfaces.ixxat.exceptions import * from can.typechecking import AutoDetectedConfig, CanFilters from can.util import deprecated_args_alias, dlc2len, len2dlc -from can.interfaces.ixxat import constants, structures -from .exceptions import * - __all__ = [ "VCITimeout", "VCIError", @@ -423,8 +422,8 @@ def __init__( fd: Optional[bool] = False, rx_fifo_size: Optional[int] = None, tx_fifo_size: Optional[int] = None, - bitrate: Optional[int] = 500000, - data_bitrate: Optional[int] = 500000, + bitrate: Optional[int] = 500_000, + data_bitrate: Optional[int] = 2_000_000, timing: Optional[Union[BitTiming, BitTimingFd]] = None, **kwargs, ): @@ -469,9 +468,9 @@ def __init__( :param timing: Optional :class:`~can.BitTiming` or :class:`~can.BitTimingFd` instance to use for custom bit timing setting. The `f_clock` value of the timing - instance must be set to 40_000_000 (40MHz). - If this parameter is provided, it takes precedence over all other - timing-related parameters like `bitrate`, `fd_bitrate` and `fd`. + instance must be set to the appropriate value for the interface. + If this parameter is provided, it takes precedence over all other optional + timing-related parameters like `bitrate`, `data_bitrate` and `fd`. """ if _canlib is None: @@ -525,6 +524,7 @@ def __init__( self._channel_handle = HANDLE() self._channel_capabilities = structures.CANCAPABILITIES2() self._message = structures.CANMSG2() + self._bus_load_calculation = False if fd: self._payload = (ctypes.c_byte * 64)() else: @@ -645,6 +645,11 @@ def __init__( ) != 0: bOpMode |= constants.CAN_OPMODE_ERRFRAME + if ( # controller supports receiving error frames: + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_BUSLOAD + ) != 0: + self._bus_load_calculation = True + bExMode = constants.CAN_EXMODE_DISABLED self._can_protocol = CanProtocol.CAN_20 # default to standard CAN protocol if fd: @@ -654,8 +659,8 @@ def __init__( bExMode |= constants.CAN_EXMODE_EXTDATALEN else: raise CanInitializationError( - "The interface %s does not support extended data frames (FD)" % - self._device_info.UniqueHardwareId.AsChar.decode("ascii"), + "The interface %s does not support extended data frames (FD)" + % self._device_info.UniqueHardwareId.AsChar.decode("ascii"), ) if ( self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_FASTDATA @@ -663,8 +668,8 @@ def __init__( bExMode |= constants.CAN_EXMODE_FASTDATA else: raise CanInitializationError( - "The interface %s does not support fast data rates (FD)" % - self._device_info.UniqueHardwareId.AsChar.decode("ascii"), + "The interface %s does not support fast data rates (FD)" + % self._device_info.UniqueHardwareId.AsChar.decode("ascii"), ) # set bus to CAN FD protocol once FD capability is verified self._can_protocol = CanProtocol.CAN_FD @@ -696,7 +701,7 @@ def __init__( else: try: timing = BitTimingFd.from_sample_point( - f_clock=self._channel_capabilities.dwCanClockFreq, + f_clock=self._channel_capabilities.dwCanClkFreq, nom_bitrate=bitrate, nom_sample_point=80, data_bitrate=data_bitrate, @@ -722,10 +727,10 @@ def __init__( pBtpSDR = IXXATBus._canptb_build( defaults=constants.CAN_BITRATE_PRESETS, - bitrate=timing.bitrate, - tseg1=timing.tseg1, - tseg2=timing.tseg2, - sjw=timing.sjw, + bitrate=timing.nom_bitrate, + tseg1=timing.nom_tseg1, + tseg2=timing.nom_tseg2, + sjw=timing.nom_sjw, ssp=0, ) pBtpFDR = IXXATBus._canptb_build( @@ -943,7 +948,6 @@ def _recv_internal(self, timeout): return rx_msg, True - def send(self, msg: Message, timeout: Optional[float] = None) -> None: """ Sends a message on the bus. The interface may buffer the message. @@ -1024,7 +1028,6 @@ def _send_periodic_internal( modifier_callback=modifier_callback, ) - def shutdown(self): super().shutdown() if self._scheduler is not None: @@ -1034,12 +1037,33 @@ def shutdown(self): _canlib.canControlClose(self._control_handle) _canlib.vciDeviceClose(self._device_handle) + @property + def clock_frequency(self) -> int: + """ + :return: The can clock frequency of the attached adapter (e.g. for use in BitTiming) + :rtype: int + """ + return self._channel_capabilities.dwCanClkFreq + + @property + def bus_load(self) -> Union[int, None]: + """ + :return: The Bus Load in % (0 - 100) if the adapter is capable of measuring it. Otherwise returns None. + :rtype: Union[int, None] + """ + if self._bus_load_calculation: + status = structures.CANLINESTATUS2() + _canlib.canControlGetStatus(self._control_handle, ctypes.byref(status)) + return status.bBusLoad + else: + warnings.warn("The current adapter does not support bus load measurement") + @property def state(self) -> BusState: """ Return the current state of the hardware """ - status = structures.CANLINESTATUS() + status = structures.CANLINESTATUS2() _canlib.canControlGetStatus(self._control_handle, ctypes.byref(status)) if status.bOpMode == constants.CAN_OPMODE_LISTONLY: return BusState.PASSIVE @@ -1058,7 +1082,6 @@ def state(self) -> BusState: @staticmethod def _detect_available_configs() -> List[AutoDetectedConfig]: - config_list = [] # list in wich to store the resulting bus kwargs # used to detect HWID diff --git a/can/interfaces/ixxat/structures.py b/can/interfaces/ixxat/structures.py index 419a52973..101a02c8b 100644 --- a/can/interfaces/ixxat/structures.py +++ b/can/interfaces/ixxat/structures.py @@ -68,51 +68,6 @@ def __str__(self): PVCIDEVICEINFO = ctypes.POINTER(VCIDEVICEINFO) -class CANLINESTATUS(ctypes.Structure): - _fields_ = [ - # current CAN operating mode. Value is a logical combination of - # one or more CAN_OPMODE_xxx constants - ("bOpMode", ctypes.c_uint8), - ("bBtReg0", ctypes.c_uint8), # current bus timing register 0 value - ("bBtReg1", ctypes.c_uint8), # current bus timing register 1 value - ("bBusLoad", ctypes.c_uint8), # average bus load in percent (0..100) - ("dwStatus", ctypes.c_uint32), # status of the CAN controller (see CAN_STATUS_) - ] - - -PCANLINESTATUS = ctypes.POINTER(CANLINESTATUS) - - -class CANCHANSTATUS(ctypes.Structure): - _fields_ = [ - ("sLineStatus", CANLINESTATUS), # current CAN line status - ("fActivated", ctypes.c_uint32), # TRUE if the channel is activated - ("fRxOverrun", ctypes.c_uint32), # TRUE if receive FIFO overrun occurred - ("bRxFifoLoad", ctypes.c_uint8), # receive FIFO load in percent (0..100) - ("bTxFifoLoad", ctypes.c_uint8), # transmit FIFO load in percent (0..100) - ] - - -PCANCHANSTATUS = ctypes.POINTER(CANCHANSTATUS) - - -class CANCAPABILITIES(ctypes.Structure): - _fields_ = [ - ("wCtrlType", ctypes.c_uint16), - ("wBusCoupling", ctypes.c_uint16), - ("dwFeatures", ctypes.c_uint32), - ("dwClockFreq", ctypes.c_uint32), - ("dwTscDivisor", ctypes.c_uint32), - ("dwCmsDivisor", ctypes.c_uint32), - ("dwCmsMaxTicks", ctypes.c_uint32), - ("dwDtxDivisor", ctypes.c_uint32), - ("dwDtxMaxTicks", ctypes.c_uint32), - ] - - -PCANCAPABILITIES = ctypes.POINTER(CANCAPABILITIES) - - class CANMSGINFO(ctypes.Union): class Bytes(ctypes.Structure): _fields_ = [ @@ -152,27 +107,6 @@ class Bits(ctypes.Structure): PCANMSGINFO = ctypes.POINTER(CANMSGINFO) -class CANMSG(ctypes.Structure): - _fields_ = [ - ("dwTime", ctypes.c_uint32), - # CAN ID of the message in Intel format (aligned right) without RTR bit. - ("dwMsgId", ctypes.c_uint32), - ("uMsgInfo", CANMSGINFO), - ("abData", ctypes.c_uint8 * 8), - ] - - def __str__(self) -> str: - return """ID: 0x{:04x}{} DLC: {:02d} DATA: {}""".format( - self.dwMsgId, - "[RTR]" if self.uMsgInfo.Bits.rtr else "", - self.uMsgInfo.Bits.dlc, - memoryview(self.abData)[: self.uMsgInfo.Bits.dlc].hex(sep=" "), - ) - - -PCANMSG = ctypes.POINTER(CANMSG) - - class CANCYCLICTXMSG(ctypes.Structure): _fields_ = [ ("wCycleTime", ctypes.c_uint16), @@ -265,8 +199,8 @@ class CANLINESTATUS2(ctypes.Structure): ("bExMode", ctypes.c_uint8), # current CAN extended operating mode ("bBusLoad", ctypes.c_uint8), # average bus load in percent (0..100) ("bReserved", ctypes.c_uint8), # reserved set to 0 - ("sBtpSdr", ctypes.c_uint8), # standard bit rate timing - ("sBtpFdr", ctypes.c_uint8), # fast data bit rate timing + ("sBtpSdr", CANBTP), # standard bit rate timing + ("sBtpFdr", CANBTP), # fast data bit rate timing ("dwStatus", ctypes.c_uint32), # status of the CAN controller (see CAN_STATUS_) ] @@ -274,6 +208,19 @@ class CANLINESTATUS2(ctypes.Structure): PCANLINESTATUS2 = ctypes.POINTER(CANLINESTATUS2) +class CANCHANSTATUS2(ctypes.Structure): + _fields_ = [ + ("sLineStatus", CANLINESTATUS2), # current CAN line status + ("fActivated", ctypes.c_uint8), # TRUE if the channel is activated + ("fRxOverrun", ctypes.c_uint8), # TRUE if receive FIFO overrun occurred + ("bRxFifoLoad", ctypes.c_uint8), # receive FIFO load in percent (0..100) + ("bTxFifoLoad", ctypes.c_uint8), # transmit FIFO load in percent (0..100) + ] + + +PCANCHANSTATUS2 = ctypes.POINTER(CANCHANSTATUS2) + + class CANMSG2(ctypes.Structure): _fields_ = [ ("dwTime", ctypes.c_uint32), # time stamp for receive message @@ -283,6 +230,14 @@ class CANMSG2(ctypes.Structure): ("abData", ctypes.c_uint8 * 64), # message data ] + def __str__(self) -> str: + return """ID: 0x{:04x}{} DLC: {:02d} DATA: {}""".format( + self.dwMsgId, + "[RTR]" if self.uMsgInfo.Bits.rtr else "", + self.uMsgInfo.Bits.dlc, + memoryview(self.abData)[: self.uMsgInfo.Bits.dlc].hex(sep=" "), + ) + PCANMSG2 = ctypes.POINTER(CANMSG2) diff --git a/doc/interfaces/ixxat.rst b/doc/interfaces/ixxat.rst index f73a01036..978d4b525 100644 --- a/doc/interfaces/ixxat.rst +++ b/doc/interfaces/ixxat.rst @@ -3,7 +3,9 @@ IXXAT Virtual Communication Interface ===================================== -Interface to `IXXAT `__ Virtual Communication Interface V3 SDK. Works on Windows. +Interface to `IXXAT `__ Virtual Communication Interface V4 SDK. Works on Windows. +Note that python-can version 4.2.1 and earlier implemented the V3 SDK for non-FD devices. Python-can 4.2.2+ +uses the V4 SDK for all devices. The Linux ECI SDK is currently unsupported, however on Linux some devices are supported with :doc:`socketcan`. @@ -34,6 +36,10 @@ module, while the following parameters are optional and are interpreted by IXXAT * ``tx_fifo_size`` (default 16 for CAN, 128 for CAN-FD) Number of TX mailboxes. * ``bitrate`` (default 500000) Channel bitrate. * ``data_bitrate`` (defaults to 2Mbps) Channel data bitrate (only canfd, to use when message bitrate_switch is used). +* ``timing`` (optional) BitTiming class. If this argument is provided, the bitrate and data_bitrate parameters are overridden. + +The following deprecated parameters will be removed in python-can version 5.0.0. + * ``sjw_abr`` (optional, only canfd) Bus timing value sample jump width (arbitration). * ``tseg1_abr`` (optional, only canfd) Bus timing value tseg1 (arbitration). * ``tseg2_abr`` (optional, only canfd) Bus timing value tseg2 (arbitration). @@ -42,6 +48,10 @@ module, while the following parameters are optional and are interpreted by IXXAT * ``tseg2_dbr`` (optional, only used if baudrate switch enabled) Bus timing value tseg2 (data). * ``ssp_dbr`` (optional, only used if baudrate switch enabled) Secondary sample point (data). +timing +------ + + Filtering @@ -56,17 +66,41 @@ VCI documentation, section "Message filters" for more info. List available devices ---------------------- -In case you have connected multiple IXXAT devices, you have to select them by using their unique hardware id. -To get a list of all connected IXXAT you can use the function ``get_ixxat_hwids()`` as demonstrated below: +In case you have connected multiple IXXAT devices, you have to select them by using their unique hardware id. +The function :meth:`~can.detect_available_configs` can be used to generate a list of :class:`~can.BusABC` constructors +(including the channel number and unique hardware ID number for the connected devices). .. testsetup:: ixxat + from unittest.mock import Mock + import can + assert hasattr(can, "detect_available_configs") + can.detect_available_configs = Mock( + "interface", + return_value=[{'interface': 'ixxat', 'channel': 0, 'unique_hardware_id': 'HW441489'}, {'interface': 'ixxat', 'channel': 0, 'unique_hardware_id': 'HW107422'}, {'interface': 'ixxat', 'channel': 1, 'unique_hardware_id': 'HW107422'}], + ) + + .. doctest:: ixxat + + >>> import can + >>> configs = can.detect_available_configs("ixxat") + >>> for config in configs: + ... print(config) + {'interface': 'ixxat', 'channel': 0, 'unique_hardware_id': 'HW441489'} + {'interface': 'ixxat', 'channel': 0, 'unique_hardware_id': 'HW107422'} + {'interface': 'ixxat', 'channel': 1, 'unique_hardware_id': 'HW107422'} + + +You may also get a list of all connected IXXAT devices using the function ``get_ixxat_hwids()`` as demonstrated below: + + .. testsetup:: ixxat2 + from unittest.mock import Mock import can.interfaces.ixxat assert hasattr(can.interfaces.ixxat, "get_ixxat_hwids") can.interfaces.ixxat.get_ixxat_hwids = Mock(side_effect=lambda: ['HW441489', 'HW107422']) - .. doctest:: ixxat + .. doctest:: ixxat2 >>> from can.interfaces.ixxat import get_ixxat_hwids >>> for hwid in get_ixxat_hwids(): @@ -81,25 +115,9 @@ Bus .. autoclass:: can.interfaces.ixxat.IXXATBus :members: -Implementation based on vcinpl.dll -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. autoclass:: can.interfaces.ixxat.canlib_vcinpl.IXXATBus - :members: - .. autoclass:: can.interfaces.ixxat.canlib_vcinpl.CyclicSendTask :members: -Implementation based on vcinpl2.dll -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. autoclass:: can.interfaces.ixxat.canlib_vcinpl2.IXXATBus - :members: - -.. autoclass:: can.interfaces.ixxat.canlib_vcinpl2.CyclicSendTask - :members: - - Internals --------- @@ -115,5 +133,6 @@ explicitly instantiated by the caller. - ``send()`` is not blocking but may raise a VCIError if the TX FIFO is full RX and TX FIFO sizes are configurable with ``rx_fifo_size`` and ``tx_fifo_size`` -options, defaulting to 16 for both. +options, defaulting to 16 for both for non-FD communication. For FD communication, +``rx_fifo_size`` defaults to 1024, and ``tx_fifo_size`` defaults to 128. From 2acbbac20cd7e0998a74f19911c5b6348f3ab853 Mon Sep 17 00:00:00 2001 From: MattWoodhead Date: Sun, 11 Jun 2023 21:55:05 +0100 Subject: [PATCH 06/15] Add hardware tests --- can/interfaces/ixxat/__init__.py | 7 +- can/interfaces/ixxat/canlib.py | 414 ++++++++++++++--------------- can/interfaces/ixxat/constants.py | 62 +++-- can/interfaces/ixxat/structures.py | 46 ++++ doc/interfaces/ixxat.rst | 24 +- test/test_interface_ixxat.py | 188 +++++++++++-- 6 files changed, 473 insertions(+), 268 deletions(-) diff --git a/can/interfaces/ixxat/__init__.py b/can/interfaces/ixxat/__init__.py index e4c7564cb..30b6a1759 100644 --- a/can/interfaces/ixxat/__init__.py +++ b/can/interfaces/ixxat/__init__.py @@ -5,14 +5,13 @@ """ __all__ = [ - "IXXATBus", "canlib", - "canlib_vcinpl", - "canlib_vcinpl2", "constants", + "CyclicSendTask" "exceptions", "get_ixxat_hwids", + "IXXATBus", "structures", ] -from can.interfaces.ixxat.canlib import IXXATBus, get_ixxat_hwids +from can.interfaces.ixxat.canlib import CyclicSendTask, get_ixxat_hwids, IXXATBus diff --git a/can/interfaces/ixxat/canlib.py b/can/interfaces/ixxat/canlib.py index 210a7565e..a770055d8 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/can/interfaces/ixxat/canlib.py @@ -64,9 +64,7 @@ log.warning("IXXAT VCI library does not work on %s platform", sys.platform) -def __vciFormatErrorExtended( - library_instance: CLibrary, function: Callable, vret: int, args: Tuple -): +def __vciFormatErrorExtended(library_instance: CLibrary, function: Callable, vret: int, args: Tuple): """Format a VCI error and attach failed function, decoded HRESULT and arguments :param CLibrary library_instance: Mapped instance of IXXAT vcinpl library @@ -80,9 +78,7 @@ def __vciFormatErrorExtended( Formatted string """ # TODO: make sure we don't generate another exception - return "{} - arguments were {}".format( - __vciFormatError(library_instance, function, vret), args - ) + return "{} - arguments were {}".format(__vciFormatError(library_instance, function, vret), args) def __vciFormatError(library_instance: CLibrary, function: Callable, vret: int): @@ -99,9 +95,7 @@ def __vciFormatError(library_instance: CLibrary, function: Callable, vret: int): buf = ctypes.create_string_buffer(constants.VCI_MAX_ERRSTRLEN) ctypes.memset(buf, 0, constants.VCI_MAX_ERRSTRLEN) library_instance.vciFormatError(vret, buf, constants.VCI_MAX_ERRSTRLEN) - return "function {} failed ({})".format( - function._name, buf.value.decode("utf-8", "replace") - ) + return "function {} failed ({})".format(function._name, buf.value.decode("utf-8", "replace")) def __check_status(result: int, function: Callable, args: Tuple): @@ -143,13 +137,9 @@ def __check_status(result: int, function: Callable, args: Tuple): # void VCIAPI vciFormatError (HRESULT hrError, PCHAR pszText, UINT32 dwsize); try: - _canlib.map_symbol( - "vciFormatError", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32) - ) + _canlib.map_symbol("vciFormatError", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32)) except ImportError: - _canlib.map_symbol( - "vciFormatErrorA", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32) - ) + _canlib.map_symbol("vciFormatErrorA", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32)) _canlib.vciFormatError = _canlib.vciFormatErrorA # Hack to have vciFormatError as a free function vciFormatError = functools.partial(__vciFormatError, _canlib) @@ -167,9 +157,7 @@ def __check_status(result: int, function: Callable, args: Tuple): ) # HRESULT VCIAPI vciDeviceOpen( IN REFVCIID rVciid, OUT PHANDLE phDevice ); - _canlib.map_symbol( - "vciDeviceOpen", hresult_type, (structures.PVCIID, PHANDLE), __check_status - ) + _canlib.map_symbol("vciDeviceOpen", hresult_type, (structures.PVCIID, PHANDLE), __check_status) # HRESULT vciDeviceClose( HANDLE hDevice ) _canlib.map_symbol("vciDeviceClose", hresult_type, (HANDLE,), __check_status) @@ -203,9 +191,7 @@ def __check_status(result: int, function: Callable, args: Tuple): __check_status, ) # EXTERN_C HRESULT VCIAPI canChannelActivate( IN HANDLE hCanChn, IN BOOL fEnable ); - _canlib.map_symbol( - "canChannelActivate", hresult_type, (HANDLE, ctypes.c_long), __check_status - ) + _canlib.map_symbol("canChannelActivate", hresult_type, (HANDLE, ctypes.c_long), __check_status) # HRESULT canChannelClose( HANDLE hChannel ) _canlib.map_symbol("canChannelClose", hresult_type, (HANDLE,), __check_status) # EXTERN_C HRESULT VCIAPI canChannelReadMessage( IN HANDLE hCanChn, IN UINT32 dwMsTimeout, OUT PCANMSG2 pCanMsg ); @@ -289,9 +275,7 @@ def __check_status(result: int, function: Callable, args: Tuple): # EXTERN_C HRESULT VCIAPI canControlReset( IN HANDLE hCanCtl ); _canlib.map_symbol("canControlReset", hresult_type, (HANDLE,), __check_status) # EXTERN_C HRESULT VCIAPI canControlStart( IN HANDLE hCanCtl, IN BOOL fStart ); - _canlib.map_symbol( - "canControlStart", hresult_type, (HANDLE, ctypes.c_long), __check_status - ) + _canlib.map_symbol("canControlStart", hresult_type, (HANDLE, ctypes.c_long), __check_status) # EXTERN_C HRESULT VCIAPI canControlGetStatus( IN HANDLE hCanCtl, OUT PCANLINESTATUS2 pStatus ); _canlib.map_symbol( "canControlGetStatus", @@ -344,9 +328,7 @@ def __check_status(result: int, function: Callable, args: Tuple): __check_status, ) # EXTERN_C HRESULT canSchedulerActivate ( HANDLE hScheduler, BOOL fEnable ); - _canlib.map_symbol( - "canSchedulerActivate", hresult_type, (HANDLE, ctypes.c_int), __check_status - ) + _canlib.map_symbol("canSchedulerActivate", hresult_type, (HANDLE, ctypes.c_int), __check_status) # EXTERN_C HRESULT canSchedulerAddMessage (HANDLE hScheduler, PCANCYCLICTXMSG2 pMessage, PUINT32 pdwIndex ); _canlib.map_symbol( "canSchedulerAddMessage", @@ -480,10 +462,10 @@ def __init__( log.info("CAN Filters: %s", can_filters) # Configuration options - self._receive_own_messages = receive_own_messages - if isinstance(timing, BitTimingFd): - # if a BitTimingFd instance has been passed, we can presume the user wants to use FD capability - fd = True + if isinstance(timing, BitTiming): + fd = False # if a BitTiming instance has been passed, force the bus to initialise as a standard bus. + elif isinstance(timing, BitTiming): + fd = True # if a BitTimingFd instance has been passed, force the bus to initialise as FD capble channel = int(channel) # Usually comes as a string from the config file if channel < 0: raise ValueError("channel number must be >= 0") @@ -491,6 +473,9 @@ def __init__( data_bitrate = int(data_bitrate) if (bitrate < 0) or (data_bitrate < 0): raise ValueError("bitrate and data_bitrate must be >= 0") + if (bitrate > 1_000_000) or (data_bitrate > 10_000_000): + raise ValueError("bitrate must be <= 1_000_000 data_bitrate must be <= 10_000_000") + self.receive_own_messages = receive_own_messages # fetch deprecated timing arguments (if provided) tseg1_abr = kwargs.get("tseg1_abr") @@ -538,9 +523,7 @@ def __init__( _canlib.vciEnumDeviceOpen(ctypes.byref(self._device_handle)) while True: try: - _canlib.vciEnumDeviceNext( - self._device_handle, ctypes.byref(self._device_info) - ) + _canlib.vciEnumDeviceNext(self._device_handle, ctypes.byref(self._device_info)) except StopIteration as exc: if unique_hardware_id is None: raise VCIDeviceNotFoundError( @@ -548,14 +531,11 @@ def __init__( ) from exc else: raise VCIDeviceNotFoundError( - "Unique HW ID {} not connected or not available.".format( - unique_hardware_id - ) + "Unique HW ID {} not connected or not available.".format(unique_hardware_id) ) from exc else: if (unique_hardware_id is None) or ( - self._device_info.UniqueHardwareId.AsChar - == bytes(unique_hardware_id, "ascii") + self._device_info.UniqueHardwareId.AsChar == bytes(unique_hardware_id, "ascii") ): break else: @@ -590,9 +570,7 @@ def __init__( ctypes.byref(self._channel_handle), ) except Exception as exc: - raise CanInitializationError( - f"Could not open and initialize channel: {exc}" - ) from exc + raise CanInitializationError(f"Could not open and initialize channel: {exc}") from exc # Signal TX/RX events when at least one frame has been handled _canlib.canChannelInitialize( @@ -606,27 +584,19 @@ def __init__( ) _canlib.canChannelActivate(self._channel_handle, constants.TRUE) - _canlib.canControlOpen( - self._device_handle, channel, ctypes.byref(self._control_handle) - ) + _canlib.canControlOpen(self._device_handle, channel, ctypes.byref(self._control_handle)) log.debug("Fetching capabilities for interface channel %d", channel) - _canlib.canControlGetCaps( - self._control_handle, ctypes.byref(self._channel_capabilities) - ) + _canlib.canControlGetCaps(self._control_handle, ctypes.byref(self._channel_capabilities)) # check capabilities bOpMode = constants.CAN_OPMODE_UNDEFINED - if ( - self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT - ) != 0: + if (self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT) != 0: # controller supports CAN_OPMODE_STANDARD and CAN_OPMODE_EXTENDED at the same time bOpMode |= constants.CAN_OPMODE_STANDARD # enable both 11 bits reception if extended: # parameter from configuration bOpMode |= constants.CAN_OPMODE_EXTENDED # enable 29 bits reception - elif ( - self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT - ) != 0: + elif (self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT) != 0: log.warning( "Channel %d capabilities allow either basic or extended IDs, but not both. using %s according to parameter [extended=%s]", channel, @@ -634,11 +604,7 @@ def __init__( "True" if extended else "False", ) # controller supports either CAN_OPMODE_STANDARD or CAN_OPMODE_EXTENDED, but not both simultaneously - bOpMode |= ( - constants.CAN_OPMODE_EXTENDED - if extended - else constants.CAN_OPMODE_STANDARD - ) + bOpMode |= constants.CAN_OPMODE_EXTENDED if extended else constants.CAN_OPMODE_STANDARD if ( # controller supports receiving error frames: self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_ERRFRAME @@ -653,18 +619,14 @@ def __init__( bExMode = constants.CAN_EXMODE_DISABLED self._can_protocol = CanProtocol.CAN_20 # default to standard CAN protocol if fd: - if ( - self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_EXTDATA - ) != 0: + if (self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_EXTDATA) != 0: bExMode |= constants.CAN_EXMODE_EXTDATALEN else: raise CanInitializationError( "The interface %s does not support extended data frames (FD)" % self._device_info.UniqueHardwareId.AsChar.decode("ascii"), ) - if ( - self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_FASTDATA - ) != 0: + if (self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_FASTDATA) != 0: bExMode |= constants.CAN_EXMODE_FASTDATA else: raise CanInitializationError( @@ -674,74 +636,26 @@ def __init__( # set bus to CAN FD protocol once FD capability is verified self._can_protocol = CanProtocol.CAN_FD - if not timing: - # only use bitrate and the deprecated args if no timing argument is provided - if tseg1_abr and tseg2_abr and sjw_abr: - if not tseg1_dbr and not tseg2_dbr and not sjw_dbr: - # if only the arbitration rate segments have been specified, duplicate them for data rate segments - tseg1_dbr = tseg1_abr - tseg1_dbr = tseg2_dbr - sjw_dbr = sjw_abr - try: - timing = BitTimingFd.from_bitrate_and_segments( - f_clock=self._channel_capabilities.dwCanClockFreq, - nom_bitrate=bitrate, - nom_tseg1=tseg1_abr, - nom_tseg2=tseg2_abr, - nom_sjw=sjw_abr, - data_bitrate=data_bitrate, - data_tseg1=tseg1_dbr, - data_tseg2=tseg2_dbr, - data_sjw=sjw_dbr, - ) - except ValueError as exc: - raise CanInitializationError( - "Could not initialise the channel with the given bitrate and segment timings" - ) from exc - else: - try: - timing = BitTimingFd.from_sample_point( - f_clock=self._channel_capabilities.dwCanClkFreq, - nom_bitrate=bitrate, - nom_sample_point=80, - data_bitrate=data_bitrate, - data_sample_point=80, - ) - except ValueError as exc: - raise CanInitializationError( - "Could not initialise the channel with the given bitrate and sample point target of 80%." - ) from exc - elif isinstance(timing, BitTiming): - # if a standard BitTiming class has been passed, convert it to a BitTimingFD instance - timing = BitTimingFd.from_bitrate_and_segments( - f_clock=timing.f_clock, - nom_bitrate=timing.bitrate, - nom_tseg1=timing.tseg1, - nom_tseg2=timing.tseg2, - nom_sjw=timing.sjw, - data_bitrate=timing.bitrate, - data_tseg1=timing.tseg1, - data_tseg2=timing.tseg2, - data_sjw=timing.sjw, + if timing and not isinstance(timing, (BitTiming, BitTimingFd)): + raise CanInitializationError( + "The timing parameter to the Ixxat Bus must be None, or an instance of can.BitTiming or can.BitTimingFd" ) - pBtpSDR = IXXATBus._canptb_build( - defaults=constants.CAN_BITRATE_PRESETS, - bitrate=timing.nom_bitrate, - tseg1=timing.nom_tseg1, - tseg2=timing.nom_tseg2, - sjw=timing.nom_sjw, - ssp=0, - ) - pBtpFDR = IXXATBus._canptb_build( - defaults=constants.CAN_DATABITRATE_PRESETS, - bitrate=data_bitrate, - tseg1=tseg1_dbr, - tseg2=tseg2_dbr, - sjw=sjw_dbr, - ssp=ssp_dbr if ssp_dbr is not None else tseg1_dbr, + pBtpSDR, pBtpFDR = self._bit_timing_constructor( + timing, + bitrate, + tseg1_abr, # deprecated + tseg2_abr, # deprecated + sjw_abr, # deprecated + data_bitrate, + tseg1_dbr, # deprecated + tseg2_dbr, # deprecated + sjw_dbr, # deprecated + ssp_dbr, # deprecated ) + log.info("Initialising Channel %d with the following parameters: \n%s\n%s", channel, pBtpSDR, pBtpFDR) + _canlib.canControlInitialize( self._control_handle, bOpMode, @@ -758,10 +672,7 @@ def __init__( # the message in ticks. The resolution of a tick can be calculated from the fields # dwClockFreq and dwTscDivisor of the structure CANCAPABILITIES in accordance with the following formula: # frequency [1/s] = dwClockFreq / dwTscDivisor - self._tick_resolution = ( - self._channel_capabilities.dwTscClkFreq - / self._channel_capabilities.dwTscDivisor - ) + self._tick_resolution = self._channel_capabilities.dwTscClkFreq / self._channel_capabilities.dwTscDivisor # Setup filters before starting the channel if can_filters: @@ -779,9 +690,7 @@ def __init__( code = int(can_filter["can_id"]) mask = int(can_filter["can_mask"]) extended = can_filter.get("extended", False) - _canlib.canControlAddFilterIds( - self._control_handle, 1 if extended else 0, code << 1, mask << 1 - ) + _canlib.canControlAddFilterIds(self._control_handle, 1 if extended else 0, code << 1, mask << 1) log.info("Accepting ID: 0x%X MASK: 0x%X", code, mask) # Start the CAN controller. Messages will be forwarded to the channel @@ -796,39 +705,12 @@ def __init__( # Clear the FIFO by filter them out with low timeout for _ in range(rx_fifo_size): try: - _canlib.canChannelReadMessage( - self._channel_handle, 0, ctypes.byref(self._message) - ) + _canlib.canChannelReadMessage(self._channel_handle, 0, ctypes.byref(self._message)) except (VCITimeout, VCIRxQueueEmptyError): break super().__init__(channel=channel, can_filters=None, **kwargs) - @staticmethod # TODO - implement BitTiming class - def _canptb_build(defaults, bitrate, tseg1, tseg2, sjw, ssp): - if bitrate in defaults: - d = defaults[bitrate] - if tseg1 is None: - tseg1 = d.wTS1 - if tseg2 is None: - tseg2 = d.wTS2 - if sjw is None: - sjw = d.wSJW - if ssp is None: - ssp = d.wTDO - dw_mode = d.dwMode - else: - dw_mode = 0 - - return structures.CANBTP( - dwMode=dw_mode, - dwBPS=bitrate, - wTS1=tseg1, - wTS2=tseg2, - wSJW=sjw, - wTDO=ssp, - ) - def _inWaiting(self): try: _canlib.canChannelWaitRxEvent(self._channel_handle, 0) @@ -851,9 +733,7 @@ def _recv_internal(self, timeout): if timeout == 0: # Peek without waiting try: - _canlib.canChannelPeekMessage( - self._channel_handle, ctypes.byref(self._message) - ) + _canlib.canChannelPeekMessage(self._channel_handle, ctypes.byref(self._message)) except (VCITimeout, VCIRxQueueEmptyError, VCIError): # VCIError means no frame available (canChannelPeekMessage returned different from zero) return None, True @@ -872,9 +752,7 @@ def _recv_internal(self, timeout): while True: try: - _canlib.canChannelReadMessage( - self._channel_handle, remaining_ms, ctypes.byref(self._message) - ) + _canlib.canChannelReadMessage(self._channel_handle, remaining_ms, ctypes.byref(self._message)) except (VCITimeout, VCIRxQueueEmptyError): # Ignore the 2 errors, the timeout is handled manually with the perf_counter() pass @@ -883,7 +761,7 @@ def _recv_internal(self, timeout): if self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_DATA: data_received = True break - elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_INFO: + if self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_INFO: log.info( constants.CAN_INFO_MESSAGES.get( self._message.abData[0], @@ -891,9 +769,7 @@ def _recv_internal(self, timeout): ) ) - elif ( - self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR - ): + elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR: log.warning( constants.CAN_ERROR_MESSAGES.get( self._message.abData[0], @@ -901,17 +777,12 @@ def _recv_internal(self, timeout): ) ) - elif ( - self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_STATUS - ): + elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_STATUS: log.info(_format_can_status(self._message.abData[0])) if self._message.abData[0] & constants.CAN_STATUS_BUSOFF: raise VCIBusOffError() - elif ( - self._message.uMsgInfo.Bits.type - == constants.CAN_MSGTYPE_TIMEOVR - ): + elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_TIMEOVR: pass else: log.warning("Unexpected message info type") @@ -929,14 +800,11 @@ def _recv_internal(self, timeout): # The _message.dwTime is a 32bit tick value and will overrun, # so expect to see the value restarting from 0 rx_msg = Message( - timestamp=self._message.dwTime - / self._tick_resolution, # Relative time in s + timestamp=self._message.dwTime / self._tick_resolution, # Relative time in s is_remote_frame=bool(self._message.uMsgInfo.Bits.rtr), is_fd=bool(self._message.uMsgInfo.Bits.edl), is_rx=True, - is_error_frame=bool( - self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR - ), + is_error_frame=bool(self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR), bitrate_switch=bool(self._message.uMsgInfo.Bits.fdr), error_state_indicator=bool(self._message.uMsgInfo.Bits.esi), is_extended_id=bool(self._message.uMsgInfo.Bits.ext), @@ -962,14 +830,10 @@ def send(self, msg: Message, timeout: Optional[float] = None) -> None: """ # This system is not designed to be very efficient message = structures.CANMSG2() - message.uMsgInfo.Bits.type = ( - constants.CAN_MSGTYPE_ERROR - if msg.is_error_frame - else constants.CAN_MSGTYPE_DATA - ) + message.uMsgInfo.Bits.type = constants.CAN_MSGTYPE_ERROR if msg.is_error_frame else constants.CAN_MSGTYPE_DATA message.uMsgInfo.Bits.rtr = 1 if msg.is_remote_frame else 0 message.uMsgInfo.Bits.ext = 1 if msg.is_extended_id else 0 - message.uMsgInfo.Bits.srr = 1 if self._receive_own_messages else 0 + message.uMsgInfo.Bits.srr = 1 if self.receive_own_messages else 0 message.uMsgInfo.Bits.fdr = 1 if msg.bitrate_switch else 0 message.uMsgInfo.Bits.esi = 1 if msg.error_state_indicator else 0 message.uMsgInfo.Bits.edl = 1 if msg.is_fd else 0 @@ -977,16 +841,12 @@ def send(self, msg: Message, timeout: Optional[float] = None) -> None: if msg.dlc: # this dlc means number of bytes of payload message.uMsgInfo.Bits.dlc = len2dlc(msg.dlc) data_len_dif = msg.dlc - len(msg.data) - data = msg.data + bytearray( - [0] * data_len_dif - ) # pad with zeros until required length + data = msg.data + bytearray([0] * data_len_dif) # pad with zeros until required length adapter = (ctypes.c_uint8 * msg.dlc).from_buffer(data) ctypes.memmove(message.abData, adapter, msg.dlc) if timeout: - _canlib.canChannelSendMessage( - self._channel_handle, int(timeout * 1000), message - ) + _canlib.canChannelSendMessage(self._channel_handle, int(timeout * 1000), message) else: _canlib.canChannelPostMessage(self._channel_handle, message) @@ -1002,18 +862,12 @@ def _send_periodic_internal( if modifier_callback is None: if self._scheduler is None: self._scheduler = HANDLE() - _canlib.canSchedulerOpen( - self._device_handle, self.channel, self._scheduler - ) + _canlib.canSchedulerOpen(self._device_handle, self.channel, self._scheduler) caps = structures.CANCAPABILITIES2() _canlib.canSchedulerGetCaps(self._scheduler, caps) - self._scheduler_resolution = ( - caps.dwCmsClkFreq / caps.dwCmsDivisor - ) # TODO: confirm + self._scheduler_resolution = caps.dwCmsClkFreq / caps.dwCmsDivisor # TODO: confirm _canlib.canSchedulerActivate(self._scheduler, constants.TRUE) - return CyclicSendTask( - self._scheduler, msgs, period, duration, self._scheduler_resolution - ) + return CyclicSendTask(self._scheduler, msgs, period, duration, self._scheduler_resolution) # fallback to thread based cyclic task warnings.warn( @@ -1034,6 +888,7 @@ def shutdown(self): _canlib.canSchedulerClose(self._scheduler) _canlib.canChannelClose(self._channel_handle) _canlib.canControlStart(self._control_handle, constants.FALSE) + _canlib.canControlReset(self._control_handle) _canlib.canControlClose(self._control_handle) _canlib.vciDeviceClose(self._device_handle) @@ -1046,17 +901,22 @@ def clock_frequency(self) -> int: return self._channel_capabilities.dwCanClkFreq @property - def bus_load(self) -> Union[int, None]: + def bus_load(self) -> int: """ - :return: The Bus Load in % (0 - 100) if the adapter is capable of measuring it. Otherwise returns None. - :rtype: Union[int, None] + :return: The Bus Load in % (0 - 100) if the adapter is capable of measuring it. + Otherwise returns 0 % with a warning message. + :rtype: int """ if self._bus_load_calculation: - status = structures.CANLINESTATUS2() - _canlib.canControlGetStatus(self._control_handle, ctypes.byref(status)) - return status.bBusLoad + return self._status.bBusLoad else: warnings.warn("The current adapter does not support bus load measurement") + return 0 + + def _status(self) -> structures.CANLINESTATUS2: + status = structures.CANLINESTATUS2() + _canlib.canControlGetStatus(self._control_handle, ctypes.byref(status)) + return status @property def state(self) -> BusState: @@ -1065,7 +925,7 @@ def state(self) -> BusState: """ status = structures.CANLINESTATUS2() _canlib.canControlGetStatus(self._control_handle, ctypes.byref(status)) - if status.bOpMode == constants.CAN_OPMODE_LISTONLY: + if status.bOpMode & constants.CAN_OPMODE_LISTONLY: return BusState.PASSIVE error_byte_1 = status.dwStatus & 0x0F @@ -1080,6 +940,128 @@ def state(self) -> BusState: return BusState.ACTIVE + def _bit_timing_constructor( + self, + timing_obj: Optional[Union[BitTiming, BitTimingFd]], + bitrate: Optional[int], + tseg1_abr: Optional[int], + tseg2_abr: Optional[int], + sjw_abr: Optional[int], + data_bitrate: Optional[int], + tseg1_dbr: Optional[int], + tseg2_dbr: Optional[int], + sjw_dbr: Optional[int], + ssp_dbr: Optional[int], + ) -> Tuple: + """ + A helper function to convert a can.BitTiming or can.BitTimingFd object into the arguments for + the VCI driver's CANBTP function. + :param timing_obj: A can.BitTiming or can.BitTimingFd instance. If this argument is specified, + all other arguments are ignored + :type timing_obj: Optional[Union[BitTiming, BitTimingFd]] + :param bitrate: The standard / arbitration bitrate in bit/s. + :type bitrate: Optional[int] + :param tseg1_abr: Time segment 1 for the standard / arbitration speed, that is, the number of quanta from + (but not including) the Sync Segment to the sampling point. + :type tseg1_abr: Optional[int] + :param tseg2_abr: Time segment 2 for the standard / arbitration speed, that is, the number of quanta from the + sampling point to the end of the bit. + :type tseg2_abr: Optional[int] + :param sjw_abr: The Synchronization Jump Width for the standard / arbitration speed. Decides the maximum + number of time quanta that the controller can resynchronize every bit. + :type sjw_abr: Optional[int] + :param data_bitrate: The CAN FD Data bitrate in bit/s. + :type data_bitrate: Optional[int] + :param tseg1_dbr: Time segment 1 for the CAN FD data speed, that is, the number of quanta from + (but not including) the Sync Segment to the sampling point. + :type tseg1_dbr: Optional[int] + :param tseg2_dbr: Time segment 2 for the CAN FD data speed, that is, the number of quanta from the + sampling point to the end of the bit. + :type tseg2_dbr: Optional[int] + :param sjw_dbr: The Synchronization Jump Width for the CAN FD data speed. Decides the maximum + number of time quanta that the controller can resynchronize every bit. + :type sjw_dbr: Optional[int] + :param ssp_dbr: Secondary Sample Point Offset for the CAN FD data speed, that is, the number of quanta from + (but not including) the Sync Segment to the secondary sampling point. If this value is not provided, it + defaults to the same value as `tseg1_dbr`. + :type ssp_dbr: Optional[int] + :param : DESCRIPTION + :type : TYPE + :return: A Tuple containing two CANBTP structures for the VCI driver. + The first is the standard CAN 2.0 CANBTP object (or the CAN FD Arbitration rate CANBTP object), + and the second is the CAN FD data rate CANBTP object (which is null if a standard bus is initialised). + :rtype: Tuple + """ + + # Create a null FD timing structure in case we are only using a standard bus + pBtpFDR = structures.CANBTP(dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0) + + # if only a bitrate is supplied + if bitrate and not timing_obj and not (tseg1_abr and tseg2_abr and sjw_abr): + # unless timing segments are specified, try and use a predefined set of timings from constants.py + pBtpSDR = constants.CAN_BITRATE_PRESETS.get(bitrate, None) + if not pBtpSDR: + # if we have failed to identify a suitable set of timings from the presets + timing_obj = BitTiming.from_sample_point( + f_clock=self._channel_capabilities.dwCanClkFreq, + bitrate=bitrate, + sample_point=80, + ) + # if a bitrate and timings are supplied + elif bitrate and not timing_obj and (tseg1_abr and tseg2_abr and sjw_abr): + pBtpSDR = structures.CANBTP(dwMode=0, dwBPS=bitrate, wTS1=tseg1_abr, wTS2=tseg2_abr, wSJW=sjw_abr, wTDO=0) + + # if a data_bitrate is supplied + if data_bitrate and not timing_obj and not (tseg1_dbr and tseg2_dbr and sjw_dbr): + # unless timing segments are specified, try and use a predefined set of timings from constants.py + pBtpFDR = constants.CAN_DATABITRATE_PRESETS.get(data_bitrate, None) + if not pBtpFDR: + # if we have failed to identify a suitable set of FD data timings from the presets + timing_obj = BitTimingFd.from_sample_point( + f_clock=self._channel_capabilities.dwCanClkFreq, + nom_bitrate=bitrate, + nom_sample_point=80, # 80% + data_bitrate=data_bitrate, + data_sample_point=80, # 80% + ) + # if a data_bitrate and timings are supplied + elif data_bitrate and not timing_obj and (tseg1_dbr and tseg2_dbr and sjw_dbr): + if not ssp_dbr: + ssp_dbr = tseg2_dbr + pBtpFDR = structures.CANBTP( + dwMode=0, dwBPS=data_bitrate, wTS1=tseg1_dbr, wTS2=tseg2_dbr, wSJW=sjw_dbr, wTDO=ssp_dbr + ) + + # if a timing object is provided + if isinstance(timing_obj, BitTiming): + pBtpSDR = structures.CANBTP( + dwMode=0, + dwBPS=timing_obj.bitrate, + wTS1=timing_obj.tseg1, + wTS2=timing_obj.tseg2, + wSJW=timing_obj.sjw, + wTDO=0, + ) + elif isinstance(timing_obj, BitTimingFd): + pBtpSDR = structures.CANBTP( + dwMode=0, + dwBPS=timing_obj.nom_bitrate, + wTS1=timing_obj.nom_tseg1, + wTS2=timing_obj.nom_tseg2, + wSJW=timing_obj.nom_sjw, + wTDO=0, + ) + pBtpFDR = structures.CANBTP( + dwMode=0, + dwBPS=timing_obj.data_bitrate, + wTS1=timing_obj.data_tseg1, + wTS2=timing_obj.data_tseg2, + wSJW=timing_obj.data_sjw, + wTDO=timing_obj.data_tseg2, + ) + + return pBtpSDR, pBtpFDR + @staticmethod def _detect_available_configs() -> List[AutoDetectedConfig]: config_list = [] # list in wich to store the resulting bus kwargs @@ -1139,9 +1121,7 @@ class CyclicSendTask(LimitedDurationCyclicSendTaskABC, RestartableCyclicTaskABC) def __init__(self, scheduler, msgs, period, duration, resolution): super().__init__(msgs, period, duration) if len(self.messages) != 1: - raise ValueError( - "IXXAT Interface only supports periodic transmission of 1 element" - ) + raise ValueError("IXXAT Interface only supports periodic transmission of 1 element") self._scheduler = scheduler self._index = None diff --git a/can/interfaces/ixxat/constants.py b/can/interfaces/ixxat/constants.py index ce07f8757..1249dfd53 100644 --- a/can/interfaces/ixxat/constants.py +++ b/can/interfaces/ixxat/constants.py @@ -220,53 +220,65 @@ CAN_BITRATE_PRESETS = { + 10000: structures.CANBTP( + dwMode=0, dwBPS=10_000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 + ), # SP = 80,0% + 20000: structures.CANBTP( + dwMode=0, dwBPS=20_000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 + ), # SP = 80,0% 50000: structures.CANBTP( - dwMode=0, dwBPS=50000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 + dwMode=0, dwBPS=50_000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 ), # SP = 80,0% + 100000: structures.CANBTP( + dwMode=0, dwBPS=100_000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 + ), # SP = 80,0% - Non CIA specified bitrate 125000: structures.CANBTP( - dwMode=0, dwBPS=125000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 + dwMode=0, dwBPS=125_000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 ), # SP = 80,0% 250000: structures.CANBTP( - dwMode=0, dwBPS=250000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 + dwMode=0, dwBPS=250_000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 ), # SP = 80,0% 500000: structures.CANBTP( - dwMode=0, dwBPS=500000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 + dwMode=0, dwBPS=500_000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 + ), # SP = 80,0% + 800000: structures.CANBTP( + dwMode=0, dwBPS=800_000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 ), # SP = 80,0% 1000000: structures.CANBTP( - dwMode=0, dwBPS=1000000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 + dwMode=0, dwBPS=1_000_000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 ), # SP = 80,0% } CAN_DATABITRATE_PRESETS = { - 500000: structures.CANBTP( - dwMode=0, dwBPS=500000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=6400 + 500_000: structures.CANBTP( + dwMode=0, dwBPS=500_000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=6400 ), # SP = 80,0% - 833333: structures.CANBTP( - dwMode=0, dwBPS=833333, wTS1=1600, wTS2=400, wSJW=400, wTDO=1620 + 833_333: structures.CANBTP( + dwMode=0, dwBPS=833_333, wTS1=1600, wTS2=400, wSJW=400, wTDO=1620 ), # SP = 80,0% - 1000000: structures.CANBTP( - dwMode=0, dwBPS=1000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600 + 1_000_000: structures.CANBTP( + dwMode=0, dwBPS=1_000_000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600 ), # SP = 80,0% - 1538461: structures.CANBTP( - dwMode=0, dwBPS=1538461, wTS1=1000, wTS2=300, wSJW=300, wTDO=1040 + 1_538_461: structures.CANBTP( + dwMode=0, dwBPS=1_538_461, wTS1=1000, wTS2=300, wSJW=300, wTDO=1040 ), # SP = 76,9% - 2000000: structures.CANBTP( - dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600 + 2_000_000: structures.CANBTP( + dwMode=0, dwBPS=2_000_000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600 ), # SP = 80,0% - 4000000: structures.CANBTP( - dwMode=0, dwBPS=4000000, wTS1=800, wTS2=200, wSJW=200, wTDO=800 + 4_000_000: structures.CANBTP( + dwMode=0, dwBPS=4_000_000, wTS1=800, wTS2=200, wSJW=200, wTDO=800 ), # SP = 80,0% - 5000000: structures.CANBTP( - dwMode=0, dwBPS=5000000, wTS1=600, wTS2=200, wSJW=200, wTDO=600 + 5_000_000: structures.CANBTP( + dwMode=0, dwBPS=5_000_000, wTS1=600, wTS2=200, wSJW=200, wTDO=600 ), # SP = 75,0% - 6666666: structures.CANBTP( - dwMode=0, dwBPS=6666666, wTS1=400, wTS2=200, wSJW=200, wTDO=402 + 6_666_666: structures.CANBTP( + dwMode=0, dwBPS=6_666_666, wTS1=400, wTS2=200, wSJW=200, wTDO=402 ), # SP = 66,7% - 8000000: structures.CANBTP( - dwMode=0, dwBPS=8000000, wTS1=400, wTS2=100, wSJW=100, wTDO=250 + 8_000_000: structures.CANBTP( + dwMode=0, dwBPS=8_000_000, wTS1=400, wTS2=100, wSJW=100, wTDO=250 ), # SP = 80,0% - 10000000: structures.CANBTP( - dwMode=0, dwBPS=10000000, wTS1=300, wTS2=100, wSJW=100, wTDO=200 + 10_000_000: structures.CANBTP( + dwMode=0, dwBPS=10_000_000, wTS1=300, wTS2=100, wSJW=100, wTDO=200 ), # SP = 75,0% } diff --git a/can/interfaces/ixxat/structures.py b/can/interfaces/ixxat/structures.py index 101a02c8b..d5cca1c6c 100644 --- a/can/interfaces/ixxat/structures.py +++ b/can/interfaces/ixxat/structures.py @@ -189,6 +189,29 @@ class CANCAPABILITIES2(ctypes.Structure): ), # maximum tick count value of the delayed message transmitter ] + def __str__(self): + cap = ", ".join( + ( + "wCtrlType=%s" % self.wCtrlType, + "wBusCoupling=%s" % self.wBusCoupling, + "dwFeatures=%s" % self.dwFeatures, + "dwCanClkFreq=%s" % self.dwCanClkFreq, + "sSdrRangeMin=%s" % self.sSdrRangeMin, + "sSdrRangeMax=%s" % self.sSdrRangeMax, + "sFdrRangeMin=%s" % self.sFdrRangeMin, + "sFdrRangeMax=%s" % self.sFdrRangeMax, + "dwTscClkFreq=%s" % self.dwTscClkFreq, + "dwTscDivisor=%s" % self.dwTscDivisor, + "dwCmsClkFreq=%s" % self.dwCmsClkFreq, + "dwCmsDivisor=%s" % self.dwCmsDivisor, + "dwCmsMaxTicks=%s" % self.dwCmsMaxTicks, + "dwDtxClkFreq=%s" % self.dwDtxClkFreq, + "dwDtxDivisor=%s" % self.dwDtxDivisor, + "dwDtxMaxTicks=%s" % self.dwDtxMaxTicks, + ) + ) + return cap + PCANCAPABILITIES2 = ctypes.POINTER(CANCAPABILITIES2) @@ -204,6 +227,18 @@ class CANLINESTATUS2(ctypes.Structure): ("dwStatus", ctypes.c_uint32), # status of the CAN controller (see CAN_STATUS_) ] + def __str__(self) -> str: + return "\n".join( + ( + f"Std Operating Mode: {self.bOpMode}", + f"Ext Operating Mode: {self.bExMode}", + f"Bus Load (%): {self.bBusLoad}", + f"Standard Bitrate Timing: {self.sBtpSdr}", + f"Fast Datarate timing: {self.sBtpFdr}", + f"CAN Controller Status: {self.dwStatus}", + ) + ) + PCANLINESTATUS2 = ctypes.POINTER(CANLINESTATUS2) @@ -217,6 +252,17 @@ class CANCHANSTATUS2(ctypes.Structure): ("bTxFifoLoad", ctypes.c_uint8), # transmit FIFO load in percent (0..100) ] + def __str__(self) -> str: + return "\n".join( + ( + f"Status: {self.sLineStatus}", + f"Activated: {bool(self.fActivated)}", + f"RxOverrun: {bool(self.fRxOverrun)}", + f"Rx Buffer Load (%): {self.bRxFifoLoad}", + f"Tx Buffer Load (%): {self.bTxFifoLoad}", + ) + ) + PCANCHANSTATUS2 = ctypes.POINTER(CANCHANSTATUS2) diff --git a/doc/interfaces/ixxat.rst b/doc/interfaces/ixxat.rst index 978d4b525..b64c213e4 100644 --- a/doc/interfaces/ixxat.rst +++ b/doc/interfaces/ixxat.rst @@ -29,14 +29,15 @@ Python-can will search for the first IXXAT device available and open the first c module, while the following parameters are optional and are interpreted by IXXAT implementation. * ``receive_own_messages`` (default False) Enable self-reception of sent messages. -* ``unique_hardware_id`` (default first device) Unique hardware ID of the IXXAT device. +* ``unique_hardware_id`` (default first device found) Unique hardware ID of the IXXAT device. * ``extended`` (default True) Allow usage of extended IDs. * ``fd`` (default False) Enable CAN-FD capabilities. * ``rx_fifo_size`` (default 16 for CAN, 1024 for CAN-FD) Number of RX mailboxes. * ``tx_fifo_size`` (default 16 for CAN, 128 for CAN-FD) Number of TX mailboxes. * ``bitrate`` (default 500000) Channel bitrate. -* ``data_bitrate`` (defaults to 2Mbps) Channel data bitrate (only canfd, to use when message bitrate_switch is used). -* ``timing`` (optional) BitTiming class. If this argument is provided, the bitrate and data_bitrate parameters are overridden. +* ``data_bitrate`` (defaults to 2Mbps) Channel data bitrate (only CAN-FD, to use when message bitrate_switch is used). +* ``timing`` (optional) a :class:`~can.BitTiming` or :class:`~can.BitTimingFd` instance. If this argument is provided, +the bitrate and data_bitrate parameters are overridden. The following deprecated parameters will be removed in python-can version 5.0.0. @@ -48,10 +49,19 @@ The following deprecated parameters will be removed in python-can version 5.0.0. * ``tseg2_dbr`` (optional, only used if baudrate switch enabled) Bus timing value tseg2 (data). * ``ssp_dbr`` (optional, only used if baudrate switch enabled) Secondary sample point (data). -timing +Timing ------ +If the IxxatBus instance is created by providing a ``bitrate`` value, the provided desired bitrate is looked up +in a table of standard timing definitions (Note that these definitions all use a sample point of 80%). Similarly, +if ``fd=True`` and a ``data_bitrate`` value is provided, the fast data rate timing definitions are also looked up in +a table of standard definitions (Note that most of these definitions use a sample point of 80%). +if a :class:`~can.BitTiming` instance is provided when the IxxatBus instance is created, it will override any other +timing arguments that are provided. it will also set the bus to standard CAN (even if ``fd=True`` was specified). + +Similarly, if a :class:`~can.BitTimingFd` instance is provided, this will override any other timing arguments that are +provided. it will also set the bus to CAN FD (even if ``fd=False`` was specified). Filtering @@ -115,7 +125,7 @@ Bus .. autoclass:: can.interfaces.ixxat.IXXATBus :members: -.. autoclass:: can.interfaces.ixxat.canlib_vcinpl.CyclicSendTask +.. autoclass:: can.interfaces.ixxat.CyclicSendTask :members: @@ -133,6 +143,6 @@ explicitly instantiated by the caller. - ``send()`` is not blocking but may raise a VCIError if the TX FIFO is full RX and TX FIFO sizes are configurable with ``rx_fifo_size`` and ``tx_fifo_size`` -options, defaulting to 16 for both for non-FD communication. For FD communication, -``rx_fifo_size`` defaults to 1024, and ``tx_fifo_size`` defaults to 128. +options, defaulting to 16 for both RX and TX for non-FD communication. +For FD communication, ``rx_fifo_size`` defaults to 1024, and ``tx_fifo_size`` defaults to 128. diff --git a/test/test_interface_ixxat.py b/test/test_interface_ixxat.py index 2ff016d97..c826557f9 100644 --- a/test/test_interface_ixxat.py +++ b/test/test_interface_ixxat.py @@ -7,58 +7,216 @@ python setup.py test --addopts "--verbose -s test/test_interface_ixxat.py" """ +import logging +import time import unittest import can +logger = logging.getLogger("can.ixxat") +default_test_bitrate = 250_000 +default_test_msg = can.Message(arbitration_id=0xC0FFEE, dlc=6, data=[0x70, 0x79, 0x74, 0x68, 0x6F, 0x6E]) -class SoftwareTestCase(unittest.TestCase): + +class LogCaptureHandler(logging.Handler): + """ + Allows a test case to get access to the logs raised in another module + """ + + def __init__(self): + super().__init__() + self.records = [] + + def emit(self, record): + self.records.append(record.getMessage()) + + def get_records(self): + return self.records + + +class TestSoftwareCase(unittest.TestCase): """ Test cases that test the software only and do not rely on an existing/connected hardware. """ def setUp(self): + self.log_capture = LogCaptureHandler() + log = logging.getLogger("can.ixxat") + log.addHandler(self.log_capture) + log.setLevel(logging.INFO) try: - bus = can.Bus(interface="ixxat", channel=0) + bus = can.Bus(interface="ixxat", channel=0, bitrate=default_test_bitrate) bus.shutdown() - except can.CanInterfaceNotImplementedError: - raise unittest.SkipTest("not available on this platform") + except can.CanInterfaceNotImplementedError as exc: + raise unittest.SkipTest("not available on this platform") from exc + + def tearDown(self): + logging.getLogger("can.ixxat").removeHandler(self.log_capture) def test_bus_creation(self): # channel must be >= 0 with self.assertRaises(ValueError): - can.Bus(interface="ixxat", channel=-1) + can.Bus(interface="ixxat", channel=-1, bitrate=default_test_bitrate) # rx_fifo_size must be > 0 with self.assertRaises(ValueError): - can.Bus(interface="ixxat", channel=0, rx_fifo_size=0) + can.Bus(interface="ixxat", channel=0, rx_fifo_size=0, bitrate=default_test_bitrate) # tx_fifo_size must be > 0 with self.assertRaises(ValueError): - can.Bus(interface="ixxat", channel=0, tx_fifo_size=0) + can.Bus(interface="ixxat", channel=0, tx_fifo_size=0, bitrate=default_test_bitrate) -class HardwareTestCase(unittest.TestCase): +class TestHardwareCase(unittest.TestCase): """ Test cases that rely on an existing/connected hardware. """ def setUp(self): + self.log_capture = LogCaptureHandler() + logging.getLogger("can.ixxat").addHandler(self.log_capture) try: bus = can.Bus(interface="ixxat", channel=0) + self.clock_frequency = bus.clock_frequency + bus.shutdown() + except can.CanInterfaceNotImplementedError as exc: + raise unittest.SkipTest("not available on this platform") from exc + + def tearDown(self): + logging.getLogger("can.ixxat").removeHandler(self.log_capture) + + def test_bus_creation_standard_bitrate(self): + bus = can.Bus(interface="ixxat", channel=0, bitrate=default_test_bitrate) + bus.shutdown() + + def test_bus_creation_arbitrary_bitrate(self): + target_bitrate = 444_444 + with can.Bus(interface="ixxat", channel=0, bitrate=target_bitrate) as bus: + timing = bus._status().sBtpSdr + bus_timing = can.BitTiming(self.clock_frequency, timing.dwBPS, timing.wTS1, timing.wTS2, timing.wSJW) + self.assertEqual( + target_bitrate, + bus_timing.bitrate, + "\n".join( + ( + "The Hardware Configured bitrate does not match the desired bitrate", + "Desired: %s" % target_bitrate, + "Hardware Setting: %s" % bus_timing.bitrate, + ) + ), + ) + + def test_bus_creation_invalid_bitrate(self): + with self.assertRaises(ValueError): + bus = can.Bus(interface="ixxat", channel=0, bitrate=2_000_000) bus.shutdown() - except can.CanInterfaceNotImplementedError: - raise unittest.SkipTest("not available on this platform") - def test_bus_creation(self): + def test_bus_creation_timing_arg(self): + # try: + timing_obj = can.BitTiming.from_bitrate_and_segments( + self.clock_frequency, default_test_bitrate, tseg1=13, tseg2=2, sjw=1 + ) + bus = can.Bus(interface="ixxat", channel=0, timing=timing_obj) + bus.shutdown() + # except can.CanInterfaceNotImplementedError: + # raise unittest.SkipTest("not available on this platform") + + def test_bus_creation_deprecated_timing_args(self): + # try: + bus = can.Bus(interface="ixxat", channel=0, bitrate=default_test_bitrate, sjw_abr=1, tseg1_abr=13, tseg2_abr=2) + bus.shutdown() + # except can.CanInterfaceNotImplementedError: + # raise unittest.SkipTest("not available on this platform") + + def test_send_single(self): + with can.Bus(interface="ixxat", channel=0, bitrate=default_test_bitrate, receive_own_messages=True) as bus: + bus.send(default_test_msg) + response = bus.recv(0.1) + + if response: + self.assertEqual( + response.arbitration_id, + default_test_msg.arbitration_id, + "The Arbitration ID of the sent message and the received message do not match", + ) + self.assertEqual( + response.data, + default_test_msg.data, + "The Data fields of the sent message and the received message do not match", + ) + else: + captured_logs = self.log_capture.get_records() + if captured_logs[-1] == "CAN bit error": + raise can.exceptions.CanOperationError( + "CAN bit error - Ensure you are connected to a " + "properly terminated bus configured at %s bps" % default_test_bitrate + ) + + elif captured_logs[-1] == "CAN ack error": + raise can.exceptions.CanOperationError( + "CAN ack error - Ensure there is at least one other (silent) node to provide ack signals", + ) + else: + raise ValueError( + "\n".join( + ( + "Response does not match the sent message", + "Sent: %s" % default_test_msg, + "Received: %s" % response, + "Last Caputred Log: %s" % captured_logs[-1], + "Ensure hardware tests are run on a bus with no other traffic.", + ) + ) + ) + + def test_send_periodic(self): + with can.Bus(interface="ixxat", channel=0, bitrate=default_test_bitrate, receive_own_messages=True) as bus: + # setup Notifier and BufferedReader instances to receive messages + msg_rx_buffer = can.BufferedReader() + msg_notifier = can.Notifier(bus, [msg_rx_buffer]) + + # setup periodic send task + task = bus.send_periodic(default_test_msg, 0.2) + assert isinstance(task, can.CyclicSendTaskABC) + time.sleep(2) + task.stop() + + # clean up the Notifier and BufferedReader instances + msg_notifier.stop() + msg_rx_buffer.stop() + + messages = [] + while msg := msg_rx_buffer.get_message(timeout=0.1): + messages.append(msg) + + if messages: + self.assertGreaterEqual(len(messages), 9) # should be 10 messages - give ±1 margin for timing issues + self.assertLessEqual(len(messages), 11) # should be 10 messages - give ±1 margin for timing issues + self.assertEqual( + messages[-1].arbitration_id, + default_test_msg.arbitration_id, + "The Arbitration ID of the sent message and the received message do not match", + ) + self.assertEqual( + messages[-1].data, + default_test_msg.data, + "The Data fields of the sent message and the received message do not match", + ) + else: + raise can.exceptions.CanOperationError( + "No messages have been received" + ) + + def test_bus_creation_invalid_channel(self): # non-existent channel -> use arbitrary high value with self.assertRaises(can.CanInitializationError): - can.Bus(interface="ixxat", channel=0xFFFF) + can.Bus(interface="ixxat", channel=0xFFFF, bitrate=default_test_bitrate) def test_send_after_shutdown(self): - with can.Bus(interface="ixxat", channel=0) as bus: - with self.assertRaises(can.CanOperationError): - bus.send(can.Message(arbitration_id=0x3FF, dlc=0)) + bus = can.Bus(interface="ixxat", channel=0, bitrate=default_test_bitrate) + bus.shutdown() + with self.assertRaises(can.CanOperationError): + bus.send(default_test_msg) if __name__ == "__main__": From e87e021a926084cf4ce2c2448e691dcf139c211d Mon Sep 17 00:00:00 2001 From: MattWoodhead Date: Sun, 11 Jun 2023 22:37:39 +0100 Subject: [PATCH 07/15] fix __init__ typo, run ruff and black --- can/interfaces/ixxat/__init__.py | 8 +- can/interfaces/ixxat/canlib.py | 205 +++++++++++++++++++++++-------- doc/interfaces/ixxat.rst | 3 +- test/test_interface_ixxat.py | 37 +++++- 4 files changed, 197 insertions(+), 56 deletions(-) diff --git a/can/interfaces/ixxat/__init__.py b/can/interfaces/ixxat/__init__.py index 30b6a1759..39e67a0b8 100644 --- a/can/interfaces/ixxat/__init__.py +++ b/can/interfaces/ixxat/__init__.py @@ -7,11 +7,15 @@ __all__ = [ "canlib", "constants", - "CyclicSendTask" + "CyclicSendTask", "exceptions", "get_ixxat_hwids", "IXXATBus", "structures", ] -from can.interfaces.ixxat.canlib import CyclicSendTask, get_ixxat_hwids, IXXATBus +from can.interfaces.ixxat.canlib import ( # noqa: F401 + CyclicSendTask, + IXXATBus, + get_ixxat_hwids, +) diff --git a/can/interfaces/ixxat/canlib.py b/can/interfaces/ixxat/canlib.py index a770055d8..1644e5973 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/can/interfaces/ixxat/canlib.py @@ -56,6 +56,7 @@ if sys.platform in ("win32", "cygwin"): try: _canlib = CLibrary("vcinpl2.dll") + print(type(_canlib)) except Exception as e: log.warning("Cannot load IXXAT vcinpl library: %s", e) else: @@ -64,7 +65,9 @@ log.warning("IXXAT VCI library does not work on %s platform", sys.platform) -def __vciFormatErrorExtended(library_instance: CLibrary, function: Callable, vret: int, args: Tuple): +def __vciFormatErrorExtended( + library_instance: CLibrary, function: Callable, vret: int, args: Tuple +): """Format a VCI error and attach failed function, decoded HRESULT and arguments :param CLibrary library_instance: Mapped instance of IXXAT vcinpl library @@ -78,7 +81,9 @@ def __vciFormatErrorExtended(library_instance: CLibrary, function: Callable, vre Formatted string """ # TODO: make sure we don't generate another exception - return "{} - arguments were {}".format(__vciFormatError(library_instance, function, vret), args) + return ( + "{__vciFormatError(library_instance, function, vret)} - arguments were {args}" + ) def __vciFormatError(library_instance: CLibrary, function: Callable, vret: int): @@ -95,7 +100,9 @@ def __vciFormatError(library_instance: CLibrary, function: Callable, vret: int): buf = ctypes.create_string_buffer(constants.VCI_MAX_ERRSTRLEN) ctypes.memset(buf, 0, constants.VCI_MAX_ERRSTRLEN) library_instance.vciFormatError(vret, buf, constants.VCI_MAX_ERRSTRLEN) - return "function {} failed ({})".format(function._name, buf.value.decode("utf-8", "replace")) + return "function {} failed ({})".format( + function._name, buf.value.decode("utf-8", "replace") + ) def __check_status(result: int, function: Callable, args: Tuple): @@ -137,9 +144,13 @@ def __check_status(result: int, function: Callable, args: Tuple): # void VCIAPI vciFormatError (HRESULT hrError, PCHAR pszText, UINT32 dwsize); try: - _canlib.map_symbol("vciFormatError", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32)) + _canlib.map_symbol( + "vciFormatError", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32) + ) except ImportError: - _canlib.map_symbol("vciFormatErrorA", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32)) + _canlib.map_symbol( + "vciFormatErrorA", None, (ctypes_HRESULT, ctypes.c_char_p, ctypes.c_uint32) + ) _canlib.vciFormatError = _canlib.vciFormatErrorA # Hack to have vciFormatError as a free function vciFormatError = functools.partial(__vciFormatError, _canlib) @@ -157,7 +168,9 @@ def __check_status(result: int, function: Callable, args: Tuple): ) # HRESULT VCIAPI vciDeviceOpen( IN REFVCIID rVciid, OUT PHANDLE phDevice ); - _canlib.map_symbol("vciDeviceOpen", hresult_type, (structures.PVCIID, PHANDLE), __check_status) + _canlib.map_symbol( + "vciDeviceOpen", hresult_type, (structures.PVCIID, PHANDLE), __check_status + ) # HRESULT vciDeviceClose( HANDLE hDevice ) _canlib.map_symbol("vciDeviceClose", hresult_type, (HANDLE,), __check_status) @@ -191,7 +204,9 @@ def __check_status(result: int, function: Callable, args: Tuple): __check_status, ) # EXTERN_C HRESULT VCIAPI canChannelActivate( IN HANDLE hCanChn, IN BOOL fEnable ); - _canlib.map_symbol("canChannelActivate", hresult_type, (HANDLE, ctypes.c_long), __check_status) + _canlib.map_symbol( + "canChannelActivate", hresult_type, (HANDLE, ctypes.c_long), __check_status + ) # HRESULT canChannelClose( HANDLE hChannel ) _canlib.map_symbol("canChannelClose", hresult_type, (HANDLE,), __check_status) # EXTERN_C HRESULT VCIAPI canChannelReadMessage( IN HANDLE hCanChn, IN UINT32 dwMsTimeout, OUT PCANMSG2 pCanMsg ); @@ -275,7 +290,9 @@ def __check_status(result: int, function: Callable, args: Tuple): # EXTERN_C HRESULT VCIAPI canControlReset( IN HANDLE hCanCtl ); _canlib.map_symbol("canControlReset", hresult_type, (HANDLE,), __check_status) # EXTERN_C HRESULT VCIAPI canControlStart( IN HANDLE hCanCtl, IN BOOL fStart ); - _canlib.map_symbol("canControlStart", hresult_type, (HANDLE, ctypes.c_long), __check_status) + _canlib.map_symbol( + "canControlStart", hresult_type, (HANDLE, ctypes.c_long), __check_status + ) # EXTERN_C HRESULT VCIAPI canControlGetStatus( IN HANDLE hCanCtl, OUT PCANLINESTATUS2 pStatus ); _canlib.map_symbol( "canControlGetStatus", @@ -328,7 +345,9 @@ def __check_status(result: int, function: Callable, args: Tuple): __check_status, ) # EXTERN_C HRESULT canSchedulerActivate ( HANDLE hScheduler, BOOL fEnable ); - _canlib.map_symbol("canSchedulerActivate", hresult_type, (HANDLE, ctypes.c_int), __check_status) + _canlib.map_symbol( + "canSchedulerActivate", hresult_type, (HANDLE, ctypes.c_int), __check_status + ) # EXTERN_C HRESULT canSchedulerAddMessage (HANDLE hScheduler, PCANCYCLICTXMSG2 pMessage, PUINT32 pdwIndex ); _canlib.map_symbol( "canSchedulerAddMessage", @@ -474,7 +493,9 @@ def __init__( if (bitrate < 0) or (data_bitrate < 0): raise ValueError("bitrate and data_bitrate must be >= 0") if (bitrate > 1_000_000) or (data_bitrate > 10_000_000): - raise ValueError("bitrate must be <= 1_000_000 data_bitrate must be <= 10_000_000") + raise ValueError( + "bitrate must be <= 1_000_000 data_bitrate must be <= 10_000_000" + ) self.receive_own_messages = receive_own_messages # fetch deprecated timing arguments (if provided) @@ -523,7 +544,9 @@ def __init__( _canlib.vciEnumDeviceOpen(ctypes.byref(self._device_handle)) while True: try: - _canlib.vciEnumDeviceNext(self._device_handle, ctypes.byref(self._device_info)) + _canlib.vciEnumDeviceNext( + self._device_handle, ctypes.byref(self._device_info) + ) except StopIteration as exc: if unique_hardware_id is None: raise VCIDeviceNotFoundError( @@ -531,11 +554,12 @@ def __init__( ) from exc else: raise VCIDeviceNotFoundError( - "Unique HW ID {} not connected or not available.".format(unique_hardware_id) + f"Unique HW ID {unique_hardware_id} not connected or not available." ) from exc else: if (unique_hardware_id is None) or ( - self._device_info.UniqueHardwareId.AsChar == bytes(unique_hardware_id, "ascii") + self._device_info.UniqueHardwareId.AsChar + == bytes(unique_hardware_id, "ascii") ): break else: @@ -570,7 +594,9 @@ def __init__( ctypes.byref(self._channel_handle), ) except Exception as exc: - raise CanInitializationError(f"Could not open and initialize channel: {exc}") from exc + raise CanInitializationError( + f"Could not open and initialize channel: {exc}" + ) from exc # Signal TX/RX events when at least one frame has been handled _canlib.canChannelInitialize( @@ -584,19 +610,27 @@ def __init__( ) _canlib.canChannelActivate(self._channel_handle, constants.TRUE) - _canlib.canControlOpen(self._device_handle, channel, ctypes.byref(self._control_handle)) + _canlib.canControlOpen( + self._device_handle, channel, ctypes.byref(self._control_handle) + ) log.debug("Fetching capabilities for interface channel %d", channel) - _canlib.canControlGetCaps(self._control_handle, ctypes.byref(self._channel_capabilities)) + _canlib.canControlGetCaps( + self._control_handle, ctypes.byref(self._channel_capabilities) + ) # check capabilities bOpMode = constants.CAN_OPMODE_UNDEFINED - if (self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT) != 0: + if ( + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT + ) != 0: # controller supports CAN_OPMODE_STANDARD and CAN_OPMODE_EXTENDED at the same time bOpMode |= constants.CAN_OPMODE_STANDARD # enable both 11 bits reception if extended: # parameter from configuration bOpMode |= constants.CAN_OPMODE_EXTENDED # enable 29 bits reception - elif (self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT) != 0: + elif ( + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT + ) != 0: log.warning( "Channel %d capabilities allow either basic or extended IDs, but not both. using %s according to parameter [extended=%s]", channel, @@ -604,7 +638,11 @@ def __init__( "True" if extended else "False", ) # controller supports either CAN_OPMODE_STANDARD or CAN_OPMODE_EXTENDED, but not both simultaneously - bOpMode |= constants.CAN_OPMODE_EXTENDED if extended else constants.CAN_OPMODE_STANDARD + bOpMode |= ( + constants.CAN_OPMODE_EXTENDED + if extended + else constants.CAN_OPMODE_STANDARD + ) if ( # controller supports receiving error frames: self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_ERRFRAME @@ -619,14 +657,18 @@ def __init__( bExMode = constants.CAN_EXMODE_DISABLED self._can_protocol = CanProtocol.CAN_20 # default to standard CAN protocol if fd: - if (self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_EXTDATA) != 0: + if ( + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_EXTDATA + ) != 0: bExMode |= constants.CAN_EXMODE_EXTDATALEN else: raise CanInitializationError( "The interface %s does not support extended data frames (FD)" % self._device_info.UniqueHardwareId.AsChar.decode("ascii"), ) - if (self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_FASTDATA) != 0: + if ( + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_FASTDATA + ) != 0: bExMode |= constants.CAN_EXMODE_FASTDATA else: raise CanInitializationError( @@ -654,7 +696,12 @@ def __init__( ssp_dbr, # deprecated ) - log.info("Initialising Channel %d with the following parameters: \n%s\n%s", channel, pBtpSDR, pBtpFDR) + log.info( + "Initialising Channel %d with the following parameters: \n%s\n%s", + channel, + pBtpSDR, + pBtpFDR, + ) _canlib.canControlInitialize( self._control_handle, @@ -672,7 +719,10 @@ def __init__( # the message in ticks. The resolution of a tick can be calculated from the fields # dwClockFreq and dwTscDivisor of the structure CANCAPABILITIES in accordance with the following formula: # frequency [1/s] = dwClockFreq / dwTscDivisor - self._tick_resolution = self._channel_capabilities.dwTscClkFreq / self._channel_capabilities.dwTscDivisor + self._tick_resolution = ( + self._channel_capabilities.dwTscClkFreq + / self._channel_capabilities.dwTscDivisor + ) # Setup filters before starting the channel if can_filters: @@ -690,7 +740,9 @@ def __init__( code = int(can_filter["can_id"]) mask = int(can_filter["can_mask"]) extended = can_filter.get("extended", False) - _canlib.canControlAddFilterIds(self._control_handle, 1 if extended else 0, code << 1, mask << 1) + _canlib.canControlAddFilterIds( + self._control_handle, 1 if extended else 0, code << 1, mask << 1 + ) log.info("Accepting ID: 0x%X MASK: 0x%X", code, mask) # Start the CAN controller. Messages will be forwarded to the channel @@ -705,7 +757,9 @@ def __init__( # Clear the FIFO by filter them out with low timeout for _ in range(rx_fifo_size): try: - _canlib.canChannelReadMessage(self._channel_handle, 0, ctypes.byref(self._message)) + _canlib.canChannelReadMessage( + self._channel_handle, 0, ctypes.byref(self._message) + ) except (VCITimeout, VCIRxQueueEmptyError): break @@ -733,7 +787,9 @@ def _recv_internal(self, timeout): if timeout == 0: # Peek without waiting try: - _canlib.canChannelPeekMessage(self._channel_handle, ctypes.byref(self._message)) + _canlib.canChannelPeekMessage( + self._channel_handle, ctypes.byref(self._message) + ) except (VCITimeout, VCIRxQueueEmptyError, VCIError): # VCIError means no frame available (canChannelPeekMessage returned different from zero) return None, True @@ -752,7 +808,9 @@ def _recv_internal(self, timeout): while True: try: - _canlib.canChannelReadMessage(self._channel_handle, remaining_ms, ctypes.byref(self._message)) + _canlib.canChannelReadMessage( + self._channel_handle, remaining_ms, ctypes.byref(self._message) + ) except (VCITimeout, VCIRxQueueEmptyError): # Ignore the 2 errors, the timeout is handled manually with the perf_counter() pass @@ -769,7 +827,9 @@ def _recv_internal(self, timeout): ) ) - elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR: + elif ( + self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR + ): log.warning( constants.CAN_ERROR_MESSAGES.get( self._message.abData[0], @@ -777,12 +837,17 @@ def _recv_internal(self, timeout): ) ) - elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_STATUS: + elif ( + self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_STATUS + ): log.info(_format_can_status(self._message.abData[0])) if self._message.abData[0] & constants.CAN_STATUS_BUSOFF: raise VCIBusOffError() - elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_TIMEOVR: + elif ( + self._message.uMsgInfo.Bits.type + == constants.CAN_MSGTYPE_TIMEOVR + ): pass else: log.warning("Unexpected message info type") @@ -800,11 +865,14 @@ def _recv_internal(self, timeout): # The _message.dwTime is a 32bit tick value and will overrun, # so expect to see the value restarting from 0 rx_msg = Message( - timestamp=self._message.dwTime / self._tick_resolution, # Relative time in s + timestamp=self._message.dwTime + / self._tick_resolution, # Relative time in s is_remote_frame=bool(self._message.uMsgInfo.Bits.rtr), is_fd=bool(self._message.uMsgInfo.Bits.edl), is_rx=True, - is_error_frame=bool(self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR), + is_error_frame=bool( + self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR + ), bitrate_switch=bool(self._message.uMsgInfo.Bits.fdr), error_state_indicator=bool(self._message.uMsgInfo.Bits.esi), is_extended_id=bool(self._message.uMsgInfo.Bits.ext), @@ -830,7 +898,11 @@ def send(self, msg: Message, timeout: Optional[float] = None) -> None: """ # This system is not designed to be very efficient message = structures.CANMSG2() - message.uMsgInfo.Bits.type = constants.CAN_MSGTYPE_ERROR if msg.is_error_frame else constants.CAN_MSGTYPE_DATA + message.uMsgInfo.Bits.type = ( + constants.CAN_MSGTYPE_ERROR + if msg.is_error_frame + else constants.CAN_MSGTYPE_DATA + ) message.uMsgInfo.Bits.rtr = 1 if msg.is_remote_frame else 0 message.uMsgInfo.Bits.ext = 1 if msg.is_extended_id else 0 message.uMsgInfo.Bits.srr = 1 if self.receive_own_messages else 0 @@ -841,12 +913,16 @@ def send(self, msg: Message, timeout: Optional[float] = None) -> None: if msg.dlc: # this dlc means number of bytes of payload message.uMsgInfo.Bits.dlc = len2dlc(msg.dlc) data_len_dif = msg.dlc - len(msg.data) - data = msg.data + bytearray([0] * data_len_dif) # pad with zeros until required length + data = msg.data + bytearray( + [0] * data_len_dif + ) # pad with zeros until required length adapter = (ctypes.c_uint8 * msg.dlc).from_buffer(data) ctypes.memmove(message.abData, adapter, msg.dlc) if timeout: - _canlib.canChannelSendMessage(self._channel_handle, int(timeout * 1000), message) + _canlib.canChannelSendMessage( + self._channel_handle, int(timeout * 1000), message + ) else: _canlib.canChannelPostMessage(self._channel_handle, message) @@ -862,12 +938,18 @@ def _send_periodic_internal( if modifier_callback is None: if self._scheduler is None: self._scheduler = HANDLE() - _canlib.canSchedulerOpen(self._device_handle, self.channel, self._scheduler) + _canlib.canSchedulerOpen( + self._device_handle, self.channel, self._scheduler + ) caps = structures.CANCAPABILITIES2() _canlib.canSchedulerGetCaps(self._scheduler, caps) - self._scheduler_resolution = caps.dwCmsClkFreq / caps.dwCmsDivisor # TODO: confirm + self._scheduler_resolution = ( + caps.dwCmsClkFreq / caps.dwCmsDivisor + ) # TODO: confirm _canlib.canSchedulerActivate(self._scheduler, constants.TRUE) - return CyclicSendTask(self._scheduler, msgs, period, duration, self._scheduler_resolution) + return CyclicSendTask( + self._scheduler, msgs, period, duration, self._scheduler_resolution + ) # fallback to thread based cyclic task warnings.warn( @@ -1009,10 +1091,21 @@ def _bit_timing_constructor( ) # if a bitrate and timings are supplied elif bitrate and not timing_obj and (tseg1_abr and tseg2_abr and sjw_abr): - pBtpSDR = structures.CANBTP(dwMode=0, dwBPS=bitrate, wTS1=tseg1_abr, wTS2=tseg2_abr, wSJW=sjw_abr, wTDO=0) + pBtpSDR = structures.CANBTP( + dwMode=0, + dwBPS=bitrate, + wTS1=tseg1_abr, + wTS2=tseg2_abr, + wSJW=sjw_abr, + wTDO=0, + ) # if a data_bitrate is supplied - if data_bitrate and not timing_obj and not (tseg1_dbr and tseg2_dbr and sjw_dbr): + if ( + data_bitrate + and not timing_obj + and not (tseg1_dbr and tseg2_dbr and sjw_dbr) + ): # unless timing segments are specified, try and use a predefined set of timings from constants.py pBtpFDR = constants.CAN_DATABITRATE_PRESETS.get(data_bitrate, None) if not pBtpFDR: @@ -1029,7 +1122,12 @@ def _bit_timing_constructor( if not ssp_dbr: ssp_dbr = tseg2_dbr pBtpFDR = structures.CANBTP( - dwMode=0, dwBPS=data_bitrate, wTS1=tseg1_dbr, wTS2=tseg2_dbr, wSJW=sjw_dbr, wTDO=ssp_dbr + dwMode=0, + dwBPS=data_bitrate, + wTS1=tseg1_dbr, + wTS2=tseg2_dbr, + wSJW=sjw_dbr, + wTDO=ssp_dbr, ) # if a timing object is provided @@ -1121,7 +1219,9 @@ class CyclicSendTask(LimitedDurationCyclicSendTaskABC, RestartableCyclicTaskABC) def __init__(self, scheduler, msgs, period, duration, resolution): super().__init__(msgs, period, duration) if len(self.messages) != 1: - raise ValueError("IXXAT Interface only supports periodic transmission of 1 element") + raise ValueError( + "IXXAT Interface only supports periodic transmission of 1 element" + ) self._scheduler = scheduler self._index = None @@ -1185,14 +1285,17 @@ def get_ixxat_hwids(): device_handle = HANDLE() device_info = structures.VCIDEVICEINFO() - _canlib.vciEnumDeviceOpen(ctypes.byref(device_handle)) - while True: - try: - _canlib.vciEnumDeviceNext(device_handle, ctypes.byref(device_info)) - except StopIteration: - break - else: - hwids.append(device_info.UniqueHardwareId.AsChar.decode("ascii")) - _canlib.vciEnumDeviceClose(device_handle) + try: + _canlib.vciEnumDeviceOpen(ctypes.byref(device_handle)) + while True: + try: + _canlib.vciEnumDeviceNext(device_handle, ctypes.byref(device_info)) + except StopIteration: + break + else: + hwids.append(device_info.UniqueHardwareId.AsChar.decode("ascii")) + _canlib.vciEnumDeviceClose(device_handle) + except AttributeError: + pass # _canlib is None in the CI tests -> return a blank list return hwids diff --git a/doc/interfaces/ixxat.rst b/doc/interfaces/ixxat.rst index b64c213e4..665a1c8cb 100644 --- a/doc/interfaces/ixxat.rst +++ b/doc/interfaces/ixxat.rst @@ -36,8 +36,7 @@ module, while the following parameters are optional and are interpreted by IXXAT * ``tx_fifo_size`` (default 16 for CAN, 128 for CAN-FD) Number of TX mailboxes. * ``bitrate`` (default 500000) Channel bitrate. * ``data_bitrate`` (defaults to 2Mbps) Channel data bitrate (only CAN-FD, to use when message bitrate_switch is used). -* ``timing`` (optional) a :class:`~can.BitTiming` or :class:`~can.BitTimingFd` instance. If this argument is provided, -the bitrate and data_bitrate parameters are overridden. +* ``timing`` (optional) a :class:`~can.BitTiming` or :class:`~can.BitTimingFd` instance. If this argument is provided, the bitrate and data_bitrate parameters are overridden. The following deprecated parameters will be removed in python-can version 5.0.0. diff --git a/test/test_interface_ixxat.py b/test/test_interface_ixxat.py index c826557f9..3e2a5a5ca 100644 --- a/test/test_interface_ixxat.py +++ b/test/test_interface_ixxat.py @@ -12,6 +12,8 @@ import unittest import can +from can.interfaces.ixxat import get_ixxat_hwids +from can.interfaces.ixxat.canlib import _format_can_status logger = logging.getLogger("can.ixxat") default_test_bitrate = 250_000 @@ -36,7 +38,39 @@ def get_records(self): class TestSoftwareCase(unittest.TestCase): """ - Test cases that test the software only and do not rely on an existing/connected hardware. + Test cases that test the python-can software only + """ + + def setUp(self): + self.log_capture = LogCaptureHandler() + log = logging.getLogger("can.ixxat") + log.addHandler(self.log_capture) + log.setLevel(logging.INFO) + + def tearDown(self): + logging.getLogger("can.ixxat").removeHandler(self.log_capture) + + def test_interface_detection(self): + if_list = can.detect_available_configs("ixxat") + self.assertIsInstance(if_list, list) + + def test_get_ixxat_hwids(self): + hwid_list = get_ixxat_hwids() + self.assertIsInstance(hwid_list, list) + + def test_format_can_status(self): + self.assertIsInstance(_format_can_status(0x01), str) + self.assertIsInstance(_format_can_status(0x02), str) + self.assertIsInstance(_format_can_status(0x04), str) + self.assertIsInstance(_format_can_status(0x08), str) + self.assertIsInstance(_format_can_status(0x10), str) + self.assertIsInstance(_format_can_status(0x20), str) + + +class TestDriverCase(unittest.TestCase): + """ + Test cases that do not rely on an existing/connected hardware, but test the software and driver communication. + The VCI 4 driver must be installed for these tests """ def setUp(self): @@ -45,6 +79,7 @@ def setUp(self): log.addHandler(self.log_capture) log.setLevel(logging.INFO) try: + # if the driver bus = can.Bus(interface="ixxat", channel=0, bitrate=default_test_bitrate) bus.shutdown() except can.CanInterfaceNotImplementedError as exc: From 44cb24fc4186aeecdd0b385057f89239c4a242ba Mon Sep 17 00:00:00 2001 From: MattWoodhead Date: Sun, 11 Jun 2023 22:45:13 +0100 Subject: [PATCH 08/15] format test --- can/interfaces/ixxat/canlib.py | 1 - test/test_interface_ixxat.py | 64 +++++++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 14 deletions(-) diff --git a/can/interfaces/ixxat/canlib.py b/can/interfaces/ixxat/canlib.py index 1644e5973..8da774b32 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/can/interfaces/ixxat/canlib.py @@ -56,7 +56,6 @@ if sys.platform in ("win32", "cygwin"): try: _canlib = CLibrary("vcinpl2.dll") - print(type(_canlib)) except Exception as e: log.warning("Cannot load IXXAT vcinpl library: %s", e) else: diff --git a/test/test_interface_ixxat.py b/test/test_interface_ixxat.py index 3e2a5a5ca..d8fca2013 100644 --- a/test/test_interface_ixxat.py +++ b/test/test_interface_ixxat.py @@ -17,7 +17,9 @@ logger = logging.getLogger("can.ixxat") default_test_bitrate = 250_000 -default_test_msg = can.Message(arbitration_id=0xC0FFEE, dlc=6, data=[0x70, 0x79, 0x74, 0x68, 0x6F, 0x6E]) +default_test_msg = can.Message( + arbitration_id=0xC0FFEE, dlc=6, data=[0x70, 0x79, 0x74, 0x68, 0x6F, 0x6E] +) class LogCaptureHandler(logging.Handler): @@ -95,11 +97,21 @@ def test_bus_creation(self): # rx_fifo_size must be > 0 with self.assertRaises(ValueError): - can.Bus(interface="ixxat", channel=0, rx_fifo_size=0, bitrate=default_test_bitrate) + can.Bus( + interface="ixxat", + channel=0, + rx_fifo_size=0, + bitrate=default_test_bitrate, + ) # tx_fifo_size must be > 0 with self.assertRaises(ValueError): - can.Bus(interface="ixxat", channel=0, tx_fifo_size=0, bitrate=default_test_bitrate) + can.Bus( + interface="ixxat", + channel=0, + tx_fifo_size=0, + bitrate=default_test_bitrate, + ) class TestHardwareCase(unittest.TestCase): @@ -128,7 +140,13 @@ def test_bus_creation_arbitrary_bitrate(self): target_bitrate = 444_444 with can.Bus(interface="ixxat", channel=0, bitrate=target_bitrate) as bus: timing = bus._status().sBtpSdr - bus_timing = can.BitTiming(self.clock_frequency, timing.dwBPS, timing.wTS1, timing.wTS2, timing.wSJW) + bus_timing = can.BitTiming( + self.clock_frequency, + timing.dwBPS, + timing.wTS1, + timing.wTS2, + timing.wSJW, + ) self.assertEqual( target_bitrate, bus_timing.bitrate, @@ -158,13 +176,25 @@ def test_bus_creation_timing_arg(self): def test_bus_creation_deprecated_timing_args(self): # try: - bus = can.Bus(interface="ixxat", channel=0, bitrate=default_test_bitrate, sjw_abr=1, tseg1_abr=13, tseg2_abr=2) + bus = can.Bus( + interface="ixxat", + channel=0, + bitrate=default_test_bitrate, + sjw_abr=1, + tseg1_abr=13, + tseg2_abr=2, + ) bus.shutdown() # except can.CanInterfaceNotImplementedError: # raise unittest.SkipTest("not available on this platform") def test_send_single(self): - with can.Bus(interface="ixxat", channel=0, bitrate=default_test_bitrate, receive_own_messages=True) as bus: + with can.Bus( + interface="ixxat", + channel=0, + bitrate=default_test_bitrate, + receive_own_messages=True, + ) as bus: bus.send(default_test_msg) response = bus.recv(0.1) @@ -184,7 +214,8 @@ def test_send_single(self): if captured_logs[-1] == "CAN bit error": raise can.exceptions.CanOperationError( "CAN bit error - Ensure you are connected to a " - "properly terminated bus configured at %s bps" % default_test_bitrate + "properly terminated bus configured at %s bps" + % default_test_bitrate ) elif captured_logs[-1] == "CAN ack error": @@ -205,7 +236,12 @@ def test_send_single(self): ) def test_send_periodic(self): - with can.Bus(interface="ixxat", channel=0, bitrate=default_test_bitrate, receive_own_messages=True) as bus: + with can.Bus( + interface="ixxat", + channel=0, + bitrate=default_test_bitrate, + receive_own_messages=True, + ) as bus: # setup Notifier and BufferedReader instances to receive messages msg_rx_buffer = can.BufferedReader() msg_notifier = can.Notifier(bus, [msg_rx_buffer]) @@ -225,8 +261,12 @@ def test_send_periodic(self): messages.append(msg) if messages: - self.assertGreaterEqual(len(messages), 9) # should be 10 messages - give ±1 margin for timing issues - self.assertLessEqual(len(messages), 11) # should be 10 messages - give ±1 margin for timing issues + self.assertGreaterEqual( + len(messages), 9 + ) # should be 10 messages - give ±1 margin for timing issues + self.assertLessEqual( + len(messages), 11 + ) # should be 10 messages - give ±1 margin for timing issues self.assertEqual( messages[-1].arbitration_id, default_test_msg.arbitration_id, @@ -238,9 +278,7 @@ def test_send_periodic(self): "The Data fields of the sent message and the received message do not match", ) else: - raise can.exceptions.CanOperationError( - "No messages have been received" - ) + raise can.exceptions.CanOperationError("No messages have been received") def test_bus_creation_invalid_channel(self): # non-existent channel -> use arbitrary high value From 06ee98cf608e8ccf3a2072637f957f01c699219e Mon Sep 17 00:00:00 2001 From: MattWoodhead Date: Mon, 12 Jun 2023 22:14:08 +0100 Subject: [PATCH 09/15] Fix send_periodic --- can/interfaces/ixxat/canlib.py | 67 +++++++++++++++++++++++----------- test/test_interface_ixxat.py | 18 +++++++++ 2 files changed, 64 insertions(+), 21 deletions(-) diff --git a/can/interfaces/ixxat/canlib.py b/can/interfaces/ixxat/canlib.py index 8da774b32..841854026 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/can/interfaces/ixxat/canlib.py @@ -507,7 +507,7 @@ def __init__( ssp_dbr = kwargs.get("ssp_dbr") # setup buffer sizes - if rx_fifo_size: # if the user provided an rx fifo size + if rx_fifo_size is not None: # if the user provided an rx fifo size if rx_fifo_size <= 0: raise ValueError("rx_fifo_size must be > 0") else: # otherwise use the default size (depending upon if FD or not) @@ -515,7 +515,7 @@ def __init__( if fd: rx_fifo_size = 1024 - if tx_fifo_size: # if the user provided a tx fifo size + if tx_fifo_size is not None: # if the user provided a tx fifo size if tx_fifo_size <= 0: raise ValueError("tx_fifo_size must be > 0") else: # otherwise use the default size (depending upon if FD or not) @@ -529,7 +529,6 @@ def __init__( self._channel_handle = HANDLE() self._channel_capabilities = structures.CANCAPABILITIES2() self._message = structures.CANMSG2() - self._bus_load_calculation = False if fd: self._payload = (ctypes.c_byte * 64)() else: @@ -652,6 +651,15 @@ def __init__( self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_BUSLOAD ) != 0: self._bus_load_calculation = True + else: + self._bus_load_calculation = False + + if ( # controller supports hardware scheduling of cyclic messages + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_SCHEDULER + ) != 0: + self._interface_scheduler_capable = True + else: + self._interface_scheduler_capable = False bExMode = constants.CAN_EXMODE_DISABLED self._can_protocol = CanProtocol.CAN_20 # default to standard CAN protocol @@ -935,26 +943,40 @@ def _send_periodic_internal( ) -> CyclicSendTaskABC: """Send a message using built-in cyclic transmit list functionality.""" if modifier_callback is None: - if self._scheduler is None: - self._scheduler = HANDLE() - _canlib.canSchedulerOpen( - self._device_handle, self.channel, self._scheduler + if self._interface_scheduler_capable: # address issue #1121 + if self._scheduler is None: + self._scheduler = HANDLE() + _canlib.canSchedulerOpen( + self._device_handle, self.channel, self._scheduler + ) + caps = structures.CANCAPABILITIES2() + _canlib.canSchedulerGetCaps(self._scheduler, caps) + self._scheduler_resolution = ( + caps.dwCmsClkFreq / caps.dwCmsDivisor + ) # TODO: confirm + _canlib.canSchedulerActivate(self._scheduler, constants.TRUE) + return CyclicSendTask( + self._scheduler, + msgs, + period, + duration, + self._scheduler_resolution, + self.receive_own_messages, ) - caps = structures.CANCAPABILITIES2() - _canlib.canSchedulerGetCaps(self._scheduler, caps) - self._scheduler_resolution = ( - caps.dwCmsClkFreq / caps.dwCmsDivisor - ) # TODO: confirm - _canlib.canSchedulerActivate(self._scheduler, constants.TRUE) - return CyclicSendTask( - self._scheduler, msgs, period, duration, self._scheduler_resolution + else: + # fallback to thread based cyclic task + warnings.warn( + "Falling back to a thread-based cyclic task:\n The CAN_FEATURE_SCHEDULER flag is false for " + f"interface {self._device_info.UniqueHardwareId.AsChar.decode('ascii')}" + ) + else: + # fallback to thread based cyclic task + warnings.warn( + f"{self.__class__.__name__} falls back to a thread-based cyclic task, " + "when the `modifier_callback` argument is given." ) - # fallback to thread based cyclic task - warnings.warn( - f"{self.__class__.__name__} falls back to a thread-based cyclic task, " - "when the `modifier_callback` argument is given." - ) + # return the BusABC periodic send task if the device is not scheduler capable or modifier_callback is used return BusABC._send_periodic_internal( self, msgs=msgs, @@ -1215,7 +1237,9 @@ def _detect_available_configs() -> List[AutoDetectedConfig]: class CyclicSendTask(LimitedDurationCyclicSendTaskABC, RestartableCyclicTaskABC): """A message in the cyclic transmit list.""" - def __init__(self, scheduler, msgs, period, duration, resolution): + def __init__( + self, scheduler, msgs, period, duration, resolution, receive_own_messages=False + ): super().__init__(msgs, period, duration) if len(self.messages) != 1: raise ValueError( @@ -1233,6 +1257,7 @@ def __init__(self, scheduler, msgs, period, duration, resolution): self._msg.uMsgInfo.Bits.ext = 1 if self.messages[0].is_extended_id else 0 self._msg.uMsgInfo.Bits.rtr = 1 if self.messages[0].is_remote_frame else 0 self._msg.uMsgInfo.Bits.dlc = self.messages[0].dlc + self._msg.uMsgInfo.Bits.srr = 1 if receive_own_messages else 0 for i, b in enumerate(self.messages[0].data): self._msg.abData[i] = b self.start() diff --git a/test/test_interface_ixxat.py b/test/test_interface_ixxat.py index d8fca2013..5317b4070 100644 --- a/test/test_interface_ixxat.py +++ b/test/test_interface_ixxat.py @@ -280,6 +280,24 @@ def test_send_periodic(self): else: raise can.exceptions.CanOperationError("No messages have been received") + def test_send_periodic_busabc_fallback(self): + with can.Bus( + interface="ixxat", + channel=0, + bitrate=default_test_bitrate, + receive_own_messages=True, + ) as bus: + # setup Notifier and BufferedReader instances to receive messages + bus._interface_scheduler_capable = False + + # setup periodic send task + task = bus.send_periodic(default_test_msg, 0.2) + assert isinstance(task, can.CyclicSendTaskABC) + time.sleep(2) + task.stop() + + + def test_bus_creation_invalid_channel(self): # non-existent channel -> use arbitrary high value with self.assertRaises(can.CanInitializationError): From 0d90b5d296d42296ce14ddf843f502d9114f571b Mon Sep 17 00:00:00 2001 From: MattWoodhead Date: Mon, 12 Jun 2023 22:58:55 +0100 Subject: [PATCH 10/15] Add FD tests. Fix linux / mac tests --- can/ctypesutil.py | 4 +- can/interfaces/ixxat/canlib.py | 4 ++ test/test_interface_ixxat.py | 82 +++++++++++++++++++++++++++++---- test/test_interface_ixxat_fd.py | 65 -------------------------- 4 files changed, 80 insertions(+), 75 deletions(-) delete mode 100644 test/test_interface_ixxat_fd.py diff --git a/can/ctypesutil.py b/can/ctypesutil.py index e624db6d2..66ad4bbf3 100644 --- a/can/ctypesutil.py +++ b/can/ctypesutil.py @@ -77,12 +77,14 @@ def map_symbol( if sys.platform == "win32": HRESULT = ctypes.HRESULT - elif sys.platform == "cygwin": class HRESULT(ctypes.c_long): pass +else: + HRESULT = None + # Common win32 definitions class HANDLE(ctypes.c_void_p): diff --git a/can/interfaces/ixxat/canlib.py b/can/interfaces/ixxat/canlib.py index 841854026..20c475887 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/can/interfaces/ixxat/canlib.py @@ -770,6 +770,10 @@ def __init__( except (VCITimeout, VCIRxQueueEmptyError): break + # TODO - it should be possible to implement a query to the VCI driver to check if there is an existing + # open handle to the VCI comms layer (either from python-can or another program). This would be worth + # implementing as an open handle with an active bus will prevent the bitrate from being altered. + super().__init__(channel=channel, can_filters=None, **kwargs) def _inWaiting(self): diff --git a/test/test_interface_ixxat.py b/test/test_interface_ixxat.py index 5317b4070..34150f2a4 100644 --- a/test/test_interface_ixxat.py +++ b/test/test_interface_ixxat.py @@ -1,7 +1,5 @@ -#!/usr/bin/env python - """ -Unittest for ixxat interface. +Unittest for ixxat VCI4 interface. Run only this test: python setup.py test --addopts "--verbose -s test/test_interface_ixxat.py" @@ -12,6 +10,7 @@ import unittest import can +import can.interfaces.ixxat.canlib as ixxat_canlib_module from can.interfaces.ixxat import get_ixxat_hwids from can.interfaces.ixxat.canlib import _format_can_status @@ -45,18 +44,23 @@ class TestSoftwareCase(unittest.TestCase): def setUp(self): self.log_capture = LogCaptureHandler() + # ensure we test as if there is no driver even if it is installed + self._canlib = ixxat_canlib_module._canlib + ixxat_canlib_module._canlib = None log = logging.getLogger("can.ixxat") log.addHandler(self.log_capture) log.setLevel(logging.INFO) def tearDown(self): + # replace the driver reference for the other tests + ixxat_canlib_module._canlib = self._canlib logging.getLogger("can.ixxat").removeHandler(self.log_capture) - def test_interface_detection(self): + def test_interface_detection(self): # driver missing test if_list = can.detect_available_configs("ixxat") self.assertIsInstance(if_list, list) - def test_get_ixxat_hwids(self): + def test_get_ixxat_hwids(self): # driver missing test hwid_list = get_ixxat_hwids() self.assertIsInstance(hwid_list, list) @@ -90,7 +94,15 @@ def setUp(self): def tearDown(self): logging.getLogger("can.ixxat").removeHandler(self.log_capture) - def test_bus_creation(self): + def test_interface_detection(self): # driver present test + if_list = can.detect_available_configs("ixxat") + self.assertIsInstance(if_list, list) + + def test_get_ixxat_hwids(self): # driver present test + hwid_list = get_ixxat_hwids() + self.assertIsInstance(hwid_list, list) + + def test_bus_creation_std(self): # channel must be >= 0 with self.assertRaises(ValueError): can.Bus(interface="ixxat", channel=-1, bitrate=default_test_bitrate) @@ -113,8 +125,33 @@ def test_bus_creation(self): bitrate=default_test_bitrate, ) + def test_bus_creation_fd(self): + # channel must be >= 0 + with self.assertRaises(ValueError): + can.Bus(interface="ixxat", fd=True, channel=-1) + + # rx_fifo_size must be > 0 + with self.assertRaises(ValueError): + can.Bus( + interface="ixxat", + fd=True, + channel=0, + rx_fifo_size=0, + bitrate=default_test_bitrate, + ) -class TestHardwareCase(unittest.TestCase): + # tx_fifo_size must be > 0 + with self.assertRaises(ValueError): + can.Bus( + interface="ixxat", + fd=True, + channel=0, + tx_fifo_size=0, + bitrate=default_test_bitrate, + ) + + +class TestHardwareCaseStd(unittest.TestCase): """ Test cases that rely on an existing/connected hardware. """ @@ -296,8 +333,6 @@ def test_send_periodic_busabc_fallback(self): time.sleep(2) task.stop() - - def test_bus_creation_invalid_channel(self): # non-existent channel -> use arbitrary high value with self.assertRaises(can.CanInitializationError): @@ -310,5 +345,34 @@ def test_send_after_shutdown(self): bus.send(default_test_msg) +class HardwareTestCaseFd(unittest.TestCase): + """ + Test cases that rely on an existing/connected hardware with CAN FD capability + """ + + def setUp(self): + try: + bus = can.Bus(interface="ixxat", fd=True, channel=0) + bus.shutdown() + except can.CanInterfaceNotImplementedError as exc: + raise unittest.SkipTest("not available on this platform") from exc + except can.CanInitializationError as exc: + raise unittest.SkipTest("connected hardware is not FD capable") from exc + + def test_bus_creation(self): + # non-existent channel -> use arbitrary high value + with self.assertRaises(can.CanInitializationError): + can.Bus( + interface="ixxat", fd=True, channel=0xFFFF, bitrate=default_test_bitrate + ) + + def test_send_after_shutdown(self): + with can.Bus( + interface="ixxat", fd=True, channel=0, bitrate=default_test_bitrate + ) as bus: + with self.assertRaises(can.CanOperationError): + bus.send(can.Message(arbitration_id=0x3FF, dlc=0)) + + if __name__ == "__main__": unittest.main() diff --git a/test/test_interface_ixxat_fd.py b/test/test_interface_ixxat_fd.py deleted file mode 100644 index 7274498aa..000000000 --- a/test/test_interface_ixxat_fd.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python - -""" -Unittest for ixxat interface using fd option. - -Run only this test: -python setup.py test --addopts "--verbose -s test/test_interface_ixxat_fd.py" -""" - -import unittest - -import can - - -class SoftwareTestCase(unittest.TestCase): - """ - Test cases that test the software only and do not rely on an existing/connected hardware. - """ - - def setUp(self): - try: - bus = can.Bus(interface="ixxat", fd=True, channel=0) - bus.shutdown() - except can.CanInterfaceNotImplementedError: - raise unittest.SkipTest("not available on this platform") - - def test_bus_creation(self): - # channel must be >= 0 - with self.assertRaises(ValueError): - can.Bus(interface="ixxat", fd=True, channel=-1) - - # rx_fifo_size must be > 0 - with self.assertRaises(ValueError): - can.Bus(interface="ixxat", fd=True, channel=0, rx_fifo_size=0) - - # tx_fifo_size must be > 0 - with self.assertRaises(ValueError): - can.Bus(interface="ixxat", fd=True, channel=0, tx_fifo_size=0) - - -class HardwareTestCase(unittest.TestCase): - """ - Test cases that rely on an existing/connected hardware. - """ - - def setUp(self): - try: - bus = can.Bus(interface="ixxat", fd=True, channel=0) - bus.shutdown() - except can.CanInterfaceNotImplementedError: - raise unittest.SkipTest("not available on this platform") - - def test_bus_creation(self): - # non-existent channel -> use arbitrary high value - with self.assertRaises(can.CanInitializationError): - can.Bus(interface="ixxat", fd=True, channel=0xFFFF) - - def test_send_after_shutdown(self): - with can.Bus(interface="ixxat", fd=True, channel=0) as bus: - with self.assertRaises(can.CanOperationError): - bus.send(can.Message(arbitration_id=0x3FF, dlc=0)) - - -if __name__ == "__main__": - unittest.main() From 84b139d975a6edb75256b5cbecc5cb9a88942b90 Mon Sep 17 00:00:00 2001 From: MattWoodhead Date: Tue, 13 Jun 2023 06:32:40 +0100 Subject: [PATCH 11/15] string formatting in constants --- can/interfaces/ixxat/canlib.py | 6 +-- can/interfaces/ixxat/structures.py | 75 ++++++++++++++++-------------- 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/can/interfaces/ixxat/canlib.py b/can/interfaces/ixxat/canlib.py index 20c475887..1b044db06 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/can/interfaces/ixxat/canlib.py @@ -99,9 +99,7 @@ def __vciFormatError(library_instance: CLibrary, function: Callable, vret: int): buf = ctypes.create_string_buffer(constants.VCI_MAX_ERRSTRLEN) ctypes.memset(buf, 0, constants.VCI_MAX_ERRSTRLEN) library_instance.vciFormatError(vret, buf, constants.VCI_MAX_ERRSTRLEN) - return "function {} failed ({})".format( - function._name, buf.value.decode("utf-8", "replace") - ) + return f"function {function._name} failed ({buf.value.decode('utf-8', 'replace')})" def __check_status(result: int, function: Callable, args: Tuple): @@ -1302,7 +1300,7 @@ def _format_can_status(status_flags: int): states.append(f"unknown state 0x{status_flags:02x}") if states: - return "CAN status message: {}".format(", ".join(states)) + return f"CAN status message: {', '.join(states)}" else: return "Empty CAN status message" diff --git a/can/interfaces/ixxat/structures.py b/can/interfaces/ixxat/structures.py index d5cca1c6c..af3f59af1 100644 --- a/can/interfaces/ixxat/structures.py +++ b/can/interfaces/ixxat/structures.py @@ -135,13 +135,15 @@ class CANBTP(ctypes.Structure): ] def __str__(self): - return "dwMode=%d, dwBPS=%d, wTS1=%d, wTS2=%d, wSJW=%d, wTDO=%d" % ( - self.dwMode, - self.dwBPS, - self.wTS1, - self.wTS2, - self.wSJW, - self.wTDO, + return ", ".join( + ( + f"dwMode={self.dwMode}", + f"dwBPS={self.dwBPS}", + f"wTS1={self.wTS1}", + f"wTS2={self.wTS2}", + f"wSJW={self.wSJW}", + f"wTDO={self.wTDO}", + ) ) @@ -192,22 +194,22 @@ class CANCAPABILITIES2(ctypes.Structure): def __str__(self): cap = ", ".join( ( - "wCtrlType=%s" % self.wCtrlType, - "wBusCoupling=%s" % self.wBusCoupling, - "dwFeatures=%s" % self.dwFeatures, - "dwCanClkFreq=%s" % self.dwCanClkFreq, - "sSdrRangeMin=%s" % self.sSdrRangeMin, - "sSdrRangeMax=%s" % self.sSdrRangeMax, - "sFdrRangeMin=%s" % self.sFdrRangeMin, - "sFdrRangeMax=%s" % self.sFdrRangeMax, - "dwTscClkFreq=%s" % self.dwTscClkFreq, - "dwTscDivisor=%s" % self.dwTscDivisor, - "dwCmsClkFreq=%s" % self.dwCmsClkFreq, - "dwCmsDivisor=%s" % self.dwCmsDivisor, - "dwCmsMaxTicks=%s" % self.dwCmsMaxTicks, - "dwDtxClkFreq=%s" % self.dwDtxClkFreq, - "dwDtxDivisor=%s" % self.dwDtxDivisor, - "dwDtxMaxTicks=%s" % self.dwDtxMaxTicks, + f"wCtrlType={self.wCtrlType}", + f"wBusCoupling={self.wBusCoupling}", + f"dwFeatures={self.dwFeatures}", + f"dwCanClkFreq={self.dwCanClkFreq}", + f"sSdrRangeMin={self.sSdrRangeMin}", + f"sSdrRangeMax={self.sSdrRangeMax}", + f"sFdrRangeMin={self.sFdrRangeMin}", + f"sFdrRangeMax={self.sFdrRangeMax}", + f"dwTscClkFreq={self.dwTscClkFreq}", + f"dwTscDivisor={self.dwTscDivisor}", + f"dwCmsClkFreq={self.dwCmsClkFreq}", + f"dwCmsDivisor={self.dwCmsDivisor}", + f"dwCmsMaxTicks={self.dwCmsMaxTicks}", + f"dwDtxClkFreq={self.dwDtxClkFreq}", + f"dwDtxDivisor={self.dwDtxDivisor}", + f"dwDtxMaxTicks={self.dwDtxMaxTicks}", ) ) return cap @@ -228,14 +230,15 @@ class CANLINESTATUS2(ctypes.Structure): ] def __str__(self) -> str: - return "\n".join( + return ", ".join( ( - f"Std Operating Mode: {self.bOpMode}", - f"Ext Operating Mode: {self.bExMode}", - f"Bus Load (%): {self.bBusLoad}", - f"Standard Bitrate Timing: {self.sBtpSdr}", - f"Fast Datarate timing: {self.sBtpFdr}", - f"CAN Controller Status: {self.dwStatus}", + f"bOpMode={self.bOpMode}", + f"bExMode={self.bExMode}", + f"bBusLoad={self.bBusLoad}", + f"bReserved={self.bReserved}", + f"sBtpSdr={self.sBtpSdr}", + f"sBtpFdr={self.sBtpFdr}", + f"dwStatus={self.dwStatus}", ) ) @@ -253,13 +256,13 @@ class CANCHANSTATUS2(ctypes.Structure): ] def __str__(self) -> str: - return "\n".join( + return ", ".join( ( - f"Status: {self.sLineStatus}", - f"Activated: {bool(self.fActivated)}", - f"RxOverrun: {bool(self.fRxOverrun)}", - f"Rx Buffer Load (%): {self.bRxFifoLoad}", - f"Tx Buffer Load (%): {self.bTxFifoLoad}", + f"sLineStatus={self.sLineStatus}", + f"fActivated={bool(self.fActivated)}", + f"fRxOverrun={bool(self.fRxOverrun)}", + f"bRxFifoLoad={self.bRxFifoLoad}", + f"bTxFifoLoad={self.bTxFifoLoad}", ) ) From 47e6e845a08a11bd9162d01719fe18ab01d193be Mon Sep 17 00:00:00 2001 From: MattWoodhead Date: Wed, 21 Jun 2023 21:51:54 +0100 Subject: [PATCH 12/15] Add warning instead of failing silently Log a warning when a VCI_E_ACCESSDENIED error is returned from a driver function call. --- can/interfaces/ixxat/canlib.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/can/interfaces/ixxat/canlib.py b/can/interfaces/ixxat/canlib.py index 1b044db06..bb7344b7a 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/can/interfaces/ixxat/canlib.py @@ -126,7 +126,8 @@ def __check_status(result: int, function: Callable, args: Tuple): elif result == constants.VCI_E_NO_MORE_ITEMS: raise StopIteration() elif result == constants.VCI_E_ACCESSDENIED: - pass # not a real error, might happen if another program has initialized the bus + log.warning(f"VCI_E_ACCESSDENIED error raised when calling VCI Function {function._name}") + # not a real error, might happen if another program has initialized the bus elif result != constants.VCI_OK: raise VCIError(vciFormatError(function, result)) From 1a594443c25868e48a04c3480ff6ad0cd10cbe51 Mon Sep 17 00:00:00 2001 From: MattWoodhead Date: Sat, 24 Jun 2023 13:21:39 +0100 Subject: [PATCH 13/15] Add multiple bus instance test case --- can/interfaces/ixxat/canlib.py | 4 +- test/test_interface_ixxat.py | 104 ++++++++++++++++++++++++++++++++- 2 files changed, 105 insertions(+), 3 deletions(-) diff --git a/can/interfaces/ixxat/canlib.py b/can/interfaces/ixxat/canlib.py index bb7344b7a..74a3cdb28 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/can/interfaces/ixxat/canlib.py @@ -126,7 +126,9 @@ def __check_status(result: int, function: Callable, args: Tuple): elif result == constants.VCI_E_NO_MORE_ITEMS: raise StopIteration() elif result == constants.VCI_E_ACCESSDENIED: - log.warning(f"VCI_E_ACCESSDENIED error raised when calling VCI Function {function._name}") + log.warning( + f"VCI_E_ACCESSDENIED error raised when calling VCI Function {function._name}" + ) # not a real error, might happen if another program has initialized the bus elif result != constants.VCI_OK: raise VCIError(vciFormatError(function, result)) diff --git a/test/test_interface_ixxat.py b/test/test_interface_ixxat.py index 34150f2a4..573fca593 100644 --- a/test/test_interface_ixxat.py +++ b/test/test_interface_ixxat.py @@ -5,6 +5,7 @@ python setup.py test --addopts "--verbose -s test/test_interface_ixxat.py" """ +from copy import copy import logging import time import unittest @@ -14,6 +15,7 @@ from can.interfaces.ixxat import get_ixxat_hwids from can.interfaces.ixxat.canlib import _format_can_status + logger = logging.getLogger("can.ixxat") default_test_bitrate = 250_000 default_test_msg = can.Message( @@ -21,6 +23,9 @@ ) +TESTING_DEBUG_LEVEL = logging.INFO + + class LogCaptureHandler(logging.Handler): """ Allows a test case to get access to the logs raised in another module @@ -49,7 +54,7 @@ def setUp(self): ixxat_canlib_module._canlib = None log = logging.getLogger("can.ixxat") log.addHandler(self.log_capture) - log.setLevel(logging.INFO) + log.setLevel(TESTING_DEBUG_LEVEL) def tearDown(self): # replace the driver reference for the other tests @@ -83,7 +88,7 @@ def setUp(self): self.log_capture = LogCaptureHandler() log = logging.getLogger("can.ixxat") log.addHandler(self.log_capture) - log.setLevel(logging.INFO) + log.setLevel(TESTING_DEBUG_LEVEL) try: # if the driver bus = can.Bus(interface="ixxat", channel=0, bitrate=default_test_bitrate) @@ -158,6 +163,9 @@ class TestHardwareCaseStd(unittest.TestCase): def setUp(self): self.log_capture = LogCaptureHandler() + log = logging.getLogger("can.ixxat") + log.addHandler(self.log_capture) + log.setLevel(TESTING_DEBUG_LEVEL) logging.getLogger("can.ixxat").addHandler(self.log_capture) try: bus = can.Bus(interface="ixxat", channel=0) @@ -333,6 +341,98 @@ def test_send_periodic_busabc_fallback(self): time.sleep(2) task.stop() + def test_multiple_bus_instances(self): + """This tests the access of multiple bus instances to the same adapter using the VCI 4 driver""" + + with can.Bus( + interface="ixxat", + channel=0, + bitrate=default_test_bitrate, + receive_own_messages=True, + ) as bus1: + with can.Bus( + interface="ixxat", + channel=0, + bitrate=default_test_bitrate, + receive_own_messages=True, + ) as bus2: + with can.Bus( + interface="ixxat", + channel=0, + bitrate=default_test_bitrate, + receive_own_messages=True, + ) as bus3: + bus1_msg = copy(default_test_msg) + bus1_msg.arbitration_id = bus1_msg.arbitration_id | 0x1000000 + bus2_msg = copy(default_test_msg) + bus2_msg.arbitration_id = bus2_msg.arbitration_id | 0x2000000 + bus3_msg = copy(default_test_msg) + bus3_msg.arbitration_id = bus3_msg.arbitration_id | 0x3000000 + # send a message on bus 1, and try to receive it on bus 2 and bus 3 + bus1.send(default_test_msg) + response2from1 = bus2.recv(0.1) + response3from1 = bus3.recv(0.1) + # send the same message on bus 2, and try to receive it on bus 1 and bus 3 + bus2.send(default_test_msg) + response1from2 = bus1.recv(0.1) + response3from2 = bus3.recv(0.1) + # send the same message on bus 3, and try to receive it on bus 1 and bus 2 + bus2.send(default_test_msg) + response1from3 = bus1.recv(0.1) + response2from3 = bus2.recv(0.1) + + if response2from1 and response3from1 and response1from2 and response3from2 and response1from3 and response2from3: + bus_checks = { + "sent from bus instance 1, received on bus instance 2": (response2from1, bus1_msg), + "sent from bus instance 1, received on bus instance 3": (response3from1, bus1_msg), + "sent from bus instance 2, received on bus instance 1": (response1from2, bus2_msg), + "sent from bus instance 2, received on bus instance 3": (response3from2, bus2_msg), + "sent from bus instance 3, received on bus instance 1": (response1from3, bus3_msg), + "sent from bus instance 3, received on bus instance 3": (response2from3, bus3_msg), + } + for case, msg_objects in bus_checks.items(): + self.assertEqual( + msg_objects[0].arbitration_id, + msg_objects[1].arbitration_id, + f"The Arbitration ID of the messages {case} do not match", + ) + self.assertEqual( + msg_objects[0].data, + msg_objects[1].data, + f"The Data fields of the messages {case} do not match.", + ) + else: + captured_logs = self.log_capture.get_records() + if captured_logs[-1] == "CAN bit error": + raise can.exceptions.CanOperationError( + "CAN bit error - Ensure you are connected to a properly " + "terminated bus configured at {default_test_bitrate} bps" + ) + + elif captured_logs[-1] == "CAN ack error": + raise can.exceptions.CanOperationError( + "CAN ack error - Ensure there is at least one other (silent) node to provide ack signals", + ) + else: + raise ValueError( + "\n".join( + ( + "At least one response does not match the sent message:", + f"Sent on bus instance 1: {default_test_msg}", + f" - Received on bus instance 2: {response2from1}", + f" - Received on bus instance 3: {response3from1}", + f"Sent on bus instance 2: {default_test_msg}", + f" - Received on bus instance 1: {response1from2}", + f" - Received on bus instance 3: {response3from2}", + f"Sent on interface 3: {default_test_msg}", + f" - Received on interface 1: {response1from3}", + f" - Received on interface 2: {response2from3}", + f"Last Caputred Log: {captured_logs[-1]}", + "Ensure hardware tests are run on a bus with no other traffic.", + ) + ) + ) + def test_bus_creation_invalid_channel(self): # non-existent channel -> use arbitrary high value with self.assertRaises(can.CanInitializationError): From da0ea874928e978c88e82017fe60f45b49168ecd Mon Sep 17 00:00:00 2001 From: MattWoodhead Date: Sun, 25 Jun 2023 12:13:21 +0100 Subject: [PATCH 14/15] fix ixxat test typos --- can/interfaces/ixxat/canlib.py | 7 ++++++- test/test_interface_ixxat.py | 12 ++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/can/interfaces/ixxat/canlib.py b/can/interfaces/ixxat/canlib.py index 74a3cdb28..f829aa25a 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/can/interfaces/ixxat/canlib.py @@ -705,8 +705,13 @@ def __init__( ) log.info( - "Initialising Channel %d with the following parameters: \n%s\n%s", + "Initialising Channel %d with the following parameters:\n" + "bOpMode=%d, bExMode=%d\n" + "pBtpSDR=%s\n" + "pBtpFDR=%s", channel, + bOpMode, + bExMode, pBtpSDR, pBtpFDR, ) diff --git a/test/test_interface_ixxat.py b/test/test_interface_ixxat.py index 573fca593..1ffa97e5b 100644 --- a/test/test_interface_ixxat.py +++ b/test/test_interface_ixxat.py @@ -369,15 +369,15 @@ def test_multiple_bus_instances(self): bus3_msg = copy(default_test_msg) bus3_msg.arbitration_id = bus3_msg.arbitration_id | 0x3000000 # send a message on bus 1, and try to receive it on bus 2 and bus 3 - bus1.send(default_test_msg) + bus1.send(bus1_msg) response2from1 = bus2.recv(0.1) response3from1 = bus3.recv(0.1) # send the same message on bus 2, and try to receive it on bus 1 and bus 3 - bus2.send(default_test_msg) + bus2.send(bus2_msg) response1from2 = bus1.recv(0.1) response3from2 = bus3.recv(0.1) # send the same message on bus 3, and try to receive it on bus 1 and bus 2 - bus2.send(default_test_msg) + bus3.send(bus3_msg) response1from3 = bus1.recv(0.1) response2from3 = bus2.recv(0.1) @@ -418,13 +418,13 @@ def test_multiple_bus_instances(self): "\n".join( ( "At least one response does not match the sent message:", - f"Sent on bus instance 1: {default_test_msg}", + f"Sent on bus instance 1: {bus1_msg}", f" - Received on bus instance 2: {response2from1}", f" - Received on bus instance 3: {response3from1}", - f"Sent on bus instance 2: {default_test_msg}", + f"Sent on bus instance 2: {bus2_msg}", f" - Received on bus instance 1: {response1from2}", f" - Received on bus instance 3: {response3from2}", - f"Sent on interface 3: {default_test_msg}", + f"Sent on interface 3: {bus3_msg}", f" - Received on interface 1: {response1from3}", f" - Received on interface 2: {response2from3}", f"Last Caputred Log: {captured_logs[-1]}", From 0ba02fe3cc2ae35dddd9f10e3f5577c0bef7a2e7 Mon Sep 17 00:00:00 2001 From: MattWoodhead Date: Wed, 30 Oct 2024 18:47:54 +0000 Subject: [PATCH 15/15] checkin old changes --- can/interfaces/ixxat/canlib.py | 258 +- can/interfaces/ixxat/constants.py | 12 +- report.html | 6999 +++++++++++++++++++++++++++++ test/test_interface_ixxat.py | 15 +- tox.ini | 3 +- 5 files changed, 7158 insertions(+), 129 deletions(-) create mode 100644 report.html diff --git a/can/interfaces/ixxat/canlib.py b/can/interfaces/ixxat/canlib.py index f829aa25a..30e867f98 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/can/interfaces/ixxat/canlib.py @@ -181,6 +181,8 @@ def __check_status(result: int, function: Callable, args: Tuple): (HANDLE, ctypes.c_uint32, ctypes.c_long, PHANDLE), __check_status, ) + # HRESULT VCIAPI vciDeviceGetInfo( IN HANDLE hDevice, OUT PVCIDEVICEINFO pInfo ); + _canlib.map_symbol("vciDeviceGetInfo", hresult_type, (HANDLE, structures.PVCIDEVICEINFO), __check_status) # EXTERN_C HRESULT VCIAPI # canChannelInitialize( IN HANDLE hCanChn, # IN UINT16 wRxFifoSize, @@ -259,6 +261,13 @@ def __check_status(result: int, function: Callable, args: Tuple): (HANDLE, ctypes.c_uint32, PHANDLE), __check_status, ) + # EXTERN_C HRESULT VCIAPI canChannelGetControl( IN HANDLE hCanChn, OUT PHANDLE phCanCtl ); + _canlib.map_symbol( + "canChannelGetControl", + hresult_type, + (HANDLE, PHANDLE), + __check_status, + ) # EXTERN_C HRESULT VCIAPI # canControlInitialize( IN HANDLE hCanCtl, # IN UINT8 bOpMode, @@ -612,121 +621,153 @@ def __init__( _canlib.canControlOpen( self._device_handle, channel, ctypes.byref(self._control_handle) ) + log.info("canControl status: %s", self._status) - log.debug("Fetching capabilities for interface channel %d", channel) _canlib.canControlGetCaps( self._control_handle, ctypes.byref(self._channel_capabilities) ) + log.info("canControlGetCaps result: %s", self._channel_capabilities) - # check capabilities - bOpMode = constants.CAN_OPMODE_UNDEFINED - if ( - self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT - ) != 0: - # controller supports CAN_OPMODE_STANDARD and CAN_OPMODE_EXTENDED at the same time - bOpMode |= constants.CAN_OPMODE_STANDARD # enable both 11 bits reception - if extended: # parameter from configuration - bOpMode |= constants.CAN_OPMODE_EXTENDED # enable 29 bits reception - elif ( - self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT - ) != 0: - log.warning( - "Channel %d capabilities allow either basic or extended IDs, but not both. using %s according to parameter [extended=%s]", - channel, - "extended" if extended else "basic", - "True" if extended else "False", - ) - # controller supports either CAN_OPMODE_STANDARD or CAN_OPMODE_EXTENDED, but not both simultaneously - bOpMode |= ( - constants.CAN_OPMODE_EXTENDED - if extended - else constants.CAN_OPMODE_STANDARD - ) - - if ( # controller supports receiving error frames: - self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_ERRFRAME - ) != 0: - bOpMode |= constants.CAN_OPMODE_ERRFRAME + if self._status.dwStatus == constants.CAN_STATUS_ININIT: - if ( # controller supports receiving error frames: - self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_BUSLOAD - ) != 0: - self._bus_load_calculation = True - else: - self._bus_load_calculation = False + # check capabilities + bOpMode = constants.CAN_OPMODE_UNDEFINED + if ( + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT + ) != 0: + # controller supports CAN_OPMODE_STANDARD and CAN_OPMODE_EXTENDED at the same time + bOpMode |= constants.CAN_OPMODE_STANDARD # enable both 11 bits reception + if extended: # parameter from configuration + bOpMode |= constants.CAN_OPMODE_EXTENDED # enable 29 bits reception + elif ( + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_STDANDEXT + ) != 0: + log.warning( + "Channel %d capabilities allow either basic or extended IDs, but not both. using %s according to parameter [extended=%s]", + channel, + "extended" if extended else "basic", + "True" if extended else "False", + ) + # controller supports either CAN_OPMODE_STANDARD or CAN_OPMODE_EXTENDED, but not both simultaneously + bOpMode |= ( + constants.CAN_OPMODE_EXTENDED + if extended + else constants.CAN_OPMODE_STANDARD + ) - if ( # controller supports hardware scheduling of cyclic messages - self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_SCHEDULER - ) != 0: - self._interface_scheduler_capable = True - else: - self._interface_scheduler_capable = False + if ( # controller supports receiving error frames: + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_ERRFRAME + ) != 0: + bOpMode |= constants.CAN_OPMODE_ERRFRAME - bExMode = constants.CAN_EXMODE_DISABLED - self._can_protocol = CanProtocol.CAN_20 # default to standard CAN protocol - if fd: - if ( - self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_EXTDATA + if ( # controller supports receiving error frames: + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_BUSLOAD ) != 0: - bExMode |= constants.CAN_EXMODE_EXTDATALEN + self._bus_load_calculation = True else: - raise CanInitializationError( - "The interface %s does not support extended data frames (FD)" - % self._device_info.UniqueHardwareId.AsChar.decode("ascii"), - ) - if ( - self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_FASTDATA + self._bus_load_calculation = False + + if ( # controller supports hardware scheduling of cyclic messages + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_SCHEDULER ) != 0: - bExMode |= constants.CAN_EXMODE_FASTDATA + self._interface_scheduler_capable = True else: + self._interface_scheduler_capable = False + + bExMode = constants.CAN_EXMODE_DISABLED + self._can_protocol = CanProtocol.CAN_20 # default to standard CAN protocol + if fd: + if ( + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_EXTDATA + ) != 0: + bExMode |= constants.CAN_EXMODE_EXTDATALEN + else: + raise CanInitializationError( + "The interface %s does not support extended data frames (FD)" + % self._device_info.UniqueHardwareId.AsChar.decode("ascii"), + ) + if ( + self._channel_capabilities.dwFeatures & constants.CAN_FEATURE_FASTDATA + ) != 0: + bExMode |= constants.CAN_EXMODE_FASTDATA + else: + raise CanInitializationError( + "The interface %s does not support fast data rates (FD)" + % self._device_info.UniqueHardwareId.AsChar.decode("ascii"), + ) + # set bus to CAN FD protocol once FD capability is verified + self._can_protocol = CanProtocol.CAN_FD + + if timing and not isinstance(timing, (BitTiming, BitTimingFd)): raise CanInitializationError( - "The interface %s does not support fast data rates (FD)" - % self._device_info.UniqueHardwareId.AsChar.decode("ascii"), + "The timing parameter to the Ixxat Bus must be None, or an instance of can.BitTiming or can.BitTimingFd" ) - # set bus to CAN FD protocol once FD capability is verified - self._can_protocol = CanProtocol.CAN_FD - if timing and not isinstance(timing, (BitTiming, BitTimingFd)): - raise CanInitializationError( - "The timing parameter to the Ixxat Bus must be None, or an instance of can.BitTiming or can.BitTimingFd" + pBtpSDR, pBtpFDR = self._bit_timing_constructor( + timing, + bitrate, + tseg1_abr, # deprecated + tseg2_abr, # deprecated + sjw_abr, # deprecated + data_bitrate, + tseg1_dbr, # deprecated + tseg2_dbr, # deprecated + sjw_dbr, # deprecated + ssp_dbr, # deprecated ) - pBtpSDR, pBtpFDR = self._bit_timing_constructor( - timing, - bitrate, - tseg1_abr, # deprecated - tseg2_abr, # deprecated - sjw_abr, # deprecated - data_bitrate, - tseg1_dbr, # deprecated - tseg2_dbr, # deprecated - sjw_dbr, # deprecated - ssp_dbr, # deprecated - ) + log.info( + "Initialising Channel %d with the following parameters:\n" + "bOpMode=%d, bExMode=%d\n" + "pBtpSDR=%s\n" + "pBtpFDR=%s", + channel, + bOpMode, + bExMode, + pBtpSDR, + pBtpFDR, + ) - log.info( - "Initialising Channel %d with the following parameters:\n" - "bOpMode=%d, bExMode=%d\n" - "pBtpSDR=%s\n" - "pBtpFDR=%s", - channel, - bOpMode, - bExMode, - pBtpSDR, - pBtpFDR, - ) + _canlib.canControlInitialize( + self._control_handle, + bOpMode, + bExMode, + constants.CAN_FILTER_PASS, + constants.CAN_FILTER_PASS, + 0, + 0, + # ctypes.byref(pBtpSDR), + # ctypes.byref(pBtpFDR), + pBtpSDR, + pBtpFDR, + ) - _canlib.canControlInitialize( - self._control_handle, - bOpMode, - bExMode, - constants.CAN_FILTER_PASS, - constants.CAN_FILTER_PASS, - 0, - 0, - ctypes.byref(pBtpSDR), - ctypes.byref(pBtpFDR), - ) + # Setup filters before starting the channel + if can_filters: + log.info("The IXXAT VCI backend is filtering messages") + # Disable every message coming in + for extended_filter in (False, True): + _canlib.canControlSetAccFilter( + self._control_handle, + extended_filter, + constants.CAN_ACC_CODE_NONE, + constants.CAN_ACC_MASK_NONE, + ) + for can_filter in can_filters: + # Filters define what messages are accepted + code = int(can_filter["can_id"]) + mask = int(can_filter["can_mask"]) + extended = can_filter.get("extended", False) + _canlib.canControlAddFilterIds( + self._control_handle, 1 if extended else 0, code << 1, mask << 1 + ) + log.info("Accepting ID: 0x%X MASK: 0x%X", code, mask) + + # Start the CAN controller. Messages will be forwarded to the channel + _canlib.canControlStart(self._control_handle, constants.TRUE) + else: + _canlib.canChannelGetControl(self._channel_handle, ctypes.byref(self._control_handle)) + warnings.warn("The BUS is already active from another thread. Attepting to access channel from already active BUS.") # With receive messages, this field contains the relative reception time of # the message in ticks. The resolution of a tick can be calculated from the fields @@ -737,30 +778,6 @@ def __init__( / self._channel_capabilities.dwTscDivisor ) - # Setup filters before starting the channel - if can_filters: - log.info("The IXXAT VCI backend is filtering messages") - # Disable every message coming in - for extended_filter in (False, True): - _canlib.canControlSetAccFilter( - self._control_handle, - extended_filter, - constants.CAN_ACC_CODE_NONE, - constants.CAN_ACC_MASK_NONE, - ) - for can_filter in can_filters: - # Filters define what messages are accepted - code = int(can_filter["can_id"]) - mask = int(can_filter["can_mask"]) - extended = can_filter.get("extended", False) - _canlib.canControlAddFilterIds( - self._control_handle, 1 if extended else 0, code << 1, mask << 1 - ) - log.info("Accepting ID: 0x%X MASK: 0x%X", code, mask) - - # Start the CAN controller. Messages will be forwarded to the channel - _canlib.canControlStart(self._control_handle, constants.TRUE) - # For cyclic transmit list. Set when .send_periodic() is first called self._scheduler = None self._scheduler_resolution = None @@ -1026,6 +1043,7 @@ def bus_load(self) -> int: warnings.warn("The current adapter does not support bus load measurement") return 0 + @property def _status(self) -> structures.CANLINESTATUS2: status = structures.CANLINESTATUS2() _canlib.canControlGetStatus(self._control_handle, ctypes.byref(status)) diff --git a/can/interfaces/ixxat/constants.py b/can/interfaces/ixxat/constants.py index 1249dfd53..84402205d 100644 --- a/can/interfaces/ixxat/constants.py +++ b/can/interfaces/ixxat/constants.py @@ -121,6 +121,7 @@ CAN_OPMODE_LISTONLY = 0x08 # listen only mode (TX passive) CAN_OPMODE_LOWSPEED = 0x10 # use low speed bus interface CAN_OPMODE_AUTOBAUD = 0x20 # automatic bit rate detection +CAN_OPMODE_TXSELFACK = 0x40 # enable TX self acknowledge # Extended operating modes CAN_EXMODE_DISABLED = 0x00 # no extended operation @@ -145,12 +146,15 @@ # Information supplied in the abData[0] field of info frames # (CANMSGINFO.Bytes.bType = CAN_MSGTYPE_ERROR). +CAN_ERROR_NONE = 0 # no additional error information CAN_ERROR_STUFF = 1 # stuff error CAN_ERROR_FORM = 2 # form error CAN_ERROR_ACK = 3 # acknowledgment error CAN_ERROR_BIT = 4 # bit error +CAN_ERROR_FDB = 5 # fast data bit error CAN_ERROR_CRC = 6 # CRC error -CAN_ERROR_OTHER = 7 # other (unspecified) error +CAN_ERROR_DLC = 7 # data length error +CAN_ERROR_OTHER = 8 # other (unspecified) error # acceptance code and mask to reject all CAN IDs CAN_ACC_MASK_NONE = 0xFFFFFFFF @@ -187,7 +191,8 @@ CAN_MSGFLAGS2_EDL = 0x04 # [bit 2] extended data length CAN_MSGFLAGS2_FDR = 0x08 # [bit 3] fast data bit rate CAN_MSGFLAGS2_ESI = 0x10 # [bit 4] error state indicator -CAN_MSGFLAGS2_RES = 0xE0 # [bit 5..7] reserved bits +CAN_MSGFLAGS2_DTM = 0x20 # [bit 5] transmit delay mode (0=pre delay, 1=post delay) +CAN_MSGFLAGS2_RES = 0xC0 # [bit 6..7] reserved bits CAN_ACCEPT_REJECT = 0x00 # message not accepted @@ -289,11 +294,14 @@ } CAN_ERROR_MESSAGES = { + CAN_ERROR_NONE: "CAN error - no additional information", CAN_ERROR_STUFF: "CAN bit stuff error", CAN_ERROR_FORM: "CAN form error", CAN_ERROR_ACK: "CAN acknowledgment error", CAN_ERROR_BIT: "CAN bit error", + CAN_ERROR_FDB: "CAN fast data bit error", CAN_ERROR_CRC: "CAN CRC error", + CAN_ERROR_DLC: "CAN DLC error", CAN_ERROR_OTHER: "Other (unknown) CAN error", } diff --git a/report.html b/report.html new file mode 100644 index 000000000..62bceb7d9 --- /dev/null +++ b/report.html @@ -0,0 +1,6999 @@ + + + + + report.html + + + +

report.html

+

Report generated on 25-Jun-2023 at 23:17:10 by pytest-html v3.2.0

+

Summary

+

433 tests ran in 47.45 seconds.

+ 431 passed, 118 skipped, 2 failed, 0 errors, 0 expected failures, 0 unexpected passes +

Results

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ResultTestDurationLinks
Failedtest/test_interface_ixxat.py::TestHardwareCaseStd::test_bus_creation_arbitrary_bitrate0.18
+
self = <test.test_interface_ixxat.TestHardwareCaseStd testMethod=test_bus_creation_arbitrary_bitrate>

def test_bus_creation_arbitrary_bitrate(self):
target_bitrate = 444_444
with can.Bus(interface="ixxat", channel=0, bitrate=target_bitrate) as bus:
> timing = bus._status().sBtpSdr
E TypeError: 'CANLINESTATUS2' object is not callable

test\test_interface_ixxat.py:187: TypeError
-------------------------------Captured log call--------------------------------
INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=500000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600 +INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=444444, wTS1=13, wTS2=4, wSJW=4, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0
Failedtest/test_interface_ixxat.py::TestHardwareCaseStd::test_multiple_bus_instances1.52
+
self = <test.test_interface_ixxat.TestHardwareCaseStd testMethod=test_multiple_bus_instances>

def test_multiple_bus_instances(self):
"""This tests the access of multiple bus instances to the same adapter using the VCI 4 driver"""

with can.Bus(
interface="ixxat",
channel=0,
bitrate=default_test_bitrate,
receive_own_messages=True,
) as bus1:
with can.Bus(
interface="ixxat",
channel=0,
bitrate=default_test_bitrate,
receive_own_messages=True,
) as bus2:
with can.Bus(
interface="ixxat",
channel=0,
bitrate=default_test_bitrate,
receive_own_messages=True,
) as bus3:
bus1_msg = copy(default_test_msg)
bus1_msg.arbitration_id = bus1_msg.arbitration_id | 0x1000000
bus2_msg = copy(default_test_msg)
bus2_msg.arbitration_id = bus2_msg.arbitration_id | 0x2000000
bus3_msg = copy(default_test_msg)
bus3_msg.arbitration_id = bus3_msg.arbitration_id | 0x3000000
# send a message on bus 1, and try to receive it on bus 2 and bus 3
bus1.send(bus1_msg)
bus1.recv(0.25) # discard own message
response2from1 = bus2.recv(0.25)
response3from1 = bus3.recv(0.25)
# send the same message on bus 2, and try to receive it on bus 1 and bus 3
bus2.send(bus2_msg)
bus2.recv(0.25) # discard own message
response1from2 = bus1.recv(0.25)
response3from2 = bus3.recv(0.25)
# send the same message on bus 3, and try to receive it on bus 1 and bus 2
bus3.send(bus3_msg)
bus3.recv(0.25) # discard own message
response1from3 = bus1.recv(0.25)
response2from3 = bus2.recv(0.25)

if response2from1 and response3from1 and response1from2 and response3from2 and response1from3 and response2from3:
bus_checks = {
"sent from bus instance 1, received on bus instance 2": (response2from1, bus1_msg),
"sent from bus instance 1, received on bus instance 3": (response3from1, bus1_msg),
"sent from bus instance 2, received on bus instance 1": (response1from2, bus2_msg),
"sent from bus instance 2, received on bus instance 3": (response3from2, bus2_msg),
"sent from bus instance 3, received on bus instance 1": (response1from3, bus3_msg),
"sent from bus instance 3, received on bus instance 3": (response2from3, bus3_msg),
}
for case, msg_objects in bus_checks.items():
self.assertEqual(
msg_objects[0].arbitration_id,
msg_objects[1].arbitration_id,
f"The Arbitration ID of the messages {case} do not match",
)
self.assertEqual(
msg_objects[0].data,
msg_objects[1].data,
f"The Data fields of the messages {case} do not match.",
)
else:
captured_logs = self.log_capture.get_records()
if captured_logs[-1] == "CAN bit error":
raise can.exceptions.CanOperationError(
"CAN bit error - Ensure you are connected to a properly "
"terminated bus configured at {default_test_bitrate} bps"
)

elif captured_logs[-1] == "CAN ack error":
raise can.exceptions.CanOperationError(
"CAN ack error - Ensure there is at least one other (silent) node to provide ack signals",
)
else:
> raise ValueError(
"\n".join(
(
"At least one response does not match the sent message:",
f"Sent on bus instance 1: {bus1_msg}",
f" - Received on bus instance 2: {response2from1}",
f" - Received on bus instance 3: {response3from1}",
f"Sent on bus instance 2: {bus2_msg}",
f" - Received on bus instance 1: {response1from2}",
f" - Received on bus instance 3: {response3from2}",
f"Sent on interface 3: {bus3_msg}",
f" - Received on interface 1: {response1from3}",
f" - Received on interface 2: {response2from3}",
f"Last Caputred Log: {captured_logs[-1]}",
"Ensure hardware tests are run on a bus with no other traffic.",
)
)
)
E ValueError: At least one response does not match the sent message:
E Sent on bus instance 1: Timestamp: 0.000000 ID: 01c0ffee X Rx DL: 6 70 79 74 68 6f 6e 'python'
E - Received on bus instance 2: None
E - Received on bus instance 3: None
E Sent on bus instance 2: Timestamp: 0.000000 ID: 02c0ffee X Rx DL: 6 70 79 74 68 6f 6e 'python'
E - Received on bus instance 1: None
E - Received on bus instance 3: None
E Sent on interface 3: Timestamp: 0.000000 ID: 03c0ffee X Rx DL: 6 70 79 74 68 6f 6e 'python'
E - Received on interface 1: None
E - Received on interface 2: None
E Last Caputred Log: VCI_E_ACCESSDENIED error raised when calling VCI Function canControlReset
E Ensure hardware tests are run on a bus with no other traffic.

test\test_interface_ixxat.py:420: ValueError
-------------------------------Captured log call--------------------------------
INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=1, dwBPS=2, wTS1=13, wTS2=2, wSJW=1, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=500000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600 +INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=1, dwBPS=1, wTS1=12, wTS2=3, wSJW=3, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=250000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600 +INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=1, dwBPS=2, wTS1=12, wTS2=3, wSJW=3, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=0 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=1, dwBPS=2, wTS1=12, wTS2=3, wSJW=3, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=0 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +WARNING can.ixxat:canlib.py:129 VCI_E_ACCESSDENIED error raised when calling VCI Function canControlStart +WARNING can.ixxat:canlib.py:129 VCI_E_ACCESSDENIED error raised when calling VCI Function canControlReset +WARNING can.ixxat:canlib.py:129 VCI_E_ACCESSDENIED error raised when calling VCI Function canControlStart +WARNING can.ixxat:canlib.py:129 VCI_E_ACCESSDENIED error raised when calling VCI Function canControlReset
Skippedtest/back2back_test.py::Back2BackTestCase::test_message_is_rx0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 146, 'Skipped: TODO: how shall this be treated if sending messages locally? should be done uniformly')
Skippedtest/back2back_test.py::Back2BackTestCase::test_message_is_rx_receive_own_messages0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 163, 'Skipped: TODO: how shall this be treated if sending messages locally? should be done uniformly')
Skippedtest/back2back_test.py::BasicTestSocketCan::test_dlc_less_than_eight0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 142, 'Skipped: skip testing of socketcan')
Skippedtest/back2back_test.py::BasicTestSocketCan::test_extended_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 128, 'Skipped: skip testing of socketcan')
Skippedtest/back2back_test.py::BasicTestSocketCan::test_fd_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 216, 'Skipped: skip testing of socketcan')
Skippedtest/back2back_test.py::BasicTestSocketCan::test_fd_message_with_brs0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 222, 'Skipped: skip testing of socketcan')
Skippedtest/back2back_test.py::BasicTestSocketCan::test_fileno0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 232, 'Skipped: skip testing of socketcan')
Skippedtest/back2back_test.py::BasicTestSocketCan::test_message_is_rx0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 146, 'Skipped: skip testing of socketcan')
Skippedtest/back2back_test.py::BasicTestSocketCan::test_message_is_rx_receive_own_messages0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 163, 'Skipped: skip testing of socketcan')
Skippedtest/back2back_test.py::BasicTestSocketCan::test_multiple_shutdown0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 101, 'Skipped: skip testing of socketcan')
Skippedtest/back2back_test.py::BasicTestSocketCan::test_no_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 97, 'Skipped: skip testing of socketcan')
Skippedtest/back2back_test.py::BasicTestSocketCan::test_remote_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 136, 'Skipped: skip testing of socketcan')
Skippedtest/back2back_test.py::BasicTestSocketCan::test_standard_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 122, 'Skipped: skip testing of socketcan')
Skippedtest/back2back_test.py::BasicTestSocketCan::test_sub_second_timestamp_resolution0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 251, 'Skipped: skip testing of socketcan')
Skippedtest/back2back_test.py::BasicTestSocketCan::test_timestamp0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 105, 'Skipped: skip testing of socketcan')
Skippedtest/back2back_test.py::BasicTestSocketCan::test_timestamp_is_absolute0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 242, 'Skipped: skip testing of socketcan')
Skippedtest/back2back_test.py::BasicTestSocketCan::test_unique_message_instances0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 186, 'Skipped: skip testing of socketcan')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv4::test_dlc_less_than_eight0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 142, 'Skipped: only supported on Unix systems (but not on macOS at Travis CI and GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv4::test_extended_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 128, 'Skipped: only supported on Unix systems (but not on macOS at Travis CI and GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv4::test_fd_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 216, 'Skipped: only supported on Unix systems (but not on macOS at Travis CI and GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv4::test_fd_message_with_brs0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 222, 'Skipped: only supported on Unix systems (but not on macOS at Travis CI and GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv4::test_fileno0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 232, 'Skipped: only supported on Unix systems (but not on macOS at Travis CI and GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv4::test_message_is_rx0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 146, 'Skipped: only supported on Unix systems (but not on macOS at Travis CI and GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv4::test_message_is_rx_receive_own_messages0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 163, 'Skipped: only supported on Unix systems (but not on macOS at Travis CI and GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv4::test_multiple_shutdown0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 101, 'Skipped: only supported on Unix systems (but not on macOS at Travis CI and GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv4::test_no_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 97, 'Skipped: only supported on Unix systems (but not on macOS at Travis CI and GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv4::test_remote_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 136, 'Skipped: only supported on Unix systems (but not on macOS at Travis CI and GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv4::test_standard_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 122, 'Skipped: only supported on Unix systems (but not on macOS at Travis CI and GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv4::test_sub_second_timestamp_resolution0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 251, 'Skipped: only supported on Unix systems (but not on macOS at Travis CI and GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv4::test_timestamp0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 105, 'Skipped: only supported on Unix systems (but not on macOS at Travis CI and GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv4::test_timestamp_is_absolute0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 242, 'Skipped: only supported on Unix systems (but not on macOS at Travis CI and GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv4::test_unique_message_instances0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 297, 'Skipped: only supported on Unix systems (but not on macOS at Travis CI and GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv6::test_dlc_less_than_eight0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 142, 'Skipped: only supported on Unix systems (but not on Travis CI; and not on macOS at GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv6::test_extended_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 128, 'Skipped: only supported on Unix systems (but not on Travis CI; and not on macOS at GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv6::test_fd_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 216, 'Skipped: only supported on Unix systems (but not on Travis CI; and not on macOS at GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv6::test_fd_message_with_brs0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 222, 'Skipped: only supported on Unix systems (but not on Travis CI; and not on macOS at GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv6::test_fileno0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 232, 'Skipped: only supported on Unix systems (but not on Travis CI; and not on macOS at GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv6::test_message_is_rx0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 146, 'Skipped: only supported on Unix systems (but not on Travis CI; and not on macOS at GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv6::test_message_is_rx_receive_own_messages0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 163, 'Skipped: only supported on Unix systems (but not on Travis CI; and not on macOS at GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv6::test_multiple_shutdown0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 101, 'Skipped: only supported on Unix systems (but not on Travis CI; and not on macOS at GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv6::test_no_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 97, 'Skipped: only supported on Unix systems (but not on Travis CI; and not on macOS at GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv6::test_remote_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 136, 'Skipped: only supported on Unix systems (but not on Travis CI; and not on macOS at GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv6::test_standard_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 122, 'Skipped: only supported on Unix systems (but not on Travis CI; and not on macOS at GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv6::test_sub_second_timestamp_resolution0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 251, 'Skipped: only supported on Unix systems (but not on Travis CI; and not on macOS at GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv6::test_timestamp0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 105, 'Skipped: only supported on Unix systems (but not on Travis CI; and not on macOS at GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv6::test_timestamp_is_absolute0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 242, 'Skipped: only supported on Unix systems (but not on Travis CI; and not on macOS at GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestUdpMulticastBusIPv6::test_unique_message_instances0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 316, 'Skipped: only supported on Unix systems (but not on Travis CI; and not on macOS at GitHub Actions)')
Skippedtest/back2back_test.py::BasicTestEtas::test_dlc_less_than_eight0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 142, 'Skipped: skip testing of etas interface')
Skippedtest/back2back_test.py::BasicTestEtas::test_extended_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 128, 'Skipped: skip testing of etas interface')
Skippedtest/back2back_test.py::BasicTestEtas::test_fd_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 216, 'Skipped: skip testing of etas interface')
Skippedtest/back2back_test.py::BasicTestEtas::test_fd_message_with_brs0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 222, 'Skipped: skip testing of etas interface')
Skippedtest/back2back_test.py::BasicTestEtas::test_fileno0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 232, 'Skipped: skip testing of etas interface')
Skippedtest/back2back_test.py::BasicTestEtas::test_message_is_rx0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 146, 'Skipped: skip testing of etas interface')
Skippedtest/back2back_test.py::BasicTestEtas::test_message_is_rx_receive_own_messages0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 163, 'Skipped: skip testing of etas interface')
Skippedtest/back2back_test.py::BasicTestEtas::test_multiple_shutdown0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 101, 'Skipped: skip testing of etas interface')
Skippedtest/back2back_test.py::BasicTestEtas::test_no_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 97, 'Skipped: skip testing of etas interface')
Skippedtest/back2back_test.py::BasicTestEtas::test_remote_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 136, 'Skipped: skip testing of etas interface')
Skippedtest/back2back_test.py::BasicTestEtas::test_standard_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 122, 'Skipped: skip testing of etas interface')
Skippedtest/back2back_test.py::BasicTestEtas::test_sub_second_timestamp_resolution0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 251, 'Skipped: skip testing of etas interface')
Skippedtest/back2back_test.py::BasicTestEtas::test_timestamp0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 105, 'Skipped: skip testing of etas interface')
Skippedtest/back2back_test.py::BasicTestEtas::test_timestamp_is_absolute0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 242, 'Skipped: skip testing of etas interface')
Skippedtest/back2back_test.py::BasicTestEtas::test_unique_message_instances0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 339, 'Skipped: skip testing of etas interface')
Skippedtest/back2back_test.py::SocketCanBroadcastChannel::test_broadcast_channel0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 355, 'Skipped: skip testing of socketcan')
Skippedtest/back2back_test.py::TestThreadSafeBus::test_message_is_rx0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 146, 'Skipped: TODO: how shall this be treated if sending messages locally? should be done uniformly')
Skippedtest/back2back_test.py::TestThreadSafeBus::test_message_is_rx_receive_own_messages0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\back2back_test.py', 163, 'Skipped: TODO: how shall this be treated if sending messages locally? should be done uniformly')
Skippedtest/logformats_test.py::TestAscFileFormat::test_append_mode0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\logformats_test.py', 321, 'Skipped: do not test append mode')
Skippedtest/logformats_test.py::TestMF4FileFormat::test_append_mode0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\logformats_test.py', 321, 'Skipped: do not test append mode')
Skippedtest/logformats_test.py::TestSqliteDatabaseFormat::test_file_like_context_manager0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\logformats_test.py', 790, 'Skipped: not implemented')
Skippedtest/logformats_test.py::TestSqliteDatabaseFormat::test_file_like_explicit_stop0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\logformats_test.py', 786, 'Skipped: not implemented')
Skippedtest/logformats_test.py::TestTrcFileFormatGen::test_append_mode0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\logformats_test.py', 321, 'Skipped: do not test append mode')
Skippedtest/logformats_test.py::TestTrcFileFormatV1_0::test_append_mode0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\logformats_test.py', 321, 'Skipped: do not test append mode')
Skippedtest/test_cyclic_socketcan.py::CyclicSocketCan::test_create_same_id0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_cyclic_socketcan.py', 263, 'Skipped: skip testing of socketcan')
Skippedtest/test_cyclic_socketcan.py::CyclicSocketCan::test_cyclic_initializer_different_arbitration_ids0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_cyclic_socketcan.py', 230, 'Skipped: skip testing of socketcan')
Skippedtest/test_cyclic_socketcan.py::CyclicSocketCan::test_cyclic_initializer_invalid_empty_list0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_cyclic_socketcan.py', 226, 'Skipped: skip testing of socketcan')
Skippedtest/test_cyclic_socketcan.py::CyclicSocketCan::test_cyclic_initializer_invalid_none0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_cyclic_socketcan.py', 222, 'Skipped: skip testing of socketcan')
Skippedtest/test_cyclic_socketcan.py::CyclicSocketCan::test_cyclic_initializer_list0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_cyclic_socketcan.py', 56, 'Skipped: skip testing of socketcan')
Skippedtest/test_cyclic_socketcan.py::CyclicSocketCan::test_cyclic_initializer_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_cyclic_socketcan.py', 195, 'Skipped: skip testing of socketcan')
Skippedtest/test_cyclic_socketcan.py::CyclicSocketCan::test_cyclic_initializer_tuple0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_cyclic_socketcan.py', 124, 'Skipped: skip testing of socketcan')
Skippedtest/test_cyclic_socketcan.py::CyclicSocketCan::test_modify_data_different_arbitration_id_than_original0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_cyclic_socketcan.py', 550, 'Skipped: skip testing of socketcan')
Skippedtest/test_cyclic_socketcan.py::CyclicSocketCan::test_modify_data_invalid0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_cyclic_socketcan.py', 506, 'Skipped: skip testing of socketcan')
Skippedtest/test_cyclic_socketcan.py::CyclicSocketCan::test_modify_data_list0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_cyclic_socketcan.py', 312, 'Skipped: skip testing of socketcan')
Skippedtest/test_cyclic_socketcan.py::CyclicSocketCan::test_modify_data_message0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_cyclic_socketcan.py', 434, 'Skipped: skip testing of socketcan')
Skippedtest/test_cyclic_socketcan.py::CyclicSocketCan::test_modify_data_unequal_lengths0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_cyclic_socketcan.py', 520, 'Skipped: skip testing of socketcan')
Skippedtest/test_cyclic_socketcan.py::CyclicSocketCan::test_start_already_started_task0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_cyclic_socketcan.py', 249, 'Skipped: skip testing of socketcan')
Skippedtest/test_cyclic_socketcan.py::CyclicSocketCan::test_stop_all_periodic_tasks_and_remove_task0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_cyclic_socketcan.py', 570, 'Skipped: skip testing of socketcan')
Skippedtest/test_detect_available_configs.py::TestDetectAvailableConfigs::test_socketcan_on_ci_server0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_detect_available_configs.py', 55, 'Skipped: this setup is very specific')
Skippedtest/test_interface.py::test_interface_calls_parent_shutdown[gs_usb]0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_interface.py', 35, 'Skipped: Unable to load interface')
Skippedtest/test_interface.py::test_interface_calls_parent_shutdown[etas]0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_interface.py', 35, 'Skipped: Unable to load interface')
Skippedtest/test_interface_ixxat.py::HardwareTestCaseFd::test_bus_creation0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_interface_ixxat.py', 465, 'Skipped: connected hardware is not FD capable')
-------------------------------Captured log call--------------------------------
INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 1024 rx buffers, 128 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=1, dwBPS=2, wTS1=12, wTS2=3, wSJW=3, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535
Skippedtest/test_interface_ixxat.py::HardwareTestCaseFd::test_send_after_shutdown0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_interface_ixxat.py', 472, 'Skipped: connected hardware is not FD capable')
-------------------------------Captured log call--------------------------------
INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 1024 rx buffers, 128 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=1, dwBPS=2, wTS1=12, wTS2=3, wSJW=3, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535
Skippedtest/test_socketcan.py::SocketCANTest::test_bus_creation_can0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_socketcan.py', 362, 'Skipped: Only run when vcan0 is available')
Skippedtest/test_socketcan.py::SocketCANTest::test_bus_creation_can_fd0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_socketcan.py', 367, 'Skipped: Only run when vcan0 is available')
Skippedtest/test_socketcan.py::SocketCANTest::test_pypy_socketcan_support0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_socketcan.py', 372, 'Skipped: Only test when run on Linux with PyPy')
Skippedtest/test_socketcan_helpers.py::TestSocketCanHelpers::test_error_code_to_str0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_socketcan_helpers.py', 17, 'Skipped: socketcan is only available on Linux')
Skippedtest/test_socketcan_helpers.py::TestSocketCanHelpers::test_find_available_interfaces0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_socketcan_helpers.py', 31, 'Skipped: socketcan is only available on Linux')
Skippedtest/test_socketcan_loopback.py::LocalLoopbackSocketCan::test_sending_message_with_loopback_enabled0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_socketcan_loopback.py', 36, 'Skipped: skip testing of socketcan')
Skippedtest/test_socketcan_loopback.py::LocalLoopbackSocketCan::test_sending_message_without_loopback_enabled0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_socketcan_loopback.py', 55, 'Skipped: skip testing of socketcan')
Skippedtest/test_vector.py::test_bus_creation0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_vector.py', 98, 'Skipped: Vector XL API is unavailable')
Skippedtest/test_vector.py::test_bus_creation_bitrate0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_vector.py', 142, 'Skipped: Vector XL API is unavailable')
Skippedtest/test_vector.py::test_bus_creation_fd0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_vector.py', 180, 'Skipped: Vector XL API is unavailable')
Skippedtest/test_vector.py::test_bus_creation_fd_bitrate_timings0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_vector.py', 248, 'Skipped: Vector XL API is unavailable')
Skippedtest/test_vector.py::test_bus_creation_timing0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_vector.py', 345, 'Skipped: Vector XL API is unavailable')
Skippedtest/test_vector.py::test_bus_creation_timingfd0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_vector.py', 424, 'Skipped: Vector XL API is unavailable')
Skippedtest/test_vector.py::test_send_and_receive0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_vector.py', 505, 'Skipped: Vector XL API is unavailable')
Skippedtest/test_vector.py::test_send_and_receive_fd0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_vector.py', 529, 'Skipped: Vector XL API is unavailable')
Skippedtest/test_vector.py::test_receive_non_msg_event0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_vector.py', 577, 'Skipped: Vector XL API is unavailable')
Skippedtest/test_vector.py::test_receive_fd_non_msg_event0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_vector.py', 601, 'Skipped: Vector XL API is unavailable')
Skippedtest/test_vector.py::test_flush_tx_buffer0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_vector.py', 619, 'Skipped: Vector XL API is unavailable')
Skippedtest/test_vector.py::test_shutdown0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_vector.py', 634, 'Skipped: Vector XL API is unavailable')
Skippedtest/test_vector.py::test_reset0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_vector.py', 657, 'Skipped: Vector XL API is unavailable')
Skippedtest/test_vector.py::test_popup_hw_cfg0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_vector.py', 675, 'Skipped: Vector XL API is unavailable')
Skippedtest/test_vector.py::test_set_and_get_application_config0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_vector.py', 699, 'Skipped: Vector XL API is unavailable')
Skippedtest/test_vector.py::test_set_timer0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_vector.py', 727, 'Skipped: Vector XL API is unavailable')
Skippedtest/test_vector.py::test_called_without_testing_argument0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_vector.py', 743, 'Skipped: Not relevant for Windows.')
Skippedtest/test_viewer.py::CanViewerTest::test_pack_unpack0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_viewer.py', 306, 'Skipped: curses might be missing on some platforms')
Skippedtest/test_viewer.py::CanViewerTest::test_parse_args0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_viewer.py', 399, 'Skipped: curses might be missing on some platforms')
Skippedtest/test_viewer.py::CanViewerTest::test_receive0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_viewer.py', 214, 'Skipped: curses might be missing on some platforms')
Skippedtest/test_viewer.py::CanViewerTest::test_send0.00
+
('C:\\Users\\matth\\Documents\\GitHub\\python-can\\test\\test_viewer.py', 165, 'Skipped: curses might be missing on some platforms')
Passedtest/back2back_test.py::Back2BackTestCase::test_dlc_less_than_eight0.00
+
No log output captured.
Passedtest/back2back_test.py::Back2BackTestCase::test_extended_message0.00
+
No log output captured.
Passedtest/back2back_test.py::Back2BackTestCase::test_fd_message0.00
+
No log output captured.
Passedtest/back2back_test.py::Back2BackTestCase::test_fd_message_with_brs0.00
+
No log output captured.
Passedtest/back2back_test.py::Back2BackTestCase::test_fileno0.00
+
No log output captured.
Passedtest/back2back_test.py::Back2BackTestCase::test_multiple_shutdown0.00
+
No log output captured.
Passedtest/back2back_test.py::Back2BackTestCase::test_no_message0.10
+
No log output captured.
Passedtest/back2back_test.py::Back2BackTestCase::test_remote_message0.00
+
No log output captured.
Passedtest/back2back_test.py::Back2BackTestCase::test_standard_message0.00
+
No log output captured.
Passedtest/back2back_test.py::Back2BackTestCase::test_sub_second_timestamp_resolution0.01
+
No log output captured.
Passedtest/back2back_test.py::Back2BackTestCase::test_timestamp2.00
+
No log output captured.
Passedtest/back2back_test.py::Back2BackTestCase::test_timestamp_is_absolute0.00
+
No log output captured.
Passedtest/back2back_test.py::Back2BackTestCase::test_unique_message_instances0.00
+
No log output captured.
Passedtest/back2back_test.py::TestThreadSafeBus::test_concurrent_writes0.10
+
No log output captured.
Passedtest/back2back_test.py::TestThreadSafeBus::test_dlc_less_than_eight0.00
+
No log output captured.
Passedtest/back2back_test.py::TestThreadSafeBus::test_extended_message0.00
+
No log output captured.
Passedtest/back2back_test.py::TestThreadSafeBus::test_fd_message0.00
+
No log output captured.
Passedtest/back2back_test.py::TestThreadSafeBus::test_fd_message_with_brs0.00
+
No log output captured.
Passedtest/back2back_test.py::TestThreadSafeBus::test_fileno0.00
+
No log output captured.
Passedtest/back2back_test.py::TestThreadSafeBus::test_filtered_bus0.09
+
No log output captured.
Passedtest/back2back_test.py::TestThreadSafeBus::test_multiple_shutdown0.00
+
No log output captured.
Passedtest/back2back_test.py::TestThreadSafeBus::test_no_message0.10
+
No log output captured.
Passedtest/back2back_test.py::TestThreadSafeBus::test_remote_message0.00
+
No log output captured.
Passedtest/back2back_test.py::TestThreadSafeBus::test_standard_message0.00
+
No log output captured.
Passedtest/back2back_test.py::TestThreadSafeBus::test_sub_second_timestamp_resolution0.01
+
No log output captured.
Passedtest/back2back_test.py::TestThreadSafeBus::test_timestamp2.00
+
No log output captured.
Passedtest/back2back_test.py::TestThreadSafeBus::test_timestamp_is_absolute0.00
+
No log output captured.
Passedtest/back2back_test.py::TestThreadSafeBus::test_unique_message_instances0.00
+
No log output captured.
Passedtest/contextmanager_test.py::ContextManagerTest::test_open_buses0.00
+
No log output captured.
Passedtest/contextmanager_test.py::ContextManagerTest::test_use_closed_bus0.00
+
No log output captured.
Passedtest/listener_test.py::ListenerImportTest::testClassesImportable0.00
+
No log output captured.
Passedtest/listener_test.py::ListenerTest::testAddListenerToNotifier0.10
+
No log output captured.
Passedtest/listener_test.py::ListenerTest::testBasicListenerCanBeAddedToNotifier0.10
+
No log output captured.
Passedtest/listener_test.py::ListenerTest::testBufferedListenerReceives0.00
+
No log output captured.
Passedtest/listener_test.py::ListenerTest::testLoggerTypeResolution0.01
+
------------------------------Captured stdout call------------------------------
testing: .asc +testing: .blf +testing: .csv +testing: .db +testing: .log +testing: .txt +
Passedtest/listener_test.py::ListenerTest::testLoggerTypeResolutionUnsupportedFileTypes0.00
+
No log output captured.
Passedtest/listener_test.py::ListenerTest::testPlayerTypeResolution0.00
+
------------------------------Captured stdout call------------------------------
testing: .asc +testing: .blf +testing: .csv +testing: .db +testing: .log +
Passedtest/listener_test.py::ListenerTest::testPlayerTypeResolutionUnsupportedFileTypes0.00
+
No log output captured.
Passedtest/listener_test.py::ListenerTest::testRemoveListenerFromNotifier0.10
+
No log output captured.
Passedtest/listener_test.py::test_deprecated_loop_arg0.00
+
No log output captured.
Passedtest/logformats_test.py::ReaderWriterExtensionTest::test_extension_matching_asc0.01
+
No log output captured.
Passedtest/logformats_test.py::ReaderWriterExtensionTest::test_extension_matching_blf0.00
+
No log output captured.
Passedtest/logformats_test.py::ReaderWriterExtensionTest::test_extension_matching_csv0.00
+
No log output captured.
Passedtest/logformats_test.py::ReaderWriterExtensionTest::test_extension_matching_db0.02
+
No log output captured.
Passedtest/logformats_test.py::ReaderWriterExtensionTest::test_extension_matching_log0.00
+
No log output captured.
Passedtest/logformats_test.py::ReaderWriterExtensionTest::test_extension_matching_mf40.03
+
No log output captured.
Passedtest/logformats_test.py::ReaderWriterExtensionTest::test_extension_matching_txt0.00
+
No log output captured.
Passedtest/logformats_test.py::TestAscFileFormat::test_absolute_time0.00
+
No log output captured.
Passedtest/logformats_test.py::TestAscFileFormat::test_can_and_canfd_error_frames0.00
+
No log output captured.
Passedtest/logformats_test.py::TestAscFileFormat::test_can_dlc_greater_than_80.00
+
No log output captured.
Passedtest/logformats_test.py::TestAscFileFormat::test_can_fd_message0.00
+
No log output captured.
Passedtest/logformats_test.py::TestAscFileFormat::test_can_fd_message_640.00
+
No log output captured.
Passedtest/logformats_test.py::TestAscFileFormat::test_can_fd_remote_message0.00
+
No log output captured.
Passedtest/logformats_test.py::TestAscFileFormat::test_can_message0.00
+
No log output captured.
Passedtest/logformats_test.py::TestAscFileFormat::test_can_remote_message0.00
+
No log output captured.
Passedtest/logformats_test.py::TestAscFileFormat::test_error_frame_channel0.00
+
No log output captured.
Passedtest/logformats_test.py::TestAscFileFormat::test_file_like_context_manager0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing comment: This is the first comment +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing comment: +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing comment: This third comment contains some strange characters: '�"�$%&/()=?__::_����� and ends here. +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing comment: This fourth comment is quite long! Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 0.001200 ID: 00000000 X Rx F DL: 64 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +writing message: Timestamp: 0.001300 ID: 00000000 X Rx F DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001400 ID: 00000000 X Rx F BS DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001500 ID: 00000000 X Rx F EI DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestAscFileFormat::test_file_like_explicit_stop0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing comment: This is the first comment +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing comment: +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing comment: This third comment contains some strange characters: '�"�$%&/()=?__::_����� and ends here. +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing comment: This fourth comment is quite long! Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 0.001200 ID: 00000000 X Rx F DL: 64 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +writing message: Timestamp: 0.001300 ID: 00000000 X Rx F DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001400 ID: 00000000 X Rx F BS DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001500 ID: 00000000 X Rx F EI DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestAscFileFormat::test_ignore_comments0.00
+
No log output captured.
Passedtest/logformats_test.py::TestAscFileFormat::test_no_triggerblock0.02
+
No log output captured.
Passedtest/logformats_test.py::TestAscFileFormat::test_path_like_context_manager0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing comment: This is the first comment +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing comment: +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing comment: This third comment contains some strange characters: '�"�$%&/()=?__::_����� and ends here. +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing comment: This fourth comment is quite long! Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 0.001200 ID: 00000000 X Rx F DL: 64 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +writing message: Timestamp: 0.001300 ID: 00000000 X Rx F DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001400 ID: 00000000 X Rx F BS DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001500 ID: 00000000 X Rx F EI DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestAscFileFormat::test_path_like_explicit_stop0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing comment: This is the first comment +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing comment: +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing comment: This third comment contains some strange characters: '�"�$%&/()=?__::_����� and ends here. +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing comment: This fourth comment is quite long! Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 0.001200 ID: 00000000 X Rx F DL: 64 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +writing message: Timestamp: 0.001300 ID: 00000000 X Rx F DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001400 ID: 00000000 X Rx F BS DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001500 ID: 00000000 X Rx F EI DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestBlfFileFormat::test_append_mode0.01
+
No log output captured.
Passedtest/logformats_test.py::TestBlfFileFormat::test_can_error_frame_ext0.00
+
No log output captured.
Passedtest/logformats_test.py::TestBlfFileFormat::test_can_fd_message0.00
+
No log output captured.
Passedtest/logformats_test.py::TestBlfFileFormat::test_can_fd_message_640.00
+
No log output captured.
Passedtest/logformats_test.py::TestBlfFileFormat::test_can_message0.00
+
No log output captured.
Passedtest/logformats_test.py::TestBlfFileFormat::test_can_message_20.00
+
No log output captured.
Passedtest/logformats_test.py::TestBlfFileFormat::test_file_like_context_manager0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 0.001200 ID: 00000000 X Rx F DL: 64 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +writing message: Timestamp: 0.001300 ID: 00000000 X Rx F DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001400 ID: 00000000 X Rx F BS DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001500 ID: 00000000 X Rx F EI DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestBlfFileFormat::test_file_like_explicit_stop0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 0.001200 ID: 00000000 X Rx F DL: 64 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +writing message: Timestamp: 0.001300 ID: 00000000 X Rx F DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001400 ID: 00000000 X Rx F BS DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001500 ID: 00000000 X Rx F EI DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestBlfFileFormat::test_path_like_context_manager0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 0.001200 ID: 00000000 X Rx F DL: 64 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +writing message: Timestamp: 0.001300 ID: 00000000 X Rx F DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001400 ID: 00000000 X Rx F BS DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001500 ID: 00000000 X Rx F EI DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestBlfFileFormat::test_path_like_explicit_stop0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 0.001200 ID: 00000000 X Rx F DL: 64 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +writing message: Timestamp: 0.001300 ID: 00000000 X Rx F DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001400 ID: 00000000 X Rx F BS DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001500 ID: 00000000 X Rx F EI DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestBlfFileFormat::test_timestamp_to_systemtime0.00
+
No log output captured.
Passedtest/logformats_test.py::TestCanutilsFileFormat::test_append_mode0.00
+
No log output captured.
Passedtest/logformats_test.py::TestCanutilsFileFormat::test_file_like_context_manager0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 0.001200 ID: 00000000 X Rx F DL: 64 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +writing message: Timestamp: 0.001300 ID: 00000000 X Rx F DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001400 ID: 00000000 X Rx F BS DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001500 ID: 00000000 X Rx F EI DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestCanutilsFileFormat::test_file_like_explicit_stop0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 0.001200 ID: 00000000 X Rx F DL: 64 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +writing message: Timestamp: 0.001300 ID: 00000000 X Rx F DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001400 ID: 00000000 X Rx F BS DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001500 ID: 00000000 X Rx F EI DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestCanutilsFileFormat::test_path_like_context_manager0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 0.001200 ID: 00000000 X Rx F DL: 64 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +writing message: Timestamp: 0.001300 ID: 00000000 X Rx F DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001400 ID: 00000000 X Rx F BS DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001500 ID: 00000000 X Rx F EI DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestCanutilsFileFormat::test_path_like_explicit_stop0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 0.001200 ID: 00000000 X Rx F DL: 64 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +writing message: Timestamp: 0.001300 ID: 00000000 X Rx F DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001400 ID: 00000000 X Rx F BS DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001500 ID: 00000000 X Rx F EI DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestCsvFileFormat::test_append_mode0.00
+
No log output captured.
Passedtest/logformats_test.py::TestCsvFileFormat::test_file_like_context_manager0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestCsvFileFormat::test_file_like_explicit_stop0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestCsvFileFormat::test_path_like_context_manager0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestCsvFileFormat::test_path_like_explicit_stop0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestMF4FileFormat::test_file_like_context_manager0.01
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 0.001200 ID: 00000000 X Rx F DL: 64 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +writing message: Timestamp: 0.001300 ID: 00000000 X Rx F DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001400 ID: 00000000 X Rx F BS DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001500 ID: 00000000 X Rx F EI DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestMF4FileFormat::test_file_like_explicit_stop0.01
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 0.001200 ID: 00000000 X Rx F DL: 64 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +writing message: Timestamp: 0.001300 ID: 00000000 X Rx F DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001400 ID: 00000000 X Rx F BS DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001500 ID: 00000000 X Rx F EI DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestMF4FileFormat::test_path_like_context_manager0.01
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 0.001200 ID: 00000000 X Rx F DL: 64 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +writing message: Timestamp: 0.001300 ID: 00000000 X Rx F DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001400 ID: 00000000 X Rx F BS DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001500 ID: 00000000 X Rx F EI DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestMF4FileFormat::test_path_like_explicit_stop0.01
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 0.001200 ID: 00000000 X Rx F DL: 64 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +writing message: Timestamp: 0.001300 ID: 00000000 X Rx F DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001400 ID: 00000000 X Rx F BS DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 0.001500 ID: 00000000 X Rx F EI DL: 8 00 01 02 03 04 05 06 07 +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestSqliteDatabaseFormat::test_append_mode0.01
+
No log output captured.
Passedtest/logformats_test.py::TestSqliteDatabaseFormat::test_path_like_context_manager0.01
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestSqliteDatabaseFormat::test_path_like_explicit_stop0.01
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestSqliteDatabaseFormat::test_read_all0.01
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +writing message: Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +writing message: Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +writing message: Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +reading all messages +
Passedtest/logformats_test.py::TestPrinter::test_not_crashes_with_file0.00
+
No log output captured.
Passedtest/logformats_test.py::TestPrinter::test_not_crashes_with_stdout0.00
+
------------------------------Captured stdout call------------------------------
Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +Timestamp: 1483389946.362000 ID: 00dadada X Rx R DL: 0 +Timestamp: 1483389946.562000 ID: 0123 S Rx R DL: 0 +Timestamp: 1483389949.362000 ID: 0768 S Rx R DL: 0 +Timestamp: 1483397804.867000 ID: 00abcdef X Rx R DL: 0 +Timestamp: 0.000000 ID: 00000000 X Rx E DL: 0 +Timestamp: 1483389946.367000 ID: 00000000 X Rx E DL: 0 +Timestamp: 1483389963.354000 ID: 00000000 X Rx E DL: 0 +Timestamp: 0.001200 ID: 00000000 X Rx F DL: 64 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +Timestamp: 0.001300 ID: 00000000 X Rx F DL: 8 00 01 02 03 04 05 06 07 +Timestamp: 0.001400 ID: 00000000 X Rx F BS DL: 8 00 01 02 03 04 05 06 07 +Timestamp: 0.001500 ID: 00000000 X Rx F EI DL: 8 00 01 02 03 04 05 06 07 +
Passedtest/logformats_test.py::TestTrcFileFormatGen::test_can_message0.00
+
No log output captured.
Passedtest/logformats_test.py::TestTrcFileFormatGen::test_can_message_versions_0_V1_00.00
+
No log output captured.
Passedtest/logformats_test.py::TestTrcFileFormatGen::test_can_message_versions_1_V1_10.00
+
No log output captured.
Passedtest/logformats_test.py::TestTrcFileFormatGen::test_can_message_versions_2_V2_10.00
+
No log output captured.
Passedtest/logformats_test.py::TestTrcFileFormatGen::test_file_like_context_manager0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +reading all messages +
Passedtest/logformats_test.py::TestTrcFileFormatGen::test_file_like_explicit_stop0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +reading all messages +
Passedtest/logformats_test.py::TestTrcFileFormatGen::test_not_supported_version0.00
+
No log output captured.
Passedtest/logformats_test.py::TestTrcFileFormatGen::test_path_like_context_manager0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +reading all messages +
Passedtest/logformats_test.py::TestTrcFileFormatGen::test_path_like_explicit_stop0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +reading all messages +
Passedtest/logformats_test.py::TestTrcFileFormatV1_0::test_file_like_context_manager0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +reading all messages +
Passedtest/logformats_test.py::TestTrcFileFormatV1_0::test_file_like_explicit_stop0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +reading all messages +
Passedtest/logformats_test.py::TestTrcFileFormatV1_0::test_path_like_context_manager0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +reading all messages +
Passedtest/logformats_test.py::TestTrcFileFormatV1_0::test_path_like_explicit_stop0.00
+
------------------------------Captured stdout call------------------------------
writing all messages/comments +writing message: Timestamp: 0.000100 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000200 ID: 00000000 X Rx DL: 2 00 42 +writing message: Timestamp: 0.000300 ID: 00ab S Rx DL: 0 +writing message: Timestamp: 0.000400 ID: 00000042 X Rx DL: 0 +writing message: Timestamp: 0.000500 ID: 00abcdef X Rx DL: 0 +writing message: Timestamp: 0.000600 ID: 00000000 X Rx DL: 0 +writing message: Timestamp: 0.000700 ID: 00000000 X Rx DL: 3 ff fe fd +writing message: Timestamp: 0.000800 ID: 00000000 X Rx DL: 0 Channel: 0 +writing message: Timestamp: 0.000900 ID: 00000000 X Rx DL: 0 Channel: 42 +writing message: Timestamp: 0.001000 ID: 00000000 X Rx DL: 0 Channel: vcan0 +writing message: Timestamp: 0.001100 ID: 00000000 X Rx DL: 0 Channel: awesome_channel +writing message: Timestamp: 1483389946.197000 ID: 00abcdef X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.362000 ID: 00dadada X Rx DL: 8 01 02 03 04 05 06 07 08 +writing message: Timestamp: 1483389946.562000 ID: 0123 S Rx DL: 2 fe ff +writing message: Timestamp: 1483389949.362000 ID: 0768 S Rx DL: 0 +writing message: Timestamp: 1483389988.617000 ID: 0123 S Rx DL: 2 ff ff +reading all messages +
Passedtest/network_test.py::ControllerAreaNetworkTestCase::testProducer0.00
+
No log output captured.
Passedtest/network_test.py::ControllerAreaNetworkTestCase::testProducerConsumer0.54
+
------------------------------Captured stdout call------------------------------
No messages... lets go +
-----------------------------Captured log teardown------------------------------
WARNING can.bus:bus.py:480 VirtualBus was not properly shut down +WARNING can.bus:bus.py:480 VirtualBus was not properly shut down
Passedtest/notifier_test.py::NotifierTest::test_multiple_bus0.20
+
No log output captured.
Passedtest/notifier_test.py::NotifierTest::test_single_bus0.10
+
No log output captured.
Passedtest/notifier_test.py::AsyncNotifierTest::test_asyncio_notifier0.10
+
No log output captured.
Passedtest/serial_test.py::SimpleSerialTest::test_can_protocol0.00
+
No log output captured.
Passedtest/serial_test.py::SimpleSerialTest::test_rx_tx_data_none0.00
+
-----------------------------Captured log teardown------------------------------
WARNING can.bus:bus.py:480 SerialBus was not properly shut down
Passedtest/serial_test.py::SimpleSerialTest::test_rx_tx_max_id0.00
+
-----------------------------Captured log teardown------------------------------
WARNING can.bus:bus.py:480 SerialBus was not properly shut down
Passedtest/serial_test.py::SimpleSerialTest::test_rx_tx_max_timestamp0.00
+
-----------------------------Captured log teardown------------------------------
WARNING can.bus:bus.py:480 SerialBus was not properly shut down
Passedtest/serial_test.py::SimpleSerialTest::test_rx_tx_max_timestamp_error0.00
+
-----------------------------Captured log teardown------------------------------
WARNING can.bus:bus.py:480 SerialBus was not properly shut down
Passedtest/serial_test.py::SimpleSerialTest::test_rx_tx_min_id0.00
+
-----------------------------Captured log teardown------------------------------
WARNING can.bus:bus.py:480 SerialBus was not properly shut down
Passedtest/serial_test.py::SimpleSerialTest::test_rx_tx_min_max_data0.00
+
-----------------------------Captured log teardown------------------------------
WARNING can.bus:bus.py:480 SerialBus was not properly shut down
Passedtest/serial_test.py::SimpleSerialTest::test_rx_tx_min_max_dlc0.00
+
-----------------------------Captured log teardown------------------------------
WARNING can.bus:bus.py:480 SerialBus was not properly shut down
Passedtest/serial_test.py::SimpleSerialTest::test_rx_tx_min_timestamp0.00
+
-----------------------------Captured log teardown------------------------------
WARNING can.bus:bus.py:480 SerialBus was not properly shut down
Passedtest/serial_test.py::SimpleSerialTest::test_rx_tx_min_timestamp_error0.00
+
-----------------------------Captured log teardown------------------------------
WARNING can.bus:bus.py:480 SerialBus was not properly shut down
Passedtest/serial_test.py::SimpleSerialTest::test_when_no_fileno0.00
+
-----------------------------Captured log teardown------------------------------
WARNING can.bus:bus.py:480 SerialBus was not properly shut down +WARNING can.bus:bus.py:480 SerialBus was not properly shut down
Passedtest/serial_test.py::SimpleSerialLoopTest::test_can_protocol0.00
+
No log output captured.
Passedtest/serial_test.py::SimpleSerialLoopTest::test_rx_tx_data_none0.00
+
No log output captured.
Passedtest/serial_test.py::SimpleSerialLoopTest::test_rx_tx_max_id0.00
+
No log output captured.
Passedtest/serial_test.py::SimpleSerialLoopTest::test_rx_tx_max_timestamp0.00
+
No log output captured.
Passedtest/serial_test.py::SimpleSerialLoopTest::test_rx_tx_max_timestamp_error0.00
+
No log output captured.
Passedtest/serial_test.py::SimpleSerialLoopTest::test_rx_tx_min_id0.00
+
No log output captured.
Passedtest/serial_test.py::SimpleSerialLoopTest::test_rx_tx_min_max_data0.02
+
No log output captured.
Passedtest/serial_test.py::SimpleSerialLoopTest::test_rx_tx_min_max_dlc0.00
+
No log output captured.
Passedtest/serial_test.py::SimpleSerialLoopTest::test_rx_tx_min_timestamp0.00
+
No log output captured.
Passedtest/serial_test.py::SimpleSerialLoopTest::test_rx_tx_min_timestamp_error0.00
+
No log output captured.
Passedtest/serial_test.py::SimpleSerialLoopTest::test_when_no_fileno0.00
+
No log output captured.
Passedtest/simplecyclic_test.py::SimpleCyclicSendTaskTest::test_cycle_time2.00
+
No log output captured.
Passedtest/simplecyclic_test.py::SimpleCyclicSendTaskTest::test_managed_tasks1.70
+
No log output captured.
Passedtest/simplecyclic_test.py::SimpleCyclicSendTaskTest::test_modifier_callback0.20
+
No log output captured.
Passedtest/simplecyclic_test.py::SimpleCyclicSendTaskTest::test_removing_bus_tasks0.00
+
No log output captured.
Passedtest/simplecyclic_test.py::SimpleCyclicSendTaskTest::test_stopping_perodic_tasks0.10
+
No log output captured.
Passedtest/simplecyclic_test.py::SimpleCyclicSendTaskTest::test_thread_based_cyclic_send_task3.00
+
-------------------------------Captured log call--------------------------------
ERROR can.bcm:broadcastmanager.py:306 Cannot operate on a closed bus +Traceback (most recent call last): + File "C:\Users\matth\Documents\GitHub\python-can\can\broadcastmanager.py", line 304, in _run + self.bus.send(self.messages[msg_index]) + File "C:\Users\matth\Documents\GitHub\python-can\can\thread_safe_bus.py", line 59, in send + return self.__wrapped__.send(msg, timeout=timeout, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 138, in send + self._check_if_open() + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 124, in _check_if_open + raise CanOperationError("Cannot operate on a closed bus") +can.exceptions.CanOperationError: Cannot operate on a closed bus +ERROR can.bcm:broadcastmanager.py:306 Cannot operate on a closed bus +Traceback (most recent call last): + File "C:\Users\matth\Documents\GitHub\python-can\can\broadcastmanager.py", line 304, in _run + self.bus.send(self.messages[msg_index]) + File "C:\Users\matth\Documents\GitHub\python-can\can\thread_safe_bus.py", line 59, in send + return self.__wrapped__.send(msg, timeout=timeout, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 138, in send + self._check_if_open() + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 124, in _check_if_open + raise CanOperationError("Cannot operate on a closed bus") +can.exceptions.CanOperationError: Cannot operate on a closed bus +ERROR can.bcm:broadcastmanager.py:306 Cannot operate on a closed bus +Traceback (most recent call last): + File "C:\Users\matth\Documents\GitHub\python-can\can\broadcastmanager.py", line 304, in _run + self.bus.send(self.messages[msg_index]) + File "C:\Users\matth\Documents\GitHub\python-can\can\thread_safe_bus.py", line 59, in send + return self.__wrapped__.send(msg, timeout=timeout, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 138, in send + self._check_if_open() + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 124, in _check_if_open + raise CanOperationError("Cannot operate on a closed bus") +can.exceptions.CanOperationError: Cannot operate on a closed bus +ERROR can.bcm:broadcastmanager.py:306 Cannot operate on a closed bus +Traceback (most recent call last): + File "C:\Users\matth\Documents\GitHub\python-can\can\broadcastmanager.py", line 304, in _run + self.bus.send(self.messages[msg_index]) + File "C:\Users\matth\Documents\GitHub\python-can\can\thread_safe_bus.py", line 59, in send + return self.__wrapped__.send(msg, timeout=timeout, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 138, in send + self._check_if_open() + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 124, in _check_if_open + raise CanOperationError("Cannot operate on a closed bus") +can.exceptions.CanOperationError: Cannot operate on a closed bus +ERROR can.bcm:broadcastmanager.py:306 Cannot operate on a closed bus +Traceback (most recent call last): + File "C:\Users\matth\Documents\GitHub\python-can\can\broadcastmanager.py", line 304, in _run + self.bus.send(self.messages[msg_index]) + File "C:\Users\matth\Documents\GitHub\python-can\can\thread_safe_bus.py", line 59, in send + return self.__wrapped__.send(msg, timeout=timeout, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 138, in send + self._check_if_open() + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 124, in _check_if_open + raise CanOperationError("Cannot operate on a closed bus") +can.exceptions.CanOperationError: Cannot operate on a closed bus +ERROR can.bcm:broadcastmanager.py:306 Cannot operate on a closed bus +Traceback (most recent call last): + File "C:\Users\matth\Documents\GitHub\python-can\can\broadcastmanager.py", line 304, in _run + self.bus.send(self.messages[msg_index]) + File "C:\Users\matth\Documents\GitHub\python-can\can\thread_safe_bus.py", line 59, in send + return self.__wrapped__.send(msg, timeout=timeout, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 138, in send + self._check_if_open() + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 124, in _check_if_open + raise CanOperationError("Cannot operate on a closed bus") +can.exceptions.CanOperationError: Cannot operate on a closed bus +ERROR can.bcm:broadcastmanager.py:306 Cannot operate on a closed bus +Traceback (most recent call last): + File "C:\Users\matth\Documents\GitHub\python-can\can\broadcastmanager.py", line 304, in _run + self.bus.send(self.messages[msg_index]) + File "C:\Users\matth\Documents\GitHub\python-can\can\thread_safe_bus.py", line 59, in send + return self.__wrapped__.send(msg, timeout=timeout, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 138, in send + self._check_if_open() + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 124, in _check_if_open + raise CanOperationError("Cannot operate on a closed bus") +can.exceptions.CanOperationError: Cannot operate on a closed bus +ERROR can.bcm:broadcastmanager.py:306 Cannot operate on a closed bus +Traceback (most recent call last): + File "C:\Users\matth\Documents\GitHub\python-can\can\broadcastmanager.py", line 304, in _run + self.bus.send(self.messages[msg_index]) + File "C:\Users\matth\Documents\GitHub\python-can\can\thread_safe_bus.py", line 59, in send + return self.__wrapped__.send(msg, timeout=timeout, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 138, in send + self._check_if_open() + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 124, in _check_if_open + raise CanOperationError("Cannot operate on a closed bus") +can.exceptions.CanOperationError: Cannot operate on a closed bus +ERROR can.bcm:broadcastmanager.py:306 Cannot operate on a closed bus +Traceback (most recent call last): + File "C:\Users\matth\Documents\GitHub\python-can\can\broadcastmanager.py", line 304, in _run + self.bus.send(self.messages[msg_index]) + File "C:\Users\matth\Documents\GitHub\python-can\can\thread_safe_bus.py", line 59, in send + return self.__wrapped__.send(msg, timeout=timeout, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 138, in send + self._check_if_open() + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 124, in _check_if_open + raise CanOperationError("Cannot operate on a closed bus") +can.exceptions.CanOperationError: Cannot operate on a closed bus +ERROR can.bcm:broadcastmanager.py:306 Cannot operate on a closed bus +Traceback (most recent call last): + File "C:\Users\matth\Documents\GitHub\python-can\can\broadcastmanager.py", line 304, in _run + self.bus.send(self.messages[msg_index]) + File "C:\Users\matth\Documents\GitHub\python-can\can\thread_safe_bus.py", line 59, in send + return self.__wrapped__.send(msg, timeout=timeout, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 138, in send + self._check_if_open() + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 124, in _check_if_open + raise CanOperationError("Cannot operate on a closed bus") +can.exceptions.CanOperationError: Cannot operate on a closed bus +ERROR can.bcm:broadcastmanager.py:306 Cannot operate on a closed bus +Traceback (most recent call last): + File "C:\Users\matth\Documents\GitHub\python-can\can\broadcastmanager.py", line 304, in _run + self.bus.send(self.messages[msg_index]) + File "C:\Users\matth\Documents\GitHub\python-can\can\thread_safe_bus.py", line 59, in send + return self.__wrapped__.send(msg, timeout=timeout, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 138, in send + self._check_if_open() + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 124, in _check_if_open + raise CanOperationError("Cannot operate on a closed bus") +can.exceptions.CanOperationError: Cannot operate on a closed bus +ERROR can.bcm:broadcastmanager.py:306 Cannot operate on a closed bus +Traceback (most recent call last): + File "C:\Users\matth\Documents\GitHub\python-can\can\broadcastmanager.py", line 304, in _run + self.bus.send(self.messages[msg_index]) + File "C:\Users\matth\Documents\GitHub\python-can\can\thread_safe_bus.py", line 59, in send + return self.__wrapped__.send(msg, timeout=timeout, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 138, in send + self._check_if_open() + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\virtual.py", line 124, in _check_if_open + raise CanOperationError("Cannot operate on a closed bus") +can.exceptions.CanOperationError: Cannot operate on a closed bus
Passedtest/test_bit_timing.py::test_sja10000.00
+
No log output captured.
Passedtest/test_bit_timing.py::test_from_bitrate_and_segments0.00
+
No log output captured.
Passedtest/test_bit_timing.py::test_can_fd0.00
+
No log output captured.
Passedtest/test_bit_timing.py::test_from_btr0.00
+
No log output captured.
Passedtest/test_bit_timing.py::test_btr_persistence0.00
+
No log output captured.
Passedtest/test_bit_timing.py::test_from_sample_point1.89
+
No log output captured.
Passedtest/test_bit_timing.py::test_equality0.00
+
No log output captured.
Passedtest/test_bit_timing.py::test_string_representation0.00
+
No log output captured.
Passedtest/test_bit_timing.py::test_repr0.00
+
No log output captured.
Passedtest/test_bit_timing.py::test_hash0.00
+
No log output captured.
Passedtest/test_bit_timing.py::test_mapping0.00
+
No log output captured.
Passedtest/test_bit_timing.py::test_oscillator_tolerance0.00
+
No log output captured.
Passedtest/test_bit_timing.py::test_recreate_with_f_clock0.00
+
No log output captured.
Passedtest/test_bus.py::test_bus_ignore_config0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 VirtualBus was not properly shut down +WARNING can.bus:bus.py:480 VirtualBus was not properly shut down
Passedtest/test_bus.py::test_bus_attempts_self_cleanup0.02
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 VirtualBus was not properly shut down
Passedtest/test_cantact.py::CantactTest::test_bus_creation0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 CantactBus was not properly shut down
Passedtest/test_cantact.py::CantactTest::test_bus_creation_bittiming0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 CantactBus was not properly shut down
Passedtest/test_cantact.py::CantactTest::test_recv0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 CantactBus was not properly shut down
Passedtest/test_cantact.py::CantactTest::test_recv_timeout0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 CantactBus was not properly shut down
Passedtest/test_cantact.py::CantactTest::test_shutdown0.00
+
No log output captured.
Passedtest/test_cantact.py::CantactTest::test_transmit0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 CantactBus was not properly shut down
Passedtest/test_detect_available_configs.py::TestDetectAvailableConfigs::test_content_socketcan0.00
+
-------------------------------Captured log call--------------------------------
ERROR can.interfaces.socketcan.utils:utils.py:55 failed to fetch opened can devices from ip link +Traceback (most recent call last): + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\socketcan\utils.py", line 52, in find_available_interfaces + output_str = subprocess.check_output(command, text=True) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\subprocess.py", line 466, in check_output + return run(*popenargs, stdout=PIPE, timeout=timeout, check=True, + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\subprocess.py", line 548, in run + with Popen(*popenargs, **kwargs) as process: + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\subprocess.py", line 1024, in __init__ + self._execute_child(args, executable, preexec_fn, close_fds, + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\subprocess.py", line 1509, in _execute_child + hp, ht, pid, tid = _winapi.CreateProcess(executable, args, + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +FileNotFoundError: [WinError 2] The system cannot find the file specified
Passedtest/test_detect_available_configs.py::TestDetectAvailableConfigs::test_content_udp_multicast0.00
+
No log output captured.
Passedtest/test_detect_available_configs.py::TestDetectAvailableConfigs::test_content_virtual0.00
+
No log output captured.
Passedtest/test_detect_available_configs.py::TestDetectAvailableConfigs::test_count_returned0.43
+
-------------------------------Captured log call--------------------------------
ERROR can.interfaces.socketcan.utils:utils.py:55 failed to fetch opened can devices from ip link +Traceback (most recent call last): + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\socketcan\utils.py", line 52, in find_available_interfaces + output_str = subprocess.check_output(command, text=True) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\subprocess.py", line 466, in check_output + return run(*popenargs, stdout=PIPE, timeout=timeout, check=True, + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\subprocess.py", line 548, in run + with Popen(*popenargs, **kwargs) as process: + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\subprocess.py", line 1024, in __init__ + self._execute_child(args, executable, preexec_fn, close_fds, + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\subprocess.py", line 1509, in _execute_child + hp, ht, pid, tid = _winapi.CreateProcess(executable, args, + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +FileNotFoundError: [WinError 2] The system cannot find the file specified +ERROR can.interfaces.nican:nican.py:140 Failed to load NI-CAN driver: Could not find module 'nican' (or one of its dependencies). Try using the full path with constructor syntax. +WARNING can.interfaces.iscan:iscan.py:51 Failed to load IS-CAN driver: Could not find module 'iscandrv' (or one of its dependencies). Try using the full path with constructor syntax. +WARNING can.systec:ucanbus.py:237 The SYSTEC ucan library has not been initialized. +WARNING can.interfaces.nixnet:nixnet.py:37 Could not import nixnet: No module named 'nixnet' +ERROR can.interfaces.socketcan.utils:utils.py:55 failed to fetch opened can devices from ip link +Traceback (most recent call last): + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\socketcan\utils.py", line 52, in find_available_interfaces + output_str = subprocess.check_output(command, text=True) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\subprocess.py", line 466, in check_output + return run(*popenargs, stdout=PIPE, timeout=timeout, check=True, + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\subprocess.py", line 548, in run + with Popen(*popenargs, **kwargs) as process: + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\subprocess.py", line 1024, in __init__ + self._execute_child(args, executable, preexec_fn, close_fds, + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\subprocess.py", line 1509, in _execute_child + hp, ht, pid, tid = _winapi.CreateProcess(executable, args, + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +FileNotFoundError: [WinError 2] The system cannot find the file specified +WARNING can.systec:ucanbus.py:237 The SYSTEC ucan library has not been initialized.
Passedtest/test_detect_available_configs.py::TestDetectAvailableConfigs::test_count_udp_multicast0.00
+
No log output captured.
Passedtest/test_detect_available_configs.py::TestDetectAvailableConfigs::test_general_values0.17
+
-------------------------------Captured log call--------------------------------
ERROR can.interfaces.socketcan.utils:utils.py:55 failed to fetch opened can devices from ip link +Traceback (most recent call last): + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\socketcan\utils.py", line 52, in find_available_interfaces + output_str = subprocess.check_output(command, text=True) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\subprocess.py", line 466, in check_output + return run(*popenargs, stdout=PIPE, timeout=timeout, check=True, + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\subprocess.py", line 548, in run + with Popen(*popenargs, **kwargs) as process: + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\subprocess.py", line 1024, in __init__ + self._execute_child(args, executable, preexec_fn, close_fds, + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\subprocess.py", line 1509, in _execute_child + hp, ht, pid, tid = _winapi.CreateProcess(executable, args, + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +FileNotFoundError: [WinError 2] The system cannot find the file specified +WARNING can.systec:ucanbus.py:237 The SYSTEC ucan library has not been initialized.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[kvaser]0.00
+
No log output captured.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[socketcan]0.00
+
No log output captured.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[serial]0.00
+
No log output captured.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[pcan]0.00
+
No log output captured.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[usb2can]0.00
+
No log output captured.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[ixxat]0.00
+
No log output captured.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[nican]0.00
+
No log output captured.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[iscan]0.00
+
No log output captured.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[virtual]0.00
+
No log output captured.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[udp_multicast]0.00
+
No log output captured.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[neovi]0.00
+
No log output captured.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[vector]0.00
+
No log output captured.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[slcan]0.00
+
No log output captured.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[robotell]0.00
+
No log output captured.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[canalystii]0.00
+
No log output captured.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[systec]0.00
+
-------------------------------Captured log call--------------------------------
ERROR can.systec:ucanbus.py:332 'MockInterface' object has no attribute '_ucan'
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[seeedstudio]0.00
+
No log output captured.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[cantact]0.00
+
No log output captured.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[nixnet]0.00
+
No log output captured.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[neousys]0.00
+
No log output captured.
Passedtest/test_interface.py::test_interface_calls_parent_shutdown[socketcand]0.00
+
No log output captured.
Passedtest/test_interface_canalystii.py::CanalystIITest::test_initialize_from_constructor0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 CANalystIIBus was not properly shut down
Passedtest/test_interface_canalystii.py::CanalystIITest::test_initialize_single_channel_only0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 CANalystIIBus was not properly shut down +WARNING can.bus:bus.py:480 CANalystIIBus was not properly shut down
Passedtest/test_interface_canalystii.py::CanalystIITest::test_initialize_with_timing_registers0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 CANalystIIBus was not properly shut down
Passedtest/test_interface_canalystii.py::CanalystIITest::test_missing_bitrate0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 CANalystIIBus was not properly shut down
Passedtest/test_interface_canalystii.py::CanalystIITest::test_receive_message0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 CANalystIIBus was not properly shut down
Passedtest/test_interface_canalystii.py::CanalystIITest::test_send_message0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 CANalystIIBus was not properly shut down
Passedtest/test_interface_ixxat.py::TestSoftwareCase::test_format_can_status0.00
+
No log output captured.
Passedtest/test_interface_ixxat.py::TestSoftwareCase::test_get_ixxat_hwids0.00
+
No log output captured.
Passedtest/test_interface_ixxat.py::TestSoftwareCase::test_interface_detection0.00
+
No log output captured.
Passedtest/test_interface_ixxat.py::TestDriverCase::test_bus_creation_fd0.09
+
-------------------------------Captured log call--------------------------------
INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=250000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600 +INFO can.ixxat:canlib.py:490 CAN Filters: None +WARNING can.bus:bus.py:480 IXXATBus was not properly shut down +INFO can.ixxat:canlib.py:490 CAN Filters: None +WARNING can.bus:bus.py:480 IXXATBus was not properly shut down +INFO can.ixxat:canlib.py:490 CAN Filters: None +WARNING can.bus:bus.py:480 IXXATBus was not properly shut down
Passedtest/test_interface_ixxat.py::TestDriverCase::test_bus_creation_std0.09
+
-------------------------------Captured log call--------------------------------
INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=250000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600 +INFO can.ixxat:canlib.py:490 CAN Filters: None +WARNING can.bus:bus.py:480 IXXATBus was not properly shut down +INFO can.ixxat:canlib.py:490 CAN Filters: None +WARNING can.bus:bus.py:480 IXXATBus was not properly shut down +INFO can.ixxat:canlib.py:490 CAN Filters: None +WARNING can.bus:bus.py:480 IXXATBus was not properly shut down
Passedtest/test_interface_ixxat.py::TestDriverCase::test_get_ixxat_hwids0.08
+
-------------------------------Captured log call--------------------------------
INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=250000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600
Passedtest/test_interface_ixxat.py::TestDriverCase::test_interface_detection0.17
+
-------------------------------Captured log call--------------------------------
INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=250000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600
Passedtest/test_interface_ixxat.py::TestHardwareCaseStd::test_bus_creation_deprecated_timing_args0.18
+
-------------------------------Captured log call--------------------------------
INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=500000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600 +INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=250000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600
Passedtest/test_interface_ixxat.py::TestHardwareCaseStd::test_bus_creation_invalid_bitrate0.09
+
-------------------------------Captured log call--------------------------------
INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=500000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600 +INFO can.ixxat:canlib.py:490 CAN Filters: None +WARNING can.bus:bus.py:480 IXXATBus was not properly shut down
Passedtest/test_interface_ixxat.py::TestHardwareCaseStd::test_bus_creation_invalid_channel0.16
+
-------------------------------Captured log call--------------------------------
INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=500000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600 +INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 65535 in shared mode, 16 rx buffers, 16 tx buffers +WARNING can.bus:bus.py:480 IXXATBus was not properly shut down
Passedtest/test_interface_ixxat.py::TestHardwareCaseStd::test_bus_creation_standard_bitrate0.01
+
-------------------------------Captured log call--------------------------------
INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=500000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600 +INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=1, dwBPS=1, wTS1=12, wTS2=3, wSJW=3, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=250000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600
Passedtest/test_interface_ixxat.py::TestHardwareCaseStd::test_bus_creation_timing_arg0.01
+
-------------------------------Captured log call--------------------------------
INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=1, dwBPS=2, wTS1=12, wTS2=3, wSJW=3, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=500000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600 +INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=1, dwBPS=1, wTS1=12, wTS2=3, wSJW=3, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=250000, wTS1=13, wTS2=2, wSJW=1, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0
Passedtest/test_interface_ixxat.py::TestHardwareCaseStd::test_send_after_shutdown0.00
+
-------------------------------Captured log call--------------------------------
INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=1, dwBPS=2, wTS1=12, wTS2=3, wSJW=3, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=500000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600 +INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=1, dwBPS=1, wTS1=12, wTS2=3, wSJW=3, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=250000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600
Passedtest/test_interface_ixxat.py::TestHardwareCaseStd::test_send_periodic3.01
+
-------------------------------Captured log call--------------------------------
INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=1, dwBPS=2, wTS1=12, wTS2=3, wSJW=3, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=500000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600 +INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=1, dwBPS=1, wTS1=12, wTS2=3, wSJW=3, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=250000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600
Passedtest/test_interface_ixxat.py::TestHardwareCaseStd::test_send_periodic_busabc_fallback2.00
+
-------------------------------Captured log call--------------------------------
INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=1, dwBPS=2, wTS1=12, wTS2=3, wSJW=3, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=500000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600 +INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=1, dwBPS=1, wTS1=12, wTS2=3, wSJW=3, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=250000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600
Passedtest/test_interface_ixxat.py::TestHardwareCaseStd::test_send_single0.01
+
-------------------------------Captured log call--------------------------------
INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=1, dwBPS=2, wTS1=12, wTS2=3, wSJW=3, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=500000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600 +INFO can.ixxat:canlib.py:490 CAN Filters: None +INFO can.ixxat:canlib.py:549 Searching for first available device +INFO can.ixxat:canlib.py:588 Using unique HW ID b'HW509182' +INFO can.ixxat:canlib.py:590 Initializing channel 0 in shared mode, 16 rx buffers, 16 tx buffers +INFO can.ixxat:canlib.py:624 canControl status: bOpMode=7, bExMode=0, bBusLoad=0, bReserved=0, sBtpSdr=dwMode=1, dwBPS=1, wTS1=12, wTS2=3, wSJW=3, wTDO=0, sBtpFdr=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwStatus=16 +INFO can.ixxat:canlib.py:629 canControlGetCaps result: wCtrlType=11, wBusCoupling=2, dwFeatures=767, dwCanClkFreq=8000000, sSdrRangeMin=dwMode=1, dwBPS=1, wTS1=1, wTS2=1, wSJW=1, wTDO=0, sSdrRangeMax=dwMode=1, dwBPS=64, wTS1=16, wTS2=8, wSJW=4, wTDO=0, sFdrRangeMin=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, sFdrRangeMax=dwMode=0, dwBPS=0, wTS1=0, wTS2=0, wSJW=0, wTDO=0, dwTscClkFreq=1000000, dwTscDivisor=1, dwCmsClkFreq=1000000, dwCmsDivisor=100, dwCmsMaxTicks=10000, dwDtxClkFreq=1000000, dwDtxDivisor=100, dwDtxMaxTicks=65535 +INFO can.ixxat:canlib.py:719 Initialising Channel 0 with the following parameters: +bOpMode=7, bExMode=0 +pBtpSDR=dwMode=0, dwBPS=250000, wTS1=6400, wTS2=1600, wSJW=1600, wTDO=0 +pBtpFDR=dwMode=0, dwBPS=2000000, wTS1=1600, wTS2=400, wSJW=400, wTDO=1600
Passedtest/test_interface_virtual.py::TestMessageFiltering::test_sendmsg0.00
+
No log output captured.
Passedtest/test_interface_virtual.py::TestMessageFiltering::test_sendmsg_preserve_timestamp0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 IXXATBus was not properly shut down +WARNING can.bus:bus.py:480 IXXATBus was not properly shut down
Passedtest/test_kvaser.py::KvaserTest::test_available_configs0.00
+
No log output captured.
Passedtest/test_kvaser.py::KvaserTest::test_bus_creation0.00
+
No log output captured.
Passedtest/test_kvaser.py::KvaserTest::test_bus_get_stats0.00
+
No log output captured.
Passedtest/test_kvaser.py::KvaserTest::test_bus_shutdown0.00
+
No log output captured.
Passedtest/test_kvaser.py::KvaserTest::test_canfd_custom_data_bitrate0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 KvaserBus was not properly shut down
Passedtest/test_kvaser.py::KvaserTest::test_canfd_default_data_bitrate0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 KvaserBus was not properly shut down
Passedtest/test_kvaser.py::KvaserTest::test_canfd_nondefault_data_bitrate0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 KvaserBus was not properly shut down
Passedtest/test_kvaser.py::KvaserTest::test_filter_setup0.00
+
No log output captured.
Passedtest/test_kvaser.py::KvaserTest::test_recv_extended0.00
+
No log output captured.
Passedtest/test_kvaser.py::KvaserTest::test_recv_no_message0.50
+
No log output captured.
Passedtest/test_kvaser.py::KvaserTest::test_recv_standard0.00
+
No log output captured.
Passedtest/test_kvaser.py::KvaserTest::test_send_extended0.00
+
No log output captured.
Passedtest/test_kvaser.py::KvaserTest::test_send_standard0.00
+
No log output captured.
Passedtest/test_load_config.py::LoadConfigTest::test_config_default0.00
+
No log output captured.
Passedtest/test_load_config.py::LoadConfigTest::test_config_merge_context0.00
+
No log output captured.
Passedtest/test_load_config.py::LoadConfigTest::test_config_merge_environment_to_context0.00
+
No log output captured.
Passedtest/test_load_config.py::LoadConfigTest::test_config_whole_context0.00
+
No log output captured.
Passedtest/test_load_config.py::LoadConfigTest::test_config_whole_default0.00
+
No log output captured.
Passedtest/test_load_config.py::LoadConfigTest::test_config_whole_environment0.00
+
No log output captured.
Passedtest/test_load_file_config.py::LoadFileConfigTest::test_config_file_extra0.00
+
No log output captured.
Passedtest/test_load_file_config.py::LoadFileConfigTest::test_config_file_with_default0.00
+
No log output captured.
Passedtest/test_load_file_config.py::LoadFileConfigTest::test_config_file_with_default_and_section0.00
+
No log output captured.
Passedtest/test_load_file_config.py::LoadFileConfigTest::test_config_file_with_non_existing_section0.00
+
No log output captured.
Passedtest/test_load_file_config.py::LoadFileConfigTest::test_config_file_with_section_and_key_in_default0.00
+
No log output captured.
Passedtest/test_load_file_config.py::LoadFileConfigTest::test_config_file_with_section_missing_interface0.00
+
No log output captured.
Passedtest/test_load_file_config.py::LoadFileConfigTest::test_config_file_with_section_only0.00
+
No log output captured.
Passedtest/test_logger.py::TestLoggerScriptModule::test_log_virtual0.00
+
------------------------------Captured stdout call------------------------------
Connected to VirtualBus: <MagicMock name='VirtualBus().channel_info' id='1875317799056'> +Can Logger (Started on 2023-06-25 23:16:49.976731) +
Passedtest/test_logger.py::TestLoggerScriptModule::test_log_virtual_active0.00
+
------------------------------Captured stdout call------------------------------
Connected to VirtualBus: <MagicMock name='VirtualBus().channel_info' id='1875330868240'> +Can Logger (Started on 2023-06-25 23:16:49.984738) +
Passedtest/test_logger.py::TestLoggerScriptModule::test_log_virtual_passive0.00
+
------------------------------Captured stdout call------------------------------
Connected to VirtualBus: <MagicMock name='VirtualBus().channel_info' id='1875331261776'> +Can Logger (Started on 2023-06-25 23:16:49.991745) +
Passedtest/test_logger.py::TestLoggerScriptModule::test_log_virtual_sizedlogger0.00
+
------------------------------Captured stdout call------------------------------
Connected to VirtualBus: <MagicMock name='VirtualBus().channel_info' id='1875332458576'> +Can Logger (Started on 2023-06-25 23:16:49.999752) +
Passedtest/test_logger.py::TestLoggerScriptModule::test_log_virtual_with_config0.00
+
------------------------------Captured stdout call------------------------------
Connected to VirtualBus: <MagicMock name='VirtualBus().channel_info' id='1875332510480'> +Can Logger (Started on 2023-06-25 23:16:50.007759) +
Passedtest/test_logger.py::TestLoggerScriptModule::test_parse_additional_config0.00
+
No log output captured.
Passedtest/test_logger.py::TestLoggerCompressedFile::test_compressed_logfile0.00
+
------------------------------Captured stdout call------------------------------
Connected to VirtualBus: <MagicMock name='VirtualBus().channel_info' id='1875332526864'> +Can Logger (Started on 2023-06-25 23:16:50.019136) +
Passedtest/test_message_class.py::TestMessageClass::test_methods6.31
+
No log output captured.
Passedtest/test_message_class.py::MessageSerialization::test_serialization0.00
+
No log output captured.
Passedtest/test_message_filtering.py::TestMessageFiltering::test_match_all0.00
+
No log output captured.
Passedtest/test_message_filtering.py::TestMessageFiltering::test_match_example_message0.00
+
No log output captured.
Passedtest/test_message_filtering.py::TestMessageFiltering::test_match_filters_is_empty0.00
+
No log output captured.
Passedtest/test_message_sync.py::TestMessageSync::test_general0.13
+
No log output captured.
Passedtest/test_message_sync.py::TestMessageSync::test_skip0.01
+
No log output captured.
Passedtest/test_message_sync.py::test_gap[0.0-0.0]0.20
+
No log output captured.
Passedtest/test_message_sync.py::test_gap[0.0-0.01]0.20
+
No log output captured.
Passedtest/test_message_sync.py::test_gap[0.01-1.5]0.20
+
No log output captured.
Passedtest/test_neousys.py::TestNeousysBus::test_bus_creation0.00
+
No log output captured.
Passedtest/test_neousys.py::TestNeousysBus::test_bus_creation_bitrate0.00
+
No log output captured.
Passedtest/test_neousys.py::TestNeousysBus::test_receive0.05
+
No log output captured.
Passedtest/test_neousys.py::TestNeousysBus::test_send0.00
+
No log output captured.
Passedtest/test_neousys.py::TestNeousysBus::test_shutdown0.00
+
No log output captured.
Passedtest/test_neovi.py::ICSApiErrorTest::test_error_pickling0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_api_version_low0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_api_version_read_fail0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 PcanBus was not properly shut down
Passedtest/test_pcan.py::TestPCANBus::test_auto_reset_init_fault0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 PcanBus was not properly shut down
Passedtest/test_pcan.py::TestPCANBus::test_bus_creation0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_bus_creation_auto_reset0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_bus_creation_fd_0_f_clock0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_bus_creation_fd_1_f_clock_mhz0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_bus_creation_state_error0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 PcanBus was not properly shut down
Passedtest/test_pcan.py::TestPCANBus::test_constructor_bit_timing0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 PcanBus was not properly shut down
Passedtest/test_pcan.py::TestPCANBus::test_constructor_bit_timing_fd0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 PcanBus was not properly shut down
Passedtest/test_pcan.py::TestPCANBus::test_constructor_with_device_id_00.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 PcanBus was not properly shut down
Passedtest/test_pcan.py::TestPCANBus::test_constructor_with_device_id_10.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_detect_available_configs0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_flash_0_on0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_flash_1_off0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_get_device_number_0_no_error0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_get_device_number_1_error0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_get_formatted_error_0_no_error0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_get_formatted_error_1_one_error0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_get_formatted_error_2_both_errors0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_peak_fd_bus_constructor_regression0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 PcanBus was not properly shut down
Passedtest/test_pcan.py::TestPCANBus::test_recv0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_recv_fd0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_recv_no_message0.50
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_reset_0_no_error0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_reset_1_error0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_send0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_send_error0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_send_fd0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_send_type_0_standart0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_send_type_1_extended0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_send_type_2_remote0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_send_type_3_error0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_send_type_4_fd0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_send_type_5_bitrate_switch0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_send_type_6_error_state_indicator0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_set_device_number_0_no_error0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_set_device_number_1_error0.00
+
-------------------------------Captured log call--------------------------------
ERROR can.pcan:pcan.py:483 Invalid value '3' for device number.
Passedtest/test_pcan.py::TestPCANBus::test_shutdown0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_state_0_active0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_state_1_passive0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_state_constructor0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 PcanBus was not properly shut down +WARNING can.bus:bus.py:480 PcanBus was not properly shut down
Passedtest/test_pcan.py::TestPCANBus::test_status0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_status_is_ok_0_no_error0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_status_is_ok_1_error0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_status_string_0_valid0.00
+
No log output captured.
Passedtest/test_pcan.py::TestPCANBus::test_status_string_1_invalid0.00
+
No log output captured.
Passedtest/test_player.py::TestPlayerScriptModule::test_play_error_frame0.00
+
------------------------------Captured stdout call------------------------------
Can LogReader (Started on 2023-06-25 23:16:57.888830) +Timestamp: 2.501000 ID: 00000000 X Rx E DL: 0 Channel: 0 +Timestamp: 2.501010 ID: 00000000 X Rx E DL: 0 Channel: 0 +Timestamp: 2.501020 ID: 00000000 X Rx E DL: 0 Channel: 1 +Timestamp: 2.520002 ID: 0200 S Tx R DL: 0 Channel: 2 +Timestamp: 2.584921 ID: 0300 S Tx R DL: 8 Channel: 3 +Timestamp: 3.098426 ID: 18ebff00 X Rx DL: 8 01 a0 0f a6 60 3b d1 40 Channel: 0 +Timestamp: 3.197693 ID: 18ebff00 X Rx DL: 8 03 e1 00 4b ff ff 3c 0f Channel: 0 +Timestamp: 17.876976 ID: 06f8 S Rx DL: 8 ff 00 0c fe 00 00 00 00 Channel: 0 +Timestamp: 20.105214 ID: 18ebff00 X Rx DL: 8 01 a0 0f a6 60 3b d1 40 Channel: 1 +Timestamp: 20.155119 ID: 18ebff00 X Rx DL: 8 02 1f de 80 25 df c0 2b Channel: 1 +Timestamp: 20.204671 ID: 18ebff00 X Rx DL: 8 03 e1 00 4b ff ff 3c 0f Channel: 1 +Timestamp: 20.248887 ID: 18ebff00 X Rx DL: 8 04 00 4b ff ff ff ff ff Channel: 1 +
Passedtest/test_player.py::TestPlayerScriptModule::test_play_skip_error_frame0.00
+
------------------------------Captured stdout call------------------------------
Can LogReader (Started on 2023-06-25 23:16:57.896841) +Timestamp: 2.520002 ID: 0200 S Tx R DL: 0 Channel: 2 +Timestamp: 2.584921 ID: 0300 S Tx R DL: 8 Channel: 3 +Timestamp: 3.098426 ID: 18ebff00 X Rx DL: 8 01 a0 0f a6 60 3b d1 40 Channel: 0 +Timestamp: 3.197693 ID: 18ebff00 X Rx DL: 8 03 e1 00 4b ff ff 3c 0f Channel: 0 +Timestamp: 17.876976 ID: 06f8 S Rx DL: 8 ff 00 0c fe 00 00 00 00 Channel: 0 +Timestamp: 20.105214 ID: 18ebff00 X Rx DL: 8 01 a0 0f a6 60 3b d1 40 Channel: 1 +Timestamp: 20.155119 ID: 18ebff00 X Rx DL: 8 02 1f de 80 25 df c0 2b Channel: 1 +Timestamp: 20.204671 ID: 18ebff00 X Rx DL: 8 03 e1 00 4b ff ff 3c 0f Channel: 1 +Timestamp: 20.248887 ID: 18ebff00 X Rx DL: 8 04 00 4b ff ff ff ff ff Channel: 1 +
Passedtest/test_player.py::TestPlayerScriptModule::test_play_virtual0.00
+
------------------------------Captured stdout call------------------------------
Can LogReader (Started on 2023-06-25 23:16:57.903845) +
Passedtest/test_player.py::TestPlayerScriptModule::test_play_virtual_exit0.00
+
------------------------------Captured stdout call------------------------------
Can LogReader (Started on 2023-06-25 23:16:57.909851) +
Passedtest/test_player.py::TestPlayerScriptModule::test_play_virtual_verbose0.00
+
No log output captured.
Passedtest/test_player.py::TestPlayerCompressedFile::test_play_error_frame0.00
+
------------------------------Captured stdout call------------------------------
Can LogReader (Started on 2023-06-25 23:16:57.921864) +Timestamp: 2.501000 ID: 00000000 X Rx E DL: 0 Channel: 0 +Timestamp: 2.501010 ID: 00000000 X Rx E DL: 0 Channel: 0 +Timestamp: 2.501020 ID: 00000000 X Rx E DL: 0 Channel: 1 +Timestamp: 2.520002 ID: 0200 S Tx R DL: 0 Channel: 2 +Timestamp: 2.584921 ID: 0300 S Tx R DL: 8 Channel: 3 +Timestamp: 3.098426 ID: 18ebff00 X Rx DL: 8 01 a0 0f a6 60 3b d1 40 Channel: 0 +Timestamp: 3.197693 ID: 18ebff00 X Rx DL: 8 03 e1 00 4b ff ff 3c 0f Channel: 0 +Timestamp: 17.876976 ID: 06f8 S Rx DL: 8 ff 00 0c fe 00 00 00 00 Channel: 0 +Timestamp: 20.105214 ID: 18ebff00 X Rx DL: 8 01 a0 0f a6 60 3b d1 40 Channel: 1 +Timestamp: 20.155119 ID: 18ebff00 X Rx DL: 8 02 1f de 80 25 df c0 2b Channel: 1 +Timestamp: 20.204671 ID: 18ebff00 X Rx DL: 8 03 e1 00 4b ff ff 3c 0f Channel: 1 +Timestamp: 20.248887 ID: 18ebff00 X Rx DL: 8 04 00 4b ff ff ff ff ff Channel: 1 +
Passedtest/test_player.py::TestPlayerCompressedFile::test_play_skip_error_frame0.00
+
------------------------------Captured stdout call------------------------------
Can LogReader (Started on 2023-06-25 23:16:57.928870) +Timestamp: 2.520002 ID: 0200 S Tx R DL: 0 Channel: 2 +Timestamp: 2.584921 ID: 0300 S Tx R DL: 8 Channel: 3 +Timestamp: 3.098426 ID: 18ebff00 X Rx DL: 8 01 a0 0f a6 60 3b d1 40 Channel: 0 +Timestamp: 3.197693 ID: 18ebff00 X Rx DL: 8 03 e1 00 4b ff ff 3c 0f Channel: 0 +Timestamp: 17.876976 ID: 06f8 S Rx DL: 8 ff 00 0c fe 00 00 00 00 Channel: 0 +Timestamp: 20.105214 ID: 18ebff00 X Rx DL: 8 01 a0 0f a6 60 3b d1 40 Channel: 1 +Timestamp: 20.155119 ID: 18ebff00 X Rx DL: 8 02 1f de 80 25 df c0 2b Channel: 1 +Timestamp: 20.204671 ID: 18ebff00 X Rx DL: 8 03 e1 00 4b ff ff 3c 0f Channel: 1 +Timestamp: 20.248887 ID: 18ebff00 X Rx DL: 8 04 00 4b ff ff ff ff ff Channel: 1 +
Passedtest/test_player.py::TestPlayerCompressedFile::test_play_virtual0.00
+
------------------------------Captured stdout call------------------------------
Can LogReader (Started on 2023-06-25 23:16:57.935879) +
Passedtest/test_player.py::TestPlayerCompressedFile::test_play_virtual_exit0.00
+
------------------------------Captured stdout call------------------------------
Can LogReader (Started on 2023-06-25 23:16:57.941886) +
Passedtest/test_player.py::TestPlayerCompressedFile::test_play_virtual_verbose0.00
+
No log output captured.
Passedtest/test_robotell.py::robotellTestCase::test_partial_recv2.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.robotell:robotell.py:99 Using device: Robotell USB-CAN s/n 0000-0000-0000-0000-0000-0000 on loop:// +WARNING can.interfaces.robotell:robotell.py:240 Ignoring extra 3 garbage bytes
Passedtest/test_robotell.py::robotellTestCase::test_protocol0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.robotell:robotell.py:99 Using device: Robotell USB-CAN s/n 0000-0000-0000-0000-0000-0000 on loop://
Passedtest/test_robotell.py::robotellTestCase::test_recv_extended0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.robotell:robotell.py:99 Using device: Robotell USB-CAN s/n 0000-0000-0000-0000-0000-0000 on loop://
Passedtest/test_robotell.py::robotellTestCase::test_recv_extended_remote0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.robotell:robotell.py:99 Using device: Robotell USB-CAN s/n 0000-0000-0000-0000-0000-0000 on loop://
Passedtest/test_robotell.py::robotellTestCase::test_recv_standard0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.robotell:robotell.py:99 Using device: Robotell USB-CAN s/n 0000-0000-0000-0000-0000-0000 on loop://
Passedtest/test_robotell.py::robotellTestCase::test_send_extended0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.robotell:robotell.py:99 Using device: Robotell USB-CAN s/n 0000-0000-0000-0000-0000-0000 on loop://
Passedtest/test_robotell.py::robotellTestCase::test_send_extended_remote0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.robotell:robotell.py:99 Using device: Robotell USB-CAN s/n 0000-0000-0000-0000-0000-0000 on loop://
Passedtest/test_robotell.py::robotellTestCase::test_send_standard0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.robotell:robotell.py:99 Using device: Robotell USB-CAN s/n 0000-0000-0000-0000-0000-0000 on loop://
Passedtest/test_robotell.py::robotellTestCase::test_serial_number0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.robotell:robotell.py:99 Using device: Robotell USB-CAN s/n 0000-0000-0000-0000-0000-0000 on loop:// +WARNING can.interfaces.robotell:robotell.py:184 Timeout waiting for response when reading config value 1FFFFF0.
Passedtest/test_robotell.py::robotellTestCase::test_set_auto_bus_management0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.robotell:robotell.py:99 Using device: Robotell USB-CAN s/n 0000-0000-0000-0000-0000-0000 on loop://
Passedtest/test_robotell.py::robotellTestCase::test_set_auto_retransmit0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.robotell:robotell.py:99 Using device: Robotell USB-CAN s/n 0000-0000-0000-0000-0000-0000 on loop://
Passedtest/test_robotell.py::robotellTestCase::test_set_bitrate0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.robotell:robotell.py:99 Using device: Robotell USB-CAN s/n 0000-0000-0000-0000-0000-0000 on loop://
Passedtest/test_robotell.py::robotellTestCase::test_set_hw_filter0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.robotell:robotell.py:99 Using device: Robotell USB-CAN s/n 0000-0000-0000-0000-0000-0000 on loop://
Passedtest/test_robotell.py::robotellTestCase::test_set_serial_rate0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.robotell:robotell.py:99 Using device: Robotell USB-CAN s/n 0000-0000-0000-0000-0000-0000 on loop://
Passedtest/test_robotell.py::robotellTestCase::test_when_no_fileno0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.robotell:robotell.py:99 Using device: Robotell USB-CAN s/n 0000-0000-0000-0000-0000-0000 on loop://
Passedtest/test_rotating_loggers.py::TestBaseRotatingLogger::test_import0.00
+
No log output captured.
Passedtest/test_rotating_loggers.py::TestBaseRotatingLogger::test_attributes0.00
+
No log output captured.
Passedtest/test_rotating_loggers.py::TestBaseRotatingLogger::test_get_new_writer0.01
+
No log output captured.
Passedtest/test_rotating_loggers.py::TestBaseRotatingLogger::test_rotation_filename0.00
+
No log output captured.
Passedtest/test_rotating_loggers.py::TestBaseRotatingLogger::test_rotate_without_rotator0.00
+
No log output captured.
Passedtest/test_rotating_loggers.py::TestBaseRotatingLogger::test_rotate_with_rotator0.00
+
No log output captured.
Passedtest/test_rotating_loggers.py::TestBaseRotatingLogger::test_stop0.00
+
No log output captured.
Passedtest/test_rotating_loggers.py::TestBaseRotatingLogger::test_on_message_received0.00
+
No log output captured.
Passedtest/test_rotating_loggers.py::TestSizedRotatingLogger::test_import0.00
+
No log output captured.
Passedtest/test_rotating_loggers.py::TestSizedRotatingLogger::test_attributes0.00
+
No log output captured.
Passedtest/test_rotating_loggers.py::TestSizedRotatingLogger::test_create_instance0.00
+
No log output captured.
Passedtest/test_rotating_loggers.py::TestSizedRotatingLogger::test_should_rollover0.00
+
No log output captured.
Passedtest/test_rotating_loggers.py::TestSizedRotatingLogger::test_logfile_size0.01
+
No log output captured.
Passedtest/test_rotating_loggers.py::TestSizedRotatingLogger::test_logfile_size_context_manager0.01
+
No log output captured.
Passedtest/test_scripts.py::TestLoggerScript::test_do_commands_exist1.99
+
No log output captured.
Passedtest/test_scripts.py::TestLoggerScript::test_does_not_crash0.00
+
------------------------------Captured stderr call------------------------------
usage: pytest.EXE [-h] [-c CHANNEL] + [-i {canalystii,cantact,etas,gs_usb,iscan,ixxat,kvaser,neousys,neovi,nican,nixnet,pcan,robotell,seeedstudio,serial,slcan,socketcan,socketcand,systec,udp_multicast,usb2can,vector,virtual}] + [-b BITRATE] [--fd] [--data_bitrate DATA_BITRATE] [-f LOG_FILE] [-a] [-s FILE_SIZE] [-v] + [--filter {<can_id>:<can_mask>,<can_id>~<can_mask>} [{<can_id>:<can_mask>,<can_id>~<can_mask>} ...]] + [--active | --passive] + ... + +Log CAN traffic, printing messages to stdout or to a given file. + +positional arguments: + extra_args The remaining arguments will be used for the interface and logger/player initialisation. For + example, `-i vector -c 1 --app-name=MyCanApp` is the equivalent to opening the bus with + `Bus('vector', channel=1, app_name='MyCanApp') + +options: + -h, --help show this help message and exit + -c CHANNEL, --channel CHANNEL + Most backend interfaces require some sort of channel. For example with the serial interface + the channel might be a rfcomm device: "/dev/rfcomm0". With the socketcan interface valid + channel examples include: "can0", "vcan0". + -i {canalystii,cantact,etas,gs_usb,iscan,ixxat,kvaser,neousys,neovi,nican,nixnet,pcan,robotell,seeedstudio,serial,slcan,socketcan,socketcand,systec,udp_multicast,usb2can,vector,virtual}, --interface {canalystii,cantact,etas,gs_usb,iscan,ixxat,kvaser,neousys,neovi,nican,nixnet,pcan,robotell,seeedstudio,serial,slcan,socketcan,socketcand,systec,udp_multicast,usb2can,vector,virtual} + Specify the backend CAN interface to use. If left blank, fall back to reading from + configuration files. + -b BITRATE, --bitrate BITRATE + Bitrate to use for the CAN bus. + --fd Activate CAN-FD support + --data_bitrate DATA_BITRATE + Bitrate to use for the data phase in case of CAN-FD. + -f LOG_FILE, --file_name LOG_FILE + Path and base log filename, for supported types see can.Logger. + -a, --append Append to the log file if it already exists. + -s FILE_SIZE, --file_size FILE_SIZE + Maximum file size in bytes. Rotate log file when size threshold is reached. (The resulting + file sizes will be consistent, but are not guaranteed to be exactly what is specified here due + to the rollover conditions being logger implementation specific.) + -v How much information do you want to see at the command line? You can add several of these + e.g., -vv is DEBUG + --filter {<can_id>:<can_mask>,<can_id>~<can_mask>} [{<can_id>:<can_mask>,<can_id>~<can_mask>} ...] + R|Space separated CAN filters for the given CAN interface: <can_id>:<can_mask> (matches when + <received_can_id> & mask == can_id & mask) <can_id>~<can_mask> (matches when <received_can_id> + & mask != can_id & mask) Fx to show only frames with ID 0x100 to 0x103 and 0x200 to 0x20F: + python -m can.viewer -f 100:7FC 200:7F0 Note that the ID and mask are always interpreted as + hex values + --active Start the bus as active, this is applied by default. + --passive Start the bus as passive. +
Passedtest/test_scripts.py::TestPlayerScript::test_do_commands_exist1.98
+
No log output captured.
Passedtest/test_scripts.py::TestPlayerScript::test_does_not_crash0.00
+
------------------------------Captured stderr call------------------------------
usage: pytest.EXE [-h] [-c CHANNEL] + [-i {canalystii,cantact,etas,gs_usb,iscan,ixxat,kvaser,neousys,neovi,nican,nixnet,pcan,robotell,seeedstudio,serial,slcan,socketcan,socketcand,systec,udp_multicast,usb2can,vector,virtual}] + [-b BITRATE] [--fd] [--data_bitrate DATA_BITRATE] [-f LOG_FILE] [-v] [--ignore-timestamps] + [--error-frames] [-g GAP] [-s SKIP] + ... input-file + +Replay CAN traffic. + +positional arguments: + extra_args The remaining arguments will be used for the interface and logger/player initialisation. For + example, `-i vector -c 1 --app-name=MyCanApp` is the equivalent to opening the bus with + `Bus('vector', channel=1, app_name='MyCanApp') + input-file The file to replay. For supported types see can.LogReader. + +options: + -h, --help show this help message and exit + -c CHANNEL, --channel CHANNEL + Most backend interfaces require some sort of channel. For example with the serial interface + the channel might be a rfcomm device: "/dev/rfcomm0". With the socketcan interface valid + channel examples include: "can0", "vcan0". + -i {canalystii,cantact,etas,gs_usb,iscan,ixxat,kvaser,neousys,neovi,nican,nixnet,pcan,robotell,seeedstudio,serial,slcan,socketcan,socketcand,systec,udp_multicast,usb2can,vector,virtual}, --interface {canalystii,cantact,etas,gs_usb,iscan,ixxat,kvaser,neousys,neovi,nican,nixnet,pcan,robotell,seeedstudio,serial,slcan,socketcan,socketcand,systec,udp_multicast,usb2can,vector,virtual} + Specify the backend CAN interface to use. If left blank, fall back to reading from + configuration files. + -b BITRATE, --bitrate BITRATE + Bitrate to use for the CAN bus. + --fd Activate CAN-FD support + --data_bitrate DATA_BITRATE + Bitrate to use for the data phase in case of CAN-FD. + -f LOG_FILE, --file_name LOG_FILE + Path and base log filename, for supported types see can.LogReader. + -v Also print can frames to stdout. You can add several of these to enable debugging + --ignore-timestamps Ignore timestamps (send all frames immediately with minimum gap between frames) + --error-frames Also send error frames to the interface. + -g GAP, --gap GAP <s> minimum time between replayed frames + -s SKIP, --skip SKIP <s> skip gaps greater than 's' seconds +
Passedtest/test_scripts.py::TestLogconvertScript::test_do_commands_exist2.04
+
No log output captured.
Passedtest/test_scripts.py::TestLogconvertScript::test_does_not_crash0.00
+
------------------------------Captured stderr call------------------------------
usage: pytest.EXE [-h] [-s FILE_SIZE] INFILE OUTFILE + +Convert a log file from one format to another. + +positional arguments: + INFILE Input filename. The type is dependent on the suffix, see can.LogReader. + OUTFILE Output filename. The type is dependent on the suffix, see can.Logger. + +options: + -h, --help show this help message and exit + -s FILE_SIZE, --file_size FILE_SIZE + Maximum file size in bytes. Rotate log file when size threshold is reached. +pytest.EXE: error: the following arguments are required: INFILE, OUTFILE +
Passedtest/test_slcan.py::slcanTestCase::test_partial_recv0.02
+
No log output captured.
Passedtest/test_slcan.py::slcanTestCase::test_recv_extended0.00
+
No log output captured.
Passedtest/test_slcan.py::slcanTestCase::test_recv_extended_remote0.00
+
No log output captured.
Passedtest/test_slcan.py::slcanTestCase::test_recv_standard0.00
+
No log output captured.
Passedtest/test_slcan.py::slcanTestCase::test_recv_standard_remote0.00
+
No log output captured.
Passedtest/test_slcan.py::slcanTestCase::test_send_extended0.00
+
No log output captured.
Passedtest/test_slcan.py::slcanTestCase::test_send_extended_remote0.00
+
No log output captured.
Passedtest/test_slcan.py::slcanTestCase::test_send_standard0.00
+
No log output captured.
Passedtest/test_slcan.py::slcanTestCase::test_send_standard_remote0.00
+
No log output captured.
Passedtest/test_slcan.py::slcanTestCase::test_serial_number0.00
+
No log output captured.
Passedtest/test_slcan.py::slcanTestCase::test_version0.00
+
No log output captured.
Passedtest/test_socketcan.py::SocketCANTest::test_bcm_header_factory_32_bit_sizeof_long_4_alignof_long_40.00
+
No log output captured.
Passedtest/test_socketcan.py::SocketCANTest::test_bcm_header_factory_32_bit_sizeof_long_4_alignof_long_long_80.00
+
No log output captured.
Passedtest/test_socketcan.py::SocketCANTest::test_bcm_header_factory_64_bit_sizeof_long_8_alignof_long_80.00
+
No log output captured.
Passedtest/test_socketcan.py::SocketCANTest::test_build_bcm_header0.00
+
No log output captured.
Passedtest/test_socketcan.py::SocketCANTest::test_build_bcm_transmit_header_initial_period_00.00
+
No log output captured.
Passedtest/test_socketcan.py::SocketCANTest::test_build_bcm_transmit_header_initial_period_1_240.00
+
No log output captured.
Passedtest/test_socketcan.py::SocketCANTest::test_build_bcm_tx_delete_header0.00
+
No log output captured.
Passedtest/test_socketcan.py::SocketCANTest::test_build_bcm_update_header0.00
+
No log output captured.
Passedtest/test_socketcan_helpers.py::TestSocketCanHelpers::test_find_available_interfaces_exception0.00
+
-------------------------------Captured log call--------------------------------
ERROR can.interfaces.socketcan.utils:utils.py:61 Failed to parse ip link JSON output: <h1>Not JSON</h1> +Traceback (most recent call last): + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\socketcan\utils.py", line 59, in find_available_interfaces + output_json = json.loads(output_str) + ^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\json\__init__.py", line 346, in loads + return _default_decoder.decode(s) + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\json\decoder.py", line 337, in decode + obj, end = self.raw_decode(s, idx=_w(s, 0).end()) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\json\decoder.py", line 355, in raw_decode + raise JSONDecodeError("Expecting value", s, err.value) from None +json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) +ERROR can.interfaces.socketcan.utils:utils.py:55 failed to fetch opened can devices from ip link +Traceback (most recent call last): + File "C:\Users\matth\Documents\GitHub\python-can\can\interfaces\socketcan\utils.py", line 52, in find_available_interfaces + output_str = subprocess.check_output(command, text=True) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\unittest\mock.py", line 1118, in __call__ + return self._mock_call(*args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\unittest\mock.py", line 1122, in _mock_call + return self._execute_mock_call(*args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\matth\anaconda3\envs\python_can_dev\Lib\unittest\mock.py", line 1177, in _execute_mock_call + raise effect +Exception: Something went wrong :-/
Passedtest/test_socketcan_helpers.py::TestSocketCanHelpers::test_find_available_interfaces_w_patch0.00
+
No log output captured.
Passedtest/test_systec.py::SystecTest::test_bus_bitrate0.00
+
-------------------------------Captured log call--------------------------------
INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled +INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled +WARNING can.bus:bus.py:480 UcanBus was not properly shut down
Passedtest/test_systec.py::SystecTest::test_bus_channel0.00
+
-------------------------------Captured log call--------------------------------
INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled +INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled +WARNING can.bus:bus.py:480 UcanBus was not properly shut down
Passedtest/test_systec.py::SystecTest::test_bus_creation0.00
+
-------------------------------Captured log call--------------------------------
INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled
Passedtest/test_systec.py::SystecTest::test_bus_custom_bitrate0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 UcanBus was not properly shut down +INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled +WARNING can.bus:bus.py:480 UcanBus was not properly shut down
Passedtest/test_systec.py::SystecTest::test_bus_defaults0.00
+
-------------------------------Captured log call--------------------------------
INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled +INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled +WARNING can.bus:bus.py:480 UcanBus was not properly shut down
Passedtest/test_systec.py::SystecTest::test_bus_passive_state0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 UcanBus was not properly shut down +INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled +INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled +WARNING can.bus:bus.py:480 UcanBus was not properly shut down
Passedtest/test_systec.py::SystecTest::test_bus_shutdown0.00
+
-------------------------------Captured log call--------------------------------
INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled
Passedtest/test_systec.py::SystecTest::test_filter_setup0.00
+
-------------------------------Captured log call--------------------------------
INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled +INFO can.systec:ucanbus.py:247 Hardware filtering on ID 0x918, mask 0x3 +INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled
Passedtest/test_systec.py::SystecTest::test_flush_tx_buffer0.00
+
-------------------------------Captured log call--------------------------------
INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled +INFO can.systec:ucanbus.py:262 Flushing transmit buffer
Passedtest/test_systec.py::SystecTest::test_receive_own_messages0.00
+
-------------------------------Captured log call--------------------------------
INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled +WARNING can.bus:bus.py:480 UcanBus was not properly shut down +WARNING can.bus:bus.py:480 UcanBus was not properly shut down +WARNING can.bus:bus.py:480 UcanBus was not properly shut down +WARNING can.bus:bus.py:480 UcanBus was not properly shut down +WARNING can.bus:bus.py:480 UcanBus was not properly shut down +INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled +WARNING can.bus:bus.py:480 UcanBus was not properly shut down
Passedtest/test_systec.py::SystecTest::test_recv_extended0.00
+
-------------------------------Captured log call--------------------------------
INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled
Passedtest/test_systec.py::SystecTest::test_recv_no_message0.50
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 UcanBus was not properly shut down +INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled
Passedtest/test_systec.py::SystecTest::test_recv_standard0.00
+
-------------------------------Captured log call--------------------------------
INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled
Passedtest/test_systec.py::SystecTest::test_rx_buffer_entries0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 UcanBus was not properly shut down +INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled +INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled +WARNING can.bus:bus.py:480 UcanBus was not properly shut down
Passedtest/test_systec.py::SystecTest::test_send_extended0.00
+
-------------------------------Captured log call--------------------------------
INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled
Passedtest/test_systec.py::SystecTest::test_send_standard0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 UcanBus was not properly shut down +INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled
Passedtest/test_systec.py::SystecTest::test_tx_buffer_entries0.00
+
-------------------------------Captured log call--------------------------------
INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled +INFO can.systec:ucanbus.py:251 Hardware filtering has been disabled +WARNING can.bus:bus.py:480 UcanBus was not properly shut down
Passedtest/test_util.py::RenameKwargsTest::test_obsolete0.00
+
No log output captured.
Passedtest/test_util.py::RenameKwargsTest::test_rename0.00
+
No log output captured.
Passedtest/test_util.py::RenameKwargsTest::test_rename_and_obsolete0.00
+
No log output captured.
Passedtest/test_util.py::RenameKwargsTest::test_with_new_and_alias_present0.00
+
No log output captured.
Passedtest/test_util.py::DeprecatedArgsAliasTest::test_decorator0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 UcanBus was not properly shut down
Passedtest/test_util.py::TestBusConfig::test_timing_can_use_int0.00
+
No log output captured.
Passedtest/test_util.py::TestChannel2Int::test_channel2int0.00
+
No log output captured.
Passedtest/test_util.py::TestCheckAdjustTimingClock::test_adjust_timing0.00
+
No log output captured.
Passedtest/test_util.py::TestCheckAdjustTimingClock::test_adjust_timing_fd0.00
+
No log output captured.
Passedtest/test_util.py::TestCastFromString::test_cast_from_string0.00
+
No log output captured.
Passedtest/test_vector.py::test_bus_creation_mocked0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.vector.canlib:canlib.py:289 Install pywin32 to avoid polling +WARNING can.bus:bus.py:480 VectorBus was not properly shut down
Passedtest/test_vector.py::test_bus_creation_bitrate_mocked0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.vector.canlib:canlib.py:417 xlCanSetChannelBitrate: baudr.=200000 +INFO can.interfaces.vector.canlib:canlib.py:289 Install pywin32 to avoid polling +WARNING can.bus:bus.py:480 VectorBus was not properly shut down
Passedtest/test_vector.py::test_bus_creation_fd_mocked0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.vector.canlib:canlib.py:490 xlCanFdSetConfiguration.: ABaudr.=500000, DBaudr.=500000 +INFO can.interfaces.vector.canlib:canlib.py:495 xlCanFdSetConfiguration.: sjwAbr=2, tseg1Abr=6, tseg2Abr=3 +INFO can.interfaces.vector.canlib:canlib.py:501 xlCanFdSetConfiguration.: sjwDbr=2, tseg1Dbr=6, tseg2Dbr=3 +INFO can.interfaces.vector.canlib:canlib.py:289 Install pywin32 to avoid polling +WARNING can.bus:bus.py:480 VectorBus was not properly shut down
Passedtest/test_vector.py::test_bus_creation_fd_bitrate_timings_mocked0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.vector.canlib:canlib.py:490 xlCanFdSetConfiguration.: ABaudr.=500000, DBaudr.=2000000 +INFO can.interfaces.vector.canlib:canlib.py:495 xlCanFdSetConfiguration.: sjwAbr=16, tseg1Abr=127, tseg2Abr=32 +INFO can.interfaces.vector.canlib:canlib.py:501 xlCanFdSetConfiguration.: sjwDbr=6, tseg1Dbr=27, tseg2Dbr=12 +INFO can.interfaces.vector.canlib:canlib.py:289 Install pywin32 to avoid polling +WARNING can.bus:bus.py:480 VectorBus was not properly shut down
Passedtest/test_vector.py::test_bus_creation_timing_8mhz_mocked0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.vector.canlib:canlib.py:435 xlCanSetChannelParamsC200: BTR0=0x3, BTR1=0x1c +INFO can.interfaces.vector.canlib:canlib.py:289 Install pywin32 to avoid polling +WARNING can.bus:bus.py:480 VectorBus was not properly shut down
Passedtest/test_vector.py::test_bus_creation_timing_16mhz_mocked0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.vector.canlib:canlib.py:452 xlCanSetChannelParams: baudr.=125000, sjwAbr=1, tseg1Abr=13, tseg2Abr=2 +INFO can.interfaces.vector.canlib:canlib.py:289 Install pywin32 to avoid polling +WARNING can.bus:bus.py:480 VectorBus was not properly shut down
Passedtest/test_vector.py::test_bus_creation_timingfd_mocked0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.vector.canlib:canlib.py:490 xlCanFdSetConfiguration.: ABaudr.=500000, DBaudr.=2000000 +INFO can.interfaces.vector.canlib:canlib.py:495 xlCanFdSetConfiguration.: sjwAbr=10, tseg1Abr=68, tseg2Abr=11 +INFO can.interfaces.vector.canlib:canlib.py:501 xlCanFdSetConfiguration.: sjwDbr=8, tseg1Dbr=10, tseg2Dbr=9 +INFO can.interfaces.vector.canlib:canlib.py:289 Install pywin32 to avoid polling +WARNING can.bus:bus.py:480 VectorBus was not properly shut down
Passedtest/test_vector.py::test_send_mocked0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.vector.canlib:canlib.py:289 Install pywin32 to avoid polling +WARNING can.bus:bus.py:480 VectorBus was not properly shut down
Passedtest/test_vector.py::test_send_fd_mocked0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.vector.canlib:canlib.py:490 xlCanFdSetConfiguration.: ABaudr.=500000, DBaudr.=500000 +INFO can.interfaces.vector.canlib:canlib.py:495 xlCanFdSetConfiguration.: sjwAbr=2, tseg1Abr=6, tseg2Abr=3 +INFO can.interfaces.vector.canlib:canlib.py:501 xlCanFdSetConfiguration.: sjwDbr=2, tseg1Dbr=6, tseg2Dbr=3 +INFO can.interfaces.vector.canlib:canlib.py:289 Install pywin32 to avoid polling +WARNING can.bus:bus.py:480 UcanBus was not properly shut down +WARNING can.bus:bus.py:480 UcanBus was not properly shut down +WARNING can.bus:bus.py:480 UcanBus was not properly shut down +WARNING can.bus:bus.py:480 VectorBus was not properly shut down
Passedtest/test_vector.py::test_receive_mocked0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.vector.canlib:canlib.py:289 Install pywin32 to avoid polling +WARNING can.bus:bus.py:480 VectorBus was not properly shut down
Passedtest/test_vector.py::test_receive_fd_mocked0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.vector.canlib:canlib.py:490 xlCanFdSetConfiguration.: ABaudr.=500000, DBaudr.=500000 +INFO can.interfaces.vector.canlib:canlib.py:495 xlCanFdSetConfiguration.: sjwAbr=2, tseg1Abr=6, tseg2Abr=3 +INFO can.interfaces.vector.canlib:canlib.py:501 xlCanFdSetConfiguration.: sjwDbr=2, tseg1Dbr=6, tseg2Dbr=3 +INFO can.interfaces.vector.canlib:canlib.py:289 Install pywin32 to avoid polling +WARNING can.bus:bus.py:480 VectorBus was not properly shut down
Passedtest/test_vector.py::test_receive_non_msg_event_mocked0.05
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.vector.canlib:canlib.py:289 Install pywin32 to avoid polling +WARNING can.bus:bus.py:480 VectorBus was not properly shut down
Passedtest/test_vector.py::test_receive_fd_non_msg_event_mocked0.06
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.vector.canlib:canlib.py:490 xlCanFdSetConfiguration.: ABaudr.=500000, DBaudr.=500000 +INFO can.interfaces.vector.canlib:canlib.py:495 xlCanFdSetConfiguration.: sjwAbr=2, tseg1Abr=6, tseg2Abr=3 +INFO can.interfaces.vector.canlib:canlib.py:501 xlCanFdSetConfiguration.: sjwDbr=2, tseg1Dbr=6, tseg2Dbr=3 +INFO can.interfaces.vector.canlib:canlib.py:289 Install pywin32 to avoid polling +WARNING can.bus:bus.py:480 VectorBus was not properly shut down
Passedtest/test_vector.py::test_flush_tx_buffer_mocked0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.vector.canlib:canlib.py:289 Install pywin32 to avoid polling +WARNING can.bus:bus.py:480 VectorBus was not properly shut down
Passedtest/test_vector.py::test_shutdown_mocked0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.vector.canlib:canlib.py:289 Install pywin32 to avoid polling
Passedtest/test_vector.py::test_reset_mocked0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.vector.canlib:canlib.py:289 Install pywin32 to avoid polling +WARNING can.bus:bus.py:480 VectorBus was not properly shut down
Passedtest/test_vector.py::test_popup_hw_cfg_mocked0.00
+
No log output captured.
Passedtest/test_vector.py::test_get_application_config_mocked0.00
+
No log output captured.
Passedtest/test_vector.py::test_set_application_config_mocked0.00
+
No log output captured.
Passedtest/test_vector.py::test_set_timer_mocked0.00
+
-------------------------------Captured log call--------------------------------
INFO can.interfaces.vector.canlib:canlib.py:490 xlCanFdSetConfiguration.: ABaudr.=500000, DBaudr.=500000 +INFO can.interfaces.vector.canlib:canlib.py:495 xlCanFdSetConfiguration.: sjwAbr=2, tseg1Abr=6, tseg2Abr=3 +INFO can.interfaces.vector.canlib:canlib.py:501 xlCanFdSetConfiguration.: sjwDbr=2, tseg1Dbr=6, tseg2Dbr=3 +INFO can.interfaces.vector.canlib:canlib.py:289 Install pywin32 to avoid polling +WARNING can.bus:bus.py:480 VectorBus was not properly shut down
Passedtest/test_vector.py::test_vector_error_pickle0.00
+
No log output captured.
Passedtest/test_vector.py::test_vector_subtype_error_from_generic0.00
+
No log output captured.
Passedtest/test_vector.py::test_get_channel_configs0.00
+
No log output captured.
Passedtest/test_vector.py::test_winapi_availability0.00
+
No log output captured.
Passedtest/test_vector.py::test_vector_channel_config_attributes0.00
+
No log output captured.
Passedtest/test_vector.py::test_vector_bus_params_attributes0.00
+
No log output captured.
Passedtest/test_vector.py::test_vector_can_params_attributes0.00
+
No log output captured.
Passedtest/test_vector.py::test_vector_canfd_params_attributes0.00
+
No log output captured.
Passedtest/zero_dlc_test.py::ZeroDLCTest::test_recv_non_zero_dlc0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 VirtualBus was not properly shut down +WARNING can.bus:bus.py:480 VirtualBus was not properly shut down
Passedtest/zero_dlc_test.py::ZeroDLCTest::test_recv_none0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 VirtualBus was not properly shut down
Passedtest/zero_dlc_test.py::ZeroDLCTest::test_recv_zero_dlc0.00
+
-------------------------------Captured log call--------------------------------
WARNING can.bus:bus.py:480 VirtualBus was not properly shut down +WARNING can.bus:bus.py:480 VirtualBus was not properly shut down
\ No newline at end of file diff --git a/test/test_interface_ixxat.py b/test/test_interface_ixxat.py index 1ffa97e5b..9ca2abe60 100644 --- a/test/test_interface_ixxat.py +++ b/test/test_interface_ixxat.py @@ -370,16 +370,19 @@ def test_multiple_bus_instances(self): bus3_msg.arbitration_id = bus3_msg.arbitration_id | 0x3000000 # send a message on bus 1, and try to receive it on bus 2 and bus 3 bus1.send(bus1_msg) - response2from1 = bus2.recv(0.1) - response3from1 = bus3.recv(0.1) + bus1.recv(0.25) # discard own message + response2from1 = bus2.recv(0.25) + response3from1 = bus3.recv(0.25) # send the same message on bus 2, and try to receive it on bus 1 and bus 3 bus2.send(bus2_msg) - response1from2 = bus1.recv(0.1) - response3from2 = bus3.recv(0.1) + bus2.recv(0.25) # discard own message + response1from2 = bus1.recv(0.25) + response3from2 = bus3.recv(0.25) # send the same message on bus 3, and try to receive it on bus 1 and bus 2 bus3.send(bus3_msg) - response1from3 = bus1.recv(0.1) - response2from3 = bus2.recv(0.1) + bus3.recv(0.25) # discard own message + response1from3 = bus1.recv(0.25) + response2from3 = bus2.recv(0.25) if response2from1 and response3from1 and response1from2 and response3from2 and response1from3 and response2from3: bus_checks = { diff --git a/tox.ini b/tox.ini index 477b1d4fc..88ac287e4 100644 --- a/tox.ini +++ b/tox.ini @@ -5,6 +5,7 @@ isolated_build = true deps = pytest==7.3.* pytest-timeout==2.1.* + pytest-html~=3.2.0 coveralls==3.3.1 pytest-cov==4.0.0 coverage==6.5.0 @@ -32,7 +33,7 @@ passenv = [pytest] testpaths = test -addopts = -v --timeout=300 --cov=can --cov-config=tox.ini --cov-report=lcov --cov-report=term +addopts = -v --timeout=300 --cov=can --cov-config=tox.ini --cov-report=lcov --cov-report=term --html=report.html --self-contained-html [coverage:run]