Простой способ запросить информацию о подключенных USB-устройствах в Python? - PullRequest
27 голосов
/ 13 ноября 2011

Как мы можем запросить информацию о подключенных USB-устройствах в Python? Я хочу получить имя устройства UID (например: SonyEricsson W660), путь к устройству (например: / dev / ttyACM0)

А также, какой из вышеперечисленных параметров лучше всего использовать для идентификации устройства при каждом повторном подключении? (UID?)

Я работаю в Ubuntu 11.04.

Банкомат У меня есть этот код (с использованием pyUSB)

busses = usb.busses()
for bus in busses:
  devices = bus.devices
  for dev in devices:
    print repr(dev)
    print "Device:", dev.filename
    print "  idVendor: %d (0x%04x)" % (dev.idVendor, dev.idVendor)
    print "  idProduct: %d (0x%04x)" % (dev.idProduct, dev.idProduct)
    print "Manufacturer:", dev.iManufacturer
    print "Serial:", dev.iSerialNumber
    print "Product:", dev.iProduct

Проблема в том, что я не получаю желаемый результат, вставлю один пример:

<usb.legacy.Device object at 0x1653990>
Device: 
  idVendor: 4046 (0x0fce)
  idProduct: 53411 (0xd0a3)
Manufacturer: 1
Serial: 3
Product: 2

Во-первых, у меня нет имени файла, это самое важное для меня. Я предполагаю, что это часть / dev / ttyACM0 и т. Д. Во-вторых, я полагаю, что у каждого USB-устройства был какой-то UID, или я должен использовать и Vendor, или Product id?

РЕДАКТИРОВАТЬ: Очевидно, у меня есть некоторые проблемы с настройкой, я думаю, что я использую неправильную библиотеку USB. (используя libusb0.1) Банкомат. Вот почему я получаю пустую строку Device (dev.filename). Если кто-то может, пожалуйста, просто сказать, что в какой операционной системе он использует какую библиотеку USB и какую версию PyUSB, я думаю, что это решит мои проблемы.

Ответы [ 7 ]

47 голосов
/ 25 ноября 2011

Я могу придумать быстрый код, подобный этому.

Поскольку все USB-порты доступны через / dev / bus / usb / /

Для идентификаторагенерируется, даже если вы отключите устройство и снова подключите его [это может быть какой-то другой порт].Это будет то же самое.

import re
import subprocess
device_re = re.compile("Bus\s+(?P<bus>\d+)\s+Device\s+(?P<device>\d+).+ID\s(?P<id>\w+:\w+)\s(?P<tag>.+)$", re.I)
df = subprocess.check_output("lsusb")
devices = []
for i in df.split('\n'):
    if i:
        info = device_re.match(i)
        if info:
            dinfo = info.groupdict()
            dinfo['device'] = '/dev/bus/usb/%s/%s' % (dinfo.pop('bus'), dinfo.pop('device'))
            devices.append(dinfo)
print devices

Пример вывода здесь будет:

[
{'device': '/dev/bus/usb/001/009', 'tag': 'Apple, Inc. Optical USB Mouse [Mitsumi]', 'id': '05ac:0304'},
{'device': '/dev/bus/usb/001/001', 'tag': 'Linux Foundation 2.0 root hub', 'id': '1d6b:0002'},
{'device': '/dev/bus/usb/001/002', 'tag': 'Intel Corp. Integrated Rate Matching Hub', 'id': '8087:0020'},
{'device': '/dev/bus/usb/001/004', 'tag': 'Microdia ', 'id': '0c45:641d'}
]
33 голосов
/ 13 ноября 2011

Если вы работаете с Windows, вы можете использовать pywin32.

Я нашел пример здесь :

import win32com.client

wmi = win32com.client.GetObject ("winmgmts:")
for usb in wmi.InstancesOf ("Win32_USBHub"):
    print usb.DeviceID
