Modul für DWD Open Data

Begonnen von jensb, 21 Januar 2018, 14:38:48

Vorheriges Thema - Nächstes Thema

jensb

#420
@mumpitzstuff
Ein paar kleine Modifikationen sollten noch einfließen:

Änderung: Regenmenge [mm] und Sonnenscheindauer [min] pro Stunde

sub logProxy_dwd2Plot($$$$;$$$)
{
  my ($device, $fcValue, $from, $to, $fcHour, $expMode, $shiftTime) = @_;
  my $regex;
  my @rl;

  return undef if(!$device);

  if ($fcValue =~ s/_$//)
  {
    $regex = "^fc[\\d]+_[\\d]+_".$fcValue."\$";
  }
  else
  {
    $regex = "^fc[\\d]+_".$fcValue."\$";
  }

  $fcHour = 12 if(!defined($fcHour));
  $expMode = "point" if(!defined($expMode));
  #Log3 undef,2, "Regex: ".$regex;

  # ermitteln aller relevanten Readings
  if ( defined($defs{$device}) )
  {
    if ( $defs{$device}{TYPE} eq "DWD_OpenData" )
    {
      @rl = sort
      {
        my ($an) = ($a =~ m/fc(\d+)_.*/);
        my ($bn) = ($b =~ m/fc(\d+)_.*/);
        my ($ao) = ($a =~ m/fc\d+_(\d+).*/);
        my ($bo) = ($b =~ m/fc\d+_(\d+).*/);
        $an <=> $bn or $ao <=> $bo or $a cmp $b;
      } ( grep /${regex}/,keys %{$defs{$device}{READINGS}} );
      #Log3 undef,2, Dumper(@rl);
      return undef if ( !@rl );
    }
    else
    {
      Log3 undef, 2, "logProxy_dwd2Plot: $device is not a DWD_OpenData device";
      return undef;
    }
  }
  #Log3 undef,2, Dumper(@rl);

  my $fromsec = SVG_time_to_sec($from);
  my $tosec   = SVG_time_to_sec($to);
  my $sec = $fromsec;
  my ($h, $hp, $fcDay, $mday, $mon, $year);
  my $timestamp;

  my $reading;
  my $value;
  my $prev_value;
  my $min = 999999;
  my $max = -999999;
  my $ret = "";

  # while not end of plot range reached
  while (($sec < $tosec) && @rl)
  {
    #remember previous value for start of plot range
    $prev_value = $value;

    $reading = shift @rl;
    ($fcDay) = $reading =~ m/^fc(\d+).*/;
    ($hp) = $reading =~ m/^fc\d+_(\d+).*/;
    #Log 1, "hp: ".$hp;

    if ($hp)
    {
      $h = ReadingsVal($device, "fc".$fcDay."_".$hp."_time", $fcHour);
      if ($h =~ m/^(\d+):\d+/)
      {
        $h = $1;
      }
    }
    else
    {
      $h = $fcHour;
    }

    $value = ReadingsVal($device, $reading, undef);

    # calculate minutes of sunshine per hour
    if ($fcValue =~ /^SunD(\d+)/)
    {
      if (defined($1))
      {
        $value = $value / ($1 * 60);
      }
      else
      {
        $value = $value / (12 * 60);
      }
    }

# calculate amount of rain per hour
if ($fcValue =~ /^RR(\d+)c$/)
{
  if (defined($1))
      {
    $value /= $1;
  }
}

    ($year, $mon, $mday) = split('\-',ReadingsVal($device, "fc".$fcDay."_date",undef));
    $timestamp = sprintf("%04d-%02d-%02d_%02d:%02d:%02d", $year, $mon, $mday, $h, 0, 0);
    $sec = SVG_time_to_sec($timestamp);
    if (defined($shiftTime))
    {
      $sec += $shiftTime;
      $timestamp = logProxy_shiftTime($timestamp, $shiftTime);
    }

    # skip all values before start of plot range
    next if ( $sec < $fromsec );

    # add first value at start of plot range
    if ( !$ret && $prev_value )
    {
      $min = $prev_value if ( $prev_value < $min );
      $max = $prev_value if ( $prev_value > $max );
      $ret .= "$from $prev_value\n";
    }

    # done if after end of plot range
    last if ($sec > $tosec);

    $min = $value if ( $value < $min );
    $max = $value if ( $value > $max );

    # add actual control point
    $ret .= "$timestamp $value\n";

    #Log 1, "$timestamp $value <<< $reading";
  }

  if (($sec < $tosec) && !@rl && ($expMode eq "day"))
  {
    $timestamp = sprintf("%04d-%02d-%02d_%02d:%02d:%02d", $year, $mon, $mday, 23, 59, 59);
    $_ = SVG_time_to_sec($timestamp);
    if (defined($shiftTime))
    {
      $_ += $shiftTime;
      $timestamp = logProxy_shiftTime($timestamp, $shiftTime);
    }

    if ($_ < $tosec)
    {
      $ret .= "$timestamp $value\n";
    }
    else
    {
      $ret .= "$to $value\n";
    }
  }
  elsif (($sec > $tosec) && ($expMode eq "day"))
  {
    $value = $prev_value + ($value - $prev_value) * (86400 + ($tosec - $sec)) / 86400;
    $ret .= "$to $value\n";
  }

  return ($ret, $min, $max, $prev_value);
}


Wesentliche Änderung (Beispiel für forecastResolution=3): Verschiebung für Sonne und Regen
Optional: Markierung für "jetzt", deutsche Beschriftung, Festskalierung für Temperatur

set terminal png transparent size <SIZE> crop
set output '<OUT>.png'
set xdata time
set timefmt "%Y-%m-%d_%H:%M:%S"
set xlabel " "
set title 'DWD'
set ytics
set y2tics
set grid ytics
set ylabel "Regen [mm]"
set y2label "Temperatur [°C]"
set y2range [-5:25]
set y3label "Wolken/Regen [%] / Sonne [min]"
set y3range [0:100]

#logProxy Func:logProxy_dwd2Plot("DWD","TTT_",$from,$to,0,"day")
#logProxy Func:logProxy_dwd2Plot("DWD","Tx",$from,$to,0,"day",(-6*3600))
#logProxy Func:logProxy_dwd2Plot("DWD","Tn",$from,$to,0,"day",(-6*3600))
#logProxy Func:logProxy_dwd2Plot("DWD","SunD3_",$from,$to,0,"day",(-3*3600))
#logProxy Func:logProxy_dwd2Plot("DWD","RR3c_",$from,$to,0,"day",(-3*3600))
#logProxy Func:logProxy_dwd2Plot("DWD","R600_",$from,$to,0,"day",(-3*3600))
#logProxy Func:logProxy_dwd2Plot("DWD","Neff_",$from,$to,0,"day")
#logProxy ConstX:TimeNow(),-5,25
#logProxy ConstY:0

plot "<IN>" using 1:2 axes x1y2 title 'T' ls l0 lw 2 with quadraticSmooth,\
     "<IN>" using 1:2 axes x1y2 title 'Tmax' ls l0dot lw 2 with quadraticSmooth,\
     "<IN>" using 1:2 axes x1y2 title 'Tmin' ls l0dot lw 2 with quadraticSmooth,\
     "<IN>" using 1:2 axes x1y3 title 'Sonnendauer' ls l4fill lw 1 with steps,\
     "<IN>" using 1:2 axes x1y1 title 'Regenmenge' ls l2fill lw 1 with steps,\
     "<IN>" using 1:2 axes x1y3 title 'Regenwahrsch.' ls l5fill lw 1 with quadraticSmooth,\
     "<IN>" using 1:2 axes x1y3 title 'Wolken' ls l6fill lw 1 with quadraticSmooth,\
     "<IN>" using 1:2 axes x1y2 notitle ls l5 lw 4 with lines,\
     "<IN>" using 1:2 axes x1y2 notitle ls l5 lw 1 with lines


Anbei der dazugehörige Plot. Er zeigt außerdem für heute die Regenmenge von meinem Sensor (mit 1 Stunde Versatz).

Grüße,
Jens

P.S.: Es ist übrigens kein FileLog vom OpenData-Modul für das SVG erforderlich, der logProxy schafft das allein. Im define für das SVG kann man das Feld vor dem 1. und nach dem 2. Doppelpunkt leer lassen. Ein FileLog für das OpenData-Modul ist, wenn man es sonst für nichts braucht, je nach Konfiguration eher eine Systembremse wegen der vielen Daten.
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

frank

echt cool, habt ihr schön gemacht.  :)

