diff --git a/tailbone/templates/tempmon/probes/graph.mako b/tailbone/templates/tempmon/probes/graph.mako
new file mode 100644
index 00000000..128fe5ce
--- /dev/null
+++ b/tailbone/templates/tempmon/probes/graph.mako
@@ -0,0 +1,66 @@
+## -*- coding: utf-8; -*-
+<%inherit file="/base.mako" />
+
+<%def name="title()">Temperature Graph%def>
+
+<%def name="extra_javascript()">
+ ${parent.extra_javascript()}
+
+
+%def>
+
+
+
+
diff --git a/tailbone/templates/tempmon/probes/view.mako b/tailbone/templates/tempmon/probes/view.mako
index 8acdbfbe..8bf3fd2e 100644
--- a/tailbone/templates/tempmon/probes/view.mako
+++ b/tailbone/templates/tempmon/probes/view.mako
@@ -41,6 +41,11 @@
## rendering methods
##############################
+<%def name="context_menu_items()">
+ ${parent.context_menu_items()}
+ ${h.link_to("View Readings as Graph", action_url('graph', instance))}
+%def>
+
<%def name="render_main_fields(form)">
${form.render_field_readonly('client')}
${form.render_field_readonly('config_key')}
diff --git a/tailbone/views/tempmon/probes.py b/tailbone/views/tempmon/probes.py
index 7256a0a3..dbb47d78 100644
--- a/tailbone/views/tempmon/probes.py
+++ b/tailbone/views/tempmon/probes.py
@@ -26,8 +26,11 @@ Views for tempmon probes
from __future__ import unicode_literals, absolute_import
+import datetime
+
import six
+from rattail.time import make_utc, localtime
from rattail_tempmon.db import model as tempmon
import colander
@@ -220,6 +223,46 @@ class TempmonProbeView(MasterView):
g.set_sort_defaults('taken', 'desc')
+ def graph(self):
+ probe = self.get_instance()
+
+ # figure out which readings we need to graph
+ # TODO: make this dynamic somehow
+ cutoff = make_utc() - datetime.timedelta(seconds=3600) # last hour
+ readings = self.Session.query(tempmon.Reading)\
+ .filter(tempmon.Reading.probe == probe)\
+ .filter(tempmon.Reading.taken >= cutoff)\
+ .order_by(tempmon.Reading.taken)\
+ .all()
+
+ # convert readings to data for scatter plot
+ data = [{
+ 'x': localtime(self.rattail_config, reading.taken, from_utc=True).isoformat(),
+ 'y': float(reading.degrees_f),
+ } for reading in readings]
+
+ context = {
+ 'probe': probe,
+ 'parent_title': six.text_type(probe),
+ 'parent_url': self.get_action_url('view', probe),
+ 'readings_data': data,
+ }
+ return self.render_to_response('graph', context)
+
+ @classmethod
+ def defaults(cls, config):
+ route_prefix = cls.get_route_prefix()
+ url_prefix = cls.get_url_prefix()
+ model_key = cls.get_model_key()
+ permission_prefix = cls.get_permission_prefix()
+ model_title_plural = cls.get_model_title_plural()
+
+ config.add_route('{}.graph'.format(route_prefix), '{}/{{{}}}/graph'.format(url_prefix, model_key))
+ config.add_view(cls, attr='graph', route_name='{}.graph'.format(route_prefix),
+ permission='{}.view'.format(permission_prefix))
+
+ cls._defaults(config)
+
def includeme(config):
TempmonProbeView.defaults(config)