Source code for being.can.pcan_darwin_patch
"""Temporary workaround for a small bug when using python-can on a Mac with a
PCAN interface running with libPCBUSB == 0.9. More details can be found here:
https://github.com/hardbyte/python-can/issues/957.
Caution:
This issue seems to be fixed with python-can version >= 4.0.0. See
https://github.com/hardbyte/python-can/blob/develop/CHANGELOG.md
"""
import re
import sys
import warnings
from ctypes import byref, c_ushort, cdll, create_string_buffer, sizeof
import can
import canopen
from can.interfaces import pcan
PCAN_LIBRARY_NAME = 'libPCBUSB.dylib'
PCAN_NONEBUS = c_ushort(0x00)
PCAN_EXT_SOFTWARE_VERSION = c_ushort(0x86)
[docs]def is_pcan_lib_installed() -> bool:
"""Check if PCAN driver library is installed or not."""
try:
cdll.LoadLibrary(PCAN_LIBRARY_NAME)
return True
except OSError:
return False
[docs]def does_python_can_need_patching() -> bool:
"""Check python-can version number for issue."""
major = can.__version__.split('.', maxsplit=1)[0]
return int(major) < 4
[docs]def patch_pcan_on_darwin():
"""Temporary workaround for an issue with the PCAN interface on a Mac and
libPCBUSB version 0.9 (32/64 bit data type issue). Patches PCAN message
structures in python-can (can.interfaces.pcan).
Example:
>>> import can
... import canopen
... # Import can & canopen before patching
... patch_pcan_on_darwin()
"""
if not sys.platform.startswith('darwin'):
warnings.warn('Not on a Mac. Nothing to patch')
return
if not is_pcan_lib_installed():
warnings.warn('PCAN driver %r seems not to be installed' % PCAN_LIBRARY_NAME)
return
if not does_python_can_need_patching():
warnings.warn('python-can >= 4.0.0 does not need patching')
return
# Get version number from dylib
lib = cdll.LoadLibrary(PCAN_LIBRARY_NAME)
buf = create_string_buffer(256)
res = lib.CAN_GetValue(PCAN_NONEBUS, PCAN_EXT_SOFTWARE_VERSION, byref(buf), sizeof(buf))
if res:
raise RuntimeError('Could not get value from lib!')
pattern = b'.+version (\d+)\.(\d+)\.(\d+)\.\d+'
m = re.match(pattern, buf.value)
major, minor, micro = map(int, m.groups())
if minor < 9:
version = b'.'.join(m.groups())
warnings.warn('Nothing to patch for PCAN driver version %s' % version.decode())
return
for mod in [pcan.basic, pcan.pcan]:
mod.TPCANMsgMac = mod.TPCANMsg
mod.TPCANMsgFDMac = mod.TPCANMsgFD