Moinsens!
Ich bastel mir gerade ein Klassen-Modul zum Auslesen eines Sensors. Für den Anfang hab ich mir mal den BH1750 (Helligkeit) genommen. Aber dieses Klassen-Modul soll quasi ein Template werden, um dann für andere Sensoren (BME280, DHT22, DS18B20, ... ) kopiert / angepaßt zu werden.
Funktionieren tut's soweit. Aber da ich in Python noch nicht so firm bin, frage ich mal in die Runde, ob der u.a. Source-Aufbau so richtig und sinnvoll ist.
Das Haupt-Programm, in dem der Sensor geladen und ausgewertet wird:
classtest.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ------------------------------------------------------------------------------
import time
import bh1750_class as Sensor
# ------------------------------------------------------------------------------
def main():
# print "Main start"
SensorLumen = Sensor.BH1750()
interval = 1.0
try:
SensorLumen.start()
while ( True ):
# print "Main tick"
v = SensorLumen.getLumen()
if ( v <> None ):
SensorLumen.setLumen( None )
print v
time.sleep( interval )
# print "Main exit (normal)"
except:
# print "Main exit (error)"
pass
# ------------------------------------------------------------------------------
if __name__ == "__main__":
main()
Alles anzeigen
Und dann das Klassen-Modul zum Auslesen des Sensors:
bh1750_class.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ------------------------------------------------------------------------------
import time
import smbus
import threading
# ------------------------------------------------------------------------------
class BH1750():
'__doc__'
# -----------------
# public properties
# -----------------
__Lumen = None
def getLumen( self ):
return self.__Lumen
def setLumen( self, v ):
if ( v <> self.__Lumen ):
self.__Lumen = v
__Time = None
def getTime( self ):
return self.__Time
def setTime( self, v ):
if ( v <> self.__Time ):
self.__Time = v
__Device = 0x23
def getDevice( self ):
return self.__Device
def setDevice( self, v ):
if ( v <> self.__Device ):
self.__Device = v
__Mode = 0x20
def getMode( self ):
return self.__Mode
def setMode( self, v ):
if ( v <> self.__Mode ):
self.__Mode = v
__Bus = 1
def getBus( self ):
return self.__Bus
def setBus( self, v ):
if ( v <> self.__Bus ):
self.__Bus = v
__Interval = 5.0
def getInterval( self ):
return self.__Interval
def setInterval( self, v ):
if ( v <> self.__Interval ):
self.__Interval = v
# ------------------
# private properties
# ------------------
__LoopActive = None
def __getLoopActive( self ):
return self.__LoopActive
def __setLoopActive( self, v ):
if ( v <> self.__LoopActive ):
self.__LoopActive = v
__LoopThread = None
# ------------------------------------------------------------------------------
# --------------
# public methods
# --------------
def start( self ):
self.__LoopThread_Start()
def stop( self ):
self.__LoopThread_Stop()
# ---------------
# private methods
# ---------------
def __getLocalTime( self ):
# print "BH1750.__getLocalTime()()"
t = time.time()
if ( not time.localtime().tm_isdst ):
t = t - time.timezone
else:
t = t - time.altzone
dt = time.gmtime( t )
return dt
# ------------------------------------------------------------------------------
def __LoopThread_Loop( self ):
# print "BH1750.LoopThread_Loop()"
while ( self.__getLoopActive() ):
# print "BH1750.LoopThread_Loop() - tick"
bus = smbus.SMBus( self.getBus() )
data = None
try:
data = bus.read_i2c_block_data( self.getDevice(), self.getMode() )
except:
# i/o-error 5 - call i2cdetect
pass
if ( data <> None ):
v = (( data[1] + ( 256 * data[0] )) / 1.2 )
self.setLumen( v )
self.setTime( self.__getLocalTime() )
time.sleep( self.getInterval() )
def __LoopThread_Start( self ):
# print "BH1750.LoopThread_Start()"
if ( not self.__getLoopActive() ):
self.__setLoopActive( True )
self.__LoopThread = threading.Thread( target = self.__LoopThread_Loop )
self.__LoopThread.daemon = True
self.__LoopThread.start()
def __LoopThread_Stop( self ):
# print "BH1750.LoopThread_Stop()"
if ( self.__getLoopActive() ):
self.__setLoopActive( False )
self.__LoopThread.join( 0 )
# ------------------------------------------------------------------------------
# -----------
# constructor
# -----------
def __init__( self, Device = 0x23, Mode = 0x20, Bus = 1, Interval = 5.0 ):
# print "BH1750.__init__()"
self.setLumen( None )
self.setTime( None )
self.setDevice( Device )
self.setMode( Mode )
self.setBus( Bus )
self.setInterval( Interval )
# self.__LoopThread_Start()
Alles anzeigen
Ich versuche eigentlich grundsätzlich, globale Variablen nicht direkt anzusprechen, sondern immer über get/set-Routinen zu gehen. Sehe ich das richtig, daß Python aber kein echtes "private" kann, sondern das nur mit den '__' etwas verschleiert? Ich würd's eigentlich nicht so witzig finden, wenn jemand im Hauptprogramm direkt z.B. die __LoopThread Variable verändern kann. Ok, wäre sein Problem, aber ein echtes "private" wäre schon schön...
Außerdem würde ich gerne einige Getter "public" und die zugehörigen Setter "private" haben. Das Objekt selbst soll ja durchaus in der Lage sein, die Werte über den Setter zu aktualisieren, aber das Hauptprogramm soll die Werte eigentlich nur noch über die Getter auslesen können.
Ist Threading hier ok? Ich könnte das ja auch umstellen und mit self.after(... arbeiten. Das würde das Starten/Stoppen des Sensors auch vielleicht etwas einfacherer / sicherer machen, als irgendwo einen wilden Thread im Zaum zu halten.
Gruß, Michael