Skip to content

Commit

Permalink
#3 | Added hourly electricity usage.
Browse files Browse the repository at this point in the history
  • Loading branch information
dennissiemensma committed Feb 5, 2016
1 parent 7b86d23 commit 08c046e
Show file tree
Hide file tree
Showing 13 changed files with 200 additions and 156 deletions.
15 changes: 15 additions & 0 deletions dsmr_backend/apps.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
import warnings

from django.apps import AppConfig
from django.db import connection
from django.utils.translation import ugettext_lazy as _


class AppConfig(AppConfig):
""" The backend app solely exists for triggering a backend signal. """
name = 'dsmr_backend'
verbose_name = _('Backend')

def ready(self):
""" Performs an DB engine check, as we maintain some engine specific queries. """
if (connection.vendor not in ['postgresql', 'mysql']):
# Temporary for backwards compatibility
warnings.showwarning(
_(
'Unsupported database engine "{}" active, '
'some features might not work properly'.format(connection.vendor)
),
RuntimeWarning, __file__, 0
)
22 changes: 21 additions & 1 deletion dsmr_consumption/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from django.conf import settings
from django.utils import timezone
from django.db import transaction
from django.db import transaction, connection
from django.db.models import Avg, Max

from dsmr_consumption.models.consumption import ElectricityConsumption, GasConsumption
Expand Down Expand Up @@ -198,3 +198,23 @@ def day_consumption(day):
def round_price(decimal_price):
""" Round the price to two decimals. """
return decimal_price.quantize(Decimal('.01'), rounding=ROUND_UP)


def average_electricity_by_hour():
""" Calculates the average consumption by hour. Measured over all consumption data. """
SQL_EXTRA = {
# Ugly engine check, but still beter than iterating over a hundred thousand items in code.
'postgresql': "date_part('hour', read_at)",
'mysql': "extract(hour from read_at)",
}

try:
sql_extra = SQL_EXTRA[connection.vendor]
except KeyError:
raise NotImplementedError(connection.vendor)

return ElectricityConsumption.objects.extra({
'hour': sql_extra
}).values('hour').order_by('hour').annotate(
avg_delivered=Avg('currently_delivered')
)
6 changes: 4 additions & 2 deletions dsmr_datalogger/tests/management_commands/test_datalogger.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,18 @@ def _poll_reading(self, serial_readline_mock, serial_open_mock):
serial_readline_mock.side_effect = self._dummy_data()

self._call_command_stdout('dsmr_datalogger')
self.assertTrue(DsmrReading.objects.exists())

def test_reading_creation(self):
""" Test whether dsmr_datalogger insert a reading. """
self._poll_reading()
self.assertGreater(DsmrReading.objects.all().count(), 0)
self.assertTrue(DsmrReading.objects.exists())

