Skip to content

Commit e59ba5d

Browse files
"All time low" implementeren #535
1 parent 4aba10e commit e59ba5d

File tree

10 files changed

+195
-25
lines changed

10 files changed

+195
-25
lines changed

docs/changelog.rst

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ v1.26.0 - 2018-xx-xx
2323
**Tickets resolved in this release:**
2424

2525
- [`#xxxxxxxxxxxxxxxxxx <https://github.com/dennissiemensma/dsmr-reader/issues/xxxxxxxxxxxxxx>`_] yyyyyyyyyyyyyyyyyyyy
26+
- [`#535 <https://github.com/dennissiemensma/dsmr-reader/issues/535>`_] "All time low" implementeren
2627
- [`#536 <https://github.com/dennissiemensma/dsmr-reader/issues/536>`_] Retentie-verbeteringen
2728

2829

dsmr_backend/mixins.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,8 @@ def __init__(self, *args, **kwargs):
140140
super(ReadOnlyAdminModel, self).__init__(*args, **kwargs)
141141
self.readonly_fields = [x.name for x in self.model._meta.get_fields()]
142142

143-
def has_view_permission(self, request, obj=None):
144-
return True
145-
146143
def has_change_permission(self, request, obj=None):
147-
return False
144+
return True
148145

149146
def has_add_permission(self, request, obj=None):
150147
return False

dsmr_frontend/templates/dsmr_frontend/statistics.html

+34
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,40 @@
198198
</td>
199199
</tr>
200200
{% endif %}
201+
202+
{% if electricity_statistics.lowest_usage_l1_value %}
203+
<tr>
204+
<td class="col-md-6">{% trans "Lowest usage (L1+)" %}</td>
205+
<td class="col-md-6">
206+
<span class="badge bg-red">
207+
<i class="fas fa-bolt"></i> &nbsp; {{ electricity_statistics.lowest_usage_l1_value }} &nbsp;
208+
{% trans "Watt" %} &nbsp; - &nbsp; {{ electricity_statistics.lowest_usage_l1_timestamp }}
209+
</span>
210+
</td>
211+
</tr>
212+
{% endif %}
213+
{% if electricity_statistics.lowest_usage_l2_value %}
214+
<tr>
215+
<td class="col-md-6">{% trans "Lowest usage (L2+)" %}</td>
216+
<td class="col-md-6">
217+
<span class="badge bg-red">
218+
<i class="fas fa-bolt"></i> &nbsp; {{ electricity_statistics.lowest_usage_l2_value }} &nbsp;
219+
{% trans "Watt" %} &nbsp; - &nbsp; {{ electricity_statistics.lowest_usage_l2_timestamp }}
220+
</span>
221+
</td>
222+
</tr>
223+
{% endif %}
224+
{% if electricity_statistics.lowest_usage_l3_value %}
225+
<tr>
226+
<td class="col-md-6">{% trans "Lowest usage (L3+)" %}</td>
227+
<td class="col-md-6">
228+
<span class="badge bg-red">
229+
<i class="fas fa-bolt"></i> &nbsp; {{ electricity_statistics.lowest_usage_l3_value }} &nbsp;
230+
{% trans "Watt" %} &nbsp; - &nbsp; {{ electricity_statistics.lowest_usage_l3_timestamp }}
231+
</span>
232+
</td>
233+
</tr>
234+
{% endif %}
201235

202236
{% if electricity_statistics.highest_return_l1_value %}
203237
<tr>
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Generated by Django 2.0.9 on 2018-10-24 17:19
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('dsmr_stats', '0012_electricity_statistics'),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name='electricitystatistics',
15+
name='lowest_usage_l1_timestamp',
16+
field=models.DateTimeField(blank=True, default=None, null=True, verbose_name='Timestamp of lowest usage on L1+'),
17+
),
18+
migrations.AddField(
19+
model_name='electricitystatistics',
20+
name='lowest_usage_l1_value',
21+
field=models.DecimalField(blank=True, decimal_places=3, default=None, max_digits=9, null=True, verbose_name='Lowest usage on L1+ (in kWh)'),
22+
),
23+
migrations.AddField(
24+
model_name='electricitystatistics',
25+
name='lowest_usage_l2_timestamp',
26+
field=models.DateTimeField(blank=True, default=None, null=True, verbose_name='Timestamp of lowest usage on L2+'),
27+
),
28+
migrations.AddField(
29+
model_name='electricitystatistics',
30+
name='lowest_usage_l2_value',
31+
field=models.DecimalField(blank=True, decimal_places=3, default=None, max_digits=9, null=True, verbose_name='Lowest usage on L2+ (in kWh)'),
32+
),
33+
migrations.AddField(
34+
model_name='electricitystatistics',
35+
name='lowest_usage_l3_timestamp',
36+
field=models.DateTimeField(blank=True, default=None, null=True, verbose_name='Timestamp of lowest usage on L3+'),
37+
),
38+
migrations.AddField(
39+
model_name='electricitystatistics',
40+
name='lowest_usage_l3_value',
41+
field=models.DecimalField(blank=True, decimal_places=3, default=None, max_digits=9, null=True, verbose_name='Lowest usage on L3+ (in kWh)'),
42+
),
43+
]

