def __init__( self, basedir ): self.builder = gtk.Builder() self.builder.add_from_file( builder_file ) self.config = TermoConfig( basedir + "config.db" ) self.mode = self.config.get( "mode", default_mode ) self.builder.get_object( "radio%s" % self.mode ).set_active( True ) self.scales = [] for i in range( 24 ): scale = self.builder.get_object( "vscale%s" % i ) scale.set_value( self.config.get( "temp_%s" % i, 0 ) ) self.scales.append( scale ) self.builder.connect_signals( self ) # collegati alla caldaia self.switch = TermoSwitch() self.update_switch_ui() # crea il thread del termometro # specifica la callback self.feed = TermoFeed( self.got_point ) self.feed.start() # apre/crea lo storico self.storico = TermoStory( basedir + "storico.db" ) # crea il grafico self.figure = Figure() self.canvas = FigureCanvas( self.figure ) # crea asse temperatura self.temp_axes = self.figure.add_subplot( 111 ) self.temp_axes.xaxis.set_major_locator( matplotlib.dates.HourLocator() ) self.temp_axes.xaxis.set_minor_locator( matplotlib.dates.MinuteLocator() ) self.temp_axes.xaxis.set_major_formatter( matplotlib.dates.DateFormatter( '%H' ) ) self.temp_axes.set_ylabel( u"Temperatura", color="m" ) self.temp_axes.yaxis.set_major_formatter( temp_formatter ) self.temp_axes.grid( True ) # crea asse umidita self.umid_axes = self.temp_axes.twinx() self.umid_axes.xaxis.set_major_locator( matplotlib.dates.HourLocator() ) self.umid_axes.xaxis.set_minor_locator( matplotlib.dates.MinuteLocator() ) self.umid_axes.xaxis.set_major_formatter( matplotlib.dates.DateFormatter( '%H' ) ) self.umid_axes.set_ylabel( u"Umidità", color= "c" ) self.umid_axes.yaxis.set_major_formatter( umid_formatter ) self.umid_axes.grid( True ) # crea linee self.temp_line = self.temp_axes.plot( [], [], "m" )[0] self.umid_line = self.umid_axes.plot( [], [], "c", alpha=0.5 )[0] self.switch_collection = None self.update_plot() hbox2 = self.builder.get_object( "hbox2" ) hbox2.add( self.canvas ) # partiamo self.builder.get_object( "window1" ).show_all()
class TermoGUI( object ): def __init__( self, basedir ): self.builder = gtk.Builder() self.builder.add_from_file( builder_file ) self.config = TermoConfig( basedir + "config.db" ) self.mode = self.config.get( "mode", default_mode ) self.builder.get_object( "radio%s" % self.mode ).set_active( True ) self.scales = [] for i in range( 24 ): scale = self.builder.get_object( "vscale%s" % i ) scale.set_value( self.config.get( "temp_%s" % i, 0 ) ) self.scales.append( scale ) self.builder.connect_signals( self ) # collegati alla caldaia self.switch = TermoSwitch() self.update_switch_ui() # crea il thread del termometro # specifica la callback self.feed = TermoFeed( self.got_point ) self.feed.start() # apre/crea lo storico self.storico = TermoStory( basedir + "storico.db" ) # crea il grafico self.figure = Figure() self.canvas = FigureCanvas( self.figure ) # crea asse temperatura self.temp_axes = self.figure.add_subplot( 111 ) self.temp_axes.xaxis.set_major_locator( matplotlib.dates.HourLocator() ) self.temp_axes.xaxis.set_minor_locator( matplotlib.dates.MinuteLocator() ) self.temp_axes.xaxis.set_major_formatter( matplotlib.dates.DateFormatter( '%H' ) ) self.temp_axes.set_ylabel( u"Temperatura", color="m" ) self.temp_axes.yaxis.set_major_formatter( temp_formatter ) self.temp_axes.grid( True ) # crea asse umidita self.umid_axes = self.temp_axes.twinx() self.umid_axes.xaxis.set_major_locator( matplotlib.dates.HourLocator() ) self.umid_axes.xaxis.set_minor_locator( matplotlib.dates.MinuteLocator() ) self.umid_axes.xaxis.set_major_formatter( matplotlib.dates.DateFormatter( '%H' ) ) self.umid_axes.set_ylabel( u"Umidità", color= "c" ) self.umid_axes.yaxis.set_major_formatter( umid_formatter ) self.umid_axes.grid( True ) # crea linee self.temp_line = self.temp_axes.plot( [], [], "m" )[0] self.umid_line = self.umid_axes.plot( [], [], "c", alpha=0.5 )[0] self.switch_collection = None self.update_plot() hbox2 = self.builder.get_object( "hbox2" ) hbox2.add( self.canvas ) # partiamo self.builder.get_object( "window1" ).show_all() def on_mode_toggled( self, radio ): """ è stata cambiata la modalità.. """ for mode in modes: radio = self.builder.get_object( "radio%s" % mode ) if radio.get_active(): self.mode = mode self.config.set( "mode", mode ) break # impostato su acceso/spento -> spegniamo/accendiamo il riscaldamento if mode == "acceso": self.switch.set_state( True ) elif mode == "spento": self.switch.set_state( False ) def on_vscale_value_changed( self, scale ): """ uno degli slider è stato spostato.. """ for idx, obj in enumerate( self.scales ): if obj == scale: self.config.set( "temp_%s" % idx, scale.get_value() ) break else: raise Exception( "VScale non trovato" ) def got_point( self, temp, umid ): """ abbiamo ricevuto una misurazione dal termometro.. """ # popola lo storico self.storico.add( temp, umid, self.switch.get_state() ) # pilota la caldaia.. if self.mode == "programmato": hh = datetime.datetime.now().hour temp_prog = self.config.get( "temp_%s" % hh, 0 ) # versione grezza # temperatura attuale +- tolleranza -> attacca e stacca # utilizziamo solo la sicurezza interna dello switch if temp < temp_prog - tolleranza: self.switch.set_state( True ) elif temp > temp_prog + tolleranza: self.switch.set_state( False ) elif self.mode == "acceso": self.switch.set_state( True ) elif self.mode == "spento": self.switch.set_state( False ) # aggiorna la UI self.update_temp_umid( temp, umid ) self.update_switch_ui() def update_switch_ui( self ): """ leggi lo stato dello switch e aggiorna la UI """ label = self.builder.get_object( "label_switch" ) state = self.switch.get_state() if state == None: label.set_text( "N/A" ) elif state: label.set_text( "Il riscaldamento è ACCESO" ) else: label.set_text( "Il riscaldamento è SPENTO" ) def update_plot( self ): """ leggi lo storico e aggiorna i grafici """ dmax = datetime.datetime.now() + graph_margin dmin = dmax - ( graph_width + graph_margin ) dates, temp, umid, switch = self.storico.search( dmin, dmax ) mpldates = [ matplotlib.dates.date2num( date ) for date in dates ] mpldmin = matplotlib.dates.date2num( dmin ) mpldmax = matplotlib.dates.date2num( dmax ) if temp: # grafico delle temperature mintemp = min(temp)*0.999 maxtemp = max(temp)*1.001 self.temp_line.set_data( mpldates, temp ) self.temp_axes.set_ylim( mintemp, maxtemp ) self.temp_axes.set_xlim( mpldmin, mpldmax ) # span della caldaia if self.switch_collection: self.switch_collection.remove() self.switch_collection = matplotlib.collections.BrokenBarHCollection.span_where( mpldates, ymin=mintemp, ymax=maxtemp, where=switch, facecolor='red', alpha=0.1, linewidths=0 ) self.temp_axes.add_collection( self.switch_collection ) if umid: # grafico delle umidita (asse x condivisa) minumid = min(umid)*0.999 maxumid = max(umid)*1.001 self.umid_line.set_data( mpldates, umid ) self.umid_axes.set_ylim( minumid, maxumid ) self.umid_axes.set_xlim( mpldmin, mpldmax ) self.canvas.draw() def update_temp_umid( self, temp, umid ): """ aggiorna le label della temperatura e umidità attuali """ gtk.gdk.threads_enter() self.builder.get_object( "label_temp" ).set_text( fmt_temp( temp ) ) self.builder.get_object( "label_umid" ).set_text( fmt_umid( umid ) ) self.update_plot() gtk.gdk.threads_leave() def on_window1_destroy( self, widget, data=None ): """ uscita dal programma """ self.storico.save() self.config.save() self.feed.stop() gtk.main_quit()