def get_application_config( app_name: str, app_channel: int) -> Tuple[xldefine.XL_HardwareType, int, int]: """Retrieve information for an application in Vector Hardware Configuration. :param app_name: The name of the application. :param app_channel: The channel of the application. :return: Returns a tuple of the hardware type, the hardware index and the hardware channel. :raises can.interfaces.vector.VectorInitializationError: If the application name does not exist in the Vector hardware configuration. """ if xldriver is None: raise CanInterfaceNotImplementedError( "The Vector API has not been loaded") hw_type = ctypes.c_uint() hw_index = ctypes.c_uint() hw_channel = ctypes.c_uint() _app_channel = ctypes.c_uint(app_channel) xldriver.xlGetApplConfig( app_name.encode(), _app_channel, hw_type, hw_index, hw_channel, xldefine.XL_BusTypes.XL_BUS_TYPE_CAN, ) return xldefine.XL_HardwareType( hw_type.value), hw_index.value, hw_channel.value
def __init__( self, channel: Union[str, int], bitrate: int = 500000, poll_interval: float = 0.01, **kwargs, ) -> None: """ :param channel: Device number :param bitrate: Bitrate in bits/s :param poll_interval: Poll interval in seconds when reading messages """ if iscan is None: raise CanInterfaceNotImplementedError( "Could not load isCAN driver") self.channel = ctypes.c_ubyte(int(channel)) self.channel_info = f"IS-CAN: {self.channel}" if bitrate not in self.BAUDRATES: raise ValueError( f"Invalid bitrate, choose one of {set(self.BAUDRATES)}") self.poll_interval = poll_interval iscan.isCAN_DeviceInitEx(self.channel, self.BAUDRATES[bitrate]) super().__init__(channel=channel, bitrate=bitrate, poll_interval=poll_interval, **kwargs)
def popup_vector_hw_configuration(wait_for_finish: int = 0) -> None: """Open vector hardware configuration window. :param wait_for_finish: Time to wait for user input in milliseconds. """ if xldriver is None: raise CanInterfaceNotImplementedError( "The Vector API has not been loaded") xldriver.xlPopupHwConfig(ctypes.c_char_p(), ctypes.c_uint(wait_for_finish))
def __init__( self, channel: str, baudrate: int = 115200, timeout: float = 0.1, rtscts: bool = False, *args, **kwargs, ) -> None: """ :param channel: The serial device to open. For example "/dev/ttyS1" or "/dev/ttyUSB0" on Linux or "COM1" on Windows systems. :param baudrate: Baud rate of the serial device in bit/s (default 115200). .. warning:: Some serial port implementations don't care about the baudrate. :param timeout: Timeout for the serial device in seconds (default 0.1). :param rtscts: turn hardware handshake (RTS/CTS) on and off :raises can.CanInitializationError: If the given parameters are invalid. :raises can.CanInterfaceNotImplementedError: If the serial module is not installed. """ if not serial: raise CanInterfaceNotImplementedError( "the serial module is not installed") if not channel: raise TypeError("Must specify a serial port.") self.channel_info = f"Serial interface: {channel}" try: self._ser = serial.serial_for_url(channel, baudrate=baudrate, timeout=timeout, rtscts=rtscts) except ValueError as error: raise CanInitializationError( "could not create the serial device") from error super().__init__(channel, *args, **kwargs)
def set_application_config( app_name: str, app_channel: int, hw_type: xldefine.XL_HardwareType, hw_index: int, hw_channel: int, **kwargs: Any, ) -> None: """Modify the application settings in Vector Hardware Configuration. This method can also be used with a channel config dictionary:: import can from can.interfaces.vector import VectorBus configs = can.detect_available_configs(interfaces=['vector']) cfg = configs[0] VectorBus.set_application_config(app_name="MyApplication", app_channel=0, **cfg) :param app_name: The name of the application. Creates a new application if it does not exist yet. :param app_channel: The channel of the application. :param hw_type: The hardware type of the interface. E.g XL_HardwareType.XL_HWTYPE_VIRTUAL :param hw_index: The index of the interface if multiple interface with the same hardware type are present. :param hw_channel: The channel index of the interface. :raises can.interfaces.vector.VectorInitializationError: If the application name does not exist in the Vector hardware configuration. """ if xldriver is None: raise CanInterfaceNotImplementedError( "The Vector API has not been loaded") xldriver.xlSetApplConfig( app_name.encode(), app_channel, hw_type, hw_index, hw_channel, xldefine.XL_BusTypes.XL_BUS_TYPE_CAN, )
def check_msgpack_installed() -> None: """Raises a :class:`can.CanInterfaceNotImplementedError` if `msgpack` is not installed.""" if msgpack is None: raise CanInterfaceNotImplementedError("msgpack not installed")
def __init__( self, channel: Union[int, Sequence[int], str], can_filters: Optional[CanFilters] = None, poll_interval: float = 0.01, receive_own_messages: bool = False, bitrate: Optional[int] = None, rx_queue_size: int = 2**14, app_name: Optional[str] = "CANalyzer", serial: Optional[int] = None, fd: bool = False, data_bitrate: Optional[int] = None, sjw_abr: int = 2, tseg1_abr: int = 6, tseg2_abr: int = 3, sjw_dbr: int = 2, tseg1_dbr: int = 6, tseg2_dbr: int = 3, **kwargs: Any, ) -> None: """ :param channel: The channel indexes to create this bus with. Can also be a single integer or a comma separated string. :param can_filters: See :class:`can.BusABC`. :param receive_own_messages: See :class:`can.BusABC`. :param poll_interval: Poll interval in seconds. :param bitrate: Bitrate in bits/s. :param rx_queue_size: Number of messages in receive queue (power of 2). CAN: range `16…32768` CAN-FD: range `8192…524288` :param app_name: Name of application in *Vector Hardware Config*. If set to `None`, the channel should be a global channel index. :param serial: Serial number of the hardware to be used. If set, the channel parameter refers to the channels ONLY on the specified hardware. If set, the `app_name` does not have to be previously defined in *Vector Hardware Config*. :param fd: If CAN-FD frames should be supported. :param data_bitrate: Which bitrate to use for data phase in CAN FD. Defaults to arbitration bitrate. :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) :param tseg2_dbr: Bus timing value tseg2 (data) :raise can.CanInterfaceNotImplementedError: If the current operating system is not supported or the driver could not be loaded. :raise can.CanInitializationError: If the bus could not be set up. This may or may not be a :class:`can.interfaces.vector.VectorInitializationError`. """ if os.name != "nt" and not kwargs.get("_testing", False): raise CanInterfaceNotImplementedError( f"The Vector interface is only supported on Windows, " f'but you are running "{os.name}"') if xldriver is None: raise CanInterfaceNotImplementedError( "The Vector API has not been loaded") self.xldriver = xldriver # keep reference so mypy knows it is not None self.poll_interval = poll_interval self.channels: Sequence[int] if isinstance(channel, int): self.channels = [channel] elif isinstance(channel, str): # must be checked before generic Sequence # Assume comma separated string of channels self.channels = [int(ch.strip()) for ch in channel.split(",")] elif isinstance(channel, Sequence): self.channels = [int(ch) for ch in channel] else: raise TypeError( f"Invalid type for channels parameter: {type(channel).__name__}" ) self._app_name = app_name.encode() if app_name is not None else b"" self.channel_info = "Application %s: %s" % ( app_name, ", ".join(f"CAN {ch + 1}" for ch in self.channels), ) if serial is not None: app_name = None channel_index = [] channel_configs = get_channel_configs() for channel_config in channel_configs: if channel_config.serialNumber == serial: if channel_config.hwChannel in self.channels: channel_index.append(channel_config.channelIndex) if channel_index: if len(channel_index) != len(self.channels): LOG.info( "At least one defined channel wasn't found on the specified hardware." ) self.channels = channel_index else: # Is there any better way to raise the error? raise CanInitializationError( "None of the configured channels could be found on the specified hardware." ) self.xldriver.xlOpenDriver() self.port_handle = xlclass.XLportHandle(xldefine.XL_INVALID_PORTHANDLE) self.mask = 0 self.fd = fd # Get channels masks self.channel_masks: Dict[Optional[Channel], int] = {} self.index_to_channel = {} for channel in self.channels: if app_name: # Get global channel index from application channel hw_type, hw_index, hw_channel = self.get_application_config( app_name, channel) LOG.debug("Channel index %d found", channel) idx = self.xldriver.xlGetChannelIndex(hw_type, hw_index, hw_channel) if idx < 0: # Undocumented behavior! See issue #353. # If hardware is unavailable, this function returns -1. # Raise an exception as if the driver # would have signalled XL_ERR_HW_NOT_PRESENT. raise VectorInitializationError( xldefine.XL_Status.XL_ERR_HW_NOT_PRESENT, xldefine.XL_Status.XL_ERR_HW_NOT_PRESENT.name, "xlGetChannelIndex", ) else: # Channel already given as global channel idx = channel mask = 1 << idx self.channel_masks[channel] = mask self.index_to_channel[idx] = channel self.mask |= mask permission_mask = xlclass.XLaccess() # Set mask to request channel init permission if needed if bitrate or fd: permission_mask.value = self.mask if fd: self.xldriver.xlOpenPort( self.port_handle, self._app_name, self.mask, permission_mask, rx_queue_size, xldefine.XL_InterfaceVersion.XL_INTERFACE_VERSION_V4, xldefine.XL_BusTypes.XL_BUS_TYPE_CAN, ) else: self.xldriver.xlOpenPort( self.port_handle, self._app_name, self.mask, permission_mask, rx_queue_size, xldefine.XL_InterfaceVersion.XL_INTERFACE_VERSION, xldefine.XL_BusTypes.XL_BUS_TYPE_CAN, ) LOG.debug( "Open Port: PortHandle: %d, PermissionMask: 0x%X", self.port_handle.value, permission_mask.value, ) if permission_mask.value == self.mask: if fd: self.canFdConf = xlclass.XLcanFdConf() if bitrate: self.canFdConf.arbitrationBitRate = int(bitrate) else: self.canFdConf.arbitrationBitRate = 500000 self.canFdConf.sjwAbr = int(sjw_abr) self.canFdConf.tseg1Abr = int(tseg1_abr) self.canFdConf.tseg2Abr = int(tseg2_abr) if data_bitrate: self.canFdConf.dataBitRate = int(data_bitrate) else: self.canFdConf.dataBitRate = self.canFdConf.arbitrationBitRate self.canFdConf.sjwDbr = int(sjw_dbr) self.canFdConf.tseg1Dbr = int(tseg1_dbr) self.canFdConf.tseg2Dbr = int(tseg2_dbr) self.xldriver.xlCanFdSetConfiguration(self.port_handle, self.mask, self.canFdConf) LOG.info( "SetFdConfig.: ABaudr.=%u, DBaudr.=%u", self.canFdConf.arbitrationBitRate, self.canFdConf.dataBitRate, ) LOG.info( "SetFdConfig.: sjwAbr=%u, tseg1Abr=%u, tseg2Abr=%u", self.canFdConf.sjwAbr, self.canFdConf.tseg1Abr, self.canFdConf.tseg2Abr, ) LOG.info( "SetFdConfig.: sjwDbr=%u, tseg1Dbr=%u, tseg2Dbr=%u", self.canFdConf.sjwDbr, self.canFdConf.tseg1Dbr, self.canFdConf.tseg2Dbr, ) else: if bitrate: self.xldriver.xlCanSetChannelBitrate( self.port_handle, permission_mask, bitrate) LOG.info("SetChannelBitrate: baudr.=%u", bitrate) else: LOG.info("No init access!") # Enable/disable TX receipts tx_receipts = 1 if receive_own_messages else 0 self.xldriver.xlCanSetChannelMode(self.port_handle, self.mask, tx_receipts, 0) if HAS_EVENTS: self.event_handle = xlclass.XLhandle() self.xldriver.xlSetNotification(self.port_handle, self.event_handle, 1) else: LOG.info("Install pywin32 to avoid polling") try: self.xldriver.xlActivateChannel( self.port_handle, self.mask, xldefine.XL_BusTypes.XL_BUS_TYPE_CAN, 0) except VectorOperationError as error: self.shutdown() raise VectorInitializationError.from_generic(error) from None # Calculate time offset for absolute timestamps offset = xlclass.XLuint64() try: if time.get_clock_info("time").resolution > 1e-5: ts, perfcounter = time_perfcounter_correlation() try: self.xldriver.xlGetSyncTime(self.port_handle, offset) except VectorInitializationError: self.xldriver.xlGetChannelTime(self.port_handle, self.mask, offset) current_perfcounter = time.perf_counter() now = ts + (current_perfcounter - perfcounter) self._time_offset = now - offset.value * 1e-9 else: try: self.xldriver.xlGetSyncTime(self.port_handle, offset) except VectorInitializationError: self.xldriver.xlGetChannelTime(self.port_handle, self.mask, offset) self._time_offset = time.time() - offset.value * 1e-9 except VectorInitializationError: self._time_offset = 0.0 self._is_filtered = False super().__init__(channel=channel, can_filters=can_filters, **kwargs)