dsmr_stats/models/statistics.py

+21
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,15 @@ class ElectricityStatistics(SingletonModel):
126126
highest_return_l3_timestamp = models.DateTimeField(
127127
null=True, blank=True, default=None, verbose_name=_('Timestamp of highest return on L3-')
128128
)
129+
lowest_usage_l1_timestamp = models.DateTimeField(
130+
null=True, blank=True, default=None, verbose_name=_('Timestamp of lowest usage on L1+')
131+
)
132+
lowest_usage_l2_timestamp = models.DateTimeField(
133+
null=True, blank=True, default=None, verbose_name=_('Timestamp of lowest usage on L2+')
134+
)
135+
lowest_usage_l3_timestamp = models.DateTimeField(
136+
null=True, blank=True, default=None, verbose_name=_('Timestamp of lowest usage on L3+')
137+
)
129138

130139
highest_usage_l1_value = models.DecimalField(
131140
max_digits=9, decimal_places=3, null=True, blank=True, default=None,
@@ -151,6 +160,18 @@ class ElectricityStatistics(SingletonModel):
151160
max_digits=9, decimal_places=3, null=True, blank=True, default=None,
152161
verbose_name=_('Highest return on L3- (in kWh)')
153162
)
163+
lowest_usage_l1_value = models.DecimalField(
164+
max_digits=9, decimal_places=3, null=True, blank=True, default=None,
165+
verbose_name=_('Lowest usage on L1+ (in kWh)')
166+
)
167+
lowest_usage_l2_value = models.DecimalField(
168+
max_digits=9, decimal_places=3, null=True, blank=True, default=None,
169+
verbose_name=_('Lowest usage on L2+ (in kWh)')
170+
)
171+
lowest_usage_l3_value = models.DecimalField(
172+
max_digits=9, decimal_places=3, null=True, blank=True, default=None,
173+
verbose_name=_('Lowest usage on L3+ (in kWh)')
174+
)
154175

155176
def export(self):
156177
""" Converts the data in to ready to use format. """

dsmr_stats/services.py

+26-11
Original file line numberDiff line numberDiff line change
@@ -269,23 +269,38 @@ def year_statistics(target_date):
269269

