Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gs_usb command-line support (and documentation updates and stability fixes) #1790

Merged
merged 6 commits into from
Aug 10, 2024
27 changes: 25 additions & 2 deletions can/interfaces/gs_usb.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class GsUsbBus(can.BusABC):
def __init__(
self,
channel,
bitrate,
bitrate: int = 500_000,
index=None,
bus=None,
address=None,
Expand All @@ -33,18 +33,24 @@ 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:
raise CanInitializationError(
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:
Expand All @@ -68,6 +74,7 @@ def __init__(
brp=bit_timing.brp,
)
self.gs_usb.start()
self._bitrate = bitrate

super().__init__(
channel=channel,
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
7 changes: 5 additions & 2 deletions doc/interfaces/gs_usb.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)
BenGardiner marked this conversation as resolved.
Show resolved Hide resolved
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:

Expand Down Expand Up @@ -50,7 +53,7 @@ Windows, Linux and Mac.
``libusb`` must be installed.

On Windows a tool such as `Zadig <https://zadig.akeo.ie/>`_ can be used to set the USB device driver to
``libusb-win32``.
``libusbK``.


Supplementary Info
Expand Down