2014-12-09 03:12:21 +00:00
import kivy
from kivy . app import App
2014-12-10 22:22:52 +00:00
from kivy . clock import Clock
2014-12-11 03:38:40 +00:00
import kivy . core . image
from kivy . core . image . img_pygame import ImageLoaderPygame
import kivy . graphics . texture
2014-12-10 22:22:52 +00:00
from kivy . logger import Logger
2014-12-11 03:38:40 +00:00
from kivy . properties import ListProperty , NumericProperty , ObjectProperty , StringProperty
2014-12-09 03:12:21 +00:00
from kivy . uix . boxlayout import BoxLayout
2014-12-10 22:22:52 +00:00
from kivy . uix . floatlayout import FloatLayout
2014-12-11 03:38:40 +00:00
from kivy . uix . image import Image
2014-12-10 22:22:52 +00:00
from kivy . uix . label import Label
import kivy . lang
2014-12-11 03:38:40 +00:00
import numpy
import matplotlib
matplotlib . use ( ' Agg ' )
import matplotlib . image
import matplotlib . pyplot
2014-12-10 22:22:52 +00:00
import Queue
2014-12-11 03:38:40 +00:00
import StringIO
2014-12-10 22:22:52 +00:00
import temp_log
import threading
2014-12-09 03:12:21 +00:00
2014-12-10 22:22:52 +00:00
dataThread = None
dataThreadDataQueue = Queue . Queue ( )
dataThreadCommandQueue = Queue . Queue ( )
class MainApp ( App ) :
2014-12-09 03:12:21 +00:00
def build ( self ) :
2014-12-10 22:22:52 +00:00
mainWindow = MainWindow ( )
Clock . schedule_interval ( mainWindow . update_last_temperature , 0.25 )
return mainWindow
def on_stop ( self ) :
global dataThreadCommandQueue
dataThreadCommandQueue . put_nowait ( ' stop ' )
def on_start ( self ) :
global dataThread
dataThread . start ( )
class MainWindow ( FloatLayout ) :
""" Main Window class """
dataSource = StringProperty ( ' /dev/ttyACM0 ' )
2014-12-11 03:38:40 +00:00
lastTemperature = NumericProperty ( - 1000. )
lastTime = NumericProperty ( - 1. )
2014-12-10 22:22:52 +00:00
def update_last_temperature ( self , dt ) :
global dataThreadDataQueue
# This breaks if there are more updates in the queue than the frequency of update_last_temperature - it pulls old data out of the queue, and not the most recent.
try :
data = dataThreadDataQueue . get_nowait ( )
if data is not None :
2014-12-11 03:38:40 +00:00
Logger . debug ( ' Data: ' + str ( data ) )
if ' data ' in data and ' temperature ' in data [ ' data ' ] :
self . lastTemperature = float ( data [ ' data ' ] [ ' temperature ' ] )
if ' time ' in data :
self . lastTime = float ( data [ ' time ' ] )
2014-12-10 22:22:52 +00:00
except Queue . Empty :
pass
2014-12-11 03:38:40 +00:00
2014-12-10 22:22:52 +00:00
def on_lastTemperature ( self , instance , value ) :
Logger . debug ( ' lastTemperature has changed to: ' + str ( value ) )
children = self . children [ : ]
while children :
child = children . pop ( )
2014-12-11 03:38:40 +00:00
children . extend ( child . children )
if child is self :
continue
2014-12-10 22:22:52 +00:00
try :
child . on_lastTemperature ( instance , value )
2014-12-11 03:38:40 +00:00
#Logger.debug('Called on_lastTemperature for child: ' + str(child))
except AttributeError :
2014-12-10 22:22:52 +00:00
pass
2014-12-11 03:38:40 +00:00
except Exception , e :
Logger . exception ( str ( e ) )
def on_lastTime ( self , instance , value ) :
Logger . debug ( ' lastTime has changed to: ' + str ( value ) )
children = self . children [ : ]
while children :
child = children . pop ( )
2014-12-10 22:22:52 +00:00
children . extend ( child . children )
2014-12-11 03:38:40 +00:00
if child is self :
continue
#Logger.debug(str(child))
try :
child . on_lastTime ( instance , value )
#Logger.debug('Called on_lastTime for child: ' + str(child))
except AttributeError , e :
pass
except Exception , e :
Logger . exception ( str ( e ) )
2014-12-10 22:22:52 +00:00
class MyLabel ( Label ) :
2014-12-09 03:12:21 +00:00
2014-12-10 22:22:52 +00:00
def on_lastTemperature ( self , instance , value ) :
self . text = ' Current temperature: ' + str ( value )
2014-12-09 03:12:21 +00:00
2014-12-11 03:38:40 +00:00
class PlotWidget ( Image ) :
def __init__ ( self , * * kwargs ) :
super ( Image , self ) . __init__ ( * * kwargs )
self . data = numpy . array ( [ ] , dtype = float ) ;
self . lastTime = 0
self . lastTemperature = 0
self . figure = matplotlib . pyplot . figure ( )
self . plot_axes = self . figure . add_subplot ( 1 , 1 , 1 )
self . plot_axes . hold ( False )
self . plot_axes . set_ylabel ( ' Temperature (deg C) ' )
self . plot_axes . set_xlabel ( ' Time ' )
self . plot_axes . set_title ( ' Recorded Temperature ' )
def update ( self ) :
if not self . data . any ( ) :
return
#Logger.debug('self.data: ' + str(self.data))
#Logger.debug('self.data shape: ' + str(self.data.shape))
data = numpy . copy ( self . data )
data = data . transpose ( )
#Logger.debug('transpoed data: ' + str(data))
#Logger.debug('transposed data shape: ' + str(data.shape))
t , temperature = numpy . split ( data , 2 , axis = 0 )
#Logger.debug('time: ' + str(t[0]))
#Logger.debug('temperature: ' + str(temperature[0]))
self . plot_axes . plot ( t [ 0 ] , temperature [ 0 ] )
image_data = StringIO . StringIO ( )
self . figure . savefig ( image_data , format = ' png ' )
image_data . seek ( 0 )
self . texture = ImageLoaderPygame ( image_data , nocache = True ) . texture
def on_lastTemperature ( self , instance , value ) :
self . lastTemperature = value
self . update_data ( )
def on_lastTime ( self , instance , value ) :
self . lastTime = value
self . update_data ( )
def update_data ( self ) :
if self . lastTime == 0 or self . lastTemperature == 0 :
return
newpoint = numpy . array ( [ ( self . lastTime , self . lastTemperature ) ] , dtype = float , ndmin = 2 )
if not self . data . any ( ) :
self . data = newpoint
return
#Logger.debug('self.data: ' + str(self.data))
#Logger.debug('newpoint: ' + str(newpoint))
self . data = numpy . vstack ( ( self . data , newpoint ) )
self . update ( )
#self.data = numpy.concatenate((self.data, newpoint), axis = 0)
#self.data = numpy.copy(self.data) # This will cause ObjectProperty to fire a change event
2014-12-09 03:12:21 +00:00
if __name__ == ' __main__ ' :
2014-12-10 22:22:52 +00:00
dataThread = threading . Thread ( None , temp_log . threaded_reader , None , [ ' /dev/ttyACM0 ' , dataThreadDataQueue , dataThreadCommandQueue ] )
MainApp ( ) . run ( )