dsmrreader / dsmr-reader

DSMR-telegram reader & data visualizer for hobbyists. Free for non-commercial use.
https://dsmr-reader.readthedocs.io
Other
463 stars 95 forks source link

⚠️ Foutieve berekeningen in dagtotalen/Archief #1770

Open nickgr6 opened 1 year ago

nickgr6 commented 1 year ago

Description

Beste,

Ik ben in het proces om mijn beeclear te vervangen door een device waarop ik dsmr reader ga draaien. Ter voorbereiding ben ik nu alle historische data aan het migreren mbv de api. Dit lijkt allemaal goed te zijn gegaan.

Toen ik echter de totalen vergeleek tussen beeclear (en vattenfall die gelijk zijn aan beeclear) en de dsmr interface, zag ik verschillen. Ook zie ik inconsistentie in de 'archive' pagina van totalen.

Het volgende toont in de archive voor 2 december: image

De data view voor gasverbruik per uur toont:

    Gas
0:00    0
1:00    0
2:00    0
3:00    0
4:00    0
5:00    0
6:00    0
7:00    0
8:00    0.019
9:00    0.219
10:00   0.598
11:00   0.485
12:00   0.149
13:00   0.112
14:00   0.279
15:00   0.007
16:00   0.044
17:00   0.076
18:00   0.07
19:00   0.026
20:00   0.02
21:00   0.136
22:00   0.083
23:00   0
0:00    0.475

Als ik die optel, kom ik uit op 2.798. Maar de interface toont 2.323. Het lijkt er dus op dat de laatste meting niet wordt meegenomen (0.475). Dus mijn aanname was dat dat uur wellicht bij de volgende dag hoort aangezien de data view 2x 0:00 toont. Als ik echter de volgende dag bekijk zie ik:

    Gas
0:00    0.475
1:00    0
2:00    0
3:00    0
4:00    0
5:00    0
6:00    0
7:00    0
8:00    0.215
9:00    0.24
10:00   0.484
11:00   0.379
12:00   0.106
13:00   0
14:00   0.006
15:00   0.172
16:00   0.119
17:00   0
18:00   0.005
19:00   0.012
20:00   0.358
21:00   0.15
22:00   0.318
23:00   0.043
0:00    0

image Hier komt het totaal van 2.607 echter wel overeen met mijn meting in beeclear/vattenfall en wordt 0.475 van de eerste 0:00 meting dus ook niet meegenomen in de optelsom. Het lijkt er dus op dat die meeting in beide dagen niet wordt meegenomen.

De dag rows in de dsmr_stats_hourstatistics db: 198069,2022-12-02 00:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.000 198070,2022-12-02 01:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.000 198071,2022-12-02 02:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.000 198072,2022-12-02 03:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.000 198073,2022-12-02 04:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.000 198074,2022-12-02 05:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.000 198075,2022-12-02 06:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.000 198076,2022-12-02 07:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.019 198077,2022-12-02 08:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.219 198078,2022-12-02 09:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.598 198079,2022-12-02 10:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.485 198080,2022-12-02 11:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.149 198081,2022-12-02 12:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.112 198082,2022-12-02 13:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.279 198083,2022-12-02 14:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.007 198084,2022-12-02 15:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.044 198085,2022-12-02 16:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.076 198086,2022-12-02 17:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.070 198087,2022-12-02 18:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.026 198088,2022-12-02 19:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.020 198089,2022-12-02 20:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.136 198090,2022-12-02 21:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.083 198091,2022-12-02 22:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.000 198092,2022-12-02 23:00:00.000000 +00:00,0.000,0.000,0.000,0.000,0.475

De daystatistics waardes in de database lijken ook correct: image

Ook het opnieuw runnen (en stats opschonen en weer runnen) van /app/manage.py dsmr_stats_reconstruct_missing_day_statistics blijft hetzelfde resultaat geven.

Gezien dsmr reader al zo'n volwassen product is (complimenten voor alle opties :)!), ga ik er vanuit dat er ergens een fout zit in de migratie oid. Echter lijkt de data in de db correct. Vandaar dat ik toch dit ticket heb aangemaakt. Aanvullend: er worden nog geen live metingen gedaan en verwerkt, dus dat kan niet in de weg zitten.

Enig idee waar het misgaat of wat ik zelf nog verder kan controleren om daar achter te komen?

Alvast bedankt!

DSMR-reader version

5.9

DSMR-reader platform

