Skip to content

Instantly share code, notes, and snippets.

@errkk
Created July 29, 2014 12:33
Show Gist options
  • Save errkk/e51da8468809ac7349b6 to your computer and use it in GitHub Desktop.
Save errkk/e51da8468809ac7349b6 to your computer and use it in GitHub Desktop.
Data Display for solar panel data
from django import forms
from .models import Temperature, PumpEvent
class TemperatureForm(forms.ModelForm):
class Meta:
model = Temperature
exclude = ('timestamp', )
class PumpEventForm(forms.ModelForm):
class Meta:
model = PumpEvent
fields = ('is_on', )
from django.db import models
FLOW_RATE = 25 # Measured for our system
class BaseReading(models.Model):
class Meta:
abstract = True
ordering = ['timestamp', ]
get_latest_by = 'timestamp'
timestamp = models.DateTimeField(auto_now_add=True)
class Temperature(BaseReading):
""" Model to reperesent a temperature reading
"""
t1 = models.FloatField('Input to pool', blank=True, null=True)
t2 = models.FloatField('Output from panels', blank=True, null=True)
t3 = models.FloatField('Output from pool', blank=True, null=True)
t4 = models.FloatField('Air Temp', blank=True, null=True)
def __unicode__(self):
return '{0}, {1}, {2}, {3} @ {4}'.format(
self.t1,
self.t2,
self.t3,
self.t4,
self.timestamp,
)
def get_uplift(self):
if self.t1 and self.t2:
return self.t2 - self.t1
return 0
def get_power(self):
""" Calculate power from temperature uplift to known flow rate
"""
uplift = self.get_uplift()
grams = 1000.0 * FLOW_RATE / 60
calories = uplift * grams
return int(calories * 4.2)
class PumpEvent(BaseReading):
""" Logs the switching of the pump
"""
is_on = models.BooleanField(default=False)
def __unicode__(self):
return 'On' if self.is_on else 'Off'
import redis
import json
from datetime import timedelta, datetime
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.core.urlresolvers import reverse
from django.views.generic.base import View
from django.views.generic import (FormView, CreateView, WeekArchiveView,
RedirectView, TemplateView)
from django.views.generic.dates import DateMixin, WeekMixin
from .forms import TemperatureForm, PumpEventForm
from .models import Temperature, PumpEvent
conn = redis.StrictRedis()
from django.views.decorators.csrf import csrf_exempt
class TemperatureView(CreateView):
form_class = TemperatureForm
template_name = 'bootstrap/form.html'
def get_success_url(self):
return reverse('panel:temperature_form')
class PumpEventView(CreateView):
form_class = PumpEventForm
template_name = 'bootstrap/form.html'
def get_success_url(self):
return reverse('panel:pumpevent_form')
class ChartDataMixin:
""" Formatter for temperature data to make it go into the D3 chart
"""
def get_chart_data(self, **kwargs):
queryset = kwargs.pop('object_list')
t1, t2, t3, t4 = [], [], [], []
power = []
for i in queryset:
timestamp = i.timestamp.strftime("%s")
t1.append({'x': timestamp, 'y': i.t1})
t2.append({'x': timestamp, 'y': i.t2})
t3.append({'x': timestamp, 'y': i.t3})
t4.append({'x': timestamp, 'y': i.t4})
data = [
{'key': 'Into Pool', 'values' : t1},
{'key': 'From Panel', 'values' : t2},
{'key': 'From Pool', 'values' : t3},
{'key': 'Air', 'values' : t4},
]
context = {
'data': json.dumps(data),
'object_list': queryset,
}
return context
class DataLp(TemplateView, ChartDataMixin, DateMixin, WeekMixin):
""" Landing page for the data section.
Has current data from sensors and external services, also the chart
for the current week
"""
template_name = 'panel/index.html'
model = Temperature
date_field = 'timestamp'
def get_today_queryset(self):
""" Get temperature datapoints for the current day
Different to how WeekArchiveView does it, as that filters qs after
"""
now = datetime.now()
since = self._make_date_lookup_arg(now)
until = self._make_date_lookup_arg(self._get_next_week(now))
qs = Temperature.objects.filter(timestamp__range=[since, until])
return qs
def get_power(self):
t = Temperature.objects.latest()
return t.get_power()
def get_context_data(self, **kwargs):
power = 0
try:
pump = PumpEvent.objects.latest()
except PumpEvent.DoesNotExist:
pump = None
else:
if pump.is_on:
power = self.get_power()
weather = json.loads(conn.get('FORECAST.IO'))
now = datetime.now()
last_week = now - timedelta(weeks=1)
object_list = self.get_today_queryset()
context = self.get_chart_data(object_list=object_list)
context['previous_week'] = last_week
context['pump'] = pump
context['power'] = power / 1000.0
if weather:
context['weather_updated'] = datetime.fromtimestamp(
int(weather['time']))
context['summary'] = weather['summary']
context.update(kwargs)
return super(DataLp, self).get_context_data(**context)
data = DataLp.as_view()
class TemperatureArchive(WeekArchiveView, ChartDataMixin):
""" Display temperature data in a weekly chart, using CBV magic to filter
by date field
"""
date_field = 'timestamp'
make_object_list = True
allow_future = False
queryset = Temperature.objects.all()
allow_empty = False
def get_context_data(self, **kwargs):
context = self.get_chart_data(**kwargs)
context.update(kwargs)
return super(TemperatureArchive, self).get_context_data(**context)
temperature_archive_view = TemperatureArchive.as_view()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment