@Ls342: Noch ein paar Anmerkungen zum Quelltext:
Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst. So wie es aussieht scheint das ganze Programm aus *einem* grossen Brocken Code zu bestehen, den man besser auf Funktionen oder Methoden verteilen sollte.
Namen sollten nicht abgekürzt werden. Einbuchstabige Namen sind nur in wenigen Ausnahmefällen sinnvoll, beispielsweise bei ganzzahligen Laufvariablen in Schleifen die aus der Mathematik üblichen `i`, `j`, `k`, oder `x`, `y`, `z` für Koordinaten. Ebenfalls nicht allzu schädlich sind einbuchstabige Namen die auf einen einzigen Ausdruck begrenzt sind („list comprehension“, Generatorausdruck, ``lambda``-Ausdruck). Aber `u` für eine serielle Verbindung oder `i` und `j` wo man bei der Definition nicht sieht was die eigentlich bedeuten sollen, gehen nicht.
`uart` wäre für `u` ein besserer Namen, aber das verrät IMHO nicht genug, denn das steht ja nicht für eine beliebige UART-Verbindung, sondern für eine zu einem Display.
Namen für alles ausser Konstanten und Klassen werden in Python konventionell `klein_mit_unterstrichen` geschrieben. Also `play_pause` statt `playPause`. Siehe auch den
Style Guide for Python Code.
`senden` wäre ein passender Name für eine Funktion oder Methode, weil die etwas tun und `senden` eine Tätigkeit beschreibt. Ein `bytearray` würde niemand hinter dem Namen vermuten. `display_send_buffer` wäre vielleicht ein passender Name. Allerdings frage ich mich gerade ob sich die Werte in dem Array während des Programmablaufs jemals ändern‽ Falls nicht, braucht man kein veränderliches `bytearray`, sondern hätte eine Konstante die man als `bytes()`-Objekt anlegen könnte. Und dann wäre der Name eher so etwas wie `FRAME_MARKER` oder etwas in der Art, wenn ich mir die Verwendung anschaue. Und es würde sich dann vielleicht auch lohnen die Verbindung zum Display in einer Klasse zu kapseln, damit man das Senden der dieser drei Bytes nicht unzählige male über den gesamten Quelltext verstreut zu stehen hat.
`fav_adress` wird unnötigerweise zweimal an eine leere Liste gebunden. Der Namen enthält eine Abkürzung und spiegelt auch nicht wieder das ein Container mit mehr als einer Adresse an den Namen gebunden wird. Namen für Listen haben üblicherweise die Mehrzahl des Bezeichners der für ein Element Sinn machen würde. Also beispielsweise `favourite_addresses` in diesem Fall.
Wenn man Dateien mit der ``with``-Anweisung zusammen öffnet, dann ist sichergestellt, dass sie am Ende auch wieder geschlossen werden, egal aus welchem Grund der ``with``-Block verlassen wird.
Der Name der Datei wäre ein sinnvoller Kandidat für eine Konstante, damit man den einfach am Programmanfang ändern/anpassen kann.
Um Bedingungen bei ``if`` und ``while`` gehören keine Klammern und man sollte das auch nicht so schreiben das man ``if`` und ``while`` mit Funktionsaufrufen verwechseln kann. Bei dem ``if`` sind auch in der Bedingung noch überflüssige Klammern.
Das gelesene Byte könnte man gleich nach dem Lesen schon in eine Zahl umwandeln, dann muss man das später nicht immer wieder aufs Neue machen.
Dieser Zahlwert wird im Programm dann mit ”magischen Zahlen” verglichen und `mode` ist auch ein Name der an solche ”magischen Zahlen” gebunden wird. So wie es jetzt dort steht, weiss man als Leser nicht was 0 oder 10 eigentlich bedeutet. Dafür führt man üblicherweise Konstanten ein, entweder unzusammenhängende, oder mittels `enum`-Modul. Das ist zwar erst mit Python 3 gekommen, aber es gibt für Python 2 einen „backport“ im Python Package Index. So etwas wie ``mode = RADIO_MODE`` oder ``mode = Mode.radio`` ist doch viel verständlicher als ``mode = 10``. (Sofern ich jetzt die Bedeutung der 10 denn richtig geraten habe, aber genau das ist ja das Problem mit ”magischen Zahlen”.)
Man kann literale Zeichenketten in ' oder " einfassen und das ist grösstenteils Geschmackssache welche man nimmt, aber wenn die Zeichenkette selbst dann eines dieser beiden Zeichen enthält, ist es sehr sinnvoll zum einfassen das *andere* zu nehmen, weil man dann nichts mit \ „escapen“ muss. Also "spam=\"Hallo\";" vs. 'spam="Hallo";', oder auch "O'Reilly" vs. 'O\'Reilly'.
Das Zusammensetzen von literalen Zeichenketten und Werten mittels ``+`` und `str()` ist eher BASIC als Python. In Python gibt es dafür Zeichenkettenformatierung.
Die ersten drei Sendevorgänge würden sich auch prima in einer Schleife machen, weil die fast identisch sind.
Kommentare sollten dem Leser einen Mehrwert über den Code geben. Wenn im Kommentar nur das steht was man als Programmierer im Quelltext oder in der Dokumentation nachlesen kann, dann braucht man den Kommentar nicht. Faustregel: Nicht kommentieren *was* der Code macht, denn das steht da schon als Code, sondern *warum* er das so macht. Sofern das überhaupt erklärungsbedürftig ist. Under dem Kriterium sind die ganzen Kommentare im Code überflüssig. ``# Deklaration Variablen`` ist zu dem falsch, weil das keine Deklaration ist sondern ”nur” eine Definition. Deklarationen gibt es in Python auch, wenn auch nur sehr wenige, darum sollte man diese beiden Begriffe nicht durcheinander bringen.
Aus den `print()`-Ausgaben würde ich `logging`-Ausgaben machen, insbesondere da das ja sowieso als Dienst im Hintergrund laufen zu scheint.
Ich lande dann ungefähr hier als Zwischenschritt (ungetestet):
Code: Alles auswählen
#!/usr/bin/python
# coding: utf8
from __future__ import absolute_import, division, print_function
import time
import mraa
RADIO_ADDRESSES_FILENAME = '/root/app/radio_adress.txt'
# TODO Oder als `enum.Enum` definieren.
I_HAVE_NO_IDEA_MODE = 0 # FIXME Namenswahl.
RADIO_MODE = 10
def main():
#
# TODO Sinnvoll auf Funktionen oder Methoden verteilen.
#
print('Programm start')
display = mraa.Uart(0)
display.setBaudRate(9600)
display.setMode(8, mraa.UART_PARITY_NONE, 1)
display.setFlowcontrol(False, False)
#
# TODO Falls das hier eine Konstante ist, dann wirklich eine Konstante
# daraus machen und die Verbindung zum Display in einer Klasse kapseln
# um die ganzen Sendeoperationen dieser drei Bytes nicht überall im
# Quelltext stehen haben zu müssen.
#
display_send_buffer = bytearray(b'\xff' * 3)
relais = mraa.Gpio(46)
relais.dir(mraa.DIR_OUT)
relais.write(0)
mode = I_HAVE_NO_IDEA_MODE
i = 0 # FIXME Namenswahl.
j = 1 # FIXME Namenswahl.
volume = 50
play_pause = 0
display.write(display_send_buffer)
display.writeStr('page Home_Screen')
display.write(display_send_buffer)
print('Bereitschaft gesendet!')
favourite_addresses = []
with open(RADIO_ADDRESSES_FILENAME) as lines:
for line in lines:
line = line.rstrip()
favourite_addresses.append(line)
print(line)
while True:
if display.dataAvailable():
byte_value = ord(display.readStr(1))
print(byte_value)
if byte_value == 10 and mode == I_HAVE_NO_IDEA_MODE:
print('Output Select Internetradio')
mode = RADIO_MODE
display.write(display_send_buffer)
#
# FIXME Hier ist ein Fehler der aber weiter oben behoben werden
# sollte, oder durch auslagern in eine Funktion oder
# Methode.
#
for i, address in enumerate(favourite_addresses, 1):
display.writeStr('fav{0}.txt="{1}"'.format(i, address))
display.write(display_send_buffer)
display.writeStr('vol.txt="Volume: {}"'.format(volume))
display.write(display_send_buffer)
# ...(weitere elif abfragen)...
time.sleep(0.1)
if __name__ == '__main__':
main()