Liebe Community,
für ein paar mit dem SQL-Adapter geloggte Datenpunkte möchte ich den Mittelwert über eine definierte Zeitspanne berechnen. Das folgende Beispielscript berechnet die mittlere Anwesenheit (in %, wenn man meanval * 100 nimmt) während der letzten 48 Stunden und tut dies auch korrekt:
async function getMeanValFromSQL(datapoint, table, t_beg)
{
var Query = 'SELECT ts,val FROM iobroker.'+table+' WHERE id IN (SELECT id FROM iobroker.datapoints WHERE name="'+datapoint+'") and (ts>'+t_beg+' or ts = (SELECT MAX(ts) FROM iobroker.'+table+' WHERE id IN (SELECT id FROM iobroker.datapoints WHERE name="'+datapoint+'") AND ts <= '+t_beg+'))';
var t_end = Date.now();
var meanval = 0;
sendTo('sql.0', 'query', Query, function (result) {
if (result.error) {
console.error(result.error);
} else {
// Berechne Mittelwert
var rs = result.result;
var timespan = t_end - t_beg;
for(var i = 0; i<rs.length; i++)
{
var sec_cur = 0;
if (i==0){
if(rs.lenght == 1){
sec_cur = t_end - t_beg;
}else{
sec_cur = rs[i+1].ts - t_beg;
}
}else if(i == rs.length-1){
sec_cur = t_end - rs[i].ts;
}else{
sec_cur = rs[i+1].ts - rs[i].ts;
}
meanval += rs[i].val*sec_cur/timespan;
}
log("Mittelwert nested: "+meanval);
}
}
);
//await sleep(30)
log("Mittelwert: "+meanval);
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
log("Start");
getMeanValFromSQL("javascript.0.Eigene_Datenpunkte.Presence", "ts_bool", Date.now()-(2*24*60*60*1000));
log("Ende");
Problem ist nur: Die (anonyme) callback-Funktion läuft natürlich asynchron. Deshalb kann die Hauptfunktion getMeanValFromSQL mit dem Mittelwert zunächst nicht weiterarbeiten, versucht das aber.
Logausgabe des obigen Scripts:
08:44:16.081 info javascript.0 (655) script.js.Test.DatabaseTest: Start
08:44:16.082 info javascript.0 (655) script.js.Test.DatabaseTest: Ende
08:44:16.082 info javascript.0 (655) script.js.Test.DatabaseTest: registered 0 subscriptions and 0 schedules
08:44:16.083 info javascript.0 (655) script.js.Test.DatabaseTest: Mittelwert: 0
08:44:16.131 info javascript.0 (655) script.js.Test.DatabaseTest: Mittelwert nested: 0.6609056365740742
Wenn ich die sleep-Zeile (38) aktiviere, funktioniert es:
08:53:01.142 info javascript.0 (655) script.js.Test.DatabaseTest: Start
08:53:01.144 info javascript.0 (655) script.js.Test.DatabaseTest: Ende
08:53:01.144 info javascript.0 (655) script.js.Test.DatabaseTest: registered 0 subscriptions and 0 schedules
08:53:01.176 info javascript.0 (655) script.js.Test.DatabaseTest: Mittelwert nested: 0.6609056385364256
08:53:01.176 info javascript.0 (655) script.js.Test.DatabaseTest: Mittelwert: 0.6609056385364256
Das ist natürlich keine Lösung, denn im Vorhinein weiß man nicht, wie lange die callback function benötigt, um ihr Ergebnis zu berechnen.
Deshalb möchte ich auf die Abarbeitung der callback function warten und dann in der Hauptfunktion weitermachen. Geht das irgendwie?
Einen Umweg über Datenpunkte will ich nicht gehen, um die Funktion universell und skalierbar zu halten (Später soll die Funktion aus einer Schleife heraus aufgerufen werden und Resultate für verschiedene Zeitspannen in ein Array speichern).
Viele Grüße und besten Dank
ceram