Запись на несколько идентичных устройств, Python USB, без серийного номера на устройстве - PullRequest
0 голосов
/ 02 января 2019

Я работаю над управлением некоторыми релейными картами из Python. Я могу отлично настроить и контролировать отдельную релейную карту (pyusb, python3.6 ubuntu 16.04). Использование стандартных методов для идентификации и настройки устройства USB.

dev = usb.core.find(idVendor=0x1a86, idProduct=0x7523)

Однако мне нужно использовать несколько устройств одного типа, и я могу найти их просто отлично:

dev = usb.core.find(idVendor=0x1a86, idProduct=0x7523, find_all=True)

Проблема возникает, потому что get_active_configuration () для обоих устройств одинаковы. Я могу запросить шину устройства и адрес устройства, однако не уверен, как использовать эту информацию USB-соединения для идентификации платы и выполнения функции последовательной записи изнутри python, используя только шину и адрес.

Примечание: в моем исследовании и документация pyusb , и несколько других сообщений на форуме указывают на использование шины и адреса USB-соединения для различения нескольких идентичных устройств, поэтому я считаю, что это правильный подход, но я я не уверен, как на самом деле написать код, чтобы сделать это, так как большинство других примеров, которые я видел, просто смотрят, чтобы соответствовать idVendor + idProduct.

Размещение здесь кода, который я сейчас использую для доступа к одному устройству:

import time
import usb.core
import usb.util

dev = usb.core.find(idVendor=0x1a86, idProduct=0x7523)

if dev is None:
    raise ValueError("Device not found")

if dev.is_kernel_driver_active(0):
    dev.detach_kernel_driver(0)

cfg = dev.get_active_configuration()
intf = cfg[(0,0)]

ep = usb.util.find_descriptor(
    intf,
    # match the first OUT endpoint
    custom_match = \
    lambda e: \
        usb.util.endpoint_direction(e.bEndpointAddress) == \
        usb.util.ENDPOINT_OUT)

assert ep is not None

# example relay hex serial command
cl_all = [0x3A, 0x46, 0x45, 0x30, 0x46, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x32, 0x46, 0x46, 0x46, 0x46, 0x45, 0x33, 0x0D, 0x0A]

# example write operation
ep.write(cl_all)

Таким образом, в основном, dev в основном выбирает любую из конфигураций, и если я использую флаг find_all = True в usb.core.find, я могу найти обе платы. Просто не уверен, как обращаться к ним отдельно, если нет серийного номера. После изучения этого я думаю (но я не уверен), что интерфейс второй платы затем сохраняется в cfg [(1,0)], но, во-первых, я не смог его успешно реализовать, и, во-вторых, не обязательно будет постоянным каждый раз, когда я загружаюсь или платы подключены и отключены.

Обновление / редактирование: после работы с этой картой в течение еще примерно 20 часов и переписки с производителем и некоторыми другими людьми, работающими над той же проблемой (ссылка на github ниже), я пришел к выводу, что плата не поддержка сериализации. Я перешел на ретранслятор на основе Ethernet и, хотя и стоил дороже, мне было легко устанавливать фиксированные IP-адреса для каждой платы и выполнять свои задачи. Я не верю, что эта проблема решаема с имеющейся у меня проблемой с USB-оборудованием, и, кроме того, плата не может вернуть простой статус (у меня есть две из этих плат, так что это не ошибка одного устройства).

https://github.com/ondrej1024/crelay/issues/21

...