ZitatDen stündlichen Wert für die Regenwahrscheinlichkeit gabs nur für Regenmengen > 0.1mm.
im sommer, beim warten und hoffen auf regen, ist mir aufgefallen, dass der regen, der im niederschlagsradar mit den kleinst möglichen intensitäten angezeigt wurde, es nie bis zum boden geschafft hat.

somit könnte dieser wahrscheinlichkeitswert vielleicht besser zu "echtem", spürbarem regen, der auch den boden erreicht, passen.
FHEM: 6.0(SVN) => Pi3(buster)
IO: CUL433|CUL868|HMLAN|HMUSB2|HMUART
CUL_HM: CC-TC|CC-VD|SEC-SD|SEC-SC|SEC-RHS|Sw1PBU-FM|Sw1-FM|Dim1TPBU-FM|Dim1T-FM|ES-PMSw1-Pl
IT: ITZ500|ITT1500|ITR1500|GRR3500
WebUI [HMdeviceTools.js (hm.js)]: https://forum.fhem.de/index.php/topic,106959.0.html

jensb

#422
Hier noch ein bisschen Errata:

Änderung (Beispiel für forecastResolution=3): Verschiebung für min./max. Temperatur - nur so bleibt die Isttemperatur TTT im Verlauf zwischen Min und Max

set terminal png transparent size <SIZE> crop
set output '<OUT>.png'
set xdata time
set timefmt "%Y-%m-%d_%H:%M:%S"
set xlabel " "
set title 'DWD'
set ytics
set y2tics
set grid ytics
set ylabel "Regen [mm]"
set y2label "Temperatur [°C]"
set y2range [-5:25]
set y3label "Wolken/Regen [%] / Sonne [min]"
set y3range [0:100]

