From aeff58dc9504c4a1b8d6cdb0a2a08f7a2e7384fa Mon Sep 17 00:00:00 2001 From: Ben Gardiner Date: Sat, 10 Aug 2024 05:44:59 -0400 Subject: [PATCH] gs_usb command-line support (and documentation updates and stability fixes) (#1790) * gs_usb, doc: correct docs to indicate libusbK not libusb-win32 * gs_usb, interface: fix bug on second .start() by repeating in shutdown() v2: updates as per review https://github.com/hardbyte/python-can/pull/1790#pullrequestreview-2121408123 by @zariiii9003 * gs_usb, interface: set a default bitrate of 500k (like many other interfaces) * gs_usb, interface: support this interface on command-line with e.g. can.logger by treating channel like index when all other arguments are missing * gs_usb: improve docs, don't use dev reference before assignment as requested in review https://github.com/hardbyte/python-can/pull/1790#pullrequestreview-2121408123 by @zariiii9003 * gs_usb: fix bug in transmit when frame timestamp is set (causes failure to pack 64bit host timestamp into gs_usb field) --- can/interfaces/gs_usb.py | 27 +++++++++++++++++++++++++-- doc/interfaces/gs_usb.rst | 7 +++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/can/interfaces/gs_usb.py b/can/interfaces/gs_usb.py index 5efbd3da6..6268350ee 100644 --- a/can/interfaces/gs_usb.py +++ b/can/interfaces/gs_usb.py @@ -17,7 +17,7 @@ class GsUsbBus(can.BusABC): def __init__( self, channel, - bitrate, + bitrate: int = 500_000, index=None, bus=None, address=None, @@ -33,11 +33,16 @@ def __init__( :param can_filters: not supported :param bitrate: CAN network bandwidth (bits/s) """ + self._is_shutdown = False if (index is not None) and ((bus or address) is not None): raise CanInitializationError( "index and bus/address cannot be used simultaneously" ) + if index is None and address is None and bus is None: + index = channel + + self._index = None if index is not None: devs = GsUsb.scan() if len(devs) <= index: @@ -45,6 +50,7 @@ def __init__( f"Cannot find device {index}. Devices found: {len(devs)}" ) gs_usb = devs[index] + self._index = index else: gs_usb = GsUsb.find(bus=bus, address=address) if not gs_usb: @@ -68,6 +74,7 @@ def __init__( brp=bit_timing.brp, ) self.gs_usb.start() + self._bitrate = bitrate super().__init__( channel=channel, @@ -102,7 +109,7 @@ def send(self, msg: can.Message, timeout: Optional[float] = None): frame = GsUsbFrame() frame.can_id = can_id frame.can_dlc = msg.dlc - frame.timestamp_us = int(msg.timestamp * 1000000) + frame.timestamp_us = 0 # timestamp frame field is only useful on receive frame.data = list(msg.data) try: @@ -154,5 +161,21 @@ def _recv_internal( return msg, False def shutdown(self): + if self._is_shutdown: + return + super().shutdown() self.gs_usb.stop() + if self._index is not None: + # Avoid errors on subsequent __init() by repeating the .scan() and .start() that would otherwise fail + # the next time the device is opened in __init__() + devs = GsUsb.scan() + if self._index < len(devs): + gs_usb = devs[self._index] + try: + gs_usb.set_bitrate(self._bitrate) + gs_usb.start() + gs_usb.stop() + except usb.core.USBError: + pass + self._is_shutdown = True diff --git a/doc/interfaces/gs_usb.rst b/doc/interfaces/gs_usb.rst index 3a869911c..e9c0131c5 100755 --- a/doc/interfaces/gs_usb.rst +++ b/doc/interfaces/gs_usb.rst @@ -8,13 +8,16 @@ and candleLight USB CAN interfaces. Install: ``pip install "python-can[gs_usb]"`` -Usage: pass device ``index`` (starting from 0) if using automatic device detection: +Usage: pass device ``index`` or ``channel`` (starting from 0) if using automatic device detection: :: import can + import usb + dev = usb.core.find(idVendor=0x1D50, idProduct=0x606F) bus = can.Bus(interface="gs_usb", channel=dev.product, index=0, bitrate=250000) + bus = can.Bus(interface="gs_usb", channel=0, bitrate=250000) # same Alternatively, pass ``bus`` and ``address`` to open a specific device. The parameters can be got by ``pyusb`` as shown below: @@ -50,7 +53,7 @@ Windows, Linux and Mac. ``libusb`` must be installed. On Windows a tool such as `Zadig `_ can be used to set the USB device driver to - ``libusb-win32``. + ``libusbK``. Supplementary Info