@Marius82: Nochmal allgemeine Maneuverkritik:
Wenn man in der „#!”-Zeile ``env`` benutzt, dann kann Python auch an anderen Stellen als ``/usr/bin/`` installiert sein. Zum Beispiel wenn auf dem Rechner ein eigenes Python in ``/usr/local/bin`` installiert wurde oder sich der Benutzer eines in sein Heimatverzeichnis gepackt hat.
Bei Sternchen-Importen verliert man schnell die Übersicht wo welcher Name eigentlich her kommt und handelt sich eventuell Namenskollisionen ein. Es wird auch `sleep()` einmal über das Modul referenziert und sonst der per Sternchen importierte Name auf Modulebene verwendet. Das sollte man vereinheitlichen.
Das Hauptprogramm auf Modulebene sollte in einer Funktion verschwinden. Dann ist man sicherer das man nicht in Versuchung gerät in Funktionen Werte zu verwenden die nicht als Argumente übergeben wurden. Und man kann mit dem ``if __name__…``-Idiom dafür sorgen dass man das Modul ohne Effekte importieren kann.
Einrücktiefe und Namenschreibweise (Konstanten) entsprechen nicht dem
Style Guide for Python Code.
Pfade werden mit `os.path.join()` zusammen gesetzt.
Der Name `read_temp_raw()` ist zu spezifisch, da wird einfach eine Datei gelesen, dass es sich um eine Datei handelt in der eine Temperatur steht, spielt keine Rolle. Den Pfad sollte man hier als Argument übergeben können. Und mit der ``with``-Anweisung wird die Ressourcenverwaltung bei der Datei sicherer und kürzer.
Bei der ``while``-Schleife zum lesen der Datei bis die erste Zeile mit 'YES' endet steht die Anweisung zum lesen der Datei zweimal im Quelltext. Hier sollte man eher eine Schleife schreiben an deren Ende geprüft wird ob die Schleife verlassen werden soll. In Python ist das syntaktisch eine Endlosschleife mit einem bedingten ``break`` im Schleifenkörper.
Ob eine Zeichenkette mit einer anderen endet prüft man mit der `endswith()`-Methode.
`str.find()` ist so ein Überbleibsel aus Zeiten wo weniger Ausnahmen verwendet wurden. Hier würde ich `index()` verwenden. Dann muss man den Rückgabewert nicht auf einen speziellen Fehlerwert prüfen und der Fall das es nicht gefunden wird, endet in einer Ausnahme und nicht dem Folgefehler den Du Dir mit Deinem Code einhandelst. Insgesamt könnte man es sich mit `partition()` noch einfacher machen.
Und der Rückgabewert sollte eine Zahl und keine Zeichenkette sein, denn die Temperatur ist eine Zahl. Die zwei Nachkommastellen ist eine Sache die zur Ausgabe gehört und nicht zum Ermitteln des Wertes.
„Magische” Zahlen wie die Nummer des LED-Pins lassen sich einfacher ändern wenn man sie nicht mehrfach in den Quelltext schreibt, sondern als Konstante an einen Namen bindet.
Die Dokumentation zu `os.system()` verweist selbst schon darauf das man eigentlich das `subprocess`-Modul verwenden sollte.
Bei der Entscheidung „loggen” oder nicht ist viel Code doppelt vorhanden. Das deutet darauf hin, dass der Code falsch organisiert ist, also die Frage ob loggen oder nicht, an der falschen Stelle gestellt wird.
Im Fall vom Logging wird die Temperatur zweimal gelesen, also eventuell etwas anderes mit ``print`` ausgegeben als in der Datei gespeichert wird. In die Datei wird aber die Zeit von der ersten Messung geschrieben. Dafür dass Du Dir sorgen um eine Verfälschung durch die Laufzeit der ``return``-Anweisung gemacht hast, bist Du hier *sehr* grosszügig.
Insgesamt würde ich dann bei so etwas hier heraus kommen (ungetestet):
Code: Alles auswählen
#!/usr/bin/env python
import os
import glob
from datetime import datetime as DateTime
from subprocess import call
from time import sleep
import RPi.GPIO as GPIO
BASE_DIR = '/sys/bus/w1/devices/'
DEVICE_FOLDER = glob.glob(os.path.join(BASE_DIR, '28*'))[0]
DEVICE_FILE = os.path.join(DEVICE_FOLDER, 'w1_slave')
LOG_FILENAME = 'temp-daten.csv'
LED_PIN = 24
LED_DURATION = 1 # In Sekunden.
def read_lines(filename):
with open(filename) as lines:
return list(lines)
def read_temperature():
while True:
lines = read_lines(DEVICE_FILE)
if lines[0].rstrip().endswith('YES'):
break
sleep(0.2)
_, _, temperature_string = lines[1].partition('t=')
return float(temperature_string) / 1000.0
def main():
GPIO.cleanup()
GPIO.setmode(GPIO.BOARD)
GPIO.setmode(GPIO.BCM) # BCM GPIO Nummern
GPIO.setup(LED_PIN, GPIO.OUT) # Ausgang fuer LED
for module_name in ['w1-gpio', 'w1-therm']:
call(['modprobe', module_name])
interval = int(raw_input('Messintervall in Sekunden? '))
should_log = raw_input('Daten loggen? (j/n) ') == 'j'
while True:
now = DateTime.now()
values = [
'{0:%Y-%m-%d}'.format(now),
'{0:%H:%M:%S}'.format(now),
'{0:.2f}C'.format(read_temperature())
]
print ' | '.join(values)
if should_log:
#
# LED leuchtet fuer LED_DURATION sek wenn daten geschrieben werden.
#
GPIO.output(LED_PIN, True)
sleep(LED_DURATION)
GPIO.output(LED_PIN, False)
sleep(interval - LED_DURATION)
with open(LOG_FILENAME, 'a') as log_file:
log_file.write(';'.join(values) + '\n')
else:
sleep(interval)
if __name__ == '__main__':
main()