#logProxy Func:logProxy_dwd2Plot("DWD","TTT_",$from,$to,0,"day")
#logProxy Func:logProxy_dwd2Plot("DWD","Tx",$from,$to,18,"day")
#logProxy Func:logProxy_dwd2Plot("DWD","Tn",$from,$to,6,"day")
#logProxy Func:logProxy_dwd2Plot("DWD","SunD3_",$from,$to,0,"day",(-3*3600))
#logProxy Func:logProxy_dwd2Plot("DWD","RR3c_",$from,$to,0,"day",(-3*3600))
#logProxy Func:logProxy_dwd2Plot("DWD","R600_",$from,$to,0,"day",(-3*3600))
#logProxy Func:logProxy_dwd2Plot("DWD","Neff_",$from,$to,0,"day")
#logProxy ConstX:TimeNow(),-5,25
#logProxy ConstY:0

plot "<IN>" using 1:2 axes x1y2 title 'T' ls l0 lw 2 with quadraticSmooth,\
     "<IN>" using 1:2 axes x1y2 title 'Tmax' ls l0dot lw 2 with quadraticSmooth,\
     "<IN>" using 1:2 axes x1y2 title 'Tmin' ls l0dot lw 2 with quadraticSmooth,\
     "<IN>" using 1:2 axes x1y3 title 'Sonnendauer' ls l4fill lw 1 with steps,\
     "<IN>" using 1:2 axes x1y1 title 'Regenmenge' ls l2fill lw 1 with steps,\
     "<IN>" using 1:2 axes x1y3 title 'Regenwahrsch.' ls l5fill lw 1 with quadraticSmooth,\
     "<IN>" using 1:2 axes x1y3 title 'Wolken' ls l6fill lw 1 with quadraticSmooth,\
     "<IN>" using 1:2 axes x1y2 notitle ls l5 lw 4 with lines,\
     "<IN>" using 1:2 axes x1y2 notitle ls l5 lw 1 with lines


ZitatIm define für das SVG kann man das Feld vor dem 1. und nach dem 2. Doppelpunkt leer lassen.
Ist unzuverlässig, FHEMWEB zeigt dann sporadisch einen Fehler. Man kann das FileLog im SVG define wohl nicht weglassen, aber man kann ein beliebiges angeben, das schon existiert, es muss keine Werte vom OpenData-Modul enthalten.

Grüße,
Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

mumpitzstuff

Ich habe da noch ein paar Fragen:

1.) Wie kommst du auf die 6 und 18 bei der min/Max Temperatur?
2.) Warum verschiebst du z.b. RR3c um 3 Stunden und nicht um 1.5, damit der Punkt in der Mitte des Messzeitraumes liegt?
3.) Min pro Stunde für SunD ist nur eine andere Einheit, die dich persönlich mehr anspricht? Ich fand es sinnvoll hier einen prozentualen Wert zu haben, um ihn mit der Bewölkung und der Regenwahrscheinlichkeit besser vergleichen zu können.

Das mit dem Regen pro Stunde sehe ich ein, da ansonsten bei Verwendung des 3h Wertes Niederschlagsmengen mehrfach gezählt werden.

curt

Entschuldigung, darf ich bitte etwas konzeptionelles fragen?

Motivation: Mir fällt gerade wieder schwer, der Diskussion zu folgen, ich bin ja nach einem Jahr immer noch in vielen Dingen Anfänger. - Hier konkret fällt mir schwer jeder Umrechnung zu folgen - und warum und wie die motiviert ist. Und wie ich die wo einbaue.

Wäre es denn nicht viel klüger, dass @jensb direkt im Modul (zusätzlich) Readings bereitstellt, die schon umgerechnet sind?

Falls Jens nun sagt "nicht mein Modulansatz" würde ich alternativ vorschlagen, dass wir uns diese umgerechneten Readings als Attribute der DWD-Device via userReadings schaffen und der Allgemeinheit (z.B. über Wiki) zur Verfügung stellen.

Ich komme wegen eines Beispiels drauf, das habe ich mir irgendwo mal abgeschrieben:

attr DWD userReadings fc0_SunDh {ReadingsVal("DWD","fc0_SunD","")/3600},\
fc1_SunDh {ReadingsVal("DWD","fc1_SunD","")/3600},\
fc2_SunDh {ReadingsVal("DWD","fc2_SunD","")/3600},\
fc3_SunDh {ReadingsVal("DWD","fc3_SunD","")/3600},\
fc4_SunDh {ReadingsVal("DWD","fc4_SunD","")/3600}


Falls wir uns nicht schreiben:
Ich wünsche allen frohe und gesegnete Weihnachten!
RPI 4 - Jeelink HomeMatic Z-Wave

mumpitzstuff

#425
Es gibt zu viele Möglichkeiten. Der eine will mm pro Quadratmeter und der nächste was weiß ich was. Ich denke das Modul sollte sich auch die Rohwerte beschränken. Das mit den Userreadings ist mir nicht so ganz klar ob das geht. Man hat hier Tage und Stunden im Reading mit drin. Ich bin mir nicht sicher, ob sich das sinnvoll mit Userreadings abbilden lässt.

