[vz-dev] Aggregationsmode "DELTA"

vz at stromtarif-24.de vz at stromtarif-24.de
Sun Nov 3 10:36:04 CET 2013


Meine Antwort ist wohl verloren gegangen, daher hier nochmal.

 

Hab von Github noch keinen echten Plan daher Code anbei...

 

Src/Buffer.cpp (ab Zeile 136):

 

else if(_aggmode == DELTA) {

                Reading *latest=NULL;

                double aggvalue=0;

                double deltavalue=0;

                for(iterator it = _sent.begin(); it != _sent.end(); it++) {

                        if(! it->deleted()) {

                                if(!latest) {

                                        latest=&*it;

                                        aggvalue=it->value();

                                }

                                if(aggvalue > it->value()) {

                                        deltavalue=aggvalue-it->value();

                                } else {

                                        deltavalue=it->value()-aggvalue;

                                }

                                if(deltavalue <
abs((aggvalue/100.0*_deltathreshold)) && &*it != latest) {

                                        it->mark_delete();

                                } else {

                                        latest=&*it;

                                        aggvalue=it->value();

                                        print(log_debug, "NEW VALUE %f @
%f", "DELTA", it->value(),it->tvtod());

                                }

                        }

                }

        }

 

Src/Channel.cpp (ab Zeile 64):

                const char *aggmode_str = optlist.lookup_string(pOptions,
"aggmode");

                double deltathreshold = atof(optlist.lookup_string(pOptions,
"deltathreshold"));

                if(strcasecmp(aggmode_str,"max")==0 ) {

                        _buffer->set_aggmode(Buffer::MAXIMUM);

                } else if( strcasecmp(aggmode_str,"avg")==0 ) {

                        _buffer->set_aggmode(Buffer::AVG);

                } else if( strcasecmp(aggmode_str,"sum")==0 ) {

                        _buffer->set_aggmode(Buffer::SUM);

                } else if( strcasecmp(aggmode_str,"delta")==0 ) {

                        _buffer->set_aggmode(Buffer::DELTA);

                        _buffer->set_deltathreshold(deltathreshold);

                } else if( strcasecmp(aggmode_str,"none")==0 ) {

                        _buffer->set_aggmode(Buffer::NONE);

                } else {

                        throw vz::VZException("Aggmode unknown.");

                }

 

Includes/Buffer.hpp

Zeile 44: enum aggmode { NONE,MAXIMUM,AVG,SUM,DELTA }; Zeile 73: inline void
set_deltathreshold(double deltathreshold) {_deltathreshold=deltathreshold;}
Zeile 80: double _deltathreshold;

 

Und in der vzlogger.conf sieht das bei mir so aus:

"meters" : [{

        "enabled" : true,       /* disabled meters will be ignored */

        "protocol" : "sml",     /* see 'vzlogger -h' for list of available
protocols */

        "device" : "/dev/ttyUSB0",

        "aggtime" : 30,

        "channels": [{

                "uuid" : "xxx",

                "middleware" : "http://xxx/vz/htdocs/middleware.php",

                "identifier" : "1-0:16.7.0", /*Haus Bezug Leistung*/

                "aggmode" : "DELTA",

                "deltathreshold" : "5"

                }]

        }, {

        "enabled" : true,       /* disabled meters will be ignored */

        "protocol" : "sml",     /* see 'vzlogger -h' for list of available
protocols */

        "device" : "/dev/ttyUSB1",

        "aggtime" : 30,

        "channels": [{

                "uuid" : "xxx",

                "middleware" : "http://xxx/vz/htdocs/middleware.php",

                "identifier" : "1-0:16.7.0", /*Solarerzeugung Leistung*/

                "aggmode" : "DELTA",

                "deltathreshold" : "5"

                }]

         }]

}

 

Entscheidend ist, dass innerhalb eines Aggregationszeitraumes mind. 1 Wert
geschrieben wird. Zur Zeit schreibe ich immer den ersten Wert plus die
Veränderten in die DB.

Auf diese Weise lässt sich die Datenmenge reduzieren und die Unschärfe (in
der Darstellung) beschränkt sich auf den Agg-Zeitraum.

 

 

Ich denke jetzt nochmal laut...

 

2013/10/28 Andreas Goetz <cpuidle at gmail.com>

Moin,

 

2013/10/28 Thorben Thuermer <r00t at constancy.org>

...

 

> Im Ergebnis führt das dazu, dass das FE hässliche "Rampen" an den Stellen
> anzeigt wo von 0-Werten (bzw. Stellen in der DB mit längeren Intervallen)
> wieder auf Daten übergegangen wird.

beschraenkt sich das problem nicht drauf, jeweils die erste UND die letzte
null drinzulassen?
wenn du die letzte loescht, kann die middleware halt nichtmehr sagen, in
welchem zeitraum die naechste aenderung stattgefunden hat,
und verteilt sie halt auf den gesamten zeitraum seit dem letzten wert.

 

Schon getestet- tut es leider nicht. Das Problem ist "so gross", wie Tupel
zusammengezählt werden. Wenn z.B. 2 Tupel am Ende vom Vortag aus 0 und x auf
x/2 aggregiert werden und die ersten beiden Tupel vom Foleetag (0 und y) auf
y/2 aggregiert, dann bedeutet das schlimmstenfalls eine Rampe von x/2 bis
y/2 ohne dass die 0 jeweils im FE angezeigt wird. Je mehr Tupel aggegiert
werden desto größer die Abweichung.

 

Das Problem ist dass wir im Moment (wenn das FT tupels=xyz übergibt) Pakete
schnüren. Seit dem entsprechenden Patch macht das die Datenbank:

    $sql = 'SELECT MAX(aggregate.timestamp) AS timestamp,
SUM(aggregate.value) AS value, COUNT(aggregate.value) AS count '.
           'FROM ('.
           '    SELECT timestamp, value, @row:=@row+1 AS row '.
           '     FROM data WHERE channel_id=?' . $sqlTimeFilter . 
           ') AS aggregate '.
           'GROUP BY row DIV ' . $packageSize .' '.
           'ORDER BY timestamp ASC';
 

In Griff kriegen liesse sich das nur wenn das FE einen irgendwie einen
Hinweis bekommen wird dass zwischendurch die 0 "steht"  und die Daten
ausgedünnt sind.

 

Was spräche denn jetzt dagegen, stattdessen äquidistante Stücke zu
schneiden, also nach timestamp DIV $packageSize zu gruppieren? und den
entsprechenden Timestamp im Select hochzuzählen? Das Ganze noch mit IFNULL
Statements ergänzt sollten wir in der Lage sein, fehlende (Null-)Werte zu
ergänzen. Performance to be tested.

Dann besteht natürlich wieder die Gefahr, dass wir zwischen zwei
Zählerwerten eine Null erfinden falls sich da kein weiterer Messwert
anfindet- Tuples darf also nicht granularer werden als Messwerte wirklich
vorliegen.

Wär hätte Lust einen Prototyp zu bauen und Performance zu testen??

vg

Andreas 

 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://demo.volkszaehler.org/pipermail/volkszaehler-dev/attachments/20131103/c6203224/attachment-0001.html>


More information about the volkszaehler-dev mailing list