Playlists über RFID-Karten steuern

  • Hallo zusammen,


    ich bin neu hier im Forum und komme bei meinem Projekt aktuell nicht weiter. Da es sehr ähnlich zu dem hier beschriebenen ist, wollte ich kein neues Thema beginnen, sondern meine Frage einfach hier anhängen. Ich hoffe, das ist ok.

    Ich bin dabei einen über RFID-Karten gesteuerten Musikplayer für meinen Sohn zu bauen. Mir ist der von hailogugo gepostete Link zum Thread [Projekt] jukebox4kids (Jukebox für Kinder) bekannt, ich habe mich aber für eine etwas andere Herangehensweise entschieden und bin im Prinzip nach dieser Anleitung hier von raspis-world.de vorgegangen.

    Bisher habe ich Folgendes gemacht, was auch soweit funktioniert.

    Ich habe den mpd Player auf dem Raspberry installiert. Über SSH lässt sich dieser ohne Probleme steuern und entsprechende Playlists abspielen.

    Nun habe ich ein RFID-MFRC522-Modul angeschlossen und die MFRC522-Bibliothek von mxgxw heruntergeladen. Ebenso habe ich zuvor auch die SPI-Py Bibliothek installiert, die ebenso benötigt wird. Wenn ich nun über

    Code
    sudo python Read.py

    das entsprechende Skript starte und anschließend eine RFID-Karte vor den Reader halte, bekomme ich folgenden Output:

    Code: Output
    Welcome to the MFRC522 data read example
    Press Ctrl-C to stop.
    Card detected
    Card read UID: 123,456,789,123
    Size: 8
    Sector 8 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

    Der Kartenleser scheint mir also korrekt zu funktionieren.


    Wenn ich nun allerdings in der Read.py-Datei über eine if-Abfrage die UID weiternutzen will, funktioniert das nicht. Hierzu habe ich am Ende der Read.py folgende Zeilen ergänzt:

    Python
    if uid == [xxx,xxx,xxx,xxx]:
                    os.system("mpc stop")
                    os.system("mpc clear")
                    os.system("mpc load lieder") #lieder ist der Name meiner Playlist
                    os.system("mpc play")
    else: 
                    print "error" 

    Leider bekomme ich immer nur "error", also den else-Zweig ausgegeben. Diesen habe ich zu Testzwecken eingefügt.

    Es scheint mir eigentlich, als ob ich fast am Ziel wäre und nicht mehr viel fehlt, um die Playlists über die RFID-Karten zu steuern. Die if-Abfrage funktioniert scheinbar nur einfach nicht. Hat jemand eine Idee, was daran falsch ist?


    Viele Grüße

    Tierchenlieb

  • Wie Manul schreibt bitte immer den gesamten Code, sonst kann man das schlecht sehen.


    Wenn du es nochmal prüfst: Schau mal, dass deine Schleife an der richtigen Position steht, also da wo auch wirkliche uid gefüllt ist & gebe dir die mit einem print einfach mal aus. Wie du in Zeile 64 siehst, werden die 4 UID-Blöcke einzelnd angesprochen und zu einem Output zusammengebaut. Somit muss deine If-Abfrage sicherlich anders aussehen, oder du musst eine Hilfsvariable vorher zusammenbauen. Müsstest du aber sehen, wenn du dir uid einmal komplett ausgibst, wie es aussieht ;)

  • os.system("mpc stop")

    os.system ist veraltet und nicht mehr zu verwenden, du willst das subprocess Modul. Steht auch in der jeweiligen offiziellen Doku drin...


    Poste mal bitte Deinen kompletten Code.

    Das bitte auf jeden Fall. Und zwar den kompletten Code den du ausführst, ohne xxx o.ä.

    Füge bitte vor deine if-Abfrage folgendes ein und poste zusätzlich zu deinem Code die Ausgabe:

    Code
    print(type(uid), type(uid[0]))

    Man weiß ja nie ;)

  • Vielen Dank für das Verschieben und die Antworten. Also zunächst hier mal mein kompletter Code:

    Ich habe hier wie von Linus vorgeschlagen vor meiner if-Abfrage

    Code
    print(type(uid), type(uid[0]))

    ergänzt.

    Dies führt zu folgender Ausgabe:

    Code
    Card detected
    Card read UID: 134,97,75,31
    Size: 8
    Sector 8 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    (<type 'list'>, <type 'int'>)
    error

    Die UID wird also wie von euch vermutet nicht übergeben, demnach kann die if-Schleife auch nicht funktionieren. Ich werde gleich mal ausprobieren, ob es wie von jumpY angesprochen an der UID-Block-Notation liegt.


    Linus: Vielen Dank für den Hinweis auf das subprocess Modul. Ich werde mich darüber noch informieren und die Befehle ersetzen.

  • Also ich bin einen Schritt weiter. Mit folgendem Code funktioniert zumindest die if-Abfrage:

    Python
    if uid[0] == 134 and uid[1] == 97 and uid[2] == 75 and uid[3] == 31:
    print "Karte erkannt"
    else:
    print "error"

    Die os.system-Befehle aus dem kompletten Code funktionieren leider wie vermutet nicht. Ich versuche jetzt noch das subprocess-Modul einzubinden.


    Aber bis hierhin schonmal vielen Dank!

  • Da fehlen ne Menge Einrückungen, so wird das nichts, bitte nachbessern!

    In meinem Code sind die Einrückungen vorhanden, sonst würde es jetzt ja auch nicht funktionieren. Die sind irgendwie beim Kopieren abhanden gekommen. Ich hab den code über den nano Editor über putty eingegeben. Da ich nicht wusste wie ich direkt daraus den kompletten Code kopieren kann, habe ich mit Filezilla auf Read.py zugegriffen und sie im Notepad geöffnet und dann kopiert. Und dabei sind die Einrückungen verschwunden, also im Notepad sieht der Code schon anders aus. Generell sollte das ja bestimmt auch einfach gehen, wie?

  • Ich habe mir nicht alles durchgelesen. Wenn du nicht mehr meine Anleitung verwendest sondern in das aktuelle Projekt auf Github von Micz Flor gehst hast du alles fertig. Seit Version 1.0 ca 1 Monat ist man auf mpd als Player umgestiegen. Das webinterface sieht noch besser aus und Datein Karten usw können über dies hinzugefügt werden.


    Es gibt auch ein One LINE installer

  • Jetzt funktioniert alles. Hier noch einmal der komplette Code (ich hoffe diesmal mit richtiger Einrückung):


    Vielen Dank an alle, die mir geholfen haben!!!!

  • Wenn du mehrere Playlisten oder Lieder hinterlegen willst, setze das doch auch in eine Liste und gleiche die ab. Wie du auf die einzelnen Stellen der Liste zugreifen kannst, hast du ja jetzt gesehen, dann kannst du dir ja auch eine eigene Liste "lieder" machen. Dann ist die Abfrage in #85 nicht so undurchsichtig.


    Wenn du das vorhast, setzt du die ganzen subprocess in eine eigene Funktion, der du die gelesenen uids "sendest" im Aufruf der Funktion, die prüft ob die Liste passt und führt das aus. Dann kannst du ganz viele Listen definieren und der Code bleibt ähnlich kompakt.

  • JumpY: Ja, ich möchte mehrere Playlisten hinterlegen. Bisher hatte ich geplant, für jede Karte einen if-Abfrage einzurichten. Wenn es aber irgendwann mal sehr viele Karten und Playlists gibt, wird das ganze natürlich immer unübersichtlicher.

    Kannst du mir vielleicht etwas genauer erklären, wie du das mit der Liste meinst?

    Würde das die Abfrage vereinfachen? Also würde ich mir sparen die 4 UID-Blöcke separat abzufragen? Oder meinst du, dass ich die ganzen subprocess-Befehle in eine Funktion packen soll, um den Code kompakter zu halten oder beides?


    Ideal wäre es natürlich, wenn man das ganze weitgehend automatisieren könnte. D.h. sobald eine neue Karte eingelesen wird, wird erkannt, dass diese neu ist und es muss nur noch die zugehörige Playlist eingegeben werden. Das ist ja sicherlich möglich. Allerdings weiß ich nicht, wie ich das angehen soll.

    Feststellen, ob es eine neue Karte ist, sollte ja über den else-Zweig in der if-Abfrage gehen. Aber wie kann ich dann automatisch entsprechende Code-Zeilen an der richtigen Stelle hinzufügen?

  • Hallo,

    Theoretisch: der Raspi setzt Events ab (z.B. wenn eine Karte eingesteckt wird). Mit Python, kann man Events abfangen (catch). Das Programm muß erkennen, ob die Daten auf der Karte das richtige Format haben und sie andernfalls (evtl. mit einer Meldung) ignorieren.

    Schönen Gruß, kle

  • Ich bin nicht sonderlich vertraut mit Python, die Logik wie Ich das machen würde ist mir aber eigentlich klar, ich könnte da gleich mal einen Versuch starten. Ob das der sauberste und schönste Weg ist weiß ich dann nicht, da werden dann sicher andere noch etwas zu beitragen können.


    Zwecks "Automatisierung" bei neuen Karten: Wenn du jetzt eine unbekannte Karte vorhälst, gibt dein Programm "error" aus. Den Code laufend ändern funktioniert nicht, dann müsste die "Datenbank" der einzelnen Playlists irgendwo extern liegen, wo man etwas bearbeiten kann. Du kannst ja nicht einfach die laufende Datei automatisiert abändern.

    Gib mir mal kurz einen Überblick von wievielen Playlist wir sprechen, ob eine Auslagerung Sinn machen würde. Python kann ja sowohl mit "richtigen" Datenbanken wie MySQL o.ä. arbeiten, ist für diese Aufgabe aber oversized. Eine csv-Datei kann auch als "Datenbank" fungieren, wenn strukturiert aufgebaut. Wenn's am Ende aber nur um 5-10 Listen geht & du nicht zwingend weiter lernen möchtest für nächste Projekte, bleibt besser alles in einem Script.

    Und: Kennst du die UIDs der Karten im voraus, oder erst nach einmaligem einlesen? Dann könnte man das ganze kombinieren. Dabei ist natürlich zu beachten, dass das System am Ende eigentlich ohne sichtbare "print" Ausgabe läuft, weil das ja ein Musikplayer ist und das Terminal nicht dauerhaft sichtbar. Dann würde ich mir dazu etwas elegantes überlegen :)

  • Kannst du mir vielleicht etwas genauer erklären, wie du das mit der Liste meinst?

    Ich bin zwar nicht JumpY, aber ich könnte mir das etwa so vorstellen (mit einem dictionary statt einer Liste:

    Code
    playlists = { '134.97.75.31' : 'lieder' }
    
    # nach Einlesen:
    karte = '.'.join(x for x in uid)
    
    if karte in playlists.keys():
        # ...
        subprocess.call(['mpc','load',playlist[karte]], shell=True)
        # ...

    Ideal wäre es natürlich, wenn man das ganze weitgehend automatisieren könnte. D.h. sobald eine neue Karte eingelesen wird, wird erkannt, dass diese neu ist und es muss nur noch die zugehörige Playlist eingegeben werden.

    Wie würdest Du die Playlist denn eingeben wollen? Ich hätte erwartet, daß Dein Player eher headless ist, d.h. weder Monitor noch Tastatur besitzt. Habe ich Dich da falsch verstanden?