Ich poste nach dem Abschluss der Diskussionen noch mal die Ergebnisse, letztendlich sind ja nur die für dich interessant. Können dann gern auch ins Wiki übernommen werden.

mumpitzstuff

Bei ConstX habe ich keine hardcoded Temperaturwerte verwendet, sondern das Folgende:

#logProxy ConstX:TimeNow(),0,100

Dann muss man die Linie noch auf Achse 3 anstatt 2 beziehen und fertig. Ansonsten kriegt man jedes Mal Probleme, wenn die Temperatur aus dem Raster raus fällt.

curt

Zitat von: mumpitzstuff am 23 Dezember 2018, 02:01:34
Es gibt zu viele Möglichkeiten.

Das ist ja erstmal sehr erfreulich.

Zitat von: mumpitzstuff am 23 Dezember 2018, 02:01:34
Der eine will mm pro Quadratmeter und der nächste was weiß ich was.

Ich würde vorschlagen: Wir halten uns an den klassischen Wetterbericht. Die dort genutzten Parameter sind ja nicht vom Himmel gefallen, die haben sich über Jahrzehnte für die Allgemeinheit (und das sind wir ja) bewehrt.

Ich selbst will und muss mich an das halten, was andere schlaue Coder so coden. Mein Beitrag wird (hier) gering sein. (Ich bin dann erst wieder bei FTUI aktiv dabei.)

Zitat von: mumpitzstuff am 23 Dezember 2018, 02:01:34
Ich denke das Modul sollte sich auch die Rohwerte beschränken.

Das ist eben die Frage. Mal sehen, was Jens zu der Frage sagt. Es gäbe ja noch die Version "das eine tun, das andere nicht lassen": Einerseits die Rohwerte, andererseits ausgewählte gewandelte Werte durch das Modul.
(Ich werde mit dem leben und leben müssen, was er entscheidet.)

Zitat von: mumpitzstuff am 23 Dezember 2018, 02:01:34
Das mit den Userreadings ist mir nicht so ganz klar ob das geht.

Das geht - behaupte ich mal keck:
Ich bin ja der FHEM-Weltmeister im Abschreiben (und erweitern), ich lerne durch Beispiele. userReadings (und setreding) habe ich durchaus nicht selten bei anderen Devices mit anderen Modulen. (Und halt das Beispiel "Sonne pro Stunde".)

Was Du da mit Perl in 99_my... vorführst, wäre -aus meiner Sicht- idealtypisch schon beim setzen der (user)Readings zu tun.

Zitat von: mumpitzstuff am 23 Dezember 2018, 02:01:34
Ich poste nach dem Abschluss der Diskussionen noch mal die Ergebnisse, letztendlich sind ja nur die für dich interessant. Können dann gern auch ins Wiki übernommen werden.

Das ist sehr freundlich.
Natürlich geht es ganz egoistisch erstmal um mich, das streite ich gar nicht ab. Aber wenn sich einige schon richtig abquälen, muss das ja einen übergeordneten Sinn haben - beziehungsweise sollte es. Nämlich den, dass andere, viele andere, das auch nutzen. Sonst wäre letzten Endes auch das Modul verschossen ...

Das kommt auch aus einer Erfahrung aus meiner Startzeit hier:
Im Forum wimmelt es von "wie geht denn das" und ich dachte "das will ich auch wissen". Und dann war meist die Antwort "guck mal wir und da und commandref". Und der Fragende antwortete entweder nie wieder - oder mit "oh, danke, jetzt geht es". Hmm, schön für euch. Schlecht für mich. Hättet ihr doch gezeigt, WIE es geht!

Von daher (und um schrittweise diesen Stil im Forum zu ändern) bin ich Dir ausnehmend dankbar, dass Du Dir die Mühe machtest (und machen willst) zu sagen: Guck her, es geht exakt so; hier das Kochrezept.

Ganz herzlichen Dank!
RPI 4 - Jeelink HomeMatic Z-Wave

jensb

@mumpitzstuff

Zitat1.) Wie kommst du auf die 6 und 18 bei der min/Max Temperatur?
Die Daten kommen (zumindest bei vielen Stationen) so vom DWD und es steht auch als Anmerkung zu diesen Readings in der Modulhilfe. Wenn man sie verschiebt, so wie du es vorgeschlagen hast, beginnt der Plot zwar schön links, aber die Isttemperaturen bleiben dann nicht zwischen Min- und Max. Macht man es aber physikalisch richtig, so wie von mir vorgeschlagen, fehlen die Punkte bis zum linken Rand.
Dazu hätte ich einen Lösungsvorschlag: neues Attribut "forecastHistoryDays" für das OpenData-Modul. Dann gäbe ab dem 1. Tageswechsel auch Readings die "fc_-1_xxx" heißen und damit könnte der Plot die Lücken schließen. Die Frage ist für mich: Soll ich das so machen oder hat jemand eine andere Idee?

