Probleme in Datendarstellung mit (High)-Charts

Hallo,

hab da ein Problem beim Darstellen der Verbrauchsdaten meiner Wärmepumpe.
Siehe screenshot:

Stelle (hier) mittels Highcharts den Stromverbrauch meiner Wärmepumpe dar. Messen tue ich es mit einem Eltako-Drehstromzähler den ich via MBUS auslesen (den jeweiligen Zählerstand, nicht die pulse…).
Wenn mein MBus mal für einen längen Zeitraum nicht läuft - also keine Werte bestimmt werden können (dann vermutlich auch nicht geloggt da keine Änderung) - stellt er im Chart beim ersten wieder verfügbaren Meßwert eine entsprechend großen Verbauch (kumulativ) dar. Damit wird im Diagramm suggeriert an diesem Tag besonders viel verbraucht zu haben (ist aber natürlich nur die summe seit dem letzten gemessenen Wer).

Kann mir da jemand auf dei Sprünge helfen, damit es so im Diagramm nicht aussieht (außer den Tipp, dass der MBUS-Zähler kontinuierlich online sein sollte :wink:

Gruß
hardlog

Abend!

Mal laut gedacht…du könntest die Werte auf „Plausibilität“ prüfen. Also wenn ein Wert viel zu hoch ist, dann „reset auf 0“ oder einen anderen Wert/Zeitraum nehmen?

Oder prüfen, wann keine Daten kommen und diese Zeiträume dann abgleichen/ignorieren oder sowas in der Richtung?!

Grüße,
Chris

hmmm,

ja ich könnte für den gewünschten Zeitraum die geloggten Daten per script durchgehen und ggf. anpassen.
Ich hatte aber irgendwie gehofft es mit boardeigenen Mitteln erledigen lassen zu können.

Ich dachte, wenn ich per AC_GetAggregatedValues mit z.B. täglicher Aggregationsstufe tatsächlich die Differenz von einem Tag bekomme und nicht vom Tag des zuletzt geloggten Wertes. Würde mir also helfen, wenn der Befehl AC_GetAggregatedValues nur dann Werte errechnet, wenn es tatsächlich auch einen (plausiblen?) Wert vom Vortag gibt und nicht den u.U. von vor 1 Woche (da danach wegen Sensorausfall Werte fehlen…).

Gruß
hardlog

Will nochmal einen Versuch strarten.

Wenn ich es richtig verstanden habe, kann ich geloggte Daten im Nachherin (nicht so ohne weiteres) korrigieren (außer sie zu löschen). Das Löschen bringt mir in diesem Fall nichts, da sich dann das ursprüngliche Problem noch vergrößern würde…

Ok wie ich die im Datensatz bestehende Lücke rechnerisch ausgleichen würde hab ich mir schon überlegt.

Problem ist nur an welcher Stelle ich am besten per script in die Daten eingreife. Ich verstehe Highcharts leider nicht so gut, das ich die Stelle finde an der ich eine Korrekturfunktion einbauen könnte. Kann mir da jemand helfen?

Oder muss ich den anzueigenden Zeitraum in eine neue Variable schreiben und dabei korrigieren? Wie mache ich das aber am besten?

Gruß
hardlog

Soooo,

ich hab mir jetzt ein Workaround gebastelt.
Ist nicht 100%ig sauber (schon gar nicht gut programmiert, aber als Laie…), aber es geht.
Vermutlich war die Denksportaufgabe und das Umsetzten bis zum Ziel aufwendiger als die Werte manuell nach zu bearbeiten, aber es ging ja auch ums Prinzip :wink:

Jetzt wo ich auf 4.0 upgedatet habe liegen die Geloggten Daten ja als CSV-Daten vor und lassen sich ganz einfach nachbearbeiten.

Ich hab ein Script gebastelt, das nach Vorgabe einiger Daten jeweils einen Monat „glättet“, bzw. wenn an einzelnen Tagen (Intervall bzw. Datendichte ist einstellbar) Daten fehlen (weil z.B. der datenlogger ausgefallen ist (kam bei mir des häufigeren vor)), mittelt das Programm Zwischenwerte aus den letzten bekannten realen Werten.

Mir machte beim Programmieren die Timestampegeschichte (UTC+1 etc) etwas Probleme, so ist es im Script an diesen Stellen auch ein wenig unsauber (und hingebastelt) ist, aber es geht wie man sieht:


Hier mein Script, falls es jemand gebrauchen kann. Irgendwo im Objektbau als script anlegen (reinkopieren), die notwenigen Anpassungen der ersten script-Zeilen mit BEDACHT!!! machen und starten.
Das Script legt sichterheitshalber eine Kopie der Ursprungsdatei an.
Die Daten des Folgemonats und des Vormonats muss man sich jeweils händisch aus der jeweiligen Datei holen. Könnte man auch noch automatisieren, dazu war ich bislang aber zu faul…


<?
/*******************************************************************************
	Diese Script kann Lücken in Kummulierten Daten (Graphen) - wie
	z.B. elektrische Leistungen - durch gemittelte Werte füllen, damit in
	den Graphen nicht so "hässlich" Lücken entstehen und der erst wieder
	gemessene Werte die y-Achse sprengt....
  Klar kann das scipt nicht hellsehen, es tut so, als ob
  zwischen letzten gemessenem Wert und dem ersten neunen Wert der Lücke
  die Daten linear weiter gestiegen wären.

	Achtung: Geht erst ab IPS4.0 (Daten liegen als CSV-Dateien vor)
  
  Keine Garantie das es sauber läuft!!!!
  
  Wichtig: in den ersten Zeilen dieses Script müssen ein paar Daten
  zur Verfügung gestellt werden. 1. Die daten des zu korrigierenden Monats
  und die ID der geloggten Variable.
  Dann aus dem Vor und dem Folgemonat die letzten verfügbaren Timestamps und
  entsprechenden Messwerte hier eintragen.
  
  Das script legt sicherheitshalber eine Kopie der zu ändernden CSV-Datei
  im ursprungsordner an. Ggf. einfach rückbenennen.


	Autor: hardlog     Stand 5.3.2106
*******************************************************************************/

// User Vorgaben: Müssen idividuell angepaßt werden !!!!
$Monat="01";  // zweistellige Angabe !! (ggf. mit führender "0" !!!
$Jahr="2016"; // vierstellige Jahreszahl
$VarID="50944";

$ArchivID=41474; // ID des ArchivHandler

$LetzterTimeStampVormonat=1451603315; // letzten Wert aus vorherigem Monat/CSV-Datei hier eintragen
$LetzterWertVormonat=14072.09; // letzten Wert aus vorherigen Monat/CSV-Datei hier eintragen

$ErsterTimeStampFolgemonat=1454286470; // ersten Wert aus folgender CSV-Datei hier eintragen
$ErsterWertFolgemonat=14514.11; //ersten Wert aus folgender CSV-Datei hier eintragen

$TSabstand=12; // Stundenzahl die zwischen den einzelnen Werten im schnitt liegen sollte (soviele werte werden neu generiert. Standard 12h

//******************************************************************************
// ****************** ab hier mauss nichts mehr verändert werden ***************
//******************************************************************************

$filePath=IPS_GetKernelDir()."db\\$Jahr\\$Monat\\$VarID.csv";
If (!file_exists($filePath)) {echo "Die Datei $filePath existiert nicht!"; Return;}

// Sicherheitslopie der ursprungsdatei im selben Verzeichnis erzeugen:
IPS_Execute("copy", $filePath." ".$filePath."_OLD", false, true);

// Rohdaten werden in Array geladen
$file_handle = fopen($filePath, "r");
$i=0;
while (!feof($file_handle) ) {
  $line_of_text = fgetcsv($file_handle, 1024);
  if ($line_of_text[1]<>"")
	{
     $CSVarray[$i]['TimeStamp']=$line_of_text[0];
     $CSVarray[$i]['Wert']=$line_of_text[1];
	  $i=$i+1;
   }
}
fclose($file_handle);
$rawCount=count($CSVarray); // Zahl der ursprünglichen Datensätze dieser Datei

// Auf Fehler etc. Prüfen ******************************************************
	// gibts in den x ($TSabstand) ersten Stunden einen realen Wert? Sonst Fehlerausgabe!
   if (((($CSVarray[0]['TimeStamp'])-mktime(2,0,0,date("m",$CSVarray[0]['TimeStamp']),1,date("Y",$CSVarray[0]['TimeStamp']))) > ($TSabstand*60*60)) and ($LetzterTimeStampVormonat==0))
	    {Echo "Monat beginnt ohne echte Werte. Bitte Prüfen, bzw. Werte in der Variable 'ManatsbeginnTS' und 'LetzterWertVormonat' in der User-Konfiguration (Anfang dieses Skriptes) vorgeben!"; Return;}
	// gibts in den x ($TSabstand) letzten Stunden des Monats einen realen Wert? Sonst Fehlerausgabe!
	if ( ( (mktime(23,0,0,date("m",$CSVarray[($rawCount-1)]['TimeStamp']),date("t",$CSVarray[($rawCount-1)]['TimeStamp']),date("Y",$CSVarray[($rawCount-1)]['TimeStamp']))-($CSVarray[($rawCount-1)]['TimeStamp'])) > ($TSabstand*60*60)) and ($ErsterTimeStampFolgemonat==0))
	  {Echo "Monat endet ohne echte Werte. Bitte Prüfen, bzw. Werte in der Variable 'ManatsabschlussTS' und 'ErsterWertFolgemonat' in der User-Konfiguration (Anfang dieses Skriptes) vorgeben!"; Return;}

// Wenn Monatsanfang uder Ende ein Problem sind, dann hier ertmal die Grenzwerte erzeugen und ins Array einfügen:
 If (((($CSVarray[0]['TimeStamp'])-mktime(2,0,0,date("m",$CSVarray[0]['TimeStamp']-3600),1,date("Y",$CSVarray[0]['TimeStamp']-3600))) > ($TSabstand*60*60)) and ($LetzterTimeStampVormonat<>0))
	{
	if ($LetzterTimeStampVormonat>(mktime(2,0,0,date("m",$CSVarray[0]['TimeStamp']-3600),1,date("Y",$CSVarray[0]['TimeStamp']-3600)))) {echo "'LetzterTimeStampVormonat' nicht real!"; Return;}
		$DifferenzMonatsende=mktime(23,0,0,date("m",$LetzterTimeStampVormonat),date("t",$LetzterTimeStampVormonat),date("Y",$LetzterTimeStampVormonat))-$LetzterTimeStampVormonat;
		$DifferenzMonatsanfang=$CSVarray[0]['TimeStamp']-(mktime(2,0,0,date("m",$CSVarray[0]['TimeStamp']-3600),1,date("Y",$CSVarray[0]['TimeStamp']-3600)));
		$BeginnAnteil=$DifferenzMonatsanfang/($DifferenzMonatsende+$DifferenzMonatsanfang);
		$ersterWert=$CSVarray[0]['Wert']-(($CSVarray[0]['Wert']-$LetzterWertVormonat)*$BeginnAnteil);
		if ($LetzterWertVormonat>$ersterWert) {echo "'ErsterWertFolgemonat' nicht real!"; Return;}
	   $ersterTS=(mktime(2,0,0,date("m",$CSVarray[0]['TimeStamp']-3600),1,date("Y",$CSVarray[0]['TimeStamp']-3600))); // Timestamp kurz vor Monatsende einfügen
		array_unshift($CSVarray,array('TimeStamp'=> $ersterTS, 'Wert' => round($ersterWert,2)));
		$rawCount=count($CSVarray);
	}

 If ( ( (mktime(23,0,0,date("m",$CSVarray[($rawCount-1)]['TimeStamp']-7200),date("t",$CSVarray[($rawCount-1)]['TimeStamp']-7200),date("Y",$CSVarray[($rawCount-1)]['TimeStamp']-7200))-($CSVarray[($rawCount-1)]['TimeStamp']-7200)) > ($TSabstand*60*60)) and ($ErsterTimeStampFolgemonat<>0))
   {
		if ($ErsterTimeStampFolgemonat<(mktime(23,0,0,date("m",$CSVarray[($rawCount-1)]['TimeStamp']-3600),date("t",$CSVarray[($rawCount-1)]['TimeStamp']-3600),date("Y",$CSVarray[($rawCount-1)]['TimeStamp']-3600)))) {echo "'ErsterTimeStampFolgemonat' nicht real!"; Return;}
		$DifferenzMonatsende=(mktime(23,0,0,date("m",$CSVarray[($rawCount-1)]['TimeStamp']-3600),date("t",$CSVarray[($rawCount-1)]['TimeStamp']-3600),date("Y",$CSVarray[($rawCount-1)]['TimeStamp']-3600)))-$CSVarray[($rawCount-1)]['TimeStamp']-3600;
		$DifferenzMonatsanfang=$ErsterTimeStampFolgemonat-(mktime(23,0,0,date("m",$CSVarray[($rawCount-1)]['TimeStamp']-3600),date("t",$CSVarray[($rawCount-1)]['TimeStamp']-3600),date("Y",$CSVarray[($rawCount-1)]['TimeStamp']-3600)));
		$AbschlussAnteil=$DifferenzMonatsende/($DifferenzMonatsende+$DifferenzMonatsanfang);
		$letzterWert=(($ErsterWertFolgemonat-$CSVarray[$rawCount-1]['Wert'])*$AbschlussAnteil)+$CSVarray[$rawCount-1]['Wert'];
		if ($ErsterWertFolgemonat<$letzterWert) {echo "'ErsterWertFolgemonat' nicht real!"; Return;}
		$CSVarray[$rawCount]['TimeStamp']=(mktime(23,0,0,date("m",$CSVarray[($rawCount-1)]['TimeStamp']-3600),date("t",$CSVarray[($rawCount-1)]['TimeStamp']-3600),date("Y",$CSVarray[($rawCount-1)]['TimeStamp']-3600))); // Timestamp kurz vor Monatsende einfügen
      $CSVarray[$rawCount]['Wert']=round($letzterWert,2);
      $rawCount=count($CSVarray);
	}

// ab hier werden die Lücken innerhalb des Monats gefüllt
do { // diese schleife wiederholen, bis keine Lücke mehr!
 $Holes=0;
 //ersten möglichen Timestamp des akteullen Monats (der gewählten Datei) errechnen
 $oldTS=$CSVarray[0]['TimeStamp'];
 $oldWert=$CSVarray[0]['Wert']; 
 for ($i=0; $i<=count($CSVarray)-1; $i++)
  {
 	if (($CSVarray[$i]['TimeStamp']-$oldTS)>($TSabstand*60*60)) // wenn ZEITlücke zwischen letztem und aktuellem wert > $TSabstand (s.o.) dann muss eine Lücke gefüllt werden
 		 {
		   $Holes++;
			$neuerTS=floor($CSVarray[$i]['TimeStamp']-(($CSVarray[$i]['TimeStamp']-$oldTS)/2)); 			// neuen TimeStamp bei der Häfte der Lücke (egal wie groß) setzten (wenn lücke dann immer noch > $TSabstand wird diese Funktion wiederholt...
			$neuerWert=round($CSVarray[$i]['Wert']-(($CSVarray[$i]['Wert']-$oldWert)/2),2);
			// neue Zeile in Array einschieben
			$neuerEintrag=array("1"=> array('TimeStamp' => $neuerTS, 'Wert' => $neuerWert));
			array_splice($CSVarray, $i, 0, $neuerEintrag); // setzt hinter $letzterRealerTS einen neuen
	    }
	$oldTS=$CSVarray[$i]['TimeStamp'];
	$oldWert=$CSVarray[$i]['Wert'];
 }
 } while ($Holes>0);

// geändert Daten in Ursprungs-Datei überschreiben
$file_handle = fopen($filePath, "w");
foreach ($CSVarray as $fields)
  {
    fputcsv($file_handle, $fields);
  }
fclose($file_handle);

$reAgg=AC_ReAggregateVariable($ArchivID,$VarID);

echo "ursprüngliche Zeilenzahl: ".$rawCount.PHP_EOL; // Zahl der roh-Datensatzzeilen
echo "Zeilenzahl nach Korrektur: ".count($CSVarray)." (d.h.: ".(count($CSVarray)-$rawCount)." Wert(e) neu eingetragen)".PHP_EOL;
if ($reAgg==TRUE) echo "Die Variable $VarID wurde erfolgereich reaggregiert."; else {echo "Reaggregationsfehler!!!";}
?>

Gruß
hardlog