temperature-logger-interface/main.py

170 lines
5.5 KiB
Python
Raw Normal View History

import kivy
from kivy.app import App
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
from kivy.logger import Logger
2014-12-11 03:38:40 +00:00
from kivy.properties import ListProperty, NumericProperty, ObjectProperty, StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
2014-12-11 03:38:40 +00:00
from kivy.uix.image import Image
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
import Queue
2014-12-11 03:38:40 +00:00
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')
2014-12-11 03:38:40 +00:00
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:
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'])
except Queue.Empty:
pass
2014-12-11 03:38:40 +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
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:
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()
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))
class MyLabel(Label):
def on_lastTemperature(self, instance, value):
self.text = 'Current temperature: ' + str(value)
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
if __name__ == '__main__':
dataThread = threading.Thread(None, temp_log.threaded_reader, None, ['/dev/ttyACM0', dataThreadDataQueue, dataThreadCommandQueue])
MainApp().run()