Zitat2.) Warum verschiebst du z.b. RR3c um 3 Stunden und nicht um 1.5, damit der Punkt in der Mitte des Messzeitraumes liegt?
RR3c ist die Regenmenge für 3 Stunden, also ein Aggregatwert, gemeldet z.B. für 13:00, also gültig von 10:00 bis 13:00. Dividiert durch 3 ist das die Regenmenge pro Stunde. Die muss dann bei Darstellung mit "steps" um 10:00, 11:00 und 12:00 angezeigt werden und um 13:00 aufhören.
Entsprechend sollte man bei RR1c "fsteps" verwenden bzw. bei "steps" um eine ganze Stunde verschieben.
R600 ist dagegen kein Aggregatwert sondern ein Einzelwert, ähnlich wie TTT. Gemeldet z.B. für 13:00, für 6 Stunden, also gültig von 07:00 bis 13:00. Dividieren macht keinen Sinn. Als Einzelwert ist dann die Mitte, also 10:00, die richtige Position. 3 Stunden Verschiebung passen also. Entsprechendes gilt für R101, hier ist, wie von dir vorgeschlagen, die halbe Stunde Verschiebung die richtige Wahl.

Zitat3.) Min pro Stunde für SunD ist nur eine andere Einheit, die dich persönlich mehr anspricht? Ich fand es sinnvoll hier einen prozentualen Wert zu haben, um ihn mit der Bewölkung und der Regenwahrscheinlichkeit besser vergleichen zu können.
Konsens, der eine mag Minuten, der andere %. Vermutlich sind % hierfür die bessere Wahl.

ZitatBei ConstX habe ich keine hardcoded Temperaturwerte verwendet, sondern das Folgende:
#logProxy ConstX:TimeNow(),0,100
Dann muss man die Linie noch auf Achse 3 anstatt 2 beziehen und fertig. Ansonsten kriegt man jedes Mal Probleme, wenn die Temperatur aus dem Raster raus fällt.
Sorry, hab mir wohl beim Experimentieren mit dem Ploteditor die Config zerschossen und dann nicht alles wieder in den ursprünglichen Zustand gebracht. 0-100% für Achse 3 ist die universellere Lösung. Bei Achse 1 und 2 sollte jeder das einstellen, was für seinen Ort typisch ist. Zumindest ich bin kein Freud der Autoskalierung: Wenn die Messwerte oder Wertebereiche klein sind, dann muss für mich auch das Abbild kleiner werden.

ZitatIch poste nach dem Abschluss der Diskussionen noch mal die Ergebnisse ... Können dann gern auch ins Wiki übernommen werden.
Das würde die Anwender des Moduls freuen, die der Diskussion nicht ganz folgen konnten. Bitte leg fest, wie wir das machen sollen, es ist schließlich dein Werk. Du kannst es selbst dem vorhandenen Artikel zum OpenData-Modul hinzufügen. Wenn das aber nicht dein Ding ist, würde ich das übernehmen.

Grüße,
Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

Newbee

Zitat von: jensb am 22 Dezember 2018, 11:17:37
@mumpitzstuff
Ein paar kleine Modifikationen sollten noch einfließen:

Änderung: Regenmenge [mm] und Sonnenscheindauer [min] pro Stunde

