temperature-logger-interface/main.py

170 lines
5.5 KiB
Python

import kivy
from kivy.app import App
from kivy.clock import Clock
import kivy.core.image
from kivy.core.image.img_pygame import ImageLoaderPygame
import kivy.graphics.texture
from kivy.logger import Logger
from kivy.properties import ListProperty, NumericProperty, ObjectProperty, StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
from kivy.uix.label import Label
import kivy.lang
import numpy
import matplotlib
matplotlib.use('Agg')
import matplotlib.image
import matplotlib.pyplot
import Queue
import StringIO
import temp_log
import threading
dataThread = None
dataThreadDataQueue = Queue.Queue()
dataThreadCommandQueue = Queue.Queue()
class MainApp(App):
def build(self):
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')
lastTemperature = NumericProperty(-1000.)
lastTime = NumericProperty(-1.)
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:
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'])
except Queue.Empty:
pass
def on_lastTemperature(self, instance, value):
Logger.debug('lastTemperature has changed to: ' + str(value))
children = self.children[:]
while children:
child = children.pop()
children.extend(child.children)
if child is self:
continue
try:
child.on_lastTemperature(instance, value)
#Logger.debug('Called on_lastTemperature for child: ' + str(child))
except AttributeError:
pass
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()
children.extend(child.children)
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))
class MyLabel(Label):
def on_lastTemperature(self, instance, value):
self.text = 'Current temperature: ' + str(value)
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
if __name__ == '__main__':
dataThread = threading.Thread(None, temp_log.threaded_reader, None, ['/dev/ttyACM0', dataThreadDataQueue, dataThreadCommandQueue])
MainApp().run()