docker-compose (relevante config):


  postgres:
    image: postgres:15-alpine

  dsmr-reader:
    image: xirixiz/dsmr-reader-docker:latest
    environment:
      - TZ=Europe/Amsterdam
      - DJANGO_TIME_ZONE=Europe/Amsterdam

### Debug info dump

_No response_
StevenM1 commented 10 months ago

Ik heb hetzelfde probleem ervaren. Bij het vergelijken van de jaarstatistieken zoals geregistreerd in DSMR reader, met handmatig bijgehouden meterstanden, bleek dat er een aanzienlijk verschil was in stroom- en gasverbruik (~10% minder gasverbruik in DSMR reader dan op de meterstanden). Hier wordt ook geen gebruik gemaakt van de standaard datalogger met live readings, maar in plaats daarvan injecteer ik zelf de telegramdata in de readings table van de database.

Volgens mij gaat het mis in het berekenen van de consumptions, en specifiek in de manier waarop een tijdsrange wordt gequery'd in consumption_by_range() in dsmr-reader/dsmr_stats/services.py:

    electricity_readings = ElectricityConsumption.objects.filter(
        read_at__gte=start,
        read_at__lt=end,
    ).order_by("read_at")

    gas_readings = GasConsumption.objects.filter(
        read_at__gte=start,
        read_at__lt=end,
    ).order_by("read_at")

Hier query't DSMR alles binnen een tijdsrange, waarbij de eerste reading wordt afgetrokken van de laatste reading om te bepalen wat de consumptie was binnen die range. end en day verschillen 1 uur of 1 dag, afhankelijk van of er een uur- of dagstatistiek wordt berekend. Maar dit kan misgaan: Stel dat je eerste reading van de dag op 00:00 (middernacht) is, en de laatste reading om 23:55, dan wordt dus de reading van 00:00 afgetrokken van de reading van 23:55 om te bepalen hoeveel gas/elektriciteit er is verbruikt op deze dag. En dus worden de laatste 5 minuten van die dag niet meegerekend. Aangezien de jaarstatistieken een optelsom zijn van de day statistieken, kan dit behoorlijk oplopen.

In plaats daarvan werkt het bij mij om de readings binnen consumption_by_range() simpelweg te query'en op read_at__lte in plaats van read_at__lt. Dan neem je ook het laatste interval van de range mee in je metingen. Hiermee komt mijn jaarverbruik zoals geregistreerd in DSMR reader exact overeen met de handmatig bijgehouden meterstanden.

Overigens laat ik create_daily_statistics (dsmr-reader/dsmr_stats/services.py) gewoon de gasmetingen uit consumption returnen (en niet de nieuwe hours_gas_sum; waarom deze daar wordt berekend in plaats van de consumption['gas'] is me niet helemaal duidelijk)

dennissiemensma commented 10 months ago

