Dev Pfad eines USB Gerätes rausfinden

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
HeAdLeSs
User
Beiträge: 22
Registriert: Dienstag 8. März 2016, 09:22

Hallo zusammen.

Ich habe heute eine recht knifflige Aufgabe und weiß noch nicht so ganz wie.

Ich habe ein USB Gerät, welches als Serielle Schnittstelle fungiert und Daten empfangen werden müssen. Nun ist der /dev/-Pfad ja keine Konstante. Daher möchte ich gern den korrekten Pfad des USB Sticks immer mal wieder prüfen und ggf. korrigieren oder - falls der USB Stick mal ganz 'weg' sein sollte, das Programm stoppen.
Ich hoffe das war jetzt nicht zu umständlich ausgedrückt.

Ich bin kein Linux Profi, also brauche ich eure Hilfe.

Ich hätte jetzt lsusb ausgelesen, geschaut ob mein Stick mit dabei ist (Vorhanden?). Doch wie kriege ich heraus welcher /dev/-Pfad diesem Stick zugeordnet ist?
Wahrscheinlich geht mein Anliegen auch anders ganz einfach, oder?

Das System ist ein Raspberry Pi mit Debian.
HeAdLeSs
User
Beiträge: 22
Registriert: Dienstag 8. März 2016, 09:22

Das mit dem Pfad habe ich jetzt erst einmal gelöst. Wahrscheinlich nicht die schönste Lösung, aber wie gesagt, ich bin kein Profi in Linux.

Code: Alles auswählen

    tty_port = ""
    process = subprocess.Popen("dmesg | grep FTDI", stdout=subprocess.PIPE, close_fds=True, shell=True)
    out, err = process.communicate()
    if out != "":
        out = out.splitlines()
        for line in reversed(out):
            if line.find("FTDI USB Serial Device converter now attached to") > -1:
                tty_port = line.split("FTDI USB Serial Device converter now attached to")
                tty_port = tty_port[1].strip()
                break

    print "Err: " + str(err)

    process.stdout.close()

    # kill
    try:
        process.kill()
    except OSError:
        # can't kill a dead proc
        pass
    del process

    if tty_port != "":
        ve = vedirect('/dev/' + str(tty_port))
    else:
        print "Kein Port gefunden."
Jetzt habe ich aber ein neues Problem.
Ich habe noch weitere USB Geräte am Pi hängen. Starte ich den Pi neu, dann bindet er (aktuell) den FTDI als erstes ein und er bekommt /dev/ttyUSB0. Soweit ok. Will ich ihn dann Auslesen, meckert Python rum "device reports readiness to read but returned no data (device disconnected?)". Nach ein wenig rumschnüffeln scheint es so das ein anderes Gerät genau den gleichen Port belegt (mein Huawei UMTS Modem).
Connecte ich den FTDI erst nachdem der Pi gestartet ist, dann bekommt es den Port /dev/ttyUSB3 und alles ist gut. Das ist aber keine Lösung. Der muss beim Starten schon korrekt eingebunden werden.

Am Pi ist ein USB Hub. Vielleicht liegt da das Problem? Oder kann ich dem FTDI irgendwie einen festen Port (/dev/ttyUSB*) zuweisen? Oder dem OS sagen das dieses USB Gerät als letztes Conncted werden soll.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das hier ist ein Python Forum. Natürlich benutzen viele hier Linux, aber ggf. hast du mehr Erfolg im Ubuntu Forum zb.

Ein Stichwort das vielleicht hilft: udev rules. Damit kann man sowas wohl beeinflussen.
nezzcarth
User
Beiträge: 1632
Registriert: Samstag 16. April 2011, 12:47

Ergäzend zu dem was __deets__ bzgl. des Zuweisens eines konkreten Gerätenamens schrieb:
Bei mir funktioniert für das Auslesen der Gerätepfade folgendes:

Code: Alles auswählen

In [1]: import os.path

In [2]: from glob import glob

In [3]: for device in glob('/dev/serial/by-id/*'):
   ...:     print(device, '->', os.path.realpath(device))
   ...:     
/dev/serial/by-id/<Name des Geräts> -> /dev/ttyUSB0

Allerdings würde ich, wie __deets__ mit seinem Verweis auf Udev Regeln schon angedeutet hat, nicht behaupten wollen, dass du diese Struktur exakt so bei dir vorfindest, bzw. dass das Distributions-übergreifend und dauerhaft stabil so funktioniert. Ein bisschen sauberer als das greppen eines hard-codeten Teils des Gerätenamens in dmesg ist es aber denke ich schon. Vielleicht kennt ja noch jemand eine zuverlässigere Methode.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@HeAdLeSs: subprocess sollte man nicht mit `shell=True` aufrufen. Das `grep` wird bei Deinem Code ja gar nicht gebraucht, weil Du in Python sowieso die Zeilen filterst.
Bei einem Programm wartet man auch, bis es sich von selbst beendet und killt es nicht einfach sondern wartet auf das Ende mit `wait`.
Du gibst `stderr` aus, obwohl Du es gar nicht umleitest. Statt leerer String nimmt man None für nicht vorhandene Werte.
Statt `find` nimmt man hier den `in`-Operator. `del` hat nicht den Effekt, den Du Dir denkst und wird eigentlich nie gebraucht.

Code: Alles auswählen

    tty_port = None
    process = subprocess.Popen(["dmesg"], stdout=subprocess.PIPE)
    for line in process.stdout:
        if "FTDI USB Serial Device converter now attached to" in line:
            tty_port = line.rsplit(None, 1)[-1]
    process.wait()

    if not tty_port:
        raise RuntimeError("Kein Port gefunden.")
    ve = vedirect('/dev/%s' % tty_port)
Ach ja, der erste Google-Treffer zu Deinem Problem führt zu https://forum.ubuntuusers.de/topic/prob ... r-geloest/. Keine Ahnung ob's daran liegt.
Antworten