web-dev-qa-db-fra.com

Un moyen simple de demander des informations sur les périphériques USB connectés en Python?

Comment interroger les informations des périphériques USB connectés en Python? Je souhaite obtenir le nom de périphérique UID (ex: SonyEricsson W660), le chemin d'accès au périphérique (ex:/dev/ttyACM0).

Et aussi quel serait le meilleur paramètre parmi les informations ci-dessus pour identifier le périphérique à chaque fois qu’il est reconnecté? (UID?)

Je travaille sur Ubuntu 11.04.

ATM j'ai ce code (en utilisant 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

Le problème est que je ne reçois pas la sortie désirée, vais coller un exemple

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

D'abord, je n'ai pas le nom de fichier, c'est le plus important pour moi. Je suppose que c’est la partie/dev/ttyACM0, etc. Deuxièmement, je suppose qu'il y a un UID sur chaque périphérique USB, ou dois-je utiliser à la fois le fournisseur ou le produit?

EDIT: Apparemment, j'ai quelques problèmes d'installation, je pense que j'utilise une mauvaise bibliothèque USB. (en utilisant libusb0.1) ATM. C'est pourquoi la chaîne Device (dev.filename) est vide. Si quelqu'un peut, s'il vous plaît, indiquer simplement sur quel système d'exploitation il utilise quelle bibliothèque USB et quelle version de PyUSB, je pense que cela résoudra mes problèmes.

25
BlackDivine

Je peux penser à un code rapide comme celui-ci.

Tous les ports USB étant accessibles via/dev/bus/usb/<bus>/<périphérique>

Pour l'ID généré, même si vous débranchez le périphérique et le rattachez [ce pourrait être un autre port]. Ce sera pareil.

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

Exemple de sortie ici:

[
{'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'}
]
43
meson10

Si vous travaillez sur Windows, vous pouvez utiliser pywin32 .

J'ai trouvé un exemple ici :

import win32com.client

wmi = win32com.client.GetObject ("winmgmts:")
for usb in wmi.InstancesOf ("Win32_USBHub"):
    print usb.DeviceID
33
joaquin

Pour Linux, j’ai écrit un script appelé find_port.py que vous pouvez trouver ici: https://github.com/dhylands/usb-ser-mon/blob/master/usb_ser_mon/find_port.py

Il utilise pyudev pour énumérer tous les périphériques tty et peut correspondre à différents attributs.

Utilisez l'option --list pour afficher tous les ports série USB connus et leurs attributs. Vous pouvez filtrer par VID, PID, numéro de série ou nom de fournisseur. Utilisez --help pour voir les options de filtrage.

find_port.py affiche le nom/dev/ttyXXX plutôt que le nom/dev/usb/....

3
Dave Hylands

Vous pouvez essayer libusb bindings

2
wRAR

Pour un système avec usb hérité revenant et libusb-1.0, cette approche fonctionnera pour extraire les différentes chaînes réelles. Je montre le vendeur et le produit à titre d'exemples. Cela peut entraîner des E/S, car il lit en fait les informations du périphérique (du moins la première fois, de toute façon.) Certains périphériques ne fournissent pas ces informations. Par conséquent, la présomption qu’ils le font lève une exception. ça va, alors on passe.

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
fyngyrz

Lorsque je lance votre code, j'obtiens le résultat suivant, par exemple.

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

Il convient de noter que a) j'ai des objets usb.Device alors que vous avez des objets usb.legacy.Device, et b) j'ai des noms de fichiers de périphérique. 

Chaque usb.Bus a un champ dirname et chaque usb.Device a le nom du fichier. Comme vous pouvez le constater, le nom du fichier est quelque chose comme 001, de même que le nom du répertoire. Vous pouvez les combiner pour obtenir le fichier de bus. Pour dirname=001 et filname=001, cela devrait ressembler à/dev/bus/usb/001/001.

Vous devez d’abord comprendre ce qu’est cette situation "usb.legacy". J'utilise la dernière version et je n'ai même pas de sous-module legacy

Enfin, vous devez utiliser les champs idVendor et idProduct pour identifier de manière unique le périphérique lorsqu'il est branché.

1
user626998

Si vous avez juste besoin du nom de l'appareil, voici un petit bidouillage que j'ai écrit en bash. Pour l'exécuter en python, vous avez besoin de l'extrait suivant. Il suffit de remplacer $ 1 et $ 2 par le numéro de bus et le numéro d'appareil, par exemple 001 ou 002.

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

Alternativement, vous pouvez l'enregistrer en tant que script bash et l'exécuter à partir de là aussi. Il suffit de le sauvegarder en tant que script bash comme foo.sh pour le rendre exécutable. 

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

Puis appelez-le en script python en tant que 

import os
os.system('foo.sh')
0
Qasim Ayyaz Khan