diff --git a/docs/_static/screenshots/statistics.png b/docs/_static/screenshots/statistics.png index be9b3883c..2fbf35ee7 100644 Binary files a/docs/_static/screenshots/statistics.png and b/docs/_static/screenshots/statistics.png differ diff --git a/docs/changelog.rst b/docs/changelog.rst index 5eac3db4e..421c97179 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -2,6 +2,20 @@ Changelog ========= +v1.2.0 - 2016-05-18 +^^^^^^^^^^^^^^^^^^^ +- Energy supplier prices does not indicate tariff type (Django admin) (`#126 `_). +- Requirements update (`#128 `_). +- Force backup (`#123 `_). +- Update clean-install.md (`#131 `_). +- Improve data export field names (`#132 `_). +- Display average temperature in archive (`#122 `_). +- Pie charts on trends page overlap their canvas (`#136 `_). +- 'Slumber' consumption (`#115 `_). +- Show lowest & highest Watt peaks (`#138 `_). +- Allow day & hour statistics reset due to changing energy prices (`#95 `_). + + v1.1.2 - 2016-05-01 ^^^^^^^^^^^^^^^^^^^ - Trends page giving errors (when lacking data) (`#125 `_). diff --git a/docs/faq.rst b/docs/faq.rst new file mode 100644 index 000000000..ac560fde1 --- /dev/null +++ b/docs/faq.rst @@ -0,0 +1,18 @@ +Frequently Asked Questions (FAQ) +================================ + +Feature/bug report +------------------ +**How can I propose a feature or report a bug I've found?** + +`Just create a ticket at Github `_ + +Recalculate prices +------------------ +**I've adjusted my energy prices but there are no changes! How can I regenerate them with my new prices?** + +*You can flush your statistics by executing:* + +``./manage.py dsmr_stats_clear_statistics --ack-to-delete-my-data`` + +*The application will delete all statistics and (slowly) regenerate them in the background. Just make sure the source data is still there.* \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index d8d438fac..dfad44172 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -8,6 +8,7 @@ DSMR Reader's documentation screenshots installation application + faq changelog contributing credits diff --git a/docs/locale/nl/LC_MESSAGES/changelog.po b/docs/locale/nl/LC_MESSAGES/changelog.po index e548d0a40..67dcab8d9 100644 --- a/docs/locale/nl/LC_MESSAGES/changelog.po +++ b/docs/locale/nl/LC_MESSAGES/changelog.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: DSMR Reader 1.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-04-23 17:05+0200\n" +"POT-Creation-Date: 2016-05-18 21:04+0200\n" "PO-Revision-Date: 2016-04-18 22:10+0100\n" "Last-Translator: Dennis Siemensma \n" "Language-Team: Dennis Siemensma \n" @@ -16,518 +16,607 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.2.0\n" -"Language: nl\n" #: ../../changelog.rst:2 msgid "Changelog" msgstr "Wijzigingenoverzicht" -#: ../../changelog.rst:5 -msgid "v1.1.0 - 2016-xx-xx" +#: ../../changelog.rst:6 +msgid "v1.2.0 - 2016-xx-xx" msgstr "" -#: ../../changelog.rst:6 +#: ../../changelog.rst:7 +msgid "" +"Energy supplier prices does not indicate tariff type (Django admin) " +"(`#126 `_)." +msgstr "" + +#: ../../changelog.rst:8 +msgid "" +"Requirements update (`#128 `_)." +msgstr "" + +#: ../../changelog.rst:9 +msgid "" +"Force backup (`#123 `_)." +msgstr "" + +#: ../../changelog.rst:10 +msgid "" +"Update clean-install.md (`#131 `_)." +msgstr "" + +#: ../../changelog.rst:11 +msgid "" +"Improve data export field names (`#132 " +"`_)." +msgstr "" + +#: ../../changelog.rst:12 +msgid "" +"Display average temperature in archive (`#122 " +"`_)." +msgstr "" + +#: ../../changelog.rst:13 +msgid "" +"Pie charts on trends page overlap their canvas (`#136 " +"`_)." +msgstr "" + +#: ../../changelog.rst:14 +msgid "" +"'Slumber' consumption (`#115 `_)." +msgstr "" + +#: ../../changelog.rst:15 +msgid "" +"Show lowest & highest Watt peaks (`#138 " +"`_)." +msgstr "" + +#: ../../changelog.rst:16 +msgid "" +"Reset day & hour statistics when changing energy prices (`#95 " +"`_)." +msgstr "" + +#: ../../changelog.rst:20 +msgid "v1.1.2 - 2016-05-01" +msgstr "" + +#: ../../changelog.rst:21 +msgid "" +"Trends page giving errors (when lacking data) (`#125 " +"`_)." +msgstr "" + +#: ../../changelog.rst:25 +msgid "v1.1.1 - 2016-04-27" +msgstr "" + +#: ../../changelog.rst:26 +msgid "" +"Improve readme (`#124 `_)." +msgstr "" + +#: ../../changelog.rst:30 +msgid "v1.1.0 - 2016-04-23" +msgstr "" + +#: ../../changelog.rst:31 msgid "" "Autorefresh dashboard (`#117 `_)." msgstr "" -#: ../../changelog.rst:7 +#: ../../changelog.rst:32 msgid "" "Improve line graphs' visibility (`#111 " "`_)." msgstr "" -#: ../../changelog.rst:8 +#: ../../changelog.rst:33 msgid "" "Easily add notes (`#110 `_)." msgstr "" -#: ../../changelog.rst:9 +#: ../../changelog.rst:34 msgid "" "Export data points in CSV format (`#2 `_)." msgstr "" -#: ../../changelog.rst:10 +#: ../../changelog.rst:35 msgid "" "Allow day/month/year comparison (`#94 `_)." msgstr "" -#: ../../changelog.rst:11 +#: ../../changelog.rst:36 msgid "" "Docs: Add FAQ and generic application info (`#113 " "`_)." msgstr "" -#: ../../changelog.rst:15 +#: ../../changelog.rst:37 +msgid "" +"Support for Iskra meter (DSMR 2.x) (`#120 " +"`_)." +msgstr "" + +#: ../../changelog.rst:41 msgid "v1.0.1 - 2016-04-07" msgstr "" -#: ../../changelog.rst:16 +#: ../../changelog.rst:42 msgid "" "Update licence to OSI compatible one (`#119 " "`_)." msgstr "" -#: ../../changelog.rst:20 +#: ../../changelog.rst:46 msgid "v1.0.0 - 2016-04-07" msgstr "" -#: ../../changelog.rst:21 +#: ../../changelog.rst:47 msgid "First official stable release." msgstr "Eerste officiële stabiele release." -#: ../../changelog.rst:25 +#: ../../changelog.rst:51 msgid "[β] v0.1 (2015-10-29) to 0.16 (2016-04-06)" msgstr "" -#: ../../changelog.rst:26 +#: ../../changelog.rst:52 msgid "" "All previous beta releases/changes have been combined to a single list " "below:" msgstr "" -#: ../../changelog.rst:28 +#: ../../changelog.rst:54 msgid "" "Move documentation to wiki or RTD (`#90 " "`_)." msgstr "" -#: ../../changelog.rst:29 +#: ../../changelog.rst:55 msgid "" "Translate README to Dutch (`#16 `_)." msgstr "" -#: ../../changelog.rst:30 +#: ../../changelog.rst:56 msgid "" "Delete (recent) history page (`#112 `_)." msgstr "" -#: ../../changelog.rst:31 +#: ../../changelog.rst:57 msgid "" "Display most recent temperature in dashboard (`#114 " "`_)." msgstr "" -#: ../../changelog.rst:32 +#: ../../changelog.rst:58 msgid "" "Upgrade Django to 1.8.12 (`#118 `_)." msgstr "" -#: ../../changelog.rst:34 +#: ../../changelog.rst:60 msgid "" "Redesign trends page (`#97 `_)." msgstr "" -#: ../../changelog.rst:35 +#: ../../changelog.rst:61 msgid "" "Support for summer time (`#105 `_)." msgstr "" -#: ../../changelog.rst:36 +#: ../../changelog.rst:62 msgid "" "Support for Daylight Saving Time (DST) transition (`#104 " "`_)." msgstr "" -#: ../../changelog.rst:37 +#: ../../changelog.rst:63 msgid "" "Add (error) hints to status page (`#106 " "`_)." msgstr "" -#: ../../changelog.rst:38 +#: ../../changelog.rst:64 msgid "" "Keep track of version (`#108 `_)." msgstr "" -#: ../../changelog.rst:40 +#: ../../changelog.rst:66 msgid "" "Django 1.8.11 released (`#82 `_)." msgstr "" -#: ../../changelog.rst:41 +#: ../../changelog.rst:67 msgid "" "Prevent tests from failing due to moment of execution (`#88 " "`_)." msgstr "" -#: ../../changelog.rst:42 +#: ../../changelog.rst:68 msgid "" "Statistics page meter positions are broken (`#93 " "`_)." msgstr "" -#: ../../changelog.rst:43 +#: ../../changelog.rst:69 msgid "" "Archive only shows graph untill 23:00 (11 pm) (`#77 " "`_)." msgstr "" -#: ../../changelog.rst:44 +#: ../../changelog.rst:70 msgid "" "Trends page crashes due to nullable fields average (`#100 " "`_)." msgstr "" -#: ../../changelog.rst:45 +#: ../../changelog.rst:71 msgid "" "Trends: Plot peak and off-peak relative to each other (`#99 " "`_)." msgstr "" -#: ../../changelog.rst:46 +#: ../../changelog.rst:72 msgid "" "Monitor requirements with requires.io (`#101 " "`_)." msgstr "" -#: ../../changelog.rst:47 +#: ../../changelog.rst:73 msgid "" "Terminology (`#41 `_)." msgstr "" -#: ../../changelog.rst:48 +#: ../../changelog.rst:74 msgid "" "Obsolete signals in dsmr_consumption (`#63 " "`_)." msgstr "" -#: ../../changelog.rst:49 +#: ../../changelog.rst:75 msgid "" "Individual app testing coverage (`#64 `_)." msgstr "" -#: ../../changelog.rst:50 +#: ../../changelog.rst:76 msgid "" "Support for extra devices on other M-bus (0-n:24.1) (`#92 " "`_)." msgstr "" -#: ../../changelog.rst:51 +#: ../../changelog.rst:77 msgid "" "Separate post-deployment commands (`#102 " "`_)." msgstr "" -#: ../../changelog.rst:53 +#: ../../changelog.rst:79 msgid "" "Show exceptions in production (webinterface) (`#87 " "`_)." msgstr "" -#: ../../changelog.rst:54 +#: ../../changelog.rst:80 msgid "" "Keep Supervisor processes running (`#79 " "`_)." msgstr "" -#: ../../changelog.rst:55 +#: ../../changelog.rst:81 msgid "" "Hourly stats of 22:00:00+00 every day lack gas (`#78 " "`_)." msgstr "" -#: ../../changelog.rst:56 +#: ../../changelog.rst:82 msgid "" "Test Travis-CI with MySQL + MariaDB + PostgreSQL (`#54 " "`_)." msgstr "" -#: ../../changelog.rst:57 +#: ../../changelog.rst:83 msgid "" "PostgreSQL tests + nosetests + coverage failure: unrecognized " "configuration parameter \"foreign_key_checks\" (`#62 " "`_)." msgstr "" -#: ../../changelog.rst:58 +#: ../../changelog.rst:84 msgid "" "Performance check (`#83 `_)." msgstr "" -#: ../../changelog.rst:59 +#: ../../changelog.rst:85 msgid "" "Allow month & year archive (`#66 `_)." msgstr "" -#: ../../changelog.rst:60 +#: ../../changelog.rst:86 msgid "" "Graphs keep increasing height on tablet (`#89 " "`_)." msgstr "" -#: ../../changelog.rst:62 +#: ../../changelog.rst:88 msgid "" "Delete StatsSettings(.track) settings model (`#71 " "`_)." msgstr "" -#: ../../changelog.rst:63 +#: ../../changelog.rst:89 msgid "" "Drop deprecated commands (`#22 `_)." msgstr "" -#: ../../changelog.rst:64 +#: ../../changelog.rst:90 msgid "" "Datalogger doesn't work properly with DSMR 4.2 (KAIFA-METER) (`#73 " "`_)." msgstr "" -#: ../../changelog.rst:65 +#: ../../changelog.rst:91 msgid "" "Dashboard month statistics costs does not add up (`#75 " "`_)." msgstr "" -#: ../../changelog.rst:66 +#: ../../changelog.rst:92 msgid "" "Log unhandled exceptions and errors (`#65 " "`_)." msgstr "" -#: ../../changelog.rst:67 +#: ../../changelog.rst:93 msgid "" "Datalogger crashes with IntegrityError because 'timestamp' is null (`#74 " "`_)." msgstr "" -#: ../../changelog.rst:68 +#: ../../changelog.rst:94 msgid "" "Trends are always shown in UTC (`#76 `_)." msgstr "" -#: ../../changelog.rst:69 +#: ../../changelog.rst:95 msgid "" "Squash migrations (`#31 `_)." msgstr "" -#: ../../changelog.rst:70 +#: ../../changelog.rst:96 msgid "" "Display 'electricity returned' graph in dashboard (`#81 " "`_)." msgstr "" -#: ../../changelog.rst:71 +#: ../../changelog.rst:97 msgid "" "Optional gas (and electricity returned) capabilities tracking (`#70 " "`_)." msgstr "" -#: ../../changelog.rst:72 +#: ../../changelog.rst:98 msgid "" "Add 'electricity returned' to trends page (`#84 " "`_)." msgstr "" -#: ../../changelog.rst:74 +#: ../../changelog.rst:100 msgid "" "Archive: View past days details (`#61 `_)." msgstr "" -#: ../../changelog.rst:75 +#: ../../changelog.rst:101 msgid "" "Dashboard: Consumption total for current month (`#60 " "`_)." msgstr "" -#: ../../changelog.rst:76 +#: ../../changelog.rst:102 msgid "" "Check whether gas readings are optional (`#34 " "`_)." msgstr "" -#: ../../changelog.rst:77 +#: ../../changelog.rst:103 msgid "" "Django security releases issued: 1.8.10 (`#68 " "`_)." msgstr "" -#: ../../changelog.rst:78 +#: ../../changelog.rst:104 msgid "" "Notes display in archive (`#69 `_)." msgstr "" -#: ../../changelog.rst:80 +#: ../../changelog.rst:106 msgid "" "Status page/alerts when features are disabled/unavailable (`#45 " "`_)." msgstr "" -#: ../../changelog.rst:81 +#: ../../changelog.rst:107 msgid "" "Integrate Travis CI (`#48 `_)." msgstr "" -#: ../../changelog.rst:82 +#: ../../changelog.rst:108 msgid "" "Testing coverage (`#38 `_)." msgstr "" -#: ../../changelog.rst:83 +#: ../../changelog.rst:109 msgid "" "Implement automatic backups & Dropbox cloud storage (`#44 " "`_)." msgstr "" -#: ../../changelog.rst:84 +#: ../../changelog.rst:110 msgid "" "Link code coverage service to repository (`#56 " "`_)." msgstr "" -#: ../../changelog.rst:85 +#: ../../changelog.rst:111 msgid "" "Explore timezone.localtime() as replacement for datetime.astimezone() " "(`#50 `_)." msgstr "" -#: ../../changelog.rst:86 +#: ../../changelog.rst:112 msgid "" "Align GasConsumption.read_at to represent the start of hour (`#40 " "`_)." msgstr "" -#: ../../changelog.rst:88 +#: ../../changelog.rst:114 msgid "" "Cleanup unused static files (`#47 `_)." msgstr "" -#: ../../changelog.rst:89 +#: ../../changelog.rst:115 msgid "" "Investigated mysql_tzinfo_to_sql — Load the Time Zone Tables (`#35 " "`_)." msgstr "" -#: ../../changelog.rst:90 +#: ../../changelog.rst:116 msgid "" "Make additional DSMR data optional (`#46 " "`_)." msgstr "" -#: ../../changelog.rst:91 +#: ../../changelog.rst:117 msgid "" "Localize graph x-axis (`#42 `_)." msgstr "" -#: ../../changelog.rst:92 +#: ../../changelog.rst:118 msgid "" "Added graph formatting string to gettext file (`#42 " "`_)." msgstr "" -#: ../../changelog.rst:93 +#: ../../changelog.rst:119 msgid "" "Different colors for peak & off-peak electricity (`#52 " "`_)." msgstr "" -#: ../../changelog.rst:94 +#: ../../changelog.rst:120 msgid "" "Admin: Note widget (`#51 `_)." msgstr "" -#: ../../changelog.rst:95 +#: ../../changelog.rst:121 msgid "" "Allow GUI to run without data (`#26 `_)." msgstr "" -#: ../../changelog.rst:97 +#: ../../changelog.rst:123 msgid "" "Moved project to GitHub (`#28 `_)." msgstr "" -#: ../../changelog.rst:98 +#: ../../changelog.rst:124 msgid "Added stdout to dsmr_backend to reflect progress." msgstr "" -#: ../../changelog.rst:99 +#: ../../changelog.rst:125 msgid "" "Restore note usage in GUI (`#39 `_)." msgstr "" -#: ../../changelog.rst:101 +#: ../../changelog.rst:127 msgid "" "Store daily, weekly, monthly and yearly statistics (`#3 " "`_)." msgstr "" -#: ../../changelog.rst:102 +#: ../../changelog.rst:128 msgid "" "Improved Recent History page performance a bit. (as result of `#3 " "`_)" msgstr "" -#: ../../changelog.rst:103 +#: ../../changelog.rst:129 msgid "" "Updates ChartJS library tot 1.1, disposing django-chartjs plugin. Labels " "finally work! (as result of `#3 `_)" msgstr "" -#: ../../changelog.rst:104 +#: ../../changelog.rst:130 msgid "" "Added trends page. (as result of `#3 `_)" msgstr "" -#: ../../changelog.rst:106 +#: ../../changelog.rst:132 msgid "" "Recent history setting: set range (`#29 " "`_)." msgstr "" -#: ../../changelog.rst:107 +#: ../../changelog.rst:133 msgid "" "Mock required for test: dsmr_weather.test_weather_tracking (`#32 " "`_)." msgstr "" -#: ../../changelog.rst:109 +#: ../../changelog.rst:135 msgid "" "Massive refactoring: Separating apps & using signals (`#19 " "`_)." msgstr "" -#: ../../changelog.rst:110 +#: ../../changelog.rst:136 msgid "" "README update: Exit character for cu (`#27 " "`_, by Jeroen " "Peters)." msgstr "" -#: ../../changelog.rst:111 +#: ../../changelog.rst:137 msgid "Fixed untranslated strings in admin interface." msgstr "" -#: ../../changelog.rst:112 +#: ../../changelog.rst:138 msgid "Upgraded Django to 1.8.9." msgstr "" @@ -771,3 +860,6 @@ msgstr "" #~ msgid "First stable release." #~ msgstr "" +#~ msgid "v1.1.0 - 2016-xx-xx" +#~ msgstr "" + diff --git a/docs/locale/nl/LC_MESSAGES/credits.po b/docs/locale/nl/LC_MESSAGES/credits.po index 0e274ea20..68e0bb33d 100644 --- a/docs/locale/nl/LC_MESSAGES/credits.po +++ b/docs/locale/nl/LC_MESSAGES/credits.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: DSMR Reader 1.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-04-23 17:05+0200\n" +"POT-Creation-Date: 2016-05-18 21:04+0200\n" "PO-Revision-Date: 2016-04-07 20:22+0100\n" "Last-Translator: Dennis Siemensma \n" "Language-Team: Dennis Siemensma \n" @@ -16,7 +16,6 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.2.0\n" -"Language: nl\n" #: ../../credits.rst:2 msgid "Credits" @@ -107,11 +106,17 @@ msgstr "`Read The Docs `_" msgid "`MW `_" msgstr "`MW `_" -#: ../../credits.rst:41 +#: ../../credits.rst:40 +msgid "" +"`Full Page Screen Capture `_" +msgstr "" + +#: ../../credits.rst:44 msgid "Testers & contributors" msgstr "Testers & mensen met bijdrage" -#: ../../credits.rst:43 +#: ../../credits.rst:46 msgid "" "`Jeroen Peters `_ (`Github " "profile `_)" @@ -119,7 +124,7 @@ msgstr "" "`Jeroen Peters `_ (`Github " "profile `_)" -#: ../../credits.rst:44 +#: ../../credits.rst:47 msgid "" "`Daniel ter Horst `_ (`Github" " profile `_)" @@ -127,7 +132,7 @@ msgstr "" "`Daniel ter Horst `_ (`Github" " profile `_)" -#: ../../credits.rst:45 +#: ../../credits.rst:48 #, fuzzy msgid "" "`Sander de Leeuw `_" @@ -136,27 +141,32 @@ msgstr "" "`Jeroen Peters `_ (`Github " "profile `_)" -#: ../../credits.rst:46 +#: ../../credits.rst:49 +#, fuzzy +msgid "\"WatskeBart\" (`Github profile `_)" +msgstr "`Github `_" + +#: ../../credits.rst:50 msgid "`Gert Schaafsma `_" msgstr "`Gert Schaafsma `_" -#: ../../credits.rst:47 +#: ../../credits.rst:51 msgid "`Bert-Jan Vos `_" msgstr "`Bert-Jan Vos `_" -#: ../../credits.rst:51 +#: ../../credits.rst:55 msgid "DSMR help" msgstr "DSMR hulp" -#: ../../credits.rst:53 +#: ../../credits.rst:57 msgid "Dutch Smart Meter reading specifications, data cables, examples and hints:" msgstr "Dutch Smart Meter reading specifications, data cables, examples and hints:" -#: ../../credits.rst:55 +#: ../../credits.rst:59 msgid "`Gé Janssen `_" msgstr "`Gé Janssen `_" -#: ../../credits.rst:57 +#: ../../credits.rst:61 msgid "" "`Joost van der Linde " "`_" @@ -164,7 +174,7 @@ msgstr "" "`Joost van der Linde " "`_" -#: ../../credits.rst:59 +#: ../../credits.rst:63 msgid "`SOS Solutions `_" msgstr "`SOS Solutions `_" diff --git a/docs/locale/nl/LC_MESSAGES/faq.mo b/docs/locale/nl/LC_MESSAGES/faq.mo new file mode 100644 index 000000000..7b0a9c2b7 Binary files /dev/null and b/docs/locale/nl/LC_MESSAGES/faq.mo differ diff --git a/docs/locale/nl/LC_MESSAGES/faq.po b/docs/locale/nl/LC_MESSAGES/faq.po new file mode 100644 index 000000000..b7215e643 --- /dev/null +++ b/docs/locale/nl/LC_MESSAGES/faq.po @@ -0,0 +1,67 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2016, Dennis Siemensma +# This file is distributed under the same license as the DSMR Reader +# package. +# FIRST AUTHOR , 2016. +# +msgid "" +msgstr "" +"Project-Id-Version: DSMR Reader 1.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-05-18 21:05+0200\n" +"PO-Revision-Date: 2016-05-18 21:07+0100\n" +"Last-Translator: Dennis Siemensma \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.2.0\n" +"X-Generator: Poedit 1.5.4\n" + +#: ../../faq.rst:2 +msgid "Frequently Asked Questions (FAQ)" +msgstr "Veelgestelde vragen (FAQ)" + +#: ../../faq.rst:5 +msgid "Feature/bug report" +msgstr "Verzoek/fout melden" + +#: ../../faq.rst:6 +msgid "**How can I propose a feature or report a bug I've found?**" +msgstr "**Hoe kan ik een verzoek indienen of een fout melden?**" + +#: ../../faq.rst:8 +msgid "" +"`Just create a ticket at Github `_" +msgstr "" +"`Maak een ticket aan op Github `_" + +#: ../../faq.rst:11 +msgid "Recalculate prices" +msgstr "Prijzen opnieuw berekenen" + +#: ../../faq.rst:12 +msgid "" +"**I've adjusted my energy prices but there are no changes! How can I " +"regenerate them with my new prices?**" +msgstr "" +"**Ik heb zojuist mijn energieprijzen aangepast, maar ik zie geen verschil! " +"Hoe kan ik de nieuwe prijzen doorvoeren?**" + +#: ../../faq.rst:14 +msgid "*You can flush your statistics by executing:*" +msgstr "*Je kunt je statistieken verwijderen door het volgende uit te voeren:*" + +#: ../../faq.rst:16 +msgid "``./manage.py dsmr_stats_clear_statistics --ack-to-delete-my-data``" +msgstr "``./manage.py dsmr_stats_clear_statistics --ack-to-delete-my-data``" + +#: ../../faq.rst:18 +msgid "" +"*The application will delete all statistics and (slowly) regenerate them in " +"the background. Just make sure the source data is still there.*" +msgstr "" +"*De applicatie verwijdert alle statistics en genereert ze (langzaam) weer op " +"de achtergrond. Zorg er wel voor dat alle brongegevens intact zijn.*" diff --git a/dsmr_consumption/migrations/0002_verbose_text.py b/dsmr_consumption/migrations/0002_verbose_text.py new file mode 100644 index 000000000..5882d7fac --- /dev/null +++ b/dsmr_consumption/migrations/0002_verbose_text.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dsmr_consumption', '0001_squashed_0004_recalculate_gas_consumption'), + ] + + operations = [ + migrations.AlterField( + model_name='energysupplierprice', + name='electricity_1_price', + field=models.DecimalField(verbose_name='Electricity 1 price (low tariff)', default=0, max_digits=11, decimal_places=5), + ), + migrations.AlterField( + model_name='energysupplierprice', + name='electricity_2_price', + field=models.DecimalField(verbose_name='Electricity 2 price (high tariff)', default=0, max_digits=11, decimal_places=5), + ), + ] diff --git a/dsmr_consumption/models/energysupplier.py b/dsmr_consumption/models/energysupplier.py index 8b2137a53..c70851572 100644 --- a/dsmr_consumption/models/energysupplier.py +++ b/dsmr_consumption/models/energysupplier.py @@ -31,10 +31,10 @@ class EnergySupplierPrice(models.Model): help_text=_('For your own reference, i.e. the name of your supplier') ) electricity_1_price = models.DecimalField( - max_digits=11, decimal_places=5, default=0, verbose_name=_('Electricity 1 price') + max_digits=11, decimal_places=5, default=0, verbose_name=_('Electricity 1 price (low tariff)') ) electricity_2_price = models.DecimalField( - max_digits=11, decimal_places=5, default=0, verbose_name=_('Electricity 2 price') + max_digits=11, decimal_places=5, default=0, verbose_name=_('Electricity 2 price (high tariff)') ) gas_price = models.DecimalField( max_digits=11, decimal_places=5, default=0, verbose_name=_('Gas price') diff --git a/dsmr_consumption/services.py b/dsmr_consumption/services.py index e40661681..97267bde0 100644 --- a/dsmr_consumption/services.py +++ b/dsmr_consumption/services.py @@ -3,8 +3,7 @@ import pytz from django.utils import timezone -from django.db import connection -from django.db.models import Avg, Max +from django.db.models import Avg, Min, Max, Count from dsmr_consumption.models.consumption import ElectricityConsumption, GasConsumption from dsmr_consumption.models.settings import ConsumptionSettings @@ -186,6 +185,12 @@ def day_consumption(day): temperature_readings = TemperatureReading.objects.filter( read_at__gte=day_start, read_at__lt=day_end, ).order_by('read_at') + consumption['lowest_temperature'] = temperature_readings.aggregate( + avg_temperature=Min('degrees_celcius'), + )['avg_temperature'] or 0 + consumption['highest_temperature'] = temperature_readings.aggregate( + avg_temperature=Max('degrees_celcius'), + )['avg_temperature'] or 0 consumption['average_temperature'] = temperature_readings.aggregate( avg_temperature=Avg('degrees_celcius'), )['avg_temperature'] or 0 @@ -199,3 +204,41 @@ def round_decimal(decimal_price): decimal_price = Decimal(str(decimal_price)) return decimal_price.quantize(Decimal('.01'), rounding=ROUND_UP) + + +def calculate_slumber_consumption_watt(): + """ Groups all electricity readings to find the most constant consumption. """ + most_common = ElectricityConsumption.objects.filter( + currently_delivered__gt=0 + ).values('currently_delivered').annotate( + currently_delivered_count=Count('currently_delivered') + ).order_by('-currently_delivered_count')[:5] + + if not most_common: + return + + # We calculate the average among the most common consumption read. + count = 0 + usage = 0 + + for item in most_common: + count += item['currently_delivered_count'] + usage += item['currently_delivered_count'] * item['currently_delivered'] + + return round(usage / count * 1000) + + +def calculate_min_max_consumption_watt(): + """ Returns the lowest and highest Wattage consumed. """ + min_max = ElectricityConsumption.objects.filter( + currently_delivered__gt=0 + ).aggregate( + min_watt=Min('currently_delivered'), + max_watt=Max('currently_delivered') + ) + + for x in min_max.keys(): + if min_max[x]: + min_max[x] = int(min_max[x] * 1000) + + return min_max diff --git a/dsmr_consumption/tests/test_services.py b/dsmr_consumption/tests/test_services.py index 91e3f4c3c..f3b0e2acd 100644 --- a/dsmr_consumption/tests/test_services.py +++ b/dsmr_consumption/tests/test_services.py @@ -151,6 +151,79 @@ def test_round_decimal(self): rounded = dsmr_consumption.services.round_decimal(decimal_price=Decimal('1.555')) self.assertEqual(rounded, Decimal('1.56')) + def test_calculate_slumber_consumption_watt(self): + most_common = dsmr_consumption.services.calculate_slumber_consumption_watt() + self.assertIsNone(most_common) + + ElectricityConsumption.objects.create( + read_at=timezone.now(), + delivered_1=1, + returned_1=1, + delivered_2=2, + returned_2=2, + currently_delivered=0.25, + currently_returned=0, + ) + ElectricityConsumption.objects.create( + read_at=timezone.now() + timezone.timedelta(minutes=1), + delivered_1=1, + returned_1=1, + delivered_2=2, + returned_2=2, + currently_delivered=0.25, + currently_returned=0, + ) + ElectricityConsumption.objects.create( + read_at=timezone.now() + timezone.timedelta(minutes=2), + delivered_1=1, + returned_1=1, + delivered_2=2, + returned_2=2, + currently_delivered=1, + currently_returned=0, + ) + most_common = dsmr_consumption.services.calculate_slumber_consumption_watt() + + # Average = 250 + 250 + 1000 / 3 = 500. + self.assertEqual(most_common, 500) + + def test_calculate_min_max_consumption_watt(self): + min_max = dsmr_consumption.services.calculate_min_max_consumption_watt() + self.assertIsNone(min_max['min_watt']) + self.assertIsNone(min_max['max_watt']) + + ElectricityConsumption.objects.create( + read_at=timezone.now(), + delivered_1=1, + returned_1=1, + delivered_2=2, + returned_2=2, + currently_delivered=0.25, + currently_returned=0, + ) + ElectricityConsumption.objects.create( + read_at=timezone.now() + timezone.timedelta(minutes=1), + delivered_1=1, + returned_1=1, + delivered_2=2, + returned_2=2, + currently_delivered=0.25, + currently_returned=0, + ) + ElectricityConsumption.objects.create( + read_at=timezone.now() + timezone.timedelta(minutes=2), + delivered_1=1, + returned_1=1, + delivered_2=2, + returned_2=2, + currently_delivered=6.123, + currently_returned=0, + ) + min_max = dsmr_consumption.services.calculate_min_max_consumption_watt() + + self.assertEqual(min_max['min_watt'], 250) + self.assertEqual(min_max['max_watt'], 6123) + class TestServicesWithoutGas(TestServices): fixtures = ['dsmr_consumption/test_dsmrreading_without_gas.json'] diff --git a/dsmr_frontend/templates/dsmr_frontend/archive.html b/dsmr_frontend/templates/dsmr_frontend/archive.html index 1d420309d..bf99ddfbb 100644 --- a/dsmr_frontend/templates/dsmr_frontend/archive.html +++ b/dsmr_frontend/templates/dsmr_frontend/archive.html @@ -59,10 +59,10 @@
-
- - - + + + + - + + + + - + + + + {% endif %} - + {% endblock %} {% block stylesheets %} @@ -356,5 +356,6 @@ ctx.canvas.height = $("#gas-chart").parent().height(); g_gas_chart_instance = new Chart(ctx).Line(data, line_options); } - + + {% endblock %} \ No newline at end of file diff --git a/dsmr_frontend/templates/dsmr_frontend/base.html b/dsmr_frontend/templates/dsmr_frontend/base.html index cf4ffb877..fd1c9306b 100644 --- a/dsmr_frontend/templates/dsmr_frontend/base.html +++ b/dsmr_frontend/templates/dsmr_frontend/base.html @@ -129,7 +129,7 @@ {% block content %}{% endblock %}
- “{% trans "DSMR reader" %}” {% trans "created by" %} Dennis Siemensma © 2015 - 2016 + “{% trans "DSMR (Dutch Smart Meter Requirements) reader" %}” {% trans "created by" %} Dennis Siemensma © 2015 - 2016 | {% trans "Theme created by" %} web-apps.ninja © 2015
diff --git a/dsmr_frontend/templates/dsmr_frontend/configuration.html b/dsmr_frontend/templates/dsmr_frontend/configuration.html index 03dc9e9fe..46d0420a8 100644 --- a/dsmr_frontend/templates/dsmr_frontend/configuration.html +++ b/dsmr_frontend/templates/dsmr_frontend/configuration.html @@ -54,10 +54,10 @@ {% model_meta_info datalogger_settings 'com_port' 'help_text' %} - - - - + + + +
@@ -91,14 +91,23 @@ {% model_meta_info backup_settings 'latest_backup' 'verbose_name' %} - {{ backup_settings.latest_backup|naturaltime|default_if_none:'-' }} + +

