[Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten

Begonnen von schwatter, 09 Juni 2025, 23:37:53

Vorheriges Thema - Nächstes Thema

schwatter

Deine Ringe nutze ich auch gerne. Zum Beispiel im devStateIcon.

{ui_Table::temp_hum_ring(ReadingsVal("THsensorBk","temperature",0),ReadingsVal("THsensorBk","humidity",0))}

Aber ich wollte mal ausbrechen und schauen.

Gruß schwatter

Damian

Zitat von: schwatter am 12 Juni 2025, 19:48:06Deine Ringe nutze ich auch gerne. Zum Beispiel im devStateIcon.

{ui_Table::temp_hum_ring(ReadingsVal("THsensorBk","temperature",0),ReadingsVal("THsensorBk","humidity",0))}

Aber ich wollte mal ausbrechen und schauen.

Gruß schwatter

Ja, es ist immer gut selber was zu machen, oft entwickelt sich ein größeres Projekt mit der Zeit.

P.S. Man kann übrigens im deviStateIcon eines Devices auch die ui_Table::card-Funktion verwenden, die solche Verläufe visualisiert

Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

schwatter

#17
Das habe ich aufm Schirm. Wollte es aber absichtlich spartanischer und visuell flexibel.
Funktional is deine Card natürlich besser.

Gruß schwatter

schwatter

#18
Nabend,

hier ein Beispiel für stateFormat ohne Echarts. Nur Html, SVG und Perl. Dadurch viel effizienter.

{
  my @v = (split /,/, ReadingsVal('Smartmeter_2E1F50','chartArray',''))[-40..-1];  # letzte 40 Werte

  my ($min, $max) = (sort {$a <=> $b} @v)[0,-1];
  $max //= 0; $min //= 0;
  my $range = $max - $min || 1;

  # SVG-Zielgröße (angepasst!)
  my $width  = 160;
  my $height = 70;

  my $w = $width / (@v - 1 || 1);

  # y-Position der Null-Linie
  my $y0 = $height - ((0 - $min) / $range * $height);

  # Punkte vorbereiten
  my @points = map {
    [ $_ * $w, $height - (($v[$_] - $min)/$range * $height), $v[$_] ]
  } 0..$#v;

  my $bar_width = $w * 0.6;

  my $bars_svg = join "", map {
    my ($x, $y, $val) = @{$points[$_]};
    my $color = $val >= 0 ? 'red' : 'green';

    if ($val >= 0) {
      my $bar_height = $y0 - $y;
      sprintf(
        '<rect x="%.2f" y="%.2f" width="%.2f" height="%.2f" fill="%s" opacity="0.8" />',
        $x - $bar_width/2, $y, $bar_width, $bar_height, $color
      );
    } else {
      my $bar_height = $y - $y0;
      sprintf(
        '<rect x="%.2f" y="%.2f" width="%.2f" height="%.2f" fill="%s" opacity="0.8" />',
        $x - $bar_width/2, $y0, $bar_width, $bar_height, $color
      );
    }
  } 0..$#points;

  my $current_power = ReadingsVal('Smartmeter_2E1F50','APOX_Power', '--');
  my $todayIn       = ReadingsVal('Smartmeter_2E1F50','statAPOX_E_inDay', '--');
  my $todayOut      = ReadingsVal('Smartmeter_2E1F50','statAPOX_E_outDay', '--');

  return qq{
    <style>
      div#Smartmeter_2E1F50 { pointer-events:none; }
    </style>
    <div style="width:365px; padding:10px; border:1px solid #ddd; border-radius:6px; font-family:sans-serif; box-shadow:0 2px 4px rgba(0,0,0,0.1); box-sizing:border-box; height:90px; position:relative;">
      <div style="position:absolute; top:10px; left:10px; width:90px; font-size:14px; text-align:left; line-height:26px;">
        <div>Currently</div><div>Today in</div><div>Total out</div>
      </div>
      <div style="position:absolute; top:10px; left:80px; width:120px; font-size:14px; font-weight:bold; text-align:center; line-height:26px; display:flex; flex-direction:column; white-space:normal; word-wrap:break-word;">
        <div>${current_power} W</div><div>${todayIn} Wh</div><div>${todayOut} kWh</div>
      </div>
      <div style="position:absolute; top:10px; right:10px; width:160px; height:70px; overflow:hidden;">
        <svg style="width:160px!important; height:70px!important; display:block;" viewBox="0 0 160 70" preserveAspectRatio="none">
          $bars_svg
        </svg>
      </div>
    </div>
  };
}


Gruß schwatter

schwatter

#19
Tag,

und hier noch als Line mit Html,SVG und Perl + Farbschleier. Das Post vorher habe ich auch nochmal angepasst. Die Viewbox war falsch skaliert.

{
  my @v = (split /,/, ReadingsVal('OpenDTU','chartArray',''))[-40..-1];  # letzte 40 Werte

  my ($min, $max) = (sort {$a <=> $b} @v)[0,-1];
  $max //= 0; $min //= 0;
  my $range = $max - $min || 1;

  # Zielgröße der SVG
  my $width = 155;
  my $height = 65;

  my $w = $width / (@v - 1 || 1);  # Abstand zwischen Punkten

  # Punkte berechnen
  my @points = map {
    my $x = $_ * $w;
    my $y = $height - (($v[$_] - $min) / $range * $height);
    [$x, $y]
  } 0..$#v;

  # Linie (Pfade) erzeugen
  my $path_d = "M" . join(" L", map { sprintf("%.2f,%.2f", @$_) } @points);

  # Fläche unter der Linie
  my $area_path_d = $path_d . sprintf(" L%.2f,%.2f L0,%.2f Z", $width, $height, $height);

  # Werte auslesen
  my $current_power = ReadingsVal('OpenDTU','total.Power.v', '--');
  my $todayIn = ReadingsVal('OpenDTU','total.Power.v', '--');
  my $todayOut = ReadingsVal('OpenDTU','total.YieldTotal.v', '--');

  return qq{
    <style>
      div#OpenDTU { pointer-events:none; }
    </style>
    <div style="width:365px; padding:10px; border:1px solid #ddd; border-radius:6px; font-family:sans-serif; box-shadow:0 2px 4px rgba(0,0,0,0.1); box-sizing:border-box; height:90px; position:relative;">
     
      <!-- Labels -->
      <div style="position:absolute; top:10px; left:10px; width:90px; font-size:14px; text-align:left; line-height:26px;">
        <div>Currently</div><div>Today in</div><div>Total out</div>
      </div>

      <!-- Werte -->
      <div style="position:absolute; top:10px; left:80px; width:120px; font-size:14px; font-weight:bold; text-align:center; line-height:26px; display:flex; flex-direction:column; white-space:normal; word-wrap:break-word;">
        <div>${current_power} W</div><div>${todayIn} Wh</div><div>${todayOut} kWh</div>
      </div>

      <!-- SVG-Chart -->
      <div style="position:absolute; top:10px; right:10px; width:160px; height:70px; overflow:hidden;">
        <svg style="width:160px!important; height:70px!important; display:block;" viewBox="0 0 160 70" preserveAspectRatio="xMidYMid meet">
          <path d="$area_path_d" fill="rgba(59,130,246,0.2)" />
          <path d="$path_d" fill="none" stroke="#3b82f6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
        </svg>
      </div>
    </div>
  };
}


Gruß schwatter