Datenstream per Subprocess

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
Peziman
User
Beiträge: 7
Registriert: Mittwoch 9. Januar 2019, 10:58

Mittwoch 9. Januar 2019, 12:58

Hallo Zusammen!

Vorwort:
Ich bin relativ neu in der Python Programmierung und sehe mich selber eher als "Noob" an. Dennoch habe ich mich auf ein paar Projekte gestürtzt, die sich Hauptsächlich um den Raspberry Pi drehen.
Mein jetziges Problem dreht sich um meinen CarPi (CarPC) der auf diesem Projekt basiert. --> https://raspicarprojekt.de/index.php
Das Projekt basiert hier auf dem XBMC (alias Kodi), daher auch Python.
Speziell geht es um die Einbindung eines Sundtek DAB+ USB Empfängers.
Bisherige Stand:
- DAB und FM Empfang läuft
- DAB und FM Sendersuche und Indizierung läuft
- Tunen, Vorwärts-, Rückwärtssuche, Quali-Check usw. läuft

Problem:
Leider Hackt es nun an der Auswertung von RDS und DLS+. Im folgenden gehe ich nur auf das Problem RDS für Analog Radio ein, da DLS+ für DAB vom Prinzip das selbe ist.
Meine Idee ist es, die Daten in einem temporären Ordner zwischen zu speichern und danach weiter zu verarbeiten.
Die Ausgabe der Daten erfolgt in der Shell mit folgendem Befehl.

Code: Alles auswählen

/opt/bin/mediaclient --readrds -d /dev/radio0
Darauf erfolgt folgende Ausgabe: (hier nur die 1. Sekunde)

Code: Alles auswählen

PROGRAM:
RADIOTEXT:
PROGRAM: KR
RADIOTEXT:
PROGRAM: KR
RADIOTEXT: die
PROGRAM: KRON
RADIOTEXT: die
PROGRAM: KRONEHIT
RADIOTEXT: die
PROGRAM: KRONEHIT
RADIOTEXT: die meis
PROGRAM: KRONEHIT
RADIOTEXT: die meis
PROGRAM: KRONEHIT
RADIOTEXT: die meis
PROGRAM: KRONEHIT
RADIOTEXT: die meiste M
PROGRAM: KRONEHIT
RADIOTEXT: die meiste M
PROGRAM: KRONEHIT
RADIOTEXT: die meiste M
PROGRAM: KRONEHIT
RADIOTEXT: die meiste Musik
PROGRAM: KRONEHIT
RADIOTEXT: KRONdie meiste Musik
PROGRAM: KRONEHIT
RADIOTEXT: KRONdie meiste Musik
PROGRAM: KRONEHIT
RADIOTEXT: KRONdie meiste Musik
PROGRAM: KRONEHIT
RADIOTEXT: KRONEHITdie meiste Musik
PROGRAM: KRONEHIT
RADIOTEXT: KRONEHITdie meiste Musik
PROGRAM: KRONEHIT
RADIOTEXT: KRONEHITdie meiste Musik
PROGRAM: KRONEHIT
RADIOTEXT: KRONEHIT - wdie meiste Musik
PROGRAM: KRONEHIT
RADIOTEXT: KRONEHIT - wdie meiste Musik
PROGRAM: KRONEHIT
RADIOTEXT: KRONEHIT - wdie meiste Musik
PROGRAM: KRONEHIT
RADIOTEXT: KRONEHIT - wir sdie meiste Musik
PROGRAM: KRONEHIT
RADIOTEXT: KRONEHIT - wir sdie meiste Musik
PROGRAM: KRONEHIT
RADIOTEXT: KRONEHIT - wir sdie meiste Musik
PROGRAM: KRONEHIT
RADIOTEXT: KRONEHIT - wir sind die meiste Musik
PROGRAM: KRONEHIT
RADIOTEXT: KRONEHIT - wir sind die meiste Musik
PROGRAM: KRONEHIT
RADIOTEXT: KRONEHIT - wir sind die meiste Musik
Die Ausgabe Erfolgt so lange bis mit Strg+C abgebrochen wird.