sub logProxy_dwd2Plot($$$$;$$$)
{
  my ($device, $fcValue, $from, $to, $fcHour, $expMode, $shiftTime) = @_;
  my $regex;
  my @rl;

  return undef if(!$device);

  if ($fcValue =~ s/_$//)
  {
    $regex = "^fc[\\d]+_[\\d]+_".$fcValue."\$";
  }
  else
  {
    $regex = "^fc[\\d]+_".$fcValue."\$";
  }

  $fcHour = 12 if(!defined($fcHour));
  $expMode = "point" if(!defined($expMode));
  #Log3 undef,2, "Regex: ".$regex;

  # ermitteln aller relevanten Readings
  if ( defined($defs{$device}) )
  {
    if ( $defs{$device}{TYPE} eq "DWD_OpenData" )
    {
      @rl = sort
      {
        my ($an) = ($a =~ m/fc(\d+)_.*/);
        my ($bn) = ($b =~ m/fc(\d+)_.*/);
        my ($ao) = ($a =~ m/fc\d+_(\d+).*/);
        my ($bo) = ($b =~ m/fc\d+_(\d+).*/);
        $an <=> $bn or $ao <=> $bo or $a cmp $b;
      } ( grep /${regex}/,keys %{$defs{$device}{READINGS}} );
      #Log3 undef,2, Dumper(@rl);
      return undef if ( !@rl );
    }
    else
    {
      Log3 undef, 2, "logProxy_dwd2Plot: $device is not a DWD_OpenData device";
      return undef;
    }
  }
  #Log3 undef,2, Dumper(@rl);

  my $fromsec = SVG_time_to_sec($from);
  my $tosec   = SVG_time_to_sec($to);
  my $sec = $fromsec;
  my ($h, $hp, $fcDay, $mday, $mon, $year);
  my $timestamp;

  my $reading;
  my $value;
  my $prev_value;
  my $min = 999999;
  my $max = -999999;
  my $ret = "";

  # while not end of plot range reached
  while (($sec < $tosec) && @rl)
  {
    #remember previous value for start of plot range
    $prev_value = $value;

    $reading = shift @rl;
    ($fcDay) = $reading =~ m/^fc(\d+).*/;
    ($hp) = $reading =~ m/^fc\d+_(\d+).*/;
    #Log 1, "hp: ".$hp;

    if ($hp)
    {
      $h = ReadingsVal($device, "fc".$fcDay."_".$hp."_time", $fcHour);
      if ($h =~ m/^(\d+):\d+/)
      {
        $h = $1;
      }
    }
    else
    {
      $h = $fcHour;
    }

    $value = ReadingsVal($device, $reading, undef);

    # calculate minutes of sunshine per hour
    if ($fcValue =~ /^SunD(\d+)/)
    {
      if (defined($1))
      {
        $value = $value / ($1 * 60);
      }
      else
      {
        $value = $value / (12 * 60);
      }
    }

# calculate amount of rain per hour
if ($fcValue =~ /^RR(\d+)c$/)
{
  if (defined($1))
      {
    $value /= $1;
  }
}

    ($year, $mon, $mday) = split('\-',ReadingsVal($device, "fc".$fcDay."_date",undef));
    $timestamp = sprintf("%04d-%02d-%02d_%02d:%02d:%02d", $year, $mon, $mday, $h, 0, 0);
    $sec = SVG_time_to_sec($timestamp);
    if (defined($shiftTime))
    {
      $sec += $shiftTime;
      $timestamp = logProxy_shiftTime($timestamp, $shiftTime);
    }

    # skip all values before start of plot range
    next if ( $sec < $fromsec );

    # add first value at start of plot range
    if ( !$ret && $prev_value )
    {
      $min = $prev_value if ( $prev_value < $min );
      $max = $prev_value if ( $prev_value > $max );
      $ret .= "$from $prev_value\n";
    }

    # done if after end of plot range
    last if ($sec > $tosec);

    $min = $value if ( $value < $min );
    $max = $value if ( $value > $max );

    # add actual control point
    $ret .= "$timestamp $value\n";

    #Log 1, "$timestamp $value <<< $reading";
  }

  if (($sec < $tosec) && !@rl && ($expMode eq "day"))
  {
    $timestamp = sprintf("%04d-%02d-%02d_%02d:%02d:%02d", $year, $mon, $mday, 23, 59, 59);
    $_ = SVG_time_to_sec($timestamp);
    if (defined($shiftTime))
    {
      $_ += $shiftTime;
      $timestamp = logProxy_shiftTime($timestamp, $shiftTime);
    }

    if ($_ < $tosec)
    {
      $ret .= "$timestamp $value\n";
    }
    else
    {
      $ret .= "$to $value\n";
    }
  }
  elsif (($sec > $tosec) && ($expMode eq "day"))
  {
    $value = $prev_value + ($value - $prev_value) * (86400 + ($tosec - $sec)) / 86400;
    $ret .= "$to $value\n";
  }

  return ($ret, $min, $max, $prev_value);
}


Wesentliche Änderung (Beispiel für forecastResolution=3): Verschiebung für Sonne und Regen
Optional: Markierung für "jetzt", deutsche Beschriftung, Festskalierung für Temperatur

set terminal png transparent size <SIZE> crop
set output '<OUT>.png'
set xdata time
set timefmt "%Y-%m-%d_%H:%M:%S"
set xlabel " "
set title 'DWD'
set ytics
set y2tics
set grid ytics
set ylabel "Regen [mm]"
set y2label "Temperatur [°C]"
set y2range [-5:25]
set y3label "Wolken/Regen [%] / Sonne [min]"
set y3range [0:100]

#logProxy Func:logProxy_dwd2Plot("DWD","TTT_",$from,$to,0,"day")
#logProxy Func:logProxy_dwd2Plot("DWD","Tx",$from,$to,0,"day",(-6*3600))
#logProxy Func:logProxy_dwd2Plot("DWD","Tn",$from,$to,0,"day",(-6*3600))
#logProxy Func:logProxy_dwd2Plot("DWD","SunD3_",$from,$to,0,"day",(-3*3600))
#logProxy Func:logProxy_dwd2Plot("DWD","RR3c_",$from,$to,0,"day",(-3*3600))
#logProxy Func:logProxy_dwd2Plot("DWD","R600_",$from,$to,0,"day",(-3*3600))
#logProxy Func:logProxy_dwd2Plot("DWD","Neff_",$from,$to,0,"day")
#logProxy ConstX:TimeNow(),-5,25
#logProxy ConstY:0

plot "<IN>" using 1:2 axes x1y2 title 'T' ls l0 lw 2 with quadraticSmooth,\
     "<IN>" using 1:2 axes x1y2 title 'Tmax' ls l0dot lw 2 with quadraticSmooth,\
     "<IN>" using 1:2 axes x1y2 title 'Tmin' ls l0dot lw 2 with quadraticSmooth,\
     "<IN>" using 1:2 axes x1y3 title 'Sonnendauer' ls l4fill lw 1 with steps,\
     "<IN>" using 1:2 axes x1y1 title 'Regenmenge' ls l2fill lw 1 with steps,\
     "<IN>" using 1:2 axes x1y3 title 'Regenwahrsch.' ls l5fill lw 1 with quadraticSmooth,\
     "<IN>" using 1:2 axes x1y3 title 'Wolken' ls l6fill lw 1 with quadraticSmooth,\
     "<IN>" using 1:2 axes x1y2 notitle ls l5 lw 4 with lines,\
     "<IN>" using 1:2 axes x1y2 notitle ls l5 lw 1 with lines


Anbei der dazugehörige Plot. Er zeigt außerdem für heute die Regenmenge von meinem Sensor (mit 1 Stunde Versatz).

Grüße,
Jens

P.S.: Es ist übrigens kein FileLog vom OpenData-Modul für das SVG erforderlich, der logProxy schafft das allein. Im define für das SVG kann man das Feld vor dem 1. und nach dem 2. Doppelpunkt leer lassen. Ein FileLog für das OpenData-Modul ist, wenn man es sonst für nichts braucht, je nach Konfiguration eher eine Systembremse wegen der vielen Daten.

Hallo Jens,

haben o.g. myUtils code übernommen und die SVG Inhalte aus dem Bsp. "forecastResulution 3"

Alles andere logProxy, attr, etc habe ich wie am Bsp. von mumpitzstuff eingestellt.

Leider ergibt sich in der SVG eine sehr eigenwilligen Darstellung!

Was habe ich übersehen?

Vielen Dank vorab.

Grüße Newbee
Intel-NUC mit ubuntu server 20.04; FHEM 6.0
HM, Dect, Netatmo, Hue

jensb

@Newbee
Das ist ja fast psychedelisch. Irgendwie scheint bei dir die Zeit nicht nur vorwärts sondern auch rückwärts zu gehen.

Hast du vielleicht mehrere forecastResolution Varianten ausprobiert? Wenn du von klein nach groß umschaltest, musst du die überschüssigen Readings einmal manuell entfernen (deletereading DWD fc_.*). Schau dir dazu den größten Stundenindex pro Tag und die Zeiten der Readings an. Bei forecastResolution=3 muss bei 24/3-1=7 Schluss sein.

Grüße,
Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

Newbee

Zitat von: jensb am 23 Dezember 2018, 14:48:50
@Newbee
Das ist ja fast psychedelisch. Irgendwie scheint bei dir die Zeit nicht nur vorwärts sondern auch rückwärts zu gehen.

Hast du vielleicht mehrere forecastResolution Varianten ausprobiert? Wenn du von klein nach groß umschaltest, musst du die überschüssigen Readings einmal manuell entfernen (deletereading DWD fc_.*). Schau dir dazu den größten Stundenindex pro Tag und die Zeiten der Readings an. Bei forecastResolution=3 muss bei 24/3-1=7 Schluss sein.

Grüße,
Jens

Danke Jens das war es!

Hatte wohl von 1 auf 3 und wieder zurück gewechselt, war alles mehrfach vorhanden.

Grüße Newbee
Intel-NUC mit ubuntu server 20.04; FHEM 6.0
HM, Dect, Netatmo, Hue

mumpitzstuff

Ich habe noch rausgefunden wie man sich ein Plot beginnend ab der aktuellen Zeit, für die nächsten 24h erstellt.

defmod SVG_FileLog_WETTER_DWD_3 SVG FileLog_WETTER_DWD:SVG_FileLog_WETTER_DWD_3:CURRENT
attr SVG_FileLog_WETTER_DWD_3 endPlotNow 1
attr SVG_FileLog_WETTER_DWD_3 fixedoffset 1
attr SVG_FileLog_WETTER_DWD_3 nrAxis 1,2


Für mehr als 1 Tag macht es leider keinen Sinn, da man dann nicht mehr die Uhrzeit erkennt.

holle75

#433
ich schau hier bei euch mit. Für jemanden der gerne Wind und Böen in km/h statt m/s (irgendwie ein visuell schwer erfühlbarer Wert) haben möchte:

in der Sub an der kommentierten Stelle
$value = ReadingsVal($device, $reading, undef);

    # calculate minutes of sunshine per hour
    if ($fcValue =~ /^SunD(\d+)/)
    {
      if (defined($1))
      {
        $value = $value / ($1 * 60);
      }
      else
      {
        $value = $value / (12 * 60);
      }
    }

# calculate amount of rain per hour
if ($fcValue =~ /^RR(\d+)c$/)
{
  if (defined($1))
      {
    $value /= $1;
  }
}

#  calculate wind or gusts in km/h
if ($fcValue =~ /^(FF|FX1|FX3|FXh)$/)
{
    $value = $value * 3.6;
}
# end  calculate wind or gusts in km/h

    ($year, $mon, $mday) = split('\-',ReadingsVal($device, "fc".$fcDay."_date",undef));
    $timestamp = sprintf("%04d-%02d-%02d_%02d:%02d:%02d", $year, $mon, $mday, $h, 0, 0);


ich hoffe, als eher Bastler als Könner, dass ich mich nicht vertan habe.

PS: Ich möchte übrigens curt hier https://forum.fhem.de/index.php/topic,83097.msg875664.html#msg875664 ein wenig zustimmen. Bin jetzt seit ca 12 Stunden dran die Hieroglyphen der DWD Daten rauszuschreiben, Einheiten zu vergleichen und zu verstehen, die Berechnungen und Verschiebungen in der sub und dann in der SVG Datei nachzuvollziehen ....

Das geht alles (und Hut ab vor mumpitzstuff und jensb ARBEIT), aber ist für die Anwendung und Nachvollziehbarkeit schon eine kleine Herausforderung.... und recht fehleranfällig. Ich möchte vor allem nicht wissen, wenn ich in einem Jahr noch einen Wert zusätzlich plotten will, ob ich mich noch an die Herangehensweise erinnere.

Ich möchte curts Idee die wahrscheinlichen Standardwerte für viele, zB

PLOT 1 -> Sonnendauer (min/%), Regenmenge (mm), Regenwahrscheinlichkeit (%), Wolkenbedeckung (%), Wind (km/h), Boen (km/h)
PLOT 2 -> Temp (C), TempMax (c), TempMin (C), .... (Frost, Frostgefahr .... fällt mir gerade ein weil es das in Proplanta gibt. Glaube in DWD direkt nicht?)

IM Modul aufzuarbeiten, sinnvoll zu benennen, für 3h und 1h aufzuarbeiten und vielleicht sogar die 2 passenden SVG´s automatisch anzulegen, hiermit auch nochmals unterstützen.

Sozusagen als Einsteiger-Set ;) was dann jemand draus macht ist ja ihm überlassen.