3 голосов
/ 27 мая 2015

Для Linux я написал скрипт find_port.py, который вы можете найти здесь: https://github.com/dhylands/usb-ser-mon/blob/master/usb_ser_mon/find_port.py

Он использует pyudev для перечисления всех tty-устройств и может соответствовать различным атрибутам.

Используйте параметр --list, чтобы отобразить все известные последовательные порты USB и их атрибуты. Вы можете фильтровать по VID, PID, серийному номеру или названию поставщика. Используйте --help, чтобы увидеть параметры фильтрации.

find_port.py печатает имя / dev / ttyXXX, а не имя / dev / usb / ....

2 голосов
/ 04 ноября 2014

Для системы с устаревшими usb и libusb-1.0 этот подход будет работать для извлечения различных фактических строк. Я показываю поставщика и продукт в качестве примеров. Это может вызвать некоторый ввод-вывод, потому что он фактически считывает информацию с устройства (по крайней мере, в первый раз, во всяком случае.) Некоторые устройства не предоставляют эту информацию, поэтому предположение, что они это сделают, вызовет исключение; все в порядке, так что мы проходим.

import usb.core
import usb.backend.libusb1

busses = usb.busses()
for bus in busses:
    devices = bus.devices
    for dev in devices:
        if dev != None:
            try:
                xdev = usb.core.find(idVendor=dev.idVendor, idProduct=dev.idProduct)
                if xdev._manufacturer is None:
                    xdev._manufacturer = usb.util.get_string(xdev, xdev.iManufacturer)
                if xdev._product is None:
                    xdev._product = usb.util.get_string(xdev, xdev.iProduct)
                stx = '%6d %6d: '+str(xdev._manufacturer).strip()+' = '+str(xdev._product).strip()
                print stx % (dev.idVendor,dev.idProduct)
            except:
                pass
2 голосов
/ 13 ноября 2011

Вы можете попробовать привязки libusb

1 голос
/ 18 ноября 2011

Когда я запускаю ваш код, я получаю следующий вывод, например.

<usb.Device object at 0xef38c0>
Device: 001
  idVendor: 7531 (0x1d6b)
  idProduct: 1 (0x0001)
Manufacturer: 3
Serial: 1
Product: 2

Примечательно, что а) у меня есть usb.Device объекты, тогда как у вас есть usb.legacy.Device объекты, и б) у меня есть имена устройств.

У каждого usb.Bus есть поле dirname, а у каждого usb.Device есть имя файла. Как вы можете видеть, имя файла примерно такое же, как 001, как и имя каталога. Вы можете объединить их, чтобы получить файл шины. Для dirname=001 и filname=001 это должно быть что-то вроде /dev/bus/usb/001/001.

Сначала вы должны хотя бы выяснить, что это за ситуация с «usb.legacy». Я использую последнюю версию, и у меня даже нет субмодуля legacy.

Наконец, вы должны использовать поля idVendor и idProduct, чтобы однозначно идентифицировать устройство, когда оно подключено.

0 голосов
/ 14 ноября 2011

Если вам просто нужно имя устройства, вот небольшой взлом, который я написал в bash. Чтобы запустить его в Python, вам понадобится следующий фрагмент. Просто замените $ 1 и $ 2 на номер шины и номер устройства, например, 001 или 002.

import os
os.system("lsusb | grep \"Bus $1 Device $2\" | sed 's/\// /' | awk '{for(i=7;i<=NF;++i)print $i}'")

Вы также можете сохранить его как скрипт bash и запустить его оттуда. Просто сохраните его как скрипт bash, например, foo.sh, чтобы сделать его исполняемым.

#!/bin/bash
myvar=$(lsusb | grep "Bus $1 Device $2" | sed 's/\// /' | awk '{for(i=7;i<=NF;++i)print $i}')
echo $myvar

Затем назовите его в скрипте Python как

import os
os.system('foo.sh')
...