Source code for canlib.canlib.wrapper

import ctypes as ct
import logging
import struct
import sys

from .. import BetaVersionNumber, VersionNumber, deprecation, dllLoader
from . import constants as const
from .busparams import BitrateSetting
from .dll import CanlibDll
from .enums import VersionEx

_ct_dll = dllLoader.load_dll(win_name='canlib32.dll', linux_name='libcanlib.so')
dll = CanlibDll(_ct_dll)
dll.canInitializeLibrary()


class CANLib:
    """Deprecated wrapper class for the Kvaser CANlib.

    .. deprecated:: 1.5

    All functionality of this class has been moved to the canlib module itself::

      # deprecated
      from canlib import canlib
      cl = canlib.CANLib()  # or canlib.canlib()
      cl.functionName()

      # use this instead
      from canlib import canlib
      canlib.functionName()

    """

    dll = dll

    def __init__(self):
        deprecation.manual_warn(
            "Creating CANLib objects is deprecated, "
            "all functionality has been moved to the canlib module itself."
        )
        # since=1.5
        self._module = sys.modules[__name__]

    def __getattr__(self, name):
        try:
            return getattr(self._module, name)
        except AttributeError:
            raise AttributeError(
                f"{str(type(self))} object has no attribute {name}"
            )

    def openChannel(self, channel, flags=0):
        from .channel import openChannel

        return openChannel(channel, flags)


[docs]def getErrorText(error_code): """Return error text for supplied error_code""" msg = ct.create_string_buffer(80) dll.canGetErrorText(error_code, msg, ct.sizeof(msg)) return msg.value.decode()
[docs]@deprecation.deprecated.favour('dllversion') def getVersion(): """Get the CANlib DLL version number as a `str` .. deprecated:: 1.5 Use `dllversion` instead. """ return str(dllversion())
def _version_number(v, beta): """Return `VersionNumber` or `BetaVersionNumber` of v""" # assuming byte order 'little': if beta: version = BetaVersionNumber(major=v >> 8, minor=v & 0xFF) else: version = VersionNumber(major=v >> 8, minor=v & 0xFF) return version
[docs]def enumerate_hardware(): """Enumerate connected Kvaser devices and rebuild list of available channels Returns: The number of CAN channels enumerated. .. versionadded:: 1.13 """ chan_count = ct.c_int() dll.canEnumHardwareEx(ct.byref(chan_count)) return chan_count.value
[docs]def dllversion(): """Get the CANlib DLL version number Args: None Returns a `canlib.BetaVersionNumber` if the CANlib DLL is marked as beta (preview), otherwise returns `canlib.VersionNumber`. .. versionchanged:: 1.6 """ try: v = dll.canGetVersionEx(VersionEx.VERSION) except NotImplementedError: # Backward compatibility with CANlib v5.22 v = dll.canGetVersion() return _version_number(v, beta=False) beta = dll.canGetVersionEx(VersionEx.BETA) return _version_number(v, beta)
[docs]def prodversion(): """Get the CANlib Product version number Args: None Returns a `canlib.BetaVersionNumber` if the CANlib driver/DLL is marked as beta (preview), otherwise returns `canlib.VersionNumber`. .. versionadded:: 1.6 """ v = dll.canGetVersionEx(VersionEx.PRODVER) beta = dll.canGetVersionEx(VersionEx.BETA) return _version_number(v, beta)
[docs]def getNumberOfChannels(driver=False): """Get number of available CAN channels. Returns the number of available CAN channels in the computer. The virtual channels are included in this number. In order to manually re-enumerate connected devices when a device has been added or removed, use `enumerate_hardware`. Args: None Returns: chanCount (int): Number of available CAN channels """ chanCount = ct.c_int() dll.canGetNumberOfChannels(chanCount) return chanCount.value
@deprecation.deprecated.favour("ChannelData(channel).channel_flags") def getChannelData_Channel_Flags(channel): """Get channel status flags .. deprecated:: 1.5 Use `ChannelData` and their ``channel_flags`` attribute instead. Returns a `ChannelData_Channel_Flags` object holding information about the channel. Note: Currently not implemented! """ buf = ct.c_uint32() dll.canGetChannelData( channel, const.canCHANNELDATA_CHANNEL_FLAGS, ct.byref(buf), ct.sizeof(buf), ) flags = ChannelData_Channel_Flags() flags.asbyte = buf.value return flags @deprecation.deprecated.favour("ChannelData(channel).device_name") def getChannelData_Name(channel): """Get the product name. .. deprecated:: 1.5 Use `ChannelData` and their ``device_name`` attribute instead. Retrieves the product name of the device connected to channel. The name is returned as a string. Args: channel (int): The channel you are interested in Returns: product_name (string): The product name """ name = ct.create_string_buffer(80) dll.canGetChannelData( channel, const.canCHANNELDATA_DEVDESCR_ASCII, ct.byref(name), ct.sizeof(name), ) buf_type = ct.c_uint * 1 buf = buf_type() dll.canGetChannelData( channel, const.canCHANNELDATA_CHAN_NO_ON_CARD, ct.byref(buf), ct.sizeof(buf), ) return f"{name.value.decode()} (channel {buf[0]})" @deprecation.deprecated.favour("ChannelData(channel).custom_name") def getChannelData_Cust_Name(channel): """Get the customized channel name. .. deprecated:: 1.5 Use `ChannelData` and their ``custom_name`` attribute instead. Retrieves the customized device channel name of the device connected to channel. The name is returned as a string. Args: channel (int): The channel you are interested in Returns: custom_name (string): The customized device channel name """ name = ct.create_string_buffer(40) dll.canGetChannelData( channel, const.canCHANNELDATA_CUST_CHANNEL_NAME, ct.byref(name), ct.sizeof(name), ) return f"{name.value.decode()}" @deprecation.deprecated.favour("ChannelData(channel).chan_no_on_card") def getChannelData_Chan_No_On_Card(channel): """Get the channel number on the card. .. deprecated:: 1.5 Use `ChannelData` and their ``chan_no_on_card`` attribute instead. Retrieves the channel number, as numbered locally on the card, device connected to channel. Args: channel (int): The channel you are interested in Returns: number (int): The local channel number """ number = ct.c_ulong() dll.canGetChannelData( channel, const.canCHANNELDATA_CHAN_NO_ON_CARD, ct.byref(number), ct.sizeof(number), ) buf_type = ct.c_uint * 1 buf = buf_type() dll.canGetChannelData( channel, const.canCHANNELDATA_CHAN_NO_ON_CARD, ct.byref(buf), ct.sizeof(buf), ) return number.value @deprecation.deprecated.favour("ChannelData(channel).card_number") def getChannelData_CardNumber(channel): """Get the card number .. deprecated:: 1.5 Use `ChannelData` and their ``card_number`` attribute instead. Retrieves the card's number in the computer. Each card type is numbered separately. For example, the first PCIEcan card in a machine will have number 0, the second PCIEcan number 1, etc. Args: channel (int): The channel you are interested in Returns: card_number (int): The device's card number """ buf_type = ct.c_ulong buf = buf_type() dll.canGetChannelData( channel, const.canCHANNELDATA_CARD_NUMBER, ct.byref(buf), ct.sizeof(buf), ) return buf.value @deprecation.deprecated.favour("ChannelData(channel).card_upc_no") def getChannelData_EAN(channel): """Get EAN code .. deprecated:: 1.5 Use `ChannelData` and their ``card_upc_no`` attribute instead. Retrieves the EAN number for the device connected to channel. If there is no EAN number, "00-00000-00000-0" will be returned. Args: channel (int): The channel you are interested in Returns: ean (str): The device's EAN number """ buf_type = ct.c_uint32 * 2 buf = buf_type() dll.canGetChannelData( channel, const.canCHANNELDATA_CARD_UPC_NO, ct.byref(buf), ct.sizeof(buf), ) (ean_lo, ean_hi) = struct.unpack('II', buf) return "%02x-%05x-%05x-%x" % ( ean_hi >> 12, ((ean_hi & 0xFFF) << 8) | (ean_lo >> 24), (ean_lo >> 4) & 0xFFFFF, ean_lo & 0xF, ) @deprecation.deprecated def getChannelData_EAN_short(channel): """Get short EAN code .. deprecated:: 1.5 Use `ChannelData` and their ``.card_upc_no.product()`` instead. Retrieves the short EAN number, aka product number, for the device connected to channel. If there is no EAN number, "00000-0" will be returned. Args: channel (int): The channel you are interested in Returns: ean (str): The device's shortened EAN number """ buf_type = ct.c_uint32 * 2 buf = buf_type() dll.canGetChannelData( channel, const.canCHANNELDATA_CARD_UPC_NO, ct.byref(buf), ct.sizeof(buf), ) (ean_lo, ean_hi) = struct.unpack('II', buf) return f"{ean_lo >> 4 & 65535:04x}-{ean_lo & 15:x}" @deprecation.deprecated.favour("ChannelData(channel).card_serial_no") def getChannelData_Serial(channel): """Get device serial number .. deprecated:: 1.5 Use `ChannelData` and their ``card_serial_no`` attribute instead. Retrieves the serial number for the device connected to channel. If the device does not have a serial number, 0 is returned. Args: channel (int): The channel you are interested in Returns: serial (int): The device serial number """ buf_type = ct.c_uint32 * 2 buf = buf_type() dll.canGetChannelData( channel, const.canCHANNELDATA_CARD_SERIAL_NO, ct.byref(buf), ct.sizeof(buf), ) (serial_lo, serial_hi) = struct.unpack('II', buf) # serial_hi is always 0 return serial_lo @deprecation.deprecated.favour("ChannelData(channel).driver_name") def getChannelData_DriverName(channel): """Get device driver name .. deprecated:: 1.5 Use `ChannelData` and their ``driver_name`` attribute instead. Retrieves the name of the device driver (e.g. "kcany") for the device connected to channel. The device driver names have no special meanings and may change from a release to another. Args: channel (int): The channel you are interested in Returns: driver_name (str): The device driver name """ name = ct.create_string_buffer(80) dll.canGetChannelData( channel, const.canCHANNELDATA_DRIVER_NAME, ct.byref(name), ct.sizeof(name), ) return name.value.decode() @deprecation.deprecated.favour("ChannelData(channel).card_firmware_rev") def getChannelData_Firmware(channel): """Get device firmware version .. deprecated:: 1.5 Use `ChannelData` and their ``card_firmware_rev`` attribute instead. Retrieves the firmvare version numbers for the device connected to channel. Args: channel (int): The channel you are interested in Returns: (fw_major, fw_minor, fw_build): The version number """ buf_type = ct.c_ushort * 4 buf = buf_type() dll.canGetChannelData( channel, const.canCHANNELDATA_CARD_FIRMWARE_REV, ct.byref(buf), ct.sizeof(buf), ) (build, release, minor, major) = struct.unpack('HHHH', buf) return (major, minor, build)
[docs]def translateBaud(freq): """Translate bitrate constant This function translates the `.canlib.Bitrate` and `.canlib.BitrateFD` enums to their corresponding bus parameter values. Args: freq: Any of the predefined `.canlib.Bitrate` or `.canlib.BitrateFD`. Returns: A `~canlib.canlib.busparams.BitrateSetting` object containing the actual values of frequency, tseg1, tseg2 etc. """ freq_p = ct.c_long(freq) tseg1_p = ct.c_uint() tseg2_p = ct.c_uint() sjw_p = ct.c_uint() nosamp_p = ct.c_uint() syncMode_p = ct.c_uint() dll.canTranslateBaud( ct.byref(freq_p), ct.byref(tseg1_p), ct.byref(tseg2_p), ct.byref(sjw_p), ct.byref(nosamp_p), ct.byref(syncMode_p), ) rateSetting = BitrateSetting( freq=freq_p.value, tseg1=tseg1_p.value, tseg2=tseg2_p.value, sjw=sjw_p.value, nosamp=nosamp_p.value, syncMode=syncMode_p.value, ) return rateSetting
[docs]def unloadLibrary(): """Unload CANlib Unload canlib and release all internal handles. Warning: Calling `unloadLibrary` invalidates every canlib-object. Use at your own risk. """ try: dll.canUnloadLibrary() except AttributeError as e: logging.debug(str(e) + ' (Not implemented in Linux)')
[docs]def initializeLibrary(): """Initialize CANlib library Note: This initializes the driver and must be called before any other function in the CANlib DLL is used. This is handled in most cases by the Python wrapper. If you want to trigger a re-enumeration of connected devices, you should call `enumerate_hardware` instead. Any errors encountered during library initialization will be "silent" and an appropriate error code will be returned later on when an API call that requires initialization is called. """ dll.canInitializeLibrary()
[docs]def reinitializeLibrary(): """Reinitializes the CANlib driver. Convenience function that calls `unloadLibrary` and `initializeLibrary` in succession. Warning: Calling `reinitializeLibrary` invalidates every canlib-object. Use at your own risk. You most likely would like to call `enumerate_hardware()` instead. """ unloadLibrary() dll.canInitializeLibrary()
class ChannelData_Channel_Flags_bits(ct.LittleEndianStructure): """Access flags of `ChannelData_Channel_Flags` .. deprecated:: 1.5 Gives access to individual parts in `ChannelData_Channel_Flags` as flags. """ _fields_ = [ ("is_exclusive", ct.c_uint32, 1), ("is_open", ct.c_uint32, 1), ("is_canfd", ct.c_uint32, 1), ] class ChannelData_Channel_Flags(ct.Union): """Holds data from `canlib.getChannelData_Channel_Flags()` .. deprecated:: 1.5 Data in this object may be accessed as an c_uint32 using `object.asbyte`, or as indivisual flags using the class `ChannelData_Channel_Flags_bits`. """ _fields_ = [("b", ChannelData_Channel_Flags_bits), ("asbyte", ct.c_uint32)]