Korrelationswert Geschrieben March 5, 2014 at 16:57 Geschrieben March 5, 2014 at 16:57 Hallo Leute, bin nun endlich dazu gekommen, etwas mit der Wetterstation zu machen. Mein Ziel ist es erstmal das Skript, welches verschieden Wetterdaten anzeigen kann ( http://www.tinkerforge.com/de/doc/Kits/WeatherStation/CSharpToButtonControl.html#starter-kit-weather-station-button-control-csharp ) von C# in Python zu übertragen. Bisher klappt folgendes: -Alle Buttons funktionieren -Button 0: Anzeige des Datums -Button 1: Aktuelle Wetterdaten -Button 2: Min-Max-Avg Daten -Button 3: Display ausschalten Was noch zu tun ist: -Fortlaufende Aktualisierung des Datums -Bisher nur Min-Max Werte für die Temperatur, auch die anderen Daten per Button anzeigen lassen -Einen Timer, der nach einer bestimmten Zeit das Display ausschaltet -Die Graphanzeige wäre auch cool Anbei ist das bisherige Python-Skript. Das Problem ist im Moment, wie ich eine fortlaufende Anzeige des Datums hinbekomme (while-Schleife), aber auch noch die anderen Buttons funktionieren. Weil mit einer "while True"-Schleife komme ich nicht mehr aus der Anzeige raus. Ebenso brauche ich eine Schleife/Thread, der die Queues befüllt, welche die Daten für die Min-Max-Avg und die Graphenanzeige bereitstellt. Mein Ansatz ist, dass im Hauptprogramm eine Schleife läuft, die jede Sekunde eine Update-Funktion aufruft, die die Daten in die Queues legt. Jedoch besteht auch dabei das Problem, dass ich das Programm nicht mehr mit Enter beenden kann, nur noch mit ctrl+c. Dies ist mein erstes Python-Skript und hoffe, dass evtl. einer schon mal etwas mit Threads und co gemacht hat.weatherstation_tf.py Zitieren
derAngler Geschrieben March 6, 2014 at 07:19 Geschrieben March 6, 2014 at 07:19 Hallo, ich hatte mal das gleiche Problem mit dem Raspi und mir deshalb zusammen mit diversen Leuten aus dem python Forum(Danke) ein kleines Script geschrieben welches mit Events arbeitet. D.h. das Script ist in keiner Schleife "gefangen", sondert wartet auf vorher von mir bestimmte Events und führt dann die ensprechenden Befehle um. Ich werde das Script heute abend mal hier posten, im Moment sitze ich noch auf der Arbeit. Zitieren
adeuring Geschrieben March 7, 2014 at 17:04 Geschrieben March 7, 2014 at 17:04 Anbei ist das bisherige Python-Skript. Das Problem ist im Moment, wie ich eine fortlaufende Anzeige des Datums hinbekomme (while-Schleife), aber auch noch die anderen Buttons funktionieren. Weil mit einer "while True"-Schleife komme ich nicht mehr aus der Anzeige raus. Ebenso brauche ich eine Schleife/Thread, der die Queues befüllt, welche die Daten für die Min-Max-Avg und die Graphenanzeige bereitstellt. Mein Ansatz ist, dass im Hauptprogramm eine Schleife läuft, die jede Sekunde eine Update-Funktion aufruft, die die Daten in die Queues legt. Jedoch besteht auch dabei das Problem, dass ich das Programm nicht mehr mit Enter beenden kann, nur noch mit ctrl+c. Dies ist mein erstes Python-Skript und hoffe, dass evtl. einer schon mal etwas mit Threads und co gemacht hat. Wow, für einen ersten Gehversuch in Python sieht das Script sehr sauber aus! Threads dürften nicht nötig sein. Was der Kern Deines Problems sein dürfte: Die "while True"-Schleife in update_queues(). Wenn Du genau diese Zeile rausnimmst, und auch das sleep() am Ende dieser Methode, sollte das Script schon um einiges besser laufen. Dann kann die "while True"-Scheife im "if __name__ = '__main__'"-Block des Scripts update_queues() einmal pro Sekunde aufrufen, und Du hast aktualisierte Werte in Deinen queues. Dann fehlt nur noch der Aufruf einer Methode, die die aktualiserten Daten auf das Display bringt. Das ginge in update_queues() selbst, kann aber natrlich auch in der Hauptschleife mit einem Aufruf einer geeigneten Methode nach dem call von update_queues() erfolgen. Zitieren
derAngler Geschrieben March 8, 2014 at 08:57 Geschrieben March 8, 2014 at 08:57 Anbei mein "altes" Python Script import asyncore import socket import select import subprocess import os class Client(asyncore.dispatcher_with_send): def __init__(self, socket=None, pollster=None): asyncore.dispatcher_with_send.__init__(self, socket) self.data = '' if pollster: self.pollster = pollster pollster.register(self, select.EPOLLIN) def handle_close(self): if self.pollster: self.pollster.unregister(self) def handle_read(self): receivedData = self.recv(8192) if not receivedData: self.close() return receivedData = self.data + receivedData while '\n' in receivedData: line, receivedData = receivedData.split('\n',1) self.handle_command(line) self.data = receivedData def handle_command(self, line): if line == 'switch_he_1 on': self.send('on') os.system("/root/switch 50 1") elif line == 'switch_he_1 off': self.send('off') os.system("/root/switch 50 0") elif line == 'switch_he_2 on': self.send('on') os.system("/root/switch 51 1") elif line == 'switch_he_2 off': self.send('off') os.system("/root/switch 51 0") elif line == 'xbmc_restart': self.send('restart') os.system("xbmc-send --host=localhost --port=9777 --action=RestartApp") elif line == 'xbmc_off': self.send('off') ausgabe='xbmc-send --host=localhost --port=9777 --action="PlayerControl(Stop)"' os.system(ausgabe) elif line == 'switch_sis_1 on': self.send('on') os.system("sispmctl -o 1") elif line == 'switch_sis_1 off': self.send('off') os.system("sispmctl -f 1") elif line == 'get status_switch_sis_1': output = subprocess.check_output(["sispmctl", "-qg", "1"]); if output.rstrip() == "on": self.send('on') else: self.send('off') elif line == 'switch_sis_2 on': self.send('on') os.system("sispmctl -o 2") elif line == 'switch_sis_2 off': self.send('off') os.system("sispmctl -f 2") elif line == 'get status_switch_sis_2': output = subprocess.check_output(["sispmctl", "-qg", "2"]); if output.rstrip() == "on": self.send('on') else: self.send('off') elif line == 'switch_sis_3 on': self.send('on') os.system("sispmctl -o 3") elif line == 'switch_sis_3 off': self.send('off') os.system("sispmctl -f 3") elif line == 'get status_switch_sis_3': output = subprocess.check_output(["sispmctl", "-qg", "3"]); if output.rstrip() == "on": self.send('on') else: self.send('off') elif line == 'switch_sis_4 on': self.send('on') os.system("sispmctl -o 4") elif line == 'switch_sis_4 off': self.send('off') os.system("sispmctl -f 4") elif line == 'get status_switch_sis_4': output = subprocess.check_output(["sispmctl", "-qg", "4"]); if output.rstrip() == "on": self.send('on') else: self.send('off') else: self.send('unknown command') class Server(asyncore.dispatcher): def __init__(self, listen_to, pollster): asyncore.dispatcher.__init__(self) self.pollster = pollster self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.bind(listen_to) self.listen(5) def handle_accept(self): newSocket, address = self.accept() print "Connected from", address Client(newSocket,self.pollster) def readwrite(obj, flags): try: if flags & select.EPOLLIN: obj.handle_read_event() if flags & select.EPOLLOUT: obj.handle_write_event() if flags & select.EPOLLPRI: obj.handle_expt_event() if flags & (select.EPOLLHUP | select.EPOLLERR | select.POLLNVAL): obj.handle_close() except socket.error, e: if e.args[0] not in asyncore._DISCONNECTED: obj.handle_error() else: obj.handle_close() except asyncore._reraised_exceptions: raise except: obj.handle_error() class EPoll(object): def __init__(self): self.epoll = select.epoll() self.fdmap = {} def register(self, obj, flags): fd = obj.fileno() self.epoll.register(fd, flags) self.fdmap[fd] = obj def unregister(self, obj): fd = obj.fileno() del self.fdmap[fd] self.epoll.unregister(fd) def poll(self): evt = self.epoll.poll() for fd, flags in evt: yield self.fdmap[fd], flags if __name__ == "__main__": pollster = EPoll() pollster.register(Server(("",54321),pollster), select.EPOLLIN) while True: evt = pollster.poll() for obj, flags in evt: readwrite(obj, flags) Ich habe das genutzt um auf Eingaben aus dem Internet zu reagieren. Das Script macht einen Server auf Port 54321 auf und reagiert dann auf verschiedene Befehle die aus dem Netz kommen. Das Ganze läuft ohne Schleife damit es auch wirklich schnell läuft. In einer anderen Version habe ich auch noch einen Schalter und eine LED an den Pi angeschlossen und konnte dann sowohl per Taste als auch per Internet dieLED steuern, das klappte nur über einen Socket Server. Ich denke mit etwas Arbeit kann man das auch für Tinkerforge umbasteln. Als Anregung hier mal mein aktuelles Tinkerforge Skript, allerdings noch ohne Socket Server #!/usr/bin/env python # -*- coding: utf-8 -*- import datetime from datetime import timedelta from tinkerforge.ip_connection import IPConnection from tinkerforge.bricklet_led_strip import LEDStrip from tinkerforge.bricklet_distance_ir import DistanceIR from tinkerforge.bricklet_motion_detector import MotionDetector from tinkerforge.bricklet_ambient_light import AmbientLight from tinkerforge.bricklet_humidity import Humidity from tinkerforge.bricklet_temperature import Temperature class cls_LED_bricklet: led_RED = 0 led_GREEN = 0 led_BLUE = 0 helligkeit = 0.0 led_verlauf = [0]*101 UID = "jGU" def __init__(self): self.bricklet = LEDStrip(self.UID, ipcon) zahl = 12 multiplikator = 0.0 zaehler = 0 while zahl < 100: multiplikator = zahl/46.2 zahl = round(zahl + multiplikator,3) self.led_verlauf[zaehler] = zahl zaehler = zaehler + 1 self.led_verlauf[zaehler-1] = 100.0 def setColor(self,vr,vg,vb,he): self.led_RED = vr self.led_GREEN = vg self.led_BLUE = vb self.helligkeit = he vRED=(self.led_RED/100)*self.helligkeit vGREEN=(self.led_GREEN/100)*self.helligkeit vBLUE=(self.led_BLUE/100)*self.helligkeit var_led_RED = [0]*16 var_led_GREEN = [0]*16 var_led_BLUE = [0]*16 for i in range(16): var_led_RED[i] = int(vRED) var_led_GREEN[i] = int(vGREEN) var_led_BLUE[i] = int(vBLUE) # LED's setzen self.bricklet.set_rgb_values(0, 15, var_led_RED, var_led_BLUE, var_led_GREEN) self.bricklet.set_rgb_values(15, 15, var_led_RED, var_led_BLUE, var_led_GREEN) self.bricklet.set_rgb_values(30, 15, var_led_RED, var_led_BLUE, var_led_GREEN) self.bricklet.set_rgb_values(45, 15, var_led_RED, var_led_BLUE, var_led_GREEN) class cls_Motion_bricklet: motion_detected = False UID = "jX1" def __init__(self): self.bricklet = MotionDetector(self.UID, ipcon) def callbackSet(self): self.bricklet.register_callback(self.bricklet.CALLBACK_MOTION_DETECTED, self.__start) self.bricklet.register_callback(self.bricklet.CALLBACK_DETECTION_CYCLE_ENDED, self.__stop) def __start(self): self.motion_detected = True print(str(get_systemzeit()) + ' - Bewegung erkannt') def __stop(self): self.motion_detected = False print(str(get_systemzeit()) + ' - Bewegung hört auf') class cls_Temperature_bricklet: temperature = 0.0 UID = "dXW" def __init__(self): self.bricklet = Temperature(self.UID, ipcon) def callbackSet(self,timeframe=5000): self.bricklet.set_temperature_callback_period(timeframe) self.bricklet.register_callback(self.bricklet.CALLBACK_TEMPERATURE, self.__write) def read(self): te = self.bricklet.get_temperature() self.temperature = (te/100.0) print(str(get_systemzeit()) + ' - Temperatur: ' + str(te/100.0) + ' °C') def __write(self, te): self.temperature = (te/100.0) print(str(get_systemzeit()) + ' - Temperatur: ' + str(te/100.0) + ' °C') class cls_Humidity_bricklet: humidity = 0.0 UID = "kdt" def __init__(self): self.bricklet = Humidity(self.UID, ipcon) def callbackSet(self,timeframe=5000): self.bricklet.set_humidity_callback_period(timeframe) self.bricklet.register_callback(self.bricklet.CALLBACK_HUMIDITY, self.__write) def read(self): rh = self.bricklet.get_humidity() self.humidity = (rh/10.0) print(str(get_systemzeit()) + ' - Luftfeuchtigkeit: ' + str(rh/10.0) + ' %') def __write(self, rh): self.humidity = (rh/10.0) print(str(get_systemzeit()) + ' - Relative Luftfeuchtigkeit: ' + str(rh/10.0) + ' %') class cls_Ambient_bricklet: ambient = 0.0 UID = "jy1" def __init__(self): self.bricklet = AmbientLight(self.UID, ipcon) def callbackSet(self,timeframe=5000): self.bricklet.set_illuminance_callback_period(timeframe) self.bricklet.register_callback(self.bricklet.CALLBACK_ILLUMINANCE, self.__write) def read(self): il = self.bricklet.get_illuminance() self.ambient = (il/10.0) print(str(get_systemzeit()) + ' - Lichtstärke: ' + str(il/10.0) + ' lx') def __write(self, il): self.ambient = (il/10.0) print(str(get_systemzeit()) + ' - Lichtstärke: ' + str(il/10.0) + ' lx') class cls_IRDistance_bricklet: distance = 0.0 distanceOld1 = 0.0 distanceOld2 = 0.0 distanceOld3 = 0.0 firstRun = True UID = "ktd" def __init__(self,ctbrick,chbrick): self.ctrl_bricklet = ctbrick self.chck_bricklet = chbrick self.bricklet = DistanceIR(self.UID, ipcon) def callbackSet(self,timeframe=200): self.bricklet.set_distance_callback_period(timeframe) self.bricklet.register_callback(self.bricklet.CALLBACK_DISTANCE, self.__changeDistance) def __changeDistance(self,distNew): if self.firstRun: self.fristRun = False self.distanceOld1 = distNew self.distanceOld2 = distNew self.distanceOld3 = distNew mittelwert=round(((self.distanceOld1 + self.distanceOld2 + self.distanceOld3 + distNew)/40),1) y = mittelwert if mittelwert > 60 or mittelwert == 0: mittelwert = 60 elif mittelwert < 10: mittelwert = 10 x = round(99/50*(50 - (mittelwert - 10)),0) led_leistung = self.ctrl_bricklet.led_verlauf[int(x)] if self.chck_bricklet.motion_detected: self.ctrl_bricklet.setColor(0,150,0,led_leistung) print (str(get_systemzeit()) + ' - Entfernungsänderung: ' + str(distNew/10.0) + ' cm => gemittelter ' + str(y) + ' => Wert ' + str(x) + ' => ' + str(led_leistung) + ' %') self.distanceOld1 = self.distanceOld2 self.distanceOld2 = self.distanceOld3 self.distanceOld3 = distNew def get_systemzeit(): now = datetime.datetime.utcnow()+timedelta(hours=1) return(now) if __name__ == "__main__": ipcon = IPConnection() # Bricklets Temperature_bricklet = cls_Temperature_bricklet() Humidity_bricklet = cls_Humidity_bricklet() Ambient_bricklet = cls_Ambient_bricklet() LED_bricklet = cls_LED_bricklet() Motion_bricklet = cls_Motion_bricklet() IRDistance_bricklet = cls_IRDistance_bricklet(LED_bricklet,Motion_bricklet) ipcon.connect("192.168.127.81", 4223) # Callbacks Temperature_bricklet.callbackSet(10000) Humidity_bricklet.callbackSet(10000) Ambient_bricklet.callbackSet(10000) Motion_bricklet.callbackSet() IRDistance_bricklet.callbackSet(50) choice = input("Press key to exit\n") ipcon.disconnect() Zitieren
Korrelationswert Geschrieben April 29, 2014 at 17:21 Autor Geschrieben April 29, 2014 at 17:21 Hey Leute, danke für eure Antworten und sorry für meine späte Antwort. Habe zum Teil einige Punkte aus meinem ersten Post geschafft. - Bei der fortlaufenden Anzeige des Datums habe ich ein bisschen geschummelt. Es hat leider nicht geklappt eine Funktion zu schreiben, die das Datum aktualisiert und auch auf die Tasten reagiert und so eine andere Seite anzeigt. Das "Schummeln" besteht jetzt darin, dass wenn die Callbacks aufgerufen werden, diese das Datum aktualisieren, wenn die Taste für das Datum gedrückt worden ist (weil ein Sensor ändert sich mindestens pro Sekunde). - Habe es geschafft, dasss alle Sensoren sowohl in einer Queue, als auch in einer sqlite3 Datenbank gespeichert werden. - Leider klappt es bisher nicht, dass ein Timer nach einer gewissen Zeit das Display ausschaltet. Dafür ist Button 3 damit belegt. Der Aufbau der Station ist wie folgt: -RaspberryPi -2 Master Bricks -2 Temperatur Bricklets (einer für außen, einer für innen) -1 Ambient Light Bricklet -1 Humidity Bricklet -1 Barometer Bricklet -1 LCD Display Bricklet Da ich den Luftdruck in hPa umrechne stellt sich die Frage, welche Temperatur zur Umrechnung benutzt werden sollte. Die von dem Außensensor oder von dem Innensensor? Funktionsweise der Station: -Button 0: Datumsanzeige -Button 1: Anzeige 1: Wetterdaten von Temperatursensor(innen), Luftfeuchte, Luftdruck, Helligkeit Anzeige 2: Temperatur von innen, aussen, Barometerchip -Button 2: 6 Queues: Temperatur innen, aussen, Barometer, Luftfeuchtigkeit, Luftdruck, Helligkeit -Button 3: Display aus Jetzt noch die Skripte: Ein wirklich ganz einfaches Skript zur Erstellung der sqlite Datenbank:#!/usr/bin/env python # -*- coding: utf-8 -*- import sqlite3 if __name__ == "__main__": connection = sqlite3.connect("/var/local/tinkerweather/tinkerweather.sqlite") cursor = connection.cursor() cursor.execute("""CREATE TABLE temperature_aussen (datum REAL, temperature_aussen REAL)""") cursor.execute("""CREATE TABLE temperature_innen (datum REAL, temperature_innen REAL)""") cursor.execute("""CREATE TABLE illuminance (datum REAL, illuminance REAL)""") cursor.execute("""CREATE TABLE humidity (datum REAL, humidity REAL)""") cursor.execute("""CREATE TABLE air_pressure (datum REAL, air_pressure REAL)""") connection.commit() connection.close() print("Database created.") Zitieren
Korrelationswert Geschrieben April 29, 2014 at 17:22 Autor Geschrieben April 29, 2014 at 17:22 Sorry für Doppelpost, aber 20.000 Zeichen sind zu wenig. 2. Teil Das Steuerungsskript: #!/usr/bin/env python # -*- coding: utf-8 -*- import sqlite3 import socket import sys import time import math import logging as log log.basicConfig(level=log.INFO) import Queue import heapq from threading import Thread, Event, Timer from datetime import datetime from tinkerforge.ip_connection import IPConnection from tinkerforge.ip_connection import Error from tinkerforge.brick_master import Master from tinkerforge.bricklet_lcd_20x4 import LCD20x4 from tinkerforge.bricklet_ambient_light import AmbientLight from tinkerforge.bricklet_humidity import Humidity from tinkerforge.bricklet_barometer import Barometer from tinkerforge.bricklet_temperature import Temperature class weatherstation: HOST = "localhost" PORT = 4223 line_length = 20 button_pressed = None button_counter = [0, 0, 0, 0] ipcon = None lcd = None al = None hum = None baro = None temp_innen = None temp_aussen = None latest_illuminance = None latest_humidity = None latest_air_pressure = None latest_temperature_baro = None latest_temperature_innen = 0 latest_temperature_aussen = 0 illuminance_queue = Queue.Queue(86400) humidity_queue = Queue.Queue(86400) air_pressure_queue = Queue.Queue(86400) temperature_baro_queue = Queue.Queue(86400) temperature_innen_queue = Queue.Queue(86400) temperature_aussen_queue = Queue.Queue(86400) def __init__(self): self.ipcon = IPConnection() while True: try: self.ipcon.connect(weatherstation.HOST, weatherstation.PORT) break except Error as e: log.error('Connection Error: ' + str(e.description)) time.sleep(1) except socket.error as e: log.error('Socket error: ' + str(e)) time.sleep(1) self.ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE, self.cb_enumerate) self.ipcon.register_callback(IPConnection.CALLBACK_CONNECTED, self.cb_connected) while True: try: self.ipcon.enumerate() break except Error as e: log.error('Enumerate Error: ' + str(e.description)) time.sleep(1) # Callbacks of the sensors # "if statements" for ongoing data on the lcd def cb_temperature_innen(self, temperature): self.latest_temperature_innen = temperature/100.0 self.temperature_innen_queue.put(self.latest_temperature_innen) if self.temperature_innen_queue.full(): self.temperature_innen_queue.get() if self.button_counter[1] % 4 == 1: text = 'Innentemp %7.2f \xDFC' % (self.latest_temperature_innen) self.lcd.write_line(0, 0, text) elif self.button_counter[1] % 4 == 2 or self.button_counter[1] % 4 == 3: text = 'Innen: %9.2f \xDFC' % (self.latest_temperature_innen) self.lcd.write_line(2, 0, text) if self.button_pressed == 0: self.update_time() # Database connection = sqlite3.connect("/var/local/tinkerweather/tinkerweather.sqlite") cursor = connection.cursor() now = datetime.now() werte = (now, self.latest_temperature_innen) sql = "INSERT INTO temperature_innen VALUES (?, ?)" cursor.execute(sql, werte) connection.commit() # def cb_temperature_aussen(self, temperature): self.latest_temperature_aussen = temperature/100.0 self.temperature_aussen_queue.put(self.latest_temperature_aussen) if self.temperature_aussen_queue.full(): self.temperature_aussen_queue.get() if self.button_counter[1] % 4 == 2 or self.button_counter[1] % 4 == 3: text = 'Aussen: %8.2f \xDFC' % (self.latest_temperature_aussen) self.lcd.write_line(1, 0, text) if self.button_pressed == 0: self.update_time() # Database connection = sqlite3.connect("/var/local/tinkerweather/tinkerweather.sqlite") cursor = connection.cursor() now = datetime.now() werte = (now, self.latest_temperature_aussen) sql = "INSERT INTO temperature_aussen VALUES (?, ?)" cursor.execute(sql, werte) connection.commit() # def cb_illuminance(self, illuminance): self.latest_illuminance = illuminance/10.0 self.illuminance_queue.put(self.latest_illuminance) if self.illuminance_queue.full(): self.illuminance_queue.get() if self.button_counter[1] % 4 == 1: text = 'Helligkeit %6.2f lx' % (self.latest_illuminance) self.lcd.write_line(3, 0, text) if self.button_pressed == 0: self.update_time() # Database connection = sqlite3.connect("/var/local/tinkerweather/tinkerweather.sqlite") cursor = connection.cursor() now = datetime.now() werte = (now, self.latest_illuminance) sql = "INSERT INTO illuminance VALUES (?, ?)" cursor.execute(sql, werte) connection.commit() # def cb_humidity(self, humidity): self.latest_humidity = humidity/10.0 self.humidity_queue.put(self.latest_humidity) if self.humidity_queue.full(): self.humidity_queue.get() if self.button_counter[1] % 4 == 1: text = 'Luftfeuchte %5.2f %%' % (self.latest_humidity) self.lcd.write_line(1, 0, text) if self.button_pressed == 0: self.update_time() # Database connection = sqlite3.connect("/var/local/tinkerweather/tinkerweather.sqlite") cursor = connection.cursor() now = datetime.now() werte = (now, self.latest_humidity) sql = "INSERT INTO humidity VALUES (?, ?)" cursor.execute(sql, werte) connection.commit() # def cb_air_pressure(self, air_pressure): temperature = self.baro.get_chip_temperature() self.latest_temperature_baro = temperature/100.0 self.latest_air_pressure = (air_pressure/1000.0)*((self.latest_temperature_aussen+273.15)/((self.latest_temperature_aussen+273.15)+(0.0065*520)))**-5.255 self.air_pressure_queue.put(self.latest_air_pressure) if self.air_pressure_queue.full(): self.air_pressure_queue.get() self.temperature_baro_queue.put(self.latest_temperature_baro) if self.temperature_baro_queue.full(): self.temperature_baro_queue.get() if self.button_counter[1] % 4 == 2 or self.button_counter[1] % 4 == 3: text = 'Barometer: %4.2f \xDFC' % (self.latest_temperature_baro) self.lcd.write_line(3, 0, text) if self.button_counter[1] % 4 == 1: text = 'Luftdruck %7.2f hP' % (self.latest_air_pressure) self.lcd.write_line(2, 0, text) if self.button_pressed == 0: self.update_time() # Database connection = sqlite3.connect("/var/local/tinkerweather/tinkerweather.sqlite") cursor = connection.cursor() now = datetime.now() werte = (now, self.latest_air_pressure) sql = "INSERT INTO air_pressure VALUES (?, ?)" cursor.execute(sql, werte) connection.commit() # # Callback functions for buttons def cb_pressed(self, button): if button == self.button_pressed: #log.info('Button Counter: ' + str(self.button_counter)) self.button_counter[button] = self.button_counter[button] + 1 else: self.button_pressed = button self.button_counter = [0, 0, 0, 0] self.update_switch(button) #def cb_released(self, button): #log.info('Released: ' + str(button)) # Turn the lcd on def lcd_on(self): self.lcd.clear_display() self.lcd.backlight_on() # Turn the lcd off def lcd_off(self): self.lcd.clear_display() self.lcd.backlight_off() # Functions for the lcd display # Button 0: def update_time(self): now = datetime.now() text = now.strftime('%d.%m.%Y') self.lcd.write_line(0, ((self.line_length-len(text))/2), text) text = now.strftime('%A') #%A, Woche %W self.lcd.write_line(1, ((self.line_length-len(text))/2), text) text = now.strftime('') self.lcd.write_line(2, ((self.line_length-len(text))/2), text) text = now.strftime('%H:%M:%S') self.lcd.write_line(3, ((self.line_length-len(text))/2), text) # Button 1: def update_standard(self): switch_lcd = self.button_counter[1] % 4 if switch_lcd == 0 or switch_lcd == 1: text = 'Innentemp %7.2f \xDFC' % (self.latest_temperature_innen) self.lcd.write_line(0, 0, text) text = 'Luftfeuchte %5.2f %%' % (self.latest_humidity) self.lcd.write_line(1, 0, text) text = 'Luftdruck %7.2f hP' % (self.latest_air_pressure) self.lcd.write_line(2, 0, text) text = 'Helligkeit %6.2f lx' % (self.latest_illuminance) self.lcd.write_line(3, 0, text) elif switch_lcd == 2 or switch_lcd == 3: text = 'Temperatur' self.lcd.write_line(0, 0, text) text = 'Aussen: %8.2f \xDFC' % (self.latest_temperature_aussen) self.lcd.write_line(1, 0, text) text = 'Innen: %9.2f \xDFC' % (self.latest_temperature_innen) self.lcd.write_line(2, 0, text) text = 'Barometer: %4.2f \xDFC' % (self.latest_temperature_baro) self.lcd.write_line(3, 0, text) # Button 2: def update_min_max_avg(self): switch_lcd = self.button_counter[2] % 6 if switch_lcd == 0: self.update_min_max_avg_write('Aussentemp ' + str(self.time_from_seconds(self.temperature_aussen_queue.qsize())), '\xDFC', self.get_min_max_avg(self.temperature_aussen_queue)) elif switch_lcd == 1: self.update_min_max_avg_write('Innentemp ' + str(self.time_from_seconds(self.temperature_innen_queue.qsize())), '\xDFC', self.get_min_max_avg(self.temperature_innen_queue)) elif switch_lcd == 2: self.update_min_max_avg_write('Barotemperatur ' + str(self.time_from_seconds(self.temperature_baro_queue.qsize())), '\xDFC', self.get_min_max_avg(self.temperature_baro_queue)) elif switch_lcd == 3: self.update_min_max_avg_write('Luftfeuchte ' + str(self.time_from_seconds(self.humidity_queue.qsize())), '%', self.get_min_max_avg(self.humidity_queue)) elif switch_lcd == 4: self.update_min_max_avg_write('Luftdruck ' + str(self.time_from_seconds(self.air_pressure_queue.qsize())), 'hPa', self.get_min_max_avg(self.air_pressure_queue)) elif switch_lcd == 5: self.update_min_max_avg_write('Helligkeit ' + str(self.time_from_seconds(self.illuminance_queue.qsize())), 'lux', self.get_min_max_avg(self.illuminance_queue)) def update_min_max_avg_write(self, title, unit, values): minimum = 'Minimum: ' + str(values[0]) + str(unit) average = 'Mittel.: ' + str(values[1]) + str(unit) maximum = 'Maximum: ' + str(values[2]) + str(unit) self.lcd.write_line(0, 0, title) self.lcd.write_line(1, 0, minimum) self.lcd.write_line(2, 0, average) self.lcd.write_line(3, 0, maximum) def time_from_seconds(self, s): string = None m = s/60 h = m/60 if h > 0: string = '(' + str(h) + 'h)' elif m >= 0: string = '(' + str(m) + 'm)' #log.info('Sekunden: ' + str(s)) #log.info('Minuten: ' + string) return string def get_min_max_avg(self, q): minimum = None average = None maximum = None #log.info('Queue Size: ' + str(q.qsize())) #log.info('Queue full?:' + str(q.full())) heap = list(q.queue) heapq.heapify(heap) heap_length = len(heap) heap_sum = math.fsum(heap) average = round((heap_sum / heap_length), 2) minimum = round(min(heap), 2) #heapq.nsmallest(1, heap) #heap[0] maximum = round(max(heap), 2) #heapq.nlargest(1, heap) return minimum, average, maximum # Check which button is pressed, then update the lcd display def update_switch(self, button): if button == 0: #log.info('Update Time: Button ' + str(button)) self.lcd_on() self.update_time() elif button == 1: #log.info('Update Standard: Button ' + str(button)) self.lcd_on() self.update_standard() elif button == 2: #log.info('Update MinMaxAvg: Button ' + str(button)) self.lcd_on() self.update_min_max_avg() elif button == 3: #log.info('Turn LCD Off: Button ' + str(button)) self.lcd_off() # Initialize the bricklets def cb_enumerate(self, uid, connected_uid, position, hardware_version, firmware_version, device_identifier, enumeration_type): if enumeration_type == IPConnection.ENUMERATION_TYPE_CONNECTED or \ enumeration_type == IPConnection.ENUMERATION_TYPE_AVAILABLE: if device_identifier == LCD20x4.DEVICE_IDENTIFIER: try: self.lcd = LCD20x4(uid, self.ipcon) self.lcd.clear_display() self.lcd.register_callback(self.lcd.CALLBACK_BUTTON_PRESSED, self.cb_pressed) # Button support #self.lcd.register_callback(self.lcd.CALLBACK_BUTTON_RELEASED, self.cb_released) log.info('LCD 20x4 initialized') except Error as e: log.error('LCD 20x4 init failed: ' + str(e.description)) self.lcd = None elif device_identifier == AmbientLight.DEVICE_IDENTIFIER: try: self.al = AmbientLight(uid, self.ipcon) self.al.set_illuminance_callback_period(1000) self.al.register_callback(self.al.CALLBACK_ILLUMINANCE, self.cb_illuminance) log.info('Ambient Light initialized') except Error as e: log.error('Ambient Light init failed: ' + str(e.description)) self.al = None elif device_identifier == Humidity.DEVICE_IDENTIFIER: try: self.hum = Humidity(uid, self.ipcon) self.hum.set_humidity_callback_period(1000) self.hum.register_callback(self.hum.CALLBACK_HUMIDITY, self.cb_humidity) log.info('Humidity initialized') except Error as e: log.error('Humidity init failed: ' + str(e.description)) self.hum = None elif device_identifier == Barometer.DEVICE_IDENTIFIER: try: self.baro = Barometer(uid, self.ipcon) self.baro.set_air_pressure_callback_period(1000) self.baro.register_callback(self.baro.CALLBACK_AIR_PRESSURE, self.cb_air_pressure) log.info('Barometer initialized') except Error as e: log.error('Barometer init failed: ' + str(e.description)) self.baro = None elif device_identifier == Temperature.DEVICE_IDENTIFIER and uid == 'neE': # Innen try: self.temp_innen = Temperature(uid, self.ipcon) self.temp_innen.set_temperature_callback_period(1000) self.temp_innen.register_callback(self.temp_innen.CALLBACK_TEMPERATURE, self.cb_temperature_innen) log.info('Temperatur innen initialized') except Error as e: log.error('Temperatur innen init failed: ' + str(e.description)) self.temp_innen = None #print(self.temp_innen.get_identity()) elif device_identifier == Temperature.DEVICE_IDENTIFIER and uid == 'ns4': # Außen try: self.temp_aussen = Temperature(uid, self.ipcon) self.temp_aussen.set_temperature_callback_period(1000) self.temp_aussen.register_callback(self.temp_aussen.CALLBACK_TEMPERATURE, self.cb_temperature_aussen) log.info('Temperatur aussen initialized') except Error as e: log.error('Temperatur aussen init failed: ' + str(e.description)) self.temp_aussen = None #print(self.temp_aussen.get_identity()) def cb_connected(self, connected_reason): if connected_reason == IPConnection.CONNECT_REASON_AUTO_RECONNECT: log.info('Auto Reconnect') while True: try: self.ipcon.enumerate() break except Error as e: log.error('Enumerate Error: ' + str(e.description)) time.sleep(1) # Main Function if __name__ == "__main__": log.info('Weatherstaion: Start\n') Weatherstation = weatherstation() if sys.version_info < (3, 0): input = raw_input # Compatibility for Python 2.x user_input = input('Press enter to exit.\n') log.info('Main program has exited!') if Weatherstation.lcd != None: Weatherstation.lcd_off() if Weatherstation.ipcon != None: Weatherstation.ipcon.disconnect() log.info('Weatherstation: End') Damit das nun alles auch bei einem Systemstart automatisch gestart wird, habe ich dafür eine systemd-unit-file geschrieben: [unit] Description=Weatherstation Requires=brickd.service After=syslog.target [service] Type=simple StandardInput=tty TTYPath=/dev/tty24 Restart=always RestartSec=30 ExecStart=/usr/bin/python /usr/local/bin/weatherstation.py [install] WantedBy=multi-user.target Damit das Skipt unendlich läuft, habe ich die Eingabe auf tty24 gelegt, damit es nicht unterbrochen wird (gefällt mir eigentlich nicht so, wusste aber nicht, wie es einmal gestartet immer weiter läuft, vielleicht hat jemand eine Idee?). So das war es erstmal. Wenn jemand noch Änderungen oder Verbesserungen hat bitte posten. Zitieren
adeuring Geschrieben May 11, 2014 at 15:33 Geschrieben May 11, 2014 at 15:33 Hey Leute, danke für eure Antworten und sorry für meine späte Antwort. So ist das Leben -- manchmal kommt einem was dazwischen, das einen darn hindert, mit hübscher Hardware zu basteln Diese Antwort kommt reiseverursacht auch recht spät... Habe zum Teil einige Punkte aus meinem ersten Post geschafft. - Bei der fortlaufenden Anzeige des Datums habe ich ein bisschen geschummelt. Es hat leider nicht geklappt eine Funktion zu schreiben, die das Datum aktualisiert und auch auf die Tasten reagiert und so eine andere Seite anzeigt. Das "Schummeln" besteht jetzt darin, dass wenn die Callbacks aufgerufen werden, diese das Datum aktualisieren, wenn die Taste für das Datum gedrückt worden ist (weil ein Sensor ändert sich mindestens pro Sekunde). Ich weiß ja nicht, was genau Du versucht hast, aber ich mutmaße mal, dass Dein Hauptproblem hier liegt: if __name__ == "__main__": log.info('Weatherstaion: Start\n') Weatherstation = weatherstation() if sys.version_info < (3, 0): input = raw_input # Compatibility for Python 2.x user_input = input('Press enter to exit.\n') "Weatherstation = weatherstation()" initialisiert die "gesamte Maschinerie", inclusive Callbacks. Danach kommt der [raw_]input() call, und hier bleibt das Script stehen, bis eben die Enter-Taste gedrückt wird. Damit muss alles in den Callbacks stattfinden, die von der IPConnection-Instanz in einem eigenen Thread ausgeführt werden, sobald die brick[lets] "etwas zu melden" haben. Da Du das Script letztlich als daemon ausführen willst, kannst Du diesen input()-call aus einfach rausnehmen und durch ungefähr folgendes ersetzen [nicht getestet...]: next_call_time = time.time() while True: Weatherstation.update_display() next_call_time += 1 time.sleep(next_call_time - time.time()) update_display() könnte dann die aktuelle Zeit anzeigen, und natürlich auch die ganzen Sensordaten, je nachdem, welcher Button las letztes gedrückt wurde. Das Script kannst Du bei Testaufrufen vom Terminal aus immer noch mit ctrl-C stoppen. Bleibt das Problem, das LCD beim Beenden abzuschalten. Das ginge so: next_call_time = time.time() try: while True: Weatherstation.update_display() next_call_time += 1 time.sleep(next_call_time - time.time()) finally: Weatherstation.lcd_off() - Leider klappt es bisher nicht, dass ein Timer nach einer gewissen Zeit das Display ausschaltet. Dafür ist Button 3 damit belegt. ...das ginge in der oben gezeigten while-Schleife problemlos. Der Aufbau der Station ist wie folgt: -RaspberryPi -2 Master Bricks -2 Temperatur Bricklets (einer für außen, einer für innen) -1 Ambient Light Bricklet -1 Humidity Bricklet -1 Barometer Bricklet -1 LCD Display Bricklet Da ich den Luftdruck in hPa umrechne stellt sich die Frage, welche Temperatur zur Umrechnung benutzt werden sollte. Die von dem Außensensor oder von dem Innensensor? Das würd ich den Temperatursensor nehmen, der am nächsten am Drucksensor liegt, Sorry für Doppelpost, aber 20.000 Zeichen sind zu wenig. 2. Teil Damit das nun alles auch bei einem Systemstart automatisch gestart wird, habe ich dafür eine systemd-unit-file geschrieben: [unit] Description=Weatherstation Requires=brickd.service After=syslog.target [service] Type=simple StandardInput=tty TTYPath=/dev/tty24 Restart=always RestartSec=30 ExecStart=/usr/bin/python /usr/local/bin/weatherstation.py [install] WantedBy=multi-user.target Damit das Skipt unendlich läuft, habe ich die Eingabe auf tty24 gelegt, damit es nicht unterbrochen wird (gefällt mir eigentlich nicht so, wusste aber nicht, wie es einmal gestartet immer weiter läuft, vielleicht hat jemand eine Idee?). Das Problem sind die logging-Aufrufe und der input()-Call, wenn kein Terminal vorhanden ist: Der input()-Call dürfte bei geschlosenem stdin einfach sofort einen Leerstring zurückliefern; die logging-Aufrufe gehen nach, was ist es normalerweise, stdout oder stderr? Wenn diese geschlossen sind, bricht das Script recht bald mit einem Fehler ab. Ein recht schlichter Trick, eine Terminal-Nutzung zu vermeiden, wäre der Aufruf per nohup: nohup /usr/bin/python /usr/local/bin/weatherstation.py (info coreutils 'nohup invocation' liefert weitere Details). Ohne weitere Parameter leitet nohup stdout und stderr in einen Datei namens nohup.out um -- da müsstest Du in dem systemd file noch das passende work directory angeben (sorry, keine Ahnung, wie das geht...); vielleicht funktioniert auch ein Aufruf in der Art nohup /usr/bin/python /usr/local/bin/weatherstation.py >> /home/pi/wstation.log -- aber ob das Sinn hat, hängt davon ab, wie genau systemd diesen Aufruf macht, d.h.: Wird diese Zeile wie bei einer normalen shell ausgewertet, oder hat systemd da seine eigene Logik? Zitieren
Malik Geschrieben May 12, 2014 at 14:48 Geschrieben May 12, 2014 at 14:48 Hallo Korrelationswert, nach welcher Formel rechnest Du den Luftdruck um? Zitieren
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.