270270
def update_electricity_statistics(reading):
271271
""" Updates the ElectricityStatistics records. """
272-
MAP = {
273-
# Reading field: Stats record field.
274-
'phase_currently_delivered_l1': 'highest_usage_l1',
275-
'phase_currently_delivered_l2': 'highest_usage_l2',
276-
'phase_currently_delivered_l3': 'highest_usage_l3',
277-
'phase_currently_returned_l1': 'highest_return_l1',
278-
'phase_currently_returned_l2': 'highest_return_l2',
279-
'phase_currently_returned_l3': 'highest_return_l3',
272+
MAPPING = {
273+
# Stats record field: Reading field.
274+
'highest_usage_l1': 'phase_currently_delivered_l1',
275+
'highest_usage_l2': 'phase_currently_delivered_l2',
276+
'highest_usage_l3': 'phase_currently_delivered_l3',
277+
'highest_return_l1': 'phase_currently_returned_l1',
278+
'highest_return_l2': 'phase_currently_returned_l2',
279+
'highest_return_l3': 'phase_currently_returned_l3',
280+
281+
'lowest_usage_l1': 'phase_currently_delivered_l1',
282+
'lowest_usage_l2': 'phase_currently_delivered_l2',
283+
'lowest_usage_l3': 'phase_currently_delivered_l3',
280284
}
281285
stats = ElectricityStatistics.get_solo()
282286
dirty = False
283287

284-
for reading_field, stat_field in MAP.items():
288+
for stat_field, reading_field in MAPPING.items():
285289
reading_value = getattr(reading, reading_field) or 0
286-
highest_value = getattr(stats, '{}_value'.format(stat_field)) or 0
290+
top_value = getattr(stats, '{}_value'.format(stat_field)) or 0
287291

288-
if reading_value and Decimal(reading_value) > Decimal(highest_value):
292+
if top_value == 0 and stat_field.startswith('lowest'):
293+
top_value = 9999999
294+
295+
reading_value = Decimal(str(reading_value))
296+
top_value = Decimal(str(top_value))
297+
298+
if not reading_value:
299+
continue
300+
301+
# Depending on what we track, compare to the current high (or low).
302+
if (stat_field.startswith('lowest') and reading_value < top_value) or \
303+
(stat_field.startswith('highest') and reading_value > top_value):
289304
dirty = True
290305
setattr(stats, '{}_value'.format(stat_field), reading_value)
291306
setattr(stats, '{}_timestamp'.format(stat_field), reading.timestamp)

dsmr_stats/tests/test_services.py

+41-9
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from dsmr_datalogger.models.reading import DsmrReading
1212
import dsmr_backend.services
1313
import dsmr_stats.services
14+
from dsmr_consumption.models.settings import ConsumptionSettings
1415

1516

1617
class TestServices(InterceptStdoutMixin, TestCase):
@@ -41,12 +42,8 @@ def test_analyze_service(self, now_mock):
4142
now_mock.return_value = timezone.make_aware(timezone.datetime(2015, 12, 12, hour=1, minute=5))
4243
dsmr_stats.services.analyze()
4344

44-
if dsmr_backend.services.get_capabilities(capability='gas'):
45-
self.assertEqual(DayStatistics.objects.count(), 0)
46-
self.assertEqual(HourStatistics.objects.count(), 0)
47-
else:
48-
self.assertEqual(DayStatistics.objects.count(), 0)
49-
self.assertEqual(HourStatistics.objects.count(), 0)
45+
self.assertEqual(DayStatistics.objects.count(), 0)
46+
self.assertEqual(HourStatistics.objects.count(), 0)
5047

5148
# Still too soon.
5249
now_mock.return_value = timezone.make_aware(timezone.datetime(2015, 12, 13, hour=1, minute=5))
@@ -471,6 +468,8 @@ def test_update_electricity_statistics(self, now_mock):
471468

472469
@mock.patch('django.utils.timezone.now')
473470
def test_update_electricity_statistics_single_phase(self, now_mock):
471+
ConsumptionSettings.objects.update(compactor_grouping_type=ConsumptionSettings.COMPACTOR_GROUPING_BY_READING)
472+
474473
now_mock.return_value = timezone.make_aware(timezone.datetime(2018, 1, 1, hour=0))
475474
stats = ElectricityStatistics.get_solo()
476475
self.assertIsNone(stats.highest_usage_l1_value)
@@ -479,6 +478,9 @@ def test_update_electricity_statistics_single_phase(self, now_mock):
479478
self.assertIsNone(stats.highest_return_l1_value)
480479
self.assertIsNone(stats.highest_return_l2_value)
481480
self.assertIsNone(stats.highest_return_l3_value)
481+
self.assertIsNone(stats.lowest_usage_l1_value)
482+
self.assertIsNone(stats.lowest_usage_l2_value)
483+
self.assertIsNone(stats.lowest_usage_l3_value)
482484

483485
# This has to differ, to make sure the right timestamp is used.
484486
reading_timestamp = timezone.now()
@@ -504,16 +506,46 @@ def test_update_electricity_statistics_single_phase(self, now_mock):
504506
self.assertEqual(stats.highest_usage_l1_value, Decimal('0.100'))
505507
self.assertEqual(stats.highest_usage_l2_value, None)
506508
self.assertEqual(stats.highest_usage_l3_value, None)
507-
self.assertEqual(stats.highest_return_l1_value, Decimal('1.100'))
508-
self.assertEqual(stats.highest_return_l2_value, None)
509-
self.assertEqual(stats.highest_return_l3_value, None)
510509
self.assertEqual(stats.highest_usage_l1_timestamp, reading_timestamp)
511510
self.assertEqual(stats.highest_usage_l2_timestamp, None)
512511
self.assertEqual(stats.highest_usage_l3_timestamp, None)
512+
513+
self.assertEqual(stats.highest_return_l1_value, Decimal('1.100'))
514+
self.assertEqual(stats.highest_return_l2_value, None)
515+
self.assertEqual(stats.highest_return_l3_value, None)
513516
self.assertEqual(stats.highest_return_l1_timestamp, reading_timestamp)
514517
self.assertEqual(stats.highest_return_l2_timestamp, None)
515518
self.assertEqual(stats.highest_return_l3_timestamp, None)
516519

520+
self.assertEqual(stats.lowest_usage_l1_value, Decimal('0.100'))
521+
self.assertEqual(stats.lowest_usage_l2_value, None)
522+
self.assertEqual(stats.lowest_usage_l3_value, None)
523+
self.assertEqual(stats.lowest_usage_l1_timestamp, reading_timestamp)
524+
self.assertEqual(stats.lowest_usage_l2_timestamp, None)
525+
self.assertEqual(stats.lowest_usage_l3_timestamp, None)
526+
527+
# Test a new low.
528+
reading2 = DsmrReading.objects.create(
529+
timestamp=reading_timestamp + timezone.timedelta(seconds=10),
530+
electricity_delivered_1=0,
531+
electricity_returned_1=0,
532+
electricity_delivered_2=0,
533+
electricity_returned_2=0,
534+
electricity_currently_delivered=0.6,
535+
electricity_currently_returned=1.6,
536+
phase_currently_delivered_l1=0.05,
537+
phase_currently_returned_l1=1.0,
538+
)
539+
dsmr_stats.services.update_electricity_statistics(reading=reading2)
540+
541+
stats = ElectricityStatistics.get_solo()
542+
self.assertEqual(stats.highest_usage_l1_value, Decimal('0.100'))
543+
self.assertEqual(stats.highest_usage_l1_timestamp, reading_timestamp)
544+
self.assertEqual(stats.highest_return_l1_value, Decimal('1.100'))
545+
self.assertEqual(stats.highest_return_l1_timestamp, reading_timestamp)
546+
self.assertEqual(stats.lowest_usage_l1_value, Decimal('0.050'))
547+
self.assertEqual(stats.lowest_usage_l1_timestamp, reading2.timestamp)
548+
517549

518550
class TestServicesWithoutGas(TestServices):
519551
fixtures = ['dsmr_stats/electricity-consumption.json']

dsmrreader/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@
1717
from django.utils.version import get_version
1818

1919

20-
VERSION = (1, 26, 0, 'beta', 1)
20+
VERSION = (1, 26, 0, 'beta', 2)
2121

2222
__version__ = get_version(VERSION)
682 Bytes
Binary file not shown.

dsmrreader/locales/nl/LC_MESSAGES/django.po

+27
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,15 @@ msgstr "Hoogste verbruik (L2+)"
850850
msgid "Highest usage (L3+)"
851851
msgstr "Hoogste verbruik (L3+)"
852852

853+
msgid "Lowest usage (L1+)"
854+
msgstr "Laagste verbruik (L1+)"
855+
856+
msgid "Lowest usage (L2+)"
857+
msgstr "Laagste verbruik (L2+)"
858+
859+
msgid "Lowest usage (L3+)"
860+
msgstr "Laagste verbruik (L3+)"
861+
853862
msgid "Highest return (L1-)"
854863
msgstr "Hoogste teruglevering (L1-)"
855864

@@ -1648,6 +1657,15 @@ msgstr "Moment van hoogste teruglevering op L2-"
16481657
msgid "Timestamp of highest return on L3-"
16491658
msgstr "Moment van hoogste teruglevering op L3-"
16501659

1660+
msgid "Timestamp of lowest usage on L1+"
1661+
msgstr "Moment van laagste verbruik op L1+"
1662+
1663+
msgid "Timestamp of lowest usage on L2+"
1664+
msgstr "Moment van laagste verbruik op L2+"
1665+
1666+
msgid "Timestamp of lowest usage on L3+"
1667+
msgstr "Moment van laagste verbruik op L3+"
1668+
16511669
msgid "Highest usage on L1+ (in kWh)"
16521670
msgstr "Hoogste verbruik op L1+ (in kWh)"
16531671

@@ -1666,6 +1684,15 @@ msgstr "Hoogste teruglevering op L2- (in kWh)"
16661684
msgid "Highest return on L3- (in kWh)"
16671685
msgstr "Hoogste teruglevering op L3- (in kWh)"
16681686

1687+
msgid "Lowest usage on L1+ (in kWh)"
1688+
msgstr "Laagste verbruik op L1+ (in kWh)"
1689+
1690+
msgid "Lowest usage on L2+ (in kWh)"
1691+
msgstr "Laagste verbruik op L2+ (in kWh)"
1692+
1693+
msgid "Lowest usage on L3+ (in kWh)"
1694+
msgstr "Laagste verbruik op L3+ (in kWh)"
1695+
16691696
msgid "Buienradar"
16701697
msgstr "Buienradar"
16711698

0 commit comments

Comments
 (0)