@StevenM1 bedankt voor je uitgebreide aanvulling. Het specifieke stukje code is al meerdere maken aangepast en weer teruggezet (#1385):

De kern van het hele probleem is uberhaupt die tussentabel in DSMR-reader, de consumption.

Er is sowieso geen garantie dat er een meting is tussen 23:55 en middernacht, wat de huidige opzet in DSMR-reader per definitie dus kan laten "lekken". Eigenlijk wil ik daar van af en die complete tussentabel er uit hebben en alles direct berekenen op de metingen. Hoewel dat niet alles oplost, zou ik dat wel kunnen gebruiken voor de dag/maand/jaar-totalen. En zou het dan in ieder geval beter moeten werken.

Alleen is dat niet te doen qua werkgrootte. Plus dat de huidige situatie onder (unit)tests staat die niet kloppen (want het klopt immers niet), dus die moeten ook over de kop. Het liefste naar een integratietest die meer naar het eindresultaat kijkt, voor DSMR v3, v4 en v5 meters.

En hoewel ik wel neig om weer terug te gaan van de situatie van 2019-2021 (dus jouw voorstel), voor nu, weet ik niet wat de gevolgen daarvan zijn. Een verbetering tov toen is wel dat er in de laatste DSMR-reader versies bij de dagtotalen ook de meterstanden opgeslagen worden. Zodat die altijd gebruikt kunnen worden voor ofwel een fix met terugwerkende kracht of gewoon als "waarheid".

Dus veel keuzes en veel wegen.

StevenM1 commented 9 months ago

Ik snap je overwegingen, en ben het er helemaal mee eens dat de beste oplossing (maar waarschijnlijk wel veel werk) zou zijn om gewoon direct de readings te query'en en aan de hand daarvan de consumption te berekenen.

Wat ik niet helemaal begrijp is wat de reden is geweest om van lte naar lt te gaan; ik kan iig zelf niet zo goed bedenken in welke situatie dat een betere benadering zou opleveren dan lte. Maar ik heb niet de hele commit history gelezen en ken de situatie van 2021 niet, allicht was er een goede reden voor.

Zonder direct de tussentabellen eruit te gooien, lijkt het mij dat de meeste accurate benadering is om een range te pakken (zeg, 24 uur), en dan de eerste meting ná die range te gebruiken als eindpunt. Dat is iets complexer dan de lte die ik eerder voorstelde, omdat het vermoedelijk echt een tweede query nodig heeft, inderdaad voor de situatie dat geen reading voldoet aan de 'equal' conditie (dus dat er bijv. geen reading is van middernacht de volgende dag). Bij mij lijkt het goed te gaan omdat er altijd wel een reading is die exact overeenkomt met het eindpunt v/d range (ook omdat de timestamps van de readings in de database iets te lijken zijn opgeschoond t.o.v. de ruwe metingen in de telegrams), maar dat hoeft niet altijd het geval te zijn.

Indien er géén reading is op exact het eind van de range, lijkt het me dat de eerstvolgende reading de meest accurate benadering daarvan is. Het kan dan wel zijn dat die reading een tijdje na de gespecificeerde range is (hypothetisch, als je slechts om het uur een meting hebt, kan het zo zijn dat er op dag t een laatste meting is om 23:00, en op dag t+1 pas een om 01:00). In dat geval moet er hoe dan ook een keuze worden gemaakt waaraan de consumptie in het interval 23:00-01:00 moet worden toebedeeld (tenzij je gaat interpoleren o.i.d. maar dat lijkt me het onnodig complex maken). Altijd de eerstvolgende reading pakken is in ieder geval consistent.

Maar goed - ik weet niet alles van de structuur van DSMR reader, en weet dat dit soort aanpassingen riskant zijn dus dat ik het begrijp dat je voorzichtig bent in het aanpassen van dit soort dingen. Maar misschien heb je iets aan wat ruggespraak.

dennissiemensma commented 9 months ago

Bedankt voor je aanvulling. Het nadeel is dat ik ook niet meer exact weet welke wijziging waarvoor is, ondanks dat ik redelijk probeer om referenties in de commit messages te zetten. Alleen weet ik niet de echte achterliggende reden.

Wat betreft de edge-cases bij missende data, daar kan DSMR-reader sowieso niets in betekenen, dus ik ben het met je eens dat buiten de scope blijft.

Inmiddels is wel duidelijk dat de wijziging hoe dan ook ingrijpend gaat worden, dus dat scheelt wat in de voorzichtigheid. Ook omdat er inmiddels ook weer qya Python/Django versies gebumped moeten worden, dus er komt sowieso een nieuwe major DSMR-reader versie uit, die mag afwijken van de vorige 5.x versie (mits data forward compatible, maar dat is zelden een issue).

Ik denk dat uiteindelijk het slopen van de tussentabellen een hoop code scheelt, maar ook wel aardig wat kan raken qua API, MQTT, GUI, etc. Als in dat die data er straks niet meer is. Maar dat is dan maar zo. Helemaal omdat het verschil dusdanig groot is (icm hoge prijzen) dat het niet meer een goede benadering is van wat men verbruikt. Een kleine afwijking vond ik nog acceptabel, maar klein is het niet meer helaas.

Rudios81 commented 9 months ago

Allereest moet ik toegeven dat ik niet de gehele historie van gesprek hier gelezen heb, maar ik stuit ook op verschillen in dagelijks gas verbruik. Wat mij met name opvalt is dat het dagelijkse gebruik binnen DSMR berekend wordt dmv de uurgetallen die uit de meter komen. Vanuit DSMR maak ik gebruik van de mogelijkheid om data naar een influxDB te pushen. Daarin wordt alleen het cumulatieve getal van de gasmeter doorgestuurd, en dus in influxDB bewaard. Nu, als ik vanuit die cumulatieve getallen een dagelijks getal bereken, komt dat niet overeen met hetgeen er door DSMR wordt berekend. Dat zou er dus eigenlijk op neer komen dat de uurgetallen die de meter afgeeft niet accuraat zijn??? Uiteindelijk zijn de € die er mee gemoeid gaan afhankelijk van de cumulatieve teller van de meter, daar wordt immers op afgerekend.

dennissiemensma commented 9 months ago

@Rudios81 je kunt er van uitgaan dat de gegevens uit de meter kloppen. De bug zit in de manier van berekenen in DSMR-reader