{{ backup_settings.latest_backup|naturaltime|default_if_none:'-' }}

+ +
+ {% csrf_token %} + +
+ {% model_meta_info backup_settings 'latest_backup' 'help_text' %} -
-
- - + + + +
@@ -121,10 +130,10 @@ {% model_meta_info consumption_settings 'compactor_grouping_type' 'help_text' %} -
-
- - + + + +
@@ -147,10 +156,10 @@ {% model_meta_info frontend_settings 'reverse_dashboard_graphs' 'help_text' %} -
-
- - + + + +
@@ -178,10 +187,10 @@ {% model_meta_info dropbox_settings 'latest_sync' 'help_text' %} -
-
- - + + + +
@@ -209,9 +218,9 @@ {% model_meta_info weather_settings 'buienradar_station' 'help_text' %} -
-
- - - + + + + + {% endblock %} diff --git a/dsmr_frontend/templates/dsmr_frontend/dashboard.html b/dsmr_frontend/templates/dsmr_frontend/dashboard.html index c743f9601..11fd9ae66 100644 --- a/dsmr_frontend/templates/dsmr_frontend/dashboard.html +++ b/dsmr_frontend/templates/dsmr_frontend/dashboard.html @@ -94,9 +94,9 @@ {{ month_statistics.total_cost|default:'-' }} - - - + + + {% endif %} @@ -147,9 +147,9 @@ {{ consumption.total_cost|default:'-' }} - - - + + + {% endif %} @@ -162,9 +162,9 @@
-
- - + + + {% endif %} @@ -177,9 +177,9 @@
-
- - + + + {% endif %} @@ -192,9 +192,9 @@
-
- - + + + {% endif %} @@ -207,12 +207,12 @@
-
- - + + + {% endif %} - + {% endblock %} @@ -329,9 +329,9 @@ datasets: [{ data: {{ temperature_y|safe }}, label: "{% trans 'Temperature' %}", - fillColor: "rgba(35,183,229,0.1)", - strokeColor: "rgba(35,183,229,1)", - pointColor: "rgba(35,183,229,1)", + fillColor: "rgba(0,115,183,0.1)", + strokeColor: "rgba(0,115,183,1)", + pointColor: "rgba(0,115,183,1)", pointStrokeColor: "#fff", pointHighlightFill: "#fff", pointHighlightStroke: "rgba(150,150,150,1)" diff --git a/dsmr_frontend/templates/dsmr_frontend/export.html b/dsmr_frontend/templates/dsmr_frontend/export.html index 0337704b8..c84139349 100644 --- a/dsmr_frontend/templates/dsmr_frontend/export.html +++ b/dsmr_frontend/templates/dsmr_frontend/export.html @@ -35,9 +35,9 @@ {% blocktrans %}Summary of each hour read. Contains electricity and gas (if applicable).{% endblocktrans %} - - - + + +
@@ -50,9 +50,9 @@
-
-
- + + +
@@ -63,9 +63,9 @@
-
-
-
+ + +
@@ -82,15 +82,15 @@ {% blocktrans %}Exports the data in Comma Separated Format, which can be read by Excel.{% endblocktrans %} -
- - + + +   Download export - + {% endblock %} {% block stylesheets %} diff --git a/dsmr_frontend/templates/dsmr_frontend/fragments/archive-xhr-statistics.html b/dsmr_frontend/templates/dsmr_frontend/fragments/archive-xhr-statistics.html index fc6616a55..2a62f8c10 100644 --- a/dsmr_frontend/templates/dsmr_frontend/fragments/archive-xhr-statistics.html +++ b/dsmr_frontend/templates/dsmr_frontend/fragments/archive-xhr-statistics.html @@ -39,16 +39,28 @@ {% if capabilities.gas %}{% trans "Gas" %}{% endif %} - {% if capabilities.gas %}{{ statistics.gas|default:'-' }}{% endif %} + {% if capabilities.gas %}{{ statistics.gas|default:'-' }}{% endif %}   {% if energy_price %}{{ energy_price.gas_price|default:'-' }}{% endif %} - {% if capabilities.gas %}{{ statistics.gas_cost|default:'-' }}{% endif %} + {% if capabilities.gas %}{{ statistics.gas_cost|default:'-' }}{% endif %} {% trans "Total" %}   {{ statistics.total_cost|default:'-' }} + {% if statistics.temperature_avg %} + +   + + + {% trans "Weather" %} + {% trans "Min." %}   {{ statistics.temperature_min|floatformat|default:'-' }} °C + {% trans "Max." %}   {{ statistics.temperature_max|floatformat|default:'-' }} °C +   + {% trans "Avg." %}   {{ statistics.temperature_avg|floatformat|default:'-' }} °C + + {% endif %} {% if notes %} @@ -56,5 +68,5 @@ {% endfor %} {% endif %} - - + + diff --git a/dsmr_frontend/templates/dsmr_frontend/statistics.html b/dsmr_frontend/templates/dsmr_frontend/statistics.html index 3a912919a..7f7ff1f9f 100644 --- a/dsmr_frontend/templates/dsmr_frontend/statistics.html +++ b/dsmr_frontend/templates/dsmr_frontend/statistics.html @@ -47,10 +47,10 @@ {% endif %} - - - - + + + +
@@ -115,10 +115,41 @@ {% blocktrans %}Tracking meter statistics is disabled. Enable this feature in the datalogger settings to view statistics.{% endblocktrans %}
{% endif %} -
- - - + + + + + +
+
+
+
+ {% trans "Usage statistics" %} +
+
+ + + + + + + + + + + + + +
+ {% trans "Most common electricity consumption" %} +
+ {% blocktrans %}Average calculated among the top five most common electricity consumption read. This might also be the (minimum) constant electricity consumption in your home.{% endblocktrans %}
+
  {{ slumber_consumption_watt|intcomma|default:'-' }}   {% trans "Watt" %}
{% trans "Lowest electricity consumption read" %}   {{ min_max_consumption_watt.min_watt|intcomma|default:'-' }}   {% trans "Watt" %}
{% trans "Highest electricity consumption read" %}   {{ min_max_consumption_watt.max_watt|intcomma|default:'-' }}   {% trans "Watt" %}
+
+
+
+
+ {% endif %}
@@ -149,13 +180,15 @@ {% else %} {% endif %} -
- - - + + + + - + {% endblock %} diff --git a/dsmr_frontend/templates/dsmr_frontend/status.html b/dsmr_frontend/templates/dsmr_frontend/status.html index b2d610a12..40f416455 100644 --- a/dsmr_frontend/templates/dsmr_frontend/status.html +++ b/dsmr_frontend/templates/dsmr_frontend/status.html @@ -32,9 +32,9 @@ {% trans 'View all releases' %} - - - + + +
@@ -65,9 +65,9 @@ {{ total_reading_count|intcomma }} -
- - + + +
@@ -126,9 +126,9 @@ {% endif %} -
- - + + +
@@ -157,10 +157,10 @@ -
- - + + + - + {% endblock %} diff --git a/dsmr_frontend/templates/dsmr_frontend/trends.html b/dsmr_frontend/templates/dsmr_frontend/trends.html index b3256ba0b..0dde31e0e 100644 --- a/dsmr_frontend/templates/dsmr_frontend/trends.html +++ b/dsmr_frontend/templates/dsmr_frontend/trends.html @@ -29,10 +29,10 @@
-
- - - + + + + {% endif %} {% if capabilities.electricity_returned %} @@ -44,10 +44,10 @@
-
- - - + + + + {% endif %} {% if capabilities.gas %} @@ -59,42 +59,41 @@
-
- - - + + + + {% endif %} {% if capabilities.electricity %}
-
+
{% blocktrans %}Electricity tariff ratio (passed week){% endblocktrans %}
-
-
-
-
+
+ + +
-
+
{% blocktrans %}Electricity tariff ratio (passed month){% endblocktrans %}
-
-
-
-
+
+ + + {% endif %} - - + {% endblock %} diff --git a/dsmr_frontend/tests/test_webinterface.py b/dsmr_frontend/tests/test_webinterface.py index 918b0b32a..a06e25ad9 100644 --- a/dsmr_frontend/tests/test_webinterface.py +++ b/dsmr_frontend/tests/test_webinterface.py @@ -8,6 +8,7 @@ from django.contrib.auth.models import User from dsmr_consumption.models.consumption import ElectricityConsumption, GasConsumption +from dsmr_backup.models.settings import BackupSettings from dsmr_consumption.models.settings import ConsumptionSettings from dsmr_datalogger.models.settings import DataloggerSettings from dsmr_frontend.models.settings import FrontendSettings @@ -275,21 +276,21 @@ def test_export_as_csv(self): @mock.patch('django.utils.timezone.now') def test_configuration(self, now_mock): + view_url = reverse('{}:configuration'.format(self.namespace)) now_mock.return_value = timezone.make_aware( timezone.datetime(2016, 1, 1) ) # Check login required. - response = self.client.get( - reverse('{}:configuration'.format(self.namespace)) - ) + response = self.client.get(view_url) self.assertEqual(response.status_code, 302) + self.assertEqual( + response['Location'], 'http://testserver/admin/login/?next={}'.format(view_url) + ) # Login and retest self.client.login(username='testuser', password='passwd') - response = self.client.get( - reverse('{}:configuration'.format(self.namespace)) - ) + response = self.client.get(view_url) self.assertEqual(response.status_code, 200) self.assertIn('consumption_settings', response.context) @@ -304,6 +305,40 @@ def test_configuration(self, now_mock): self.assertIn('weather_settings', response.context) self.assertIsInstance(response.context['weather_settings'], WeatherSettings) + @mock.patch('django.utils.timezone.now') + def test_configuration_force_backup(self, now_mock): + view_url = reverse('{}:configuration-force-backup'.format(self.namespace)) + now_mock.return_value = timezone.make_aware( + timezone.datetime(2016, 1, 1) + ) + backup_settings = BackupSettings.get_solo() + backup_settings.latest_backup = now_mock.return_value + backup_settings.save() + + self.assertEqual(BackupSettings.get_solo().latest_backup, now_mock.return_value) + + # Check login required. + response = self.client.post(view_url) + self.assertEqual(response.status_code, 302) + self.assertEqual( + response['Location'], 'http://testserver/configuration/admin/login/?next={}'.format(view_url) + ) + + # Login and retest. + self.client.login(username='testuser', password='passwd') + response = self.client.post(view_url) + + success_url = reverse('{}:configuration'.format(self.namespace)) + self.assertEqual(response.status_code, 302) + self.assertEqual( + response['Location'], 'http://testserver{}'.format(success_url) + ) + # Setting should have been altered. + self.assertEqual( + BackupSettings.get_solo().latest_backup, + now_mock.return_value - timezone.timedelta(days=7) + ) + class TestViewsWithoutData(TestViews): """ Same tests as above, but without any data as it's flushed in setUp(). """ diff --git a/dsmr_frontend/urls.py b/dsmr_frontend/urls.py index 36c72ab14..77255ef6d 100644 --- a/dsmr_frontend/urls.py +++ b/dsmr_frontend/urls.py @@ -10,7 +10,7 @@ from dsmr_frontend.views.compare import Compare from dsmr_frontend.views.export import Export, ExportAsCsv from dsmr_frontend.views.status import Status -from dsmr_frontend.views.configuration import Configuration +from dsmr_frontend.views.configuration import Configuration, ForceBackup urlpatterns = [ @@ -43,4 +43,9 @@ url(r'^export/csv$', login_required(ExportAsCsv.as_view()), name='export-as-csv'), url(r'^configuration$', login_required(Configuration.as_view()), name='configuration'), + url( + r'^configuration/force-backup$', + login_required(ForceBackup.as_view()), + name='configuration-force-backup' + ), ] diff --git a/dsmr_frontend/views/configuration.py b/dsmr_frontend/views/configuration.py index 34d9b93dd..07e84ef40 100644 --- a/dsmr_frontend/views/configuration.py +++ b/dsmr_frontend/views/configuration.py @@ -1,4 +1,7 @@ -from django.views.generic.base import TemplateView +from django.views.generic.base import TemplateView, View +from django.core.urlresolvers import reverse +from django.shortcuts import redirect +from django.utils import timezone from dsmr_consumption.models.settings import ConsumptionSettings from dsmr_datalogger.models.settings import DataloggerSettings @@ -19,3 +22,13 @@ def get_context_data(self, **kwargs): context_data['backup_settings'] = BackupSettings.get_solo() context_data['dropbox_settings'] = DropboxSettings.get_solo() return context_data + + +class ForceBackup(View): + """ Alters the backup settings, forcing the application to create a (new) backup right away. """ + def post(self, request): + backup_settings = BackupSettings.get_solo() + backup_settings.latest_backup = timezone.now() - timezone.timedelta(days=7) + backup_settings.save() + + return redirect(reverse('frontend:configuration')) diff --git a/dsmr_frontend/views/export.py b/dsmr_frontend/views/export.py index 2cf43a5b3..d7cb4fa97 100644 --- a/dsmr_frontend/views/export.py +++ b/dsmr_frontend/views/export.py @@ -78,6 +78,7 @@ class Echo(object): def write(self, value): """ Write the value by returning it, instead of storing in a buffer. """ return value + pseudo_buffer = Echo() writer = csv.writer(pseudo_buffer) response = StreamingHttpResponse( @@ -93,7 +94,14 @@ def write(self, value): return response def _generate_csv_row(self, writer, data, fields): - yield writer.writerow(fields) + if not data: + raise StopIteration() + + # Write header, but use the fields' verbose name. + data_class = data[0].__class__ + header = [data_class._meta.get_field(x).verbose_name.title() for x in fields] + + yield writer.writerow(header) for current_data in data: yield writer.writerow([ diff --git a/dsmr_frontend/views/statistics.py b/dsmr_frontend/views/statistics.py index 89203fd3c..dd1630105 100644 --- a/dsmr_frontend/views/statistics.py +++ b/dsmr_frontend/views/statistics.py @@ -5,6 +5,7 @@ from dsmr_consumption.models.energysupplier import EnergySupplierPrice from dsmr_datalogger.models.settings import DataloggerSettings import dsmr_backend.services +import dsmr_consumption.services class Statistics(TemplateView): @@ -28,4 +29,11 @@ def get_context_data(self, **kwargs): except EnergySupplierPrice.DoesNotExist: pass + # Use stats + context_data['slumber_consumption_watt'] = dsmr_consumption.services.\ + calculate_slumber_consumption_watt() + + context_data['min_max_consumption_watt'] = dsmr_consumption.services.\ + calculate_min_max_consumption_watt() + return context_data diff --git a/dsmr_stats/management/__init__.py b/dsmr_stats/management/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/dsmr_stats/management/commands/__init__.py b/dsmr_stats/management/commands/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/dsmr_stats/management/commands/dsmr_stats_clear_statistics.py b/dsmr_stats/management/commands/dsmr_stats_clear_statistics.py new file mode 100644 index 000000000..fa2f8f06a --- /dev/null +++ b/dsmr_stats/management/commands/dsmr_stats_clear_statistics.py @@ -0,0 +1,26 @@ +from django.core.management.base import BaseCommand, CommandError +from django.utils.translation import ugettext as _ + +import dsmr_stats.services + + +class Command(BaseCommand): + help = _('Clears all statistics generated. Use this to regenerate them after altering prices.') + + def add_arguments(self, parser): + super(Command, self).add_arguments(parser) + parser.add_argument( + '--ack-to-delete-my-data', + action='store_true', + dest='acked_warning', + default=False, + help=_('Required to acknowledge you that you WILL delete your statistics with this.') + ) + + def handle(self, **options): + if not options.get('acked_warning'): + raise CommandError(_( + 'Intended usage is NOT production! Force by using --ack-to-delete-my-data' + )) + + dsmr_stats.services.clear_statistics() diff --git a/dsmr_stats/migrations/0005_statistics_exportverbose_names.py b/dsmr_stats/migrations/0005_statistics_exportverbose_names.py new file mode 100644 index 000000000..07bcd4c27 --- /dev/null +++ b/dsmr_stats/migrations/0005_statistics_exportverbose_names.py @@ -0,0 +1,99 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dsmr_stats', '0004_hour_statistics_gas_default_retroactive'), + ] + + operations = [ + migrations.AlterField( + model_name='daystatistics', + name='average_temperature', + field=models.DecimalField(decimal_places=1, verbose_name='Average temperature', null=True, default=None, max_digits=4), + ), + migrations.AlterField( + model_name='daystatistics', + name='day', + field=models.DateField(unique=True, verbose_name='Date'), + ), + migrations.AlterField( + model_name='daystatistics', + name='electricity1', + field=models.DecimalField(decimal_places=3, verbose_name='Electricity 1 (low tariff)', max_digits=9), + ), + migrations.AlterField( + model_name='daystatistics', + name='electricity1_cost', + field=models.DecimalField(decimal_places=2, verbose_name='Electricity 1 price (low tariff)', max_digits=8), + ), + migrations.AlterField( + model_name='daystatistics', + name='electricity1_returned', + field=models.DecimalField(decimal_places=3, verbose_name='Electricity 1 returned (low tariff)', max_digits=9), + ), + migrations.AlterField( + model_name='daystatistics', + name='electricity2', + field=models.DecimalField(decimal_places=3, verbose_name='Electricity 2 (high tariff)', max_digits=9), + ), + migrations.AlterField( + model_name='daystatistics', + name='electricity2_cost', + field=models.DecimalField(decimal_places=2, verbose_name='Electricity 2 price (high tariff)', max_digits=8), + ), + migrations.AlterField( + model_name='daystatistics', + name='electricity2_returned', + field=models.DecimalField(decimal_places=3, verbose_name='Electricity 2 returned (high tariff)', max_digits=9), + ), + migrations.AlterField( + model_name='daystatistics', + name='gas', + field=models.DecimalField(decimal_places=3, verbose_name='Gas', null=True, default=None, max_digits=9), + ), + migrations.AlterField( + model_name='daystatistics', + name='gas_cost', + field=models.DecimalField(decimal_places=2, verbose_name='Gas price', null=True, default=None, max_digits=8), + ), + migrations.AlterField( + model_name='daystatistics', + name='total_cost', + field=models.DecimalField(decimal_places=2, verbose_name='Total cost', max_digits=8), + ), + migrations.AlterField( + model_name='hourstatistics', + name='electricity1', + field=models.DecimalField(decimal_places=3, verbose_name='Electricity 1 (low tariff)', max_digits=9), + ), + migrations.AlterField( + model_name='hourstatistics', + name='electricity1_returned', + field=models.DecimalField(decimal_places=3, verbose_name='Electricity 1 returned (low tariff)', max_digits=9), + ), + migrations.AlterField( + model_name='hourstatistics', + name='electricity2', + field=models.DecimalField(decimal_places=3, verbose_name='Electricity 2 (high tariff)', max_digits=9), + ), + migrations.AlterField( + model_name='hourstatistics', + name='electricity2_returned', + field=models.DecimalField(decimal_places=3, verbose_name='Electricity 2 returned (high tariff)', max_digits=9), + ), + migrations.AlterField( + model_name='hourstatistics', + name='gas', + field=models.DecimalField(decimal_places=3, verbose_name='Gas', max_digits=9, default=0), + ), + migrations.AlterField( + model_name='hourstatistics', + name='hour_start', + field=models.DateTimeField(unique=True, verbose_name='Hour start'), + ), + ] diff --git a/dsmr_stats/migrations/0006_min_max_temperature_statistics.py b/dsmr_stats/migrations/0006_min_max_temperature_statistics.py new file mode 100644 index 000000000..a786011c4 --- /dev/null +++ b/dsmr_stats/migrations/0006_min_max_temperature_statistics.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dsmr_stats', '0005_statistics_exportverbose_names'), + ] + + operations = [ + migrations.AddField( + model_name='daystatistics', + name='highest_temperature', + field=models.DecimalField(decimal_places=1, max_digits=4, verbose_name='Highest temperature', default=None, null=True), + ), + migrations.AddField( + model_name='daystatistics', + name='lowest_temperature', + field=models.DecimalField(decimal_places=1, max_digits=4, verbose_name='Lowest temperature', default=None, null=True), + ), + ] diff --git a/dsmr_stats/migrations/0007_min_max_temperature_statistics_retroactive.py b/dsmr_stats/migrations/0007_min_max_temperature_statistics_retroactive.py new file mode 100644 index 000000000..27a36662c --- /dev/null +++ b/dsmr_stats/migrations/0007_min_max_temperature_statistics_retroactive.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations +from django.db.models import Q + + +def regenerate_data(apps, schema_editor): + DayStatistics = apps.get_model('dsmr_stats', 'DayStatistics') + + # Only when we have at least one temperature reading which was not zero. + if not DayStatistics.objects.filter(~Q(average_temperature=0)).exists(): + return + + print('') + + day_count = DayStatistics.objects.all().count() + DayStatistics.objects.all().delete() + + import dsmr_stats.services + + for x in range(1, day_count + 1): + # Just call analyze for each day. If we missed a day or so, the backend will regenerate it. + print('Regenerating day: {} / {}'.format(x, day_count)) + dsmr_stats.services.analyze() + + +class Migration(migrations.Migration): + + dependencies = [ + ('dsmr_stats', '0006_min_max_temperature_statistics'), + ] + + operations = [ + migrations.RunPython(regenerate_data) + ] diff --git a/dsmr_stats/models/statistics.py b/dsmr_stats/models/statistics.py index 67e3c90ec..f392c82eb 100644 --- a/dsmr_stats/models/statistics.py +++ b/dsmr_stats/models/statistics.py @@ -1,25 +1,48 @@ from django.db import models +from django.utils.translation import ugettext_lazy as _ class DayStatistics(models.Model): """ Daily consumption usage summary. """ - day = models.DateField(unique=True) - total_cost = models.DecimalField(max_digits=8, decimal_places=2) + day = models.DateField(unique=True, verbose_name=_('Date')) + total_cost = models.DecimalField(max_digits=8, decimal_places=2, verbose_name=_('Total cost')) - electricity1 = models.DecimalField(max_digits=9, decimal_places=3) - electricity2 = models.DecimalField(max_digits=9, decimal_places=3) - electricity1_returned = models.DecimalField(max_digits=9, decimal_places=3) - electricity2_returned = models.DecimalField(max_digits=9, decimal_places=3) - electricity1_cost = models.DecimalField(max_digits=8, decimal_places=2) - electricity2_cost = models.DecimalField(max_digits=8, decimal_places=2) + electricity1 = models.DecimalField( + max_digits=9, decimal_places=3, verbose_name=_('Electricity 1 (low tariff)') + ) + electricity2 = models.DecimalField( + max_digits=9, decimal_places=3, verbose_name=_('Electricity 2 (high tariff)') + ) + electricity1_returned = models.DecimalField( + max_digits=9, decimal_places=3, verbose_name=_('Electricity 1 returned (low tariff)') + ) + electricity2_returned = models.DecimalField( + max_digits=9, decimal_places=3, verbose_name=_('Electricity 2 returned (high tariff)') + ) + electricity1_cost = models.DecimalField( + max_digits=8, decimal_places=2, verbose_name=_('Electricity 1 price (low tariff)') + ) + electricity2_cost = models.DecimalField( + max_digits=8, decimal_places=2, verbose_name=_('Electricity 2 price (high tariff)') + ) # Gas readings are optional/not guaranteed. - gas = models.DecimalField(max_digits=9, decimal_places=3, null=True, default=None) - gas_cost = models.DecimalField(max_digits=8, decimal_places=2, null=True, default=None) + gas = models.DecimalField( + max_digits=9, decimal_places=3, null=True, default=None, verbose_name=_('Gas') + ) + gas_cost = models.DecimalField( + max_digits=8, decimal_places=2, null=True, default=None, verbose_name=_('Gas price') + ) # Temperature readings depend on user settings. + lowest_temperature = models.DecimalField( + max_digits=4, decimal_places=1, null=True, default=None, verbose_name=_('Lowest temperature') + ) + highest_temperature = models.DecimalField( + max_digits=4, decimal_places=1, null=True, default=None, verbose_name=_('Highest temperature') + ) average_temperature = models.DecimalField( - max_digits=4, decimal_places=1, null=True, default=None + max_digits=4, decimal_places=1, null=True, default=None, verbose_name=_('Average temperature') ) class Meta: @@ -33,15 +56,23 @@ def __str__(self): class HourStatistics(models.Model): """ Hourly consumption usage summary. """ - hour_start = models.DateTimeField(unique=True) + hour_start = models.DateTimeField(unique=True, verbose_name=_('Hour start')) - electricity1 = models.DecimalField(max_digits=9, decimal_places=3) - electricity2 = models.DecimalField(max_digits=9, decimal_places=3) - electricity1_returned = models.DecimalField(max_digits=9, decimal_places=3) - electricity2_returned = models.DecimalField(max_digits=9, decimal_places=3) + electricity1 = models.DecimalField( + max_digits=9, decimal_places=3, verbose_name=_('Electricity 1 (low tariff)') + ) + electricity2 = models.DecimalField( + max_digits=9, decimal_places=3, verbose_name=_('Electricity 2 (high tariff)') + ) + electricity1_returned = models.DecimalField( + max_digits=9, decimal_places=3, verbose_name=_('Electricity 1 returned (low tariff)') + ) + electricity2_returned = models.DecimalField( + max_digits=9, decimal_places=3, verbose_name=_('Electricity 2 returned (high tariff)') + ) # Gas readings are optional/not guaranteed. But need to be zero due to averages. - gas = models.DecimalField(max_digits=9, decimal_places=3, default=0) + gas = models.DecimalField(max_digits=9, decimal_places=3, default=0, verbose_name=_('Gas')) class Meta: default_permissions = tuple() diff --git a/dsmr_stats/services.py b/dsmr_stats/services.py index 773f66779..e1a11b1a1 100644 --- a/dsmr_stats/services.py +++ b/dsmr_stats/services.py @@ -3,7 +3,7 @@ from dateutil.relativedelta import relativedelta from django.db import transaction, connection -from django.db.models.aggregates import Avg, Sum +from django.db.models.aggregates import Avg, Sum, Min, Max from django.core.cache import cache from django.utils import timezone from django.conf import settings @@ -106,7 +106,9 @@ def create_daily_statistics(day): gas=consumption.get('gas', 0), gas_cost=consumption.get('gas_cost', 0), - average_temperature=consumption.get('average_temperature', 0), + lowest_temperature=consumption.get('lowest_temperature'), + highest_temperature=consumption.get('highest_temperature'), + average_temperature=consumption.get('average_temperature'), ) @@ -141,6 +143,12 @@ def create_hourly_statistics(hour_start): HourStatistics.objects.create(**creation_kwargs) +def clear_statistics(): + """ Clears ALL statistics ever generated. """ + DayStatistics.objects.all().delete() + HourStatistics.objects.all().delete() + + def electricity_tariff_percentage(start_date): """ Returns the total electricity consumption percentage by tariff (high/low tariff). """ totals = DayStatistics.objects.filter(day__gte=start_date).aggregate( @@ -204,6 +212,9 @@ def range_statistics(start, end): electricity2_returned=Sum('electricity2_returned'), gas=Sum('gas'), gas_cost=Sum('gas_cost'), + temperature_min=Min('lowest_temperature'), + temperature_max=Max('highest_temperature'), + temperature_avg=Avg('average_temperature'), ) diff --git a/dsmr_stats/tests/test_management_command.py b/dsmr_stats/tests/test_management_command.py new file mode 100644 index 000000000..c32dfee5a --- /dev/null +++ b/dsmr_stats/tests/test_management_command.py @@ -0,0 +1,17 @@ +from unittest import mock + +from django.test.testcases import TestCase +from django.core.management.base import CommandError + +from dsmr_backend.tests.mixins import InterceptStdoutMixin + + +class TestManagementCommand(InterceptStdoutMixin, TestCase): + def test_dsmr_stats_clear_statistics(self): + with self.assertRaisesMessage(CommandError, 'Intended usage is NOT production! Force by using --ack-to-delete-my-data'): + self._intercept_command_stdout('dsmr_stats_clear_statistics') + + with mock.patch('dsmr_stats.services.clear_statistics') as service_mock: + self.assertFalse(service_mock.called) + self._intercept_command_stdout('dsmr_stats_clear_statistics', acked_warning=True) + self.assertTrue(service_mock.called) diff --git a/dsmr_stats/tests/test_services.py b/dsmr_stats/tests/test_services.py index 4b16cca8a..ab33ab010 100644 --- a/dsmr_stats/tests/test_services.py +++ b/dsmr_stats/tests/test_services.py @@ -160,6 +160,27 @@ def test_analyze_service_skip_current_day(self, now_mock): self.assertFalse(DayStatistics.objects.exists()) self.assertFalse(HourStatistics.objects.exists()) + def test_clear_statistics(self): + # Prepare some test data that should be deleted. + target_date = timezone.make_aware(timezone.datetime(2016, 1, 1, 12)) + statistics_dict = self._get_statistics_dict(target_date) + DayStatistics.objects.create(**statistics_dict) + + HourStatistics.objects.create( + hour_start=timezone.now(), + electricity1=1, + electricity2=0, + electricity1_returned=0, + electricity2_returned=0, + ) + self.assertTrue(DayStatistics.objects.exists()) + self.assertTrue(HourStatistics.objects.exists()) + + dsmr_stats.services.clear_statistics() + + self.assertFalse(DayStatistics.objects.exists()) + self.assertFalse(HourStatistics.objects.exists()) + @mock.patch('django.core.cache.cache.clear') @mock.patch('django.utils.timezone.now') def test_analyze_service_clear_cache(self, now_mock, clear_cache_mock): diff --git a/dsmrreader/__init__.py b/dsmrreader/__init__.py index f40fedde6..2d76db6a5 100644 --- a/dsmrreader/__init__.py +++ b/dsmrreader/__init__.py @@ -17,6 +17,6 @@ from django.utils.version import get_version -VERSION = (1, 1, 2, 'final', 0) +VERSION = (1, 2, 0, 'final', 0) __version__ = get_version(VERSION) diff --git a/dsmrreader/archive/clean-install.md b/dsmrreader/archive/clean-install.md index 5b8d55c46..451d91b03 100644 --- a/dsmrreader/archive/clean-install.md +++ b/dsmrreader/archive/clean-install.md @@ -2,7 +2,7 @@ Only required when you didn't have your RaspberryPi installed at all. ### Raspbian ### -Either use the headless version of Raspbian, [netinstall](https://github.com/debian-pi/raspbian-ua-netinst), or the [full Raspbian image](https://www.raspbian.org/RaspbianImages), with graphics stack. You don't need the latter when you intend to only use your decive for DSMR readings. +Either use the headless version of Raspbian, [netinstall](https://github.com/debian-pi/raspbian-ua-netinst), or the [full Raspbian image](https://www.raspbian.org/RaspbianImages), with graphics stack. You don't need the latter when you intend to only use your device for DSMR readings. ### Init ### Power on RaspberryPi and connect using SSH: diff --git a/dsmrreader/locales/nl/LC_MESSAGES/django.mo b/dsmrreader/locales/nl/LC_MESSAGES/django.mo index 8f69edaa5..820c2e252 100644 Binary files a/dsmrreader/locales/nl/LC_MESSAGES/django.mo and b/dsmrreader/locales/nl/LC_MESSAGES/django.mo differ diff --git a/dsmrreader/locales/nl/LC_MESSAGES/django.po b/dsmrreader/locales/nl/LC_MESSAGES/django.po index 7f3b78949..b242b74fa 100644 --- a/dsmrreader/locales/nl/LC_MESSAGES/django.po +++ b/dsmrreader/locales/nl/LC_MESSAGES/django.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: DSMR Reader\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-04-18 20:05+0200\n" -"PO-Revision-Date: 2016-04-18 19:57+0100\n" +"POT-Creation-Date: 2016-05-18 21:10+0200\n" +"PO-Revision-Date: 2016-05-18 21:10+0100\n" "Last-Translator: Dennis Siemensma \n" "Language-Team: Dennis Siemensma \n" "Language: nl\n" @@ -120,11 +120,11 @@ msgstr "Omschrijving" msgid "For your own reference, i.e. the name of your supplier" msgstr "Voor je eigen referentie, bijvoorbeeld de naam van je energieleverancier" -msgid "Electricity 1 price" -msgstr "Elektriciteitstarief 1 (laag)" +msgid "Electricity 1 price (low tariff)" +msgstr "Prijs elektriciteit 1 (daltarief)" -msgid "Electricity 2 price" -msgstr "Elektriciteitstarief 2 (piek)" +msgid "Electricity 2 price (high tariff)" +msgstr "Prijs elektriciteit 2 (piektarief)" msgid "Gas price" msgstr "Gasprijs" @@ -351,8 +351,8 @@ msgstr "Inloggen vereist" msgid "Configuration" msgstr "Configuratie" -msgid "DSMR reader" -msgstr "DSMR-reader" +msgid "DSMR (Dutch Smart Meter Requirements) reader" +msgstr "DSMR (Dutch Smart Meter Requirements) reader" msgid "created by" msgstr "gemaakt door" @@ -378,6 +378,12 @@ msgstr "Alle instellingen" msgid "Setting" msgstr "Instelling" +msgid "This will simply alter the latest backup timestamp displayed above to a week ago." +msgstr "Dit zorgt er simpelweg voor dat het tijdstip van de meest recente back-up een week in het verleden wordt gezet." + +msgid "Schedule new backup now" +msgstr "Plan per direct nieuwe back-up in" + msgid "Watt" msgstr "Watt" @@ -436,13 +442,13 @@ msgid "Day totals" msgstr "Dagtotalen" msgid "Summary of each day. Contains electricity, gas and costs (if applicable)." -msgstr "Samenvatting van elke dag. Bevat electriciteit, gas en gemaakte kosten (wanneer van toepassing)." +msgstr "Samenvatting van elke dag. Bevat elektriciteit, gas en gemaakte kosten (wanneer van toepassing)." msgid "Hour totals" msgstr "Uurtotalen" msgid "Summary of each hour read. Contains electricity and gas (if applicable)." -msgstr "Samenvatting van elk uur. Bevat electriciteit en gas (wanneer van toepassing)." +msgstr "Samenvatting van elk uur. Bevat elektriciteit en gas (wanneer van toepassing)." msgid "Select date range start" msgstr "Selecteer startdatum" @@ -474,6 +480,18 @@ msgstr "Voeg notitie toe voor deze datum" msgid "Energy price" msgstr "Energieprijs" +msgid "Weather" +msgstr "Weergegevens" + +msgid "Min." +msgstr "Min." + +msgid "Max." +msgstr "Max." + +msgid "Avg." +msgstr "Gem." + msgid "Meter positions" msgstr "Meterstanden" @@ -489,6 +507,21 @@ msgstr "Meterstatistieken" msgid "Tracking meter statistics is disabled. Enable this feature in the datalogger settings to view statistics." msgstr "Meterstatistieken worden niet bijgehouden. Schakel dit bij de dataloggerinstellingen in om de statistieken weer te geven." +msgid "Usage statistics" +msgstr "Verbruiksstatistieken" + +msgid "Most common electricity consumption" +msgstr "Veelvoorkomend elektriciteitsverbruik" + +msgid "Average calculated among the top five most common electricity consumption read. This might also be the (minimum) constant electricity consumption in your home." +msgstr "Gemiddeld elektriciteitsverbruik berekend over de vijf meest voorkomende waardes. Dit is vaak ook het (minimale) elektriciteitsverbruik van je woning." + +msgid "Lowest electricity consumption read" +msgstr "Laagst gemeten elektriciteitsverbruik" + +msgid "Highest electricity consumption read" +msgstr "Hoogst gemeten elektriciteitsverbruik" + msgid "Current energy prices" msgstr "Huidige energietarieven" @@ -513,9 +546,6 @@ msgstr "DSMR-reader" msgid "Current version" msgstr "Huidige versie" -msgid "View current release" -msgstr "Bekijk huidige versie" - msgid "Changelog" msgstr "Wijzigingenoverzicht" @@ -553,10 +583,10 @@ msgid "There are too many unprocessed readings. Your backend processachtergrondproces of is deze gecrashed." msgid "Latest electricity consumption tracked" -msgstr "Meest recente electriciteitsverbruik verwerkt" +msgstr "Meest recente elektriciteitsverbruik verwerkt" msgid "It has been a while since electricity consumption was tracked. Your backend process might hang or has been crashed." -msgstr "Het meest recente electriciteitsverbruik is een tijdje geleden verwerkt. Mogelijk hangt het achtergrondproces of is deze gecrashed." +msgstr "Het meest recente elektriciteitsverbruik is een tijdje geleden verwerkt. Mogelijk hangt het achtergrondproces of is deze gecrashed." msgid "Latest gas consumption tracked" msgstr "Meest recente gasverbruik verwerkt" @@ -568,7 +598,7 @@ msgid "Data availability" msgstr "Beschikbaarheid gegevens" msgid "Based on readings until this moment. Electricity usage should be always available. Gas usage and electricity return depend on your home situation." -msgstr "Gebaseerd op verwerkte uitlezingen tot nu toe. Electriciteitsverbruik zou altijd beschikbaar moeten zijn. Gasverbruik en elektriciteitsteruglevering hangen af van je thuissituatie." +msgstr "Gebaseerd op verwerkte metingen tot nu toe. Elektriciteitsverbruik zou altijd beschikbaar moeten zijn. Gasverbruik en elektriciteitsteruglevering hangen af van je thuissituatie." msgid "Data type" msgstr "Soort gegevens" @@ -599,22 +629,49 @@ msgid "Average hourly gas consumed (in %%)" msgstr "Gemiddeld gasverbruik per daguur (in %%)" msgid "Electricity tariff ratio (passed week)" -msgstr "Electriciteitsverbruik piek- en daltarief (afgelopen week)" +msgstr "Elektriciteitsverbruik piek- en daltarief (afgelopen week)" msgid "Electricity tariff ratio (passed month)" -msgstr "Electriciteitsverbruik piek- en daltarief (afgelopen maand)" +msgstr "Elektriciteitsverbruik piek- en daltarief (afgelopen maand)" msgid "Trend & statistics" msgstr "Trends & statistieken" +msgid "Clears all statistics generated. Use this to regenerate them after altering prices." +msgstr "Verwijdert alle (dag/uur)statistieken. Gebruik dit wanneer je de energieprijzen hebt aangepast." + +msgid "Required to acknowledge you that you WILL delete your statistics with this." +msgstr "Verplichte parameter om te bevestigen dat je beseft dat je hiermee (gegenereerde) data verwijdert." + +msgid "Intended usage is NOT production! Force by using --ack-to-delete-my-data" +msgstr "Bedoeld voor gebruik buiten productie. Forceer uitvoer met --ack-to-delete-my-data" + msgid "Note" msgstr "Notitie" msgid "Notes" msgstr "Notities" -msgid "Weather" -msgstr "Weergegevens" +msgid "Date" +msgstr "Datum" + +msgid "Total cost" +msgstr "Totale kosten" + +msgid "Electricity 2 returned (high tariff)" +msgstr "Elektriciteit 2 teruggeleverd (piektarief)" + +msgid "Lowest temperature" +msgstr "Laagste temperatuur" + +msgid "Highest temperature" +msgstr "Hoogste temperatuur" + +msgid "Average temperature" +msgstr "Gemiddelde temperatuur" + +msgid "Hour start" +msgstr "Begintijd uur" msgid "Weather station Arcen" msgstr "Weerstation Arcen" @@ -796,6 +853,18 @@ msgstr "Nederlands" msgid "English" msgstr "Engels" +#~ msgid "DSMR reader" +#~ msgstr "DSMR-reader" + +#~ msgid "Electricity 1 price" +#~ msgstr "Elektriciteitstarief 1 (laag)" + +#~ msgid "Electricity 2 price" +#~ msgstr "Elektriciteitstarief 2 (piek)" + +#~ msgid "View current release" +#~ msgstr "Bekijk huidige versie" + #~ msgid "Deploy" #~ msgstr "Uitrollen" @@ -856,9 +925,6 @@ msgstr "Engels" #~ msgid "Daily gas usage" #~ msgstr "Dagelijks gasverbruik" -#~ msgid "Daily average temperature" -#~ msgstr "Dagelijks temperatuurgemiddelde" - #~ msgid "(in °C)" #~ msgstr "(in °C)" @@ -874,9 +940,6 @@ msgstr "Engels" #~ msgid "Gas cost" #~ msgstr "Gaskosten" -#~ msgid "Total cost" -#~ msgstr "Totale kosten" - #~ msgid "Theme by" #~ msgstr "Thema door" diff --git a/dsmrreader/provisioning/requirements/base.txt b/dsmrreader/provisioning/requirements/base.txt index 4008191f8..aee83365d 100644 --- a/dsmrreader/provisioning/requirements/base.txt +++ b/dsmrreader/provisioning/requirements/base.txt @@ -1,8 +1,8 @@ Django==1.8.12 django-flat-theme==1.1.3 django-solo==1.1.2 -dropbox==6.1 +dropbox==6.2 gunicorn==19.4.5 pyserial==3.0.1 -python-dateutil==2.5.2 -pytz==2016.3 \ No newline at end of file +python-dateutil==2.5.3 +pytz==2016.4 \ No newline at end of file diff --git a/dsmrreader/provisioning/requirements/dev.txt b/dsmrreader/provisioning/requirements/dev.txt index 9b618d895..3421d81cf 100644 --- a/dsmrreader/provisioning/requirements/dev.txt +++ b/dsmrreader/provisioning/requirements/dev.txt @@ -1,4 +1,4 @@ -Sphinx==1.4 +Sphinx==1.4.1 sphinx-autobuild==0.6.0 sphinx-intl==0.9.9 sphinx-rtd-theme==0.1.9 \ No newline at end of file