def test_reading_values(self):
""" Test whether dsmr_datalogger reads the correct values. """
self._poll_reading()
reading = DsmrReading.objects.get(pk=1)
self.assertTrue(DsmrReading.objects.exists())
reading = DsmrReading.objects.get()
self.assertEqual(
reading.timestamp,
datetime(2015, 11, 10, 18, 29, 59, tzinfo=pytz.UTC)
Expand Down
10 changes: 9 additions & 1 deletion dsmr_frontend/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,20 @@ def get_context_data(self, **kwargs):
class StatisticsMixin(object):
def get_context_data(self, **kwargs):
context_data = super(StatisticsMixin, self).get_context_data(**kwargs)

today = timezone.now().astimezone(settings.LOCAL_TIME_ZONE).date()
context_data['latest_reading'] = DsmrReading.objects.all().order_by('-pk')[0]
context_data['first_reading'] = DsmrReading.objects.all().order_by('pk')[0]
context_data['total_reading_count'] = DsmrReading.objects.count()

avg_electricity_per_hour = dsmr_consumption.services.average_electricity_by_hour()
context_data['avg_electricity_x'] = json.dumps(
['{}:00'.format(x['hour']) for x in avg_electricity_per_hour]
)
context_data['avg_electricity_y'] = json.dumps(
[float(x['avg_delivered'] * 1000) for x in avg_electricity_per_hour]
)
context_data['average_electricity_by_hour'] = avg_electricity_per_hour

try:
context_data['energy_prices'] = EnergySupplierPrice.objects.by_date(today)
except EnergySupplierPrice.DoesNotExist:
Expand Down
6 changes: 3 additions & 3 deletions dsmr_frontend/templates/dsmr_frontend/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@
labels: {{ electricity_x|safe }},
datasets: [{
data: {{ electricity_y|safe }},
label: "Electricity",
label: "{% trans 'Electricity' %}",
fillColor: "rgba(255,255,255,0.2)",
strokeColor: "rgba(255,0,0,1)",
pointColor: "rgba(255,0,0,1)",
Expand All @@ -173,7 +173,7 @@
labels: {{ gas_x|safe }},
datasets: [{
data: {{ gas_y|safe }},
label: "Gas",
label: "{% trans 'Gas' %}",
fillColor: "rgba(255,255,255,0.2)",
strokeColor: "rgba(250,133,0,1)",
pointColor: "rgba(250,133,0,1)",
Expand Down Expand Up @@ -201,7 +201,7 @@
labels: {{ temperature_x|safe }},
datasets: [{
data: {{ temperature_y|safe }},
label: "Temperature",
label: "{% trans 'Temperature' %}",
fillColor: "rgba(255,255,255,0.2)",
strokeColor: "rgba(35,183,229,1)",
pointColor: "rgba(35,183,229,1)",
Expand Down
12 changes: 6 additions & 6 deletions dsmr_frontend/templates/dsmr_frontend/history.html
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@
labels: {{ chart.days|safe }},
datasets: [{
data: {{ chart.electricity1|safe }},
label: "Electricity 1 (off-peak)",
label: "{% trans 'Electricity 1 (off-peak)' %}",
fillColor: "rgba(255,255,255,0.2)",
strokeColor: "rgba(255,0,0,1)",
pointColor: "rgba(255,0,0,1)",
Expand All @@ -196,7 +196,7 @@
pointHighlightStroke: "rgba(255,0,0,1)"
}, {
data: {{ chart.electricity2|safe }},
label: "Electricity 2 (peak)",
label: "{% trans 'Electricity 2 (peak)' %}",
fillColor: "rgba(255,255,255,0.2)",
strokeColor: "rgba(255,0,0,1)",
pointColor: "rgba(255,0,0,1)",
Expand All @@ -205,7 +205,7 @@
pointHighlightStroke: "rgba(255,0,0,1)"
}, {
data: {{ chart.electricity1_returned|safe }},
label: "Electricity 1 returned (off-peak)",
label: "{% trans 'Electricity 1 returned (off-peak)' %}",
fillColor: "rgba(255,255,255,0.2)",
strokeColor: "rgba(133,20,75,1)",
pointColor: "rgba(133,20,75,1)",
Expand All @@ -214,7 +214,7 @@
pointHighlightStroke: "rgba(133,20,75,1)"
}, {
data: {{ chart.electricity2_returned|safe }},
label: "Electricity 1 returned (peak)",
label: "{% trans 'Electricity 1 returned (peak)' %}",
fillColor: "rgba(255,255,255,0.2)",
strokeColor: "rgba(133,20,75,1)",
pointColor: "rgba(133,20,75,1)",
Expand All @@ -241,7 +241,7 @@
labels: {{ chart.days|safe }},
datasets: [{
data: {{ chart.gas|safe }},
label: "Gas",
label: "{% trans 'Gas' %}",
fillColor: "rgba(255,255,255,0.2)",
strokeColor: "rgba(250,133,0,1)",
pointColor: "rgba(250,133,0,1)",
Expand Down Expand Up @@ -269,7 +269,7 @@
labels: {{ chart.days|safe }},
datasets: [{
data: {{ chart.average_temperature|safe }},
label: "Gas",
label: "{% trans 'Temperature' %}",
fillColor: "rgba(255,255,255,0.2)",
strokeColor: "rgba(35,183,229,1)",
pointColor: "rgba(35,183,229,1)",
Expand Down
54 changes: 53 additions & 1 deletion dsmr_frontend/templates/dsmr_frontend/statistics.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{% extends "dsmr_frontend/base.html" %}
{% load humanize %}
{% load static %}
{% load i18n %}

{% block title %}{% trans "Statistics" %}{% endblock %}
Expand Down Expand Up @@ -87,7 +88,20 @@
</div><!-- /.panel -->
</div><!-- /.col -->
</div><!-- /.row -->


<div class="row">
<div class="col-md-12">
<div class="panel">
<header class="panel-heading">
{% blocktrans %}Average electricity usage by hour{% endblocktrans %} ({% trans "in Watt" noop %})
</header>
<div class="panel-body">
<canvas id="average-electricity-chart" width="1000" height="200"></canvas>
</div><!-- /.panel-body -->
</div><!-- /.panel -->
</div><!-- /.col -->
</div><!-- /.row -->

{% if energy_prices %}
<div class="row">
<div class="col-md-12">
Expand Down Expand Up @@ -155,4 +169,42 @@
</div><!-- /.row -->

</section><!-- /.content -->
{% endblock %}


{% block javascript %}
{{ block.super }}
<script type="text/javascript" src="{% static 'js/Chart.min.js' %}"></script>
<script type="text/javascript">
$(document).ready(function(){
render_average_electricity_chart();
});

function render_average_electricity_chart()
{
var data = {
labels: {{ avg_electricity_x|safe }},
datasets: [{
data: {{ avg_electricity_y|safe }},
label: "{% trans 'Average electricity usage per hour' %}",
fillColor: "rgba(151,187,205,0.5)",
strokeColor: "rgba(151,187,205,0.8)",
highlightFill: "rgba(151,187,205,0.75)",
highlightStroke: "rgba(151,187,205,1)",
// pointHighlightStroke: "rgba(0,0,0,1)"
}]
};

{% verbatim %}
var options = {
segmentShowStroke: true,
animation: false
};
{% endverbatim %}

var ctx = $("#average-electricity-chart").get(0).getContext("2d");
new Chart(ctx).Bar(data, options);
}

</script>
{% endblock %}
6 changes: 2 additions & 4 deletions dsmr_frontend/tests/test_webinterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ class TestViews(CallCommandStdoutMixin, TestCase):
def _synchronize_date(self, interval=None):
""" Little hack to fake any output for today (moment of test). """
self._call_command_stdout('dsmr_backend')
ec = ElectricityConsumption.objects.get(pk=1)
gc = GasConsumption.objects.get(pk=1)
ec = ElectricityConsumption.objects.all()[0]
gc = GasConsumption.objects.all()[0]

timestamp = timezone.now()

Expand Down Expand Up @@ -83,8 +83,6 @@ def test_history(self):
reverse('{}:history'.format(self.namespace))
)
self.assertIn('usage', response.context)
self.assertIn('notes', response.context['usage'][0])
self.assertEqual(response.context['usage'][0]['notes'][0], 'Gourmetten')
self.assertEqual(response.context['days_ago'], frontend_settings.recent_history_weeks * 7)
self.assertFalse(response.context['track_temperature'])
self.assertEqual(response.status_code, 200)
Expand Down
12 changes: 0 additions & 12 deletions dsmrreader/config/development.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,4 @@
from dsmrreader.config.base import *


DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'dsmrreader',
'USER': 'dsmrreader',
'PASSWORD': 'dsmrreader',
'HOST': '127.0.0.1',
'PORT': '5432',
'CONN_MAX_AGE': 300,
}
}

CACHES['default']['TIMEOUT'] = 0
7 changes: 3 additions & 4 deletions dsmrreader/config/test.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
""" Tests with SQLite backend, which WILL result in failing some tests, but it's bloody fast. """
from dsmrreader.config.base import *
""" Tests with SQLite backend. """
from dsmrreader.config.development import *


CACHES['default']['TIMEOUT'] = 0

DATABASES = {
'default': {
# SQLite is NOT supported and will FAIL tests. Use only for developing tests initially.
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'dsmrreader', # Will be adjusted to 'test_*' by Django.
'USER': 'dsmrreader',
Expand Down
Binary file modified dsmrreader/locales/nl/LC_MESSAGES/django.mo
Binary file not shown.
Loading

0 comments on commit 08c046e

Please sign in to comment.