Ich habe dann folgendes Text-Script erstellt:

Code: Alles auswählen

import subprocess

FREQ = 104900000
lh = ""

# Tuner auf 104,9MHz stellen
tune = subprocess.call(['/opt/bin/mediaclient','-m','RADIO','-f',str(FREQ)])
# Tuner Ausgabe einschalten
unmute = subprocess.call(['/opt/bin/mediaclient','-m','RADIO','-g','off'])


Text = subprocess.Popen(['/opt/bin/mediaclient','--readrds','-d','/dev/radio0']$
lh = Text.stdout.read()
print lh
Jetzt bin ich davon ausgegangen dass ich so die selbe Ausgabe habe, wie als wenn ich das ganze direkt in die Shell eingebe.
Pustekuchen! Die Ausgabe ist folgende:

Code: Alles auswählen

pi@raspberrypi:~ $ python RDS.py
Using device: /dev/radio0
Tuning in FM Channel...
Checking for (analog) lock:
. [LOCKED]
done.
Using device: /dev/radio0
Enabling audiostream
Und bleibt dann stehen. Ich gehe davon aus das im Hintergrund der Stream abläuft und Python eigentlich wartet das der Stream beendet wird. Was aber nicht passiert.

Verstehe ich das richtig?

Wie kann ich die empfangenen Daten weiter verarbeiten?
Wie kann ich aus meinen Programm heraus, den Datenausgabe abbrechen?

Ich habe schon einige optionen von subprocess probiert, aber das ergebniss ist immer das selbe...

Ich hoffe es kann mir einer Helfen. ;)

Lg Pezi
__deets__
User
Beiträge: 5589
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mittwoch 9. Januar 2019, 15:24

Wo kommt denn der mediaclient her? Das gesamte car-pi-Forum durchzuwuehlen war mir ein bisschen muehsam. Und hast du auch ein /dev/rds0-Device parallel zu deinem Radio-Interface?
Benutzeravatar
__blackjack__
User
Beiträge: 3350
Registriert: Samstag 2. Juni 2018, 10:21

Mittwoch 9. Januar 2019, 15:36

@Peziman: `read()` liest bis zum Ende, also bis das Programm irgendwann sein Ende der Pipe schliesst. Was in diesem Fall nicht passiert, also liest `read()` ewig weiter.

Du müsstest die Ausgaben von dem Programm zeilenweise lesen und verarbeiten.

Die Zuweisung an `lh` am Anfang macht keinen Sinn, weil dieser Wert, die leere Zeichenkette, dann nirgends verwendet wird. Was soll der Name überhaupt bedeuten.

Die Rückgabewerte von der beiden `subprocess.call()`-Aufrufen bindest Du an Namen, verwendest sie dann aber nicht, also braucht man die auch nicht an Namen binden. Die zudem nicht wirklich zu dem Rückgabecode passen.

In aktuellen Python-Versionen ist `subprocess.run()` dem `call()` vorzuziehen.

`Text` ist als Name falsch. Der Name steht weder für eine Klasse, was das grosse T suggeriert, noch für einen Text. Das Objekt steht für den externen Prozess.
“I am Dyslexic of Borg, Your Ass will be Laminated” -- unknown
Peziman
User
Beiträge: 7
Registriert: Mittwoch 9. Januar 2019, 10:58

Mittwoch 9. Januar 2019, 16:37

__deets__ hat geschrieben:
Mittwoch 9. Januar 2019, 12:58
Wo kommt denn der mediaclient her?
Ist beim Treiberpaket des Sundtek DAB stick dabei.

Auf /dev/rds0 habe ich noch nicht gedacht. Muss ich dann gleich nachschauen.
__blackjack__ hat geschrieben:
Mittwoch 9. Januar 2019, 15:36
@Peziman: `read()` liest bis zum Ende, also bis das Programm irgendwann sein Ende der Pipe schliesst. Was in diesem Fall nicht passiert, also liest `read()` ewig weiter.
Also ist meine Vermutung gar nicht so verkehrt. Nur habe ich jetzt keine Ahnung wie ich das Zeilenweise löse. Mit bufsize=1 und/oder newlines=True im Popen Konstrukt?

Stimmt, du hast vollkommen recht. Das lh macht keinen Sinn.

Ich dachte ein subprocess.call muss an einem Namen gebunden sein damit es zu keinem Syntax Fehler kommt. Werde ich mir gleich anschauen.

Subprocess.run kann ich leider nicht verwenden, da xbmc kein Python 3 unterstützt. Daher bin ich auf Python 2 gebunden.

Text habe ich deswegen als Name vergeben, da es sich um den RDS-Text handelt, den ich hier versuche aus zu lesen.
Das mit der Groß und Kleinschreibung wusste ich nicht, werde aber in Zukunft darauf achten.
Danke für den Hinweis! :)
Benutzeravatar
__blackjack__
User
Beiträge: 3350
Registriert: Samstag 2. Juni 2018, 10:21

Mittwoch 9. Januar 2019, 17:00

@Peziman: `Popen.stdout` ist ein Dateiobjekt, also ``bufsize=0`` und dann einfach über das Dateiobjekt iterieren, wie man das bei einer Datei halt so macht.
“I am Dyslexic of Borg, Your Ass will be Laminated” -- unknown
Peziman
User
Beiträge: 7
Registriert: Mittwoch 9. Januar 2019, 10:58

Mittwoch 9. Januar 2019, 22:43

Mit dem richtigen Tipp, funktioniert es.
Ich habe jetzt folgendes mal zusammen getüftelt.

Code: Alles auswählen

import subprocess

FREQ = 104900000
i = 1

# Tuner auf 104,9MHz stellen
subprocess.call(['/opt/bin/mediaclient','-m','RADIO','-f',str(FREQ)])
# Tuner Ausgabe einschalten
subprocess.call(['/opt/bin/mediaclient','-m','RADIO','-g','off'])
# Offne die Text Datei zum schreiben
rds_out = open("RDS.txt","w")
# Lese RDS-Daten
readrds = subprocess.Popen(['/opt/bin/mediaclient','--readrds','-d','/dev/radio0'], stdout=subprocess.PIPE)

#Schreibe 50 Einträge mit Nummerierung in die Datei und beende das Lesen der RDS-Daten
while i < 50:
        line = readrds.stdout.readline()
        rds_out.write(str(i) + ": " + line)
        i = i + 1

readrds.kill()
rds_out.close()
Aber eins verstehe ich nicht.....
Wenn ich den RDS-Text auf der Shell per Kommando ausführe, erhalte ich folgendes....

Code: Alles auswählen

PROGRAM: KRONEHIT
RADIOTEXT: ATTENTION
In der Text-Datei kommt es dazu zu folgenden Eintägen. (ausschnitt)

Code: Alles auswählen

47: PROGRAM: KRONEHIT
48: RADIOTEXT: ATTENTION^M  ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
Ich verstehe nicht wo das ^M und die ^@ herkommen und vorallem nur in den Zeilen RADIOTEXT....
Benutzeravatar
__blackjack__
User
Beiträge: 3350
Registriert: Samstag 2. Juni 2018, 10:21

Mittwoch 9. Januar 2019, 22:52

@Peziman: Das sind nicht die Zeichen/Bytes die da drin sind, sondern so stellt sie Dein Editor dar, weil das eigentlich nicht darstellbare (Steuer)Zeichen sind. Das müsste man sich mal in einem Hexeditor oder als Hexdump anschauen. Ich vermute mal jedes ^@ ist eigentlich ein Nullbyte.
“I am Dyslexic of Borg, Your Ass will be Laminated” -- unknown
Peziman
User
Beiträge: 7
Registriert: Mittwoch 9. Januar 2019, 10:58

Mittwoch 9. Januar 2019, 23:00

Jetzt wo du es sagst, eigentlich klar.
Aber warum Die Steuerzeichen nur beim Text und nicht beim Sendernamen vorkommen ist mir etwas schleierhaft.
Aber letztendlich egal.... Mit der Ausgabe kann ich gut Arbeiten.
Antworten