Versteht mich nicht falsch. Alles schon ganz weit vorne! (ich habs mit DarkSky hier https://forum.fhem.de/index.php/topic,93869.msg870069.html#msg870069 versucht und bin bis jetzt komplett gescheitert) .... aber Einfach ist anders (wenn man jetzt den Anspruch hätte es Neu- und Alteinsteigern möglichst einfach zu machen) ... und ich verstehe jeden der sagt "Ich mach das für mich, brauch den ganzen anderen Kremsel nicht und was willst du überhaupt"

.... einen herzlichen Dank für eure Arbeit!


jensb

@holle75

ZitatIch möchte übrigens curt hier https://forum.fhem.de/index.php/topic,83097.msg875664.html#msg875664 ein wenig zustimmen. Bin jetzt seit ca 12 Stunden dran die Hieroglyphen der DWD Daten rauszuschreiben, Einheiten zu vergleichen und zu verstehen, die Berechnungen und Verschiebungen in der sub und dann in der SVG Datei nachzuvollziehen ....
Das geht alles (und Hut ab vor mumpitzstuff und jensb ARBEIT), aber ist für die Anwendung und Nachvollziehbarkeit schon eine kleine Herausforderung.... und recht fehleranfällig. Ich möchte vor allem nicht wissen, wenn ich in einem Jahr noch einen Wert zusätzlich plotten will, ob ich mich noch an die Herangehensweise erinnere.
Ich möchte curts Idee die wahrscheinlichen Standardwerte ...  IM Modul aufzuarbeiten, sinnvoll zu benennen, für 3h und 1h aufzuarbeiten und vielleicht sogar die 2 passenden SVG´s automatisch anzulegen, hiermit auch nochmals unterstützen.

Ich stimme der dahinter liegenden Idee genauso zu. Allerdings sehe ich nicht, wie wir mit den zur Verfügung stehenden Entwickler-Resourcen dahin kommen und - das ist die noch größere Aufgabe - da auch langfristig bleiben können. Nur wenn sich hier im Forum ein paar Engagierte zusammen tun, etwas auf die Beine stellen und es für andere verständlich in der Wiki hinterlassen, können wir überhaupt leicht Anwendbares zur Verfügung stellen. Leider hat die Vergangenheit gezeigt, dass sich beim DWD z.B. die Rohdaten deutlich ändern können. Werteverfügbarkeit, Zeitbezüge, Einheiten - nichts muss in der nächsten Version vom DWD genauso sein. Natürlich wäre es toll, wenn diese lästigen Anpassungsarbeiten von einem Modul übernommen werden. Aber fehlende Messwerte zu generieren ist schwer bis unmöglich und Zeitbezüge von Wetterdaten umzurechnen ist Meteorologie und keine Datenverarbeitung. Lassen wir mal ganz außen vor, dass es sicherlich einen Satz "wahrscheinlichen Standardwerte" mit eben so wahrscheinlichen Einheiten gibt, aber die Frage nach noch einem Wert X mehr und einer alternativen Einheit für Wert Y wird dann immer noch vom dem einen oder anderen Anwender kommen.

Um den Aufwand in Grenzen zu halten und überhaupt etwas zur Verfügung stellen zu können gibt es das OpenData-Modul in seiner jetzigen Form mit den Rohdaten des DWD. Für die aufbereiteten Werte habe ich schon mehr als einmal vorgeschlagen, die Werte, die das Weblink-Modul anzeigt, als Readings zur Verfügung zu stellen. Die Aufbereitung könnte man auch erweitern und mehr Werte zur Verfügung stellen, als es der Weblink bisher tut. Aber hier hören meine (zeitlich begrenzten) Möglichkeiten auf. Deshalb gibt es schon den Weblink nicht direkt mit FHEM. Wer sich berufen fühlt, kann ein Modul schreiben, dass die Datenaufbereitung in der gewünschten Form übernimmt und z.B. auch die Anpassungen für die FTUI durchführt.

@mumpitzstuff
Gib mir bitte bei Gelegenheit noch eine Rückmeldung zu diesem Beitrag.

Grüße,
Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb